nbnsconv.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include <thread.h>
  5. #include "netbios.h"
  6. void
  7. nbnsmessagequestionfree(NbnsMessageQuestion **qp)
  8. {
  9. NbnsMessageQuestion *q = *qp;
  10. if (q) {
  11. free(q);
  12. *qp = nil;
  13. }
  14. }
  15. void
  16. nbnsmessageresourcefree(NbnsMessageResource **rp)
  17. {
  18. NbnsMessageResource *r = *rp;
  19. if (r) {
  20. free(r->rdata);
  21. free(r);
  22. *rp = nil;
  23. }
  24. }
  25. static void
  26. questionfree(NbnsMessageQuestion **qp)
  27. {
  28. while (*qp) {
  29. NbnsMessageQuestion *next = (*qp)->next;
  30. nbnsmessagequestionfree(qp);
  31. *qp = next;
  32. }
  33. }
  34. static void
  35. resourcefree(NbnsMessageResource **rp)
  36. {
  37. while (*rp) {
  38. NbnsMessageResource *next = (*rp)->next;
  39. nbnsmessageresourcefree(rp);
  40. *rp = next;
  41. }
  42. }
  43. void
  44. nbnsmessagefree(NbnsMessage **sp)
  45. {
  46. NbnsMessage *s = *sp;
  47. if (s) {
  48. questionfree(&s->q);
  49. resourcefree(&s->an);
  50. resourcefree(&s->ns);
  51. resourcefree(&s->ar);
  52. free(s);
  53. *sp = nil;
  54. }
  55. }
  56. void
  57. nbnsmessageaddquestion(NbnsMessage *s, NbnsMessageQuestion *q)
  58. {
  59. NbnsMessageQuestion **qp;
  60. for (qp = &s->q; *qp; qp = &(*qp)->next)
  61. ;
  62. *qp = q;
  63. }
  64. NbnsMessageQuestion *
  65. nbnsmessagequestionnew(NbName name, ushort type, ushort class)
  66. {
  67. NbnsMessageQuestion *q;
  68. q = mallocz(sizeof(*q), 1);
  69. if (q == nil)
  70. return nil;
  71. nbnamecpy(q->name, name);
  72. q->type = type;
  73. q->class = class;
  74. return q;
  75. }
  76. NbnsMessageResource *
  77. nbnsmessageresourcenew(NbName name, ushort type, ushort class, ulong ttl, int rdlength, uchar *rdata)
  78. {
  79. NbnsMessageResource *r;
  80. r= mallocz(sizeof(*r), 1);
  81. if (r == nil)
  82. return nil;
  83. nbnamecpy(r->name, name);
  84. r->type = type;
  85. r->class = class;
  86. r->ttl = ttl;
  87. r->rdlength = rdlength;
  88. if (rdlength) {
  89. r->rdata = malloc(rdlength);
  90. if (r->rdata == nil) {
  91. free(r);
  92. return nil;
  93. }
  94. memcpy(r->rdata, rdata, rdlength);
  95. }
  96. return r;
  97. }
  98. void
  99. nbnsmessageaddresource(NbnsMessageResource **rp, NbnsMessageResource *r)
  100. {
  101. for (; *rp; rp = &(*rp)->next)
  102. ;
  103. *rp = r;
  104. }
  105. NbnsMessage *
  106. nbnsmessagenew(void)
  107. {
  108. return mallocz(sizeof(NbnsMessage), 1);
  109. }
  110. static int
  111. resourcedecode(NbnsMessageResource **headp, int count, uchar *ap, uchar *pp, uchar *ep)
  112. {
  113. uchar *p = pp;
  114. int i;
  115. for (i = 0; i < count; i++) {
  116. int n;
  117. NbnsMessageResource *r, **rp;
  118. r = mallocz(sizeof(NbnsMessageResource), 1);
  119. if (r == nil)
  120. return -1;
  121. for (rp = headp; *rp; rp = &(*rp)->next)
  122. ;
  123. *rp = r;
  124. n = nbnamedecode(ap, p, ep, r->name);
  125. if (n == 0)
  126. return -1;
  127. p += n;
  128. if (p + 10 > ep)
  129. return -1;
  130. r->type = nhgets(p); p += 2;
  131. r->class = nhgets(p); p += 2;
  132. r->ttl = nhgetl(p); p += 4;
  133. r->rdlength = nhgets(p); p += 2;
  134. //print("rdlength %d\n", r->rdlength);
  135. if (r->rdlength) {
  136. if (p + r->rdlength > ep)
  137. return -1;
  138. r->rdata = malloc(r->rdlength);
  139. if (r == nil)
  140. return -1;
  141. memcpy(r->rdata, p, r->rdlength);
  142. p += r->rdlength;
  143. }
  144. }
  145. return p - pp;
  146. }
  147. NbnsMessage *
  148. nbnsconvM2S(uchar *ap, int nap)
  149. {
  150. uchar *p, *ep;
  151. ushort qdcount, ancount, nscount, arcount, ctrl;
  152. int i;
  153. NbnsMessage *s;
  154. int n;
  155. if (nap < 12)
  156. return nil;
  157. p = ap;
  158. ep = ap + nap;
  159. s = nbnsmessagenew();
  160. if (s == nil)
  161. return nil;
  162. s->id = nhgets(p); p+= 2;
  163. ctrl = nhgets(p); p += 2;
  164. qdcount = nhgets(p); p += 2;
  165. ancount = nhgets(p); p += 2;
  166. nscount = nhgets(p); p += 2;
  167. arcount = nhgets(p); p += 2;
  168. s->response = (ctrl & NbnsResponse) != 0;
  169. s->opcode = (ctrl >> NbnsOpShift) & NbnsOpMask;
  170. s->broadcast = (ctrl & NbnsFlagBroadcast) != 0;
  171. s->recursionavailable = (ctrl & NbnsFlagRecursionAvailable) != 0;
  172. s->recursiondesired = (ctrl & NbnsFlagRecursionDesired) != 0;
  173. s->truncation = (ctrl & NbnsFlagTruncation) != 0;
  174. s->authoritativeanswer = (ctrl & NbnsFlagAuthoritativeAnswer) != 0;
  175. s->rcode = s->response ? (ctrl & NbnsRcodeMask) : 0;
  176. for (i = 0; i < qdcount; i++) {
  177. int n;
  178. NbName nbname;
  179. NbnsMessageQuestion *q;
  180. ushort type, class;
  181. n = nbnamedecode(ap, p, ep, nbname);
  182. if (n == 0)
  183. goto fail;
  184. p += n;
  185. if (p + 4 > ep)
  186. goto fail;
  187. type = nhgets(p); p += 2;
  188. class = nhgets(p); p += 2;
  189. q = nbnsmessagequestionnew(nbname, type, class);
  190. if (q == nil)
  191. goto fail;
  192. nbnsmessageaddquestion(s, q);
  193. }
  194. n = resourcedecode(&s->an, ancount, ap, p, ep);
  195. if (n < 0)
  196. goto fail;
  197. p += n;
  198. n = resourcedecode(&s->ns, nscount, ap, p, ep);
  199. if (n < 0)
  200. goto fail;
  201. p += n;
  202. n = resourcedecode(&s->ar, arcount, ap, p, ep);
  203. if (n < 0)
  204. goto fail;
  205. //print("arcount %d\n", arcount);
  206. return s;
  207. fail:
  208. nbnsmessagefree(&s);
  209. return nil;
  210. }
  211. static int
  212. resourceencode(NbnsMessageResource *r, uchar *ap, uchar *ep)
  213. {
  214. uchar *p = ap;
  215. for (; r; r = r->next) {
  216. int n = nbnameencode(p, ep, r->name);
  217. if (n == 0)
  218. return -1;
  219. p += n;
  220. if (p + 10 > ep)
  221. return -1;
  222. hnputs(p, r->type); p += 2;
  223. hnputs(p, r->class); p += 2;
  224. hnputl(p, r->ttl); p += 4;
  225. hnputs(p, r->rdlength); p += 2;
  226. if (p + r->rdlength > ep)
  227. return -1;
  228. memcpy(p, r->rdata, r->rdlength);
  229. p += r->rdlength;
  230. }
  231. return p - ap;
  232. }
  233. int
  234. nbnsconvS2M(NbnsMessage *s, uchar *ap, int nap)
  235. {
  236. uchar *p = ap;
  237. uchar *ep = ap + nap;
  238. ushort ctrl;
  239. NbnsMessageQuestion *q;
  240. NbnsMessageResource *r;
  241. int k;
  242. int n;
  243. if (p + 12 > ep)
  244. return 0;
  245. hnputs(p, s->id); p+= 2;
  246. ctrl = (s->opcode & NbnsOpMask) << NbnsOpShift;
  247. if (s->response) {
  248. ctrl |= s->rcode & NbnsRcodeMask;
  249. ctrl |= NbnsResponse;
  250. }
  251. if (s->broadcast)
  252. ctrl |= NbnsFlagBroadcast;
  253. if (s->recursionavailable)
  254. ctrl |= NbnsFlagRecursionAvailable;
  255. if (s->recursiondesired)
  256. ctrl |= NbnsFlagRecursionDesired;
  257. if (s->truncation)
  258. ctrl |= NbnsFlagTruncation;
  259. if (s->authoritativeanswer)
  260. ctrl |= NbnsFlagAuthoritativeAnswer;
  261. hnputs(p, ctrl); p += 2;
  262. for (q = s->q, k = 0; q; k++, q = q->next)
  263. ;
  264. hnputs(p, k); p += 2;
  265. for (r = s->an, k = 0; r; k++, r = r->next)
  266. ;
  267. hnputs(p, k); p += 2;
  268. for (r = s->ns, k = 0; r; k++, r = r->next)
  269. ;
  270. hnputs(p, k); p += 2;
  271. for (r = s->ar, k = 0; r; k++, r = r->next)
  272. ;
  273. hnputs(p, k); p += 2;
  274. for (q = s->q; q; q = q->next) {
  275. int n = nbnameencode(p, ep, q->name);
  276. if (n == 0)
  277. return 0;
  278. p += n;
  279. if (p + 4 > ep)
  280. return 0;
  281. hnputs(p, q->type); p += 2;
  282. hnputs(p, q->class); p += 2;
  283. }
  284. n = resourceencode(s->an, p, ep);
  285. if (n < 0)
  286. return 0;
  287. p += n;
  288. n = resourceencode(s->ns, p, ep);
  289. if (n < 0)
  290. return 0;
  291. p += n;
  292. n = resourceencode(s->ar, p, ep);
  293. if (n < 0)
  294. return 0;
  295. p += n;
  296. return p - ap;
  297. }