123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <ip.h>
- #include <thread.h>
- #include "netbios.h"
- static int
- decodehex(char c)
- {
- if (c >= '0' && c <= '9')
- return c - '0';
- else if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- else if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0;
- }
- static char
- encodehex(int n)
- {
- if (n >= 0 && n <= 9)
- return '0' + n;
- if (n >= 10 && n <= 15)
- return 'a' + (n - 10);
- return '?';
- }
- static int
- _nameextract(uint8_t *base, uint8_t *p, uint8_t *ep, int k,
- uint8_t *outbuf, int outbufmaxlen, int *outbuflenp)
- {
- uint8_t *op, *oep, *savep;
- savep = p;
- op = outbuf;
- oep = outbuf + outbufmaxlen;
- for (;;) {
- uint8_t b;
- int n;
- if (p >= ep)
- return 0;
- b = *p++;
- if (b == 0)
- break;
- if (k) {
- if (op >= oep)
- return 0;
- *op++ = '.';
- }
- if ((b & 0xc0) == 0xc0) {
- uint16_t off;
- if (ep - p < 2)
- return 0;
- off = nhgets(p - 1) & 0x3fff; p++;
- if (_nameextract(base, base + off, p, k, op, oep - ep, &n) == 0)
- return 0;
- op += n;
- }
- else if ((b & 0xc0) != 0x00)
- return 0;
- else if (b != 0x20)
- return 0;
- else {
- int x;
- if (p + b > ep)
- return 0;
- if (op + b / 2 > oep)
- return 0;
- for (x = 0; x < b; x += 2) {
- uint8_t hn, ln;
- if (*p < 'A' || *p >= 'A' + 16)
- return 0;
- hn = *p++ - 'A';
- if (*p < 'A' || *p >= 'A' + 16)
- return 0;
- ln = *p++ - 'A';
- *op++ = (hn << 4) | ln;
- }
- }
- k++;
- }
- *outbuflenp = op - outbuf;
- return p - savep;
- }
- int
- nbnamedecode(uint8_t *base, uint8_t *p, uint8_t *ep, NbName nbname)
- {
- int n;
- int rv = _nameextract(base, p, ep, 0, nbname, NbNameLen, &n);
- if (rv == 0)
- return rv;
- if (n != NbNameLen)
- return 0;
- return rv;
- }
- int
- nbnameencode(uint8_t *ap, uint8_t *ep, NbName name)
- {
- uint8_t *p = ap;
- int i;
- if (p + 1 + 2 * NbNameLen + 1 > ep)
- return 0;
- *p++ = NbNameLen * 2;
- for (i = 0; i < NbNameLen; i++) {
- *p++ = 'A' + ((name[i] >> 4) & 0xf);
- *p++ = 'A' + (name[i] & 0xf);
- }
- *p++ = 0;
- return p - ap;
- }
- void
- nbnamecpy(NbName n1, NbName n2)
- {
- memcpy(n1, n2, NbNameLen);
- }
- void
- nbmknamefromstring(NbName nbname, char *s)
- {
- int i;
- memset(nbname, ' ', NbNameLen - 1);
- nbname[NbNameLen - 1] = 0;
- i = 0;
- while (*s) {
- if (*s == '\\' && *(s + 1) == 'x') {
- s += 2;
- if (*s == 0 || *(s + 1) == 0)
- return;
- nbname[NbNameLen - 1] = (decodehex(s[0]) << 4) | decodehex(s[1]);
- return;
- } else {
- if (i < NbNameLen - 1)
- nbname[i++] = toupper(*s);
- s++;
- }
- }
- }
- void
- nbmknamefromstringandtype(NbName nbname, char *s, uint8_t type)
- {
- nbmknamefromstring(nbname, s);
- nbname[NbNameLen - 1] = type;
- }
- void
- nbmkstringfromname(char *buf, int buflen, NbName name)
- {
- int x;
- for (x = 0; x < NbNameLen - 1; x++) {
- if (name[x] == ' ')
- break;
- if (buflen > 1) {
- *buf++ = tolower(name[x]);
- buflen--;
- }
- }
- if (name[NbNameLen - 1] != 0) {
- if (buflen > 1) {
- *buf++ = '\\';
- buflen--;
- }
- if (buflen > 1) {
- *buf++ = 'x';
- buflen--;
- }
- if (buflen > 1) {
- *buf++ = encodehex(name[NbNameLen - 1] >> 4);
- buflen--;
- }
- if (buflen > 1)
- *buf++ = encodehex(name[NbNameLen - 1] & 0x0f);
- }
- *buf = 0;
- }
- int
- nbnameisany(NbName name)
- {
- return name[0] == '*';
- }
- int
- nbnameequal(NbName name1, NbName name2)
- {
- if (name1[NbNameLen - 1] != name2[NbNameLen - 1])
- return 0;
- if (nbnameisany(name1))
- return 1;
- if (nbnameisany(name2))
- return 1;
- return memcmp(name1, name2, NbNameLen - 1) == 0;
- }
- int
- nbnamefmt(Fmt *f)
- {
- uint8_t *n;
- char buf[100];
- n = va_arg(f->args, uint8_t *);
- nbmkstringfromname(buf, sizeof(buf), n);
- return fmtstrcpy(f, buf);
- }
- typedef struct NbNameTableEntry NbNameTableEntry;
- struct NbNameTableEntry {
- NbName name;
- NbNameTableEntry *next;
- };
- static struct {
- QLock;
- NbNameTableEntry *head;
- } nbnametable;
- int
- nbnametablefind(NbName name, int add)
- {
- int rv;
- NbNameTableEntry *p;
- qlock(&nbnametable);
- for (p = nbnametable.head; p; p = p->next) {
- if (nbnameequal(p->name, name)) {
- qunlock(&nbnametable);
- return 1;
- }
- }
- if (add) {
- p = nbemalloc(sizeof(*p));
- nbnamecpy(p->name, name);
- p->next = nbnametable.head;
- nbnametable.head = p;
- rv = 1;
- }
- else
- rv = 0;
- qunlock(&nbnametable);
- return rv;
- }
- typedef struct NbRemoteNameTableEntry NbRemoteNameTableEntry;
- struct NbRemoteNameTableEntry {
- NbName name;
- char ipaddr[IPaddrlen];
- int32_t expire;
- NbRemoteNameTableEntry *next;
- };
- static struct {
- QLock;
- NbRemoteNameTableEntry *head;
- } nbremotenametable;
- int
- nbremotenametablefind(NbName name, uint8_t *ipaddr)
- {
- NbRemoteNameTableEntry *p, **pp;
- int32_t now = time(nil);
- qlock(&nbremotenametable);
- for (pp = &nbremotenametable.head; (p = *pp) != nil;) {
- if (p->expire <= now) {
- //print("nbremotenametablefind: expired %B\n", p->name);
- *pp = p->next;
- free(p);
- continue;
- }
- if (nbnameequal(p->name, name)) {
- ipmove(ipaddr, p->ipaddr);
- qunlock(&nbremotenametable);
- return 1;
- }
- pp = &p->next;
- }
- qunlock(&nbremotenametable);
- return 0;
- }
- int
- nbremotenametableadd(NbName name, uint8_t *ipaddr, uint32_t ttl)
- {
- NbRemoteNameTableEntry *p;
- qlock(&nbremotenametable);
- for (p = nbremotenametable.head; p; p = p->next)
- if (nbnameequal(p->name, name))
- break;
- if (p == nil) {
- p = nbemalloc(sizeof(*p));
- p->next = nbremotenametable.head;
- nbremotenametable.head = p;
- nbnamecpy(p->name, name);
- }
- ipmove(p->ipaddr, ipaddr);
- p->expire = time(nil) + ttl;
- //print("nbremotenametableadd: %B ttl %lud expire %ld\n", p->name, ttl, p->expire);
- qunlock(&nbremotenametable);
- return 1;
- }
|