nbname.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <thread.h>
  5. #include "netbios.h"
  6. static int
  7. decodehex(char c)
  8. {
  9. if (c >= '0' && c <= '9')
  10. return c - '0';
  11. else if (c >= 'A' && c <= 'F')
  12. return c - 'A' + 10;
  13. else if (c >= 'a' && c <= 'f')
  14. return c - 'a' + 10;
  15. return 0;
  16. }
  17. static char
  18. encodehex(int n)
  19. {
  20. if (n >= 0 && n <= 9)
  21. return '0' + n;
  22. if (n >= 10 && n <= 15)
  23. return 'a' + (n - 10);
  24. return '?';
  25. }
  26. static int
  27. _nameextract(uchar *base, uchar *p, uchar *ep, int k, uchar *outbuf, int outbufmaxlen, int *outbuflenp)
  28. {
  29. uchar *op, *oep, *savep;
  30. savep = p;
  31. op = outbuf;
  32. oep = outbuf + outbufmaxlen;
  33. for (;;) {
  34. uchar b;
  35. int n;
  36. if (p >= ep)
  37. return 0;
  38. b = *p++;
  39. if (b == 0)
  40. break;
  41. if (k) {
  42. if (op >= oep)
  43. return 0;
  44. *op++ = '.';
  45. }
  46. if ((b & 0xc0) == 0xc0) {
  47. ushort off;
  48. if (ep - p < 2)
  49. return 0;
  50. off = nhgets(p - 1) & 0x3fff; p++;
  51. if (_nameextract(base, base + off, p, k, op, oep - ep, &n) == 0)
  52. return 0;
  53. op += n;
  54. }
  55. else if ((b & 0xc0) != 0x00)
  56. return 0;
  57. else if (b != 0x20)
  58. return 0;
  59. else {
  60. int x;
  61. if (p + b > ep)
  62. return 0;
  63. if (op + b / 2 > oep)
  64. return 0;
  65. for (x = 0; x < b; x += 2) {
  66. uchar hn, ln;
  67. if (*p < 'A' || *p >= 'A' + 16)
  68. return 0;
  69. hn = *p++ - 'A';
  70. if (*p < 'A' || *p >= 'A' + 16)
  71. return 0;
  72. ln = *p++ - 'A';
  73. *op++ = (hn << 4) | ln;
  74. }
  75. }
  76. k++;
  77. }
  78. *outbuflenp = op - outbuf;
  79. return p - savep;
  80. }
  81. int
  82. nbnamedecode(uchar *base, uchar *p, uchar *ep, NbName nbname)
  83. {
  84. int n;
  85. int rv = _nameextract(base, p, ep, 0, nbname, NbNameLen, &n);
  86. if (rv == 0)
  87. return rv;
  88. if (n != NbNameLen)
  89. return 0;
  90. return rv;
  91. }
  92. int
  93. nbnameencode(uchar *ap, uchar *ep, NbName name)
  94. {
  95. uchar *p = ap;
  96. int i;
  97. if (p + 1 + 2 * NbNameLen + 1 > ep)
  98. return 0;
  99. *p++ = NbNameLen * 2;
  100. for (i = 0; i < NbNameLen; i++) {
  101. *p++ = 'A' + ((name[i] >> 4) & 0xf);
  102. *p++ = 'A' + (name[i] & 0xf);
  103. }
  104. *p++ = 0;
  105. return p - ap;
  106. }
  107. void
  108. nbnamecpy(NbName n1, NbName n2)
  109. {
  110. memcpy(n1, n2, NbNameLen);
  111. }
  112. void
  113. nbmknamefromstring(NbName nbname, char *s)
  114. {
  115. int i;
  116. memset(nbname, ' ', NbNameLen - 1);
  117. nbname[NbNameLen - 1] = 0;
  118. i = 0;
  119. while (*s) {
  120. if (*s == '\\' && *(s + 1) == 'x') {
  121. s += 2;
  122. if (*s == 0 || *(s + 1) == 0)
  123. return;
  124. nbname[NbNameLen - 1] = (decodehex(s[0]) << 4) | decodehex(s[1]);
  125. return;
  126. } else {
  127. if (i < NbNameLen - 1)
  128. nbname[i++] = toupper(*s);
  129. s++;
  130. }
  131. }
  132. }
  133. void
  134. nbmknamefromstringandtype(NbName nbname, char *s, uchar type)
  135. {
  136. nbmknamefromstring(nbname, s);
  137. nbname[NbNameLen - 1] = type;
  138. }
  139. void
  140. nbmkstringfromname(char *buf, int buflen, NbName name)
  141. {
  142. int x;
  143. for (x = 0; x < NbNameLen - 1; x++) {
  144. if (name[x] == ' ')
  145. break;
  146. if (buflen > 1) {
  147. *buf++ = tolower(name[x]);
  148. buflen--;
  149. }
  150. }
  151. if (name[NbNameLen - 1] != 0) {
  152. if (buflen > 1) {
  153. *buf++ = '\\';
  154. buflen--;
  155. }
  156. if (buflen > 1) {
  157. *buf++ = 'x';
  158. buflen--;
  159. }
  160. if (buflen > 1) {
  161. *buf++ = encodehex(name[NbNameLen - 1] >> 4);
  162. buflen--;
  163. }
  164. if (buflen > 1)
  165. *buf++ = encodehex(name[NbNameLen - 1] & 0x0f);
  166. }
  167. *buf = 0;
  168. }
  169. int
  170. nbnameisany(NbName name)
  171. {
  172. return name[0] == '*';
  173. }
  174. int
  175. nbnameequal(NbName name1, NbName name2)
  176. {
  177. if (name1[NbNameLen - 1] != name2[NbNameLen - 1])
  178. return 0;
  179. if (nbnameisany(name1))
  180. return 1;
  181. if (nbnameisany(name2))
  182. return 1;
  183. return memcmp(name1, name2, NbNameLen - 1) == 0;
  184. }
  185. int
  186. nbnamefmt(Fmt *f)
  187. {
  188. uchar *n;
  189. char buf[100];
  190. n = va_arg(f->args, uchar *);
  191. nbmkstringfromname(buf, sizeof(buf), n);
  192. return fmtstrcpy(f, buf);
  193. }
  194. typedef struct NbNameTableEntry NbNameTableEntry;
  195. struct NbNameTableEntry {
  196. NbName name;
  197. NbNameTableEntry *next;
  198. };
  199. static struct {
  200. QLock;
  201. NbNameTableEntry *head;
  202. } nbnametable;
  203. int
  204. nbnametablefind(NbName name, int add)
  205. {
  206. int rv;
  207. NbNameTableEntry *p;
  208. qlock(&nbnametable);
  209. for (p = nbnametable.head; p; p = p->next) {
  210. if (nbnameequal(p->name, name)) {
  211. qunlock(&nbnametable);
  212. return 1;
  213. }
  214. }
  215. if (add) {
  216. p = nbemalloc(sizeof(*p));
  217. nbnamecpy(p->name, name);
  218. p->next = nbnametable.head;
  219. nbnametable.head = p;
  220. rv = 1;
  221. }
  222. else
  223. rv = 0;
  224. qunlock(&nbnametable);
  225. return rv;
  226. }
  227. typedef struct NbRemoteNameTableEntry NbRemoteNameTableEntry;
  228. struct NbRemoteNameTableEntry {
  229. NbName name;
  230. char ipaddr[IPaddrlen];
  231. long expire;
  232. NbRemoteNameTableEntry *next;
  233. };
  234. static struct {
  235. QLock;
  236. NbRemoteNameTableEntry *head;
  237. } nbremotenametable;
  238. int
  239. nbremotenametablefind(NbName name, uchar *ipaddr)
  240. {
  241. NbRemoteNameTableEntry *p, **pp;
  242. long now = time(nil);
  243. qlock(&nbremotenametable);
  244. for (pp = &nbremotenametable.head; (p = *pp) != nil;) {
  245. if (p->expire <= now) {
  246. //print("nbremotenametablefind: expired %B\n", p->name);
  247. *pp = p->next;
  248. free(p);
  249. continue;
  250. }
  251. if (nbnameequal(p->name, name)) {
  252. ipmove(ipaddr, p->ipaddr);
  253. qunlock(&nbremotenametable);
  254. return 1;
  255. }
  256. pp = &p->next;
  257. }
  258. qunlock(&nbremotenametable);
  259. return 0;
  260. }
  261. int
  262. nbremotenametableadd(NbName name, uchar *ipaddr, ulong ttl)
  263. {
  264. NbRemoteNameTableEntry *p;
  265. qlock(&nbremotenametable);
  266. for (p = nbremotenametable.head; p; p = p->next)
  267. if (nbnameequal(p->name, name))
  268. break;
  269. if (p == nil) {
  270. p = nbemalloc(sizeof(*p));
  271. p->next = nbremotenametable.head;
  272. nbremotenametable.head = p;
  273. nbnamecpy(p->name, name);
  274. }
  275. ipmove(p->ipaddr, ipaddr);
  276. p->expire = time(nil) + ttl;
  277. //print("nbremotenametableadd: %B ttl %lud expire %ld\n", p->name, ttl, p->expire);
  278. qunlock(&nbremotenametable);
  279. return 1;
  280. }