nbss.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <thread.h>
  5. #include "netbios.h"
  6. static struct {
  7. int thread;
  8. QLock;
  9. char adir[NETPATHLEN];
  10. int acfd;
  11. char ldir[NETPATHLEN];
  12. int lcfd;
  13. } tcp = { -1 };
  14. typedef struct Session Session;
  15. enum { NeedSessionRequest, Connected, Dead };
  16. struct Session {
  17. NbSession;
  18. int thread;
  19. Session *next;
  20. int state;
  21. NBSSWRITEFN *write;
  22. };
  23. static struct {
  24. QLock;
  25. Session *head;
  26. } sessions;
  27. typedef struct Listen Listen;
  28. struct Listen {
  29. NbName to;
  30. NbName from;
  31. int (*accept)(void *magic, NbSession *s, NBSSWRITEFN **writep);
  32. void *magic;
  33. Listen *next;
  34. };
  35. static struct {
  36. QLock;
  37. Listen *head;
  38. } listens;
  39. static void
  40. deletesession(Session *s)
  41. {
  42. Session **sp;
  43. close(s->fd);
  44. qlock(&sessions);
  45. for (sp = &sessions.head; *sp && *sp != s; sp = &(*sp)->next)
  46. ;
  47. if (*sp)
  48. *sp = s->next;
  49. qunlock(&sessions);
  50. free(s);
  51. }
  52. static void
  53. tcpreader(void *a)
  54. {
  55. Session *s = a;
  56. uchar *buf;
  57. int buflen = 0x1ffff + 4;
  58. buf = nbemalloc(buflen);
  59. for (;;) {
  60. int n;
  61. uchar flags;
  62. ushort length;
  63. n = readn(s->fd, buf, 4);
  64. if (n != 4) {
  65. die:
  66. free(buf);
  67. if (s->state == Connected)
  68. (*s->write)(s, nil, -1);
  69. deletesession(s);
  70. return;
  71. }
  72. flags = buf[1];
  73. length = nhgets(buf + 2) | ((flags & 1) << 16);
  74. n = readn(s->fd, buf + 4, length);
  75. if (n != length)
  76. goto die;
  77. if (flags & 0xfe) {
  78. print("nbss: invalid flags field 0x%.2ux\n", flags);
  79. goto die;
  80. }
  81. switch (buf[0]) {
  82. case 0: /* session message */
  83. if (s->state != Connected && s->state != Dead) {
  84. print("nbss: unexpected session message\n");
  85. goto die;
  86. }
  87. if (s->state == Connected) {
  88. if ((*s->write)(s, buf + 4, length) != 0) {
  89. s->state = Dead;
  90. goto die;
  91. }
  92. }
  93. break;
  94. case 0x81: /* session request */ {
  95. uchar *p, *ep;
  96. Listen *l;
  97. int k;
  98. int called_found;
  99. uchar error_code;
  100. if (s->state == Connected) {
  101. print("nbss: unexpected session request\n");
  102. goto die;
  103. }
  104. p = buf + 4;
  105. ep = p + length;
  106. k = nbnamedecode(p, p, ep, s->to);
  107. if (k == 0) {
  108. print("nbss: malformed called name in session request\n");
  109. goto die;
  110. }
  111. p += k;
  112. k = nbnamedecode(p, p, ep, s->from);
  113. if (k == 0) {
  114. print("nbss: malformed calling name in session request\n");
  115. goto die;
  116. }
  117. /*
  118. p += k;
  119. if (p != ep) {
  120. print("nbss: extra data at end of session request\n");
  121. goto die;
  122. }
  123. */
  124. called_found = 0;
  125. //print("nbss: called %B calling %B\n", s->to, s->from);
  126. qlock(&listens);
  127. for (l = listens.head; l; l = l->next)
  128. if (nbnameequal(l->to, s->to)) {
  129. called_found = 1;
  130. if (nbnameequal(l->from, s->from))
  131. break;
  132. }
  133. if (l == nil) {
  134. qunlock(&listens);
  135. error_code = called_found ? 0x81 : 0x80;
  136. replydie:
  137. buf[0] = 0x83;
  138. buf[1] = 0;
  139. hnputs(buf + 2, 1);
  140. buf[4] = error_code;
  141. write(s->fd, buf, 5);
  142. goto die;
  143. }
  144. if (!(*l->accept)(l->magic, s, &s->write)) {
  145. qunlock(&listens);
  146. error_code = 0x83;
  147. goto replydie;
  148. }
  149. buf[0] = 0x82;
  150. buf[1] = 0;
  151. hnputs(buf + 2, 0);
  152. if (write(s->fd, buf, 4) != 4) {
  153. qunlock(&listens);
  154. goto die;
  155. }
  156. s->state = Connected;
  157. qunlock(&listens);
  158. break;
  159. }
  160. case 0x85: /* keep awake */
  161. break;
  162. default:
  163. print("nbss: opcode 0x%.2ux unexpected\n", buf[0]);
  164. goto die;
  165. }
  166. }
  167. }
  168. static NbSession *
  169. createsession(int fd)
  170. {
  171. Session *s;
  172. s = nbemalloc(sizeof(Session));
  173. s->fd = fd;
  174. s->state = NeedSessionRequest;
  175. qlock(&sessions);
  176. s->thread = procrfork(tcpreader, s, 32768, RFNAMEG);
  177. if (s->thread < 0) {
  178. qunlock(&sessions);
  179. free(s);
  180. return nil;
  181. }
  182. s->next = sessions.head;
  183. sessions.head = s;
  184. qunlock(&sessions);
  185. return s;
  186. }
  187. static void
  188. tcplistener(void *)
  189. {
  190. for (;;) {
  191. int dfd;
  192. char ldir[NETPATHLEN];
  193. int lcfd;
  194. //print("tcplistener: listening\n");
  195. lcfd = listen(tcp.adir, ldir);
  196. //print("tcplistener: contact\n");
  197. if (lcfd < 0) {
  198. die:
  199. qlock(&tcp);
  200. close(tcp.acfd);
  201. tcp.thread = -1;
  202. qunlock(&tcp);
  203. return;
  204. }
  205. dfd = accept(lcfd, ldir);
  206. close(lcfd);
  207. if (dfd < 0)
  208. goto die;
  209. if (createsession(dfd) == nil)
  210. close(dfd);
  211. }
  212. }
  213. int
  214. nbsslisten(NbName to, NbName from,int (*accept)(void *magic, NbSession *s, NBSSWRITEFN **writep), void *magic)
  215. {
  216. Listen *l;
  217. qlock(&tcp);
  218. if (tcp.thread < 0) {
  219. fmtinstall('B', nbnamefmt);
  220. tcp.acfd = announce("tcp!*!netbios", tcp.adir);
  221. if (tcp.acfd < 0) {
  222. print("nbsslisten: can't announce: %r\n");
  223. qunlock(&tcp);
  224. return -1;
  225. }
  226. tcp.thread = proccreate(tcplistener, nil, 16384);
  227. }
  228. qunlock(&tcp);
  229. l = nbemalloc(sizeof(Listen));
  230. nbnamecpy(l->to, to);
  231. nbnamecpy(l->from, from);
  232. l->accept = accept;
  233. l->magic = magic;
  234. qlock(&listens);
  235. l->next = listens.head;
  236. listens.head = l;
  237. qunlock(&listens);
  238. return 0;
  239. }
  240. void
  241. nbssfree(NbSession *s)
  242. {
  243. deletesession((Session *)s);
  244. }
  245. int
  246. nbssgatherwrite(NbSession *s, NbScatterGather *a)
  247. {
  248. uchar hdr[4];
  249. NbScatterGather *ap;
  250. long l = 0;
  251. for (ap = a; ap->p; ap++)
  252. l += ap->l;
  253. //print("nbssgatherwrite %ld bytes\n", l);
  254. hnputl(hdr, l);
  255. //nbdumpdata(hdr, sizeof(hdr));
  256. if (write(s->fd, hdr, sizeof(hdr)) != sizeof(hdr))
  257. return -1;
  258. for (ap = a; ap->p; ap++) {
  259. //nbdumpdata(ap->p, ap->l);
  260. if (write(s->fd, ap->p, ap->l) != ap->l)
  261. return -1;
  262. }
  263. return 0;
  264. }
  265. NbSession *
  266. nbssconnect(NbName to, NbName from)
  267. {
  268. Session *s;
  269. uchar ipaddr[IPaddrlen];
  270. char dialaddress[100];
  271. char dir[NETPATHLEN];
  272. uchar msg[576];
  273. int fd;
  274. long o;
  275. uchar flags;
  276. long length;
  277. if (!nbnameresolve(to, ipaddr))
  278. return nil;
  279. fmtinstall('I', eipfmt);
  280. snprint(dialaddress, sizeof(dialaddress), "tcp!%I!netbios", ipaddr);
  281. fd = dial(dialaddress, nil, dir, nil);
  282. if (fd < 0)
  283. return nil;
  284. msg[0] = 0x81;
  285. msg[1] = 0;
  286. o = 4;
  287. o += nbnameencode(msg + o, msg + sizeof(msg) - o, to);
  288. o += nbnameencode(msg + o, msg + sizeof(msg) - o, from);
  289. hnputs(msg + 2, o - 4);
  290. if (write(fd, msg, o) != o) {
  291. close(fd);
  292. return nil;
  293. }
  294. if (readn(fd, msg, 4) != 4) {
  295. close(fd);
  296. return nil;
  297. }
  298. flags = msg[1];
  299. length = nhgets(msg + 2) | ((flags & 1) << 16);
  300. switch (msg[0]) {
  301. default:
  302. close(fd);
  303. werrstr("unexpected session message code 0x%.2ux", msg[0]);
  304. return nil;
  305. case 0x82:
  306. if (length != 0) {
  307. close(fd);
  308. werrstr("length not 0 in positive session response");
  309. return nil;
  310. }
  311. break;
  312. case 0x83:
  313. if (length != 1) {
  314. close(fd);
  315. werrstr("length not 1 in negative session response");
  316. return nil;
  317. }
  318. if (readn(fd, msg + 4, 1) != 1) {
  319. close(fd);
  320. return nil;
  321. }
  322. close(fd);
  323. werrstr("negative session response 0x%.2ux", msg[4]);
  324. return nil;
  325. }
  326. s = nbemalloc(sizeof(Session));
  327. s->fd = fd;
  328. s->state = Connected;
  329. qlock(&sessions);
  330. s->next = sessions.head;
  331. sessions.head = s;
  332. qunlock(&sessions);
  333. return s;
  334. }
  335. long
  336. nbssscatterread(NbSession *nbs, NbScatterGather *a)
  337. {
  338. uchar hdr[4];
  339. uchar flags;
  340. long length, total;
  341. NbScatterGather *ap;
  342. Session *s = (Session *)nbs;
  343. long l = 0;
  344. for (ap = a; ap->p; ap++)
  345. l += ap->l;
  346. //print("nbssscatterread %ld bytes\n", l);
  347. again:
  348. if (readn(s->fd, hdr, 4) != 4) {
  349. dead:
  350. s->state = Dead;
  351. return -1;
  352. }
  353. flags = hdr[1];
  354. length = nhgets(hdr + 2) | ((flags & 1) << 16);
  355. //print("%.2ux: %d\n", hdr[0], length);
  356. switch (hdr[0]) {
  357. case 0x85:
  358. if (length != 0) {
  359. werrstr("length in keepalive not 0");
  360. goto dead;
  361. }
  362. goto again;
  363. case 0x00:
  364. break;
  365. default:
  366. werrstr("unexpected session message code 0x%.2ux", hdr[0]);
  367. goto dead;
  368. }
  369. if (length > l) {
  370. werrstr("message too big (%ld)", length);
  371. goto dead;
  372. }
  373. total = length;
  374. for (ap = a; length && ap->p; ap++) {
  375. long thistime;
  376. long n;
  377. thistime = length;
  378. if (thistime > ap->l)
  379. thistime = ap->l;
  380. //print("reading %d\n", length);
  381. n = readn(s->fd, ap->p, thistime);
  382. if (n != thistime)
  383. goto dead;
  384. length -= thistime;
  385. }
  386. return total;
  387. }
  388. int
  389. nbsswrite(NbSession *s, void *buf, long maxlen)
  390. {
  391. NbScatterGather a[2];
  392. a[0].l = maxlen;
  393. a[0].p = buf;
  394. a[1].p = nil;
  395. return nbssgatherwrite(s, a);
  396. }
  397. long
  398. nbssread(NbSession *s, void *buf, long maxlen)
  399. {
  400. NbScatterGather a[2];
  401. a[0].l = maxlen;
  402. a[0].p = buf;
  403. a[1].p = nil;
  404. return nbssscatterread(s, a);
  405. }