nbdgram.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. int fd;
  10. } udp = { -1 };
  11. typedef struct Listen Listen;
  12. struct Listen {
  13. NbName to;
  14. int (*deliver)(void *magic, NbDgram *s);
  15. void *magic;
  16. Listen *next;
  17. };
  18. static struct {
  19. QLock;
  20. Listen *head;
  21. } listens;
  22. static void
  23. udplistener(void *)
  24. {
  25. //print("udplistener - starting\n");
  26. for (;;) {
  27. uchar msg[Udphdrsize + 576];
  28. int len = read(udp.fd, msg, sizeof(msg));
  29. if (len < 0)
  30. break;
  31. if (len >= nbudphdrsize) {
  32. NbDgram s;
  33. // Udphdr *uh;
  34. uchar *p;
  35. int n;
  36. // uh = (Udphdr*)msg;
  37. p = msg + nbudphdrsize;
  38. len -= nbudphdrsize;
  39. n = nbdgramconvM2S(&s, p, p + len);
  40. if (n) {
  41. switch (s.type) {
  42. case NbDgramError:
  43. print("nbdgramlisten: error: ip %I port %d code 0x%.2ux\n", s.srcip, s.srcport, s.error.code);
  44. break;
  45. case NbDgramDirectUnique:
  46. case NbDgramDirectGroup:
  47. case NbDgramBroadcast: {
  48. int delivered = 0;
  49. Listen **lp, *l;
  50. if ((s.flags & NbDgramMore) || s.datagram.offset != 0)
  51. break;
  52. if (!nbnameisany(s.datagram.dstname)
  53. && !nbnametablefind(s.datagram.dstname, 0)) {
  54. /* - only do this if a broadcast node, and can tell when packets are broadcast...
  55. s.flags &= 3;
  56. ipmove(s.srcip, nbglobals.myipaddr);
  57. s.srcport = NbDgramPort;
  58. s.type = NbDgramError;
  59. s.error.code = NbDgramErrorDestinationNameNotPresent;
  60. nbdgramsendto(uh->raddr, nhgets(uh->rport), &s);
  61. */
  62. break;
  63. }
  64. qlock(&listens);
  65. for (lp = &listens.head; (l = *lp) != nil;) {
  66. if (nbnameisany(l->to) || nbnameequal(l->to, s.datagram.dstname)) {
  67. switch ((*l->deliver)(l->magic, &s)) {
  68. case 0:
  69. delivered = 1;
  70. /* fall through */
  71. case -1:
  72. *lp = l->next;
  73. free(l);
  74. continue;
  75. default:
  76. delivered = 1;
  77. break;
  78. }
  79. }
  80. lp = &l->next;
  81. }
  82. qunlock(&listens);
  83. USED(delivered);
  84. }
  85. default:
  86. ;
  87. }
  88. }
  89. }
  90. }
  91. print("udplistener - exiting\n");
  92. qlock(&udp);
  93. udp.thread = -1;
  94. qunlock(&udp);
  95. }
  96. static char *
  97. startlistener(void)
  98. {
  99. qlock(&udp);
  100. if (udp.thread < 0) {
  101. char *e;
  102. e = nbudpannounce(NbDgramPort, &udp.fd);
  103. if (e) {
  104. qunlock(&udp);
  105. return e;
  106. }
  107. udp.thread = proccreate(udplistener, nil, 16384);
  108. }
  109. qunlock(&udp);
  110. return nil;
  111. }
  112. char *
  113. nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic)
  114. {
  115. Listen *l;
  116. char *e;
  117. nbnametablefind(to, 1);
  118. e = startlistener();
  119. if (e)
  120. return e;
  121. l = nbemalloc(sizeof(Listen));
  122. nbnamecpy(l->to, to);
  123. l->deliver = deliver;
  124. l->magic = magic;
  125. qlock(&listens);
  126. l->next = listens.head;
  127. listens.head = l;
  128. qunlock(&listens);
  129. return 0;
  130. }
  131. int
  132. nbdgramsendto(uchar *ipaddr, ushort port, NbDgram *s)
  133. {
  134. Udphdr *u;
  135. uchar msg[NbDgramMaxPacket + Udphdrsize];
  136. int l;
  137. int rv;
  138. char *e;
  139. e = startlistener();
  140. if (e != nil)
  141. return 0;
  142. l = nbdgramconvS2M(msg + nbudphdrsize, msg + sizeof(msg), s);
  143. if (l == 0) {
  144. print("conv failed\n");
  145. return 0;
  146. }
  147. u = (Udphdr *)msg;
  148. ipmove(u->laddr, nbglobals.myipaddr);
  149. hnputs(u->lport, NbDgramPort);
  150. ipmove(u->raddr, ipaddr);
  151. hnputs(u->rport, port);
  152. //nbdumpdata(msg, l + nbudphdrsize);
  153. //print("transmitting\n");
  154. rv = write(udp.fd, msg, l + nbudphdrsize);
  155. //print("rv %d l %d hdrsize %d error %r\n", rv, l, nbudphdrsize);
  156. return rv == l + nbudphdrsize;
  157. }
  158. static struct {
  159. Lock;
  160. ushort id;
  161. } id;
  162. static ushort
  163. nextdgramid(void)
  164. {
  165. ushort v;
  166. lock(&id);
  167. v = id.id++;
  168. unlock(&id);
  169. return v;
  170. }
  171. int
  172. nbdgramsend(NbDgramSendParameters *p, uchar *data, long datalen)
  173. {
  174. NbDgram s;
  175. uchar dstip[IPaddrlen];
  176. s.type = p->type;
  177. switch (p->type) {
  178. case NbDgramBroadcast:
  179. case NbDgramDirectGroup:
  180. ipmove(dstip, nbglobals.bcastaddr);
  181. break;
  182. case NbDgramDirectUnique:
  183. if (!nbnameresolve(p->to, dstip)) {
  184. werrstr("nbdgramsend: name resolution failed");
  185. return 0;
  186. }
  187. break;
  188. default:
  189. werrstr("nbdgramsend: illegal datagram type");
  190. return 0;
  191. }
  192. s.flags = NbDgramFirst;
  193. s.id = nextdgramid();
  194. ipmove(s.srcip, nbglobals.myipaddr);
  195. s.srcport = NbDgramPort;
  196. s.datagram.offset = 0;
  197. s.datagram.data = data;
  198. s.datagram.length = datalen;
  199. nbnamecpy(s.datagram.dstname, p->to);
  200. nbnamecpy(s.datagram.srcname, nbglobals.myname);
  201. return nbdgramsendto(dstip, NbDgramPort, &s);
  202. }