xref: /dragonfly/contrib/tcpdump/print-bootp.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
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
bootp_print(netdissect_options * ndo,const u_char * cp,u_int length)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
rfc1048_print(netdissect_options * ndo,const u_char * bp)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
cmu_print(netdissect_options * ndo,const u_char * bp)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 *
client_fqdn_flags(u_int flags)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 }
1075