2 * Routines for BOOTP/DHCP packet disassembly
3 * Copyright 1998, Gilbert Ramirez <gram@alumni.rice.edu>
4 * Copyright 2004, Thomas Anders <thomas.anders [AT] blue-cable.de>
8 * The information used comes from:
9 * RFC 951: Bootstrap Protocol
10 * RFC 1497: BOOTP extensions
11 * RFC 1542: Clarifications and Extensions for the Bootstrap Protocol
12 * RFC 2131: Dynamic Host Configuration Protocol
13 * RFC 2132: DHCP Options and BOOTP Vendor Extensions
14 * RFC 2241: DHCP Options for Novell Directory Services
15 * RFC 2242: NetWare/IP Domain Name and Information
16 * RFC 2489: Procedure for Defining New DHCP Options
17 * RFC 2610: DHCP Options for Service Location Protocol
18 * RFC 3046: DHCP Relay Agent Information Option
19 * RFC 3118: Authentication for DHCP Messages
20 * RFC 3203: DHCP reconfigure extension
21 * RFC 3315: Dynamic Host Configuration Protocol for IPv6 (DHCPv6)
22 * RFC 3495: DHCP Option (122) for CableLabs Client Configuration
23 * RFC 3594: PacketCable Security Ticket Control Sub-Option (122.9)
24 * RFC 3442: Classless Static Route Option for DHCP version 4
25 * RFC 3825: Dynamic Host Configuration Protocol Option for Coordinate-based Location Configuration Information
26 * RFC 3925: Vendor-Identifying Vendor Options for Dynamic Host Configuration Protocol version 4 (DHCPv4)
27 * RFC 3942: Reclassifying DHCPv4 Options
28 * RFC 4243: Vendor-Specific Information Suboption for the Dynamic Host Configuration Protocol (DHCP) Relay Agent Option
29 * RFC 4361: Node-specific Client Identifiers for Dynamic Host Configuration Protocol Version Four (DHCPv4)
30 * RFC 4388: Dynamic Host Configuration Protocol (DHCP) Leasequery
31 * RFC 4578: Dynamic Host Configuration Protocol (DHCP) Options for PXE
32 * RFC 4776: Dynamic Host Configuration Protocol (DHCPv4 and DHCPv6) Option for Civic Addresses Configuration Information
33 * RFC 5223: Discovering Location-to-Service Translation (LoST) Servers Using the Dynamic Host Configuration Protocol (DHCP)
34 * RFC 5417: CAPWAP Access Controller DHCP Option
35 * draft-ietf-dhc-fqdn-option-07.txt
36 * TFTP Server Address Option for DHCPv4 [draft-raj-dhc-tftp-addr-option-06.txt: http://tools.ietf.org/html/draft-raj-dhc-tftp-addr-option-06]
37 * BOOTP and DHCP Parameters
38 * http://www.iana.org/assignments/bootp-dhcp-parameters
39 * DOCSIS(TM) 2.0 Radio Frequency Interface Specification
40 * http://www.cablemodem.com/downloads/specs/CM-SP-RFI2.0-I10-051209.pdf
41 * PacketCable(TM) 1.0 MTA Device Provisioning Specification
42 * http://www.packetcable.com/downloads/specs/PKT-SP-PROV-I11-050812.pdf
43 * http://www.cablelabs.com/specifications/archives/PKT-SP-PROV-I05-021127.pdf (superseded by above)
44 * PacketCable(TM) 1.5 MTA Device Provisioning Specification
45 * http://www.packetcable.com/downloads/specs/PKT-SP-PROV1.5-I02-050812.pdf
46 * PacketCable(TM) 2.0 EUE Device Provisioning Specification
47 * www.cablelabs.com/specifications/PKT-SP-EUE-DATA-I03-090528.pdf
48 * CableHome(TM) 1.1 Specification
49 * http://www.cablelabs.com/projects/cablehome/downloads/specs/CH-SP-CH1.1-I11-060407.pdf
51 * http://www.dslforum.org/techwork/tr/TR-111.pdf
53 * Wireshark - Network traffic analyzer
54 * By Gerald Combs <gerald@wireshark.org>
55 * Copyright 1998 Gerald Combs
57 * This program is free software; you can redistribute it and/or
58 * modify it under the terms of the GNU General Public License
59 * as published by the Free Software Foundation; either version 2
60 * of the License, or (at your option) any later version.
62 * This program is distributed in the hope that it will be useful,
63 * but WITHOUT ANY WARRANTY; without even the implied warranty of
64 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65 * GNU General Public License for more details.
67 * You should have received a copy of the GNU General Public License
68 * along with this program; if not, write to the Free Software
69 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
73 * Some of the development of the BOOTP/DHCP protocol decoder was sponsored by
74 * Cable Television Laboratories, Inc. ("CableLabs") based upon proprietary
75 * CableLabs' specifications. Your license and use of this protocol decoder
76 * does not mean that you are licensed to use the CableLabs'
77 * specifications. If you have questions about this protocol, contact
78 * jf.mule [AT] cablelabs.com or c.stuart [AT] cablelabs.com for additional
90 #include <epan/packet.h>
91 #include "packet-arp.h"
92 #include "packet-dns.h" /* for get_dns_name() */
93 #include <epan/addr_resolv.h>
94 #include <epan/prefs.h>
96 #include <epan/strutil.h>
97 #include <epan/arptypes.h>
98 #include <epan/sminmpec.h>
99 #include <epan/expert.h>
102 static int bootp_dhcp_tap = -1;
103 static int proto_bootp = -1;
104 static int hf_bootp_type = -1;
105 static int hf_bootp_hw_type = -1;
106 static int hf_bootp_hw_len = -1;
107 static int hf_bootp_hops = -1;
108 static int hf_bootp_id = -1;
109 static int hf_bootp_secs = -1;
110 static int hf_bootp_flags = -1;
111 static int hf_bootp_flags_broadcast = -1;
112 static int hf_bootp_flags_reserved = -1;
113 static int hf_bootp_ip_client = -1;
114 static int hf_bootp_ip_your = -1;
115 static int hf_bootp_ip_server = -1;
116 static int hf_bootp_ip_relay = -1;
117 static int hf_bootp_hw_addr = -1;
118 static int hf_bootp_hw_addr_padding = -1;
119 static int hf_bootp_hw_ether_addr = -1;
120 static int hf_bootp_server = -1;
121 static int hf_bootp_file = -1;
122 static int hf_bootp_cookie = -1;
123 static int hf_bootp_vendor = -1;
124 static int hf_bootp_dhcp = -1;
125 static int hf_bootp_fqdn_s = -1;
126 static int hf_bootp_fqdn_o = -1;
127 static int hf_bootp_fqdn_e = -1;
128 static int hf_bootp_fqdn_n = -1;
129 static int hf_bootp_fqdn_mbz = -1;
130 static int hf_bootp_fqdn_rcode1 = -1;
131 static int hf_bootp_fqdn_rcode2 = -1;
132 static int hf_bootp_fqdn_name = -1;
133 static int hf_bootp_fqdn_asciiname = -1;
134 static int hf_bootp_pkt_mtacap_len = -1;
135 static int hf_bootp_docsis_cmcap_len = -1;
136 static int hf_bootp_alu_vid = -1;
137 static int hf_bootp_alu_tftp1 = -1;
138 static int hf_bootp_alu_tftp2 = -1;
139 static int hf_bootp_alu_app_type = -1;
140 static int hf_bootp_alu_sip_url = -1;
141 static int hf_bootp_client_identifier_uuid = -1;
142 static int hf_bootp_client_network_id_major_ver = -1;
143 static int hf_bootp_client_network_id_minor_ver = -1;
144 static int hf_bootp_option_type = -1;
145 static int hf_bootp_option_length = -1;
146 static int hf_bootp_option_value = -1;
148 static gint ett_bootp = -1;
149 static gint ett_bootp_flags = -1;
150 static gint ett_bootp_option = -1;
151 static gint ett_bootp_fqdn = -1;
153 static const char *pref_optionstring = "";
155 /* RFC3825decoder error codes of the conversion function */
156 #define RFC3825_NOERROR 0
157 #define RFC3825_LATITUDE_OUTOFRANGE 1
158 #define RFC3825_LATITUDE_UNCERTAINTY_OUTOFRANGE 2
159 #define RFC3825_LONGITUDE_OUTOFRANGE 3
160 #define RFC3825_LONGITUDE_UNCERTAINTY_OUTOFRANGE 4
161 #define RFC3825_ALTITUDE_OUTOFRANGE 5
162 #define RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE 6
163 #define RFC3825_ALTITUDE_TYPE_OUTOFRANGE 7
164 #define RFC3825_DATUM_TYPE_OUTOFRANGE 8
170 struct rfc3825_location_fixpoint_t {
172 gint64 latitude; /* latitude in degrees, allowed range from -90deg to 90deg.
173 Fixpoint A(8,25) with 34 bits */
174 guint8 latitude_res; /* the resolution of the latitude in bits, allowed range is from 0 to 34.
176 gint64 longitude; /* longitude in degrees, range from -180deg to 180deg.
177 Fixpoint A(8,25) with 34 bits */
178 guint8 longitude_res; /* the resolution of the longitude in bits, allowed range is from 0 to 34.
180 gint32 altitude; /* the altitude, 30 bits.
181 Depending on alt_type this are meters or floors, no range limit.
182 altitude_type==1: A(13,8) with 22 bits
183 altitude_type==2: A(13,8) with 22 bits */
184 guint8 altitude_res; /* the resolution of the altitude in bits, allowed range is from 0 to 30.
186 altitude_type==1: any value between 0 and 30
187 altitude_type==2: either 0 (floor unknown) or 30 */
188 guint8 altitude_type; /* the type of the altitude, 4 bits. allowed values are:
190 1: altitude in meters
191 2: altitude in floors */
192 guint8 datum_type; /* the map datum used for the coordinates. 8 bits.
193 All values are allowed although currently only the
194 following ones are defined:
200 /* The rfc3825_location_decimal_t structure holds the location parameters
201 * in decimal (floating point) format.
203 struct rfc3825_location_decimal_t {
205 double latitude; /* latitude in degrees, allowed range from -90deg to 90deg */
206 double latitude_res; /* the uncertainty of the latitude in grad, "0.01" means +-0.01deg
207 from the altitude. During conversion this will be rounded to
208 next smaller value which can be respresented in fixpoint arithmetic */
209 double longitude; /* longitude in degrees, range from -180deg to 180deg */
210 double longitude_res; /* the uncertainty of the longitude in grad, "0.01" means +-0.01deg
211 from the longitude. During conversion this will be rounded to
212 next smaller value which can be respresented in fixpoint arithmetic */
213 double altitude; /* the altitude, depending on alt_type this are meters or floors, no range limit */
214 double altitude_res; /* the uncertainty of the altitude in either:
215 - altitude-type=meters: "10" means 10 meters which means +-10 meters from the altitude
216 - altitude-type=floors: either 0 (unknown) or 30 (exact) */
217 int altitude_type; /* the type of the altitude, allowed values are
219 1: altitude in meters
220 2: altitude in floors */
221 int datum_type; /* the map datum used for the coordinates.
222 All values are allowed although currently only the
223 following ones are defined:
229 /* converts fixpoint presentation into decimal presentation
230 also converts values which are out of range to allow decoding of received data */
231 static int rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct rfc3825_location_decimal_t *decimal);
233 /* decodes the LCI string received from DHCP into the fixpoint values */
234 static void rfc3825_lci_to_fixpoint(const unsigned char lci[16], struct rfc3825_location_fixpoint_t *fixpoint);
237 /* Map Datum Types used for the coordinates (RFC 3825) */
238 static const value_string map_datum_type_values[] = {
240 { 2, "NAD83 (NAVD88)" },
241 { 3, "NAD83 (MLLW)" },
246 /* Altitude Types used for the coordinates (RFC 3825) */
247 static const value_string altitude_type_values[] = {
253 /* AutoConfigure (RFC 2563) */
254 static const value_string dhcp_autoconfig[] = {
255 {0, "DoNotAutoConfigure"},
256 {1, "AutoConfigure"},
260 /* Error Types for RFC 3825 coordinate location decoding */
261 static const value_string rfc3825_error_types[] = {
262 {1, "Latitude is out of range [-90,90]"},
263 {2, "Latitude Uncertainty is out of range [0,90]"},
264 {3, "Longitude is out of range [-180,180]"},
265 {4, "Longitude Uncertainty is out of range [0,180]"},
266 {5, "Altitude is out of range [-(2^21),(2^21)-1]"},
267 {6, "Altitude Uncertainty is out of range [0,2^20]"},
268 {7, "Altitude Type is out of range [0,2]"},
269 {8, "Datum is out of range [1,3]"},
275 /* Civic Address What field (RFC 4776) */
276 static const value_string civic_address_what_values[] = {
277 { 0, "Location of the DHCP server" },
278 { 1, "Location of the network element believed to be closest to the client" },
279 { 2, "Location of the client"},
283 /* Civic Address Type field (RFC 4119, RFC 4776, RFC 5139) */
284 static const value_string civic_address_type_values[] = {
292 { 16, "PRD (Leading street direction)" },
293 { 17, "POD (Trailing street suffix)" },
294 { 18, "STS (Street suffix)" },
295 { 19, "HNO (House number)" },
296 { 20, "HNS (House number suffix)" },
297 { 21, "LMK (Landmark or vanity address)" },
298 { 22, "LOC (Additional location information)" },
300 { 24, "PC (Postal/ZIP code)" },
301 { 25, "BLD (Building)" },
303 { 27, "FLR (Floor)" },
305 { 29, "PLC (Place-type)" },
306 { 30, "PCN (Postal community name)" },
308 { 32, "ADDCODE (Additional Code)" },
310 { 34, "RD (Primary road or street)" },
311 { 35, "RDSEC (Road section)" },
312 { 36, "RDBR (Road branch)" },
313 { 37, "RDSUBBR (Road sub-branch)" },
314 { 38, "PRM (Road pre-modifier)" },
315 { 39, "POM (Road post-modifier" },
320 static const value_string cablelab_ipaddr_mode_vals[] = {
326 static const value_string duidtype_vals[] =
328 { DUID_LLT, "link-layer address plus time" },
329 { DUID_EN, "assigned by vendor based on Enterprise number" },
330 { DUID_LL, "link-layer address" },
334 static gboolean novell_string = FALSE;
336 #define UDP_PORT_BOOTPS 67
337 #define UDP_PORT_BOOTPC 68
339 #define BOOTP_BC 0x8000
340 #define BOOTP_MBZ 0x7FFF
343 #define F_FQDN_S 0x01
344 #define F_FQDN_O 0x02
345 #define F_FQDN_E 0x04
346 #define F_FQDN_N 0x08
347 #define F_FQDN_MBZ 0xf0
349 static const true_false_string tfs_fqdn_s = {
354 static const true_false_string tfs_fqdn_o = {
359 static const true_false_string tfs_fqdn_e = {
364 static const true_false_string tfs_fqdn_n = {
366 "Some server updates"
373 ipv4, /* single IPv4 address */
374 ipv4_list, /* list of IPv4 addresses */
384 time_in_s_secs, /* Signed */
385 time_in_u_secs, /* Unsigned (not micro) */
392 enum field_type ftype;
396 static const true_false_string flag_set_broadcast = {
402 /* PacketCable/DOCSIS definitions */
403 #define PACKETCABLE_MTA_CAP10 "pktc1.0:"
404 #define PACKETCABLE_MTA_CAP15 "pktc1.5:"
405 #define PACKETCABLE_MTA_CAP20 "pktc2.0:"
406 #define PACKETCABLE_CM_CAP11 "docsis1.1:"
407 #define PACKETCABLE_CM_CAP20 "docsis2.0:"
408 #define PACKETCABLE_CM_CAP30 "docsis3.0:"
410 #define PACKETCABLE_CCC_I05 1
411 #define PACKETCABLE_CCC_DRAFT5 2
412 #define PACKETCABLE_CCC_RFC_3495 3
414 static enum_val_t pkt_ccc_protocol_versions[] = {
415 { "ccc_i05", "PKT-SP-PROV-I05-021127", PACKETCABLE_CCC_I05 },
416 { "ccc_draft_5", "IETF Draft 5", PACKETCABLE_CCC_DRAFT5 },
417 { "rfc_3495", "RFC 3495", PACKETCABLE_CCC_RFC_3495 },
421 static gint pkt_ccc_protocol_version = PACKETCABLE_CCC_RFC_3495;
422 static guint pkt_ccc_option = 122;
425 static int dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
426 int optoff, int optend);
427 static int dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb,
428 int optoff, int optend);
429 static int dissect_vendor_alcatel_suboption(proto_tree *v_tree, tvbuff_t *tvb,
430 int optoff, int optend);
431 static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
432 int optoff, int optend);
433 static int dissect_vendor_tr111_suboption(proto_tree *v_tree, tvbuff_t *tvb,
434 int optoff, int optend);
435 static int bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb,
436 int optoff, int optend);
437 static void dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb,
439 static void dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb,
441 static int dissect_packetcable_i05_ccc(proto_tree *v_tree, tvbuff_t *tvb,
442 int optoff, int optend);
443 static int dissect_packetcable_ietf_ccc(proto_tree *v_tree, tvbuff_t *tvb,
444 int optoff, int optend, int revision);
445 static int dissect_vendor_cl_suboption(proto_tree *v_tree, tvbuff_t *tvb,
446 int optoff, int optend);
448 #define OPT53_DISCOVER "Discover"
449 /* http://www.iana.org/assignments/bootp-dhcp-parameters */
450 static const value_string opt53_text[] = {
451 { 1, OPT53_DISCOVER },
459 { 9, "Force Renew" },
460 { 10, "Lease query" }, /* RFC4388 */
461 { 11, "Lease Unassigned" }, /* RFC4388 */
462 { 12, "Lease Unknown" }, /* RFC4388 */
463 { 13, "Lease Active" }, /* RFC4388 */
464 /* draft-ietf-dhc-leasequery-09.txt
465 { 13, "Lease query" }, */
466 { 14, "Lease known" },
467 { 15, "Lease unknown" },
468 { 16, "Lease active" },
469 { 17, "Unimplemented" },
474 /* DHCP Authentication protocols */
475 #define AUTHEN_PROTO_CONFIG_TOKEN 0
476 #define AUTHEN_PROTO_DELAYED_AUTHEN 1
478 /* DHCP Authentication algorithms for delayed authentication */
479 #define AUTHEN_DELAYED_ALGO_HMAC_MD5 1
481 /* DHCP Authentication Replay Detection Methods */
482 #define AUTHEN_RDM_MONOTONIC_COUNTER 0x00
484 /* DHCP Option Overload (option code 52) */
485 #define OPT_OVERLOAD_FILE 1
486 #define OPT_OVERLOAD_SNAME 2
487 #define OPT_OVERLOAD_BOTH 3
489 /* Server name and boot file offsets and lengths */
490 #define SERVER_NAME_OFFSET 44
491 #define SERVER_NAME_LEN 64
492 #define FILE_NAME_OFFSET 108
493 #define FILE_NAME_LEN 128
494 #define VENDOR_INFO_OFFSET 236
496 static const value_string bootp_nbnt_vals[] = {
504 static const value_string bootp_client_arch[] = {
505 { 0x0000, "IA x86 PC" },
506 { 0x0001, "NEC/PC98" },
507 { 0x0002, "IA64 PC" },
508 { 0x0003, "DEC Alpha" },
509 { 0x0004, "ArcX86" },
510 { 0x0005, "Intel Lean Client" },
511 { 0x0006, "EFI IA32" },
512 { 0x0007, "EFI BC" },
513 { 0x0008, "EFI Xscale" },
514 { 0x0009, "EFI x86-64" },
518 /* bootp options administration */
519 #define BOOTP_OPT_NUM 256
521 /* Re-define structure. Values to be upated by bootp_init_protocol */
522 static struct opt_info bootp_opt[BOOTP_OPT_NUM];
524 static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = {
525 /* 0 */ { "Padding", none, NULL },
526 /* 1 */ { "Subnet Mask", ipv4, NULL },
527 /* 2 */ { "Time Offset", time_in_s_secs, NULL },
528 /* 3 */ { "Router", ipv4_list, NULL },
529 /* 4 */ { "Time Server", ipv4_list, NULL },
530 /* 5 */ { "Name Server", ipv4_list, NULL },
531 /* 6 */ { "Domain Name Server", ipv4_list, NULL },
532 /* 7 */ { "Log Server", ipv4_list, NULL },
533 /* 8 */ { "Quotes Server", ipv4_list, NULL },
534 /* 9 */ { "LPR Server", ipv4_list, NULL },
535 /* 10 */ { "Impress Server", ipv4_list, NULL },
536 /* 11 */ { "Resource Location Server", ipv4_list, NULL },
537 /* 12 */ { "Host Name", string, NULL },
538 /* 13 */ { "Boot File Size", val_u_short, NULL },
539 /* 14 */ { "Merit Dump File", string, NULL },
540 /* 15 */ { "Domain Name", string, NULL },
541 /* 16 */ { "Swap Server", ipv4, NULL },
542 /* 17 */ { "Root Path", string, NULL },
543 /* 18 */ { "Extensions Path", string, NULL },
544 /* 19 */ { "IP Forwarding", val_boolean, TFS(&tfs_enabled_disabled) },
545 /* 20 */ { "Non-Local Source Routing", val_boolean, TFS(&tfs_enabled_disabled) },
546 /* 21 */ { "Policy Filter", special, NULL },
547 /* 22 */ { "Maximum Datagram Reassembly Size", val_u_short, NULL },
548 /* 23 */ { "Default IP Time-to-Live", val_u_byte, NULL },
549 /* 24 */ { "Path MTU Aging Timeout", time_in_u_secs, NULL },
550 /* 25 */ { "Path MTU Plateau Table", val_u_short_list, NULL },
551 /* 26 */ { "Interface MTU", val_u_short, NULL },
552 /* 27 */ { "All Subnets are Local", val_boolean, TFS(&tfs_yes_no) },
553 /* 28 */ { "Broadcast Address", ipv4, NULL },
554 /* 29 */ { "Perform Mask Discovery", val_boolean, TFS(&tfs_enabled_disabled) },
555 /* 30 */ { "Mask Supplier", val_boolean, TFS(&tfs_yes_no) },
556 /* 31 */ { "Perform Router Discover", val_boolean, TFS(&tfs_enabled_disabled) },
557 /* 32 */ { "Router Solicitation Address", ipv4, NULL },
558 /* 33 */ { "Static Route", special, NULL },
559 /* 34 */ { "Trailer Encapsulation", val_boolean, TFS(&tfs_enabled_disabled) },
560 /* 35 */ { "ARP Cache Timeout", time_in_u_secs, NULL },
561 /* 36 */ { "Ethernet Encapsulation", val_boolean, TFS(&tfs_enabled_disabled) },
562 /* 37 */ { "TCP Default TTL", val_u_byte, NULL },
563 /* 38 */ { "TCP Keepalive Interval", time_in_u_secs, NULL },
564 /* 39 */ { "TCP Keepalive Garbage", val_boolean, TFS(&tfs_enabled_disabled) },
565 /* 40 */ { "Network Information Service Domain", string, NULL },
566 /* 41 */ { "Network Information Service Servers", ipv4_list, NULL },
567 /* 42 */ { "Network Time Protocol Servers", ipv4_list, NULL },
568 /* 43 */ { "Vendor-Specific Information", special, NULL },
569 /* 44 */ { "NetBIOS over TCP/IP Name Server", ipv4_list, NULL },
570 /* 45 */ { "NetBIOS over TCP/IP Datagram Distribution Name Server", ipv4_list, NULL },
571 /* 46 */ { "NetBIOS over TCP/IP Node Type", val_u_byte, VALS(bootp_nbnt_vals) },
572 /* 47 */ { "NetBIOS over TCP/IP Scope", string, NULL },
573 /* 48 */ { "X Window System Font Server", ipv4_list, NULL },
574 /* 49 */ { "X Window System Display Manager", ipv4_list, NULL },
575 /* 50 */ { "Requested IP Address", ipv4, NULL },
576 /* 51 */ { "IP Address Lease Time", time_in_u_secs, NULL },
577 /* 52 */ { "Option Overload", special, NULL },
578 /* 53 */ { "DHCP Message Type", special, NULL },
579 /* 54 */ { "DHCP Server Identifier", ipv4, NULL },
580 /* 55 */ { "Parameter Request List", special, NULL },
581 /* 56 */ { "Message", string, NULL },
582 /* 57 */ { "Maximum DHCP Message Size", val_u_short, NULL },
583 /* 58 */ { "Renewal Time Value", time_in_u_secs, NULL },
584 /* 59 */ { "Rebinding Time Value", time_in_u_secs, NULL },
585 /* 60 */ { "Vendor class identifier", special, NULL },
586 /* 61 */ { "Client identifier", special, NULL },
587 /* 62 */ { "Novell/Netware IP domain", string, NULL },
588 /* 63 */ { "Novell Options", special, NULL },
589 /* 64 */ { "Network Information Service+ Domain", string, NULL },
590 /* 65 */ { "Network Information Service+ Servers", ipv4_list, NULL },
591 /* 66 */ { "TFTP Server Name", string, NULL },
592 /* 67 */ { "Bootfile name", string, NULL },
593 /* 68 */ { "Mobile IP Home Agent", ipv4_list, NULL },
594 /* 69 */ { "SMTP Server", ipv4_list, NULL },
595 /* 70 */ { "POP3 Server", ipv4_list, NULL },
596 /* 71 */ { "NNTP Server", ipv4_list, NULL },
597 /* 72 */ { "Default WWW Server", ipv4_list, NULL },
598 /* 73 */ { "Default Finger Server", ipv4_list, NULL },
599 /* 74 */ { "Default IRC Server", ipv4_list, NULL },
600 /* 75 */ { "StreetTalk Server", ipv4_list, NULL },
601 /* 76 */ { "StreetTalk Directory Assistance Server", ipv4_list, NULL },
602 /* 77 */ { "User Class Information", opaque, NULL },
603 /* 78 */ { "Directory Agent Information", special, NULL },
604 /* 79 */ { "Service Location Agent Scope", special, NULL },
605 /* 80 */ { "Rapid commit", opaque, NULL },
606 /* 81 */ { "Client Fully Qualified Domain Name", special, NULL },
607 /* 82 */ { "Agent Information Option", special, NULL },
608 /* 83 */ { "iSNS [TODO:RFC4174]", opaque, NULL },
609 /* 84 */ { "Removed/Unassigned", opaque, NULL },
610 /* 85 */ { "Novell Directory Services Servers", special, NULL },
611 /* 86 */ { "Novell Directory Services Tree Name", string, NULL },
612 /* 87 */ { "Novell Directory Services Context", string, NULL },
613 /* 88 */ { "BCMCS Controller Domain Name [TODO:RFC4280]", opaque, NULL },
614 /* 89 */ { "BCMCS Controller IPv4 address [TODO:RFC4280]", opaque, NULL },
615 /* 90 */ { "Authentication", special, NULL },
616 /* 91 */ { "Client last transaction time", time_in_u_secs, NULL },
617 /* 92 */ { "Associated IP option", ipv4_list, NULL },
618 /* 93 */ { "Client System Architecture", val_u_short, VALS(bootp_client_arch) },
619 /* 94 */ { "Client Network Device Interface", special, NULL },
620 /* 95 */ { "LDAP [TODO:RFC3679]", opaque, NULL },
621 /* 96 */ { "Removed/Unassigend", opaque, NULL },
622 /* 97 */ { "UUID/GUID-based Client Identifier", special, NULL },
623 /* 98 */ { "Open Group's User Authentication [TODO:RFC2485]", opaque, NULL },
624 /* 99 */ { "Civic Addresses Configuration", special, NULL },
625 /* 100 */ { "PCode [TODO:RFC4833]", opaque, NULL },
626 /* 101 */ { "TCode [TODO:RFC4833]", opaque, NULL },
627 /* 102 */ { "Removed/unassigned", opaque, NULL },
628 /* 103 */ { "Removed/unassigned", opaque, NULL },
629 /* 104 */ { "Removed/unassigned", opaque, NULL },
630 /* 105 */ { "Removed/unassigned", opaque, NULL },
631 /* 106 */ { "Removed/unassigned", opaque, NULL },
632 /* 107 */ { "Removed/unassigned", opaque, NULL },
633 /* 108 */ { "Removed/Unassigend", opaque, NULL },
634 /* 109 */ { "Unassigned", opaque, NULL },
635 /* 110 */ { "Removed/Uassigend", opaque, NULL },
636 /* 111 */ { "Unassigned", opaque, NULL },
637 /* 112 */ { "NetInfo Parent Server Address", ipv4_list, NULL },
638 /* 113 */ { "NetInfo Parent Server Tag", string, NULL },
639 /* 114 */ { "URL [TODO:RFC3679]", opaque, NULL },
640 /* 115 */ { "Removed/Unassigend", opaque, NULL },
641 /* 116 */ { "DHCP Auto-Configuration", val_u_byte, VALS(dhcp_autoconfig) },
642 /* 117 */ { "Name Service Search [TODO:RFC2937]", opaque, NULL },
643 /* 118 */ { "Subnet Selection Option", ipv4_list, NULL },
644 /* 119 */ { "Domain Search [TODO:RFC3397]", opaque, NULL },
645 /* 120 */ { "SIP Servers [TODO:RFC3361]", opaque, NULL },
646 /* 121 */ { "Classless Static Route", special, NULL },
647 /* 122 */ { "CableLabs Client Configuration [TODO:RFC3495]", opaque, NULL },
648 /* 123 */ { "Coordinate-based Location Configuration", special, NULL },
649 /* 124 */ { "V-I Vendor Class", special, NULL },
650 /* 125 */ { "V-I Vendor-specific Information", special, NULL },
651 /* 126 */ { "Removed/Unassigned", opaque, NULL },
652 /* 127 */ { "Removed/Unassigend", opaque, NULL },
653 /* 128 */ { "DOCSIS full security server IP [TODO]", opaque, NULL },
654 /* 129 */ { "PXE - undefined (vendor specific)", opaque, NULL },
655 /* 130 */ { "PXE - undefined (vendor specific)", opaque, NULL },
656 /* 131 */ { "PXE - undefined (vendor specific)", opaque, NULL },
657 /* 132 */ { "PXE - undefined (vendor specific)", opaque, NULL },
658 /* 133 */ { "PXE - undefined (vendor specific)", opaque, NULL },
659 /* 134 */ { "PXE - undefined (vendor specific)", opaque, NULL },
660 /* 135 */ { "PXE - undefined (vendor specific)", opaque, NULL },
661 /* 136 */ { "OPTION_PANA_AGENT [TODO:RFC5192]", opaque, NULL },
662 /* 137 */ { "LoST Server Domain Name", string, NULL },
663 /* 138 */ { "CAPWAP Access Controllers", ipv4_list, NULL },
664 /* 139 */ { "IPv4 Address-MoS", opaque, NULL },
665 /* 140 */ { "IPv4 FQDN-MoS", opaque, NULL },
666 /* 141 */ { "SIP UA Configuration Domains", opaque, NULL },
667 /* 142 */ { "Unassigned", opaque, NULL },
668 /* 143 */ { "Unassigned", opaque, NULL },
669 /* 144 */ { "Unassigned", opaque, NULL },
670 /* 145 */ { "Unassigned", opaque, NULL },
671 /* 146 */ { "Unassigned", opaque, NULL },
672 /* 147 */ { "Unassigned", opaque, NULL },
673 /* 148 */ { "Unassigned", opaque, NULL },
674 /* 149 */ { "Unassigned", opaque, NULL },
675 /* 150 */ { "TFTP Server Address", ipv4_list, NULL },
676 /* 151 */ { "Unassigned", opaque, NULL },
677 /* 152 */ { "Unassigned", opaque, NULL },
678 /* 153 */ { "Unassigned", opaque, NULL },
679 /* 154 */ { "Unassigned", opaque, NULL },
680 /* 155 */ { "Unassigned", opaque, NULL },
681 /* 156 */ { "Unassigned", opaque, NULL },
682 /* 157 */ { "Unassigned", opaque, NULL },
683 /* 158 */ { "Unassigned", opaque, NULL },
684 /* 159 */ { "Unassigned", opaque, NULL },
685 /* 160 */ { "Unassigned", opaque, NULL },
686 /* 161 */ { "Unassigned", opaque, NULL },
687 /* 162 */ { "Unassigned", opaque, NULL },
688 /* 163 */ { "Unassigned", opaque, NULL },
689 /* 164 */ { "Unassigned", opaque, NULL },
690 /* 165 */ { "Unassigned", opaque, NULL },
691 /* 166 */ { "Unassigned", opaque, NULL },
692 /* 167 */ { "Unassigned", opaque, NULL },
693 /* 168 */ { "Unassigned", opaque, NULL },
694 /* 169 */ { "Unassigned", opaque, NULL },
695 /* 170 */ { "Unassigned", opaque, NULL },
696 /* 171 */ { "Unassigned", opaque, NULL },
697 /* 172 */ { "Unassigned", opaque, NULL },
698 /* 173 */ { "Unassigned", opaque, NULL },
699 /* 174 */ { "Unassigned", opaque, NULL },
700 /* 175 */ { "Etherboot", opaque, NULL },
701 /* 176 */ { "IP Telephone", opaque, NULL },
702 /* 177 */ { "Etherboot", opaque, NULL },
703 /* 178 */ { "Unassigned", opaque, NULL },
704 /* 179 */ { "Unassigned", opaque, NULL },
705 /* 180 */ { "Unassigned", opaque, NULL },
706 /* 181 */ { "Unassigned", opaque, NULL },
707 /* 182 */ { "Unassigned", opaque, NULL },
708 /* 183 */ { "Unassigned", opaque, NULL },
709 /* 184 */ { "Unassigned", opaque, NULL },
710 /* 185 */ { "Unassigned", opaque, NULL },
711 /* 186 */ { "Unassigned", opaque, NULL },
712 /* 187 */ { "Unassigned", opaque, NULL },
713 /* 188 */ { "Unassigned", opaque, NULL },
714 /* 189 */ { "Unassigned", opaque, NULL },
715 /* 190 */ { "Unassigned", opaque, NULL },
716 /* 191 */ { "Unassigned", opaque, NULL },
717 /* 192 */ { "Unassigned", opaque, NULL },
718 /* 193 */ { "Unassigned", opaque, NULL },
719 /* 194 */ { "Unassigned", opaque, NULL },
720 /* 195 */ { "Unassigned", opaque, NULL },
721 /* 196 */ { "Unassigned", opaque, NULL },
722 /* 197 */ { "Unassigned", opaque, NULL },
723 /* 198 */ { "Unassigned", opaque, NULL },
724 /* 199 */ { "Unassigned", opaque, NULL },
725 /* 200 */ { "Unassigned", opaque, NULL },
726 /* 201 */ { "Unassigned", opaque, NULL },
727 /* 202 */ { "Unassigned", opaque, NULL },
728 /* 203 */ { "Unassigned", opaque, NULL },
729 /* 204 */ { "Unassigned", opaque, NULL },
730 /* 205 */ { "Unassigned", opaque, NULL },
731 /* 206 */ { "Unassigned", opaque, NULL },
732 /* 207 */ { "Unassigned", opaque, NULL },
733 /* 208 */ { "PXELINUX Magic", opaque, NULL },
734 /* 209 */ { "Configuration file", opaque, NULL },
735 /* 210 */ { "Authentication", special, NULL }, /* Path Prefix rfc5071 */
736 /* 211 */ { "Reboot Time", opaque, NULL },
737 /* 212 */ { "6RD", opaque, NULL },
738 /* 213 */ { "V4 Access Domain", opaque, NULL },
739 /* 214 */ { "Unassigned", opaque, NULL },
740 /* 215 */ { "Unassigned", opaque, NULL },
741 /* 216 */ { "Unassigned", opaque, NULL },
742 /* 217 */ { "Unassigned", opaque, NULL },
743 /* 218 */ { "Unassigned", opaque, NULL },
744 /* 219 */ { "Unassigned", opaque, NULL },
745 /* 220 */ { "Subnet Allocation", opaque, NULL },
746 /* 221 */ { "Virtual Subnet Selection", opaque, NULL },
747 /* 222 */ { "Unassigned", opaque, NULL },
748 /* 223 */ { "Unassigned", opaque, NULL },
749 /* 224 */ { "Private", opaque, NULL },
750 /* 225 */ { "Private", opaque, NULL },
751 /* 226 */ { "Private", opaque, NULL },
752 /* 227 */ { "Private", opaque, NULL },
753 /* 228 */ { "Private", opaque, NULL },
754 /* 229 */ { "Private", opaque, NULL },
755 /* 230 */ { "Private", opaque, NULL },
756 /* 231 */ { "Private", opaque, NULL },
757 /* 232 */ { "Private", opaque, NULL },
758 /* 233 */ { "Private", opaque, NULL },
759 /* 234 */ { "Private", opaque, NULL },
760 /* 235 */ { "Private", opaque, NULL },
761 /* 236 */ { "Private", opaque, NULL },
762 /* 237 */ { "Private", opaque, NULL },
763 /* 238 */ { "Private", opaque, NULL },
764 /* 239 */ { "Private", opaque, NULL },
765 /* 240 */ { "Private", opaque, NULL },
766 /* 241 */ { "Private", opaque, NULL },
767 /* 242 */ { "Private", opaque, NULL },
768 /* 243 */ { "Private", opaque, NULL },
769 /* 244 */ { "Private", opaque, NULL },
770 /* 245 */ { "Private", opaque, NULL },
771 /* 246 */ { "Private", opaque, NULL },
772 /* 247 */ { "Private", opaque, NULL },
773 /* 248 */ { "Private", opaque, NULL },
774 /* 249 */ { "Private/Classless Static Route (Microsoft)", special, NULL },
775 /* 250 */ { "Private", opaque, NULL },
776 /* 251 */ { "Private", opaque, NULL },
777 /* 252 */ { "Private/Proxy autodiscovery", string, NULL },
778 /* 253 */ { "Private", opaque, NULL },
779 /* 254 */ { "Private", opaque, NULL },
780 /* 255 */ { "End", opaque, NULL }
784 bootp_get_opt_text(unsigned int idx)
786 if(idx>=BOOTP_OPT_NUM)
788 return bootp_opt[idx].text;
792 bootp_get_opt_data(unsigned int idx)
794 if(idx>=BOOTP_OPT_NUM)
796 return bootp_opt[idx].data;
799 static enum field_type
800 bootp_get_opt_ftype(unsigned int idx)
802 if(idx>=BOOTP_OPT_NUM)
804 return bootp_opt[idx].ftype;
808 /* Returns the number of bytes consumed by this option. */
810 bootp_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, int voff,
811 int eoff, gboolean first_pass, gboolean *at_end, const char **dhcp_type_p,
812 const guint8 **vendor_class_id_p, guint8 *overload_p)
815 enum field_type ftype;
816 guchar code = tvb_get_guint8(tvb, voff);
818 const struct true_false_string *tfs;
819 const value_string *vs;
822 int optoff, optleft, optend;
825 proto_tree *v_tree, *ft;
831 int o52voff, o52eoff;
835 const guchar *dns_name;
838 static const value_string slpda_vals[] = {
839 {0x00, "Dynamic Discovery" },
840 {0x01, "Static Discovery" },
841 {0x80, "Backwards compatibility" },
844 static const value_string slp_scope_vals[] = {
845 {0x00, "Preferred Scope" },
846 {0x01, "Mandatory Scope" },
849 static const value_string authen_protocol_vals[] = {
850 {AUTHEN_PROTO_CONFIG_TOKEN, "configuration token" },
851 {AUTHEN_PROTO_DELAYED_AUTHEN, "delayed authentication" },
854 static const value_string authen_da_algo_vals[] = {
855 {AUTHEN_DELAYED_ALGO_HMAC_MD5, "HMAC_MD5" },
858 static const value_string authen_rdm_vals[] = {
859 {AUTHEN_RDM_MONOTONIC_COUNTER, "Monotonically-increasing counter" },
862 static const value_string opt_overload_vals[] = {
863 { OPT_OVERLOAD_FILE, "Boot file name holds options", },
864 { OPT_OVERLOAD_SNAME, "Server host name holds options", },
865 { OPT_OVERLOAD_BOTH, "Boot file and server host names hold options" },
868 /* Options whose length isn't "optlen + 2". */
871 case 0: /* Padding */
872 /* check how much padding we have */
873 for (i = voff + 1; i < eoff; i++ ) {
874 if (tvb_get_guint8(tvb, i) != 0) {
880 if (bp_tree != NULL) {
881 proto_tree_add_text(bp_tree, tvb, voff, i,
882 "Padding (%d byte%s)", i, plurality(i, "", "s"));
888 case 255: /* End Option */
890 if (bp_tree != NULL) {
891 proto_tree_add_text(bp_tree, tvb, voff, 1,
892 "End Option%s", *overload_p?" (overload)":"");
901 * Get the length of the option, and the number of bytes it
902 * consumes (the length doesn't include the option code or
905 * On the first pass, check first whether we have the length
906 * byte, so that we don't throw an exception; if we throw an
907 * exception in the first pass, which is only checking for options
908 * whose values we need in order to properly dissect the packet
909 * on the second pass, we won't actually dissect the options, so
910 * you won't be able to see which option had the problem.
913 if (!tvb_bytes_exist(tvb, voff+1, 1)) {
915 * We don't have the length byte; just return 1
916 * as the number of bytes we consumed, to count
922 optlen = tvb_get_guint8(tvb, voff+1);
923 consumed = optlen + 2;
926 * In the first pass, we don't put anything into the protocol
927 * tree; we just check for some options we have to look at
928 * in order to properly process the packet:
930 * 52 (Overload) - we need this to properly dissect the
931 * file and sname fields
933 * 53 (DHCP message type) - if this is present, this is DHCP
935 * 60 (Vendor class identifier) - we need this in order to
936 * interpret the vendor-specific info
938 * We also check, before fetching anything, to make sure we
939 * have the entire item we're fetching, so that we don't throw
943 if (tvb_bytes_exist(tvb, voff+2, consumed-2)) {
947 *overload_p = tvb_get_guint8(tvb, voff+2);
952 val_to_str(tvb_get_guint8(tvb, voff+2),
954 "Unknown Message Type (0x%02x)");
959 tvb_get_ptr(tvb, voff+2, consumed-2);
965 * We don't do anything else here.
971 text = bootp_get_opt_text(code);
972 ftype = bootp_get_opt_ftype(code);
976 vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
977 "Option: (t=%d,l=%d) %s", code, optlen, text);
978 v_tree = proto_item_add_subtree(vti, ett_bootp_option);
979 proto_tree_add_uint_format_value(v_tree, hf_bootp_option_type,
980 tvb, voff, 1, code, "(%d) %s", code, text);
981 proto_tree_add_item(v_tree, hf_bootp_option_length, tvb, voff+1, 1, FALSE);
983 proto_tree_add_item(v_tree, hf_bootp_option_value, tvb, voff+2, optlen, FALSE);
989 case 21: /* Policy Filter */
991 /* one IP address pair */
992 proto_item_append_text(vti, " = %s/%s",
993 ip_to_str(tvb_get_ptr(tvb, optoff, 4)),
994 ip_to_str(tvb_get_ptr(tvb, optoff+4, 4)));
996 /* > 1 IP address pair. Let's make a sub-tree */
997 for (i = optoff, optleft = optlen;
998 optleft > 0; i += 8, optleft -= 8) {
1000 proto_tree_add_text(v_tree, tvb, i, optleft,
1001 "Option length isn't a multiple of 8");
1004 proto_tree_add_text(v_tree, tvb, i, 8, "IP Address/Mask: %s/%s",
1005 ip_to_str(tvb_get_ptr(tvb, i, 4)),
1006 ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
1011 case 33: /* Static Route */
1013 /* one IP address pair */
1014 proto_item_append_text(vti, " = %s/%s",
1015 ip_to_str(tvb_get_ptr(tvb, optoff, 4)),
1016 ip_to_str(tvb_get_ptr(tvb, optoff+4, 4)));
1018 /* > 1 IP address pair. Let's make a sub-tree */
1019 for (i = optoff, optleft = optlen; optleft > 0;
1020 i += 8, optleft -= 8) {
1022 proto_tree_add_text(v_tree, tvb, i, optleft,
1023 "Option length isn't a multiple of 8");
1026 proto_tree_add_text(v_tree, tvb, i, 8,
1027 "Destination IP Address/Router: %s/%s",
1028 ip_to_str(tvb_get_ptr(tvb, i, 4)),
1029 ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
1034 case 43: /* Vendor-Specific Info */
1035 s_option = tvb_get_guint8(tvb, optoff);
1037 /* PXE protocol 2.1 as described in the intel specs */
1038 if (*vendor_class_id_p != NULL &&
1039 strncmp((const gchar*)*vendor_class_id_p, "PXEClient", strlen("PXEClient")) == 0) {
1040 proto_item_append_text(vti, " (PXEClient)");
1041 v_tree = proto_item_add_subtree(vti, ett_bootp_option);
1043 optend = optoff + optlen;
1044 while (optoff < optend) {
1045 optoff = dissect_vendor_pxeclient_suboption(v_tree,
1046 tvb, optoff, optend);
1048 } else if (*vendor_class_id_p != NULL &&
1049 ((strncmp((const gchar*)*vendor_class_id_p, "pktc", strlen("pktc")) == 0) ||
1050 (strncmp((const gchar*)*vendor_class_id_p, "docsis", strlen("docsis")) == 0) ||
1051 (strncmp((const gchar*)*vendor_class_id_p, "OpenCable2.0", strlen("OpenCable2.0")) == 0) ||
1052 (strncmp((const gchar*)*vendor_class_id_p, "CableHome", strlen("CableHome")) == 0))) {
1053 /* CableLabs standard - see www.cablelabs.com/projects */
1054 proto_item_append_text(vti, " (CableLabs)");
1056 optend = optoff + optlen;
1057 while (optoff < optend) {
1058 optoff = dissect_vendor_cablelabs_suboption(v_tree,
1059 tvb, optoff, optend);
1061 } else if (s_option==58 || s_option==64 || s_option==65
1062 || s_option==66 || s_option==67) {
1063 /* Note that this is a rather weak (permissive) heuristic, */
1064 /* but since it comes last, i guess this is ok. */
1065 /* Add any stronger (less permissive) heuristics before this! */
1066 /* Alcatel-Lucent DHCP Extensions */
1067 proto_item_append_text(vti, " (Alcatel-Lucent)");
1068 optend = optoff + optlen;
1069 while (optoff < optend) {
1070 optoff = dissect_vendor_alcatel_suboption(v_tree,
1071 tvb, optoff, optend);
1076 case 52: /* Option Overload */
1078 proto_item_append_text(vti, " length isn't >= 1");
1081 byte = tvb_get_guint8(tvb, optoff);
1082 proto_item_append_text(vti, " = %s",
1083 val_to_str(byte, opt_overload_vals,
1084 "Unknown (0x%02x)"));
1086 /* Just in case we find an option 52 in sname or file */
1087 if (voff > VENDOR_INFO_OFFSET && byte >= 1 && byte <= 3) {
1088 if (byte & OPT_OVERLOAD_FILE) {
1090 oti = proto_tree_add_text (bp_tree, tvb,
1091 FILE_NAME_OFFSET, FILE_NAME_LEN,
1092 "Boot file name option overload");
1093 o52voff = FILE_NAME_OFFSET;
1094 o52eoff = FILE_NAME_OFFSET + FILE_NAME_LEN;
1096 while (o52voff < o52eoff && !o52at_end) {
1097 o52voff += bootp_option(tvb, pinfo, bp_tree, o52voff,
1098 o52eoff, FALSE, &o52at_end,
1099 dhcp_type_p, vendor_class_id_p,
1104 expert_add_info_format(pinfo, oti, PI_PROTOCOL,
1105 PI_ERROR, "file overload end option missing");
1108 if (byte & OPT_OVERLOAD_SNAME) {
1110 oti = proto_tree_add_text (bp_tree, tvb,
1111 SERVER_NAME_OFFSET, SERVER_NAME_LEN,
1112 "Server host name option overload");
1113 o52voff = SERVER_NAME_OFFSET;
1114 o52eoff = SERVER_NAME_OFFSET + SERVER_NAME_LEN;
1116 while (o52voff < o52eoff && !o52at_end) {
1117 o52voff += bootp_option(tvb, pinfo, bp_tree, o52voff,
1118 o52eoff, FALSE, &o52at_end,
1119 dhcp_type_p, vendor_class_id_p,
1124 expert_add_info_format(pinfo, oti, PI_PROTOCOL,
1125 PI_ERROR, "sname overload end option missing");
1128 /* The final end option is not in overload */
1133 case 53: /* DHCP Message Type */
1135 proto_item_append_text(vti, " length isn't 1");
1138 proto_item_append_text(vti, " = DHCP %s",
1139 val_to_str(tvb_get_guint8(tvb, optoff),
1141 "Unknown Message Type (0x%02x)"));
1144 case 55: /* Parameter Request List */
1145 for (i = 0; i < optlen; i++) {
1146 byte = tvb_get_guint8(tvb, optoff+i);
1147 proto_tree_add_text(v_tree, tvb, optoff+i, 1, "%d = %s",
1148 byte, bootp_get_opt_text(byte));
1152 case 60: /* Vendor class identifier */
1154 * XXX - RFC 2132 says this is a string of octets;
1155 * should we check for non-printables?
1157 proto_item_append_text(vti, " = \"%s\"",
1158 tvb_format_stringzpad(tvb, optoff, consumed-2));
1159 if ((tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP10,
1160 (int)strlen(PACKETCABLE_MTA_CAP10)) == 0)
1162 (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP15,
1163 (int)strlen(PACKETCABLE_MTA_CAP15)) == 0)
1165 (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP20,
1166 (int)strlen(PACKETCABLE_MTA_CAP20)) == 0))
1168 dissect_packetcable_mta_cap(v_tree, tvb, optoff, optlen);
1170 if ((tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP11,
1171 (int)strlen(PACKETCABLE_CM_CAP11)) == 0)
1173 (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP20,
1174 (int)strlen(PACKETCABLE_CM_CAP20)) == 0 ))
1176 dissect_docsis_cm_cap(v_tree, tvb, optoff, optlen);
1178 if (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP30,
1179 (int)strlen(PACKETCABLE_CM_CAP30)) == 0 )
1181 proto_tree_add_text(v_tree, tvb, optoff, optlen,
1182 "vendor-class-data: \"%s\"", tvb_format_stringzpad(tvb, optoff, optlen));
1186 case 61: /* Client Identifier */
1188 byte = tvb_get_guint8(tvb, optoff);
1192 /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll
1193 guess that the first is the hwtype, and the last 6
1195 /* See http://www.iana.org/assignments/arp-parameters */
1196 /* RFC2132 9.14 Client-identifier has the following to say:
1197 A hardware type of 0 (zero) should be used when the value
1198 field contains an identifier other than a hardware address
1199 (e.g. a fully qualified domain name). */
1201 if (optlen == 7 && byte > 0 && byte < 48) {
1202 proto_tree_add_text(v_tree, tvb, optoff, 1,
1203 "Hardware type: %s",
1204 arphrdtype_to_str(byte,
1205 "Unknown (0x%02x)"));
1206 if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802)
1207 proto_tree_add_item(v_tree,
1208 hf_bootp_hw_ether_addr, tvb, optoff+1, 6,
1211 proto_tree_add_text(v_tree, tvb, optoff+1, 6,
1212 "Client hardware address: %s",
1213 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+1, 6),
1215 } else if (optlen == 17 && byte == 0) {
1216 /* Identifier is a UUID */
1217 proto_tree_add_item(v_tree, hf_bootp_client_identifier_uuid,
1218 tvb, optoff + 1, 16, TRUE);
1219 /* From RFC 4631 paragraph 6.1 DHCPv4 Client Behavior:
1220 To send an RFC 3315-style binding identifier in a DHCPv4 'client
1221 identifier' option, the type of the 'client identifier' option is set
1223 } else if (byte == 255) {
1229 /* The type field is immediately followed by the IAID, which is
1230 an opaque 32-bit quantity */
1231 proto_tree_add_text(v_tree, tvb, optoff+1, 4,
1233 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+1, 4),
1235 optoff = optoff + 5;
1236 duidtype = tvb_get_ntohs(tvb, optoff);
1237 proto_tree_add_text(v_tree, tvb, optoff, 2,
1238 "DUID type: %s (%u)",
1239 val_to_str(duidtype,
1240 duidtype_vals, "Unknown"),
1245 proto_tree_add_text(v_tree, tvb, optoff,
1246 optlen, "DUID: malformed option");
1249 hwtype=tvb_get_ntohs(tvb, optoff + 2);
1250 proto_tree_add_text(v_tree, tvb, optoff + 2, 2,
1251 "Hardware type: %s (%u)", arphrdtype_to_str(hwtype, "Unknown"),
1253 /* XXX seconds since Jan 1 2000 */
1254 proto_tree_add_text(v_tree, tvb, optoff + 4, 4,
1255 "Time: %u", tvb_get_ntohl(tvb, optoff + 4));
1257 proto_tree_add_text(v_tree, tvb, optoff + 8,
1258 optlen - 13, "Link-layer address: %s",
1259 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+8, optlen-13), optlen-13, hwtype));
1264 proto_tree_add_text(v_tree, tvb, optoff,
1265 optlen, "DUID: malformed option");
1268 enterprise = tvb_get_ntohl(tvb, optoff+2);
1269 proto_tree_add_text(v_tree, tvb, optoff + 2, 4,
1270 "Enterprise-number: %s (%u)",
1271 val_to_str_ext_const( enterprise, &sminmpec_values_ext, "Unknown"),
1274 buf = tvb_bytes_to_str(tvb, optoff + 6, optlen - 11);
1275 proto_tree_add_text(v_tree, tvb, optoff + 6,
1276 optlen - 11, "identifier: %s", buf);
1281 proto_tree_add_text(v_tree, tvb, optoff,
1282 optlen, "DUID: malformed option");
1285 hwtype=tvb_get_ntohs(tvb, optoff + 2);
1286 proto_tree_add_text(v_tree, tvb, optoff + 2, 2,
1287 "Hardware type: %s (%u)",
1288 arphrdtype_to_str(hwtype, "Unknown"),
1291 proto_tree_add_text(v_tree, tvb, optoff + 4,
1292 optlen - 9, "Link-layer address: %s",
1293 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+4, optlen-9), optlen-9, hwtype));
1298 /* otherwise, it's opaque data */
1302 case 97: /* Client Identifier (UUID) */
1304 byte = tvb_get_guint8(tvb, optoff);
1308 /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll
1309 guess that the first is the hwtype, and the last 6
1311 /* See http://www.iana.org/assignments/arp-parameters */
1312 /* RFC2132 9.14 Client-identifier has the following to say:
1313 A hardware type of 0 (zero) should be used when the value
1314 field contains an identifier other than a hardware address
1315 (e.g. a fully qualified domain name). */
1317 if (optlen == 7 && byte > 0 && byte < 48) {
1318 proto_tree_add_text(v_tree, tvb, optoff, 1,
1319 "Hardware type: %s",
1320 arphrdtype_to_str(byte,
1321 "Unknown (0x%02x)"));
1322 if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802)
1323 proto_tree_add_item(v_tree,
1324 hf_bootp_hw_ether_addr, tvb, optoff+1, 6,
1327 proto_tree_add_text(v_tree, tvb, optoff+1, 6,
1328 "Client hardware address: %s",
1329 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+1, 6),
1331 } else if (optlen == 17 && byte == 0) {
1332 /* Identifier is a UUID */
1333 proto_tree_add_item(v_tree, hf_bootp_client_identifier_uuid,
1334 tvb, optoff + 1, 16, TRUE);
1336 /* otherwise, it's opaque data */
1340 case 63: /* NetWare/IP options (RFC 2242) */
1342 optend = optoff + optlen;
1343 while (optoff < optend)
1344 optoff = dissect_netware_ip_suboption(v_tree, tvb, optoff, optend);
1347 case 78: /* SLP Directory Agent Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
1349 proto_item_append_text(vti, " length isn't >= 1");
1353 byte = tvb_get_guint8(tvb, optoff);
1354 proto_item_append_text(vti, " = %s",
1355 val_to_str(byte, slpda_vals,
1356 "Unknown (0x%02x)"));
1365 for (i = optoff; optleft > 0; i += 4, optleft -= 4) {
1367 proto_tree_add_text(v_tree, tvb, i, optleft,
1368 "Option length isn't a multiple of 4");
1371 proto_tree_add_text(v_tree, tvb, i, 4, "SLPDA Address: %s",
1372 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1376 case 79: /* SLP Service Scope Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
1377 byte = tvb_get_guint8(tvb, optoff);
1378 proto_item_append_text(vti, " = %s",
1379 val_to_str(byte, slp_scope_vals,
1380 "Unknown (0x%02x)"));
1382 optleft = optlen - 1;
1383 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1384 "%s = \"%s\"", text,
1385 tvb_format_stringzpad(tvb, optoff, optleft));
1388 case 81: /* Client Fully Qualified Domain Name */
1390 proto_item_append_text(vti, " length isn't >= 3");
1393 fqdn_flags = tvb_get_guint8(tvb, optoff);
1394 ft = proto_tree_add_text(v_tree, tvb, optoff, 1, "Flags: 0x%02x", fqdn_flags);
1395 proto_tree_add_item(v_tree, hf_bootp_fqdn_mbz, tvb, optoff, 1, FALSE);
1396 proto_tree_add_item(v_tree, hf_bootp_fqdn_n, tvb, optoff, 1, FALSE);
1397 proto_tree_add_item(v_tree, hf_bootp_fqdn_e, tvb, optoff, 1, FALSE);
1398 proto_tree_add_item(v_tree, hf_bootp_fqdn_o, tvb, optoff, 1, FALSE);
1399 proto_tree_add_item(v_tree, hf_bootp_fqdn_s, tvb, optoff, 1, FALSE);
1400 /* XXX: use code from packet-dns for return code decoding */
1401 proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode1, tvb, optoff+1, 1, FALSE);
1402 /* XXX: use code from packet-dns for return code decoding */
1403 proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode2, tvb, optoff+2, 1, FALSE);
1405 if (fqdn_flags & F_FQDN_E) {
1406 get_dns_name(tvb, optoff+3, optlen-3, optoff+3, &dns_name);
1407 proto_tree_add_string(v_tree, hf_bootp_fqdn_name,
1408 tvb, optoff+3, optlen-3, dns_name);
1410 proto_tree_add_item(v_tree, hf_bootp_fqdn_asciiname,
1411 tvb, optoff+3, optlen-3, FALSE);
1416 case 82: /* Relay Agent Information Option */
1417 optend = optoff + optlen;
1418 while (optoff < optend)
1419 optoff = bootp_dhcp_decode_agent_info(v_tree, tvb, optoff, optend);
1422 case 85: /* Novell Servers (RFC 2241) */
1423 /* Option 85 can be sent as a string */
1424 /* Added by Greg Morris (gmorris[AT]novell.com) */
1425 if (novell_string) {
1426 proto_item_append_text(vti, " = \"%s\"",
1427 tvb_format_stringzpad(tvb, optoff, optlen));
1430 /* one IP address */
1431 proto_item_append_text(vti, " = %s",
1432 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1434 /* > 1 IP addresses. Let's make a sub-tree */
1435 for (i = optoff, optleft = optlen; optleft > 0;
1436 i += 4, optleft -= 4) {
1438 proto_tree_add_text(v_tree, tvb, i, optleft,
1439 "Option length isn't a multiple of 4");
1442 proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
1443 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1449 case 94: { /* Client network interface identifier */
1452 id_type = tvb_get_guint8(tvb, optoff);
1454 if (id_type == 0x01) {
1455 proto_tree_add_item(v_tree, hf_bootp_client_network_id_major_ver,
1456 tvb, optoff + 1, 1, TRUE);
1457 proto_tree_add_item(v_tree, hf_bootp_client_network_id_minor_ver,
1458 tvb, optoff + 2, 1, TRUE);
1464 case 90: /* DHCP Authentication */
1465 case 210: /* Was this used for authentication at one time? */
1467 proto_item_append_text(vti, " length isn't >= 11");
1471 protocol = tvb_get_guint8(tvb, optoff);
1472 proto_tree_add_text(v_tree, tvb, optoff, 1, "Protocol: %s (%u)",
1473 val_to_str(protocol, authen_protocol_vals, "Unknown"),
1478 algorithm = tvb_get_guint8(tvb, optoff);
1481 case AUTHEN_PROTO_DELAYED_AUTHEN:
1482 proto_tree_add_text(v_tree, tvb, optoff, 1,
1483 "Algorithm: %s (%u)",
1484 val_to_str(algorithm, authen_da_algo_vals, "Unknown"),
1489 proto_tree_add_text(v_tree, tvb, optoff, 1,
1490 "Algorithm: %u", algorithm);
1496 rdm = tvb_get_guint8(tvb, optoff);
1497 proto_tree_add_text(v_tree, tvb, optoff, 1,
1498 "Replay Detection Method: %s (%u)",
1499 val_to_str(rdm, authen_rdm_vals, "Unknown"),
1506 case AUTHEN_RDM_MONOTONIC_COUNTER:
1507 proto_tree_add_text(v_tree, tvb, optoff, 8,
1508 "RDM Replay Detection Value: %" G_GINT64_MODIFIER "x",
1509 tvb_get_ntoh64(tvb, optoff));
1513 proto_tree_add_text(v_tree, tvb, optoff, 8,
1514 "Replay Detection Value: %s",
1515 tvb_bytes_to_str(tvb, optoff, 8));
1523 case AUTHEN_PROTO_DELAYED_AUTHEN:
1524 switch (algorithm) {
1526 case AUTHEN_DELAYED_ALGO_HMAC_MD5:
1527 if (*dhcp_type_p && !strcmp(*dhcp_type_p, OPT53_DISCOVER)) {
1528 /* Discover has no Secret ID nor HMAC MD5 Hash */
1532 proto_item_append_text(vti,
1533 " length isn't >= 31");
1536 proto_tree_add_text(v_tree, tvb, optoff, 4,
1537 "Secret ID: 0x%08x",
1538 tvb_get_ntohl(tvb, optoff));
1541 proto_tree_add_text(v_tree, tvb, optoff, 16,
1542 "HMAC MD5 Hash: %s",
1543 tvb_bytes_to_str(tvb, optoff, 16));
1550 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1551 "Authentication Information: %s",
1552 tvb_bytes_to_str(tvb, optoff, optleft));
1560 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1561 "Authentication Information: %s",
1562 tvb_bytes_to_str(tvb, optoff, optleft));
1567 case 99: /* civic location (RFC 4776) */
1572 proto_tree_add_text(v_tree, tvb, optoff, 1, "What: %d (%s)",
1573 tvb_get_guint8(tvb, optoff), val_to_str(tvb_get_guint8(tvb, optoff),
1574 civic_address_what_values, "Unknown") );
1575 proto_tree_add_text(v_tree, tvb, optoff + 1, 2, "Country: \"%s\"",
1576 tvb_format_text(tvb, optoff + 1, 2) );
1577 optleft = optleft - 3;
1578 optoff = optoff + 3;
1580 while (optleft >= 2)
1582 int catype = tvb_get_guint8(tvb, optoff);
1585 s_option = tvb_get_guint8(tvb, optoff);
1591 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1592 "CAType %d [%s] (l=%d): EMTPY", catype,
1593 val_to_str(catype, civic_address_type_values,
1594 "Unknown"), s_option);
1598 if (optleft >= s_option)
1600 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1601 "CAType %d [%s] (l=%d): \"%s\"", catype,
1602 val_to_str(catype, civic_address_type_values,
1603 "Unknown"), s_option,
1604 tvb_format_text(tvb, optoff, s_option));
1605 optoff = optoff + s_option;
1606 optleft = optleft - s_option;
1611 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1612 "Error with CAType");
1619 case 121: /* Classless Static Route */
1620 case 249: { /* Classless Static Route (Microsoft) */
1621 int mask_width, significant_octets;
1622 optend = optoff + optlen;
1623 /* minimum length is 5 bytes */
1625 proto_item_append_text(vti, " [ERROR: Option length < 5 bytes]");
1628 while (optoff < optend) {
1629 mask_width = tvb_get_guint8(tvb, optoff);
1630 /* mask_width <= 32 */
1631 if (mask_width > 32) {
1632 proto_tree_add_text(v_tree, tvb, optoff,
1634 "Subnet/MaskWidth-Router: [ERROR: Mask width (%d) > 32]",
1638 significant_octets = (mask_width + 7) / 8;
1639 vti = proto_tree_add_text(v_tree, tvb, optoff,
1640 1 + significant_octets + 4,
1641 "Subnet/MaskWidth-Router: ");
1643 /* significant octets + router(4) */
1644 if (optend < optoff + significant_octets + 4) {
1645 proto_item_append_text(vti, "[ERROR: Remaining length (%d) < %d bytes]",
1646 optend - optoff, significant_octets + 4);
1650 proto_item_append_text(vti, "default");
1652 for(i = 0 ; i < significant_octets ; i++) {
1654 proto_item_append_text(vti, ".");
1655 byte = tvb_get_guint8(tvb, optoff++);
1656 proto_item_append_text(vti, "%d", byte);
1658 for(i = significant_octets ; i < 4 ; i++)
1659 proto_item_append_text(vti, ".0");
1660 proto_item_append_text(vti, "/%d", mask_width);
1662 proto_item_append_text(vti, "-%s",
1663 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1669 case 123: /* coordinate based location RFC 3825 */
1672 unsigned char lci[16];
1673 struct rfc3825_location_fixpoint_t location_fp;
1674 struct rfc3825_location_decimal_t location;
1676 for (c=0; c < 16;c++)
1677 lci[c] = (unsigned char) tvb_get_guint8(tvb, optoff + c);
1679 /* convert lci encoding into fixpoint location */
1680 rfc3825_lci_to_fixpoint(lci, &location_fp);
1682 /* convert location from decimal to fixpoint */
1683 i = rfc3825_fixpoint_to_decimal(&location_fp, &location);
1685 if (i != RFC3825_NOERROR) {
1686 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Error: %s", val_to_str(i, rfc3825_error_types, "Unknown"));
1688 proto_tree_add_text(v_tree, tvb, optoff, 5, "Latitude: %15.10f", location.latitude);
1689 proto_tree_add_text(v_tree, tvb, optoff+5, 5, "Longitude: %15.10f", location.longitude);
1690 proto_tree_add_text(v_tree, tvb, optoff, 1, "Latitude resolution: %15.10f", location.latitude_res);
1691 proto_tree_add_text(v_tree, tvb, optoff+5, 1, "Longitude resolution: %15.10f", location.longitude_res);
1692 proto_tree_add_text(v_tree, tvb, optoff+12, 4, "Altitude: %15.10f", location.altitude);
1693 proto_tree_add_text(v_tree, tvb, optoff+10, 2, "Altitude resolution: %15.10f", location.altitude_res);
1694 proto_tree_add_text(v_tree, tvb, optoff+10, 1, "Altitude type: %s (%d)", val_to_str(location.altitude_type, altitude_type_values, "Unknown"), location.altitude_type);
1695 proto_tree_add_text(v_tree, tvb, optoff+15, 1, "Map Datum: %s (%d)", val_to_str(location.datum_type, map_datum_type_values, "Unknown"), location.datum_type);
1697 } else if (optlen == 34) {
1698 s_option = tvb_get_guint8(tvb, optoff);
1699 s_len = tvb_get_guint8(tvb, optoff+1);
1700 if (s_option == 1) {
1701 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Suboption 1: Primary DSS_ID = \"%s\"",
1702 tvb_format_stringzpad(tvb, optoff+2, s_len));
1703 } else if (s_option == 2) {
1704 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Suboption 2: Secondary DSS_ID = \"%s\"",
1705 tvb_format_stringzpad(tvb, optoff+2, s_len));
1707 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Unknown");
1710 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Error: Invalid length of DHCP option!");
1714 case 124: { /* V-I Vendor Class */
1719 /* CableLab specific */
1720 s_option = tvb_get_guint8(tvb, optoff);
1721 proto_tree_add_text(v_tree, tvb, optoff, optlen,
1722 "CableLabs IP addressing mode preference: %s",
1723 val_to_str (s_option, cablelab_ipaddr_mode_vals, "Unknown"));
1727 optend = optoff + optlen;
1730 while (optleft > 0) {
1733 proto_tree_add_text(v_tree, tvb, optoff,
1734 optleft, "Vendor Class: malformed option");
1738 enterprise = tvb_get_ntohl(tvb, optoff);
1740 vti = proto_tree_add_text(v_tree, tvb, optoff, 4,
1741 "Enterprise-number: %s (%u)",
1742 val_to_str_ext_const(enterprise, &sminmpec_values_ext, "Unknown"),
1745 data_len = tvb_get_guint8(tvb, optoff + 4);
1747 proto_tree_add_text(v_tree, tvb, optoff + 4, 1,
1748 "Data len: %d", data_len);
1752 proto_tree_add_text(v_tree, tvb, optoff, data_len,
1753 "Vendor Class data: %s",
1754 tvb_bytes_to_str(tvb, optoff, data_len));
1756 /* look for next enterprise number */
1758 optleft -= data_len;
1763 case 125: { /* V-I Vendor-specific Information */
1766 int s_option_len = 0;
1767 proto_tree *e_tree = 0;
1769 optend = optoff + optlen;
1773 while (optleft > 0) {
1776 proto_tree_add_text(v_tree, tvb, optoff,
1777 optleft, "Vendor-specific Information: malformed option");
1781 enterprise = tvb_get_ntohl(tvb, optoff);
1783 vti = proto_tree_add_text(v_tree, tvb, optoff, 4,
1784 "Enterprise-number: %s (%u)",
1785 val_to_str_ext_const( enterprise, &sminmpec_values_ext, "Unknown"),
1788 s_option_len = tvb_get_guint8(tvb, optoff + 4);
1793 /* Handle DSL Forum TR-111 Option 125 */
1794 switch (enterprise) {
1796 case 3561: /* ADSL Forum */
1797 s_end = optoff + s_option_len;
1798 if ( s_end > optend ) {
1799 proto_tree_add_text(v_tree, tvb, optoff, 1,
1800 "no room left in option for enterprise %u data", enterprise);
1805 e_tree = proto_item_add_subtree(vti, ett_bootp_option);
1806 while (optoff < s_end) {
1808 optoff = dissect_vendor_tr111_suboption(e_tree,
1809 tvb, optoff, s_end);
1812 case 4491: /* CableLab */
1813 s_end = optoff + s_option_len;
1814 if ( s_end > optend ) {
1815 proto_tree_add_text(v_tree, tvb, optoff, 1,
1816 "no room left in option for enterprise %u data", enterprise);
1820 e_tree = proto_item_add_subtree(vti, ett_bootp_option);
1821 while (optoff < s_end) {
1822 optoff = dissect_vendor_cl_suboption(e_tree,
1823 tvb, optoff, s_end);
1827 /* skip over the data and look for next enterprise number */
1828 optoff += s_option_len;
1831 optleft -= s_option_len;
1837 default: /* not special */
1838 /* The PacketCable CCC option number can vary. If this is a CCC option,
1839 handle it as a special.
1841 if (code == pkt_ccc_option) {
1843 proto_item_append_text(vti,
1844 "CableLabs Client Configuration (%d bytes)",
1846 optend = optoff + optlen;
1847 while (optoff < optend) {
1848 switch (pkt_ccc_protocol_version) {
1850 case PACKETCABLE_CCC_I05:
1851 optoff = dissect_packetcable_i05_ccc(v_tree, tvb, optoff, optend);
1853 case PACKETCABLE_CCC_DRAFT5:
1854 case PACKETCABLE_CCC_RFC_3495:
1855 optoff = dissect_packetcable_ietf_ccc(v_tree, tvb, optoff, optend, pkt_ccc_protocol_version);
1857 default: /* XXX Should we do something here? */
1870 proto_item_append_text(vti,
1871 " - length isn't 4");
1874 proto_item_append_text(vti, " = %s",
1875 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1880 /* one IP address */
1881 proto_item_append_text(vti, " = %s",
1882 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1884 /* > 1 IP addresses. Let's make a sub-tree */
1885 for (i = optoff, optleft = optlen; optleft > 0;
1886 i += 4, optleft -= 4) {
1888 proto_tree_add_text(v_tree, tvb, i, voff + consumed - i,
1889 "Option length isn't a multiple of 4");
1892 proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
1893 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1899 /* Fix for non null-terminated string supplied by
1900 * John Lines <John.Lines[AT]aeat.co.uk>
1902 proto_item_append_text(vti, " = \"%s\"",
1903 tvb_format_stringzpad(tvb, optoff, consumed-2));
1908 proto_item_append_text(vti,
1909 " - length isn't 1");
1912 tfs = (const struct true_false_string *) bootp_get_opt_data(code);
1914 i = tvb_get_guint8(tvb, optoff);
1915 if (i != 0 && i != 1) {
1916 proto_item_append_text(vti,
1917 " = Invalid Value %d", i);
1919 proto_item_append_text(vti, " = %s",
1920 i == 0 ? tfs->false_string : tfs->true_string);
1927 proto_item_append_text(vti,
1928 " - length isn't 1");
1931 vs = (const value_string *) bootp_get_opt_data(code);
1932 byte = tvb_get_guint8(tvb, optoff);
1934 proto_item_append_text(vti, " = %s",
1935 val_to_str(byte, vs, "Unknown (%u)"));
1937 proto_item_append_text(vti, " = %u", byte);
1944 proto_item_append_text(vti,
1945 " - length isn't 2");
1949 vs = (const value_string *) bootp_get_opt_data(code);
1950 vd = tvb_get_ntohs(tvb, optoff);
1953 proto_item_append_text(vti, " = %s",
1954 val_to_str(vd, vs, "Unknown (%u)"));
1956 proto_item_append_text(vti, " = %u", vd);
1961 case val_u_short_list:
1964 proto_item_append_text(vti, " = %u",
1965 tvb_get_ntohs(tvb, optoff));
1968 for (i = optoff, optleft = optlen; optleft > 0;
1969 i += 2, optleft -= 2) {
1971 proto_tree_add_text(v_tree, tvb, i, voff + consumed - i,
1972 "Option length isn't a multiple of 2");
1975 proto_tree_add_text(v_tree, tvb, i, 4, "Value: %u",
1976 tvb_get_ntohs(tvb, i));
1983 proto_item_append_text(vti,
1984 " - length isn't 4");
1987 proto_item_append_text(vti, " = %u",
1988 tvb_get_ntohl(tvb, optoff));
1991 case time_in_s_secs:
1993 proto_item_append_text(vti,
1994 " - length isn't 4");
1997 time_s_secs = (gint32) tvb_get_ntohl(tvb, optoff);
1998 proto_item_append_text(vti, " = %s",
1999 time_secs_to_str(time_s_secs));
2002 case time_in_u_secs:
2004 proto_item_append_text(vti,
2005 " - length isn't 4");
2008 time_u_secs = tvb_get_ntohl(tvb, optoff);
2009 proto_item_append_text(vti, " = %s",
2010 ((time_u_secs == 0xffffffff) ?
2012 time_secs_to_str_unsigned(time_u_secs)));
2023 bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
2026 int suboptoff = optoff;
2027 guint8 subopt, vs_opt, vs_len;
2028 int subopt_len, datalen;
2031 proto_tree *subtree = 0;
2032 guint8 tag, tag_len;
2034 subopt = tvb_get_guint8(tvb, optoff);
2037 if (suboptoff >= optend) {
2038 proto_tree_add_text(v_tree, tvb, optoff, 1,
2039 "Suboption %d: no room left in option for suboption length",
2043 subopt_len = tvb_get_guint8(tvb, suboptoff);
2046 if (suboptoff+subopt_len > optend) {
2047 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2048 "Suboption %d: no room left in option for suboption value",
2054 case 1: /* 1 Agent Circuit ID Sub-option [RFC3046] */
2055 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2056 "Agent Circuit ID: %s",
2057 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2060 case 2: /* 2 Agent Remote ID Sub-option [RFC3046] */
2061 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2062 "Agent Remote ID: %s",
2063 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2067 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2069 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2072 case 4: /* 4 DOCSIS Device Class Suboption [RFC3256] */
2073 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2074 "DOCSIS Device Class: %s",
2075 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2078 case 5: /* 5 Link selection Sub-option [RFC3527] */
2079 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2080 "Link selection: %s",
2081 ip_to_str(tvb_get_ptr(tvb, suboptoff, subopt_len)));
2084 case 6: /*Subscriber-ID Suboption [RFC3993] */
2085 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2086 "Subscriber ID: %s",
2087 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2090 case 7: /* 7 RADIUS Attributes Sub-option [RFC4014] */
2091 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2092 "RADIUS Attributes: %s",
2093 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2096 case 8: /* 8 Authentication Suboption [RFC4030] */
2097 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2098 "Authentication: %s",
2099 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2102 case 9: /* Vendor-Specific Information Suboption [RFC 4243] */
2103 while (suboptoff < optend) {
2104 enterprise = tvb_get_ntohl(tvb, suboptoff);
2105 datalen = tvb_get_guint8(tvb, suboptoff+4);
2106 vti = proto_tree_add_text(v_tree, tvb, suboptoff, 4 + datalen + 1,
2107 "Enterprise-number: %s (%u)",
2108 val_to_str_ext_const( enterprise, &sminmpec_values_ext, "Unknown"),
2112 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2113 proto_tree_add_text(subtree, tvb, suboptoff, 1,
2114 "Data Length: %u", datalen);
2117 switch (enterprise) {
2118 case 4491: /* CableLab */
2119 vs_opt = tvb_get_guint8(tvb, suboptoff);
2121 vs_len = tvb_get_guint8(tvb, suboptoff);
2128 tag = tvb_get_guint8(tvb, suboptoff);
2129 tag_len = tvb_get_guint8(tvb, suboptoff+1);
2132 proto_tree_add_text(subtree, tvb, suboptoff, tag_len,
2133 "DOCSIS Version Number %d.%d",
2134 tvb_get_guint8(tvb, suboptoff),
2135 tvb_get_guint8(tvb, suboptoff+1));
2138 proto_tree_add_text(subtree, tvb, suboptoff, tag_len,
2139 "Unknown tag=%u %s (%d byte%s)", tag,
2140 tvb_bytes_to_str(tvb, suboptoff, tag_len),
2141 tag_len, plurality(tag_len, "", "s"));
2142 suboptoff += tag_len;
2145 suboptoff += vs_len;
2150 proto_tree_add_text(subtree, tvb, suboptoff, vs_len,
2151 "Invalid suboption %d (%d byte%s)",
2152 vs_opt, vs_len, plurality(vs_len, "", "s"));
2153 suboptoff += vs_len;
2158 proto_tree_add_text(subtree, tvb, suboptoff, datalen,
2159 "Suboption Data: %s", tvb_bytes_to_str(tvb, suboptoff, datalen));
2160 suboptoff += datalen;
2166 case 10: /* 10 Relay Agent Flags [RFC5010] */
2167 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2169 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2172 case 11: /* Server Identifier Override Suboption [RFC 5107] */
2173 if (subopt_len == 4) {
2174 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2175 "Server ID Override: %s",
2176 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2178 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2179 "Server ID Override: Invalid length (%d instead of 4)",
2185 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2186 "Unknown agent suboption %d (%d bytes)",
2187 subopt, subopt_len);
2190 optoff += (subopt_len + 2);
2195 dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2196 int optoff, int optend)
2198 int suboptoff = optoff;
2202 proto_tree *o43pxeclient_v_tree;
2205 static struct opt_info o43pxeclient_opt[]= {
2206 /* 0 */ {"nop", special, NULL}, /* dummy */
2207 /* 1 */ {"PXE mtftp IP", ipv4_list, NULL},
2208 /* 2 */ {"PXE mtftp client port", val_u_le_short, NULL},
2209 /* 3 */ {"PXE mtftp server port",val_u_le_short, NULL},
2210 /* 4 */ {"PXE mtftp timeout", val_u_byte, NULL},
2211 /* 5 */ {"PXE mtftp delay", val_u_byte, NULL},
2212 /* 6 */ {"PXE discovery control", val_u_byte, NULL},
2214 * Correct: b0 (lsb): disable broadcast discovery
2215 * b1: disable multicast discovery
2216 * b2: only use/accept servers in boot servers
2217 * b3: download bootfile without prompt/menu/disc
2219 /* 7 */ {"PXE multicast address", ipv4_list, NULL},
2220 /* 8 */ {"PXE boot servers", special, NULL},
2221 /* 9 */ {"PXE boot menu", special, NULL},
2222 /* 10 */ {"PXE menu prompt", special, NULL},
2223 /* 11 */ {"PXE multicast address alloc", special, NULL},
2224 /* 12 */ {"PXE credential types", special, NULL},
2225 /* 71 {"PXE boot item", special, NULL}, */
2226 /* 255 {"PXE end options", special, NULL} */
2229 subopt = tvb_get_guint8(tvb, suboptoff);
2233 proto_tree_add_text(v_tree, tvb, optoff, 1, "Padding");
2235 } else if (subopt == 255) { /* End Option */
2236 proto_tree_add_text(v_tree, tvb, optoff, 1, "End PXEClient option");
2237 /* Make sure we skip any junk left this option */
2241 if (suboptoff >= optend) {
2242 proto_tree_add_text(v_tree, tvb, optoff, 1,
2243 "Suboption %d: no room left in option for suboption length",
2247 subopt_len = tvb_get_guint8(tvb, suboptoff);
2250 if (suboptoff+subopt_len > optend) {
2251 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2252 "Suboption %d: no room left in option for suboption value",
2256 if ( subopt == 71 ) { /* 71 {"PXE boot item", special} */
2258 /* I may need to decode that properly one day */
2259 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2260 "Suboption %d: %s (%d byte%s)" ,
2261 subopt, "PXE boot item",
2262 subopt_len, plurality(subopt_len, "", "s"));
2263 } else if ((subopt < 1) || (subopt >= array_length(o43pxeclient_opt))) {
2264 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2265 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
2266 plurality(subopt_len, "", "s"));
2268 switch (o43pxeclient_opt[subopt].ftype) {
2271 /* I may need to decode that properly one day */
2272 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2273 "Suboption %d: %s (%d byte%s)",
2274 subopt, o43pxeclient_opt[subopt].text,
2275 subopt_len, plurality(subopt_len, "", "s"));
2279 if (subopt_len == 4) {
2280 /* one IP address */
2281 proto_tree_add_text(v_tree, tvb, optoff, 6,
2282 "Suboption %d : %s = %s",
2283 subopt, o43pxeclient_opt[subopt].text,
2284 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2286 /* > 1 IP addresses. Let's make a sub-tree */
2287 vti = proto_tree_add_text(v_tree, tvb, optoff,
2288 subopt_len+2, "Suboption %d: %s",
2289 subopt, o43pxeclient_opt[subopt].text);
2290 o43pxeclient_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
2291 for (suboptleft = subopt_len; suboptleft > 0;
2292 suboptoff += 4, suboptleft -= 4) {
2293 if (suboptleft < 4) {
2294 proto_tree_add_text(o43pxeclient_v_tree,
2295 tvb, suboptoff, suboptleft,
2296 "Suboption length isn't a multiple of 4");
2299 proto_tree_add_text(o43pxeclient_v_tree,
2300 tvb, suboptoff, 4, "IP Address: %s",
2301 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2308 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2309 "Suboption %d: %s", subopt, o43pxeclient_opt[subopt].text);
2314 if (subopt_len != 1) {
2315 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2316 "Suboption %d: suboption length isn't 1", subopt);
2319 proto_tree_add_text(v_tree, tvb, optoff, 3, "Suboption %d: %s = %u",
2320 subopt, o43pxeclient_opt[subopt].text,
2321 tvb_get_guint8(tvb, suboptoff));
2324 case val_u_le_short:
2325 if (subopt_len != 2) {
2326 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2327 "Suboption %d: suboption length isn't 2", subopt);
2330 proto_tree_add_text(v_tree, tvb, optoff, 4, "Suboption %d: %s = %u",
2331 subopt, o43pxeclient_opt[subopt].text,
2332 tvb_get_letohs(tvb, suboptoff));
2336 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2340 optoff += (subopt_len + 2);
2344 /* RFC3825Decoder: http://www.enum.at/rfc3825encoder.529.0.html */
2346 rfc3825_lci_to_fixpoint(const unsigned char lci[16], struct rfc3825_location_fixpoint_t *fixpoint)
2348 fixpoint->latitude_res = (lci[0]>>2) & 0x3F; /* make sure that right-shift does not copy sign bit */
2349 if (lci[0] & 2) { /* LSB<<1 contains the sign of the latitude */
2350 /* Latitude is negative, expand two's complement */
2351 fixpoint->latitude = (((gint64)lci[0] & 3)<<32) | ((gint64)lci[1]<<24) |
2352 ((gint64)lci[2]<<16) | ((gint64)lci[3]<<8) |
2353 (gint64)lci[4] | ((gint64)0x3FFFFFFF<<34);
2356 /* Latitude is positive */
2357 fixpoint->latitude = (((gint64)lci[0] & 3)<<32) | ((gint64)lci[1]<<24) |
2358 ((gint64)lci[2]<<16) | ((gint64)lci[3]<<8) |
2361 fixpoint->longitude_res = (lci[5]>>2) & 0x3F; /* make sure that right-shift does not copy sign bit */
2362 if (lci[5] & 2) { /* LSB<<1 contains the sign of the latitude */
2363 /* Longitude is negative, expand two's complement */
2364 fixpoint->longitude = (((gint64)lci[5] & 3)<<32) | ((gint64)lci[6]<<24) |
2365 ((gint64)lci[7]<<16) | ((gint64)lci[8]<<8) |
2366 (gint64)lci[9] | ((gint64)0x3FFFFFFF<<34);
2369 /* Longitude is positive */
2370 fixpoint->longitude = (((gint64)lci[5] & 3)<<32) | ((gint64)lci[6]<<24) |
2371 ((gint64)lci[7]<<16) | ((gint64)lci[8]<<8) |
2374 fixpoint->altitude_type = (lci[10]>>4) & 0x0F; /* make sure that right-shift does not copy sign bit */
2375 fixpoint->altitude_res = ((lci[10] & 0x0F) << 2) | ((lci[11]>>6) & 0x03);
2376 if (lci[11] & 0x20) { /* LSB<<1 contains the sign of the latitude */
2377 /* Altitude is negative, expand two's complement */
2378 fixpoint->altitude = (((gint32)lci[11] & 0x3F)<<24) | ((gint32)lci[12]<<16) |
2379 ((gint32)lci[13]<<8) | ((gint32)lci[14]) |
2383 /* Altitudee is positive */
2384 fixpoint->altitude = (((gint32)lci[11] & 0x3F)<<24) | ((gint32)lci[12]<<16) |
2385 ((gint32)lci[13]<<8) | ((gint32)lci[14]);
2388 fixpoint->datum_type = lci[15];
2392 /* RFC3825Decoder: http://www.enum.at/rfc3825encoder.529.0.html */
2394 rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct rfc3825_location_decimal_t *decimal)
2397 decimal->latitude = (double) fixpoint->latitude / (1 << 25);
2398 if ((decimal->latitude > 90) || (decimal->latitude < -90)) {
2399 return RFC3825_LATITUDE_OUTOFRANGE;
2402 /* Latitude Uncertainty */
2403 if (fixpoint->latitude_res > 34) {
2404 return RFC3825_LATITUDE_UNCERTAINTY_OUTOFRANGE;
2406 if (fixpoint->latitude_res > 8 ) {
2407 decimal->latitude_res = (double) 1 / (1 << (fixpoint->latitude_res - 8));
2409 decimal->latitude_res = 1 << (8 - fixpoint->latitude_res);
2413 decimal->longitude = (double) fixpoint->longitude / (1 << 25);
2414 if ((decimal->longitude > 180) || (decimal->longitude < -180)) {
2415 return RFC3825_LONGITUDE_OUTOFRANGE;
2418 /* Longitude Uncertainty */
2419 if (fixpoint->longitude_res > 34) {
2420 return RFC3825_LONGITUDE_UNCERTAINTY_OUTOFRANGE;
2422 if (fixpoint->longitude_res > 8 ) {
2423 decimal->longitude_res = (double) 1 / (1 << (fixpoint->longitude_res - 8));
2425 decimal->longitude_res = 1 << (8 - fixpoint->longitude_res);
2429 decimal->altitude_type = fixpoint->altitude_type;
2430 decimal->altitude = 0;
2431 decimal->altitude_res = 0;
2433 if (decimal->altitude_type == 0) { /* Unknown */
2434 } else if (decimal->altitude_type == 1) { /* Meters */
2436 decimal->altitude = (double) fixpoint->altitude / (1 << 8);
2437 if ((decimal->altitude > ((gint32) 1<<21)-1) || (decimal->altitude < ((gint32) -(1<<21))))
2438 return RFC3825_ALTITUDE_OUTOFRANGE;
2440 /* Altitude Uncertainty */
2441 if (fixpoint->altitude_res > 30) {
2442 return RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE;
2444 if (fixpoint->altitude_res > 21 ) {
2445 decimal->altitude_res = (double) 1 / (1 << (fixpoint->altitude_res - 21));
2447 decimal->altitude_res = 1 << (21 - fixpoint->altitude_res);
2449 } else if (decimal->altitude_type == 2) { /* Floors */
2451 if ((fixpoint->altitude_res != 30) && (fixpoint->altitude_res != 0)) {
2452 return RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE;
2454 decimal->altitude = (double) fixpoint->altitude / (1 << 8);
2455 } else { /* invalid type */
2456 return RFC3825_ALTITUDE_TYPE_OUTOFRANGE;
2460 decimal->datum_type = 0;
2461 if ((fixpoint->datum_type > 3) || (fixpoint->datum_type < 1)) {
2462 return RFC3825_DATUM_TYPE_OUTOFRANGE;
2464 decimal->datum_type = fixpoint->datum_type;
2466 return RFC3825_NOERROR;
2471 dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2472 int optoff, int optend)
2474 int suboptoff = optoff;
2475 guint8 subopt, byte_val;
2478 static struct opt_info o43cablelabs_opt[]= {
2479 /* 0 */ {"nop", special, NULL}, /* dummy */
2480 /* 1 */ {"Suboption Request List", string, NULL},
2481 /* 2 */ {"Device Type", string, NULL},
2482 /* 3 */ {"eSAFE Types", string, NULL},
2483 /* 4 */ {"Serial Number", string, NULL},
2484 /* 5 */ {"Hardware Version", string, NULL},
2485 /* 6 */ {"Software Version", string, NULL},
2486 /* 7 */ {"Boot ROM version", string, NULL},
2487 /* 8 */ {"Organizationally Unique Identifier", special, NULL},
2488 /* 9 */ {"Model Number", string, NULL},
2489 /* 10 */ {"Vendor Name", string, NULL},
2490 /* *** 11-30: CableHome *** */
2491 /* 11 */ {"Address Realm", special, NULL},
2492 /* 12 */ {"CM/PS System Description", string, NULL},
2493 /* 13 */ {"CM/PS Firmware Revision", string, NULL},
2494 /* 14 */ {"Firewall Policy File Version", string, NULL},
2495 /* 15 */ {"eSafe Config File Devices", string, NULL},
2496 /* 16 */ {"Unassigned (CableHome)", special, NULL},
2497 /* 17 */ {"Unassigned (CableHome)", special, NULL},
2498 /* 18 */ {"Video Security Type", string, NULL},
2499 /* 19 */ {"Unassigned (CableHome)", special, NULL},
2500 /* 20 */ {"Unassigned (CableHome)", special, NULL},
2501 /* 21 */ {"Unassigned (CableHome)", special, NULL},
2502 /* 22 */ {"Unassigned (CableHome)", special, NULL},
2503 /* 23 */ {"Unassigned (CableHome)", special, NULL},
2504 /* 24 */ {"Unassigned (CableHome)", special, NULL},
2505 /* 25 */ {"Unassigned (CableHome)", special, NULL},
2506 /* 26 */ {"Unassigned (CableHome)", special, NULL},
2507 /* 27 */ {"Unassigned (CableHome)", special, NULL},
2508 /* 28 */ {"Unassigned (CableHome)", special, NULL},
2509 /* 29 */ {"Unassigned (CableHome)", special, NULL},
2510 /* 30 */ {"Unassigned (CableHome)", special, NULL},
2511 /* *** 31-50: PacketCable *** */
2512 /* 31 */ {"MTA MAC Address", special, NULL},
2513 /* 32 */ {"Correlation ID", val_u_long, NULL},
2514 /* 33 */ {"Unassigned (PacketCable)", special, NULL},
2515 /* 34 */ {"Unassigned (PacketCable)", special, NULL},
2516 /* 35 */ {"Unassigned (PacketCable)", special, NULL},
2517 /* 36 */ {"Unassigned (PacketCable)", special, NULL},
2518 /* 37 */ {"Unassigned (PacketCable)", special, NULL},
2519 /* 38 */ {"Unassigned (PacketCable)", special, NULL},
2520 /* 39 */ {"Unassigned (PacketCable)", special, NULL},
2521 /* 40 */ {"Unassigned (PacketCable)", special, NULL},
2522 /* 41 */ {"Unassigned (PacketCable)", special, NULL},
2523 /* 42 */ {"Unassigned (PacketCable)", special, NULL},
2524 /* 43 */ {"Unassigned (PacketCable)", special, NULL},
2525 /* 44 */ {"Unassigned (PacketCable)", special, NULL},
2526 /* 45 */ {"Unassigned (PacketCable)", special, NULL},
2527 /* 46 */ {"Unassigned (PacketCable)", special, NULL},
2528 /* 47 */ {"Unassigned (PacketCable)", special, NULL},
2529 /* 48 */ {"Unassigned (PacketCable)", special, NULL},
2530 /* 49 */ {"Unassigned (PacketCable)", special, NULL},
2531 /* 50 */ {"Unassigned (PacketCable)", special, NULL},
2532 /* *** 51-127: CableLabs *** */
2533 /* 51 */ {"Vendor Name", string, NULL},
2534 /* 52 */ {"CableCARD Capability", special, NULL},
2535 /* 53 */ {"Device Identification (CA)", special, NULL},
2536 /* 54 */ {"Device Identification (X.509)", string, NULL},
2537 /* 55 */ {"Unassigned (CableLabs)", special, NULL},
2538 /* *** 128-254: Vendors *** */
2539 /* 128-254 {"Unassigned (Vendors)", special, NULL}, */
2540 /* 255 {"end options", special, NULL} */
2543 static const value_string cablehome_subopt11_vals[] = {
2544 { 1, "PS WAN-Man" },
2545 { 2, "PS WAN-Data" },
2549 subopt = tvb_get_guint8(tvb, suboptoff);
2553 proto_tree_add_text(v_tree, tvb, optoff, 1, "Padding");
2555 } else if (subopt == 255) { /* End Option */
2556 proto_tree_add_text(v_tree, tvb, optoff, 1, "End CableLabs option");
2557 /* Make sure we skip any junk left this option */
2561 if (suboptoff >= optend) {
2562 proto_tree_add_text(v_tree, tvb, optoff, 1,
2563 "Suboption %d: no room left in option for suboption length",
2567 subopt_len = tvb_get_guint8(tvb, suboptoff);
2570 if (suboptoff+subopt_len > optend) {
2571 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2572 "Suboption %d: no room left in option for suboption value",
2576 if ( (subopt < 1 ) || (subopt >= array_length(o43cablelabs_opt)) ) {
2577 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2578 "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len,
2579 plurality(subopt_len, "", "s"));
2581 switch (o43cablelabs_opt[subopt].ftype) {
2584 if ( subopt == 8 ) { /* OUI */
2585 /* CableLabs specs treat 43.8 inconsistently
2586 * as either binary (3b) or string (6b) */
2587 if (subopt_len == 3) {
2588 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2589 "Suboption %d: Organization Unique Identifier = %s", subopt,
2590 bytes_to_str_punct(tvb_get_ptr(tvb, suboptoff, 3), 3, ':'));
2591 } else if (subopt_len == 6) {
2592 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2593 "Suboption %d: Organization Unique Identifier = \"%s\"", subopt,
2594 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2596 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2597 "Suboption %d: suboption length isn't 3 or 6", subopt);
2600 } else if ( subopt == 11 ) { /* Address Realm */
2601 if (subopt_len != 1) {
2602 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2603 "Suboption %d: suboption length isn't 1", subopt);
2606 byte_val = tvb_get_guint8(tvb, suboptoff);
2607 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2608 "Suboption %d: %s = %s (0x%02x)",
2609 subopt, o43cablelabs_opt[subopt].text,
2610 val_to_str(byte_val, cablehome_subopt11_vals, "Unknown"), byte_val);
2611 } else if ( subopt == 31 ) { /* MTA MAC address */
2612 if (subopt_len != 6) {
2613 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2614 "Suboption %d: suboption length isn't 6", subopt);
2617 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2618 "Suboption %d: %s = %s",
2619 subopt, o43cablelabs_opt[subopt].text,
2620 bytes_to_str_punct(tvb_get_ptr(tvb, suboptoff, 6), 6, ':'));
2622 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2623 "Suboption %d: %s (%d byte%s)" ,
2624 subopt, o43cablelabs_opt[subopt].text,
2625 subopt_len, plurality(subopt_len, "", "s"));
2630 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2631 "Suboption %d: %s = \"%s\"", subopt,
2632 o43cablelabs_opt[subopt].text,
2633 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2637 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2638 "Suboption %d: %s = 0x%s", subopt,
2639 o43cablelabs_opt[subopt].text,
2640 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2644 if (subopt_len != 4) {
2645 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2646 "Suboption %d: suboption length isn't 4", subopt);
2649 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2650 "Suboption %d: %s = %u", subopt,
2651 o43cablelabs_opt[subopt].text,
2652 tvb_get_ntohl(tvb, suboptoff));
2656 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2660 optoff += (subopt_len + 2);
2666 dissect_vendor_alcatel_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2667 int optoff, int optend)
2669 int suboptoff = optoff;
2672 proto_tree *subtree;
2675 subopt = tvb_get_guint8(tvb, suboptoff);
2679 proto_tree_add_text(v_tree, tvb, optoff, 1, "Padding");
2681 } else if (subopt == 255) { /* End Option */
2682 proto_tree_add_text(v_tree, tvb, optoff, 1, "End Alcatel-Lucent option");
2683 /* Make sure we skip any junk left this option */
2687 if (suboptoff >= optend) {
2688 proto_tree_add_text(v_tree, tvb, optoff, 1,
2689 "Suboption %d: no room left in option for suboption length",
2693 subopt_len = tvb_get_guint8(tvb, suboptoff);
2696 if (suboptoff+subopt_len > optend) {
2697 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2698 "Suboption %d: no room left in option for suboption value",
2702 if ( subopt == 58 ) { /* 0x3A - Alcatel-Lucent AVA VLAN Id */
2703 if (subopt_len != 2) {
2704 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2705 "Suboption %d: Bad suboption length!", subopt);
2708 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2709 "Alcatel-Lucent-Specific Suboption %d: %s = %u",
2711 tvb_get_ntohs(tvb, optoff+2));
2712 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2713 proto_tree_add_uint(subtree, hf_bootp_alu_vid, tvb, optoff+2, 2,
2714 tvb_get_ntohs(tvb, optoff+2));
2715 } else if ( subopt == 64 ) { /* 0x40 - Alcatel-Lucent TFTP1 */
2716 if (subopt_len != 4) {
2717 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2718 "Suboption %d: Bad suboption length!", subopt);
2721 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2722 "Alcatel-Lucent-Specific Suboption %d: %s = %s",
2723 subopt, "Spatial Redundancy TFTP1",
2724 ip_to_str(tvb_get_ptr(tvb, optoff+2, 4)));
2725 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2726 proto_tree_add_ipv4(subtree, hf_bootp_alu_tftp1, tvb, optoff+2, 4,
2727 tvb_get_ipv4(tvb, optoff+2));
2728 } else if ( subopt == 65 ) { /* 0x41 - Alcatel-Lucent TFTP2 */
2729 if (subopt_len != 4) {
2730 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2731 "Suboption %d: Bad suboption length!", subopt);
2734 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2735 "Alcatel-Lucent-Specific Suboption %d: %s = %s",
2736 subopt, "Spatial Redundancy TFTP2",
2737 ip_to_str(tvb_get_ptr(tvb, optoff+2, 4)));
2738 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2739 proto_tree_add_ipv4(subtree, hf_bootp_alu_tftp2, tvb, optoff+2, 4,
2740 tvb_get_ipv4(tvb, optoff+2));
2741 } else if ( subopt == 66 ) { /* 0x42 - Alcatel-Lucent APPLICATION TYPE */
2742 if (subopt_len != 1) {
2743 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2744 "Suboption %d: Bad suboption length!", subopt);
2747 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2748 "Alcatel-Lucent-Specific Suboption %d: %s = %u",
2749 subopt, "Application Type (0=NOE, 1=SIP)",
2750 tvb_get_guint8(tvb, optoff+2));
2751 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2752 proto_tree_add_uint(subtree, hf_bootp_alu_app_type, tvb, optoff+2, 1,
2753 tvb_get_guint8(tvb, optoff+2));
2754 } else if ( subopt == 67 ) { /* 0x43 - Alcatel-Lucent SIP URL */
2755 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2756 "Alcatel-Lucent-Specific Suboption %d: %s = \"%s\"",
2758 tvb_format_stringzpad(tvb, optoff+2, subopt_len));
2759 subtree = proto_item_add_subtree(vti, ett_bootp_option);
2760 proto_tree_add_item(subtree, hf_bootp_alu_sip_url, tvb, optoff+2, subopt_len,
2763 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2764 "ERROR, please report: Unknown subopt type handler %d", subopt);
2767 optoff += (subopt_len + 2);
2773 dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2774 int optoff, int optend)
2776 int suboptoff = optoff;
2780 const struct true_false_string *tfs;
2782 proto_tree *o63_v_tree;
2785 static struct opt_info o63_opt[]= {
2786 /* 0 */ {"",none,NULL},
2787 /* 1 */ {"NWIP does not exist on subnet",presence,NULL},
2788 /* 2 */ {"NWIP exists in options area",presence,NULL},
2789 /* 3 */ {"NWIP exists in sname/file",presence,NULL},
2790 /* 4 */ {"NWIP exists, but too big",presence,NULL},
2791 /* 5 */ {"Broadcast for nearest Netware server",val_boolean,TFS(&tfs_yes_no)},
2792 /* 6 */ {"Preferred DSS server",ipv4_list,NULL},
2793 /* 7 */ {"Nearest NWIP server",ipv4_list,NULL},
2794 /* 8 */ {"Autoretries",val_u_byte,NULL},
2795 /* 9 */ {"Autoretry delay, secs",val_u_byte,NULL},
2796 /* 10*/ {"Support NetWare/IP v1.1",val_boolean,TFS(&tfs_yes_no)},
2797 /* 11*/ {"Primary DSS",ipv4,NULL}
2800 subopt = tvb_get_guint8(tvb, optoff);
2803 if (suboptoff >= optend) {
2804 proto_tree_add_text(v_tree, tvb, optoff, 1,
2805 "Suboption %d: no room left in option for suboption length",
2809 subopt_len = tvb_get_guint8(tvb, suboptoff);
2812 if (subopt >= array_length(o63_opt)) {
2813 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2, "Unknown suboption %d", subopt);
2815 switch (o63_opt[subopt].ftype) {
2818 if (subopt_len != 0) {
2819 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2820 "Suboption %d: length isn't 0", subopt);
2823 proto_tree_add_text(v_tree, tvb, optoff, 2, "Suboption %d: %s", subopt, o63_opt[subopt].text);
2827 if (subopt_len != 4) {
2828 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2829 "Suboption %d: length isn't 4", subopt);
2832 if (suboptoff+4 > optend) {
2833 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2834 "Suboption %d: no room left in option for suboption value",
2838 proto_tree_add_text(v_tree, tvb, optoff, 6,
2839 "Suboption %d: %s = %s" ,
2840 subopt, o63_opt[subopt].text,
2841 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2845 if (subopt_len == 4) {
2846 /* one IP address */
2847 proto_tree_add_text(v_tree, tvb, optoff, 6,
2848 "Suboption %d : %s = %s",
2849 subopt, o63_opt[subopt].text,
2850 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2852 /* > 1 IP addresses. Let's make a sub-tree */
2853 vti = proto_tree_add_text(v_tree, tvb, optoff,
2854 subopt_len+2, "Suboption %d: %s",
2855 subopt, o63_opt[subopt].text);
2856 o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
2857 for (suboptleft = subopt_len; suboptleft > 0;
2858 suboptoff += 4, suboptleft -= 4) {
2859 if (suboptleft < 4) {
2860 proto_tree_add_text(o63_v_tree,
2861 tvb, suboptoff, suboptleft,
2862 "Suboption length isn't a multiple of 4");
2865 proto_tree_add_text(o63_v_tree, tvb, suboptoff, 4, "IP Address: %s",
2866 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2872 if (subopt_len != 1) {
2873 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2874 "Suboption %d: suboption length isn't 1", subopt);
2877 if (suboptoff+1 > optend) {
2878 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2879 "Suboption %d: no room left in option for suboption value",
2883 tfs = (const struct true_false_string *) o63_opt[subopt].data;
2884 i = tvb_get_guint8(tvb, suboptoff);
2885 if (i != 0 && i != 1) {
2886 proto_tree_add_text(v_tree, tvb, optoff, 3,
2887 "Suboption %d: %s = Invalid Value %d",
2888 subopt, o63_opt[subopt].text, i);
2890 proto_tree_add_text(v_tree, tvb, optoff, 3,
2891 "Suboption %d: %s = %s", subopt,
2892 o63_opt[subopt].text,
2893 i == 0 ? tfs->false_string : tfs->true_string);
2898 if (subopt_len != 1) {
2899 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2900 "Suboption %d: length isn't 1", subopt);
2903 if (suboptoff+1 > optend) {
2904 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2905 "Suboption %d: no room left in option for suboption value",
2909 proto_tree_add_text(v_tree, tvb, optoff, 3, "Suboption %d: %s = %u",
2910 subopt, o63_opt[subopt].text,
2911 tvb_get_guint8(tvb, suboptoff));
2915 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,"Unknown suboption %d", subopt);
2919 optoff += (subopt_len + 2);
2926 dissect_vendor_tr111_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2927 int optoff, int optend)
2929 int suboptoff = optoff;
2933 /* Reference: TR-111 DHCP Option 125 Sub-Option Data Fields
2937 static struct opt_info o125_tr111_opt[]= {
2938 /* 0 */ {"nop", special, NULL}, /* dummy */
2939 /* 1 */ {"DeviceManufacturerOUI", string, NULL},
2940 /* 2 */ {"DeviceSerialNumber", string, NULL},
2941 /* 3 */ {"DeviceProductClass", string, NULL},
2942 /* 4 */ {"GatewayManufacturerOUI", string, NULL},
2943 /* 5 */ {"GatewaySerialNumber", string, NULL},
2944 /* 6 */ {"GatewayProductClass", string, NULL},
2947 subopt = tvb_get_guint8(tvb, suboptoff);
2950 if (suboptoff >= optend) {
2951 proto_tree_add_text(v_tree, tvb, optoff, 1,
2952 "Suboption %d: no room left in option for suboption length",
2956 subopt_len = tvb_get_guint8(tvb, suboptoff);
2959 if (suboptoff+subopt_len > optend) {
2960 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2961 "Suboption %d: no room left in option for suboption value",
2967 if ((subopt < 1) || (subopt >= array_length(o125_tr111_opt))) {
2968 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2969 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
2970 plurality(subopt_len, "", "s"));
2972 switch (o125_tr111_opt[subopt].ftype) {
2975 /* I may need to decode that properly one day */
2976 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2977 "Suboption %d: %s (%d byte%s)",
2978 subopt, o125_tr111_opt[subopt].text,
2979 subopt_len, plurality(subopt_len, "", "s"));
2983 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2984 "Suboption %d: %s = \"%s\"", subopt,
2985 o125_tr111_opt[subopt].text,
2986 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2990 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2994 optoff += (subopt_len + 2);
2999 dissect_vendor_cl_suboption(proto_tree *v_tree, tvbuff_t *tvb,
3000 int optoff, int optend)
3002 int suboptoff = optoff;
3006 proto_tree *subtree;
3009 static struct opt_info o125_cl_opt[]= {
3010 /* 0 */ {"nop", special, NULL}, /* dummy */
3011 /* 1 */ {"Option Request = ", val_u_byte, NULL},
3012 /* 2 */ {"TFTP Server Addresses : ", ipv4_list, NULL},
3013 /* 3 */ {"eRouter Container Option : ", bytes, NULL},
3014 /* 4 */ {"MIB Environment Indicator Option = ", special, NULL},
3015 /* 5 */ {"Modem Capabilities : ", special, NULL},
3018 static const value_string pkt_mib_env_ind_opt_vals[] = {
3019 { 0x00, "Reserved" },
3020 { 0x01, "CableLabs" },
3022 { 0x03, "EuroCableLabs" },
3026 subopt = tvb_get_guint8(tvb, suboptoff);
3029 if (suboptoff >= optend) {
3030 proto_tree_add_text(v_tree, tvb, optoff, 1,
3031 "Suboption %d: no room left in option for suboption length",
3035 subopt_len = tvb_get_guint8(tvb, suboptoff);
3038 if (suboptoff+subopt_len > optend) {
3039 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
3040 "Suboption %d: no room left in option for suboption value",
3045 if ((subopt < 1) || (subopt >= array_length(o125_cl_opt))) {
3046 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3047 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
3048 plurality(subopt_len, "", "s"));
3050 switch (o125_cl_opt[subopt].ftype) {
3053 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3054 "Suboption %d: %s%s (%d byte%s)", subopt,
3055 o125_cl_opt[subopt].text,
3056 tvb_bytes_to_str(tvb, suboptoff, subopt_len),
3057 subopt_len, plurality(subopt_len, "", "s"));
3061 ti = proto_tree_add_text(v_tree, tvb, optoff, 2,
3062 "Suboption %d %s", subopt, o125_cl_opt[subopt].text);
3064 if ((subopt_len % 4) != 0) {
3065 proto_item_append_text(ti,
3066 "Invalid length for suboption %d (%d byte%s)", subopt, subopt_len,
3067 plurality(subopt_len, "", "s"));
3069 subtree = proto_item_add_subtree(ti, ett_bootp_option);
3070 for (i = 0; i < subopt_len; i+=4) {
3071 proto_tree_add_text(subtree, tvb, suboptoff+i, 4, "IP Address: %s",
3072 ip_to_str(tvb_get_ptr(tvb, (suboptoff+i), 4)));
3079 val = tvb_get_guint8(tvb, suboptoff);
3080 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3081 "Suboption %d: %s%s", subopt,
3082 o125_cl_opt[subopt].text,
3083 val_to_str(val, pkt_mib_env_ind_opt_vals, "unknown"));
3086 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3087 "Suboption %d: %s%s (%d byte%s)",
3088 subopt, o125_cl_opt[subopt].text,
3089 tvb_bytes_to_str(tvb, suboptoff, subopt_len),
3090 subopt_len, plurality(subopt_len, "", "s"));
3095 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3096 "Suboption %d: %s\"%s\"", subopt,
3097 o125_cl_opt[subopt].text,
3098 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
3102 val = tvb_get_guint8(tvb, suboptoff);
3103 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3104 "Suboption %d: %s\"%s\"", subopt,
3105 o125_cl_opt[subopt].text,
3106 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
3110 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
3111 "Suboption %d: %s%d", subopt,
3112 o125_cl_opt[subopt].text,
3113 tvb_get_ntohs(tvb, suboptoff));
3117 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
3121 optoff += (subopt_len + 2);
3125 /* PacketCable Multimedia Terminal Adapter device capabilities (option 60).
3126 Ref: PKT-SP-I05-021127 sections 8.2 and 10 */
3128 #define PKT_MDC_TLV_OFF 10
3131 /* These are ASCII-encoded hexadecimal digits. We use the raw hex equivalent for
3133 #define PKT_MDC_VERSION 0x3031 /* "01" */
3134 #define PKT_MDC_TEL_END 0x3032 /* "02" */
3135 #define PKT_MDC_TGT 0x3033 /* "03" */
3136 #define PKT_MDC_HTTP_ACC 0x3034 /* "04" */
3137 #define PKT_MDC_SYSLOG 0x3035 /* "05" */
3138 #define PKT_MDC_NCS 0x3036 /* "06" */
3139 #define PKT_MDC_PRI_LINE 0x3037 /* "07" */
3140 #define PKT_MDC_VENDOR_TLV 0x3038 /* "08" */
3141 #define PKT_MDC_NVRAM_STOR 0x3039 /* "09" */
3142 #define PKT_MDC_PROV_REP 0x3041 /* "0A" */
3143 #define PKT_MDC_PROV_REP_LC 0x3061 /* "0a" */
3144 #define PKT_MDC_SUPP_CODECS 0x3042 /* "0B" */
3145 #define PKT_MDC_SUPP_CODECS_LC 0x3062 /* "0b" */
3146 #define PKT_MDC_SILENCE 0x3043 /* "0C" */
3147 #define PKT_MDC_SILENCE_LC 0x3063 /* "0c" */
3148 #define PKT_MDC_ECHO_CANCEL 0x3044 /* "0D" */
3149 #define PKT_MDC_ECHO_CANCEL_LC 0x3064 /* "0d" */
3150 #define PKT_MDC_RSVP 0x3045 /* "0E" */
3151 #define PKT_MDC_RSVP_LC 0x3065 /* "0e" */
3152 #define PKT_MDC_UGS_AD 0x3046 /* "0F" */
3153 #define PKT_MDC_UGS_AD_LC 0x3066 /* "0f" */
3154 #define PKT_MDC_IF_INDEX 0x3130 /* "10" */
3155 #define PKT_MDC_FLOW_LOG 0x3131 /* "11" */
3156 #define PKT_MDC_PROV_FLOWS 0x3132 /* "12" */
3157 /* PacketCable 1.5: */
3158 #define PKT_MDC_T38_VERSION 0x3133 /* "13" */
3159 #define PKT_MDC_T38_EC 0x3134 /* "14" */
3160 #define PKT_MDC_RFC2833_DTMF 0x3135 /* "15" */
3161 #define PKT_MDC_VOICE_METRICS 0x3136 /* "16" */
3162 #define PKT_MDC_MIBS 0x3137 /* "17" */
3163 #define PKT_MDC_MGPI 0x3138 /* "18" */
3164 #define PKT_MDC_V152 0x3139 /* "19" */
3165 #define PKT_MDC_CBS 0x3141 /* "1A" */
3166 #define PKT_MDC_CBS_LC 0x3161 /* "1a" */
3168 static const value_string pkt_mdc_type_vals[] = {
3169 { PKT_MDC_VERSION, "PacketCable Version" },
3170 { PKT_MDC_TEL_END, "Number Of Telephony Endpoints" },
3171 { PKT_MDC_TGT, "TGT Support" },
3172 { PKT_MDC_HTTP_ACC, "HTTP Download File Access Method Support" },
3173 { PKT_MDC_SYSLOG, "MTA-24 Event SYSLOG Notification Support" },
3174 { PKT_MDC_NCS, "NCS Service Flow Support" },
3175 { PKT_MDC_PRI_LINE, "Primary Line Support" },
3176 { PKT_MDC_VENDOR_TLV, "Vendor Specific TLV Type(s)" },
3177 { PKT_MDC_NVRAM_STOR, "NVRAM Ticket/Session Keys Storage Support" },
3178 { PKT_MDC_PROV_REP, "Provisioning Event Reporting Support" },
3179 { PKT_MDC_PROV_REP_LC, "Provisioning Event Reporting Support" },
3180 { PKT_MDC_SUPP_CODECS, "Supported CODEC(s)" },
3181 { PKT_MDC_SUPP_CODECS_LC, "Supported CODEC(s)" },
3182 { PKT_MDC_SILENCE, "Silence Suppression Support" },
3183 { PKT_MDC_SILENCE_LC, "Silence Suppression Support" },
3184 { PKT_MDC_ECHO_CANCEL, "Echo Cancellation Support" },
3185 { PKT_MDC_ECHO_CANCEL_LC, "Echo Cancellation Support" },
3186 { PKT_MDC_RSVP, "RSVP Support/ Reserved" },
3187 { PKT_MDC_RSVP_LC, "RSVP Support/ Reserved" },
3188 { PKT_MDC_UGS_AD, "UGS-AD Support" },
3189 { PKT_MDC_UGS_AD_LC, "UGS-AD Support" },
3190 { PKT_MDC_IF_INDEX, "MTA's \"ifIndex\" starting number in \"ifTable\"" },
3191 { PKT_MDC_FLOW_LOG, "Provisioning Flow Logging Support" },
3192 { PKT_MDC_PROV_FLOWS, "Supported Provisioning Flows" },
3193 /* PacketCable 1.5: */
3194 { PKT_MDC_T38_VERSION, "T38 Version Support" },
3195 { PKT_MDC_T38_EC, "T38 Error Correction Support" },
3196 { PKT_MDC_RFC2833_DTMF, "RFC 2833 DTMF Support" },
3197 { PKT_MDC_VOICE_METRICS, "Voice Metrics Support" },
3198 { PKT_MDC_MIBS, "MIB Support" },
3199 { PKT_MDC_MGPI, "Multiple Grants Per Interval Support" },
3200 { PKT_MDC_V152, "V.152 Support" },
3201 /* PacketCable 2.0: */
3202 { PKT_MDC_CBS, "Certificate Bootstrapping Support" },
3203 { PKT_MDC_CBS_LC, "Certificate Bootstrapping Support" },
3207 static const value_string pkt_mdc_version_vals[] = {
3208 { 0x3030, "PacketCable 1.0" },
3209 { 0x3031, "PacketCable 1.1/1.5" }, /* 1.5 replaces 1.1-1.3 */
3210 { 0x3032, "PacketCable 2.0" },
3214 static const value_string pkt_mdc_boolean_vals[] = {
3220 static const value_string pkt_mdc_codec_vals[] = {
3221 { 0x3031, "other" }, /* "01" */
3222 { 0x3032, "unknown" },
3223 { 0x3033, "G.729" },
3224 { 0x3034, "reserved" },
3225 { 0x3035, "G.729E" },
3227 { 0x3037, "G.726-32" },
3228 { 0x3038, "G.728" },
3229 { 0x3039, "PCMA" }, /* "09" */
3230 { 0x3041, "G.726-16" }, /* "0A" */
3231 { 0x3042, "G.726-24" },
3232 { 0x3043, "G.726-40" },
3235 { 0x3046, "telephone-event" }, /* "0F" */
3239 static const value_string pkt_mdc_t38_version_vals[] = {
3240 { 0x3030, "Unsupported" },
3241 { 0x3031, "T.38 Version Zero" }, /* default */
3242 { 0x3032, "T.38 Version One" },
3243 { 0x3033, "T.38 Version Two" },
3244 { 0x3035, "T.38 Version Three" },
3248 static const value_string pkt_mdc_t38_ec_vals[] = {
3250 { 0x3031, "Redundancy" }, /* default */
3255 static const value_string pkt_mdc_mib_orgs[] = {
3256 { 0x3030, "CableLabs" },
3258 { 0x3032, "Reserved" },
3259 { 0x3033, "Reserved" },
3260 { 0x3034, "Reserved" },
3261 { 0x3035, "Reserved" },
3262 { 0x3036, "Reserved" },
3263 { 0x3037, "Reserved" },
3264 { 0x3038, "Reserved" },
3265 { 0x3039, "Reserved" },
3269 /* DOCSIS Cable Modem device capabilities (option 60). */
3270 #define DOCS_CM_TLV_OFF 12
3272 #define DOCS_CM_CONCAT_SUP 0x3031 /* "01" */
3273 #define DOCS_CM_DOCSIS_VER 0x3032 /* "02" */
3274 #define DOCS_CM_FRAG_SUP 0x3033 /* "03" */
3275 #define DOCS_CM_PHS_SUP 0x3034 /* "04" */
3276 #define DOCS_CM_IGMP_SUP 0x3035 /* "05" */
3277 #define DOCS_CM_PRIV_SUP 0x3036 /* "06" */
3278 #define DOCS_CM_DSAID_SUP 0x3037 /* "07" */
3279 #define DOCS_CM_USID_SUP 0x3038 /* "08" */
3280 #define DOCS_CM_FILT_SUP 0x3039 /* "09" */
3281 #define DOCS_CM_TET_MI 0x3041 /* "0A" */
3282 #define DOCS_CM_TET_MI_LC 0x3061 /* "0a" */
3283 #define DOCS_CM_TET 0x3042 /* "0B" */
3284 #define DOCS_CM_TET_LC 0x3062 /* "0b" */
3285 #define DOCS_CM_DCC_SUP 0x3043 /* "0C" */
3286 #define DOCS_CM_DCC_SUP_LC 0x3063 /* "0c" */
3287 #define DOCS_CM_IPFILT_SUP 0x3044 /* "0D" */
3288 #define DOCS_CM_IPFILT_SUP_LC 0x3064 /* "0d" */
3289 #define DOCS_CM_LLCFILT_SUP 0x3045 /* "0E" */
3290 #define DOCS_CM_LLCFILT_SUP_LC 0x3065 /* "0e" */
3292 static const value_string docs_cm_type_vals[] = {
3293 { DOCS_CM_CONCAT_SUP, "Concatenation Support" },
3294 { DOCS_CM_DOCSIS_VER, "DOCSIS Version" },
3295 { DOCS_CM_FRAG_SUP, "Fragmentation Support" },
3296 { DOCS_CM_PHS_SUP, "PHS Support" },
3297 { DOCS_CM_IGMP_SUP, "IGMP Support" },
3298 { DOCS_CM_PRIV_SUP, "Privacy Support" },
3299 { DOCS_CM_DSAID_SUP, "Downstream SAID Support" },
3300 { DOCS_CM_USID_SUP, "Upstream SID Support" },
3301 { DOCS_CM_FILT_SUP, "Optional Filtering Support" },
3302 { DOCS_CM_TET_MI, "Transmit Equalizer Taps per Modulation Interval" },
3303 { DOCS_CM_TET_MI_LC, "Transmit Equalizer Taps per Modulation Interval" },
3304 { DOCS_CM_TET, "Number of Transmit Equalizer Taps" },
3305 { DOCS_CM_TET_LC, "Number of Transmit Equalizer Taps" },
3306 { DOCS_CM_DCC_SUP, "DCC Support" },
3307 { DOCS_CM_DCC_SUP_LC, "DCC Support" },
3308 { DOCS_CM_IPFILT_SUP, "IP Filters Support" },
3309 { DOCS_CM_IPFILT_SUP_LC, "IP Filters Support" },
3310 { DOCS_CM_LLCFILT_SUP, "LLC Filters Support" },
3311 { DOCS_CM_LLCFILT_SUP_LC, "LLC Filters Support" },
3315 static const value_string docs_cm_version_vals[] = {
3316 { 0x3030, "DOCSIS 1.0" },
3317 { 0x3031, "DOCSIS 1.1" },
3318 { 0x3032, "DOCSIS 2.0" },
3319 { 0x3033, "DOCSIS 3.0" },
3323 static const value_string docs_cm_privacy_vals[] = {
3324 { 0x3030, "BPI Support" },
3325 { 0x3031, "BPI Plus Support" },
3330 static const value_string pkt_mdc_supp_flow_vals[] = {
3331 { 1 << 0, "Secure Flow (Full Secure Provisioning Flow)" },
3332 { 1 << 1, "Hybrid Flow" },
3333 { 1 << 2, "Basic Flow" },
3337 #define PKT_MDC_MIB_CL 0x3030
3338 static const value_string pkt_mdc_cl_mib_vals[] = {
3339 { 1 << 0, "PacketCable 1.5 MTA MIB" },
3340 { 1 << 1, "PacketCable 1.5 Signaling MIB" },
3341 { 1 << 2, "PacketCable 1.5 Management Event MIB" },
3342 { 1 << 3, "PacketCable 1.5 MTA Extension MIB" },
3343 { 1 << 4, "PacketCable 1.5 Signaling Extension MIB" },
3344 { 1 << 5, "PacketCable 1.5 MEM Extension MIB" },
3345 { 1 << 6, "Reserved" },
3346 { 1 << 7, "Reserved" },
3350 #define PKT_MDC_MIB_IETF 0x3031
3351 static const value_string pkt_mdc_ietf_mib_vals[] = {
3352 { 1 << 0, "IETF MTA MIB" },
3353 { 1 << 1, "IETF Signaling MIB" },
3354 { 1 << 2, "IETF Management Event MIB" },
3355 { 1 << 3, "Reserved" },
3356 { 1 << 4, "Reserved" },
3357 { 1 << 5, "Reserved" },
3358 { 1 << 6, "Reserved" },
3359 { 1 << 7, "Reserved" },
3365 dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
3368 unsigned long flow_val = 0;
3369 int off = PKT_MDC_TLV_OFF + voff;
3370 int subopt_off, max_len;
3371 guint tlv_len, i, mib_val;
3372 guint8 asc_val[3] = " ", flow_val_str[5];
3374 proto_item *ti, *mib_ti;
3375 proto_tree *subtree, *subtree2;
3377 tvb_memcpy (tvb, asc_val, off, 2);
3378 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len > 0xff) {
3379 proto_tree_add_text(v_tree, tvb, off, len - off,
3380 "Bogus length: %s", asc_val);
3383 proto_tree_add_uint_format_value(v_tree, hf_bootp_pkt_mtacap_len, tvb, off, 2,
3384 tlv_len, "%d", tlv_len);
3387 while (off - voff < len) {
3389 raw_val = tvb_get_ntohs (tvb, off);
3392 tvb_memcpy(tvb, asc_val, off + 2, 2);
3393 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1
3394 || tlv_len < 1 || tlv_len > G_MAXUINT16) {
3395 proto_tree_add_text(v_tree, tvb, off, len - off,
3396 "[Bogus length: %s]", asc_val);
3401 ti = proto_tree_add_text(v_tree,
3402 tvb, off, (tlv_len * 2) + 4,
3404 tvb_format_text(tvb, off, 2),
3405 val_to_str(raw_val, pkt_mdc_type_vals, "unknown"));
3408 case PKT_MDC_VERSION:
3409 raw_val = tvb_get_ntohs(tvb, off + 4);
3410 proto_item_append_text(ti,
3412 val_to_str(raw_val, pkt_mdc_version_vals, "Reserved"),
3413 tvb_format_stringzpad(tvb, off + 4, 2) );
3416 case PKT_MDC_TEL_END:
3417 case PKT_MDC_IF_INDEX:
3418 proto_item_append_text(ti,
3420 tvb_format_stringzpad(tvb, off + 4, 2) );
3424 case PKT_MDC_HTTP_ACC:
3425 case PKT_MDC_SYSLOG:
3427 case PKT_MDC_PRI_LINE:
3428 case PKT_MDC_NVRAM_STOR:
3429 case PKT_MDC_PROV_REP:
3430 case PKT_MDC_PROV_REP_LC:
3431 case PKT_MDC_SILENCE:
3432 case PKT_MDC_SILENCE_LC:
3433 case PKT_MDC_ECHO_CANCEL:
3434 case PKT_MDC_ECHO_CANCEL_LC:
3436 case PKT_MDC_RSVP_LC:
3437 case PKT_MDC_UGS_AD:
3438 case PKT_MDC_UGS_AD_LC:
3439 case PKT_MDC_FLOW_LOG:
3440 case PKT_MDC_RFC2833_DTMF:
3441 case PKT_MDC_VOICE_METRICS:
3445 case PKT_MDC_CBS_LC:
3446 raw_val = tvb_get_ntohs(tvb, off + 4);
3447 proto_item_append_text(ti,
3449 val_to_str(raw_val, pkt_mdc_boolean_vals, "unknown"),
3450 tvb_format_stringzpad(tvb, off + 4, 2) );
3453 case PKT_MDC_SUPP_CODECS:
3454 case PKT_MDC_SUPP_CODECS_LC:
3455 for (i = 0; i < tlv_len; i++) {
3456 raw_val = tvb_get_ntohs(tvb, off + 4 + (i * 2) );
3457 proto_item_append_text(ti,
3459 plurality(i + 1, "", ", "),
3460 val_to_str(raw_val, pkt_mdc_codec_vals, "unknown"),
3461 tvb_format_stringzpad(tvb, off + 4 + (i * 2), 2) );
3465 case PKT_MDC_PROV_FLOWS:
3466 tvb_memcpy(tvb, flow_val_str, off + 4, 4);
3467 flow_val_str[4] = '\0';
3468 flow_val = strtoul((gchar*)flow_val_str, NULL, 16);
3469 proto_item_append_text(ti,
3470 "0x%04lx", flow_val);
3473 case PKT_MDC_T38_VERSION:
3474 raw_val = tvb_get_ntohs(tvb, off + 4);
3475 proto_item_append_text(ti,
3477 val_to_str(raw_val, pkt_mdc_t38_version_vals, "unknown"),
3478 tvb_format_stringzpad(tvb, off + 4, 2) );
3481 case PKT_MDC_T38_EC:
3482 raw_val = tvb_get_ntohs(tvb, off + 4);
3483 proto_item_append_text(ti,
3485 val_to_str(raw_val, pkt_mdc_t38_ec_vals, "unknown"),
3486 tvb_format_stringzpad(tvb, off + 4, 2) );
3492 case PKT_MDC_VENDOR_TLV:
3494 proto_item_append_text(ti,
3496 tvb_format_stringzpad(tvb, off + 4, tlv_len * 2) );
3500 subtree = proto_item_add_subtree(ti, ett_bootp_option);
3501 if (raw_val == PKT_MDC_PROV_FLOWS) {
3502 for (i = 0 ; i < 3; i++) {
3503 if (flow_val & pkt_mdc_supp_flow_vals[i].value) {
3504 decode_bitfield_value(bit_fld, flow_val, pkt_mdc_supp_flow_vals[i].value, 16);
3505 proto_tree_add_text(subtree, tvb, off + 4, 4, "%s%s",
3506 bit_fld, pkt_mdc_supp_flow_vals[i].strptr);
3509 } else if (raw_val == PKT_MDC_MIBS) {
3510 /* 17 06 02 00 38 02 01 07 */
3511 subopt_off = off + 4;
3512 max_len = subopt_off + (tlv_len * 2);
3513 while (subopt_off < max_len) {
3514 raw_val = tvb_get_ntohs(tvb, subopt_off);
3515 if (raw_val != 0x3032) { /* We only know how to handle a length of 2 */
3516 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3517 proto_tree_add_text(subtree, tvb, subopt_off, 2,
3518 "[Bogus length: %s]", asc_val);
3523 raw_val = tvb_get_ntohs(tvb, subopt_off);
3524 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3526 mib_ti = proto_tree_add_text(subtree, tvb, subopt_off, 2, "%s (%s)",
3527 val_to_str(raw_val, pkt_mdc_mib_orgs, "Unknown"), asc_val);
3528 if (subopt_off > off + 4 + 2) {
3529 proto_item_append_text(ti, ", ");
3531 proto_item_append_text(ti, "%s", val_to_str(raw_val, pkt_mdc_mib_orgs, "Unknown"));
3534 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3535 if (sscanf((gchar*)asc_val, "%x", &mib_val) != 1) {
3536 proto_tree_add_text(v_tree, tvb, subopt_off, 2,
3537 "[Bogus bitfield: %s]", asc_val);
3542 case PKT_MDC_MIB_CL:
3543 subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option);
3545 for (i = 0; i < 8; i++) {
3546 if (mib_val & pkt_mdc_cl_mib_vals[i].value) {
3547 decode_bitfield_value(bit_fld, mib_val, pkt_mdc_cl_mib_vals[i].value, 8);
3548 proto_tree_add_text(subtree2, tvb, subopt_off, 2,
3549 "%s%s", bit_fld, pkt_mdc_cl_mib_vals[i].strptr);
3554 case PKT_MDC_MIB_IETF:
3555 subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option);
3557 for (i = 0; i < 8; i++) {
3558 if (mib_val & pkt_mdc_ietf_mib_vals[i].value) {
3559 decode_bitfield_value(bit_fld, mib_val, pkt_mdc_ietf_mib_vals[i].value, 8);
3560 proto_tree_add_text(subtree2, tvb, subopt_off, 2,
3561 "%s%s", bit_fld, pkt_mdc_ietf_mib_vals[i].strptr);
3573 off += (tlv_len * 2) + 4;
3579 dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
3581 unsigned long raw_val;
3582 int off = DOCS_CM_TLV_OFF + voff;
3584 guint8 asc_val[4] = " ";
3587 tvb_memcpy (tvb, asc_val, off, 2);
3588 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len < 1) {
3589 proto_tree_add_text(v_tree, tvb, off, len - off,
3590 "Bogus length: %s", asc_val);
3593 proto_tree_add_uint_format_value(v_tree, hf_bootp_docsis_cmcap_len, tvb, off, 2,
3594 tlv_len, "%d", tlv_len);
3597 while (off - voff < len) {
3599 raw_val = tvb_get_ntohs (tvb, off);
3602 tvb_memcpy(tvb, asc_val, off + 2, 2);
3603 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len > 0xff) {
3604 proto_tree_add_text(v_tree, tvb, off, len - off,
3605 "[Bogus length: %s]", asc_val);
3609 ti = proto_tree_add_text(v_tree, tvb, off,
3612 tvb_format_text(tvb, off, 2),
3613 val_to_str(raw_val, docs_cm_type_vals, "unknown"));
3616 case DOCS_CM_CONCAT_SUP:
3617 case DOCS_CM_FRAG_SUP:
3618 case DOCS_CM_PHS_SUP:
3619 case DOCS_CM_IGMP_SUP:
3620 case DOCS_CM_DCC_SUP:
3621 case DOCS_CM_DCC_SUP_LC:
3622 for (i = 0; i < tlv_len; i++) {
3623 raw_val = tvb_get_ntohs(tvb, off + 4 + (i * 2) );
3624 proto_item_append_text(ti,
3626 plurality(i + 1, "", ", "),
3627 val_to_str(raw_val, pkt_mdc_boolean_vals, "unknown"),
3628 tvb_format_text(tvb, off + 4 + (i * 2), 2) );
3632 case DOCS_CM_DOCSIS_VER:
3633 raw_val = tvb_get_ntohs(tvb, off + 4);
3634 proto_item_append_text(ti,
3636 val_to_str(raw_val, docs_cm_version_vals, "Reserved"),
3637 tvb_format_text(tvb, off + 4, 2) );
3640 case DOCS_CM_PRIV_SUP:
3641 raw_val = tvb_get_ntohs(tvb, off + 4);
3642 proto_item_append_text(ti,
3644 val_to_str(raw_val, docs_cm_privacy_vals, "Reserved"),
3645 tvb_format_text(tvb, off + 4, 2) );
3648 case DOCS_CM_DSAID_SUP:
3649 case DOCS_CM_USID_SUP:
3650 case DOCS_CM_TET_MI:
3651 case DOCS_CM_TET_MI_LC:
3653 case DOCS_CM_TET_LC:
3654 tvb_memcpy (tvb, asc_val, off + 4, 2);
3655 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3656 proto_item_append_text(ti,
3660 case DOCS_CM_IPFILT_SUP:
3661 case DOCS_CM_IPFILT_SUP_LC:
3662 case DOCS_CM_LLCFILT_SUP:
3663 case DOCS_CM_LLCFILT_SUP_LC:
3664 tvb_memcpy (tvb, asc_val, off + 4, 4);
3665 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3666 proto_item_append_text(ti,
3670 case DOCS_CM_FILT_SUP:
3671 tvb_memcpy (tvb, asc_val, off + 4, 2);
3672 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3674 proto_item_append_text(ti,
3675 "802.1p filtering");
3676 if (raw_val & 0x02) {
3678 proto_item_append_text(ti, ", ");
3679 proto_item_append_text(ti,
3680 "802.1Q filtering");
3682 if (!(raw_val & 0x03))
3683 proto_item_append_text(ti,
3685 proto_item_append_text(ti,
3686 " (0x%02lx)", raw_val);
3690 off += (tlv_len * 2) + 4;
3696 /* Definitions specific to PKT-SP-PROV-I05-021127 begin with "PKT_CCC_I05".
3697 Definitions specific to IETF draft 5 and RFC 3495 begin with "PKT_CCC_IETF".
3698 Shared definitions begin with "PKT_CCC".
3700 #define PKT_CCC_PRI_DHCP 1
3701 #define PKT_CCC_SEC_DHCP 2
3702 #define PKT_CCC_I05_SNMP 3
3703 #define PKT_CCC_IETF_PROV_SRV 3
3704 #define PKT_CCC_I05_PRI_DNS 4
3705 #define PKT_CCC_IETF_AS_KRB 4
3706 #define PKT_CCC_I05_SEC_DNS 5
3707 #define PKT_CCC_IETF_AP_KRB 5
3708 #define PKT_CCC_KRB_REALM 6
3709 #define PKT_CCC_TGT_FLAG 7
3710 #define PKT_CCC_PROV_TIMER 8
3711 #define PKT_CCC_CMS_FQDN 9
3712 #define PKT_CCC_IETF_SEC_TKT 9
3713 #define PKT_CCC_AS_KRB 10
3714 #define PKT_CCC_AP_KRB 11
3715 #define PKT_CCC_MTA_KRB_CLEAR 12
3717 static const value_string pkt_i05_ccc_opt_vals[] = {
3718 { PKT_CCC_PRI_DHCP, "Primary DHCP Server" },
3719 { PKT_CCC_SEC_DHCP, "Secondary DHCP Server" },
3720 { PKT_CCC_I05_SNMP, "SNMP Entity" },
3721 { PKT_CCC_I05_PRI_DNS, "Primary DNS Server" },
3722 { PKT_CCC_I05_SEC_DNS, "Secondary DNS Server" },
3723 { PKT_CCC_KRB_REALM, "Kerberos Realm" },
3724 { PKT_CCC_TGT_FLAG, "MTA should fetch TGT?" },
3725 { PKT_CCC_PROV_TIMER, "Provisioning Timer" },
3726 { PKT_CCC_CMS_FQDN, "CMS FQDN" },
3727 { PKT_CCC_AS_KRB, "AS-REQ/AS-REP Backoff and Retry" },
3728 { PKT_CCC_AP_KRB, "AP-REQ/AP-REP Backoff and Retry" },
3729 { PKT_CCC_MTA_KRB_CLEAR, "MTA should clear Kerberos tickets?" },
3733 static const value_string pkt_draft5_ccc_opt_vals[] = {
3734 { PKT_CCC_PRI_DHCP, "TSP's Primary DHCP Server" },
3735 { PKT_CCC_SEC_DHCP, "TSP's Secondary DHCP Server" },
3736 { PKT_CCC_IETF_PROV_SRV, "TSP's Provisioning Server" },
3737 { PKT_CCC_IETF_AS_KRB, "TSP's AS-REQ/AS-REP Backoff and Retry" },
3738 { PKT_CCC_IETF_AP_KRB, "TSP's AP-REQ/AP-REP Backoff and Retry" },
3739 { PKT_CCC_KRB_REALM, "TSP's Kerberos Realm Name" },
3740 { PKT_CCC_TGT_FLAG, "TSP's Ticket Granting Server Utilization" },
3741 { PKT_CCC_PROV_TIMER, "TSP's Provisioning Timer Value" },
3742 { PKT_CCC_IETF_SEC_TKT, "PacketCable Security Ticket Control" },
3746 static const value_string pkt_i05_ccc_ticket_ctl_vals[] = {
3747 { 1, "Invalidate Provisioning Application Server's ticket" },
3748 { 2, "Invalidate all CMS Application Server tickets" },
3749 { 3, "Invalidate all Application Server tickets" },
3754 dissect_packetcable_i05_ccc(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
3757 int suboptoff = optoff;
3758 guint8 subopt, subopt_len, fetch_tgt, timer_val, ticket_ctl;
3759 proto_tree *pkt_s_tree;
3762 subopt = tvb_get_guint8(tvb, optoff);
3765 if (suboptoff >= optend) {
3766 proto_tree_add_text(v_tree, tvb, optoff, 1,
3767 "Suboption %d: no room left in option for suboption length",
3771 subopt_len = tvb_get_guint8(tvb, optoff);
3774 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
3775 "Suboption %u: %s: ", subopt,
3776 val_to_str(subopt, pkt_i05_ccc_opt_vals, "unknown/reserved") );
3780 case PKT_CCC_PRI_DHCP: /* String values */
3781 case PKT_CCC_SEC_DHCP:
3782 case PKT_CCC_I05_SNMP:
3783 case PKT_CCC_I05_PRI_DNS:
3784 case PKT_CCC_I05_SEC_DNS:
3785 case PKT_CCC_KRB_REALM:
3786 case PKT_CCC_CMS_FQDN:
3787 proto_item_append_text(vti, "%s (%u byte%s)",
3788 tvb_format_stringzpad(tvb, suboptoff, subopt_len),
3790 plurality(subopt_len, "", "s") );
3791 suboptoff += subopt_len;
3794 case PKT_CCC_TGT_FLAG:
3795 if (suboptoff+1 > optend) {
3796 proto_item_append_text(vti,
3797 "no room left in option for suboption value");
3800 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
3801 proto_item_append_text(vti, "%s (%u byte%s%s)",
3802 fetch_tgt ? "Yes" : "No",
3804 plurality(subopt_len, "", "s"),
3805 subopt_len != 1 ? " [Invalid]" : "");
3806 suboptoff += subopt_len;
3809 case PKT_CCC_PROV_TIMER:
3810 if (suboptoff+1 > optend) {
3811 proto_item_append_text(vti,
3812 "no room left in option for suboption value");
3815 timer_val = tvb_get_guint8(tvb, suboptoff);
3816 proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
3817 timer_val > 30 ? " [Invalid]" : "",
3819 plurality(subopt_len, "", "s"),
3820 subopt_len != 1 ? " [Invalid]" : "");
3821 suboptoff += subopt_len;
3824 case PKT_CCC_AS_KRB:
3825 if (suboptoff+12 > optend) {
3826 proto_item_append_text(vti,
3827 "no room left in option for suboption value");
3830 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3831 plurality(subopt_len, "", "s"),
3832 subopt_len != 12 ? " [Invalid]" : "");
3833 if (subopt_len == 12) {
3834 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3835 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3836 "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u",
3837 tvb_get_ntohl(tvb, suboptoff));
3838 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3839 "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u",
3840 tvb_get_ntohl(tvb, suboptoff + 4));
3841 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3842 "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u",
3843 tvb_get_ntohl(tvb, suboptoff + 8));
3845 suboptoff += subopt_len;
3848 case PKT_CCC_AP_KRB:
3849 if (suboptoff+12 > optend) {
3850 proto_item_append_text(vti,
3851 "no room left in option for suboption value");
3854 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3855 plurality(subopt_len, "", "s"),
3856 subopt_len != 12 ? " [Invalid]" : "");
3857 if (subopt_len == 12) {
3858 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3859 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3860 "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u",
3861 tvb_get_ntohl(tvb, suboptoff));
3862 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3863 "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u",
3864 tvb_get_ntohl(tvb, suboptoff + 4));
3865 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3866 "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u",
3867 tvb_get_ntohl(tvb, suboptoff + 8));
3869 suboptoff += subopt_len;
3872 case PKT_CCC_MTA_KRB_CLEAR:
3873 if (suboptoff+1 > optend) {
3874 proto_item_append_text(vti,
3875 "no room left in option for suboption value");
3878 ticket_ctl = tvb_get_guint8(tvb, suboptoff);
3879 proto_item_append_text(vti, "%s (%u) (%u byte%s%s)",
3880 val_to_str (ticket_ctl, pkt_i05_ccc_ticket_ctl_vals, "unknown/invalid"),
3883 plurality(subopt_len, "", "s"),
3884 subopt_len != 1 ? " [Invalid]" : "");
3885 suboptoff += subopt_len;
3889 suboptoff += subopt_len;
3897 static const value_string sec_tcm_vals[] = {
3898 { 1 << 0, "PacketCable Provisioning Server" },
3899 { 1 << 1, "All PacketCable Call Management Servers" },
3904 dissect_packetcable_ietf_ccc(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
3905 int optend, int revision)
3907 int suboptoff = optoff;
3908 guint8 subopt, subopt_len;
3910 guint8 prov_type, fetch_tgt, timer_val;
3912 proto_tree *pkt_s_tree;
3914 int max_timer_val = 255, i;
3915 const guchar *dns_name;
3918 subopt = tvb_get_guint8(tvb, suboptoff);
3921 if (suboptoff >= optend) {
3922 proto_tree_add_text(v_tree, tvb, optoff, 1,
3923 "Suboption %d: no room left in option for suboption length",
3927 subopt_len = tvb_get_guint8(tvb, suboptoff);
3930 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
3931 "Suboption %u: %s: ", subopt,
3932 val_to_str(subopt, pkt_draft5_ccc_opt_vals, "unknown/reserved") );
3936 case PKT_CCC_PRI_DHCP: /* IPv4 values */
3937 case PKT_CCC_SEC_DHCP:
3938 if (suboptoff+4 > optend) {
3939 proto_item_append_text(vti,
3940 "no room left in option for suboption value");
3943 ipv4addr = tvb_get_ipv4(tvb, suboptoff);
3944 proto_item_append_text(vti, "%s (%u byte%s%s)",
3945 ip_to_str((guint8 *)&ipv4addr),
3947 plurality(subopt_len, "", "s"),
3948 subopt_len != 4 ? " [Invalid]" : "");
3949 suboptoff += subopt_len;
3952 case PKT_CCC_IETF_PROV_SRV:
3953 if (suboptoff+1 > optend) {
3954 proto_item_append_text(vti,
3955 "no room left in option for suboption value");
3958 prov_type = tvb_get_guint8(tvb, suboptoff);
3960 switch (prov_type) {
3963 get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name);
3964 proto_item_append_text(vti, "%s (%u byte%s)", dns_name,
3965 subopt_len - 1, plurality(subopt_len, "", "s") );
3969 if (suboptoff+4 > optend) {
3970 proto_item_append_text(vti,
3971 "no room left in option for suboption value");
3974 ipv4addr = tvb_get_ipv4(tvb, suboptoff);
3975 proto_item_append_text(vti, "%s (%u byte%s%s)",
3976 ip_to_str((guint8 *)&ipv4addr),
3978 plurality(subopt_len, "", "s"),
3979 subopt_len != 5 ? " [Invalid]" : "");
3983 proto_item_append_text(vti, "Invalid type: %u (%u byte%s)",
3986 plurality(subopt_len, "", "s") );
3989 suboptoff += subopt_len - 1;
3992 case PKT_CCC_IETF_AS_KRB:
3993 if (suboptoff+12 > optend) {
3994 proto_item_append_text(vti,
3995 "no room left in option for suboption value");
3998 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3999 plurality(subopt_len, "", "s"),
4000 subopt_len != 12 ? " [Invalid]" : "");
4001 if (subopt_len == 12) {
4002 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
4003 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
4004 "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u",
4005 tvb_get_ntohl(tvb, suboptoff));
4006 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
4007 "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u",
4008 tvb_get_ntohl(tvb, suboptoff + 4));
4009 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
4010 "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u",
4011 tvb_get_ntohl(tvb, suboptoff + 8));
4013 suboptoff += subopt_len;
4016 case PKT_CCC_IETF_AP_KRB:
4017 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
4018 plurality(subopt_len, "", "s"),
4019 subopt_len != 12 ? " [Invalid]" : "");
4020 if (subopt_len == 12) {
4021 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
4022 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
4023 "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u",
4024 tvb_get_ntohl(tvb, suboptoff));
4025 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
4026 "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u",
4027 tvb_get_ntohl(tvb, suboptoff + 4));
4028 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
4029 "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u",
4030 tvb_get_ntohl(tvb, suboptoff + 8));
4032 suboptoff += subopt_len;
4035 case PKT_CCC_KRB_REALM: /* String values */
4036 get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name);
4037 proto_item_append_text(vti, "%s (%u byte%s)", dns_name,
4038 subopt_len, plurality(subopt_len, "", "s") );
4039 suboptoff += subopt_len;
4042 case PKT_CCC_TGT_FLAG:
4043 if (suboptoff+1 > optend) {
4044 proto_item_append_text(vti,
4045 "no room left in option for suboption value");
4048 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
4049 proto_item_append_text(vti, "%s (%u byte%s%s)",
4050 fetch_tgt ? "Yes" : "No",
4052 plurality(subopt_len, "", "s"),
4053 subopt_len != 1 ? " [Invalid]" : "");
4057 case PKT_CCC_PROV_TIMER:
4058 if (suboptoff+1 > optend) {
4059 proto_item_append_text(vti,
4060 "no room left in option for suboption value");
4063 if (revision == PACKETCABLE_CCC_DRAFT5)
4065 timer_val = tvb_get_guint8(tvb, suboptoff);
4066 proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
4067 timer_val > max_timer_val ? " [Invalid]" : "",
4069 plurality(subopt_len, "", "s"),
4070 subopt_len != 1 ? " [Invalid]" : "");
4074 case PKT_CCC_IETF_SEC_TKT:
4075 if (suboptoff+2 > optend) {
4076 proto_item_append_text(vti,
4077 "no room left in option for suboption value");
4080 sec_tcm = tvb_get_ntohs(tvb, suboptoff);
4081 proto_item_append_text(vti, "0x%04x (%u byte%s%s)", sec_tcm, subopt_len,
4082 plurality(subopt_len, "", "s"),
4083 subopt_len != 2 ? " [Invalid]" : "");
4084 if (subopt_len == 2) {
4085 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
4086 for (i = 0; i < 2; i++) {
4087 if (sec_tcm & sec_tcm_vals[i].value) {
4088 decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16);
4089 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%sInvalidate %s",
4090 bit_fld, sec_tcm_vals[i].strptr);
4094 suboptoff += subopt_len;
4098 suboptoff += subopt_len;
4104 #define BOOTREQUEST 1
4107 static const value_string op_vals[] = {
4108 { BOOTREQUEST, "Boot Request" },
4109 { BOOTREPLY, "Boot Reply" },
4114 dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4116 proto_tree *bp_tree;
4118 proto_tree *flag_tree;
4119 proto_item *fi, *hidden_item;
4122 const guint8 *haddr;
4123 int voff, eoff, tmpvoff; /* vendor offset, end offset */
4126 const char *dhcp_type = NULL;
4127 const guint8 *vendor_class_id = NULL;
4128 guint16 flags, secs;
4130 guint8 overload = 0; /* DHCP option overload */
4132 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOOTP");
4134 * In case we throw an exception fetching the opcode, etc.
4136 col_clear(pinfo->cinfo, COL_INFO);
4138 op = tvb_get_guint8(tvb, 0);
4139 htype = tvb_get_guint8(tvb, 1);
4140 hlen = tvb_get_guint8(tvb, 2);
4144 if ((htype == ARPHRD_ETHER || htype == ARPHRD_IEEE802)
4146 if (check_col(pinfo->cinfo, COL_INFO)) {
4147 col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s (%s)",
4148 arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
4150 get_ether_name(tvb_get_ptr(tvb, 28, hlen)));
4154 if (check_col(pinfo->cinfo, COL_INFO)) {
4155 col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s",
4156 arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
4163 col_set_str(pinfo->cinfo, COL_INFO, "Boot Reply");
4167 if (check_col(pinfo->cinfo, COL_INFO))
4168 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BOOTP message type (%u)", op);
4172 voff = VENDOR_INFO_OFFSET;
4174 /* rfc2132 says it SHOULD exist, not that it MUST exist */
4175 if (tvb_bytes_exist(tvb, voff, 4) &&
4176 (tvb_get_ntohl(tvb, voff) == 0x63825363)) {
4181 eoff = tvb_reported_length(tvb);
4184 * In the first pass, we just look for the DHCP message type
4185 * and Vendor class identifier options.
4189 while (tmpvoff < eoff && !at_end) {
4190 offset_delta = bootp_option(tvb, pinfo, 0, tmpvoff, eoff, TRUE, &at_end,
4191 &dhcp_type, &vendor_class_id, &overload);
4192 if (offset_delta <= 0) {
4193 THROW(ReportedBoundsError);
4195 tmpvoff += offset_delta;
4199 * If there was a DHCP message type option, flag this packet
4202 if (dhcp_type != NULL) {
4204 * Yes, this is a DHCP packet, and "dhcp_type" is the
4207 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCP");
4208 if (check_col(pinfo->cinfo, COL_INFO))
4209 col_add_fstr(pinfo->cinfo, COL_INFO, "DHCP %-8s - Transaction ID 0x%x",
4210 dhcp_type, tvb_get_ntohl(tvb, 4));
4211 tap_queue_packet( bootp_dhcp_tap, pinfo, dhcp_type);
4215 * OK, now build the protocol tree.
4218 ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, FALSE);
4219 bp_tree = proto_item_add_subtree(ti, ett_bootp);
4221 proto_tree_add_uint(bp_tree, hf_bootp_type, tvb,
4224 proto_tree_add_uint_format_value(bp_tree, hf_bootp_hw_type, tvb,
4228 arphrdtype_to_str(htype,
4229 "Unknown (0x%02x)"));
4230 proto_tree_add_uint(bp_tree, hf_bootp_hw_len, tvb,
4232 proto_tree_add_item(bp_tree, hf_bootp_hops, tvb,
4234 proto_tree_add_item(bp_tree, hf_bootp_id, tvb,
4237 * Windows (98, XP and Vista tested) sends the "secs" value on
4238 * the wire formatted as little-endian. See if the LE value
4241 secs = tvb_get_letohs(tvb, 8);
4242 if (secs > 0 && secs <= 0xff) {
4243 ti = proto_tree_add_uint_format_value(bp_tree, hf_bootp_secs, tvb,
4244 8, 2, secs, "%u", secs);
4245 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_NOTE,
4246 "Seconds elapsed (%u) appears to be encoded as little-endian", secs);
4248 proto_tree_add_item(bp_tree, hf_bootp_secs, tvb,
4251 flags = tvb_get_ntohs(tvb, 10);
4252 fi = proto_tree_add_uint(bp_tree, hf_bootp_flags, tvb,
4254 proto_item_append_text(fi, " (%s)",
4255 (flags & BOOTP_BC) ? "Broadcast" : "Unicast");
4256 flag_tree = proto_item_add_subtree(fi, ett_bootp_flags);
4257 proto_tree_add_boolean(flag_tree, hf_bootp_flags_broadcast, tvb,
4259 proto_tree_add_uint(flag_tree, hf_bootp_flags_reserved, tvb,
4261 proto_tree_add_item(bp_tree, hf_bootp_ip_client, tvb,
4263 proto_tree_add_item(bp_tree, hf_bootp_ip_your, tvb,
4265 proto_tree_add_item(bp_tree, hf_bootp_ip_server, tvb,
4267 proto_tree_add_item(bp_tree, hf_bootp_ip_relay, tvb,
4270 if (hlen > 0 && hlen <= 16) {
4271 haddr = tvb_get_ptr(tvb, 28, hlen);
4272 if ((htype == ARPHRD_ETHER || htype == ARPHRD_IEEE802)
4274 proto_tree_add_item(bp_tree, hf_bootp_hw_ether_addr, tvb, 28, 6, FALSE);
4276 /* The chaddr element is 16 bytes in length,
4277 although only the first hlen bytes are used */
4278 proto_tree_add_bytes_format_value(bp_tree, hf_bootp_hw_addr, tvb, 28, 16,
4280 "%s", arphrdaddr_to_str(haddr, hlen, htype));
4281 if ((16 - hlen) > 0)
4282 proto_tree_add_item(bp_tree, hf_bootp_hw_addr_padding, tvb, 28+hlen, 16-hlen, FALSE);
4284 proto_tree_add_text(bp_tree, tvb,
4285 28, 16, "Client address not given");
4288 if (overload & OPT_OVERLOAD_SNAME) {
4289 proto_tree_add_text (bp_tree, tvb,
4290 SERVER_NAME_OFFSET, SERVER_NAME_LEN,
4291 "Server name option overloaded by DHCP");
4293 /* The server host name is optional */
4294 if (tvb_get_guint8(tvb, SERVER_NAME_OFFSET) != '\0') {
4295 proto_tree_add_item(bp_tree, hf_bootp_server, tvb,
4297 SERVER_NAME_LEN, FALSE);
4300 proto_tree_add_string_format(bp_tree, hf_bootp_server, tvb,
4303 "", "Server host name not given");
4307 if (overload & OPT_OVERLOAD_FILE) {
4308 proto_tree_add_text (bp_tree, tvb,
4309 FILE_NAME_OFFSET, FILE_NAME_LEN,
4310 "Boot file name option overloaded by DHCP");
4312 /* Boot file is optional */
4313 if (tvb_get_guint8(tvb, FILE_NAME_OFFSET) != '\0') {
4314 proto_tree_add_item(bp_tree, hf_bootp_file, tvb,
4316 FILE_NAME_LEN, FALSE);
4318 proto_tree_add_string_format(bp_tree, hf_bootp_file, tvb,
4321 "", "Boot file name not given");
4325 voff = VENDOR_INFO_OFFSET;
4326 if (dhcp_type != NULL) {
4327 hidden_item = proto_tree_add_boolean(bp_tree, hf_bootp_dhcp, tvb, 0, 0, 1);
4328 PROTO_ITEM_SET_HIDDEN(hidden_item);
4330 if (tvb_bytes_exist(tvb, voff, 4) &&
4331 (tvb_get_ntohl(tvb, voff) == 0x63825363)) {
4332 ip_addr = tvb_get_ipv4(tvb, voff);
4333 proto_tree_add_ipv4_format_value(bp_tree, hf_bootp_cookie, tvb,
4334 voff, 4, ip_addr, "DHCP");
4337 proto_tree_add_text(bp_tree, tvb,
4338 voff, 64, "Bootp vendor specific options");
4343 while (voff < eoff && !at_end) {
4344 offset_delta = bootp_option(tvb, pinfo, bp_tree, voff, eoff, FALSE, &at_end,
4345 &dhcp_type, &vendor_class_id, &overload);
4346 if (offset_delta <= 0) {
4347 THROW(ReportedBoundsError);
4349 voff += offset_delta;
4351 if ((dhcp_type != NULL) && (!at_end))
4353 expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_ERROR, "End option missing");
4357 * Padding after the end option.
4359 proto_tree_add_text(bp_tree, tvb, voff, eoff - voff, "Padding");
4364 bootp_init_protocol(void)
4366 gchar **optionstrings = NULL;
4367 gchar **optiondetail = NULL;
4371 /* first copy default_bootp_opt[] to bootp_opt[]. This resets all values to default */
4372 for(i=0; i<BOOTP_OPT_NUM; i++)
4374 bootp_opt[i].text = default_bootp_opt[i].text;
4375 bootp_opt[i].ftype = default_bootp_opt[i].ftype;
4376 bootp_opt[i].data = default_bootp_opt[i].data;
4379 /* now split semicolon seperated fields groups */
4380 optionstrings = ep_strsplit(pref_optionstring, ";", -1);
4381 for (i=0;optionstrings[i]!=NULL;i++)
4383 /* input string should have 3 fields:
4384 1 - bootp option - uint8 1-254, not being a special
4385 2 - option name - string
4386 3 - option type - defined in enum represented as a string
4389 /* now split field groups to usable data */
4390 optiondetail = ep_strsplit(optionstrings[i], ",",-1);
4391 /* verify array has 3 or more entries, any entries beyond 3 are ingnored */
4392 for(ii=0;(optiondetail[ii]!=NULL);ii++)
4396 if (ii < 3) continue; /* not enough values. Go again */
4397 ii = atoi(optiondetail[0]); /* get the bootp option number */
4398 if (ii==0 || ii>=BOOTP_OPT_NUM-1) continue; /* not a number or out of range. Go again */
4399 if (bootp_opt[ii].ftype == special) continue; /* don't mess with specials. Go again */
4400 bootp_opt[ii].text = se_strdup(optiondetail[1]); /* store a permanent ("seasonal") copy */
4401 type = optiondetail[2]; /* A string to be converted to an ftype enum */
4402 /* XXX This if statement could be extended to allow for additinonal types */
4403 if (g_ascii_strcasecmp(type,"string") == 0)
4405 bootp_opt[ii].ftype = string;
4406 } else if (g_ascii_strcasecmp(type,"ipv4") == 0)
4408 bootp_opt[ii].ftype = ipv4;
4409 } else if (g_ascii_strcasecmp(type,"bytes") == 0)
4411 bootp_opt[ii].ftype = bytes;
4414 bootp_opt[ii].ftype = opaque;
4420 proto_register_bootp(void)
4422 static hf_register_info hf[] = {
4424 { "Frame is DHCP", "bootp.dhcp", FT_BOOLEAN,
4425 BASE_NONE, NULL, 0x0,
4429 { "Message type", "bootp.type", FT_UINT8,
4430 BASE_DEC, VALS(op_vals), 0x0,
4433 { &hf_bootp_hw_type,
4434 { "Hardware type", "bootp.hw.type", FT_UINT8,
4435 BASE_HEX, NULL, 0x0,
4439 { "Hardware address length", "bootp.hw.len", FT_UINT8,
4440 BASE_DEC, NULL, 0x0,
4444 { "Hops", "bootp.hops", FT_UINT8,
4445 BASE_DEC, NULL, 0x0,
4449 { "Transaction ID", "bootp.id", FT_UINT32,
4450 BASE_HEX, NULL, 0x0,
4454 { "Seconds elapsed", "bootp.secs", FT_UINT16,
4455 BASE_DEC, NULL, 0x0,
4459 { "Bootp flags", "bootp.flags", FT_UINT16,
4460 BASE_HEX, NULL, 0x0,
4463 { &hf_bootp_flags_broadcast,
4464 { "Broadcast flag", "bootp.flags.bc", FT_BOOLEAN,
4465 16, TFS(&flag_set_broadcast), BOOTP_BC,
4468 { &hf_bootp_flags_reserved,
4469 { "Reserved flags", "bootp.flags.reserved", FT_UINT16,
4470 BASE_HEX, NULL, BOOTP_MBZ,
4473 { &hf_bootp_ip_client,
4474 { "Client IP address", "bootp.ip.client",FT_IPv4,
4475 BASE_NONE, NULL, 0x0,
4478 { &hf_bootp_ip_your,
4479 { "Your (client) IP address", "bootp.ip.your", FT_IPv4,
4480 BASE_NONE, NULL, 0x0,
4483 { &hf_bootp_ip_server,
4484 { "Next server IP address", "bootp.ip.server",FT_IPv4,
4485 BASE_NONE, NULL, 0x0,
4488 { &hf_bootp_ip_relay,
4489 { "Relay agent IP address", "bootp.ip.relay", FT_IPv4,
4490 BASE_NONE, NULL, 0x0,
4493 { &hf_bootp_hw_addr,
4494 { "Client hardware address", "bootp.hw.addr", FT_BYTES,
4495 BASE_NONE, NULL, 0x0,
4498 { &hf_bootp_hw_addr_padding,
4499 { "Client hardware address padding", "bootp.hw.addr_padding", FT_BYTES,
4500 BASE_NONE, NULL, 0x0,
4503 { &hf_bootp_hw_ether_addr,
4504 { "Client MAC address", "bootp.hw.mac_addr", FT_ETHER,
4505 BASE_NONE, NULL, 0x0,
4509 { "Server host name", "bootp.server", FT_STRING,
4510 BASE_NONE, NULL, 0x0,
4514 { "Boot file name", "bootp.file", FT_STRING,
4515 BASE_NONE, NULL, 0x0,
4519 { "Magic cookie", "bootp.cookie", FT_IPv4,
4520 BASE_NONE, NULL, 0x0,
4524 { "Bootp Vendor Options", "bootp.vendor", FT_BYTES,
4525 BASE_NONE, NULL, 0x0,
4529 { "Server", "bootp.fqdn.s", FT_BOOLEAN,
4530 8, TFS(&tfs_fqdn_s), F_FQDN_S,
4531 "If true, server should do DDNS update", HFILL }},
4534 { "Server overrides", "bootp.fqdn.o", FT_BOOLEAN,
4535 8, TFS(&tfs_fqdn_o), F_FQDN_O,
4536 "If true, server insists on doing DDNS update", HFILL }},
4539 { "Encoding", "bootp.fqdn.e", FT_BOOLEAN,
4540 8, TFS(&tfs_fqdn_e), F_FQDN_E,
4541 "If true, name is binary encoded", HFILL }},
4544 { "Server DDNS", "bootp.fqdn.n", FT_BOOLEAN,
4545 8, TFS(&tfs_fqdn_n), F_FQDN_N,
4546 "If true, server should not do any DDNS updates", HFILL }},
4548 { &hf_bootp_fqdn_mbz,
4549 { "Reserved flags", "bootp.fqdn.mbz",FT_UINT8,
4550 BASE_HEX, NULL, F_FQDN_MBZ,
4553 { &hf_bootp_fqdn_rcode1,
4554 { "A-RR result", "bootp.fqdn.rcode1", FT_UINT8,
4555 BASE_DEC, NULL, 0x0,
4556 "Result code of A-RR update", HFILL }},
4558 { &hf_bootp_fqdn_rcode2,
4559 { "PTR-RR result", "bootp.fqdn.rcode2", FT_UINT8,
4560 BASE_DEC, NULL, 0x0,
4561 "Result code of PTR-RR update", HFILL }},
4563 { &hf_bootp_fqdn_name,
4564 { "Client name", "bootp.fqdn.name", FT_STRING,
4565 BASE_NONE, NULL, 0x0,
4566 "Name to register via DDNS", HFILL }},
4568 { &hf_bootp_fqdn_asciiname,
4569 { "Client name", "bootp.fqdn.name", FT_STRING,
4570 BASE_NONE, NULL, 0x0,
4571 "Name to register via DDNS", HFILL }},
4573 { &hf_bootp_pkt_mtacap_len,
4574 { "MTA DC Length", "bootp.vendor.pktc.mtacap_len", FT_UINT8,
4575 BASE_DEC, NULL, 0x0,
4576 "PacketCable MTA Device Capabilities Length", HFILL }},
4578 { &hf_bootp_docsis_cmcap_len,
4579 { "CM DC Length", "bootp.vendor.docsis.cmcap_len", FT_UINT8,
4580 BASE_DEC, NULL, 0x0,
4581 "DOCSIS Cable Modem Device Capabilities Length", HFILL }},
4583 { &hf_bootp_alu_vid,
4584 { "Voice VLAN ID", "bootp.vendor.alu.vid", FT_UINT16,
4585 BASE_DEC, NULL, 0x0,
4588 { &hf_bootp_alu_tftp1,
4589 { "Spatial Redundancy TFTP1", "bootp.vendor.alu.tftp1", FT_IPv4,
4590 BASE_NONE, NULL, 0x0,
4593 { &hf_bootp_alu_tftp2,
4594 { "Spatial Redundancy TFTP2", "bootp.vendor.alu.tftp2", FT_IPv4,
4595 BASE_NONE, NULL, 0x0,
4598 { &hf_bootp_alu_app_type,
4599 { "Application Type", "bootp.vendor.alu.app_type", FT_UINT8,
4600 BASE_DEC, NULL, 0x0,
4603 { &hf_bootp_alu_sip_url,
4604 { "SIP URL", "bootp.vendor.alu.sip_url", FT_STRING,
4605 BASE_NONE, NULL, 0x0,
4608 { &hf_bootp_client_identifier_uuid,
4609 { "Client Identifier (UUID)", "bootp.client_id_uuid", FT_GUID,
4610 BASE_NONE, NULL, 0x0,
4611 "Client Machine Identifier (UUID)", HFILL }},
4613 { &hf_bootp_client_network_id_major_ver,
4614 { "Client Network ID Major Version", "bootp.client_network_id_major", FT_UINT8,
4615 BASE_DEC, NULL, 0x0,
4616 "Client Machine Identifier, Major Version", HFILL }},
4618 { &hf_bootp_client_network_id_minor_ver,
4619 { "Client Network ID Minor Version", "bootp.client_network_id_minor", FT_UINT8,
4620 BASE_DEC, NULL, 0x0,
4621 "Client Machine Identifier, Major Version", HFILL }},
4623 { &hf_bootp_option_type,
4624 { "Option", "bootp.option.type", FT_UINT8,
4625 BASE_DEC, NULL, 0x0,
4626 "Bootp/Dhcp option type", HFILL }},
4628 { &hf_bootp_option_length,
4629 { "Length", "bootp.option.length", FT_UINT8,
4630 BASE_DEC, NULL, 0x0,
4631 "Bootp/Dhcp option length", HFILL }},
4633 { &hf_bootp_option_value,
4634 { "Value", "bootp.option.value", FT_BYTES,
4635 BASE_NONE, NULL, 0x0,
4636 "Bootp/Dhcp option value", HFILL }},
4640 static gint *ett[] = {
4647 module_t *bootp_module;
4649 proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP",
4651 proto_register_field_array(proto_bootp, hf, array_length(hf));
4652 proto_register_subtree_array(ett, array_length(ett));
4653 bootp_dhcp_tap = register_tap("bootp");
4655 /* register init routine to setup the custom bootp options */
4656 register_init_routine(&bootp_init_protocol);
4658 /* Allow dissector to find be found by name. */
4659 register_dissector("bootp", dissect_bootp, proto_bootp);
4661 bootp_module = prefs_register_protocol(proto_bootp, NULL);
4663 prefs_register_bool_preference(bootp_module, "novellserverstring",
4664 "Decode Option 85 as String",
4665 "Novell Servers option 85 can be configured as a string instead of address",
4668 prefs_register_enum_preference(bootp_module, "pkt.ccc.protocol_version",
4669 "PacketCable CCC protocol version",
4670 "The PacketCable CCC protocol version",
4671 &pkt_ccc_protocol_version,
4672 pkt_ccc_protocol_versions,
4675 prefs_register_uint_preference(bootp_module, "pkt.ccc.option",
4676 "PacketCable CCC option",
4677 "Option Number for PacketCable CableLabs Client Configuration",
4681 prefs_register_string_preference(bootp_module, "displayasstring",
4682 "Custom BootP/DHCP Options (Excl. suboptions)",
4683 "Format: OptionNumber,OptionName,OptionType[;Format].\n"
4684 "Example: 176,MyOption,string;242,NewOption,ipv4.\n"
4685 "OptionNumbers: 1-254, but no special options. "
4686 "OptionType: string, ipv4 and bytes",
4687 &pref_optionstring );
4691 proto_reg_handoff_bootp(void)
4693 dissector_handle_t bootp_handle;
4695 bootp_handle = create_dissector_handle(dissect_bootp, proto_bootp);
4696 dissector_add("udp.port", UDP_PORT_BOOTPS, bootp_handle);
4697 dissector_add("udp.port", UDP_PORT_BOOTPC, bootp_handle);