tcpdump  4.99.1
About: tcpdump is a tool for network monitoring and data acquisition.
  Fossies Dox: tcpdump-4.99.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

print-lwres.c
Go to the documentation of this file.
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 
30 /* \summary: BIND9 Lightweight Resolver protocol printer */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #include "netdissect-stdinc.h"
37 
38 #define ND_LONGJMP_FROM_TCHECK
39 #include "netdissect.h"
40 #include "addrtoname.h"
41 #include "extract.h"
42 
43 #include "nameser.h"
44 
45 /* BIND9 lib/lwres/include/lwres */
46 /*
47  * Use nd_uint16_t for lwres_uint16_t
48  * Use nd_uint32_t for lwres_uint32_t
49 */
50 
61 };
62 
63 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
64 
65 #define LWRES_LWPACKETVERSION_0 0
66 
67 #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
68 #define LWRES_FLAG_SECUREDATA 0x00000002U
69 
70 /*
71  * no-op
72  */
73 #define LWRES_OPCODE_NOOP 0x00000000U
74 
75 typedef struct {
76  /* public */
78  /* data follows */
80 
81 typedef struct {
82  /* public */
84  /* data follows */
86 
87 /*
88  * get addresses by name
89  */
90 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
91 
92 typedef struct lwres_addr lwres_addr_t;
93 
94 struct lwres_addr {
97  /* address follows */
98 };
99 #define LWRES_ADDR_LEN 6
100 
101 typedef struct {
102  /* public */
106  /* name follows */
108 #define LWRES_GABNREQUEST_LEN 10
109 
110 typedef struct {
111  /* public */
116  /* aliases follows */
117  /* addrs follows */
118  /* realname follows */
120 #define LWRES_GABNRESPONSE_LEN 10
121 
122 /*
123  * get name by address
124  */
125 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
126 typedef struct {
127  /* public */
129  /* addr follows */
131 #define LWRES_GNBAREQUEST_LEN 4
132 
133 typedef struct {
134  /* public */
138  /* aliases follows */
139  /* realname follows */
141 #define LWRES_GNBARESPONSE_LEN 8
142 
143 /*
144  * get rdata by name
145  */
146 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
147 
148 typedef struct {
149  /* public */
154  /* name follows */
156 #define LWRES_GRBNREQUEST_LEN 10
157 
158 typedef struct {
159  /* public */
166  /* realname here (len + name) */
167  /* rdata here (len + name) */
168  /* signatures here (len + name) */
170 #define LWRES_GRBNRESPONSE_LEN 16
171 
172 #define LWRDATA_VALIDATED 0x00000001
173 
174 #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
175 #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
176 
177 #define LWRES_MAX_ALIASES 16 /* max # of aliases */
178 #define LWRES_MAX_ADDRS 64 /* max # of addrs */
179 
180 static const struct tok opcode[] = {
181  { LWRES_OPCODE_NOOP, "noop", },
182  { LWRES_OPCODE_GETADDRSBYNAME, "getaddrsbyname", },
183  { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr", },
184  { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname", },
185  { 0, NULL, },
186 };
187 
188 /* print-domain.c */
189 extern const struct tok ns_type2str[];
190 extern const struct tok ns_class2str[];
191 
192 static unsigned
194  size_t l, const u_char *p0)
195 {
196  ND_PRINT(" ");
197  (void)nd_printn(ndo, p0, l, NULL);
198  p0 += l;
199  if (GET_U_1(p0))
200  ND_PRINT(" (not NUL-terminated!)");
201  return l + 1;
202 }
203 
204 static unsigned
206  const u_char *p)
207 {
208  uint16_t l;
209  int advance;
210 
211  l = GET_BE_U_2(p);
212  advance = lwres_printname(ndo, l, p + 2);
213  return 2 + advance;
214 }
215 
216 static unsigned
218  const u_char *p0)
219 {
220  const u_char *p;
221  uint16_t l;
222  int i;
223 
224  p = p0;
225  l = GET_BE_U_2(p);
226  p += 2;
227  for (i = 0; i < l; i++) {
228  ND_PRINT("%02x", GET_U_1(p));
229  p++;
230  }
231  return 2 + l;
232 }
233 
234 static int
236  const u_char *p0)
237 {
238  const u_char *p;
239  const lwres_addr_t *ap;
240  uint16_t l;
241  int i;
242 
243  p = p0;
244  ap = (const lwres_addr_t *)p;
245  l = GET_BE_U_2(ap->length);
246  p += LWRES_ADDR_LEN;
247  ND_TCHECK_LEN(p, l);
248 
249  switch (GET_BE_U_4(ap->family)) {
250  case 1: /* IPv4 */
251  if (l < 4)
252  return -1;
253  ND_PRINT(" %s", GET_IPADDR_STRING(p));
254  p += sizeof(nd_ipv4);
255  break;
256  case 2: /* IPv6 */
257  if (l < 16)
258  return -1;
259  ND_PRINT(" %s", GET_IP6ADDR_STRING(p));
260  p += sizeof(nd_ipv6);
261  break;
262  default:
263  ND_PRINT(" %u/", GET_BE_U_4(ap->family));
264  for (i = 0; i < l; i++) {
265  ND_PRINT("%02x", GET_U_1(p));
266  p++;
267  }
268  }
269 
270  return ND_BYTES_BETWEEN(p, p0);
271 }
272 
273 void
275  const u_char *bp, u_int length)
276 {
277  const u_char *p;
278  const struct lwres_lwpacket *np;
279  uint32_t v;
280  const u_char *s;
281  int response;
282  int advance;
283  int unsupported = 0;
284 
285  ndo->ndo_protocol = "lwres";
286  np = (const struct lwres_lwpacket *)bp;
287  ND_TCHECK_2(np->authlength);
288 
289  ND_PRINT(" lwres");
290  v = GET_BE_U_2(np->version);
291  if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
292  ND_PRINT(" v%u", v);
293  if (v != LWRES_LWPACKETVERSION_0) {
294  s = bp + GET_BE_U_4(np->length);
295  goto tail;
296  }
297 
299 
300  /* opcode and pktflags */
301  v = GET_BE_U_4(np->opcode);
302  ND_PRINT(" %s%s", tok2str(opcode, "#0x%x", v), response ? "" : "?");
303 
304  /* pktflags */
305  v = GET_BE_U_2(np->pktflags);
307  ND_PRINT("[0x%x]", v);
308 
309  if (ndo->ndo_vflag > 1) {
310  ND_PRINT(" ("); /*)*/
311  ND_PRINT("serial:0x%x", GET_BE_U_4(np->serial));
312  ND_PRINT(" result:0x%x", GET_BE_U_4(np->result));
313  ND_PRINT(" recvlen:%u", GET_BE_U_4(np->recvlength));
314  /* BIND910: not used */
315  if (ndo->ndo_vflag > 2) {
316  ND_PRINT(" authtype:0x%x", GET_BE_U_2(np->authtype));
317  ND_PRINT(" authlen:%u", GET_BE_U_2(np->authlength));
318  }
319  /*(*/
320  ND_PRINT(")");
321  }
322 
323  /* per-opcode content */
324  if (!response) {
325  /*
326  * queries
327  */
328  const lwres_gabnrequest_t *gabn;
329  const lwres_gnbarequest_t *gnba;
330  const lwres_grbnrequest_t *grbn;
331  uint32_t l;
332 
333  gabn = NULL;
334  gnba = NULL;
335  grbn = NULL;
336 
337  p = (const u_char *)(np + 1);
338  switch (GET_BE_U_4(np->opcode)) {
339  case LWRES_OPCODE_NOOP:
340  s = p;
341  break;
343  gabn = (const lwres_gabnrequest_t *)p;
344  ND_TCHECK_2(gabn->namelen);
345 
346  /* BIND910: not used */
347  if (ndo->ndo_vflag > 2) {
348  ND_PRINT(" flags:0x%x",
349  GET_BE_U_4(gabn->flags));
350  }
351 
352  v = GET_BE_U_4(gabn->addrtypes);
353  switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
354  case LWRES_ADDRTYPE_V4:
355  ND_PRINT(" IPv4");
356  break;
357  case LWRES_ADDRTYPE_V6:
358  ND_PRINT(" IPv6");
359  break;
361  ND_PRINT(" IPv4/6");
362  break;
363  }
365  ND_PRINT("[0x%x]", v);
366 
367  s = p + LWRES_GABNREQUEST_LEN;
368  l = GET_BE_U_2(gabn->namelen);
369  advance = lwres_printname(ndo, l, s);
370  s += advance;
371  break;
373  gnba = (const lwres_gnbarequest_t *)p;
374  ND_TCHECK_4(gnba->flags);
375 
376  /* BIND910: not used */
377  if (ndo->ndo_vflag > 2) {
378  ND_PRINT(" flags:0x%x",
379  GET_BE_U_4(gnba->flags));
380  }
381 
382  s = p + LWRES_GNBAREQUEST_LEN;
383  advance = lwres_printaddr(ndo, s);
384  if (advance < 0)
385  goto invalid;
386  s += advance;
387  break;
389  /* XXX no trace, not tested */
390  grbn = (const lwres_grbnrequest_t *)p;
391  ND_TCHECK_2(grbn->namelen);
392 
393  /* BIND910: not used */
394  if (ndo->ndo_vflag > 2) {
395  ND_PRINT(" flags:0x%x",
396  GET_BE_U_4(grbn->flags));
397  }
398 
399  ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
400  GET_BE_U_2(grbn->rdtype)));
401  if (GET_BE_U_2(grbn->rdclass) != C_IN) {
402  ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
403  GET_BE_U_2(grbn->rdclass)));
404  }
405 
406  s = p + LWRES_GRBNREQUEST_LEN;
407  l = GET_BE_U_2(grbn->namelen);
408  advance = lwres_printname(ndo, l, s);
409  s += advance;
410  break;
411  default:
412  s = p;
413  unsupported++;
414  break;
415  }
416  } else {
417  /*
418  * responses
419  */
420  const lwres_gabnresponse_t *gabn;
421  const lwres_gnbaresponse_t *gnba;
422  const lwres_grbnresponse_t *grbn;
423  uint32_t l, na;
424  uint32_t i;
425 
426  gabn = NULL;
427  gnba = NULL;
428  grbn = NULL;
429 
430  p = (const u_char *)(np + 1);
431  switch (GET_BE_U_4(np->opcode)) {
432  case LWRES_OPCODE_NOOP:
433  s = p;
434  break;
436  gabn = (const lwres_gabnresponse_t *)p;
437  ND_TCHECK_2(gabn->realnamelen);
438 
439  /* BIND910: not used */
440  if (ndo->ndo_vflag > 2) {
441  ND_PRINT(" flags:0x%x",
442  GET_BE_U_4(gabn->flags));
443  }
444 
445  ND_PRINT(" %u/%u", GET_BE_U_2(gabn->naliases),
446  GET_BE_U_2(gabn->naddrs));
447 
448  s = p + LWRES_GABNRESPONSE_LEN;
449  l = GET_BE_U_2(gabn->realnamelen);
450  advance = lwres_printname(ndo, l, s);
451  s += advance;
452 
453  /* aliases */
454  na = GET_BE_U_2(gabn->naliases);
455  for (i = 0; i < na; i++) {
456  advance = lwres_printnamelen(ndo, s);
457  s += advance;
458  }
459 
460  /* addrs */
461  na = GET_BE_U_2(gabn->naddrs);
462  for (i = 0; i < na; i++) {
463  advance = lwres_printaddr(ndo, s);
464  if (advance < 0)
465  goto invalid;
466  s += advance;
467  }
468  break;
470  gnba = (const lwres_gnbaresponse_t *)p;
471  ND_TCHECK_2(gnba->realnamelen);
472 
473  /* BIND910: not used */
474  if (ndo->ndo_vflag > 2) {
475  ND_PRINT(" flags:0x%x",
476  GET_BE_U_4(gnba->flags));
477  }
478 
479  ND_PRINT(" %u", GET_BE_U_2(gnba->naliases));
480 
481  s = p + LWRES_GNBARESPONSE_LEN;
482  l = GET_BE_U_2(gnba->realnamelen);
483  advance = lwres_printname(ndo, l, s);
484  s += advance;
485 
486  /* aliases */
487  na = GET_BE_U_2(gnba->naliases);
488  for (i = 0; i < na; i++) {
489  advance = lwres_printnamelen(ndo, s);
490  s += advance;
491  }
492  break;
494  /* XXX no trace, not tested */
495  grbn = (const lwres_grbnresponse_t *)p;
496  ND_TCHECK_2(grbn->nsigs);
497 
498  /* BIND910: not used */
499  if (ndo->ndo_vflag > 2) {
500  ND_PRINT(" flags:0x%x",
501  GET_BE_U_4(grbn->flags));
502  }
503 
504  ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
505  GET_BE_U_2(grbn->rdtype)));
506  if (GET_BE_U_2(grbn->rdclass) != C_IN) {
507  ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
508  GET_BE_U_2(grbn->rdclass)));
509  }
510  ND_PRINT(" TTL ");
512  GET_BE_U_4(grbn->ttl));
513  ND_PRINT(" %u/%u", GET_BE_U_2(grbn->nrdatas),
514  GET_BE_U_2(grbn->nsigs));
515 
516  s = p + LWRES_GRBNRESPONSE_LEN;
517  advance = lwres_printnamelen(ndo, s);
518  s += advance;
519 
520  /* rdatas */
521  na = GET_BE_U_2(grbn->nrdatas);
522  for (i = 0; i < na; i++) {
523  /* XXX should decode resource data */
524  advance = lwres_printbinlen(ndo, s);
525  s += advance;
526  }
527 
528  /* sigs */
529  na = GET_BE_U_2(grbn->nsigs);
530  for (i = 0; i < na; i++) {
531  /* XXX how should we print it? */
532  advance = lwres_printbinlen(ndo, s);
533  s += advance;
534  }
535  break;
536  default:
537  s = p;
538  unsupported++;
539  break;
540  }
541  }
542 
543  tail:
544  /* length mismatch */
545  if (GET_BE_U_4(np->length) != length) {
546  ND_PRINT(" [len: %u != %u]", GET_BE_U_4(np->length),
547  length);
548  }
549  if (!unsupported && s < bp + GET_BE_U_4(np->length))
550  ND_PRINT("[extra]");
551  return;
552 
553  invalid:
554  nd_print_invalid(ndo);
555 }
#define GET_IPADDR_STRING(p)
Definition: addrtoname.h:120
#define GET_IP6ADDR_STRING(p)
Definition: addrtoname.h:121
#define GET_BE_U_4(p)
Definition: extract.h:877
#define GET_BE_U_2(p)
Definition: extract.h:875
#define ND_TCHECK_2(p)
Definition: extract.h:555
#define GET_U_1(p)
Definition: extract.h:872
#define ND_TCHECK_4(p)
Definition: extract.h:561
#define C_IN
Definition: nameser.h:193
unsigned char nd_uint16_t[2]
Definition: netdissect.h:47
void unsigned_relts_print(netdissect_options *, uint32_t)
Definition: util-print.c:350
#define ND_BYTES_BETWEEN(p1, p2)
Definition: netdissect.h:377
#define ND_TCHECK_LEN(p, l)
Definition: netdissect.h:368
const char * tok2str(const struct tok *, const char *, u_int)
Definition: util-print.c:485
void nd_print_invalid(netdissect_options *)
Definition: util-print.c:429
unsigned char nd_ipv4[4]
Definition: netdissect.h:92
#define ND_PRINT(...)
Definition: netdissect.h:385
int nd_printn(netdissect_options *, const u_char *, u_int, const u_char *)
Definition: util-print.c:160
unsigned char nd_uint32_t[4]
Definition: netdissect.h:49
unsigned char nd_ipv6[16]
Definition: netdissect.h:97
#define LWRES_GNBARESPONSE_LEN
Definition: print-lwres.c:141
#define LWRES_OPCODE_NOOP
Definition: print-lwres.c:73
static const struct tok opcode[]
Definition: print-lwres.c:180
static unsigned lwres_printbinlen(netdissect_options *ndo, const u_char *p0)
Definition: print-lwres.c:217
#define LWRES_GNBAREQUEST_LEN
Definition: print-lwres.c:131
#define LWRES_ADDRTYPE_V4
Definition: print-lwres.c:174
#define LWRES_GABNRESPONSE_LEN
Definition: print-lwres.c:120
const struct tok ns_class2str[]
Definition: print-domain.c:548
static int lwres_printaddr(netdissect_options *ndo, const u_char *p0)
Definition: print-lwres.c:235
#define LWRES_OPCODE_GETADDRSBYNAME
Definition: print-lwres.c:90
#define LWRES_GRBNREQUEST_LEN
Definition: print-lwres.c:156
void lwres_print(netdissect_options *ndo, const u_char *bp, u_int length)
Definition: print-lwres.c:274
#define LWRES_OPCODE_GETNAMEBYADDR
Definition: print-lwres.c:125
#define LWRES_ADDRTYPE_V6
Definition: print-lwres.c:175
static unsigned lwres_printnamelen(netdissect_options *ndo, const u_char *p)
Definition: print-lwres.c:205
const struct tok ns_type2str[]
Definition: print-domain.c:480
#define LWRES_ADDR_LEN
Definition: print-lwres.c:99
#define LWRES_GABNREQUEST_LEN
Definition: print-lwres.c:108
#define LWRES_LWPACKETVERSION_0
Definition: print-lwres.c:65
#define LWRES_LWPACKETFLAG_RESPONSE
Definition: print-lwres.c:63
#define LWRES_OPCODE_GETRDATABYNAME
Definition: print-lwres.c:146
static unsigned lwres_printname(netdissect_options *ndo, size_t l, const u_char *p0)
Definition: print-lwres.c:193
#define LWRES_GRBNRESPONSE_LEN
Definition: print-lwres.c:170
nd_uint16_t length
Definition: print-lwres.c:96
nd_uint32_t family
Definition: print-lwres.c:95
nd_uint32_t flags
Definition: print-lwres.c:103
nd_uint32_t addrtypes
Definition: print-lwres.c:104
nd_uint16_t namelen
Definition: print-lwres.c:105
nd_uint16_t naddrs
Definition: print-lwres.c:114
nd_uint16_t naliases
Definition: print-lwres.c:113
nd_uint16_t realnamelen
Definition: print-lwres.c:115
nd_uint32_t flags
Definition: print-lwres.c:128
nd_uint16_t naliases
Definition: print-lwres.c:136
nd_uint16_t realnamelen
Definition: print-lwres.c:137
nd_uint32_t flags
Definition: print-lwres.c:150
nd_uint16_t rdtype
Definition: print-lwres.c:152
nd_uint16_t namelen
Definition: print-lwres.c:153
nd_uint16_t rdclass
Definition: print-lwres.c:151
nd_uint16_t nrdatas
Definition: print-lwres.c:164
nd_uint16_t rdclass
Definition: print-lwres.c:161
nd_uint16_t rdtype
Definition: print-lwres.c:162
nd_uint16_t pktflags
Definition: print-lwres.c:54
nd_uint16_t authlength
Definition: print-lwres.c:60
nd_uint32_t serial
Definition: print-lwres.c:55
nd_uint32_t result
Definition: print-lwres.c:57
nd_uint32_t opcode
Definition: print-lwres.c:56
nd_uint16_t authtype
Definition: print-lwres.c:59
nd_uint32_t length
Definition: print-lwres.c:52
nd_uint16_t version
Definition: print-lwres.c:53
nd_uint32_t recvlength
Definition: print-lwres.c:58
nd_uint16_t datalength
Definition: print-lwres.c:77
nd_uint16_t datalength
Definition: print-lwres.c:83
const char * ndo_protocol
Definition: netdissect.h:218