print-lwres.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /*
  2. * Copyright (C) 2001 WIDE Project.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the project nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /* \summary: BIND9 Lightweight Resolver protocol printer */
  30. #ifdef HAVE_CONFIG_H
  31. #include "config.h"
  32. #endif
  33. #include <netdissect-stdinc.h>
  34. #include "nameser.h"
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include "netdissect.h"
  38. #include "addrtoname.h"
  39. #include "extract.h"
  40. /* BIND9 lib/lwres/include/lwres */
  41. typedef uint32_t lwres_uint32_t;
  42. typedef uint16_t lwres_uint16_t;
  43. typedef uint8_t lwres_uint8_t;
  44. struct lwres_lwpacket {
  45. lwres_uint32_t length;
  46. lwres_uint16_t version;
  47. lwres_uint16_t pktflags;
  48. lwres_uint32_t serial;
  49. lwres_uint32_t opcode;
  50. lwres_uint32_t result;
  51. lwres_uint32_t recvlength;
  52. lwres_uint16_t authtype;
  53. lwres_uint16_t authlength;
  54. };
  55. #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
  56. #define LWRES_LWPACKETVERSION_0 0
  57. #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
  58. #define LWRES_FLAG_SECUREDATA 0x00000002U
  59. /*
  60. * no-op
  61. */
  62. #define LWRES_OPCODE_NOOP 0x00000000U
  63. typedef struct {
  64. /* public */
  65. lwres_uint16_t datalength;
  66. /* data follows */
  67. } lwres_nooprequest_t;
  68. typedef struct {
  69. /* public */
  70. lwres_uint16_t datalength;
  71. /* data follows */
  72. } lwres_noopresponse_t;
  73. /*
  74. * get addresses by name
  75. */
  76. #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
  77. typedef struct lwres_addr lwres_addr_t;
  78. struct lwres_addr {
  79. lwres_uint32_t family;
  80. lwres_uint16_t length;
  81. /* address folows */
  82. };
  83. typedef struct {
  84. /* public */
  85. lwres_uint32_t flags;
  86. lwres_uint32_t addrtypes;
  87. lwres_uint16_t namelen;
  88. /* name follows */
  89. } lwres_gabnrequest_t;
  90. typedef struct {
  91. /* public */
  92. lwres_uint32_t flags;
  93. lwres_uint16_t naliases;
  94. lwres_uint16_t naddrs;
  95. lwres_uint16_t realnamelen;
  96. /* aliases follows */
  97. /* addrs follows */
  98. /* realname follows */
  99. } lwres_gabnresponse_t;
  100. /*
  101. * get name by address
  102. */
  103. #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
  104. typedef struct {
  105. /* public */
  106. lwres_uint32_t flags;
  107. lwres_addr_t addr;
  108. /* addr body follows */
  109. } lwres_gnbarequest_t;
  110. typedef struct {
  111. /* public */
  112. lwres_uint32_t flags;
  113. lwres_uint16_t naliases;
  114. lwres_uint16_t realnamelen;
  115. /* aliases follows */
  116. /* realname follows */
  117. } lwres_gnbaresponse_t;
  118. /*
  119. * get rdata by name
  120. */
  121. #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
  122. typedef struct {
  123. /* public */
  124. lwres_uint32_t flags;
  125. lwres_uint16_t rdclass;
  126. lwres_uint16_t rdtype;
  127. lwres_uint16_t namelen;
  128. /* name follows */
  129. } lwres_grbnrequest_t;
  130. typedef struct {
  131. /* public */
  132. lwres_uint32_t flags;
  133. lwres_uint16_t rdclass;
  134. lwres_uint16_t rdtype;
  135. lwres_uint32_t ttl;
  136. lwres_uint16_t nrdatas;
  137. lwres_uint16_t nsigs;
  138. /* realname here (len + name) */
  139. /* rdata here (len + name) */
  140. /* signatures here (len + name) */
  141. } lwres_grbnresponse_t;
  142. #define LWRDATA_VALIDATED 0x00000001
  143. #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
  144. #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
  145. #define LWRES_MAX_ALIASES 16 /* max # of aliases */
  146. #define LWRES_MAX_ADDRS 64 /* max # of addrs */
  147. static const struct tok opcode[] = {
  148. { LWRES_OPCODE_NOOP, "noop", },
  149. { LWRES_OPCODE_GETADDRSBYNAME, "getaddrsbyname", },
  150. { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr", },
  151. { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname", },
  152. { 0, NULL, },
  153. };
  154. /* print-domain.c */
  155. extern const struct tok ns_type2str[];
  156. extern const struct tok ns_class2str[];
  157. static int
  158. lwres_printname(netdissect_options *ndo,
  159. size_t l, const char *p0)
  160. {
  161. const char *p;
  162. size_t i;
  163. p = p0;
  164. /* + 1 for terminating \0 */
  165. if (p + l + 1 > (const char *)ndo->ndo_snapend)
  166. goto trunc;
  167. ND_PRINT((ndo, " "));
  168. for (i = 0; i < l; i++)
  169. safeputchar(ndo, *p++);
  170. p++; /* skip terminating \0 */
  171. return p - p0;
  172. trunc:
  173. return -1;
  174. }
  175. static int
  176. lwres_printnamelen(netdissect_options *ndo,
  177. const char *p)
  178. {
  179. uint16_t l;
  180. int advance;
  181. if (p + 2 > (const char *)ndo->ndo_snapend)
  182. goto trunc;
  183. l = EXTRACT_16BITS(p);
  184. advance = lwres_printname(ndo, l, p + 2);
  185. if (advance < 0)
  186. goto trunc;
  187. return 2 + advance;
  188. trunc:
  189. return -1;
  190. }
  191. static int
  192. lwres_printbinlen(netdissect_options *ndo,
  193. const char *p0)
  194. {
  195. const char *p;
  196. uint16_t l;
  197. int i;
  198. p = p0;
  199. if (p + 2 > (const char *)ndo->ndo_snapend)
  200. goto trunc;
  201. l = EXTRACT_16BITS(p);
  202. if (p + 2 + l > (const char *)ndo->ndo_snapend)
  203. goto trunc;
  204. p += 2;
  205. for (i = 0; i < l; i++)
  206. ND_PRINT((ndo, "%02x", *p++));
  207. return p - p0;
  208. trunc:
  209. return -1;
  210. }
  211. static int
  212. lwres_printaddr(netdissect_options *ndo,
  213. const lwres_addr_t *ap)
  214. {
  215. uint16_t l;
  216. const char *p;
  217. int i;
  218. ND_TCHECK(ap->length);
  219. l = EXTRACT_16BITS(&ap->length);
  220. /* XXX ap points to packed struct */
  221. p = (const char *)&ap->length + sizeof(ap->length);
  222. ND_TCHECK2(*p, l);
  223. switch (EXTRACT_32BITS(&ap->family)) {
  224. case 1: /* IPv4 */
  225. if (l < 4)
  226. return -1;
  227. ND_PRINT((ndo, " %s", ipaddr_string(ndo, p)));
  228. p += sizeof(struct in_addr);
  229. break;
  230. case 2: /* IPv6 */
  231. if (l < 16)
  232. return -1;
  233. ND_PRINT((ndo, " %s", ip6addr_string(ndo, p)));
  234. p += sizeof(struct in6_addr);
  235. break;
  236. default:
  237. ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family)));
  238. for (i = 0; i < l; i++)
  239. ND_PRINT((ndo, "%02x", *p++));
  240. }
  241. return p - (const char *)ap;
  242. trunc:
  243. return -1;
  244. }
  245. void
  246. lwres_print(netdissect_options *ndo,
  247. register const u_char *bp, u_int length)
  248. {
  249. const struct lwres_lwpacket *np;
  250. uint32_t v;
  251. const char *s;
  252. int response;
  253. int advance;
  254. int unsupported = 0;
  255. np = (const struct lwres_lwpacket *)bp;
  256. ND_TCHECK(np->authlength);
  257. ND_PRINT((ndo, " lwres"));
  258. v = EXTRACT_16BITS(&np->version);
  259. if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
  260. ND_PRINT((ndo, " v%u", v));
  261. if (v != LWRES_LWPACKETVERSION_0) {
  262. s = (const char *)np + EXTRACT_32BITS(&np->length);
  263. goto tail;
  264. }
  265. response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
  266. /* opcode and pktflags */
  267. v = EXTRACT_32BITS(&np->opcode);
  268. s = tok2str(opcode, "#0x%x", v);
  269. ND_PRINT((ndo, " %s%s", s, response ? "" : "?"));
  270. /* pktflags */
  271. v = EXTRACT_16BITS(&np->pktflags);
  272. if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
  273. ND_PRINT((ndo, "[0x%x]", v));
  274. if (ndo->ndo_vflag > 1) {
  275. ND_PRINT((ndo, " (")); /*)*/
  276. ND_PRINT((ndo, "serial:0x%x", EXTRACT_32BITS(&np->serial)));
  277. ND_PRINT((ndo, " result:0x%x", EXTRACT_32BITS(&np->result)));
  278. ND_PRINT((ndo, " recvlen:%u", EXTRACT_32BITS(&np->recvlength)));
  279. /* BIND910: not used */
  280. if (ndo->ndo_vflag > 2) {
  281. ND_PRINT((ndo, " authtype:0x%x", EXTRACT_16BITS(&np->authtype)));
  282. ND_PRINT((ndo, " authlen:%u", EXTRACT_16BITS(&np->authlength)));
  283. }
  284. /*(*/
  285. ND_PRINT((ndo, ")"));
  286. }
  287. /* per-opcode content */
  288. if (!response) {
  289. /*
  290. * queries
  291. */
  292. const lwres_gabnrequest_t *gabn;
  293. const lwres_gnbarequest_t *gnba;
  294. const lwres_grbnrequest_t *grbn;
  295. uint32_t l;
  296. gabn = NULL;
  297. gnba = NULL;
  298. grbn = NULL;
  299. switch (EXTRACT_32BITS(&np->opcode)) {
  300. case LWRES_OPCODE_NOOP:
  301. break;
  302. case LWRES_OPCODE_GETADDRSBYNAME:
  303. gabn = (const lwres_gabnrequest_t *)(np + 1);
  304. ND_TCHECK(gabn->namelen);
  305. /* XXX gabn points to packed struct */
  306. s = (const char *)&gabn->namelen +
  307. sizeof(gabn->namelen);
  308. l = EXTRACT_16BITS(&gabn->namelen);
  309. /* BIND910: not used */
  310. if (ndo->ndo_vflag > 2) {
  311. ND_PRINT((ndo, " flags:0x%x",
  312. EXTRACT_32BITS(&gabn->flags)));
  313. }
  314. v = EXTRACT_32BITS(&gabn->addrtypes);
  315. switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
  316. case LWRES_ADDRTYPE_V4:
  317. ND_PRINT((ndo, " IPv4"));
  318. break;
  319. case LWRES_ADDRTYPE_V6:
  320. ND_PRINT((ndo, " IPv6"));
  321. break;
  322. case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
  323. ND_PRINT((ndo, " IPv4/6"));
  324. break;
  325. }
  326. if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
  327. ND_PRINT((ndo, "[0x%x]", v));
  328. advance = lwres_printname(ndo, l, s);
  329. if (advance < 0)
  330. goto trunc;
  331. s += advance;
  332. break;
  333. case LWRES_OPCODE_GETNAMEBYADDR:
  334. gnba = (const lwres_gnbarequest_t *)(np + 1);
  335. ND_TCHECK(gnba->addr);
  336. /* BIND910: not used */
  337. if (ndo->ndo_vflag > 2) {
  338. ND_PRINT((ndo, " flags:0x%x",
  339. EXTRACT_32BITS(&gnba->flags)));
  340. }
  341. s = (const char *)&gnba->addr;
  342. advance = lwres_printaddr(ndo, &gnba->addr);
  343. if (advance < 0)
  344. goto trunc;
  345. s += advance;
  346. break;
  347. case LWRES_OPCODE_GETRDATABYNAME:
  348. /* XXX no trace, not tested */
  349. grbn = (const lwres_grbnrequest_t *)(np + 1);
  350. ND_TCHECK(grbn->namelen);
  351. /* BIND910: not used */
  352. if (ndo->ndo_vflag > 2) {
  353. ND_PRINT((ndo, " flags:0x%x",
  354. EXTRACT_32BITS(&grbn->flags)));
  355. }
  356. ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
  357. EXTRACT_16BITS(&grbn->rdtype))));
  358. if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
  359. ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
  360. EXTRACT_16BITS(&grbn->rdclass))));
  361. }
  362. /* XXX grbn points to packed struct */
  363. s = (const char *)&grbn->namelen +
  364. sizeof(grbn->namelen);
  365. l = EXTRACT_16BITS(&grbn->namelen);
  366. advance = lwres_printname(ndo, l, s);
  367. if (advance < 0)
  368. goto trunc;
  369. s += advance;
  370. break;
  371. default:
  372. unsupported++;
  373. break;
  374. }
  375. } else {
  376. /*
  377. * responses
  378. */
  379. const lwres_gabnresponse_t *gabn;
  380. const lwres_gnbaresponse_t *gnba;
  381. const lwres_grbnresponse_t *grbn;
  382. uint32_t l, na;
  383. uint32_t i;
  384. gabn = NULL;
  385. gnba = NULL;
  386. grbn = NULL;
  387. switch (EXTRACT_32BITS(&np->opcode)) {
  388. case LWRES_OPCODE_NOOP:
  389. break;
  390. case LWRES_OPCODE_GETADDRSBYNAME:
  391. gabn = (const lwres_gabnresponse_t *)(np + 1);
  392. ND_TCHECK(gabn->realnamelen);
  393. /* XXX gabn points to packed struct */
  394. s = (const char *)&gabn->realnamelen +
  395. sizeof(gabn->realnamelen);
  396. l = EXTRACT_16BITS(&gabn->realnamelen);
  397. /* BIND910: not used */
  398. if (ndo->ndo_vflag > 2) {
  399. ND_PRINT((ndo, " flags:0x%x",
  400. EXTRACT_32BITS(&gabn->flags)));
  401. }
  402. ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&gabn->naliases),
  403. EXTRACT_16BITS(&gabn->naddrs)));
  404. advance = lwres_printname(ndo, l, s);
  405. if (advance < 0)
  406. goto trunc;
  407. s += advance;
  408. /* aliases */
  409. na = EXTRACT_16BITS(&gabn->naliases);
  410. for (i = 0; i < na; i++) {
  411. advance = lwres_printnamelen(ndo, s);
  412. if (advance < 0)
  413. goto trunc;
  414. s += advance;
  415. }
  416. /* addrs */
  417. na = EXTRACT_16BITS(&gabn->naddrs);
  418. for (i = 0; i < na; i++) {
  419. advance = lwres_printaddr(ndo, (const lwres_addr_t *)s);
  420. if (advance < 0)
  421. goto trunc;
  422. s += advance;
  423. }
  424. break;
  425. case LWRES_OPCODE_GETNAMEBYADDR:
  426. gnba = (const lwres_gnbaresponse_t *)(np + 1);
  427. ND_TCHECK(gnba->realnamelen);
  428. /* XXX gnba points to packed struct */
  429. s = (const char *)&gnba->realnamelen +
  430. sizeof(gnba->realnamelen);
  431. l = EXTRACT_16BITS(&gnba->realnamelen);
  432. /* BIND910: not used */
  433. if (ndo->ndo_vflag > 2) {
  434. ND_PRINT((ndo, " flags:0x%x",
  435. EXTRACT_32BITS(&gnba->flags)));
  436. }
  437. ND_PRINT((ndo, " %u", EXTRACT_16BITS(&gnba->naliases)));
  438. advance = lwres_printname(ndo, l, s);
  439. if (advance < 0)
  440. goto trunc;
  441. s += advance;
  442. /* aliases */
  443. na = EXTRACT_16BITS(&gnba->naliases);
  444. for (i = 0; i < na; i++) {
  445. advance = lwres_printnamelen(ndo, s);
  446. if (advance < 0)
  447. goto trunc;
  448. s += advance;
  449. }
  450. break;
  451. case LWRES_OPCODE_GETRDATABYNAME:
  452. /* XXX no trace, not tested */
  453. grbn = (const lwres_grbnresponse_t *)(np + 1);
  454. ND_TCHECK(grbn->nsigs);
  455. /* BIND910: not used */
  456. if (ndo->ndo_vflag > 2) {
  457. ND_PRINT((ndo, " flags:0x%x",
  458. EXTRACT_32BITS(&grbn->flags)));
  459. }
  460. ND_PRINT((ndo, " %s", tok2str(ns_type2str, "Type%d",
  461. EXTRACT_16BITS(&grbn->rdtype))));
  462. if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) {
  463. ND_PRINT((ndo, " %s", tok2str(ns_class2str, "Class%d",
  464. EXTRACT_16BITS(&grbn->rdclass))));
  465. }
  466. ND_PRINT((ndo, " TTL "));
  467. unsigned_relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
  468. ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
  469. EXTRACT_16BITS(&grbn->nsigs)));
  470. /* XXX grbn points to packed struct */
  471. s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs);
  472. advance = lwres_printnamelen(ndo, s);
  473. if (advance < 0)
  474. goto trunc;
  475. s += advance;
  476. /* rdatas */
  477. na = EXTRACT_16BITS(&grbn->nrdatas);
  478. for (i = 0; i < na; i++) {
  479. /* XXX should decode resource data */
  480. advance = lwres_printbinlen(ndo, s);
  481. if (advance < 0)
  482. goto trunc;
  483. s += advance;
  484. }
  485. /* sigs */
  486. na = EXTRACT_16BITS(&grbn->nsigs);
  487. for (i = 0; i < na; i++) {
  488. /* XXX how should we print it? */
  489. advance = lwres_printbinlen(ndo, s);
  490. if (advance < 0)
  491. goto trunc;
  492. s += advance;
  493. }
  494. break;
  495. default:
  496. unsupported++;
  497. break;
  498. }
  499. }
  500. tail:
  501. /* length mismatch */
  502. if (EXTRACT_32BITS(&np->length) != length) {
  503. ND_PRINT((ndo, " [len: %u != %u]", EXTRACT_32BITS(&np->length),
  504. length));
  505. }
  506. if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length))
  507. ND_PRINT((ndo, "[extra]"));
  508. return;
  509. trunc:
  510. ND_PRINT((ndo, "[|lwres]"));
  511. }