]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-bootp.c
Merge llvm-project release/16.x llvmorg-16.0.4-0-gae42196bc493
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-bootp.c
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 /* \summary: BOOTP and IPv4 DHCP printer */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "netdissect-stdinc.h"
29
30 #include <string.h>
31
32 #include "netdissect.h"
33 #include "addrtoname.h"
34 #include "extract.h"
35
36
37 /*
38  * Bootstrap Protocol (BOOTP).  RFC951 and RFC1048.
39  *
40  * This file specifies the "implementation-independent" BOOTP protocol
41  * information which is common to both client and server.
42  *
43  * Copyright 1988 by Carnegie Mellon.
44  *
45  * Permission to use, copy, modify, and distribute this program for any
46  * purpose and without fee is hereby granted, provided that this copyright
47  * and permission notice appear on all copies and supporting documentation,
48  * the name of Carnegie Mellon not be used in advertising or publicity
49  * pertaining to distribution of the program without specific prior
50  * permission, and notice be given in supporting documentation that copying
51  * and distribution is by permission of Carnegie Mellon and Stanford
52  * University.  Carnegie Mellon makes no representations about the
53  * suitability of this software for any purpose.  It is provided "as is"
54  * without express or implied warranty.
55  */
56
57 struct bootp {
58         nd_uint8_t      bp_op;          /* packet opcode type */
59         nd_uint8_t      bp_htype;       /* hardware addr type */
60         nd_uint8_t      bp_hlen;        /* hardware addr length */
61         nd_uint8_t      bp_hops;        /* gateway hops */
62         nd_uint32_t     bp_xid;         /* transaction ID */
63         nd_uint16_t     bp_secs;        /* seconds since boot began */
64         nd_uint16_t     bp_flags;       /* flags - see bootp_flag_values[]
65                                            in print-bootp.c */
66         nd_ipv4         bp_ciaddr;      /* client IP address */
67         nd_ipv4         bp_yiaddr;      /* 'your' IP address */
68         nd_ipv4         bp_siaddr;      /* server IP address */
69         nd_ipv4         bp_giaddr;      /* gateway IP address */
70         nd_byte         bp_chaddr[16];  /* client hardware address */
71         nd_byte         bp_sname[64];   /* server host name */
72         nd_byte         bp_file[128];   /* boot file name */
73         nd_byte         bp_vend[64];    /* vendor-specific area */
74 };
75
76 #define BOOTPREPLY      2
77 #define BOOTPREQUEST    1
78
79 /*
80  * Vendor magic cookie (v_magic) for CMU
81  */
82 #define VM_CMU          "CMU"
83
84 /*
85  * Vendor magic cookie (v_magic) for RFC1048
86  */
87 #define VM_RFC1048      { 99, 130, 83, 99 }
88
89 /*
90  * RFC1048 tag values used to specify what information is being supplied in
91  * the vendor field of the packet.
92  */
93
94 #define TAG_PAD                 ((uint8_t)   0)
95 #define TAG_SUBNET_MASK         ((uint8_t)   1)
96 #define TAG_TIME_OFFSET         ((uint8_t)   2)
97 #define TAG_GATEWAY             ((uint8_t)   3)
98 #define TAG_TIME_SERVER         ((uint8_t)   4)
99 #define TAG_NAME_SERVER         ((uint8_t)   5)
100 #define TAG_DOMAIN_SERVER       ((uint8_t)   6)
101 #define TAG_LOG_SERVER          ((uint8_t)   7)
102 #define TAG_COOKIE_SERVER       ((uint8_t)   8)
103 #define TAG_LPR_SERVER          ((uint8_t)   9)
104 #define TAG_IMPRESS_SERVER      ((uint8_t)  10)
105 #define TAG_RLP_SERVER          ((uint8_t)  11)
106 #define TAG_HOSTNAME            ((uint8_t)  12)
107 #define TAG_BOOTSIZE            ((uint8_t)  13)
108 #define TAG_END                 ((uint8_t) 255)
109 /* RFC1497 tags */
110 #define TAG_DUMPPATH            ((uint8_t)  14)
111 #define TAG_DOMAINNAME          ((uint8_t)  15)
112 #define TAG_SWAP_SERVER         ((uint8_t)  16)
113 #define TAG_ROOTPATH            ((uint8_t)  17)
114 #define TAG_EXTPATH             ((uint8_t)  18)
115 /* RFC2132 */
116 #define TAG_IP_FORWARD          ((uint8_t)  19)
117 #define TAG_NL_SRCRT            ((uint8_t)  20)
118 #define TAG_PFILTERS            ((uint8_t)  21)
119 #define TAG_REASS_SIZE          ((uint8_t)  22)
120 #define TAG_DEF_TTL             ((uint8_t)  23)
121 #define TAG_MTU_TIMEOUT         ((uint8_t)  24)
122 #define TAG_MTU_TABLE           ((uint8_t)  25)
123 #define TAG_INT_MTU             ((uint8_t)  26)
124 #define TAG_LOCAL_SUBNETS       ((uint8_t)  27)
125 #define TAG_BROAD_ADDR          ((uint8_t)  28)
126 #define TAG_DO_MASK_DISC        ((uint8_t)  29)
127 #define TAG_SUPPLY_MASK         ((uint8_t)  30)
128 #define TAG_DO_RDISC            ((uint8_t)  31)
129 #define TAG_RTR_SOL_ADDR        ((uint8_t)  32)
130 #define TAG_STATIC_ROUTE        ((uint8_t)  33)
131 #define TAG_USE_TRAILERS        ((uint8_t)  34)
132 #define TAG_ARP_TIMEOUT         ((uint8_t)  35)
133 #define TAG_ETH_ENCAP           ((uint8_t)  36)
134 #define TAG_TCP_TTL             ((uint8_t)  37)
135 #define TAG_TCP_KEEPALIVE       ((uint8_t)  38)
136 #define TAG_KEEPALIVE_GO        ((uint8_t)  39)
137 #define TAG_NIS_DOMAIN          ((uint8_t)  40)
138 #define TAG_NIS_SERVERS         ((uint8_t)  41)
139 #define TAG_NTP_SERVERS         ((uint8_t)  42)
140 #define TAG_VENDOR_OPTS         ((uint8_t)  43)
141 #define TAG_NETBIOS_NS          ((uint8_t)  44)
142 #define TAG_NETBIOS_DDS         ((uint8_t)  45)
143 #define TAG_NETBIOS_NODE        ((uint8_t)  46)
144 #define TAG_NETBIOS_SCOPE       ((uint8_t)  47)
145 #define TAG_XWIN_FS             ((uint8_t)  48)
146 #define TAG_XWIN_DM             ((uint8_t)  49)
147 #define TAG_NIS_P_DOMAIN        ((uint8_t)  64)
148 #define TAG_NIS_P_SERVERS       ((uint8_t)  65)
149 #define TAG_MOBILE_HOME         ((uint8_t)  68)
150 #define TAG_SMPT_SERVER         ((uint8_t)  69)
151 #define TAG_POP3_SERVER         ((uint8_t)  70)
152 #define TAG_NNTP_SERVER         ((uint8_t)  71)
153 #define TAG_WWW_SERVER          ((uint8_t)  72)
154 #define TAG_FINGER_SERVER       ((uint8_t)  73)
155 #define TAG_IRC_SERVER          ((uint8_t)  74)
156 #define TAG_STREETTALK_SRVR     ((uint8_t)  75)
157 #define TAG_STREETTALK_STDA     ((uint8_t)  76)
158 /* DHCP options */
159 #define TAG_REQUESTED_IP        ((uint8_t)  50)
160 #define TAG_IP_LEASE            ((uint8_t)  51)
161 #define TAG_OPT_OVERLOAD        ((uint8_t)  52)
162 #define TAG_TFTP_SERVER         ((uint8_t)  66)
163 #define TAG_BOOTFILENAME        ((uint8_t)  67)
164 #define TAG_DHCP_MESSAGE        ((uint8_t)  53)
165 #define TAG_SERVER_ID           ((uint8_t)  54)
166 #define TAG_PARM_REQUEST        ((uint8_t)  55)
167 #define TAG_MESSAGE             ((uint8_t)  56)
168 #define TAG_MAX_MSG_SIZE        ((uint8_t)  57)
169 #define TAG_RENEWAL_TIME        ((uint8_t)  58)
170 #define TAG_REBIND_TIME         ((uint8_t)  59)
171 #define TAG_VENDOR_CLASS        ((uint8_t)  60)
172 #define TAG_CLIENT_ID           ((uint8_t)  61)
173 /* RFC 2241 */
174 #define TAG_NDS_SERVERS         ((uint8_t)  85)
175 #define TAG_NDS_TREE_NAME       ((uint8_t)  86)
176 #define TAG_NDS_CONTEXT         ((uint8_t)  87)
177 /* RFC 2242 */
178 #define TAG_NDS_IPDOMAIN        ((uint8_t)  62)
179 #define TAG_NDS_IPINFO          ((uint8_t)  63)
180 /* RFC 2485 */
181 #define TAG_OPEN_GROUP_UAP      ((uint8_t)  98)
182 /* RFC 2563 */
183 #define TAG_DISABLE_AUTOCONF    ((uint8_t) 116)
184 /* RFC 2610 */
185 #define TAG_SLP_DA              ((uint8_t)  78)
186 #define TAG_SLP_SCOPE           ((uint8_t)  79)
187 /* RFC 2937 */
188 #define TAG_NS_SEARCH           ((uint8_t) 117)
189 /* RFC 3004 - The User Class Option for DHCP */
190 #define TAG_USER_CLASS          ((uint8_t)  77)
191 /* RFC 3011 */
192 #define TAG_IP4_SUBNET_SELECT   ((uint8_t) 118)
193 /* RFC 3442 */
194 #define TAG_CLASSLESS_STATIC_RT ((uint8_t) 121)
195 #define TAG_CLASSLESS_STA_RT_MS ((uint8_t) 249)
196 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
197 #define TAG_TFTP_SERVER_ADDRESS ((uint8_t) 150)
198 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml */
199 #define TAG_SLP_NAMING_AUTH     ((uint8_t)  80)
200 #define TAG_CLIENT_FQDN         ((uint8_t)  81)
201 #define TAG_AGENT_CIRCUIT       ((uint8_t)  82)
202 #define TAG_AGENT_REMOTE        ((uint8_t)  83)
203 #define TAG_TZ_STRING           ((uint8_t)  88)
204 #define TAG_FQDN_OPTION         ((uint8_t)  89)
205 #define TAG_AUTH                ((uint8_t)  90)
206 #define TAG_CLIENT_LAST_TRANSACTION_TIME        ((uint8_t)  91)
207 #define TAG_ASSOCIATED_IP                       ((uint8_t)  92)
208 #define TAG_CLIENT_ARCH         ((uint8_t)  93)
209 #define TAG_CLIENT_NDI          ((uint8_t)  94)
210 #define TAG_CLIENT_GUID         ((uint8_t)  97)
211 #define TAG_LDAP_URL            ((uint8_t)  95)
212 /* RFC 4833, TZ codes */
213 #define TAG_TZ_PCODE            ((uint8_t) 100)
214 #define TAG_TZ_TCODE            ((uint8_t) 101)
215 #define TAG_NETINFO_PARENT      ((uint8_t) 112)
216 #define TAG_NETINFO_PARENT_TAG  ((uint8_t) 113)
217 #define TAG_URL                 ((uint8_t) 114)
218 #define TAG_MUDURL              ((uint8_t) 161)
219
220 /* DHCP Message types (values for TAG_DHCP_MESSAGE option) */
221 #define DHCPDISCOVER    1
222 #define DHCPOFFER       2
223 #define DHCPREQUEST     3
224 #define DHCPDECLINE     4
225 #define DHCPACK         5
226 #define DHCPNAK         6
227 #define DHCPRELEASE     7
228 #define DHCPINFORM      8
229 /* Defined in RFC4388 */
230 #define DHCPLEASEQUERY       10
231 #define DHCPLEASEUNASSIGNED  11
232 #define DHCPLEASEUNKNOWN     12
233 #define DHCPLEASEACTIVE      13
234
235
236 /*
237  * "vendor" data permitted for CMU bootp clients.
238  */
239
240 struct cmu_vend {
241         nd_byte         v_magic[4];     /* magic number */
242         nd_uint32_t     v_flags;        /* flags/opcodes, etc. */
243         nd_ipv4         v_smask;        /* Subnet mask */
244         nd_ipv4         v_dgate;        /* Default gateway */
245         nd_ipv4         v_dns1, v_dns2; /* Domain name servers */
246         nd_ipv4         v_ins1, v_ins2; /* IEN-116 name servers */
247         nd_ipv4         v_ts1, v_ts2;   /* Time servers */
248         nd_byte         v_unused[24];   /* currently unused */
249 };
250
251
252 /* v_flags values */
253 #define VF_SMASK        1       /* Subnet mask field contains valid data */
254
255 /* RFC 4702 DHCP Client FQDN Option */
256
257 #define CLIENT_FQDN_FLAGS_S     0x01
258 #define CLIENT_FQDN_FLAGS_O     0x02
259 #define CLIENT_FQDN_FLAGS_E     0x04
260 #define CLIENT_FQDN_FLAGS_N     0x08
261 /* end of original bootp.h */
262
263 static void rfc1048_print(netdissect_options *, const u_char *);
264 static void cmu_print(netdissect_options *, const u_char *);
265 static char *client_fqdn_flags(u_int flags);
266
267 static const struct tok bootp_flag_values[] = {
268         { 0x8000,       "Broadcast" },
269         { 0, NULL}
270 };
271
272 static const struct tok bootp_op_values[] = {
273         { BOOTPREQUEST, "Request" },
274         { BOOTPREPLY,   "Reply" },
275         { 0, NULL}
276 };
277
278 /*
279  * Print bootp requests
280  */
281 void
282 bootp_print(netdissect_options *ndo,
283             const u_char *cp, u_int length)
284 {
285         const struct bootp *bp;
286         static const u_char vm_cmu[4] = VM_CMU;
287         static const u_char vm_rfc1048[4] = VM_RFC1048;
288         uint8_t bp_op, bp_htype, bp_hlen;
289
290         ndo->ndo_protocol = "bootp";
291         bp = (const struct bootp *)cp;
292         bp_op = GET_U_1(bp->bp_op);
293         ND_PRINT("BOOTP/DHCP, %s",
294                   tok2str(bootp_op_values, "unknown (0x%02x)", bp_op));
295
296         bp_htype = GET_U_1(bp->bp_htype);
297         bp_hlen = GET_U_1(bp->bp_hlen);
298         if (bp_htype == 1 && bp_hlen == MAC_ADDR_LEN && bp_op == BOOTPREQUEST) {
299                 ND_PRINT(" from %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
300         }
301
302         ND_PRINT(", length %u", length);
303
304         if (!ndo->ndo_vflag)
305                 return;
306
307         ND_TCHECK_2(bp->bp_secs);
308
309         /* The usual hardware address type is 1 (10Mb Ethernet) */
310         if (bp_htype != 1)
311                 ND_PRINT(", htype %u", bp_htype);
312
313         /* The usual length for 10Mb Ethernet address is 6 bytes */
314         if (bp_htype != 1 || bp_hlen != MAC_ADDR_LEN)
315                 ND_PRINT(", hlen %u", bp_hlen);
316
317         /* Only print interesting fields */
318         if (GET_U_1(bp->bp_hops))
319                 ND_PRINT(", hops %u", GET_U_1(bp->bp_hops));
320         if (GET_BE_U_4(bp->bp_xid))
321                 ND_PRINT(", xid 0x%x", GET_BE_U_4(bp->bp_xid));
322         if (GET_BE_U_2(bp->bp_secs))
323                 ND_PRINT(", secs %u", GET_BE_U_2(bp->bp_secs));
324
325         ND_PRINT(", Flags [%s]",
326                   bittok2str(bootp_flag_values, "none", GET_BE_U_2(bp->bp_flags)));
327         if (ndo->ndo_vflag > 1)
328                 ND_PRINT(" (0x%04x)", GET_BE_U_2(bp->bp_flags));
329
330         /* Client's ip address */
331         if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_ciaddr))
332                 ND_PRINT("\n\t  Client-IP %s", GET_IPADDR_STRING(bp->bp_ciaddr));
333
334         /* 'your' ip address (bootp client) */
335         if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_yiaddr))
336                 ND_PRINT("\n\t  Your-IP %s", GET_IPADDR_STRING(bp->bp_yiaddr));
337
338         /* Server's ip address */
339         if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_siaddr))
340                 ND_PRINT("\n\t  Server-IP %s", GET_IPADDR_STRING(bp->bp_siaddr));
341
342         /* Gateway's ip address */
343         if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_giaddr))
344                 ND_PRINT("\n\t  Gateway-IP %s", GET_IPADDR_STRING(bp->bp_giaddr));
345
346         /* Client's Ethernet address */
347         if (bp_htype == 1 && bp_hlen == MAC_ADDR_LEN) {
348                 ND_PRINT("\n\t  Client-Ethernet-Address %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
349         }
350
351         if (GET_U_1(bp->bp_sname)) {    /* get first char only */
352                 ND_PRINT("\n\t  sname \"");
353                 if (nd_printztn(ndo, bp->bp_sname, (u_int)sizeof(bp->bp_sname),
354                                 ndo->ndo_snapend) == 0) {
355                         ND_PRINT("\"");
356                         nd_print_trunc(ndo);
357                         return;
358                 }
359                 ND_PRINT("\"");
360         }
361         if (GET_U_1(bp->bp_file)) {     /* get first char only */
362                 ND_PRINT("\n\t  file \"");
363                 if (nd_printztn(ndo, bp->bp_file, (u_int)sizeof(bp->bp_file),
364                                 ndo->ndo_snapend) == 0) {
365                         ND_PRINT("\"");
366                         nd_print_trunc(ndo);
367                         return;
368                 }
369                 ND_PRINT("\"");
370         }
371
372         /* Decode the vendor buffer */
373         ND_TCHECK_4(bp->bp_vend);
374         if (memcmp((const char *)bp->bp_vend, vm_rfc1048,
375                     sizeof(uint32_t)) == 0)
376                 rfc1048_print(ndo, bp->bp_vend);
377         else if (memcmp((const char *)bp->bp_vend, vm_cmu,
378                         sizeof(uint32_t)) == 0)
379                 cmu_print(ndo, bp->bp_vend);
380         else {
381                 uint32_t ul;
382
383                 ul = GET_BE_U_4(bp->bp_vend);
384                 if (ul != 0)
385                         ND_PRINT("\n\t  Vendor-#0x%x", ul);
386         }
387
388         return;
389 trunc:
390         nd_print_trunc(ndo);
391 }
392
393 /*
394  * The first character specifies the format to print:
395  *     i - ip address (32 bits)
396  *     p - ip address pairs (32 bits + 32 bits)
397  *     l - long (32 bits)
398  *     L - unsigned long (32 bits)
399  *     s - short (16 bits)
400  *     b - period-separated decimal bytes (variable length)
401  *     x - colon-separated hex bytes (variable length)
402  *     a - ASCII string (variable length)
403  *     B - on/off (8 bits)
404  *     $ - special (explicit code to handle)
405  */
406 static const struct tok tag2str[] = {
407 /* RFC1048 tags */
408         { TAG_PAD,              " PAD" },
409         { TAG_SUBNET_MASK,      "iSubnet-Mask" },       /* subnet mask (RFC950) */
410         { TAG_TIME_OFFSET,      "LTime-Zone" }, /* seconds from UTC */
411         { TAG_GATEWAY,          "iDefault-Gateway" },   /* default gateway */
412         { TAG_TIME_SERVER,      "iTime-Server" },       /* time servers (RFC868) */
413         { TAG_NAME_SERVER,      "iIEN-Name-Server" },   /* IEN name servers (IEN116) */
414         { TAG_DOMAIN_SERVER,    "iDomain-Name-Server" },        /* domain name (RFC1035) */
415         { TAG_LOG_SERVER,       "iLOG" },       /* MIT log servers */
416         { TAG_COOKIE_SERVER,    "iCS" },        /* cookie servers (RFC865) */
417         { TAG_LPR_SERVER,       "iLPR-Server" },        /* lpr server (RFC1179) */
418         { TAG_IMPRESS_SERVER,   "iIM" },        /* impress servers (Imagen) */
419         { TAG_RLP_SERVER,       "iRL" },        /* resource location (RFC887) */
420         { TAG_HOSTNAME,         "aHostname" },  /* ASCII hostname */
421         { TAG_BOOTSIZE,         "sBS" },        /* 512 byte blocks */
422         { TAG_END,              " END" },
423 /* RFC1497 tags */
424         { TAG_DUMPPATH,         "aDP" },
425         { TAG_DOMAINNAME,       "aDomain-Name" },
426         { TAG_SWAP_SERVER,      "iSS" },
427         { TAG_ROOTPATH,         "aRP" },
428         { TAG_EXTPATH,          "aEP" },
429 /* RFC2132 tags */
430         { TAG_IP_FORWARD,       "BIPF" },
431         { TAG_NL_SRCRT,         "BSRT" },
432         { TAG_PFILTERS,         "pPF" },
433         { TAG_REASS_SIZE,       "sRSZ" },
434         { TAG_DEF_TTL,          "bTTL" },
435         { TAG_MTU_TIMEOUT,      "lMTU-Timeout" },
436         { TAG_MTU_TABLE,        "sMTU-Table" },
437         { TAG_INT_MTU,          "sMTU" },
438         { TAG_LOCAL_SUBNETS,    "BLSN" },
439         { TAG_BROAD_ADDR,       "iBR" },
440         { TAG_DO_MASK_DISC,     "BMD" },
441         { TAG_SUPPLY_MASK,      "BMS" },
442         { TAG_DO_RDISC,         "BRouter-Discovery" },
443         { TAG_RTR_SOL_ADDR,     "iRSA" },
444         { TAG_STATIC_ROUTE,     "pStatic-Route" },
445         { TAG_USE_TRAILERS,     "BUT" },
446         { TAG_ARP_TIMEOUT,      "lAT" },
447         { TAG_ETH_ENCAP,        "BIE" },
448         { TAG_TCP_TTL,          "bTT" },
449         { TAG_TCP_KEEPALIVE,    "lKI" },
450         { TAG_KEEPALIVE_GO,     "BKG" },
451         { TAG_NIS_DOMAIN,       "aYD" },
452         { TAG_NIS_SERVERS,      "iYS" },
453         { TAG_NTP_SERVERS,      "iNTP" },
454         { TAG_VENDOR_OPTS,      "bVendor-Option" },
455         { TAG_NETBIOS_NS,       "iNetbios-Name-Server" },
456         { TAG_NETBIOS_DDS,      "iWDD" },
457         { TAG_NETBIOS_NODE,     "$Netbios-Node" },
458         { TAG_NETBIOS_SCOPE,    "aNetbios-Scope" },
459         { TAG_XWIN_FS,          "iXFS" },
460         { TAG_XWIN_DM,          "iXDM" },
461         { TAG_NIS_P_DOMAIN,     "sN+D" },
462         { TAG_NIS_P_SERVERS,    "iN+S" },
463         { TAG_MOBILE_HOME,      "iMH" },
464         { TAG_SMPT_SERVER,      "iSMTP" },
465         { TAG_POP3_SERVER,      "iPOP3" },
466         { TAG_NNTP_SERVER,      "iNNTP" },
467         { TAG_WWW_SERVER,       "iWWW" },
468         { TAG_FINGER_SERVER,    "iFG" },
469         { TAG_IRC_SERVER,       "iIRC" },
470         { TAG_STREETTALK_SRVR,  "iSTS" },
471         { TAG_STREETTALK_STDA,  "iSTDA" },
472         { TAG_REQUESTED_IP,     "iRequested-IP" },
473         { TAG_IP_LEASE,         "lLease-Time" },
474         { TAG_OPT_OVERLOAD,     "$OO" },
475         { TAG_TFTP_SERVER,      "aTFTP" },
476         { TAG_BOOTFILENAME,     "aBF" },
477         { TAG_DHCP_MESSAGE,     " DHCP-Message" },
478         { TAG_SERVER_ID,        "iServer-ID" },
479         { TAG_PARM_REQUEST,     "bParameter-Request" },
480         { TAG_MESSAGE,          "aMSG" },
481         { TAG_MAX_MSG_SIZE,     "sMSZ" },
482         { TAG_RENEWAL_TIME,     "lRN" },
483         { TAG_REBIND_TIME,      "lRB" },
484         { TAG_VENDOR_CLASS,     "aVendor-Class" },
485         { TAG_CLIENT_ID,        "$Client-ID" },
486 /* RFC 2485 */
487         { TAG_OPEN_GROUP_UAP,   "aUAP" },
488 /* RFC 2563 */
489         { TAG_DISABLE_AUTOCONF, "BNOAUTO" },
490 /* RFC 2610 */
491         { TAG_SLP_DA,           "bSLP-DA" },    /*"b" is a little wrong */
492         { TAG_SLP_SCOPE,        "bSLP-SCOPE" }, /*"b" is a little wrong */
493 /* RFC 2937 */
494         { TAG_NS_SEARCH,        "sNSSEARCH" },  /* XXX 's' */
495 /* RFC 3004 - The User Class Option for DHCP */
496         { TAG_USER_CLASS,       "$User-Class" },
497 /* RFC 3011 */
498         { TAG_IP4_SUBNET_SELECT, "iSUBNET" },
499 /* RFC 3442 */
500         { TAG_CLASSLESS_STATIC_RT, "$Classless-Static-Route" },
501         { TAG_CLASSLESS_STA_RT_MS, "$Classless-Static-Route-Microsoft" },
502 /* RFC 5859 - TFTP Server Address Option for DHCPv4 */
503         { TAG_TFTP_SERVER_ADDRESS, "iTFTP-Server-Address" },
504 /* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
505         { TAG_SLP_NAMING_AUTH,  "aSLP-NA" },
506         { TAG_CLIENT_FQDN,      "$FQDN" },
507         { TAG_AGENT_CIRCUIT,    "$Agent-Information" },
508         { TAG_AGENT_REMOTE,     "bARMT" },
509         { TAG_TZ_STRING,        "aTZSTR" },
510         { TAG_FQDN_OPTION,      "bFQDNS" },     /* XXX 'b' */
511         { TAG_AUTH,             "bAUTH" },      /* XXX 'b' */
512         { TAG_CLIENT_LAST_TRANSACTION_TIME, "LLast-Transaction-Time" },
513         { TAG_ASSOCIATED_IP,    "iAssociated-IP" },
514         { TAG_CLIENT_ARCH,      "sARCH" },
515         { TAG_CLIENT_NDI,       "bNDI" },       /* XXX 'b' */
516         { TAG_CLIENT_GUID,      "bGUID" },      /* XXX 'b' */
517         { TAG_LDAP_URL,         "aLDAP" },
518         { TAG_TZ_PCODE,         "aPOSIX-TZ" },
519         { TAG_TZ_TCODE,         "aTZ-Name" },
520         { TAG_NETINFO_PARENT,   "iNI" },
521         { TAG_NETINFO_PARENT_TAG, "aNITAG" },
522         { TAG_URL,              "aURL" },
523         { TAG_MUDURL,           "aMUD-URL" },
524         { 0, NULL }
525 };
526
527 /* DHCP "options overload" types */
528 static const struct tok oo2str[] = {
529         { 1,    "file" },
530         { 2,    "sname" },
531         { 3,    "file+sname" },
532         { 0, NULL }
533 };
534
535 /* NETBIOS over TCP/IP node type options */
536 static const struct tok nbo2str[] = {
537         { 0x1,  "b-node" },
538         { 0x2,  "p-node" },
539         { 0x4,  "m-node" },
540         { 0x8,  "h-node" },
541         { 0, NULL }
542 };
543
544 /* ARP Hardware types, for Client-ID option */
545 static const struct tok arp2str[] = {
546         { 0x1,  "ether" },
547         { 0x6,  "ieee802" },
548         { 0x7,  "arcnet" },
549         { 0xf,  "frelay" },
550         { 0x17, "strip" },
551         { 0x18, "ieee1394" },
552         { 0, NULL }
553 };
554
555 static const struct tok dhcp_msg_values[] = {
556         { DHCPDISCOVER,        "Discover" },
557         { DHCPOFFER,           "Offer" },
558         { DHCPREQUEST,         "Request" },
559         { DHCPDECLINE,         "Decline" },
560         { DHCPACK,             "ACK" },
561         { DHCPNAK,             "NACK" },
562         { DHCPRELEASE,         "Release" },
563         { DHCPINFORM,          "Inform" },
564         { DHCPLEASEQUERY,      "LeaseQuery" },
565         { DHCPLEASEUNASSIGNED, "LeaseUnassigned" },
566         { DHCPLEASEUNKNOWN,    "LeaseUnknown" },
567         { DHCPLEASEACTIVE,     "LeaseActive" },
568         { 0, NULL }
569 };
570
571 #define AGENT_SUBOPTION_CIRCUIT_ID      1       /* RFC 3046 */
572 #define AGENT_SUBOPTION_REMOTE_ID       2       /* RFC 3046 */
573 #define AGENT_SUBOPTION_SUBSCRIBER_ID   6       /* RFC 3993 */
574 static const struct tok agent_suboption_values[] = {
575         { AGENT_SUBOPTION_CIRCUIT_ID,    "Circuit-ID" },
576         { AGENT_SUBOPTION_REMOTE_ID,     "Remote-ID" },
577         { AGENT_SUBOPTION_SUBSCRIBER_ID, "Subscriber-ID" },
578         { 0, NULL }
579 };
580
581
582 static void
583 rfc1048_print(netdissect_options *ndo,
584               const u_char *bp)
585 {
586         uint16_t tag;
587         u_int len;
588         const char *cp;
589         char c;
590         int first, idx;
591         uint8_t subopt, suboptlen;
592
593         ND_PRINT("\n\t  Vendor-rfc1048 Extensions");
594
595         /* Step over magic cookie */
596         ND_PRINT("\n\t    Magic Cookie 0x%08x", GET_BE_U_4(bp));
597         bp += sizeof(int32_t);
598
599         /* Loop while we there is a tag left in the buffer */
600         while (ND_TTEST_1(bp)) {
601                 tag = GET_U_1(bp);
602                 bp++;
603                 if (tag == TAG_PAD && ndo->ndo_vflag < 3)
604                         continue;
605                 if (tag == TAG_END && ndo->ndo_vflag < 3)
606                         return;
607                 cp = tok2str(tag2str, "?Unknown", tag);
608                 c = *cp++;
609
610                 if (tag == TAG_PAD || tag == TAG_END)
611                         len = 0;
612                 else {
613                         /* Get the length; check for truncation */
614                         len = GET_U_1(bp);
615                         bp++;
616                 }
617
618                 ND_PRINT("\n\t    %s (%u), length %u%s", cp, tag, len,
619                           len > 0 ? ": " : "");
620
621                 if (tag == TAG_PAD && ndo->ndo_vflag > 2) {
622                         u_int ntag = 1;
623                         while (ND_TTEST_1(bp) &&
624                                GET_U_1(bp) == TAG_PAD) {
625                                 bp++;
626                                 ntag++;
627                         }
628                         if (ntag > 1)
629                                 ND_PRINT(", occurs %u", ntag);
630                 }
631
632                 ND_TCHECK_LEN(bp, len);
633
634                 if (tag == TAG_DHCP_MESSAGE && len == 1) {
635                         ND_PRINT("%s",
636                                  tok2str(dhcp_msg_values, "Unknown (%u)", GET_U_1(bp)));
637                         bp++;
638                         continue;
639                 }
640
641                 if (tag == TAG_PARM_REQUEST) {
642                         idx = 0;
643                         while (len > 0) {
644                                 uint8_t innertag = GET_U_1(bp);
645                                 bp++;
646                                 len--;
647                                 cp = tok2str(tag2str, "?Unknown", innertag);
648                                 if (idx % 4 == 0)
649                                         ND_PRINT("\n\t      ");
650                                 else
651                                         ND_PRINT(", ");
652                                 ND_PRINT("%s (%u)", cp + 1, innertag);
653                                 idx++;
654                         }
655                         continue;
656                 }
657
658                 /* Print data */
659                 if (c == '?') {
660                         /* Base default formats for unknown tags on data size */
661                         if (len & 1)
662                                 c = 'b';
663                         else if (len & 2)
664                                 c = 's';
665                         else
666                                 c = 'l';
667                 }
668                 first = 1;
669                 switch (c) {
670
671                 case 'a':
672                         /* ASCII strings */
673                         ND_PRINT("\"");
674                         if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
675                                 ND_PRINT("\"");
676                                 goto trunc;
677                         }
678                         ND_PRINT("\"");
679                         bp += len;
680                         len = 0;
681                         break;
682
683                 case 'i':
684                 case 'l':
685                 case 'L':
686                         /* ip addresses/32-bit words */
687                         while (len >= 4) {
688                                 if (!first)
689                                         ND_PRINT(",");
690                                 if (c == 'i')
691                                         ND_PRINT("%s", GET_IPADDR_STRING(bp));
692                                 else if (c == 'L')
693                                         ND_PRINT("%d", GET_BE_S_4(bp));
694                                 else
695                                         ND_PRINT("%u", GET_BE_U_4(bp));
696                                 bp += 4;
697                                 len -= 4;
698                                 first = 0;
699                         }
700                         break;
701
702                 case 'p':
703                         /* IP address pairs */
704                         while (len >= 2*4) {
705                                 if (!first)
706                                         ND_PRINT(",");
707                                 ND_PRINT("(%s:", GET_IPADDR_STRING(bp));
708                                 bp += 4;
709                                 len -= 4;
710                                 ND_PRINT("%s)", GET_IPADDR_STRING(bp));
711                                 bp += 4;
712                                 len -= 4;
713                                 first = 0;
714                         }
715                         break;
716
717                 case 's':
718                         /* shorts */
719                         while (len >= 2) {
720                                 if (!first)
721                                         ND_PRINT(",");
722                                 ND_PRINT("%u", GET_BE_U_2(bp));
723                                 bp += 2;
724                                 len -= 2;
725                                 first = 0;
726                         }
727                         break;
728
729                 case 'B':
730                         /* boolean */
731                         while (len > 0) {
732                                 uint8_t bool_value;
733                                 if (!first)
734                                         ND_PRINT(",");
735                                 bool_value = GET_U_1(bp);
736                                 switch (bool_value) {
737                                 case 0:
738                                         ND_PRINT("N");
739                                         break;
740                                 case 1:
741                                         ND_PRINT("Y");
742                                         break;
743                                 default:
744                                         ND_PRINT("%u?", bool_value);
745                                         break;
746                                 }
747                                 ++bp;
748                                 --len;
749                                 first = 0;
750                         }
751                         break;
752
753                 case 'b':
754                 case 'x':
755                 default:
756                         /* Bytes */
757                         while (len > 0) {
758                                 uint8_t byte_value;
759                                 if (!first)
760                                         ND_PRINT(c == 'x' ? ":" : ".");
761                                 byte_value = GET_U_1(bp);
762                                 if (c == 'x')
763                                         ND_PRINT("%02x", byte_value);
764                                 else
765                                         ND_PRINT("%u", byte_value);
766                                 ++bp;
767                                 --len;
768                                 first = 0;
769                         }
770                         break;
771
772                 case '$':
773                         /* Guys we can't handle with one of the usual cases */
774                         switch (tag) {
775
776                         case TAG_NETBIOS_NODE:
777                                 /* this option should be at least 1 byte long */
778                                 if (len < 1) {
779                                         ND_PRINT("[ERROR: length < 1 bytes]");
780                                         break;
781                                 }
782                                 tag = GET_U_1(bp);
783                                 ++bp;
784                                 --len;
785                                 ND_PRINT("%s", tok2str(nbo2str, NULL, tag));
786                                 break;
787
788                         case TAG_OPT_OVERLOAD:
789                                 /* this option should be at least 1 byte long */
790                                 if (len < 1) {
791                                         ND_PRINT("[ERROR: length < 1 bytes]");
792                                         break;
793                                 }
794                                 tag = GET_U_1(bp);
795                                 ++bp;
796                                 --len;
797                                 ND_PRINT("%s", tok2str(oo2str, NULL, tag));
798                                 break;
799
800                         case TAG_CLIENT_FQDN:
801                                 /* this option should be at least 3 bytes long */
802                                 if (len < 3) {
803                                         ND_PRINT("[ERROR: length < 3 bytes]");
804                                         bp += len;
805                                         len = 0;
806                                         break;
807                                 }
808                                 if (GET_U_1(bp) & 0xf0) {
809                                         ND_PRINT("[ERROR: MBZ nibble 0x%x != 0] ",
810                                                  (GET_U_1(bp) & 0xf0) >> 4);
811                                 }
812                                 if (GET_U_1(bp) & 0x0f)
813                                         ND_PRINT("[%s] ",
814                                                  client_fqdn_flags(GET_U_1(bp)));
815                                 bp++;
816                                 if (GET_U_1(bp) || GET_U_1(bp + 1))
817                                         ND_PRINT("%u/%u ", GET_U_1(bp),
818                                                  GET_U_1(bp + 1));
819                                 bp += 2;
820                                 ND_PRINT("\"");
821                                 if (nd_printn(ndo, bp, len - 3, ndo->ndo_snapend)) {
822                                         ND_PRINT("\"");
823                                         goto trunc;
824                                 }
825                                 ND_PRINT("\"");
826                                 bp += len - 3;
827                                 len = 0;
828                                 break;
829
830                         case TAG_CLIENT_ID:
831                             {
832                                 int type;
833
834                                 /* this option should be at least 1 byte long */
835                                 if (len < 1) {
836                                         ND_PRINT("[ERROR: length < 1 bytes]");
837                                         break;
838                                 }
839                                 type = GET_U_1(bp);
840                                 bp++;
841                                 len--;
842                                 if (type == 0) {
843                                         ND_PRINT("\"");
844                                         if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
845                                                 ND_PRINT("\"");
846                                                 goto trunc;
847                                         }
848                                         ND_PRINT("\"");
849                                         bp += len;
850                                         len = 0;
851                                         break;
852                                 } else {
853                                         ND_PRINT("%s ", tok2str(arp2str, "hardware-type %u,", type));
854                                         while (len > 0) {
855                                                 if (!first)
856                                                         ND_PRINT(":");
857                                                 ND_PRINT("%02x", GET_U_1(bp));
858                                                 ++bp;
859                                                 --len;
860                                                 first = 0;
861                                         }
862                                 }
863                                 break;
864                             }
865
866                         case TAG_AGENT_CIRCUIT:
867                                 while (len >= 2) {
868                                         subopt = GET_U_1(bp);
869                                         suboptlen = GET_U_1(bp + 1);
870                                         bp += 2;
871                                         len -= 2;
872                                         if (suboptlen > len) {
873                                                 ND_PRINT("\n\t      %s SubOption %u, length %u: length goes past end of option",
874                                                           tok2str(agent_suboption_values, "Unknown", subopt),
875                                                           subopt,
876                                                           suboptlen);
877                                                 bp += len;
878                                                 len = 0;
879                                                 break;
880                                         }
881                                         ND_PRINT("\n\t      %s SubOption %u, length %u: ",
882                                                   tok2str(agent_suboption_values, "Unknown", subopt),
883                                                   subopt,
884                                                   suboptlen);
885                                         switch (subopt) {
886
887                                         case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
888                                         case AGENT_SUBOPTION_REMOTE_ID:
889                                         case AGENT_SUBOPTION_SUBSCRIBER_ID:
890                                                 if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend))
891                                                         goto trunc;
892                                                 break;
893
894                                         default:
895                                                 print_unknown_data(ndo, bp, "\n\t\t", suboptlen);
896                                         }
897
898                                         len -= suboptlen;
899                                         bp += suboptlen;
900                                 }
901                                 break;
902
903                         case TAG_CLASSLESS_STATIC_RT:
904                         case TAG_CLASSLESS_STA_RT_MS:
905                             {
906                                 u_int mask_width, significant_octets, i;
907
908                                 /* this option should be at least 5 bytes long */
909                                 if (len < 5) {
910                                         ND_PRINT("[ERROR: length < 5 bytes]");
911                                         bp += len;
912                                         len = 0;
913                                         break;
914                                 }
915                                 while (len > 0) {
916                                         if (!first)
917                                                 ND_PRINT(",");
918                                         mask_width = GET_U_1(bp);
919                                         bp++;
920                                         len--;
921                                         /* mask_width <= 32 */
922                                         if (mask_width > 32) {
923                                                 ND_PRINT("[ERROR: Mask width (%u) > 32]", mask_width);
924                                                 bp += len;
925                                                 len = 0;
926                                                 break;
927                                         }
928                                         significant_octets = (mask_width + 7) / 8;
929                                         /* significant octets + router(4) */
930                                         if (len < significant_octets + 4) {
931                                                 ND_PRINT("[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4);
932                                                 bp += len;
933                                                 len = 0;
934                                                 break;
935                                         }
936                                         ND_PRINT("(");
937                                         if (mask_width == 0)
938                                                 ND_PRINT("default");
939                                         else {
940                                                 for (i = 0; i < significant_octets ; i++) {
941                                                         if (i > 0)
942                                                                 ND_PRINT(".");
943                                                         ND_PRINT("%u",
944                                                                  GET_U_1(bp));
945                                                         bp++;
946                                                 }
947                                                 for (i = significant_octets ; i < 4 ; i++)
948                                                         ND_PRINT(".0");
949                                                 ND_PRINT("/%u", mask_width);
950                                         }
951                                         ND_PRINT(":%s)", GET_IPADDR_STRING(bp));
952                                         bp += 4;
953                                         len -= (significant_octets + 4);
954                                         first = 0;
955                                 }
956                                 break;
957                             }
958
959                         case TAG_USER_CLASS:
960                             {
961                                 u_int suboptnumber = 1;
962
963                                 first = 1;
964                                 if (len < 2) {
965                                         ND_PRINT("[ERROR: length < 2 bytes]");
966                                         bp += len;
967                                         len = 0;
968                                         break;
969                                 }
970                                 while (len > 0) {
971                                         suboptlen = GET_U_1(bp);
972                                         bp++;
973                                         len--;
974                                         ND_PRINT("\n\t      ");
975                                         ND_PRINT("instance#%u: ", suboptnumber);
976                                         if (suboptlen == 0) {
977                                                 ND_PRINT("[ERROR: suboption length must be non-zero]");
978                                                 bp += len;
979                                                 len = 0;
980                                                 break;
981                                         }
982                                         if (len < suboptlen) {
983                                                 ND_PRINT("[ERROR: invalid option]");
984                                                 bp += len;
985                                                 len = 0;
986                                                 break;
987                                         }
988                                         ND_PRINT("\"");
989                                         if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) {
990                                                 ND_PRINT("\"");
991                                                 goto trunc;
992                                         }
993                                         ND_PRINT("\"");
994                                         ND_PRINT(", length %u", suboptlen);
995                                         suboptnumber++;
996                                         len -= suboptlen;
997                                         bp += suboptlen;
998                                 }
999                                 break;
1000                             }
1001
1002                         default:
1003                                 ND_PRINT("[unknown special tag %u, size %u]",
1004                                           tag, len);
1005                                 bp += len;
1006                                 len = 0;
1007                                 break;
1008                         }
1009                         break;
1010                 }
1011                 /* Data left over? */
1012                 if (len) {
1013                         ND_PRINT("\n\t  trailing data length %u", len);
1014                         bp += len;
1015                 }
1016         }
1017         return;
1018 trunc:
1019         nd_print_trunc(ndo);
1020 }
1021
1022 #define PRINTCMUADDR(m, s) { ND_TCHECK_4(cmu->m); \
1023     if (GET_IPV4_TO_NETWORK_ORDER(cmu->m) != 0) \
1024         ND_PRINT(" %s:%s", s, GET_IPADDR_STRING(cmu->m)); }
1025
1026 static void
1027 cmu_print(netdissect_options *ndo,
1028           const u_char *bp)
1029 {
1030         const struct cmu_vend *cmu;
1031         uint8_t v_flags;
1032
1033         ND_PRINT(" vend-cmu");
1034         cmu = (const struct cmu_vend *)bp;
1035
1036         /* Only print if there are unknown bits */
1037         ND_TCHECK_4(cmu->v_flags);
1038         v_flags = GET_U_1(cmu->v_flags);
1039         if ((v_flags & ~(VF_SMASK)) != 0)
1040                 ND_PRINT(" F:0x%x", v_flags);
1041         PRINTCMUADDR(v_dgate, "DG");
1042         PRINTCMUADDR(v_smask, v_flags & VF_SMASK ? "SM" : "SM*");
1043         PRINTCMUADDR(v_dns1, "NS1");
1044         PRINTCMUADDR(v_dns2, "NS2");
1045         PRINTCMUADDR(v_ins1, "IEN1");
1046         PRINTCMUADDR(v_ins2, "IEN2");
1047         PRINTCMUADDR(v_ts1, "TS1");
1048         PRINTCMUADDR(v_ts2, "TS2");
1049         return;
1050
1051 trunc:
1052         nd_print_trunc(ndo);
1053 }
1054
1055 #undef PRINTCMUADDR
1056
1057 static char *
1058 client_fqdn_flags(u_int flags)
1059 {
1060         static char buf[8+1];
1061         int i = 0;
1062
1063         if (flags & CLIENT_FQDN_FLAGS_S)
1064                 buf[i++] = 'S';
1065         if (flags & CLIENT_FQDN_FLAGS_O)
1066                 buf[i++] = 'O';
1067         if (flags & CLIENT_FQDN_FLAGS_E)
1068                 buf[i++] = 'E';
1069         if (flags & CLIENT_FQDN_FLAGS_N)
1070                 buf[i++] = 'N';
1071         buf[i] = '\0';
1072
1073         return buf;
1074 }