nbns.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. Lock;
  20. ushort id;
  21. } id;
  22. struct {
  23. QLock;
  24. NbnsTransaction *head;
  25. } transactionlist;
  26. static void
  27. udplistener(void *)
  28. {
  29. for (;;) {
  30. uchar msg[Udphdrsize + 576];
  31. int len = read(udp.fd, msg, sizeof(msg));
  32. if (len < 0)
  33. break;
  34. if (len >= nbudphdrsize) {
  35. NbnsMessage *s;
  36. // Udphdr *uh;
  37. uchar *p;
  38. // uh = (Udphdr*)msg;
  39. p = msg + nbudphdrsize;
  40. len -= nbudphdrsize;
  41. s = nbnsconvM2S(p, len);
  42. if (s) {
  43. //print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
  44. //nbnsdumpmessage(s);
  45. if (s->response) {
  46. NbnsTransaction *t;
  47. qlock(&transactionlist);
  48. for (t = transactionlist.head; t; t = t->next)
  49. if (t->id == s->id)
  50. break;
  51. if (t)
  52. sendp(t->c, s);
  53. else
  54. nbnsmessagefree(&s);
  55. qunlock(&transactionlist);
  56. }
  57. else
  58. nbnsmessagefree(&s);
  59. }
  60. }
  61. }
  62. }
  63. static char *
  64. startlistener(void)
  65. {
  66. qlock(&udp);
  67. if (udp.thread < 0) {
  68. char *e;
  69. e = nbudpannounce(NbnsPort, &udp.fd);
  70. if (e) {
  71. qunlock(&udp);
  72. return e;
  73. }
  74. udp.thread = proccreate(udplistener, nil, 16384);
  75. }
  76. qunlock(&udp);
  77. return nil;
  78. }
  79. ushort
  80. nbnsnextid(void)
  81. {
  82. ushort rv;
  83. lock(&id);
  84. rv = id.id++;
  85. unlock(&id);
  86. return rv;
  87. }
  88. NbnsTransaction *
  89. nbnstransactionnew(NbnsMessage *s, uchar *ipaddr)
  90. {
  91. NbnsTransaction *t;
  92. uchar msg[Udphdrsize + 576];
  93. Udphdr *u;
  94. int len;
  95. startlistener();
  96. len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize);
  97. if (len == 0)
  98. return 0;
  99. t = mallocz(sizeof(*t), 1);
  100. if (t == nil)
  101. return nil;
  102. t->id = s->id;
  103. t->c = chancreate(sizeof(NbnsMessage *), 3);
  104. if (t->c == nil) {
  105. free(t);
  106. return nil;
  107. }
  108. qlock(&transactionlist);
  109. t->next = transactionlist.head;
  110. transactionlist.head = t;
  111. qunlock(&transactionlist);
  112. u = (Udphdr *)msg;
  113. ipmove(u->laddr, nbglobals.myipaddr);
  114. hnputs(u->lport, NbnsPort);
  115. if (s->broadcast || ipaddr == nil)
  116. ipmove(u->raddr, nbglobals.bcastaddr);
  117. else
  118. ipmove(u->raddr, ipaddr);
  119. hnputs(u->rport, NbnsPort);
  120. write(udp.fd, msg, len + nbudphdrsize);
  121. return t;
  122. }
  123. void
  124. nbnstransactionfree(NbnsTransaction **tp)
  125. {
  126. NbnsTransaction **tp2;
  127. NbnsMessage *s;
  128. NbnsTransaction *t;
  129. t = *tp;
  130. if (t) {
  131. qlock(&transactionlist);
  132. while ((s = nbrecvp(t->c)) != nil)
  133. nbnsmessagefree(&s);
  134. for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
  135. ;
  136. if (*tp2) {
  137. *tp2 = t->next;
  138. free(t);
  139. }
  140. qunlock(&transactionlist);
  141. *tp = nil;
  142. }
  143. }