nbns.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <ip.h>
  12. #include <thread.h>
  13. #include "netbios.h"
  14. static struct {
  15. int thread;
  16. QLock qlock;
  17. int fd;
  18. } udp = { -1 };
  19. typedef struct Listen Listen;
  20. struct Listen {
  21. NbName to;
  22. int (*deliver)(void *magic, NbDgram *s);
  23. void *magic;
  24. Listen *next;
  25. };
  26. static struct {
  27. Lock lock;
  28. uint16_t id;
  29. } id;
  30. struct {
  31. QLock qlock;
  32. NbnsTransaction *head;
  33. } transactionlist;
  34. static void
  35. udplistener(void *v)
  36. {
  37. for (;;) {
  38. uint8_t msg[Udphdrsize + 576];
  39. int len = read(udp.fd, msg, sizeof(msg));
  40. if (len < 0)
  41. break;
  42. if (len >= nbudphdrsize) {
  43. NbnsMessage *s;
  44. // Udphdr *uh;
  45. uint8_t *p;
  46. // uh = (Udphdr*)msg;
  47. p = msg + nbudphdrsize;
  48. len -= nbudphdrsize;
  49. s = nbnsconvM2S(p, len);
  50. if (s) {
  51. //print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
  52. //nbnsdumpmessage(s);
  53. if (s->response) {
  54. NbnsTransaction *t;
  55. qlock(&transactionlist.qlock);
  56. for (t = transactionlist.head; t; t = t->next)
  57. if (t->id == s->id)
  58. break;
  59. if (t)
  60. sendp(t->c, s);
  61. else
  62. nbnsmessagefree(&s);
  63. qunlock(&transactionlist.qlock);
  64. }
  65. else
  66. nbnsmessagefree(&s);
  67. }
  68. }
  69. }
  70. }
  71. static char *
  72. startlistener(void)
  73. {
  74. qlock(&udp.qlock);
  75. if (udp.thread < 0) {
  76. char *e;
  77. e = nbudpannounce(NbnsPort, &udp.fd);
  78. if (e) {
  79. qunlock(&udp.qlock);
  80. return e;
  81. }
  82. udp.thread = proccreate(udplistener, nil, 16384);
  83. }
  84. qunlock(&udp.qlock);
  85. return nil;
  86. }
  87. uint16_t
  88. nbnsnextid(void)
  89. {
  90. uint16_t rv;
  91. lock(&id.lock);
  92. rv = id.id++;
  93. unlock(&id.lock);
  94. return rv;
  95. }
  96. NbnsTransaction *
  97. nbnstransactionnew(NbnsMessage *s, uint8_t *ipaddr)
  98. {
  99. NbnsTransaction *t;
  100. uint8_t msg[Udphdrsize + 576];
  101. Udphdr *u;
  102. int len;
  103. startlistener();
  104. len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize);
  105. if (len == 0)
  106. return 0;
  107. t = mallocz(sizeof(*t), 1);
  108. if (t == nil)
  109. return nil;
  110. t->id = s->id;
  111. t->c = chancreate(sizeof(NbnsMessage *), 3);
  112. if (t->c == nil) {
  113. free(t);
  114. return nil;
  115. }
  116. qlock(&transactionlist.qlock);
  117. t->next = transactionlist.head;
  118. transactionlist.head = t;
  119. qunlock(&transactionlist.qlock);
  120. u = (Udphdr *)msg;
  121. ipmove(u->laddr, nbglobals.myipaddr);
  122. hnputs(u->lport, NbnsPort);
  123. if (s->broadcast || ipaddr == nil)
  124. ipmove(u->raddr, nbglobals.bcastaddr);
  125. else
  126. ipmove(u->raddr, ipaddr);
  127. hnputs(u->rport, NbnsPort);
  128. write(udp.fd, msg, len + nbudphdrsize);
  129. return t;
  130. }
  131. void
  132. nbnstransactionfree(NbnsTransaction **tp)
  133. {
  134. NbnsTransaction **tp2;
  135. NbnsMessage *s;
  136. NbnsTransaction *t;
  137. t = *tp;
  138. if (t) {
  139. qlock(&transactionlist.qlock);
  140. while ((s = nbrecvp(t->c)) != nil)
  141. nbnsmessagefree(&s);
  142. for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
  143. ;
  144. if (*tp2) {
  145. *tp2 = t->next;
  146. free(t);
  147. }
  148. qunlock(&transactionlist.qlock);
  149. *tp = nil;
  150. }
  151. }