mdns.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. /*
  2. * tinysvcmdns - a tiny MDNS implementation for publishing services
  3. * Copyright (C) 2011 Darell Tan
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "mdns.h"
  29. #include <stdint.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <assert.h>
  34. #ifdef _WIN32
  35. #include <winsock.h>
  36. #include <in6addr.h>
  37. #else
  38. #include <netinet/in.h>
  39. #endif
  40. struct name_comp {
  41. uint8_t *label; // label
  42. size_t pos; // position in msg
  43. struct name_comp *next;
  44. };
  45. // ----- label functions -----
  46. // duplicates a name
  47. //inline uint8_t *dup_nlabel(const uint8_t *n) {
  48. uint8_t *dup_nlabel(const uint8_t *n) {
  49. assert(n[0] <= 63); // prevent mis-use
  50. return (uint8_t *) strdup((char *) n);
  51. }
  52. // duplicates a label
  53. uint8_t *dup_label(const uint8_t *label) {
  54. int len = *label + 1;
  55. uint8_t *newlabel;
  56. if (len > 63)
  57. return NULL;
  58. newlabel = malloc(len + 1);
  59. strncpy((char *) newlabel, (char *) label, len);
  60. newlabel[len] = '\0';
  61. return newlabel;
  62. }
  63. uint8_t *join_nlabel(const uint8_t *n1, const uint8_t *n2) {
  64. int len1, len2;
  65. uint8_t *s;
  66. assert(n1[0] <= 63 && n2[0] <= 63); // detect misuse
  67. len1 = strlen((char *) n1);
  68. len2 = strlen((char *) n2);
  69. s = malloc(len1 + len2 + 1);
  70. strncpy((char *) s, (char *) n1, len1);
  71. strncpy((char *) s+len1, (char *) n2, len2);
  72. s[len1 + len2] = '\0';
  73. return s;
  74. }
  75. // returns a human-readable name label in dotted form
  76. char *nlabel_to_str(const uint8_t *name) {
  77. char *label, *labelp;
  78. const uint8_t *p;
  79. size_t buf_len = 256;
  80. assert(name != NULL);
  81. label = labelp = malloc(buf_len);
  82. for (p = name; *p; p++) {
  83. uint8_t label_len = *p;
  84. if (buf_len <= label_len)
  85. break;
  86. strncpy(labelp, (char *)p + 1, label_len);
  87. labelp += label_len;
  88. *labelp = '.';
  89. labelp++;
  90. buf_len -= label_len + 1;
  91. p += label_len;
  92. }
  93. // avoid writing NULL past end of buffer
  94. if (buf_len == 0)
  95. labelp--;
  96. *labelp = '\0';
  97. return label;
  98. }
  99. // returns the length of a label field
  100. // does NOT uncompress the field, so it could be as small as 2 bytes
  101. // or 1 for the root
  102. static size_t label_len(uint8_t *pkt_buf, size_t pkt_len, size_t off) {
  103. uint8_t *p;
  104. uint8_t *e = pkt_buf + pkt_len;
  105. size_t len = 0;
  106. for (p = pkt_buf + off; p < e; p++) {
  107. if (*p == 0) {
  108. return len + 1;
  109. } else if ((*p & 0xC0) == 0xC0) {
  110. return len + 2;
  111. } else {
  112. len += *p + 1;
  113. p += *p;
  114. }
  115. }
  116. return len;
  117. }
  118. // creates a label
  119. // free() after use
  120. uint8_t *create_label(const char *txt) {
  121. int len;
  122. uint8_t *s;
  123. assert(txt != NULL);
  124. len = strlen(txt);
  125. if (len > 63)
  126. return NULL;
  127. s = malloc(len + 2);
  128. s[0] = len;
  129. strncpy((char *) s + 1, txt, len);
  130. s[len + 1] = '\0';
  131. return s;
  132. }
  133. // creates a uncompressed name label given a DNS name like "apple.b.com"
  134. // free() after use
  135. uint8_t *create_nlabel(const char *name) {
  136. char *label;
  137. char *p, *e, *lenpos;
  138. int len = 0;
  139. assert(name != NULL);
  140. len = strlen(name);
  141. label = malloc(len + 1 + 1);
  142. if (label == NULL)
  143. return NULL;
  144. strncpy((char *) label + 1, name, len);
  145. label[len + 1] = '\0';
  146. p = label;
  147. e = p + len;
  148. lenpos = p;
  149. while (p < e) {
  150. char *dot = memchr(p + 1, '.', e - p - 1);
  151. *lenpos = 0;
  152. if (dot == NULL)
  153. dot = e + 1;
  154. *lenpos = dot - p - 1;
  155. p = dot;
  156. lenpos = dot;
  157. }
  158. return (uint8_t *) label;
  159. }
  160. // copies a label from the buffer into a newly-allocated string
  161. // free() after use
  162. static uint8_t *copy_label(uint8_t *pkt_buf, size_t pkt_len, size_t off) {
  163. int len;
  164. if (off > pkt_len)
  165. return NULL;
  166. len = pkt_buf[off] + 1;
  167. if (off + len > pkt_len) {
  168. DEBUG_PRINTF("label length exceeds packet buffer\n");
  169. return NULL;
  170. }
  171. return dup_label(pkt_buf + off);
  172. }
  173. // uncompresses a name
  174. // free() after use
  175. static uint8_t *uncompress_nlabel(uint8_t *pkt_buf, size_t pkt_len, size_t off) {
  176. uint8_t *p;
  177. uint8_t *e = pkt_buf + pkt_len;
  178. size_t len = 0;
  179. char *str, *sp;
  180. if (off >= pkt_len)
  181. return NULL;
  182. // calculate length of uncompressed label
  183. for (p = pkt_buf + off; *p && p < e; p++) {
  184. size_t llen = 0;
  185. if ((*p & 0xC0) == 0xC0) {
  186. uint8_t *p2 = pkt_buf + (((p[0] & ~0xC0) << 8) | p[1]);
  187. llen = *p2 + 1;
  188. p = p2 + llen - 1;
  189. } else {
  190. llen = *p + 1;
  191. p += llen - 1;
  192. }
  193. len += llen;
  194. }
  195. str = sp = malloc(len + 1);
  196. if (str == NULL)
  197. return NULL;
  198. // FIXME: must merge this with above code
  199. for (p = pkt_buf + off; *p && p < e; p++) {
  200. size_t llen = 0;
  201. if ((*p & 0xC0) == 0xC0) {
  202. uint8_t *p2 = pkt_buf + (((p[0] & ~0xC0) << 8) | p[1]);
  203. llen = *p2 + 1;
  204. strncpy(sp, (char *) p2, llen);
  205. p = p2 + llen - 1;
  206. } else {
  207. llen = *p + 1;
  208. strncpy(sp, (char *) p, llen);
  209. p += llen - 1;
  210. }
  211. sp += llen;
  212. }
  213. *sp = '\0';
  214. return (uint8_t *) str;
  215. }
  216. // ----- RR list & group functions -----
  217. const char *rr_get_type_name(enum rr_type type) {
  218. switch (type) {
  219. case RR_A: return "A";
  220. case RR_PTR: return "PTR";
  221. case RR_TXT: return "TXT";
  222. case RR_AAAA: return "AAAA";
  223. case RR_SRV: return "SRV";
  224. case RR_NSEC: return "NSEC";
  225. case RR_ANY: return "ANY";
  226. }
  227. return NULL;
  228. }
  229. void rr_entry_destroy(struct rr_entry *rr) {
  230. struct rr_data_txt *txt_rec;
  231. assert(rr);
  232. // check rr_type and free data elements
  233. switch (rr->type) {
  234. case RR_PTR:
  235. if (rr->data.PTR.name)
  236. free(rr->data.PTR.name);
  237. // don't free entry
  238. break;
  239. case RR_TXT:
  240. txt_rec = &rr->data.TXT;
  241. while (txt_rec) {
  242. struct rr_data_txt *next = txt_rec->next;
  243. if (txt_rec->txt)
  244. free(txt_rec->txt);
  245. // only free() if it wasn't part of the struct
  246. if (txt_rec != &rr->data.TXT)
  247. free(txt_rec);
  248. txt_rec = next;
  249. }
  250. break;
  251. case RR_SRV:
  252. if (rr->data.SRV.target)
  253. free(rr->data.SRV.target);
  254. break;
  255. case RR_AAAA:
  256. if (rr->data.AAAA.addr)
  257. free(rr->data.AAAA.addr);
  258. break;
  259. default:
  260. // nothing to free
  261. break;
  262. }
  263. free(rr->name);
  264. free(rr);
  265. }
  266. // destroys an RR list (and optionally, items)
  267. void rr_list_destroy(struct rr_list *rr, char destroy_items) {
  268. struct rr_list *rr_next;
  269. for (; rr; rr = rr_next) {
  270. rr_next = rr->next;
  271. if (destroy_items)
  272. rr_entry_destroy(rr->e);
  273. free(rr);
  274. }
  275. }
  276. int rr_list_count(struct rr_list *rr) {
  277. int i = 0;
  278. for (; rr; i++, rr = rr->next);
  279. return i;
  280. }
  281. struct rr_entry *rr_entry_remove(struct rr_group *group, struct rr_entry *entry, enum rr_type type) {
  282. struct rr_group *g;
  283. for (g = group; g; g = g->next) {
  284. struct rr_list *lrr = g->rr, *prr= NULL;
  285. for (; lrr; lrr = lrr->next) {
  286. if (lrr->e->type == type) {
  287. switch (type) {
  288. case RR_PTR:
  289. if (lrr->e->data.PTR.entry == entry) {
  290. struct rr_entry *e = lrr->e;
  291. if (prr == NULL) {
  292. g->rr = lrr->next;
  293. } else {
  294. prr->next = lrr->next;
  295. }
  296. free(lrr);
  297. return e;
  298. }
  299. break;
  300. default:
  301. break;
  302. }
  303. }
  304. prr = lrr;
  305. }
  306. }
  307. return NULL;
  308. }
  309. struct rr_entry *rr_list_remove(struct rr_list **rr_head, struct rr_entry *rr) {
  310. struct rr_list *le = *rr_head, *pe = NULL;
  311. for (; le; le = le->next) {
  312. if (le->e == rr) {
  313. if (pe == NULL) {
  314. *rr_head = le->next;
  315. free(le);
  316. return rr;
  317. } else {
  318. pe->next = le->next;
  319. free(le);
  320. return rr;
  321. }
  322. }
  323. pe = le;
  324. }
  325. return NULL;
  326. }
  327. void rr_group_clean(struct rr_group **head) {
  328. struct rr_group *le = *head, *pe = NULL;
  329. while (le) {
  330. if (le->rr == NULL) {
  331. free(le->name);
  332. if (pe == NULL) {
  333. *head = le->next;
  334. free(le);
  335. le = *head;
  336. } else {
  337. pe->next = le->next;
  338. free(le);
  339. le = pe->next;
  340. }
  341. } else {
  342. pe = le;
  343. le = le->next;
  344. }
  345. }
  346. }
  347. // appends an rr_entry to an RR list
  348. // if the RR is already in the list, it will not be added
  349. // RRs are compared by memory location - not its contents
  350. // return value of 0 means item not added
  351. int rr_list_append(struct rr_list **rr_head, struct rr_entry *rr) {
  352. struct rr_list *node = malloc(sizeof(struct rr_list));
  353. node->e = rr;
  354. node->next = NULL;
  355. if (*rr_head == NULL) {
  356. *rr_head = node;
  357. } else {
  358. struct rr_list *e = *rr_head, *taile = NULL;
  359. for (; e; e = e->next) {
  360. // already in list - don't add
  361. if (e->e == rr) {
  362. free(node);
  363. return 0;
  364. }
  365. if (e->next == NULL)
  366. taile = e;
  367. }
  368. taile->next = node;
  369. }
  370. return 1;
  371. }
  372. #define FILL_RR_ENTRY(rr, _name, _type) \
  373. rr->name = _name; \
  374. rr->type = _type; \
  375. rr->ttl = DEFAULT_TTL; \
  376. rr->cache_flush = 1; \
  377. rr->rr_class = 1;
  378. struct rr_entry *rr_create_a(uint8_t *name, struct in_addr addr) {
  379. DECL_MALLOC_ZERO_STRUCT(rr, rr_entry);
  380. FILL_RR_ENTRY(rr, name, RR_A);
  381. rr->data.A.addr = addr.s_addr;
  382. rr->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME; // 120 seconds -- see RFC 6762 Section 10
  383. return rr;
  384. }
  385. struct rr_entry *rr_create_aaaa(uint8_t *name, struct in6_addr *addr) {
  386. DECL_MALLOC_ZERO_STRUCT(rr, rr_entry);
  387. FILL_RR_ENTRY(rr, name, RR_AAAA);
  388. rr->data.AAAA.addr = addr;
  389. rr->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME; // 120 seconds -- see RFC 6762 Section 10
  390. return rr;
  391. }
  392. struct rr_entry *rr_create_srv(uint8_t *name, uint16_t port, uint8_t *target) {
  393. DECL_MALLOC_ZERO_STRUCT(rr, rr_entry);
  394. FILL_RR_ENTRY(rr, name, RR_SRV);
  395. rr->data.SRV.port = port;
  396. rr->data.SRV.target = target;
  397. rr->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME; // 120 seconds -- see RFC 6762 Section 10
  398. return rr;
  399. }
  400. struct rr_entry *rr_create_ptr(uint8_t *name, struct rr_entry *d_rr) {
  401. DECL_MALLOC_ZERO_STRUCT(rr, rr_entry);
  402. FILL_RR_ENTRY(rr, name, RR_PTR);
  403. rr->cache_flush = 0; // PTRs shouldn't have their cache flush bit set
  404. rr->data.PTR.entry = d_rr;
  405. rr->ttl = DEFAULT_TTL_FOR_RECORD_WITH_HOSTNAME; // 120 seconds -- see RFC 6762 Section 10
  406. return rr;
  407. }
  408. struct rr_entry *rr_create(uint8_t *name, enum rr_type type) {
  409. DECL_MALLOC_ZERO_STRUCT(rr, rr_entry);
  410. FILL_RR_ENTRY(rr, name, type);
  411. return rr;
  412. }
  413. void rr_set_nsec(struct rr_entry *rr_nsec, enum rr_type type) {
  414. assert(rr_nsec->type == RR_NSEC);
  415. assert((type / 8) < sizeof(rr_nsec->data.NSEC.bitmap));
  416. rr_nsec->data.NSEC.bitmap[ type / 8 ] = 1 << (7 - (type % 8));
  417. }
  418. void rr_add_txt(struct rr_entry *rr_txt, const char *txt) {
  419. struct rr_data_txt *txt_rec;
  420. assert(rr_txt->type == RR_TXT);
  421. txt_rec = &rr_txt->data.TXT;
  422. // is current data filled?
  423. if (txt_rec->txt == NULL) {
  424. txt_rec->txt = create_label(txt);
  425. return;
  426. }
  427. // find the last node
  428. for (; txt_rec->next; txt_rec = txt_rec->next);
  429. // create a new empty node
  430. txt_rec->next = malloc(sizeof(struct rr_data_txt));
  431. txt_rec = txt_rec->next;
  432. txt_rec->txt = create_label(txt);
  433. txt_rec->next = NULL;
  434. }
  435. // adds a record to an rr_group
  436. void rr_group_add(struct rr_group **group, struct rr_entry *rr) {
  437. struct rr_group *g;
  438. assert(rr != NULL);
  439. if (*group) {
  440. g = rr_group_find(*group, rr->name);
  441. if (g) {
  442. rr_list_append(&g->rr, rr);
  443. return;
  444. }
  445. }
  446. MALLOC_ZERO_STRUCT(g, rr_group);
  447. g->name = dup_nlabel(rr->name);
  448. rr_list_append(&g->rr, rr);
  449. // prepend to list
  450. g->next = *group;
  451. *group = g;
  452. }
  453. // finds a rr_group matching the given name
  454. struct rr_group *rr_group_find(struct rr_group* g, uint8_t *name) {
  455. for (; g; g = g->next) {
  456. if (cmp_nlabel(g->name, name) == 0)
  457. return g;
  458. }
  459. return NULL;
  460. }
  461. struct rr_entry *rr_entry_find(struct rr_list *rr_list, uint8_t *name, uint16_t type) {
  462. struct rr_list *rr = rr_list;
  463. for (; rr; rr = rr->next) {
  464. if (rr->e->type == type && cmp_nlabel(rr->e->name, name) == 0)
  465. return rr->e;
  466. }
  467. return NULL;
  468. }
  469. // looks for a matching entry in rr_list
  470. // if entry is a PTR, we need to check if the PTR target also matches
  471. struct rr_entry *rr_entry_match(struct rr_list *rr_list, struct rr_entry *entry) {
  472. struct rr_list *rr = rr_list;
  473. for (; rr; rr = rr->next) {
  474. if (rr->e->type == entry->type && cmp_nlabel(rr->e->name, entry->name) == 0) {
  475. if (entry->type != RR_PTR) {
  476. return rr->e;
  477. } else if (cmp_nlabel(MDNS_RR_GET_PTR_NAME(entry), MDNS_RR_GET_PTR_NAME(rr->e)) == 0) {
  478. // if it's a PTR, we need to make sure PTR target also matches
  479. return rr->e;
  480. }
  481. }
  482. }
  483. return NULL;
  484. }
  485. void rr_group_destroy(struct rr_group *group) {
  486. struct rr_group *g = group;
  487. while (g) {
  488. struct rr_group *nextg = g->next;
  489. free(g->name);
  490. rr_list_destroy(g->rr, 1);
  491. free(g);
  492. g = nextg;
  493. }
  494. }
  495. uint8_t *mdns_write_u16(uint8_t *ptr, const uint16_t v) {
  496. *ptr++ = (uint8_t) (v >> 8) & 0xFF;
  497. *ptr++ = (uint8_t) (v >> 0) & 0xFF;
  498. return ptr;
  499. }
  500. uint8_t *mdns_write_u32(uint8_t *ptr, const uint32_t v) {
  501. *ptr++ = (uint8_t) (v >> 24) & 0xFF;
  502. *ptr++ = (uint8_t) (v >> 16) & 0xFF;
  503. *ptr++ = (uint8_t) (v >> 8) & 0xFF;
  504. *ptr++ = (uint8_t) (v >> 0) & 0xFF;
  505. return ptr;
  506. }
  507. uint16_t mdns_read_u16(const uint8_t *ptr) {
  508. return ((ptr[0] & 0xFF) << 8) |
  509. ((ptr[1] & 0xFF) << 0);
  510. }
  511. uint32_t mdns_read_u32(const uint8_t *ptr) {
  512. return ((ptr[0] & 0xFF) << 24) |
  513. ((ptr[1] & 0xFF) << 16) |
  514. ((ptr[2] & 0xFF) << 8) |
  515. ((ptr[3] & 0xFF) << 0);
  516. }
  517. // initialize the packet for reply
  518. // clears the packet of list structures but not its list items
  519. void mdns_init_reply(struct mdns_pkt *pkt, uint16_t id) {
  520. // broadcast by default
  521. pkt->unicast = 0;
  522. // copy transaction ID
  523. pkt->id = id;
  524. // response flags
  525. pkt->flags = MDNS_FLAG_RESP | MDNS_FLAG_AA;
  526. rr_list_destroy(pkt->rr_qn, 0);
  527. rr_list_destroy(pkt->rr_ans, 0);
  528. rr_list_destroy(pkt->rr_auth, 0);
  529. rr_list_destroy(pkt->rr_add, 0);
  530. pkt->rr_qn = NULL;
  531. pkt->rr_ans = NULL;
  532. pkt->rr_auth = NULL;
  533. pkt->rr_add = NULL;
  534. pkt->num_qn = 0;
  535. pkt->num_ans_rr = 0;
  536. pkt->num_auth_rr = 0;
  537. pkt->num_add_rr = 0;
  538. }
  539. // destroys an mdns_pkt struct, including its contents
  540. void mdns_pkt_destroy(struct mdns_pkt *p) {
  541. rr_list_destroy(p->rr_qn, 1);
  542. rr_list_destroy(p->rr_ans, 1);
  543. rr_list_destroy(p->rr_auth, 1);
  544. rr_list_destroy(p->rr_add, 1);
  545. free(p);
  546. }
  547. // parse the MDNS questions section
  548. // stores the parsed data in the given mdns_pkt struct
  549. static size_t mdns_parse_qn(uint8_t *pkt_buf, size_t pkt_len, size_t off,
  550. struct mdns_pkt *pkt) {
  551. const uint8_t *p = pkt_buf + off;
  552. struct rr_entry *rr;
  553. uint8_t *name;
  554. assert(pkt != NULL);
  555. rr = malloc(sizeof(struct rr_entry));
  556. memset(rr, 0, sizeof(struct rr_entry));
  557. name = uncompress_nlabel(pkt_buf, pkt_len, off);
  558. p += label_len(pkt_buf, pkt_len, off);
  559. rr->name = name;
  560. rr->type = mdns_read_u16(p);
  561. p += sizeof(uint16_t);
  562. rr->unicast_query = (*p & 0x80) == 0x80;
  563. rr->rr_class = mdns_read_u16(p) & ~0x80;
  564. p += sizeof(uint16_t);
  565. rr_list_append(&pkt->rr_qn, rr);
  566. return p - (pkt_buf + off);
  567. }
  568. // parse the MDNS RR section
  569. // stores the parsed data in the given mdns_pkt struct
  570. static size_t mdns_parse_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off,
  571. struct mdns_pkt *pkt) {
  572. const uint8_t *p = pkt_buf + off;
  573. const uint8_t *e = pkt_buf + pkt_len;
  574. struct rr_entry *rr;
  575. uint8_t *name;
  576. size_t rr_data_len = 0;
  577. struct rr_data_txt *txt_rec;
  578. int parse_error = 0;
  579. assert(pkt != NULL);
  580. if (off > pkt_len)
  581. return 0;
  582. rr = malloc(sizeof(struct rr_entry));
  583. memset(rr, 0, sizeof(struct rr_entry));
  584. name = uncompress_nlabel(pkt_buf, pkt_len, off);
  585. p += label_len(pkt_buf, pkt_len, off);
  586. rr->name = name;
  587. rr->type = mdns_read_u16(p);
  588. p += sizeof(uint16_t);
  589. rr->cache_flush = (*p & 0x80) == 0x80;
  590. rr->rr_class = mdns_read_u16(p) & ~0x80;
  591. p += sizeof(uint16_t);
  592. rr->ttl = mdns_read_u32(p);
  593. p += sizeof(uint32_t);
  594. // RR data
  595. rr_data_len = mdns_read_u16(p);
  596. p += sizeof(uint16_t);
  597. if (p + rr_data_len > e) {
  598. DEBUG_PRINTF("rr_data_len goes beyond packet buffer: %zu > %zu\n", rr_data_len, e - p);
  599. rr_entry_destroy(rr);
  600. return 0;
  601. }
  602. e = p + rr_data_len;
  603. // see if we can parse the RR data
  604. switch (rr->type) {
  605. case RR_A:
  606. if (rr_data_len < sizeof(uint32_t)) {
  607. DEBUG_PRINTF("invalid rr_data_len=%zu for A record\n", rr_data_len);
  608. parse_error = 1;
  609. break;
  610. }
  611. rr->data.A.addr = ntohl(mdns_read_u32(p)); /* addr already in net order */
  612. p += sizeof(uint32_t);
  613. break;
  614. case RR_AAAA: {
  615. int i;
  616. if (rr_data_len < sizeof(struct in6_addr)) {
  617. DEBUG_PRINTF("invalid rr_data_len=%zu for AAAA record\n", rr_data_len);
  618. parse_error = 1;
  619. break;
  620. }
  621. rr->data.AAAA.addr = malloc(sizeof(struct in6_addr));
  622. for (i = 0; i < sizeof(struct in6_addr); i++)
  623. rr->data.AAAA.addr->s6_addr[i] = p[i];
  624. p += sizeof(struct in6_addr);
  625. break;
  626. }
  627. case RR_PTR:
  628. rr->data.PTR.name = uncompress_nlabel(pkt_buf, pkt_len, p - pkt_buf);
  629. if (rr->data.PTR.name == NULL) {
  630. DEBUG_PRINTF("unable to parse/uncompress label for PTR name\n");
  631. parse_error = 1;
  632. break;
  633. }
  634. p += rr_data_len;
  635. break;
  636. case RR_TXT:
  637. txt_rec = &rr->data.TXT;
  638. // not supposed to happen, but we should handle it
  639. if (rr_data_len == 0) {
  640. DEBUG_PRINTF("WARN: rr_data_len for TXT is 0\n");
  641. txt_rec->txt = create_label("");
  642. break;
  643. }
  644. while (1) {
  645. txt_rec->txt = copy_label(pkt_buf, pkt_len, p - pkt_buf);
  646. if (txt_rec->txt == NULL) {
  647. DEBUG_PRINTF("unable to copy label for TXT record\n");
  648. parse_error = 1;
  649. break;
  650. }
  651. p += txt_rec->txt[0] + 1;
  652. if (p >= e)
  653. break;
  654. // allocate another record
  655. txt_rec->next = malloc(sizeof(struct rr_data_txt));
  656. txt_rec = txt_rec->next;
  657. txt_rec->next = NULL;
  658. }
  659. break;
  660. default:
  661. // skip to end of RR data
  662. p = e;
  663. }
  664. // if there was a parse error, destroy partial rr_entry
  665. if (parse_error) {
  666. rr_entry_destroy(rr);
  667. return 0;
  668. }
  669. rr_list_append(&pkt->rr_ans, rr);
  670. return p - (pkt_buf + off);
  671. }
  672. // parse a MDNS packet into an mdns_pkt struct
  673. struct mdns_pkt *mdns_parse_pkt(uint8_t *pkt_buf, size_t pkt_len) {
  674. uint8_t *p = pkt_buf;
  675. size_t off;
  676. struct mdns_pkt *pkt;
  677. int i;
  678. if (pkt_len < 12)
  679. return NULL;
  680. MALLOC_ZERO_STRUCT(pkt, mdns_pkt);
  681. // parse header
  682. pkt->id = mdns_read_u16(p); p += sizeof(uint16_t);
  683. pkt->flags = mdns_read_u16(p); p += sizeof(uint16_t);
  684. pkt->num_qn = mdns_read_u16(p); p += sizeof(uint16_t);
  685. pkt->num_ans_rr = mdns_read_u16(p); p += sizeof(uint16_t);
  686. pkt->num_auth_rr = mdns_read_u16(p); p += sizeof(uint16_t);
  687. pkt->num_add_rr = mdns_read_u16(p); p += sizeof(uint16_t);
  688. off = p - pkt_buf;
  689. // parse questions
  690. for (i = 0; i < pkt->num_qn; i++) {
  691. size_t l = mdns_parse_qn(pkt_buf, pkt_len, off, pkt);
  692. if (! l) {
  693. DEBUG_PRINTF("error parsing question #%d\n", i);
  694. mdns_pkt_destroy(pkt);
  695. return NULL;
  696. }
  697. off += l;
  698. }
  699. // parse answer RRs
  700. for (i = 0; i < pkt->num_ans_rr; i++) {
  701. size_t l = mdns_parse_rr(pkt_buf, pkt_len, off, pkt);
  702. if (! l) {
  703. DEBUG_PRINTF("error parsing answer #%d\n", i);
  704. mdns_pkt_destroy(pkt);
  705. return NULL;
  706. }
  707. off += l;
  708. }
  709. // TODO: parse the authority and additional RR sections
  710. return pkt;
  711. }
  712. // encodes a name (label) into a packet using the name compression scheme
  713. // encoded names will be added to the compression list for subsequent use
  714. static size_t mdns_encode_name(uint8_t *pkt_buf, size_t pkt_len, size_t off,
  715. const uint8_t *name, struct name_comp *comp) {
  716. struct name_comp *c, *c_tail = NULL;
  717. uint8_t *p = pkt_buf + off;
  718. size_t len = 0;
  719. if (name) {
  720. while (*name) {
  721. int segment_len;
  722. // cache the name for subsequent compression
  723. DECL_STRUCT(new_c, name_comp);
  724. // find match for compression
  725. for (c = comp; c; c = c->next) {
  726. if (cmp_nlabel(name, c->label) == 0) {
  727. mdns_write_u16(p, 0xC000 | (c->pos & ~0xC000));
  728. return len + sizeof(uint16_t);
  729. }
  730. if (c->next == NULL)
  731. c_tail = c;
  732. }
  733. // copy this segment
  734. segment_len = *name + 1;
  735. strncpy((char *) p, (char *) name, segment_len);
  736. MALLOC_ZERO_STRUCT(new_c, name_comp);
  737. new_c->label = (uint8_t *) name;
  738. new_c->pos = p - pkt_buf;
  739. c_tail->next = new_c;
  740. // advance to next name segment
  741. p += segment_len;
  742. len += segment_len;
  743. name += segment_len;
  744. }
  745. }
  746. *p = '\0'; // root "label"
  747. len += 1;
  748. return len;
  749. }
  750. // encodes an RR entry at the given offset
  751. // returns the size of the entire RR entry
  752. static size_t mdns_encode_rr(uint8_t *pkt_buf, size_t pkt_len, size_t off,
  753. struct rr_entry *rr, struct name_comp *comp) {
  754. uint8_t *p = pkt_buf + off, *p_data;
  755. size_t l;
  756. struct rr_data_txt *txt_rec;
  757. uint8_t *label;
  758. int i;
  759. assert(off < pkt_len);
  760. // name
  761. l = mdns_encode_name(pkt_buf, pkt_len, off, rr->name, comp);
  762. assert(l != 0);
  763. p += l;
  764. // type
  765. p = mdns_write_u16(p, rr->type);
  766. // class & cache flush
  767. p = mdns_write_u16(p, (rr->rr_class & ~0x8000) | (rr->cache_flush << 15));
  768. // TTL
  769. p = mdns_write_u32(p, rr->ttl);
  770. // data length (filled in later)
  771. p += sizeof(uint16_t);
  772. // start of data marker
  773. p_data = p;
  774. switch (rr->type) {
  775. case RR_A:
  776. /* htonl() needed coz addr already in net order */
  777. p = mdns_write_u32(p, htonl(rr->data.A.addr));
  778. break;
  779. case RR_AAAA:
  780. for (i = 0; i < sizeof(struct in6_addr); i++)
  781. *p++ = rr->data.AAAA.addr->s6_addr[i];
  782. break;
  783. case RR_PTR:
  784. label = rr->data.PTR.name ?
  785. rr->data.PTR.name :
  786. rr->data.PTR.entry->name;
  787. p += mdns_encode_name(pkt_buf, pkt_len, p - pkt_buf, label, comp);
  788. break;
  789. case RR_TXT:
  790. txt_rec = &rr->data.TXT;
  791. for (; txt_rec; txt_rec = txt_rec->next) {
  792. int len = txt_rec->txt[0] + 1;
  793. strncpy((char *) p, (char *) txt_rec->txt, len);
  794. p += len;
  795. }
  796. break;
  797. case RR_SRV:
  798. p = mdns_write_u16(p, rr->data.SRV.priority);
  799. p = mdns_write_u16(p, rr->data.SRV.weight);
  800. p = mdns_write_u16(p, rr->data.SRV.port);
  801. p += mdns_encode_name(pkt_buf, pkt_len, p - pkt_buf,
  802. rr->data.SRV.target, comp);
  803. break;
  804. case RR_NSEC:
  805. p += mdns_encode_name(pkt_buf, pkt_len, p - pkt_buf,
  806. rr->name, comp);
  807. *p++ = 0; // bitmap window/block number
  808. *p++ = sizeof(rr->data.NSEC.bitmap); // bitmap length
  809. for (i = 0; i < sizeof(rr->data.NSEC.bitmap); i++)
  810. *p++ = rr->data.NSEC.bitmap[i];
  811. break;
  812. default:
  813. DEBUG_PRINTF("unhandled rr type 0x%02x\n", rr->type);
  814. }
  815. // calculate data length based on p
  816. l = p - p_data;
  817. // fill in the length
  818. mdns_write_u16(p - l - sizeof(uint16_t), l);
  819. return p - pkt_buf - off;
  820. }
  821. // encodes a MDNS packet from the given mdns_pkt struct into a buffer
  822. // returns the size of the entire MDNS packet
  823. size_t mdns_encode_pkt(struct mdns_pkt *answer, uint8_t *pkt_buf, size_t pkt_len) {
  824. struct name_comp *comp;
  825. uint8_t *p = pkt_buf;
  826. //uint8_t *e = pkt_buf + pkt_len;
  827. size_t off;
  828. int i;
  829. struct rr_list *rr_set[3];
  830. assert(answer != NULL);
  831. assert(pkt_len >= 12);
  832. if (p == NULL)
  833. return -1;
  834. // this is an Answer - number of qns should be zero
  835. assert(answer->num_qn == 0);
  836. p = mdns_write_u16(p, answer->id);
  837. p = mdns_write_u16(p, answer->flags);
  838. p = mdns_write_u16(p, answer->num_qn);
  839. p = mdns_write_u16(p, answer->num_ans_rr);
  840. p = mdns_write_u16(p, answer->num_auth_rr);
  841. p = mdns_write_u16(p, answer->num_add_rr);
  842. off = p - pkt_buf;
  843. // allocate list for name compression
  844. comp = malloc(sizeof(struct name_comp));
  845. if (comp == NULL)
  846. return -1;
  847. memset(comp, 0, sizeof(struct name_comp));
  848. // dummy entry
  849. comp->label = (uint8_t *) "";
  850. comp->pos = 0;
  851. // skip encoding of qn
  852. rr_set[0] = answer->rr_ans;
  853. rr_set[1] = answer->rr_auth;
  854. rr_set[2] = answer->rr_add;
  855. // encode answer, authority and additional RRs
  856. for (i = 0; i < sizeof(rr_set) / sizeof(rr_set[0]); i++) {
  857. struct rr_list *rr = rr_set[i];
  858. for (; rr; rr = rr->next) {
  859. size_t l = mdns_encode_rr(pkt_buf, pkt_len, off, rr->e, comp);
  860. off += l;
  861. if (off >= pkt_len) {
  862. DEBUG_PRINTF("packet buffer too small\n");
  863. return -1;
  864. }
  865. }
  866. }
  867. // free name compression list
  868. while (comp) {
  869. struct name_comp *c = comp->next;
  870. free(comp);
  871. comp = c;
  872. }
  873. return off;
  874. }