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 3495: DHCP Option (122) for CableLabs Client Configuration
22 * RFC 3594: PacketCable Security Ticket Control Sub-Option (122.9)
23 * RFC 3442: Classless Static Route Option for DHCP version 4
24 * RFC 3825: Dynamic Host Configuration Protocol Option for Coordinate-based Location Configuration Information
25 * RFC 3942: Reclassifying DHCPv4 Options
26 * RFC 4243: Vendor-Specific Information Suboption for the Dynamic Host Configuration Protocol (DHCP) Relay Agent Option
27 * RFC 4776: Dynamic Host Configuration Protocol (DHCPv4 and DHCPv6) Option for Civic Addresses Configuration Information
28 * RFC 5223: Discovering Location-to-Service Translation (LoST) Servers Using the Dynamic Host Configuration Protocol (DHCP)
29 * RFC 5417: CAPWAP Access Controller DHCP Option
30 * draft-ietf-dhc-fqdn-option-07.txt
31 * BOOTP and DHCP Parameters
32 * http://www.iana.org/assignments/bootp-dhcp-parameters
33 * DOCSIS(TM) 2.0 Radio Frequency Interface Specification
34 * http://www.cablemodem.com/downloads/specs/CM-SP-RFI2.0-I10-051209.pdf
35 * PacketCable(TM) 1.0 MTA Device Provisioning Specification
36 * http://www.packetcable.com/downloads/specs/PKT-SP-PROV-I11-050812.pdf
37 * http://www.cablelabs.com/specifications/archives/PKT-SP-PROV-I05-021127.pdf (superseded by above)
38 * PacketCable(TM) 1.5 MTA Device Provisioning Specification
39 * http://www.packetcable.com/downloads/specs/PKT-SP-PROV1.5-I02-050812.pdf
40 * CableHome(TM) 1.1 Specification
41 * http://www.cablelabs.com/projects/cablehome/downloads/specs/CH-SP-CH1.1-I11-060407.pdf
43 * http://www.dslforum.org/techwork/tr/TR-111.pdf
45 * Wireshark - Network traffic analyzer
46 * By Gerald Combs <gerald@wireshark.org>
47 * Copyright 1998 Gerald Combs
49 * This program is free software; you can redistribute it and/or
50 * modify it under the terms of the GNU General Public License
51 * as published by the Free Software Foundation; either version 2
52 * of the License, or (at your option) any later version.
54 * This program is distributed in the hope that it will be useful,
55 * but WITHOUT ANY WARRANTY; without even the implied warranty of
56 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 * GNU General Public License for more details.
59 * You should have received a copy of the GNU General Public License
60 * along with this program; if not, write to the Free Software
61 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
65 * Some of the development of the BOOTP/DHCP protocol decoder was sponsored by
66 * Cable Television Laboratories, Inc. ("CableLabs") based upon proprietary
67 * CableLabs' specifications. Your license and use of this protocol decoder
68 * does not mean that you are licensed to use the CableLabs'
69 * specifications. If you have questions about this protocol, contact
70 * jf.mule [AT] cablelabs.com or c.stuart [AT] cablelabs.com for additional
82 #include <epan/packet.h>
83 #include "packet-arp.h"
84 #include "packet-dns.h" /* for get_dns_name() */
85 #include <epan/addr_resolv.h>
86 #include <epan/prefs.h>
88 #include <epan/strutil.h>
89 #include <epan/arptypes.h>
90 #include <epan/sminmpec.h>
91 #include <epan/expert.h>
94 static int bootp_dhcp_tap = -1;
95 static int proto_bootp = -1;
96 static int hf_bootp_type = -1;
97 static int hf_bootp_hw_type = -1;
98 static int hf_bootp_hw_len = -1;
99 static int hf_bootp_hops = -1;
100 static int hf_bootp_id = -1;
101 static int hf_bootp_secs = -1;
102 static int hf_bootp_flags = -1;
103 static int hf_bootp_flags_broadcast = -1;
104 static int hf_bootp_flags_reserved = -1;
105 static int hf_bootp_ip_client = -1;
106 static int hf_bootp_ip_your = -1;
107 static int hf_bootp_ip_server = -1;
108 static int hf_bootp_ip_relay = -1;
109 static int hf_bootp_hw_addr = -1;
110 static int hf_bootp_hw_addr_padding = -1;
111 static int hf_bootp_hw_ether_addr = -1;
112 static int hf_bootp_server = -1;
113 static int hf_bootp_file = -1;
114 static int hf_bootp_cookie = -1;
115 static int hf_bootp_vendor = -1;
116 static int hf_bootp_dhcp = -1;
117 static int hf_bootp_fqdn_s = -1;
118 static int hf_bootp_fqdn_o = -1;
119 static int hf_bootp_fqdn_e = -1;
120 static int hf_bootp_fqdn_n = -1;
121 static int hf_bootp_fqdn_mbz = -1;
122 static int hf_bootp_fqdn_rcode1 = -1;
123 static int hf_bootp_fqdn_rcode2 = -1;
124 static int hf_bootp_fqdn_name = -1;
125 static int hf_bootp_fqdn_asciiname = -1;
126 static int hf_bootp_pkt_mtacap_len = -1;
127 static int hf_bootp_docsis_cmcap_len = -1;
128 static int hf_bootp_alu_vid = -1;
129 static int hf_bootp_alu_tftp1 = -1;
130 static int hf_bootp_alu_tftp2 = -1;
131 static int hf_bootp_client_identifier_uuid = -1;
132 static int hf_bootp_client_network_id_major_ver = -1;
133 static int hf_bootp_client_network_id_minor_ver = -1;
134 static int hf_bootp_option_type = -1;
135 static int hf_bootp_option_length = -1;
136 static int hf_bootp_option_value = -1;
138 static gint ett_bootp = -1;
139 static gint ett_bootp_flags = -1;
140 static gint ett_bootp_option = -1;
141 static gint ett_bootp_fqdn = -1;
143 static const char *pref_optionstring = "";
145 /* RFC3825decoder error codes of the conversion function */
146 #define RFC3825_NOERROR 0
147 #define RFC3825_LATITUDE_OUTOFRANGE 1
148 #define RFC3825_LATITUDE_UNCERTAINTY_OUTOFRANGE 2
149 #define RFC3825_LONGITUDE_OUTOFRANGE 3
150 #define RFC3825_LONGITUDE_UNCERTAINTY_OUTOFRANGE 4
151 #define RFC3825_ALTITUDE_OUTOFRANGE 5
152 #define RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE 6
153 #define RFC3825_ALTITUDE_TYPE_OUTOFRANGE 7
154 #define RFC3825_DATUM_TYPE_OUTOFRANGE 8
156 struct rfc3825_location_fixpoint_t {
158 gint64 latitude; /* latitude in degrees, allowed range from -90deg to 90deg.
159 Fixpoint A(8,25) with 34 bits */
160 guint8 latitude_res; /* the resolution of the latitude in bits, allowed range is from 0 to 34.
162 gint64 longitude; /* longitude in degrees, range from -180deg to 180deg.
163 Fixpoint A(8,25) with 34 bits */
164 guint8 longitude_res; /* the resolution of the longitude in bits, allowed range is from 0 to 34.
166 gint32 altitude; /* the altitude, 30 bits.
167 Depending on alt_type this are meters or floors, no range limit.
168 altitude_type==1: A(13,8) with 22 bits
169 altitude_type==2: A(13,8) with 22 bits */
170 guint8 altitude_res; /* the resolution of the altitude in bits, allowed range is from 0 to 30.
172 altitude_type==1: any value between 0 and 30
173 altitude_type==2: either 0 (floor unknown) or 30 */
174 guint8 altitude_type; /* the type of the altitude, 4 bits. allowed values are:
176 1: altitude in meters
177 2: altitude in floors */
178 guint8 datum_type; /* the map datum used for the coordinates. 8 bits.
179 All values are allowed although currently only the
180 following ones are defined:
186 /* The rfc3825_location_decimal_t structure holds the location parameters
187 * in decimal (floating point) format.
189 struct rfc3825_location_decimal_t {
191 double latitude; /* latitude in degrees, allowed range from -90deg to 90deg */
192 double latitude_res; /* the uncertainty of the latitude in grad, "0.01" means +-0.01deg
193 from the altitude. During conversion this will be rounded to
194 next smaller value which can be respresented in fixpoint arithmetic */
195 double longitude; /* longitude in degrees, range from -180deg to 180deg */
196 double longitude_res; /* the uncertainty of the longitude in grad, "0.01" means +-0.01deg
197 from the longitude. During conversion this will be rounded to
198 next smaller value which can be respresented in fixpoint arithmetic */
199 double altitude; /* the altitude, depending on alt_type this are meters or floors, no range limit */
200 double altitude_res; /* the uncertainty of the altitude in either:
201 - altitude-type=meters: "10" means 10 meters which means +-10 meters from the altitude
202 - altitude-type=floors: either 0 (unknown) or 30 (exact) */
203 int altitude_type; /* the type of the altitude, allowed values are
205 1: altitude in meters
206 2: altitude in floors */
207 int datum_type; /* the map datum used for the coordinates.
208 All values are allowed although currently only the
209 following ones are defined:
215 /* converts fixpoint presentation into decimal presentation
216 also converts values which are out of range to allow decoding of received data */
217 static int rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct rfc3825_location_decimal_t *decimal);
219 /* decodes the LCI string received from DHCP into the fixpoint values */
220 static void rfc3825_lci_to_fixpoint(const unsigned char lci[16], struct rfc3825_location_fixpoint_t *fixpoint);
223 /* Map Datum Types used for the coordinates (RFC 3825) */
224 static const value_string map_datum_type_values[] = {
226 { 2, "NAD83 (NAVD88)" },
227 { 3, "NAD83 (MLLW)" },
232 /* Altitude Types used for the coordinates (RFC 3825) */
233 static const value_string altitude_type_values[] = {
239 /* AutoConfigure (RFC 2563) */
240 static const value_string dhcp_autoconfig[] = {
241 {0, "DoNotAutoConfigure"},
242 {1, "AutoConfigure"},
246 /* Error Types for RFC 3825 coordinate location decoding */
247 static const value_string rfc3825_error_types[] = {
248 {1, "Latitude is out of range [-90,90]"},
249 {2, "Latitude Uncertainty is out of range [0,90]"},
250 {3, "Longitude is out of range [-180,180]"},
251 {4, "Longitude Uncertainty is out of range [0,180]"},
252 {5, "Altitude is out of range [-(2^21),(2^21)-1]"},
253 {6, "Altitude Uncertainty is out of range [0,2^20]"},
254 {7, "Altitude Type is out of range [0,2]"},
255 {8, "Datum is out of range [1,3]"},
261 /* Civic Address What field (RFC 4776) */
262 static const value_string civic_address_what_values[] = {
263 { 0, "Location of the DHCP server" },
264 { 1, "Location of the network element believed to be closest to the client" },
265 { 2, "Location of the client"},
269 /* Civic Address Type field (RFC 4119, RFC 4776, RFC 5139) */
270 static const value_string civic_address_type_values[] = {
278 { 16, "PRD (Leading street direction)" },
279 { 17, "POD (Trailing street suffix)" },
280 { 18, "STS (Street suffix)" },
281 { 19, "HNO (House number)" },
282 { 20, "HNS (House number suffix)" },
283 { 21, "LMK (Landmark or vanity address)" },
284 { 22, "LOC (Additional location information)" },
286 { 24, "PC (Postal/ZIP code)" },
287 { 25, "BLD (Building)" },
289 { 27, "FLR (Floor)" },
291 { 29, "PLC (Place-type)" },
292 { 30, "PCN (Postal community name)" },
294 { 32, "ADDCODE (Additional Code)" },
296 { 34, "RD (Primary road or street)" },
297 { 35, "RDSEC (Road section)" },
298 { 36, "RDBR (Road branch)" },
299 { 37, "RDSUBBR (Road sub-branch)" },
300 { 38, "PRM (Road pre-modifier)" },
301 { 39, "POM (Road post-modifier" },
307 static gboolean novell_string = FALSE;
309 #define UDP_PORT_BOOTPS 67
310 #define UDP_PORT_BOOTPC 68
312 #define BOOTP_BC 0x8000
313 #define BOOTP_MBZ 0x7FFF
316 #define F_FQDN_S 0x01
317 #define F_FQDN_O 0x02
318 #define F_FQDN_E 0x04
319 #define F_FQDN_N 0x08
320 #define F_FQDN_MBZ 0xf0
322 static const true_false_string tfs_fqdn_s = {
327 static const true_false_string tfs_fqdn_o = {
332 static const true_false_string tfs_fqdn_e = {
337 static const true_false_string tfs_fqdn_n = {
339 "Some server updates"
346 ipv4, /* single IPv4 address */
347 ipv4_list, /* list of IPv4 addresses */
364 enum field_type ftype;
368 static const true_false_string flag_set_broadcast = {
374 /* PacketCable/DOCSIS definitions */
375 #define PACKETCABLE_MTA_CAP10 "pktc1.0:"
376 #define PACKETCABLE_MTA_CAP15 "pktc1.5:"
377 #define PACKETCABLE_CM_CAP11 "docsis1.1:"
378 #define PACKETCABLE_CM_CAP20 "docsis2.0:"
380 #define PACKETCABLE_CCC_I05 1
381 #define PACKETCABLE_CCC_DRAFT5 2
382 #define PACKETCABLE_CCC_RFC_3495 3
384 static enum_val_t pkt_ccc_protocol_versions[] = {
385 { "ccc_i05", "PKT-SP-PROV-I05-021127", PACKETCABLE_CCC_I05 },
386 { "ccc_draft_5", "IETF Draft 5", PACKETCABLE_CCC_DRAFT5 },
387 { "rfc_3495", "RFC 3495", PACKETCABLE_CCC_RFC_3495 },
391 static gint pkt_ccc_protocol_version = PACKETCABLE_CCC_RFC_3495;
392 static guint pkt_ccc_option = 122;
395 static int dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
396 int optoff, int optend);
397 static int dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb,
398 int optoff, int optend);
399 static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
400 int optoff, int optend);
401 static int dissect_vendor_tr111_suboption(proto_tree *v_tree, tvbuff_t *tvb,
402 int optoff, int optend);
403 static int bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb,
404 int optoff, int optend);
405 static void dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb,
407 static void dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb,
409 static int dissect_packetcable_i05_ccc(proto_tree *v_tree, tvbuff_t *tvb,
410 int optoff, int optend);
411 static int dissect_packetcable_ietf_ccc(proto_tree *v_tree, tvbuff_t *tvb,
412 int optoff, int optend, int revision);
413 static int dissect_vendor_cl_suboption(proto_tree *v_tree, tvbuff_t *tvb,
414 int optoff, int optend);
416 #define OPT53_DISCOVER "Discover"
417 /* http://www.iana.org/assignments/bootp-dhcp-parameters */
418 static const value_string opt53_text[] = {
419 { 1, OPT53_DISCOVER },
427 { 9, "Force Renew" },
428 { 10, "Lease query" }, /* RFC4388 */
429 { 11, "Lease Unassigned" }, /* RFC4388 */
430 { 12, "Lease Unknown" }, /* RFC4388 */
431 { 13, "Lease Active" }, /* RFC4388 */
432 /* draft-ietf-dhc-leasequery-09.txt
433 { 13, "Lease query" }, */
434 { 14, "Lease known" },
435 { 15, "Lease unknown" },
436 { 16, "Lease active" },
437 { 17, "Unimplemented" },
442 /* DHCP Authentication protocols */
443 #define AUTHEN_PROTO_CONFIG_TOKEN 0
444 #define AUTHEN_PROTO_DELAYED_AUTHEN 1
446 /* DHCP Authentication algorithms for delayed authentication */
447 #define AUTHEN_DELAYED_ALGO_HMAC_MD5 1
449 /* DHCP Authentication Replay Detection Methods */
450 #define AUTHEN_RDM_MONOTONIC_COUNTER 0x00
452 /* DHCP Option Overload (option code 52) */
453 #define OPT_OVERLOAD_FILE 1
454 #define OPT_OVERLOAD_SNAME 2
455 #define OPT_OVERLOAD_BOTH 3
457 /* Server name and boot file offsets and lengths */
458 #define SERVER_NAME_OFFSET 44
459 #define SERVER_NAME_LEN 64
460 #define FILE_NAME_OFFSET 108
461 #define FILE_NAME_LEN 128
462 #define VENDOR_INFO_OFFSET 236
464 static const value_string bootp_nbnt_vals[] = {
472 static const value_string bootp_client_arch[] = {
473 { 0x0000, "IA x86 PC" },
474 { 0x0001, "NEC/PC98" },
475 { 0x0002, "IA64 PC" },
476 { 0x0003, "DEC Alpha" },
477 { 0x0004, "ArcX86" },
478 { 0x0005, "Intel Lean Client" },
482 /* bootp options administration */
483 #define BOOTP_OPT_NUM 256
485 /* Re-define structure. Values to be upated by bootp_init_protocol */
486 static struct opt_info bootp_opt[BOOTP_OPT_NUM];
488 static struct opt_info default_bootp_opt[BOOTP_OPT_NUM] = {
489 /* 0 */ { "Padding", none, NULL },
490 /* 1 */ { "Subnet Mask", ipv4, NULL },
491 /* 2 */ { "Time Offset", time_in_secs, NULL },
492 /* 3 */ { "Router", ipv4_list, NULL },
493 /* 4 */ { "Time Server", ipv4_list, NULL },
494 /* 5 */ { "Name Server", ipv4_list, NULL },
495 /* 6 */ { "Domain Name Server", ipv4_list, NULL },
496 /* 7 */ { "Log Server", ipv4_list, NULL },
497 /* 8 */ { "Quotes Server", ipv4_list, NULL },
498 /* 9 */ { "LPR Server", ipv4_list, NULL },
499 /* 10 */ { "Impress Server", ipv4_list, NULL },
500 /* 11 */ { "Resource Location Server", ipv4_list, NULL },
501 /* 12 */ { "Host Name", string, NULL },
502 /* 13 */ { "Boot File Size", val_u_short, NULL },
503 /* 14 */ { "Merit Dump File", string, NULL },
504 /* 15 */ { "Domain Name", string, NULL },
505 /* 16 */ { "Swap Server", ipv4, NULL },
506 /* 17 */ { "Root Path", string, NULL },
507 /* 18 */ { "Extensions Path", string, NULL },
508 /* 19 */ { "IP Forwarding", val_boolean, TFS(&tfs_enabled_disabled) },
509 /* 20 */ { "Non-Local Source Routing", val_boolean, TFS(&tfs_enabled_disabled) },
510 /* 21 */ { "Policy Filter", special, NULL },
511 /* 22 */ { "Maximum Datagram Reassembly Size", val_u_short, NULL },
512 /* 23 */ { "Default IP Time-to-Live", val_u_byte, NULL },
513 /* 24 */ { "Path MTU Aging Timeout", time_in_secs, NULL },
514 /* 25 */ { "Path MTU Plateau Table", val_u_short_list, NULL },
515 /* 26 */ { "Interface MTU", val_u_short, NULL },
516 /* 27 */ { "All Subnets are Local", val_boolean, TFS(&tfs_yes_no) },
517 /* 28 */ { "Broadcast Address", ipv4, NULL },
518 /* 29 */ { "Perform Mask Discovery", val_boolean, TFS(&tfs_enabled_disabled) },
519 /* 30 */ { "Mask Supplier", val_boolean, TFS(&tfs_yes_no) },
520 /* 31 */ { "Perform Router Discover", val_boolean, TFS(&tfs_enabled_disabled) },
521 /* 32 */ { "Router Solicitation Address", ipv4, NULL },
522 /* 33 */ { "Static Route", special, NULL },
523 /* 34 */ { "Trailer Encapsulation", val_boolean, TFS(&tfs_enabled_disabled) },
524 /* 35 */ { "ARP Cache Timeout", time_in_secs, NULL },
525 /* 36 */ { "Ethernet Encapsulation", val_boolean, TFS(&tfs_enabled_disabled) },
526 /* 37 */ { "TCP Default TTL", val_u_byte, NULL },
527 /* 38 */ { "TCP Keepalive Interval", time_in_secs, NULL },
528 /* 39 */ { "TCP Keepalive Garbage", val_boolean, TFS(&tfs_enabled_disabled) },
529 /* 40 */ { "Network Information Service Domain", string, NULL },
530 /* 41 */ { "Network Information Service Servers", ipv4_list, NULL },
531 /* 42 */ { "Network Time Protocol Servers", ipv4_list, NULL },
532 /* 43 */ { "Vendor-Specific Information", special, NULL },
533 /* 44 */ { "NetBIOS over TCP/IP Name Server", ipv4_list, NULL },
534 /* 45 */ { "NetBIOS over TCP/IP Datagram Distribution Name Server", ipv4_list, NULL },
535 /* 46 */ { "NetBIOS over TCP/IP Node Type", val_u_byte, VALS(bootp_nbnt_vals) },
536 /* 47 */ { "NetBIOS over TCP/IP Scope", string, NULL },
537 /* 48 */ { "X Window System Font Server", ipv4_list, NULL },
538 /* 49 */ { "X Window System Display Manager", ipv4_list, NULL },
539 /* 50 */ { "Requested IP Address", ipv4, NULL },
540 /* 51 */ { "IP Address Lease Time", time_in_secs, NULL },
541 /* 52 */ { "Option Overload", special, NULL },
542 /* 53 */ { "DHCP Message Type", special, NULL },
543 /* 54 */ { "DHCP Server Identifier", ipv4, NULL },
544 /* 55 */ { "Parameter Request List", special, NULL },
545 /* 56 */ { "Message", string, NULL },
546 /* 57 */ { "Maximum DHCP Message Size", val_u_short, NULL },
547 /* 58 */ { "Renewal Time Value", time_in_secs, NULL },
548 /* 59 */ { "Rebinding Time Value", time_in_secs, NULL },
549 /* 60 */ { "Vendor class identifier", special, NULL },
550 /* 61 */ { "Client identifier", special, NULL },
551 /* 62 */ { "Novell/Netware IP domain", string, NULL },
552 /* 63 */ { "Novell Options", special, NULL },
553 /* 64 */ { "Network Information Service+ Domain", string, NULL },
554 /* 65 */ { "Network Information Service+ Servers", ipv4_list, NULL },
555 /* 66 */ { "TFTP Server Name", string, NULL },
556 /* 67 */ { "Bootfile name", string, NULL },
557 /* 68 */ { "Mobile IP Home Agent", ipv4_list, NULL },
558 /* 69 */ { "SMTP Server", ipv4_list, NULL },
559 /* 70 */ { "POP3 Server", ipv4_list, NULL },
560 /* 71 */ { "NNTP Server", ipv4_list, NULL },
561 /* 72 */ { "Default WWW Server", ipv4_list, NULL },
562 /* 73 */ { "Default Finger Server", ipv4_list, NULL },
563 /* 74 */ { "Default IRC Server", ipv4_list, NULL },
564 /* 75 */ { "StreetTalk Server", ipv4_list, NULL },
565 /* 76 */ { "StreetTalk Directory Assistance Server", ipv4_list, NULL },
566 /* 77 */ { "User Class Information", opaque, NULL },
567 /* 78 */ { "Directory Agent Information", special, NULL },
568 /* 79 */ { "Service Location Agent Scope", special, NULL },
569 /* 80 */ { "Rapid commit", opaque, NULL },
570 /* 81 */ { "Client Fully Qualified Domain Name", special, NULL },
571 /* 82 */ { "Agent Information Option", special, NULL },
572 /* 83 */ { "iSNS [TODO:RFC4174]", opaque, NULL },
573 /* 84 */ { "Removed/Unassigned", opaque, NULL },
574 /* 85 */ { "Novell Directory Services Servers", special, NULL },
575 /* 86 */ { "Novell Directory Services Tree Name", string, NULL },
576 /* 87 */ { "Novell Directory Services Context", string, NULL },
577 /* 88 */ { "BCMCS Controller Domain Name [TODO:RFC4280]", opaque, NULL },
578 /* 89 */ { "BCMCS Controller IPv4 address [TODO:RFC4280]", opaque, NULL },
579 /* 90 */ { "Authentication", special, NULL },
580 /* 91 */ { "Client last transaction time [TODO:RFC4388]", opaque, NULL },
581 /* 92 */ { "associated ip option [TODO:RFC4388]", opaque, NULL },
582 /* 93 */ { "Client System Architecture", val_u_short, VALS(bootp_client_arch) },
583 /* 94 */ { "Client Network Device Interface", special, NULL },
584 /* 95 */ { "LDAP [TODO:RFC3679]", opaque, NULL },
585 /* 96 */ { "Removed/Unassigend", opaque, NULL },
586 /* 97 */ { "UUID/GUID-based Client Identifier", special, NULL },
587 /* 98 */ { "Open Group's User Authentication [TODO:RFC2485]", opaque, NULL },
588 /* 99 */ { "Civic Addresses Configuration", special, NULL },
589 /* 100 */ { "PCode [TODO:RFC4833]", opaque, NULL },
590 /* 101 */ { "TCode [TODO:RFC4833]", opaque, NULL },
591 /* 102 */ { "Removed/unassigned", opaque, NULL },
592 /* 103 */ { "Removed/unassigned", opaque, NULL },
593 /* 104 */ { "Removed/unassigned", opaque, NULL },
594 /* 105 */ { "Removed/unassigned", opaque, NULL },
595 /* 106 */ { "Removed/unassigned", opaque, NULL },
596 /* 107 */ { "Removed/unassigned", opaque, NULL },
597 /* 108 */ { "Removed/Unassigend", opaque, NULL },
598 /* 109 */ { "Unassigned", opaque, NULL },
599 /* 110 */ { "Removed/Uassigend", opaque, NULL },
600 /* 111 */ { "Unassigned", opaque, NULL },
601 /* 112 */ { "NetInfo Parent Server Address", ipv4_list, NULL },
602 /* 113 */ { "NetInfo Parent Server Tag", string, NULL },
603 /* 114 */ { "URL [TODO:RFC3679]", opaque, NULL },
604 /* 115 */ { "Removed/Unassigend", opaque, NULL },
605 /* 116 */ { "DHCP Auto-Configuration", val_u_byte, VALS(dhcp_autoconfig) },
606 /* 117 */ { "Name Service Search [TODO:RFC2937]", opaque, NULL },
607 /* 118 */ { "Subnet Selection Option", ipv4_list, NULL },
608 /* 119 */ { "Domain Search [TODO:RFC3397]", opaque, NULL },
609 /* 120 */ { "SIP Servers [TODO:RFC3361]", opaque, NULL },
610 /* 121 */ { "Classless Static Route", special, NULL },
611 /* 122 */ { "CableLabs Client Configuration [TODO:RFC3495]", opaque, NULL },
612 /* 123 */ { "Coordinate-based Location Configuration", special, NULL },
613 /* 124 */ { "V-I Vendor Class [TODO:RFC3925]", opaque, NULL },
614 /* 125 */ { "V-I Vendor-specific Information", special, NULL },
615 /* 126 */ { "Removed/Unassigned", opaque, NULL },
616 /* 127 */ { "Removed/Unassigend", opaque, NULL },
617 /* 128 */ { "DOCSIS full security server IP [TODO]", opaque, NULL },
618 /* 129 */ { "PXE - undefined (vendor specific)", opaque, NULL },
619 /* 130 */ { "PXE - undefined (vendor specific)", opaque, NULL },
620 /* 131 */ { "PXE - undefined (vendor specific)", opaque, NULL },
621 /* 132 */ { "PXE - undefined (vendor specific)", opaque, NULL },
622 /* 133 */ { "PXE - undefined (vendor specific)", opaque, NULL },
623 /* 134 */ { "PXE - undefined (vendor specific)", opaque, NULL },
624 /* 135 */ { "PXE - undefined (vendor specific)", opaque, NULL },
625 /* 136 */ { "OPTION_PANA_AGENT [TODO:RFC5192]", opaque, NULL },
626 /* 137 */ { "LoST Server Domain Name", string, NULL },
627 /* 138 */ { "CAPWAP Access Controllers", ipv4_list, NULL },
628 /* 139 */ { "Unassigned", opaque, NULL },
629 /* 140 */ { "Unassigned", opaque, NULL },
630 /* 141 */ { "Unassigned", opaque, NULL },
631 /* 142 */ { "Unassigned", opaque, NULL },
632 /* 143 */ { "Unassigned", opaque, NULL },
633 /* 144 */ { "Unassigned", opaque, NULL },
634 /* 145 */ { "Unassigned", opaque, NULL },
635 /* 146 */ { "Unassigned", opaque, NULL },
636 /* 147 */ { "Unassigned", opaque, NULL },
637 /* 148 */ { "Unassigned", opaque, NULL },
638 /* 149 */ { "Unassigned", opaque, NULL },
639 /* 150 */ { "TFTP server address", opaque, NULL },
640 /* 151 */ { "Unassigned", opaque, NULL },
641 /* 152 */ { "Unassigned", opaque, NULL },
642 /* 153 */ { "Unassigned", opaque, NULL },
643 /* 154 */ { "Unassigned", opaque, NULL },
644 /* 155 */ { "Unassigned", opaque, NULL },
645 /* 156 */ { "Unassigned", opaque, NULL },
646 /* 157 */ { "Unassigned", opaque, NULL },
647 /* 158 */ { "Unassigned", opaque, NULL },
648 /* 159 */ { "Unassigned", opaque, NULL },
649 /* 160 */ { "Unassigned", opaque, NULL },
650 /* 161 */ { "Unassigned", opaque, NULL },
651 /* 162 */ { "Unassigned", opaque, NULL },
652 /* 163 */ { "Unassigned", opaque, NULL },
653 /* 164 */ { "Unassigned", opaque, NULL },
654 /* 165 */ { "Unassigned", opaque, NULL },
655 /* 166 */ { "Unassigned", opaque, NULL },
656 /* 167 */ { "Unassigned", opaque, NULL },
657 /* 168 */ { "Unassigned", opaque, NULL },
658 /* 169 */ { "Unassigned", opaque, NULL },
659 /* 170 */ { "Unassigned", opaque, NULL },
660 /* 171 */ { "Unassigned", opaque, NULL },
661 /* 172 */ { "Unassigned", opaque, NULL },
662 /* 173 */ { "Unassigned", opaque, NULL },
663 /* 174 */ { "Unassigned", opaque, NULL },
664 /* 175 */ { "Etherboot", opaque, NULL },
665 /* 176 */ { "IP Telephone", opaque, NULL },
666 /* 177 */ { "Etherboot", opaque, NULL },
667 /* 178 */ { "Unassigned", opaque, NULL },
668 /* 179 */ { "Unassigned", opaque, NULL },
669 /* 180 */ { "Unassigned", opaque, NULL },
670 /* 181 */ { "Unassigned", opaque, NULL },
671 /* 182 */ { "Unassigned", opaque, NULL },
672 /* 183 */ { "Unassigned", opaque, NULL },
673 /* 184 */ { "Unassigned", opaque, NULL },
674 /* 185 */ { "Unassigned", opaque, NULL },
675 /* 186 */ { "Unassigned", opaque, NULL },
676 /* 187 */ { "Unassigned", opaque, NULL },
677 /* 188 */ { "Unassigned", opaque, NULL },
678 /* 189 */ { "Unassigned", opaque, NULL },
679 /* 190 */ { "Unassigned", opaque, NULL },
680 /* 191 */ { "Unassigned", opaque, NULL },
681 /* 192 */ { "Unassigned", opaque, NULL },
682 /* 193 */ { "Unassigned", opaque, NULL },
683 /* 194 */ { "Unassigned", opaque, NULL },
684 /* 195 */ { "Unassigned", opaque, NULL },
685 /* 196 */ { "Unassigned", opaque, NULL },
686 /* 197 */ { "Unassigned", opaque, NULL },
687 /* 198 */ { "Unassigned", opaque, NULL },
688 /* 199 */ { "Unassigned", opaque, NULL },
689 /* 200 */ { "Unassigned", opaque, NULL },
690 /* 201 */ { "Unassigned", opaque, NULL },
691 /* 202 */ { "Unassigned", opaque, NULL },
692 /* 203 */ { "Unassigned", opaque, NULL },
693 /* 204 */ { "Unassigned", opaque, NULL },
694 /* 205 */ { "Unassigned", opaque, NULL },
695 /* 206 */ { "Unassigned", opaque, NULL },
696 /* 207 */ { "Unassigned", opaque, NULL },
697 /* 208 */ { "PXELINUX Magic", opaque, NULL },
698 /* 209 */ { "Configuration file", opaque, NULL },
699 /* 210 */ { "Authentication", special, NULL }, /* Path Prefix rfc5071 */
700 /* 211 */ { "Reboot Time", opaque, NULL },
701 /* 212 */ { "Unassigned", opaque, NULL },
702 /* 213 */ { "Unassigned", opaque, NULL },
703 /* 214 */ { "Unassigned", opaque, NULL },
704 /* 215 */ { "Unassigned", opaque, NULL },
705 /* 216 */ { "Unassigned", opaque, NULL },
706 /* 217 */ { "Unassigned", opaque, NULL },
707 /* 218 */ { "Unassigned", opaque, NULL },
708 /* 219 */ { "Unassigned", opaque, NULL },
709 /* 220 */ { "Subnet Allocation", opaque, NULL },
710 /* 221 */ { "Virtual Subnet Selection", opaque, NULL },
711 /* 222 */ { "Unassigned", opaque, NULL },
712 /* 223 */ { "Unassigned", opaque, NULL },
713 /* 224 */ { "Private", opaque, NULL },
714 /* 225 */ { "Private", opaque, NULL },
715 /* 226 */ { "Private", opaque, NULL },
716 /* 227 */ { "Private", opaque, NULL },
717 /* 228 */ { "Private", opaque, NULL },
718 /* 229 */ { "Private", opaque, NULL },
719 /* 230 */ { "Private", opaque, NULL },
720 /* 231 */ { "Private", opaque, NULL },
721 /* 232 */ { "Private", opaque, NULL },
722 /* 233 */ { "Private", opaque, NULL },
723 /* 234 */ { "Private", opaque, NULL },
724 /* 235 */ { "Private", opaque, NULL },
725 /* 236 */ { "Private", opaque, NULL },
726 /* 237 */ { "Private", opaque, NULL },
727 /* 238 */ { "Private", opaque, NULL },
728 /* 239 */ { "Private", opaque, NULL },
729 /* 240 */ { "Private", opaque, NULL },
730 /* 241 */ { "Private", opaque, NULL },
731 /* 242 */ { "Private", opaque, NULL },
732 /* 243 */ { "Private", opaque, NULL },
733 /* 244 */ { "Private", opaque, NULL },
734 /* 245 */ { "Private", opaque, NULL },
735 /* 246 */ { "Private", opaque, NULL },
736 /* 247 */ { "Private", opaque, NULL },
737 /* 248 */ { "Private", opaque, NULL },
738 /* 249 */ { "Private/Classless Static Route (Microsoft)", special, NULL },
739 /* 250 */ { "Private", opaque, NULL },
740 /* 251 */ { "Private", opaque, NULL },
741 /* 252 */ { "Private/Proxy autodiscovery", string, NULL },
742 /* 253 */ { "Private", opaque, NULL },
743 /* 254 */ { "Private", opaque, NULL },
744 /* 255 */ { "End", opaque, NULL }
748 bootp_get_opt_text(unsigned int idx)
750 if(idx>=BOOTP_OPT_NUM)
752 return bootp_opt[idx].text;
756 bootp_get_opt_data(unsigned int idx)
758 if(idx>=BOOTP_OPT_NUM)
760 return bootp_opt[idx].data;
763 static enum field_type
764 bootp_get_opt_ftype(unsigned int idx)
766 if(idx>=BOOTP_OPT_NUM)
768 return bootp_opt[idx].ftype;
772 /* Returns the number of bytes consumed by this option. */
774 bootp_option(tvbuff_t *tvb, proto_tree *bp_tree, int voff, int eoff,
775 gboolean first_pass, gboolean *at_end, const char **dhcp_type_p,
776 const guint8 **vendor_class_id_p, guint8 *overload_p)
779 enum field_type ftype;
780 guchar code = tvb_get_guint8(tvb, voff);
782 const struct true_false_string *tfs;
783 const value_string *vs;
786 int optoff, optleft, optend;
788 proto_tree *v_tree, *ft;
794 int o52voff, o52eoff;
798 const guchar *dns_name;
801 static const value_string slpda_vals[] = {
802 {0x00, "Dynamic Discovery" },
803 {0x01, "Static Discovery" },
804 {0x80, "Backwards compatibility" },
807 static const value_string slp_scope_vals[] = {
808 {0x00, "Preferred Scope" },
809 {0x01, "Mandatory Scope" },
812 static const value_string authen_protocol_vals[] = {
813 {AUTHEN_PROTO_CONFIG_TOKEN, "configuration token" },
814 {AUTHEN_PROTO_DELAYED_AUTHEN, "delayed authentication" },
817 static const value_string authen_da_algo_vals[] = {
818 {AUTHEN_DELAYED_ALGO_HMAC_MD5, "HMAC_MD5" },
821 static const value_string authen_rdm_vals[] = {
822 {AUTHEN_RDM_MONOTONIC_COUNTER, "Monotonically-increasing counter" },
825 static const value_string opt_overload_vals[] = {
826 { OPT_OVERLOAD_FILE, "Boot file name holds options", },
827 { OPT_OVERLOAD_SNAME, "Server host name holds options", },
828 { OPT_OVERLOAD_BOTH, "Boot file and server host names hold options" },
831 /* Options whose length isn't "optlen + 2". */
834 case 0: /* Padding */
835 /* check how much padding we have */
836 for (i = voff + 1; i < eoff; i++ ) {
837 if (tvb_get_guint8(tvb, i) != 0) {
843 if (bp_tree != NULL) {
844 proto_tree_add_text(bp_tree, tvb, voff, i,
845 "Padding (%d byte%s)", i, (i>1)?"s":"");
851 case 255: /* End Option */
853 if (bp_tree != NULL) {
854 proto_tree_add_text(bp_tree, tvb, voff, 1,
855 "End Option%s", *overload_p?" (overload)":"");
864 * Get the length of the option, and the number of bytes it
865 * consumes (the length doesn't include the option code or
868 * On the first pass, check first whether we have the length
869 * byte, so that we don't throw an exception; if we throw an
870 * exception in the first pass, which is only checking for options
871 * whose values we need in order to properly dissect the packet
872 * on the second pass, we won't actually dissect the options, so
873 * you won't be able to see which option had the problem.
876 if (!tvb_bytes_exist(tvb, voff+1, 1)) {
878 * We don't have the length byte; just return 1
879 * as the number of bytes we consumed, to count
885 optlen = tvb_get_guint8(tvb, voff+1);
886 consumed = optlen + 2;
889 * In the first pass, we don't put anything into the protocol
890 * tree; we just check for some options we have to look at
891 * in order to properly process the packet:
893 * 52 (Overload) - we need this to properly dissect the
894 * file and sname fields
896 * 53 (DHCP message type) - if this is present, this is DHCP
898 * 60 (Vendor class identifier) - we need this in order to
899 * interpret the vendor-specific info
901 * We also check, before fetching anything, to make sure we
902 * have the entire item we're fetching, so that we don't throw
906 if (tvb_bytes_exist(tvb, voff+2, consumed-2)) {
910 *overload_p = tvb_get_guint8(tvb, voff+2);
915 val_to_str(tvb_get_guint8(tvb, voff+2),
917 "Unknown Message Type (0x%02x)");
922 tvb_get_ptr(tvb, voff+2, consumed-2);
928 * We don't do anything else here.
934 * This is the second pass - if there's a protocol tree to be
935 * built, we put stuff into it, otherwise we just return.
937 if (bp_tree == NULL) {
938 /* Don't put anything in the protocol tree. */
943 text = bootp_get_opt_text(code);
944 ftype = bootp_get_opt_ftype(code);
948 vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
949 "Option: (t=%d,l=%d) %s", code, optlen, text);
950 v_tree = proto_item_add_subtree(vti, ett_bootp_option);
951 proto_tree_add_uint_format_value(v_tree, hf_bootp_option_type,
952 tvb, voff, 1, code, "(%d) %s", code, text);
953 proto_tree_add_item(v_tree, hf_bootp_option_length, tvb, voff+1, 1, FALSE);
955 proto_tree_add_item(v_tree, hf_bootp_option_value, tvb, voff+2, optlen, FALSE);
961 case 21: /* Policy Filter */
963 /* one IP address pair */
964 proto_item_append_text(vti, " = %s/%s",
965 ip_to_str(tvb_get_ptr(tvb, optoff, 4)),
966 ip_to_str(tvb_get_ptr(tvb, optoff+4, 4)));
968 /* > 1 IP address pair. Let's make a sub-tree */
969 for (i = optoff, optleft = optlen;
970 optleft > 0; i += 8, optleft -= 8) {
972 proto_tree_add_text(v_tree, tvb, i, optleft,
973 "Option length isn't a multiple of 8");
976 proto_tree_add_text(v_tree, tvb, i, 8, "IP Address/Mask: %s/%s",
977 ip_to_str(tvb_get_ptr(tvb, i, 4)),
978 ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
983 case 33: /* Static Route */
985 /* one IP address pair */
986 proto_item_append_text(vti, " = %s/%s",
987 ip_to_str(tvb_get_ptr(tvb, optoff, 4)),
988 ip_to_str(tvb_get_ptr(tvb, optoff+4, 4)));
990 /* > 1 IP address pair. Let's make a sub-tree */
991 for (i = optoff, optleft = optlen; optleft > 0;
992 i += 8, optleft -= 8) {
994 proto_tree_add_text(v_tree, tvb, i, optleft,
995 "Option length isn't a multiple of 8");
998 proto_tree_add_text(v_tree, tvb, i, 8,
999 "Destination IP Address/Router: %s/%s",
1000 ip_to_str(tvb_get_ptr(tvb, i, 4)),
1001 ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
1006 case 43: /* Vendor-Specific Info */
1007 s_option = tvb_get_guint8(tvb, optoff);
1009 /* Alcatel-Lucent AVA */
1010 if (optlen == 5 && s_option == 58)
1012 proto_item_append_text(vti, " (Alcatel-Lucent AVA)");
1013 ava_vid = tvb_get_ntohs(tvb, optoff + 2);
1014 proto_tree_add_text (v_tree, tvb, optoff + 2,
1017 proto_tree_add_uint (v_tree, hf_bootp_alu_vid, tvb, optoff + 2,
1020 if (ava_vid == 65535)
1022 proto_tree_add_text (v_tree, tvb, optoff + 2,
1023 2, "Type: Request from ALU IP Phone");
1025 proto_tree_add_text (v_tree, tvb, optoff + 2,
1026 2, "Type: Response from DHCP Server");
1032 /* Alcatel-Lucent DHCP Extensions for Spatial Redundancy */
1034 if ((optlen == 12 && s_option == 64) ||
1035 (optlen == 6 && s_option == 64) ||
1036 (optlen == 6 && s_option == 65))
1038 if (optlen == 6 && s_option == 64)
1040 proto_item_append_text(vti, " (Alcatel-Lucent TFTP Options)");
1041 proto_tree_add_text (v_tree, tvb, optoff + 2,
1043 proto_tree_add_ipv4(v_tree,hf_bootp_alu_tftp1 ,tvb,optoff+2, 4,
1044 tvb_get_ipv4(tvb,optoff+2));
1046 if (optlen == 6 && s_option == 65)
1048 proto_item_append_text(vti, " (Alcatel-Lucent TFTP Options)");
1049 proto_tree_add_text (v_tree, tvb, optoff + 2,
1051 proto_tree_add_ipv4(v_tree,hf_bootp_alu_tftp2 ,tvb,optoff+2 ,4,
1052 tvb_get_ipv4(tvb,optoff+2));
1054 if (optlen == 12 && s_option == 64)
1056 proto_item_append_text(vti, " (Alcatel-Lucent TFTP Options)");
1057 proto_tree_add_text (v_tree, tvb, optoff + 2,
1058 2, "Opcode: 64 and 65");
1059 proto_tree_add_ipv4(v_tree,hf_bootp_alu_tftp1 ,tvb,optoff+2 ,4,
1060 tvb_get_ipv4(tvb,optoff+2));
1061 proto_tree_add_ipv4(v_tree,hf_bootp_alu_tftp2 ,tvb,optoff+8 ,4,
1062 tvb_get_ipv4(tvb,optoff+8));
1069 /* PXE protocol 2.1 as described in the intel specs */
1070 if (*vendor_class_id_p != NULL &&
1071 strncmp((const gchar*)*vendor_class_id_p, "PXEClient", strlen("PXEClient")) == 0) {
1072 proto_item_append_text(vti, " (PXEClient)");
1073 v_tree = proto_item_add_subtree(vti, ett_bootp_option);
1075 optend = optoff + optlen;
1076 while (optoff < optend) {
1077 optoff = dissect_vendor_pxeclient_suboption(v_tree,
1078 tvb, optoff, optend);
1080 } else if (*vendor_class_id_p != NULL &&
1081 ((strncmp((const gchar*)*vendor_class_id_p, "pktc", strlen("pktc")) == 0) ||
1082 (strncmp((const gchar*)*vendor_class_id_p, "docsis", strlen("docsis")) == 0) ||
1083 (strncmp((const gchar*)*vendor_class_id_p, "OpenCable2.0", strlen("OpenCable2.0")) == 0) ||
1084 (strncmp((const gchar*)*vendor_class_id_p, "CableHome", strlen("CableHome")) == 0))) {
1085 /* CableLabs standard - see www.cablelabs.com/projects */
1086 proto_item_append_text(vti, " (CableLabs)");
1088 optend = optoff + optlen;
1089 while (optoff < optend) {
1090 optoff = dissect_vendor_cablelabs_suboption(v_tree,
1091 tvb, optoff, optend);
1096 case 52: /* Option Overload */
1098 proto_item_append_text(vti, " length isn't >= 1");
1101 byte = tvb_get_guint8(tvb, optoff);
1102 proto_item_append_text(vti, " = %s",
1103 val_to_str(byte, opt_overload_vals,
1104 "Unknown (0x%02x)"));
1106 /* Just in case we find an option 52 in sname or file */
1107 if (voff > VENDOR_INFO_OFFSET && byte >= 1 && byte <= 3) {
1108 if (byte & OPT_OVERLOAD_FILE) {
1109 proto_tree_add_text (bp_tree, tvb,
1110 FILE_NAME_OFFSET, FILE_NAME_LEN,
1111 "Boot file name option overload");
1112 o52voff = FILE_NAME_OFFSET;
1113 o52eoff = FILE_NAME_OFFSET + FILE_NAME_LEN;
1115 while (o52voff < o52eoff && !o52at_end) {
1116 o52voff += bootp_option(tvb, bp_tree, o52voff,
1117 o52eoff, FALSE, &o52at_end,
1118 dhcp_type_p, vendor_class_id_p,
1122 if (byte & OPT_OVERLOAD_SNAME) {
1123 proto_tree_add_text (bp_tree, tvb,
1124 SERVER_NAME_OFFSET, SERVER_NAME_LEN,
1125 "Server host name option overload");
1126 o52voff = SERVER_NAME_OFFSET;
1127 o52eoff = SERVER_NAME_OFFSET + SERVER_NAME_LEN;
1129 while (o52voff < o52eoff && !o52at_end) {
1130 o52voff += bootp_option(tvb, bp_tree, o52voff,
1131 o52eoff, FALSE, &o52at_end,
1132 dhcp_type_p, vendor_class_id_p,
1136 /* The final end option is not in overload */
1141 case 53: /* DHCP Message Type */
1143 proto_item_append_text(vti, " length isn't 1");
1146 proto_item_append_text(vti, " = DHCP %s",
1147 val_to_str(tvb_get_guint8(tvb, optoff),
1149 "Unknown Message Type (0x%02x)"));
1152 case 55: /* Parameter Request List */
1153 for (i = 0; i < optlen; i++) {
1154 byte = tvb_get_guint8(tvb, optoff+i);
1155 proto_tree_add_text(v_tree, tvb, optoff+i, 1, "%d = %s",
1156 byte, bootp_get_opt_text(byte));
1160 case 60: /* Vendor class identifier */
1162 * XXX - RFC 2132 says this is a string of octets;
1163 * should we check for non-printables?
1165 proto_item_append_text(vti, " = \"%s\"",
1166 tvb_format_stringzpad(tvb, optoff, consumed-2));
1167 if ((tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP10,
1168 (int)strlen(PACKETCABLE_MTA_CAP10)) == 0)
1170 (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_MTA_CAP15,
1171 (int)strlen(PACKETCABLE_MTA_CAP10)) == 0))
1173 dissect_packetcable_mta_cap(v_tree, tvb, optoff, optlen);
1176 if (tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP11,
1177 (int)strlen(PACKETCABLE_CM_CAP11)) == 0
1179 tvb_memeql(tvb, optoff, (const guint8*)PACKETCABLE_CM_CAP20,
1180 (int)strlen(PACKETCABLE_CM_CAP20)) == 0 )
1182 dissect_docsis_cm_cap(v_tree, tvb, optoff, optlen);
1187 case 61: /* Client Identifier */
1188 case 97: /* Client Identifier (UUID) */
1190 byte = tvb_get_guint8(tvb, optoff);
1194 /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll
1195 guess that the first is the hwtype, and the last 6
1197 /* See http://www.iana.org/assignments/arp-parameters */
1198 /* RFC2132 9.14 Client-identifier has the following to say:
1199 A hardware type of 0 (zero) should be used when the value
1200 field contains an identifier other than a hardware address
1201 (e.g. a fully qualified domain name). */
1203 if (optlen == 7 && byte > 0 && byte < 48) {
1204 proto_tree_add_text(v_tree, tvb, optoff, 1,
1205 "Hardware type: %s",
1206 arphrdtype_to_str(byte,
1207 "Unknown (0x%02x)"));
1208 if (byte == ARPHRD_ETHER || byte == ARPHRD_IEEE802)
1209 proto_tree_add_item(v_tree,
1210 hf_bootp_hw_ether_addr, tvb, optoff+1, 6,
1213 proto_tree_add_text(v_tree, tvb, optoff+1, 6,
1214 "Client hardware address: %s",
1215 arphrdaddr_to_str(tvb_get_ptr(tvb, optoff+1, 6),
1217 } else if (optlen == 17 && byte == 0) {
1218 /* Identifier is a UUID */
1219 proto_tree_add_item(v_tree, hf_bootp_client_identifier_uuid,
1220 tvb, optoff + 1, 16, TRUE);
1222 /* otherwise, it's opaque data */
1226 case 63: /* NetWare/IP options (RFC 2242) */
1228 optend = optoff + optlen;
1229 while (optoff < optend)
1230 optoff = dissect_netware_ip_suboption(v_tree, tvb, optoff, optend);
1233 case 78: /* SLP Directory Agent Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
1235 proto_item_append_text(vti, " length isn't >= 1");
1239 byte = tvb_get_guint8(tvb, optoff);
1240 proto_item_append_text(vti, " = %s",
1241 val_to_str(byte, slpda_vals,
1242 "Unknown (0x%02x)"));
1251 for (i = optoff; optleft > 0; i += 4, optleft -= 4) {
1253 proto_tree_add_text(v_tree, tvb, i, optleft,
1254 "Option length isn't a multiple of 4");
1257 proto_tree_add_text(v_tree, tvb, i, 4, "SLPDA Address: %s",
1258 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1262 case 79: /* SLP Service Scope Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
1263 byte = tvb_get_guint8(tvb, optoff);
1264 proto_item_append_text(vti, " = %s",
1265 val_to_str(byte, slp_scope_vals,
1266 "Unknown (0x%02x)"));
1268 optleft = optlen - 1;
1269 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1270 "%s = \"%s\"", text,
1271 tvb_format_stringzpad(tvb, optoff, optleft));
1274 case 81: /* Client Fully Qualified Domain Name */
1276 proto_item_append_text(vti, " length isn't >= 3");
1279 fqdn_flags = tvb_get_guint8(tvb, optoff);
1280 ft = proto_tree_add_text(v_tree, tvb, optoff, 1, "Flags: 0x%02x", fqdn_flags);
1281 proto_tree_add_item(v_tree, hf_bootp_fqdn_mbz, tvb, optoff, 1, FALSE);
1282 proto_tree_add_item(v_tree, hf_bootp_fqdn_n, tvb, optoff, 1, FALSE);
1283 proto_tree_add_item(v_tree, hf_bootp_fqdn_e, tvb, optoff, 1, FALSE);
1284 proto_tree_add_item(v_tree, hf_bootp_fqdn_o, tvb, optoff, 1, FALSE);
1285 proto_tree_add_item(v_tree, hf_bootp_fqdn_s, tvb, optoff, 1, FALSE);
1286 /* XXX: use code from packet-dns for return code decoding */
1287 proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode1, tvb, optoff+1, 1, FALSE);
1288 /* XXX: use code from packet-dns for return code decoding */
1289 proto_tree_add_item(v_tree, hf_bootp_fqdn_rcode2, tvb, optoff+2, 1, FALSE);
1291 if (fqdn_flags & F_FQDN_E) {
1292 get_dns_name(tvb, optoff+3, optlen-3, optoff+3, &dns_name);
1293 proto_tree_add_string(v_tree, hf_bootp_fqdn_name,
1294 tvb, optoff+3, optlen-3, dns_name);
1296 proto_tree_add_item(v_tree, hf_bootp_fqdn_asciiname,
1297 tvb, optoff+3, optlen-3, FALSE);
1302 case 82: /* Relay Agent Information Option */
1303 optend = optoff + optlen;
1304 while (optoff < optend)
1305 optoff = bootp_dhcp_decode_agent_info(v_tree, tvb, optoff, optend);
1308 case 85: /* Novell Servers (RFC 2241) */
1309 /* Option 85 can be sent as a string */
1310 /* Added by Greg Morris (gmorris[AT]novell.com) */
1311 if (novell_string) {
1312 proto_item_append_text(vti, " = \"%s\"",
1313 tvb_format_stringzpad(tvb, optoff, optlen));
1316 /* one IP address */
1317 proto_item_append_text(vti, " = %s",
1318 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1320 /* > 1 IP addresses. Let's make a sub-tree */
1321 for (i = optoff, optleft = optlen; optleft > 0;
1322 i += 4, optleft -= 4) {
1324 proto_tree_add_text(v_tree, tvb, i, optleft,
1325 "Option length isn't a multiple of 4");
1328 proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
1329 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1335 case 94: { /* Client network interface identifier */
1338 id_type = tvb_get_guint8(tvb, optoff);
1340 if (id_type == 0x01) {
1341 proto_tree_add_item(v_tree, hf_bootp_client_network_id_major_ver,
1342 tvb, optoff + 1, 1, TRUE);
1343 proto_tree_add_item(v_tree, hf_bootp_client_network_id_minor_ver,
1344 tvb, optoff + 2, 1, TRUE);
1350 case 90: /* DHCP Authentication */
1351 case 210: /* Was this used for authentication at one time? */
1353 proto_item_append_text(vti, " length isn't >= 11");
1357 protocol = tvb_get_guint8(tvb, optoff);
1358 proto_tree_add_text(v_tree, tvb, optoff, 1, "Protocol: %s (%u)",
1359 val_to_str(protocol, authen_protocol_vals, "Unknown"),
1364 algorithm = tvb_get_guint8(tvb, optoff);
1367 case AUTHEN_PROTO_DELAYED_AUTHEN:
1368 proto_tree_add_text(v_tree, tvb, optoff, 1,
1369 "Algorithm: %s (%u)",
1370 val_to_str(algorithm, authen_da_algo_vals, "Unknown"),
1375 proto_tree_add_text(v_tree, tvb, optoff, 1,
1376 "Algorithm: %u", algorithm);
1382 rdm = tvb_get_guint8(tvb, optoff);
1383 proto_tree_add_text(v_tree, tvb, optoff, 1,
1384 "Replay Detection Method: %s (%u)",
1385 val_to_str(rdm, authen_rdm_vals, "Unknown"),
1392 case AUTHEN_RDM_MONOTONIC_COUNTER:
1393 proto_tree_add_text(v_tree, tvb, optoff, 8,
1394 "RDM Replay Detection Value: %" G_GINT64_MODIFIER "x",
1395 tvb_get_ntoh64(tvb, optoff));
1399 proto_tree_add_text(v_tree, tvb, optoff, 8,
1400 "Replay Detection Value: %s",
1401 tvb_bytes_to_str(tvb, optoff, 8));
1409 case AUTHEN_PROTO_DELAYED_AUTHEN:
1410 switch (algorithm) {
1412 case AUTHEN_DELAYED_ALGO_HMAC_MD5:
1413 if (*dhcp_type_p && !strcmp(*dhcp_type_p, OPT53_DISCOVER)) {
1414 /* Discover has no Secret ID nor HMAC MD5 Hash */
1418 proto_item_append_text(vti,
1419 " length isn't >= 31");
1422 proto_tree_add_text(v_tree, tvb, optoff, 4,
1423 "Secret ID: 0x%08x",
1424 tvb_get_ntohl(tvb, optoff));
1427 proto_tree_add_text(v_tree, tvb, optoff, 16,
1428 "HMAC MD5 Hash: %s",
1429 tvb_bytes_to_str(tvb, optoff, 16));
1436 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1437 "Authentication Information: %s",
1438 tvb_bytes_to_str(tvb, optoff, optleft));
1446 proto_tree_add_text(v_tree, tvb, optoff, optleft,
1447 "Authentication Information: %s",
1448 tvb_bytes_to_str(tvb, optoff, optleft));
1453 case 99: /* civic location (RFC 4776) */
1458 proto_tree_add_text(v_tree, tvb, optoff, 1, "What: %d (%s)",
1459 tvb_get_guint8(tvb, optoff), val_to_str(tvb_get_guint8(tvb, optoff),
1460 civic_address_what_values, "Unknown") );
1461 proto_tree_add_text(v_tree, tvb, optoff + 1, 2, "Country: \"%s\"",
1462 tvb_format_text(tvb, optoff + 1, 2) );
1463 optleft = optleft - 3;
1464 optoff = optoff + 3;
1466 while (optleft >= 2)
1468 int catype = tvb_get_guint8(tvb, optoff);
1471 s_option = tvb_get_guint8(tvb, optoff);
1477 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1478 "CAType %d [%s] (l=%d): EMTPY", catype,
1479 val_to_str(catype, civic_address_type_values,
1480 "Unknown"), s_option);
1484 if (optleft >= s_option)
1486 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1487 "CAType %d [%s] (l=%d): \"%s\"", catype,
1488 val_to_str(catype, civic_address_type_values,
1489 "Unknown"), s_option,
1490 tvb_format_text(tvb, optoff, s_option));
1491 optoff = optoff + s_option;
1492 optleft = optleft - s_option;
1497 proto_tree_add_text(v_tree, tvb, optoff, s_option,
1498 "Error with CAType");
1505 case 121: /* Classless Static Route */
1506 case 249: { /* Classless Static Route (Microsoft) */
1507 int mask_width, significant_octets;
1508 optend = optoff + optlen;
1509 /* minimum length is 5 bytes */
1511 proto_item_append_text(vti, " [ERROR: Option length < 5 bytes]");
1514 while (optoff < optend) {
1515 mask_width = tvb_get_guint8(tvb, optoff);
1516 /* mask_width <= 32 */
1517 if (mask_width > 32) {
1518 proto_tree_add_text(v_tree, tvb, optoff,
1520 "Subnet/MaskWidth-Router: [ERROR: Mask width (%d) > 32]",
1524 significant_octets = (mask_width + 7) / 8;
1525 vti = proto_tree_add_text(v_tree, tvb, optoff,
1526 1 + significant_octets + 4,
1527 "Subnet/MaskWidth-Router: ");
1529 /* significant octets + router(4) */
1530 if (optend < optoff + significant_octets + 4) {
1531 proto_item_append_text(vti, "[ERROR: Remaining length (%d) < %d bytes]",
1532 optend - optoff, significant_octets + 4);
1536 proto_item_append_text(vti, "default");
1538 for(i = 0 ; i < significant_octets ; i++) {
1540 proto_item_append_text(vti, ".");
1541 byte = tvb_get_guint8(tvb, optoff++);
1542 proto_item_append_text(vti, "%d", byte);
1544 for(i = significant_octets ; i < 4 ; i++)
1545 proto_item_append_text(vti, ".0");
1546 proto_item_append_text(vti, "/%d", mask_width);
1548 proto_item_append_text(vti, "-%s",
1549 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1555 case 123: /* coordinate based location RFC 3825 */
1558 unsigned char lci[16];
1559 struct rfc3825_location_fixpoint_t location_fp;
1560 struct rfc3825_location_decimal_t location;
1562 for (c=0; c < 16;c++)
1563 lci[c] = (unsigned char) tvb_get_guint8(tvb, optoff + c);
1565 /* convert lci encoding into fixpoint location */
1566 rfc3825_lci_to_fixpoint(lci, &location_fp);
1568 /* convert location from decimal to fixpoint */
1569 i = rfc3825_fixpoint_to_decimal(&location_fp, &location);
1571 if (i != RFC3825_NOERROR) {
1572 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Error: %s", val_to_str(i, rfc3825_error_types, "Unknown"));
1574 proto_tree_add_text(v_tree, tvb, optoff, 5, "Latitude: %15.10f", location.latitude);
1575 proto_tree_add_text(v_tree, tvb, optoff+5, 5, "Longitude: %15.10f", location.longitude);
1576 proto_tree_add_text(v_tree, tvb, optoff, 1, "Latitude resolution: %15.10f", location.latitude_res);
1577 proto_tree_add_text(v_tree, tvb, optoff+5, 1, "Longitude resolution: %15.10f", location.longitude_res);
1578 proto_tree_add_text(v_tree, tvb, optoff+12, 4, "Altitude: %15.10f", location.altitude);
1579 proto_tree_add_text(v_tree, tvb, optoff+10, 2, "Altitude resolution: %15.10f", location.altitude_res);
1580 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);
1581 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);
1584 proto_tree_add_text(v_tree, tvb, optoff, optlen, "Error: Invalid length of DHCP option!");
1588 case 125: { /* V-I Vendor-specific Information */
1591 int s_option_len = 0;
1592 proto_tree *e_tree = 0;
1594 optend = optoff + optlen;
1598 while (optleft > 0) {
1601 proto_tree_add_text(v_tree, tvb, optoff,
1602 optleft, "Vendor-specific Information: malformed option");
1606 enterprise = tvb_get_ntohl(tvb, optoff);
1608 vti = proto_tree_add_text(v_tree, tvb, optoff, 4,
1609 "Enterprise-number: %s-%u",
1610 val_to_str( enterprise, sminmpec_values, "Unknown"),
1613 s_option_len = tvb_get_guint8(tvb, optoff + 4);
1618 /* Handle DSL Forum TR-111 Option 125 */
1619 if ( enterprise == 3561 ) {
1621 s_end = optoff + s_option_len;
1622 if ( s_end > optend ) {
1623 proto_tree_add_text(v_tree, tvb, optoff, 1,
1624 "no room left in option for enterprise %u data", enterprise);
1629 e_tree = proto_item_add_subtree(vti, ett_bootp_option);
1630 while (optoff < s_end) {
1632 optoff = dissect_vendor_tr111_suboption(e_tree,
1633 tvb, optoff, s_end);
1635 } else if ( enterprise == 4491 ) {
1637 s_end = optoff + s_option_len;
1638 if ( s_end > optend ) {
1639 proto_tree_add_text(v_tree, tvb, optoff, 1,
1640 "no room left in option for enterprise %u data", enterprise);
1645 e_tree = proto_item_add_subtree(vti, ett_bootp_option);
1646 while (optoff < s_end) {
1648 optoff = dissect_vendor_cl_suboption(e_tree,
1649 tvb, optoff, s_end);
1653 /* skip over the data and look for next enterprise number */
1654 optoff += s_option_len;
1657 optleft -= s_option_len;
1663 default: /* not special */
1664 /* The PacketCable CCC option number can vary. If this is a CCC option,
1665 handle it as a special.
1667 if (code == pkt_ccc_option) {
1669 proto_item_append_text(vti,
1670 "CableLabs Client Configuration (%d bytes)",
1672 optend = optoff + optlen;
1673 while (optoff < optend) {
1674 switch (pkt_ccc_protocol_version) {
1676 case PACKETCABLE_CCC_I05:
1677 optoff = dissect_packetcable_i05_ccc(v_tree, tvb, optoff, optend);
1679 case PACKETCABLE_CCC_DRAFT5:
1680 case PACKETCABLE_CCC_RFC_3495:
1681 optoff = dissect_packetcable_ietf_ccc(v_tree, tvb, optoff, optend, pkt_ccc_protocol_version);
1683 default: /* XXX Should we do something here? */
1696 proto_item_append_text(vti,
1697 " - length isn't 4");
1700 proto_item_append_text(vti, " = %s",
1701 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1706 /* one IP address */
1707 proto_item_append_text(vti, " = %s",
1708 ip_to_str(tvb_get_ptr(tvb, optoff, 4)));
1710 /* > 1 IP addresses. Let's make a sub-tree */
1711 for (i = optoff, optleft = optlen; optleft > 0;
1712 i += 4, optleft -= 4) {
1714 proto_tree_add_text(v_tree, tvb, i, voff + consumed - i,
1715 "Option length isn't a multiple of 4");
1718 proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
1719 ip_to_str(tvb_get_ptr(tvb, i, 4)));
1725 /* Fix for non null-terminated string supplied by
1726 * John Lines <John.Lines[AT]aeat.co.uk>
1728 proto_item_append_text(vti, " = \"%s\"",
1729 tvb_format_stringzpad(tvb, optoff, consumed-2));
1734 proto_item_append_text(vti,
1735 " - length isn't 1");
1738 tfs = (const struct true_false_string *) bootp_get_opt_data(code);
1740 i = tvb_get_guint8(tvb, optoff);
1741 if (i != 0 && i != 1) {
1742 proto_item_append_text(vti,
1743 " = Invalid Value %d", i);
1745 proto_item_append_text(vti, " = %s",
1746 i == 0 ? tfs->false_string : tfs->true_string);
1753 proto_item_append_text(vti,
1754 " - length isn't 1");
1757 vs = (const value_string *) bootp_get_opt_data(code);
1758 byte = tvb_get_guint8(tvb, optoff);
1760 proto_item_append_text(vti, " = %s",
1761 val_to_str(byte, vs, "Unknown (%u)"));
1763 proto_item_append_text(vti, " = %u", byte);
1770 proto_item_append_text(vti,
1771 " - length isn't 2");
1775 vs = (const value_string *) bootp_get_opt_data(code);
1776 vd = tvb_get_ntohs(tvb, optoff);
1779 proto_item_append_text(vti, " = %s",
1780 val_to_str(vd, vs, "Unknown (%u)"));
1782 proto_item_append_text(vti, " = %u", vd);
1787 case val_u_short_list:
1790 proto_item_append_text(vti, " = %u",
1791 tvb_get_ntohs(tvb, optoff));
1794 for (i = optoff, optleft = optlen; optleft > 0;
1795 i += 2, optleft -= 2) {
1797 proto_tree_add_text(v_tree, tvb, i, voff + consumed - i,
1798 "Option length isn't a multiple of 2");
1801 proto_tree_add_text(v_tree, tvb, i, 4, "Value: %u",
1802 tvb_get_ntohs(tvb, i));
1809 proto_item_append_text(vti,
1810 " - length isn't 4");
1813 proto_item_append_text(vti, " = %u",
1814 tvb_get_ntohl(tvb, optoff));
1819 proto_item_append_text(vti,
1820 " - length isn't 4");
1823 time_secs = tvb_get_ntohl(tvb, optoff);
1824 proto_item_append_text(vti, " = %s",
1825 ((time_secs == 0xffffffff) ?
1827 time_secs_to_str_unsigned(time_secs)));
1838 bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
1841 int suboptoff = optoff;
1842 guint8 subopt, vs_opt, vs_len;
1843 int subopt_len, datalen;
1846 proto_tree *subtree = 0;
1847 guint8 tag, tag_len;
1849 subopt = tvb_get_guint8(tvb, optoff);
1852 if (suboptoff >= optend) {
1853 proto_tree_add_text(v_tree, tvb, optoff, 1,
1854 "Suboption %d: no room left in option for suboption length",
1858 subopt_len = tvb_get_guint8(tvb, suboptoff);
1861 if (suboptoff+subopt_len > optend) {
1862 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
1863 "Suboption %d: no room left in option for suboption value",
1869 case 1: /* 1 Agent Circuit ID Sub-option [RFC3046] */
1870 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1871 "Agent Circuit ID: %s",
1872 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1875 case 2: /* 2 Agent Remote ID Sub-option [RFC3046] */
1876 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1877 "Agent Remote ID: %s",
1878 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1882 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1884 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1887 case 4: /* 4 DOCSIS Device Class Suboption [RFC3256] */
1888 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1889 "DOCSIS Device Class: %s",
1890 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1893 case 5: /* 5 Link selection Sub-option [RFC3527] */
1894 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1895 "Link selection: %s",
1896 ip_to_str(tvb_get_ptr(tvb, suboptoff, subopt_len)));
1899 case 6: /*Subscriber-ID Suboption [RFC3993] */
1900 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1901 "Subscriber ID: %s",
1902 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1905 case 7: /* 7 RADIUS Attributes Sub-option [RFC4014] */
1906 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1907 "RADIUS Attributes: %s",
1908 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1911 case 8: /* 8 Authentication Suboption [RFC4030] */
1912 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1913 "Authentication: %s",
1914 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1917 case 9: /* Vendor-Specific Information Suboption [RFC 4243] */
1918 while (suboptoff < optend) {
1919 enterprise = tvb_get_ntohl(tvb, suboptoff);
1920 vti = proto_tree_add_text(v_tree, tvb, suboptoff, 4,
1921 "Enterprise-number: %s-%u",
1922 val_to_str( enterprise, sminmpec_values, "Unknown"),
1926 if ( enterprise == 4491 ) {
1927 subtree = proto_item_add_subtree(vti, ett_bootp_option);
1928 vs_opt = tvb_get_guint8(tvb, suboptoff);
1930 vs_len = tvb_get_guint8(tvb, suboptoff);
1937 tag = tvb_get_guint8(tvb, suboptoff);
1938 tag_len = tvb_get_guint8(tvb, suboptoff+1);
1941 proto_tree_add_text(subtree, tvb, suboptoff, vs_len,
1942 "DOCSIS Version Number %d.%d",
1943 tvb_get_guint8(tvb, suboptoff),
1944 tvb_get_guint8(tvb, suboptoff+1));
1947 proto_tree_add_text(subtree, tvb, suboptoff, vs_len,
1948 "Unknown tag=%u %s (%d byte%s)", tag,
1949 tvb_bytes_to_str(tvb, suboptoff, tag_len),
1950 tag_len, plurality(tag_len, "", "s"));
1951 suboptoff += tag_len;
1957 proto_tree_add_text(subtree, tvb, suboptoff, vs_len,
1958 "Invalid suboption %d (%d byte%s)",
1959 vs_opt, vs_len, plurality(vs_len, "", "s"));
1963 datalen = tvb_get_guint8(tvb, suboptoff);
1964 proto_tree_add_text(v_tree, tvb, suboptoff, 1,
1965 "Data Length: %u", datalen);
1968 proto_tree_add_text(v_tree, tvb, suboptoff, datalen,
1969 "Suboption Data: %s", tvb_bytes_to_str(tvb, suboptoff, datalen));
1970 suboptoff += datalen;
1975 case 10: /* 10 Relay Agent Flags [RFC5010] */
1976 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1978 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
1981 case 11: /* Server Identifier Override Suboption [RFC 5107] */
1982 if (subopt_len == 4) {
1983 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1984 "Server ID Override: %s",
1985 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
1987 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1988 "Server ID Override: Invalid length (%d instead of 4)",
1994 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
1995 "Unknown agent suboption %d (%d bytes)",
1996 subopt, subopt_len);
1999 optoff += (subopt_len + 2);
2004 dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2005 int optoff, int optend)
2007 int suboptoff = optoff;
2011 proto_tree *o43pxeclient_v_tree;
2014 static struct opt_info o43pxeclient_opt[]= {
2015 /* 0 */ {"nop", special, NULL}, /* dummy */
2016 /* 1 */ {"PXE mtftp IP", ipv4_list, NULL},
2017 /* 2 */ {"PXE mtftp client port", val_u_le_short, NULL},
2018 /* 3 */ {"PXE mtftp server port",val_u_le_short, NULL},
2019 /* 4 */ {"PXE mtftp timeout", val_u_byte, NULL},
2020 /* 5 */ {"PXE mtftp delay", val_u_byte, NULL},
2021 /* 6 */ {"PXE discovery control", val_u_byte, NULL},
2023 * Correct: b0 (lsb): disable broadcast discovery
2024 * b1: disable multicast discovery
2025 * b2: only use/accept servers in boot servers
2026 * b3: download bootfile without prompt/menu/disc
2028 /* 7 */ {"PXE multicast address", ipv4_list, NULL},
2029 /* 8 */ {"PXE boot servers", special, NULL},
2030 /* 9 */ {"PXE boot menu", special, NULL},
2031 /* 10 */ {"PXE menu prompt", special, NULL},
2032 /* 11 */ {"PXE multicast address alloc", special, NULL},
2033 /* 12 */ {"PXE credential types", special, NULL},
2034 /* 71 {"PXE boot item", special, NULL}, */
2035 /* 255 {"PXE end options", special, NULL} */
2038 subopt = tvb_get_guint8(tvb, suboptoff);
2042 proto_tree_add_text(v_tree, tvb, optoff, 1, "Padding");
2044 } else if (subopt == 255) { /* End Option */
2045 proto_tree_add_text(v_tree, tvb, optoff, 1, "End PXEClient option");
2046 /* Make sure we skip any junk left this option */
2050 if (suboptoff >= optend) {
2051 proto_tree_add_text(v_tree, tvb, optoff, 1,
2052 "Suboption %d: no room left in option for suboption length",
2056 subopt_len = tvb_get_guint8(tvb, suboptoff);
2059 if (suboptoff+subopt_len > optend) {
2060 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2061 "Suboption %d: no room left in option for suboption value",
2065 if ( subopt == 71 ) { /* 71 {"PXE boot item", special} */
2067 /* I may need to decode that properly one day */
2068 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2069 "Suboption %d: %s (%d byte%s)" ,
2070 subopt, "PXE boot item",
2071 subopt_len, plurality(subopt_len, "", "s"));
2072 } else if ((subopt < 1) || (subopt >= array_length(o43pxeclient_opt))) {
2073 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2074 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
2075 plurality(subopt_len, "", "s"));
2077 switch (o43pxeclient_opt[subopt].ftype) {
2080 /* I may need to decode that properly one day */
2081 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2082 "Suboption %d: %s (%d byte%s)",
2083 subopt, o43pxeclient_opt[subopt].text,
2084 subopt_len, plurality(subopt_len, "", "s"));
2088 if (subopt_len == 4) {
2089 /* one IP address */
2090 proto_tree_add_text(v_tree, tvb, optoff, 6,
2091 "Suboption %d : %s = %s",
2092 subopt, o43pxeclient_opt[subopt].text,
2093 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2095 /* > 1 IP addresses. Let's make a sub-tree */
2096 vti = proto_tree_add_text(v_tree, tvb, optoff,
2097 subopt_len+2, "Suboption %d: %s",
2098 subopt, o43pxeclient_opt[subopt].text);
2099 o43pxeclient_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
2100 for (suboptleft = subopt_len; suboptleft > 0;
2101 suboptoff += 4, suboptleft -= 4) {
2102 if (suboptleft < 4) {
2103 proto_tree_add_text(o43pxeclient_v_tree,
2104 tvb, suboptoff, suboptleft,
2105 "Suboption length isn't a multiple of 4");
2108 proto_tree_add_text(o43pxeclient_v_tree,
2109 tvb, suboptoff, 4, "IP Address: %s",
2110 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2117 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2118 "Suboption %d: %s", subopt, o43pxeclient_opt[subopt].text);
2123 if (subopt_len != 1) {
2124 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2125 "Suboption %d: suboption length isn't 1", subopt);
2128 proto_tree_add_text(v_tree, tvb, optoff, 3, "Suboption %d: %s = %u",
2129 subopt, o43pxeclient_opt[subopt].text,
2130 tvb_get_guint8(tvb, suboptoff));
2133 case val_u_le_short:
2134 if (subopt_len != 2) {
2135 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2136 "Suboption %d: suboption length isn't 2", subopt);
2139 proto_tree_add_text(v_tree, tvb, optoff, 4, "Suboption %d: %s = %u",
2140 subopt, o43pxeclient_opt[subopt].text,
2141 tvb_get_letohs(tvb, suboptoff));
2145 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2149 optoff += (subopt_len + 2);
2153 /* RFC3825Decoder: http://www.enum.at/rfc3825encoder.529.0.html */
2155 rfc3825_lci_to_fixpoint(const unsigned char lci[16], struct rfc3825_location_fixpoint_t *fixpoint)
2157 fixpoint->latitude_res = (lci[0]>>2) & 0x3F; /* make sure that right-shift does not copy sign bit */
2158 if (lci[0] & 2) { /* LSB<<1 contains the sign of the latitude */
2159 /* Latitude is negative, expand two's complement */
2160 fixpoint->latitude = (((gint64)lci[0] & 3)<<32) | ((gint64)lci[1]<<24) |
2161 ((gint64)lci[2]<<16) | ((gint64)lci[3]<<8) |
2162 (gint64)lci[4] | ((gint64)0x3FFFFFFF<<34);
2165 /* Latitude is positive */
2166 fixpoint->latitude = (((gint64)lci[0] & 3)<<32) | ((gint64)lci[1]<<24) |
2167 ((gint64)lci[2]<<16) | ((gint64)lci[3]<<8) |
2170 fixpoint->longitude_res = (lci[5]>>2) & 0x3F; /* make sure that right-shift does not copy sign bit */
2171 if (lci[5] & 2) { /* LSB<<1 contains the sign of the latitude */
2172 /* Longitude is negative, expand two's complement */
2173 fixpoint->longitude = (((gint64)lci[5] & 3)<<32) | ((gint64)lci[6]<<24) |
2174 ((gint64)lci[7]<<16) | ((gint64)lci[8]<<8) |
2175 (gint64)lci[9] | ((gint64)0x3FFFFFFF<<34);
2178 /* Longitude is positive */
2179 fixpoint->longitude = (((gint64)lci[5] & 3)<<32) | ((gint64)lci[6]<<24) |
2180 ((gint64)lci[7]<<16) | ((gint64)lci[8]<<8) |
2183 fixpoint->altitude_type = (lci[10]>>4) & 0x0F; /* make sure that right-shift does not copy sign bit */
2184 fixpoint->altitude_res = ((lci[10] & 0x0F) << 2) | ((lci[11]>>6) & 0x03);
2185 if (lci[11] & 0x20) { /* LSB<<1 contains the sign of the latitude */
2186 /* Altitude is negative, expand two's complement */
2187 fixpoint->altitude = (((gint32)lci[11] & 0x3F)<<24) | ((gint32)lci[12]<<16) |
2188 ((gint32)lci[13]<<8) | ((gint32)lci[14]) |
2192 /* Altitudee is positive */
2193 fixpoint->altitude = (((gint32)lci[11] & 0x3F)<<24) | ((gint32)lci[12]<<16) |
2194 ((gint32)lci[13]<<8) | ((gint32)lci[14]);
2197 fixpoint->datum_type = lci[15];
2201 /* RFC3825Decoder: http://www.enum.at/rfc3825encoder.529.0.html */
2203 rfc3825_fixpoint_to_decimal(struct rfc3825_location_fixpoint_t *fixpoint, struct rfc3825_location_decimal_t *decimal)
2206 decimal->latitude = (double) fixpoint->latitude / (1 << 25);
2207 if ((decimal->latitude > 90) || (decimal->latitude < -90)) {
2208 return RFC3825_LATITUDE_OUTOFRANGE;
2211 /* Latitude Uncertainty */
2212 if (fixpoint->latitude_res > 34) {
2213 return RFC3825_LATITUDE_UNCERTAINTY_OUTOFRANGE;
2215 if (fixpoint->latitude_res > 8 ) {
2216 decimal->latitude_res = (double) 1 / (1 << (fixpoint->latitude_res - 8));
2218 decimal->latitude_res = 1 << (8 - fixpoint->latitude_res);
2222 decimal->longitude = (double) fixpoint->longitude / (1 << 25);
2223 if ((decimal->longitude > 180) || (decimal->longitude < -180)) {
2224 return RFC3825_LONGITUDE_OUTOFRANGE;
2227 /* Longitude Uncertainty */
2228 if (fixpoint->longitude_res > 34) {
2229 return RFC3825_LONGITUDE_UNCERTAINTY_OUTOFRANGE;
2231 if (fixpoint->longitude_res > 8 ) {
2232 decimal->longitude_res = (double) 1 / (1 << (fixpoint->longitude_res - 8));
2234 decimal->longitude_res = 1 << (8 - fixpoint->longitude_res);
2238 decimal->altitude_type = fixpoint->altitude_type;
2239 decimal->altitude = 0;
2240 decimal->altitude_res = 0;
2242 if (decimal->altitude_type == 0) { /* Unknown */
2243 } else if (decimal->altitude_type == 1) { /* Meters */
2245 decimal->altitude = (double) fixpoint->altitude / (1 << 8);
2246 if ((decimal->altitude > ((gint32) 1<<21)-1) || (decimal->altitude < ((gint32) -(1<<21))))
2247 return RFC3825_ALTITUDE_OUTOFRANGE;
2249 /* Altitude Uncertainty */
2250 if (fixpoint->altitude_res > 30) {
2251 return RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE;
2253 if (fixpoint->altitude_res > 21 ) {
2254 decimal->altitude_res = (double) 1 / (1 << (fixpoint->altitude_res - 21));
2256 decimal->altitude_res = 1 << (21 - fixpoint->altitude_res);
2258 } else if (decimal->altitude_type == 2) { /* Floors */
2260 if ((fixpoint->altitude_res != 30) && (fixpoint->altitude_res != 0)) {
2261 return RFC3825_ALTITUDE_UNCERTAINTY_OUTOFRANGE;
2263 decimal->altitude = (double) fixpoint->altitude / (1 << 8);
2264 } else { /* invalid type */
2265 return RFC3825_ALTITUDE_TYPE_OUTOFRANGE;
2269 decimal->datum_type = 0;
2270 if ((fixpoint->datum_type > 3) || (fixpoint->datum_type < 1)) {
2271 return RFC3825_DATUM_TYPE_OUTOFRANGE;
2273 decimal->datum_type = fixpoint->datum_type;
2275 return RFC3825_NOERROR;
2280 dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2281 int optoff, int optend)
2283 int suboptoff = optoff;
2284 guint8 subopt, byte_val;
2287 static struct opt_info o43cablelabs_opt[]= {
2288 /* 0 */ {"nop", special, NULL}, /* dummy */
2289 /* 1 */ {"Suboption Request List", string, NULL},
2290 /* 2 */ {"Device Type", string, NULL},
2291 /* 3 */ {"eSAFE Types", string, NULL},
2292 /* 4 */ {"Serial Number", string, NULL},
2293 /* 5 */ {"Hardware Version", string, NULL},
2294 /* 6 */ {"Software Version", string, NULL},
2295 /* 7 */ {"Boot ROM version", string, NULL},
2296 /* 8 */ {"Organizationally Unique Identifier", special, NULL},
2297 /* 9 */ {"Model Number", string, NULL},
2298 /* 10 */ {"Vendor Name", string, NULL},
2299 /* *** 11-30: CableHome *** */
2300 /* 11 */ {"Address Realm", special, NULL},
2301 /* 12 */ {"CM/PS System Description", string, NULL},
2302 /* 13 */ {"CM/PS Firmware Revision", string, NULL},
2303 /* 14 */ {"Firewall Policy File Version", string, NULL},
2304 /* 15 */ {"eSafe Config File Devices", string, NULL},
2305 /* 16 */ {"Unassigned (CableHome)", special, NULL},
2306 /* 17 */ {"Unassigned (CableHome)", special, NULL},
2307 /* 18 */ {"Video Security Type", string, NULL},
2308 /* 19 */ {"Unassigned (CableHome)", special, NULL},
2309 /* 20 */ {"Unassigned (CableHome)", special, NULL},
2310 /* 21 */ {"Unassigned (CableHome)", special, NULL},
2311 /* 22 */ {"Unassigned (CableHome)", special, NULL},
2312 /* 23 */ {"Unassigned (CableHome)", special, NULL},
2313 /* 24 */ {"Unassigned (CableHome)", special, NULL},
2314 /* 25 */ {"Unassigned (CableHome)", special, NULL},
2315 /* 26 */ {"Unassigned (CableHome)", special, NULL},
2316 /* 27 */ {"Unassigned (CableHome)", special, NULL},
2317 /* 28 */ {"Unassigned (CableHome)", special, NULL},
2318 /* 29 */ {"Unassigned (CableHome)", special, NULL},
2319 /* 30 */ {"Unassigned (CableHome)", special, NULL},
2320 /* *** 31-50: PacketCable *** */
2321 /* 31 */ {"MTA MAC Address", special, NULL},
2322 /* 32 */ {"Correlation ID", val_u_long, NULL},
2323 /* 33 */ {"Unassigned (PacketCable)", special, NULL},
2324 /* 34 */ {"Unassigned (PacketCable)", special, NULL},
2325 /* 35 */ {"Unassigned (PacketCable)", special, NULL},
2326 /* 36 */ {"Unassigned (PacketCable)", special, NULL},
2327 /* 37 */ {"Unassigned (PacketCable)", special, NULL},
2328 /* 38 */ {"Unassigned (PacketCable)", special, NULL},
2329 /* 39 */ {"Unassigned (PacketCable)", special, NULL},
2330 /* 40 */ {"Unassigned (PacketCable)", special, NULL},
2331 /* 41 */ {"Unassigned (PacketCable)", special, NULL},
2332 /* 42 */ {"Unassigned (PacketCable)", special, NULL},
2333 /* 43 */ {"Unassigned (PacketCable)", special, NULL},
2334 /* 44 */ {"Unassigned (PacketCable)", special, NULL},
2335 /* 45 */ {"Unassigned (PacketCable)", special, NULL},
2336 /* 46 */ {"Unassigned (PacketCable)", special, NULL},
2337 /* 47 */ {"Unassigned (PacketCable)", special, NULL},
2338 /* 48 */ {"Unassigned (PacketCable)", special, NULL},
2339 /* 49 */ {"Unassigned (PacketCable)", special, NULL},
2340 /* 50 */ {"Unassigned (PacketCable)", special, NULL},
2341 /* *** 51-127: CableLabs *** */
2342 /* 51 */ {"Vendor Name", string, NULL},
2343 /* 52 */ {"CableCARD Capability", special, NULL},
2344 /* 53 */ {"Device Identification (CA)", special, NULL},
2345 /* 54 */ {"Device Identification (X.509)", string, NULL},
2346 /* 55 */ {"Unassigned (CableLabs)", special, NULL},
2347 /* *** 128-254: Vendors *** */
2348 /* 128-254 {"Unassigned (Vendors)", special, NULL}, */
2349 /* 255 {"end options", special, NULL} */
2352 static const value_string cablehome_subopt11_vals[] = {
2353 { 1, "PS WAN-Man" },
2354 { 2, "PS WAN-Data" },
2358 subopt = tvb_get_guint8(tvb, suboptoff);
2362 proto_tree_add_text(v_tree, tvb, optoff, 1, "Padding");
2364 } else if (subopt == 255) { /* End Option */
2365 proto_tree_add_text(v_tree, tvb, optoff, 1, "End CableLabs option");
2366 /* Make sure we skip any junk left this option */
2370 if (suboptoff >= optend) {
2371 proto_tree_add_text(v_tree, tvb, optoff, 1,
2372 "Suboption %d: no room left in option for suboption length",
2376 subopt_len = tvb_get_guint8(tvb, suboptoff);
2379 if (suboptoff+subopt_len > optend) {
2380 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2381 "Suboption %d: no room left in option for suboption value",
2385 if ( (subopt < 1 ) || (subopt >= array_length(o43cablelabs_opt)) ) {
2386 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2387 "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len,
2388 plurality(subopt_len, "", "s"));
2390 switch (o43cablelabs_opt[subopt].ftype) {
2393 if ( subopt == 8 ) { /* OUI */
2394 /* CableLabs specs treat 43.8 inconsistently
2395 * as either binary (3b) or string (6b) */
2396 if (subopt_len == 3) {
2397 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2398 "Suboption %d: OUI = %s", subopt,
2399 bytes_to_str_punct(tvb_get_ptr(tvb, suboptoff, 3), 3, ':'));
2400 } else if (subopt_len == 6) {
2401 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2402 "Suboption %d: OUI = \"%s\"", subopt,
2403 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2405 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2406 "Suboption %d: suboption length isn't 3 or 6", subopt);
2409 } else if ( subopt == 11 ) { /* Address Realm */
2410 if (subopt_len != 1) {
2411 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2412 "Suboption %d: suboption length isn't 1", subopt);
2415 byte_val = tvb_get_guint8(tvb, suboptoff);
2416 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2417 "Suboption %d: %s = %s (0x%02x)",
2418 subopt, o43cablelabs_opt[subopt].text,
2419 val_to_str(byte_val, cablehome_subopt11_vals, "Unknown"), byte_val);
2420 } else if ( subopt == 31 ) { /* MTA MAC address */
2421 if (subopt_len != 6) {
2422 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2423 "Suboption %d: suboption length isn't 6", subopt);
2426 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2427 "Suboption %d: %s = %s",
2428 subopt, o43cablelabs_opt[subopt].text,
2429 bytes_to_str_punct(tvb_get_ptr(tvb, suboptoff, 6), 6, ':'));
2431 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2432 "Suboption %d: %s (%d byte%s)" ,
2433 subopt, o43cablelabs_opt[subopt].text,
2434 subopt_len, plurality(subopt_len, "", "s"));
2439 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2440 "Suboption %d: %s = \"%s\"", subopt,
2441 o43cablelabs_opt[subopt].text,
2442 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2446 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2447 "Suboption %d: %s = 0x%s", subopt,
2448 o43cablelabs_opt[subopt].text,
2449 tvb_bytes_to_str(tvb, suboptoff, subopt_len));
2453 if (subopt_len != 4) {
2454 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2455 "Suboption %d: suboption length isn't 4", subopt);
2458 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2459 "Suboption %d: %s = %u", subopt,
2460 o43cablelabs_opt[subopt].text,
2461 tvb_get_ntohl(tvb, suboptoff));
2465 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2469 optoff += (subopt_len + 2);
2476 dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2477 int optoff, int optend)
2479 int suboptoff = optoff;
2483 const struct true_false_string *tfs;
2485 proto_tree *o63_v_tree;
2488 static struct opt_info o63_opt[]= {
2489 /* 0 */ {"",none,NULL},
2490 /* 1 */ {"NWIP does not exist on subnet",presence,NULL},
2491 /* 2 */ {"NWIP exists in options area",presence,NULL},
2492 /* 3 */ {"NWIP exists in sname/file",presence,NULL},
2493 /* 4 */ {"NWIP exists, but too big",presence,NULL},
2494 /* 5 */ {"Broadcast for nearest Netware server",val_boolean,TFS(&tfs_yes_no)},
2495 /* 6 */ {"Preferred DSS server",ipv4_list,NULL},
2496 /* 7 */ {"Nearest NWIP server",ipv4_list,NULL},
2497 /* 8 */ {"Autoretries",val_u_byte,NULL},
2498 /* 9 */ {"Autoretry delay, secs",val_u_byte,NULL},
2499 /* 10*/ {"Support NetWare/IP v1.1",val_boolean,TFS(&tfs_yes_no)},
2500 /* 11*/ {"Primary DSS",ipv4,NULL}
2503 subopt = tvb_get_guint8(tvb, optoff);
2506 if (suboptoff >= optend) {
2507 proto_tree_add_text(v_tree, tvb, optoff, 1,
2508 "Suboption %d: no room left in option for suboption length",
2512 subopt_len = tvb_get_guint8(tvb, suboptoff);
2515 if (subopt >= array_length(o63_opt)) {
2516 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2, "Unknown suboption %d", subopt);
2518 switch (o63_opt[subopt].ftype) {
2521 if (subopt_len != 0) {
2522 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2523 "Suboption %d: length isn't 0", subopt);
2526 proto_tree_add_text(v_tree, tvb, optoff, 2, "Suboption %d: %s", subopt, o63_opt[subopt].text);
2530 if (subopt_len != 4) {
2531 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2532 "Suboption %d: length isn't 4", subopt);
2535 if (suboptoff+4 > optend) {
2536 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2537 "Suboption %d: no room left in option for suboption value",
2541 proto_tree_add_text(v_tree, tvb, optoff, 6,
2542 "Suboption %d: %s = %s" ,
2543 subopt, o63_opt[subopt].text,
2544 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2548 if (subopt_len == 4) {
2549 /* one IP address */
2550 proto_tree_add_text(v_tree, tvb, optoff, 6,
2551 "Suboption %d : %s = %s",
2552 subopt, o63_opt[subopt].text,
2553 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2555 /* > 1 IP addresses. Let's make a sub-tree */
2556 vti = proto_tree_add_text(v_tree, tvb, optoff,
2557 subopt_len+2, "Suboption %d: %s",
2558 subopt, o63_opt[subopt].text);
2559 o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
2560 for (suboptleft = subopt_len; suboptleft > 0;
2561 suboptoff += 4, suboptleft -= 4) {
2562 if (suboptleft < 4) {
2563 proto_tree_add_text(o63_v_tree,
2564 tvb, suboptoff, suboptleft,
2565 "Suboption length isn't a multiple of 4");
2568 proto_tree_add_text(o63_v_tree, tvb, suboptoff, 4, "IP Address: %s",
2569 ip_to_str(tvb_get_ptr(tvb, suboptoff, 4)));
2575 if (subopt_len != 1) {
2576 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2577 "Suboption %d: suboption length isn't 1", subopt);
2580 if (suboptoff+1 > optend) {
2581 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2582 "Suboption %d: no room left in option for suboption value",
2586 tfs = (const struct true_false_string *) o63_opt[subopt].data;
2587 i = tvb_get_guint8(tvb, suboptoff);
2588 if (i != 0 && i != 1) {
2589 proto_tree_add_text(v_tree, tvb, optoff, 3,
2590 "Suboption %d: %s = Invalid Value %d",
2591 subopt, o63_opt[subopt].text, i);
2593 proto_tree_add_text(v_tree, tvb, optoff, 3,
2594 "Suboption %d: %s = %s", subopt,
2595 o63_opt[subopt].text,
2596 i == 0 ? tfs->false_string : tfs->true_string);
2601 if (subopt_len != 1) {
2602 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
2603 "Suboption %d: length isn't 1", subopt);
2606 if (suboptoff+1 > optend) {
2607 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2608 "Suboption %d: no room left in option for suboption value",
2612 proto_tree_add_text(v_tree, tvb, optoff, 3, "Suboption %d: %s = %u",
2613 subopt, o63_opt[subopt].text,
2614 tvb_get_guint8(tvb, suboptoff));
2618 proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,"Unknown suboption %d", subopt);
2622 optoff += (subopt_len + 2);
2629 dissect_vendor_tr111_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2630 int optoff, int optend)
2632 int suboptoff = optoff;
2636 /* Reference: TR-111 DHCP Option 125 Sub-Option Data Fields
2640 static struct opt_info o125_tr111_opt[]= {
2641 /* 0 */ {"nop", special, NULL}, /* dummy */
2642 /* 1 */ {"DeviceManufacturerOUI", string, NULL},
2643 /* 2 */ {"DeviceSerialNumber", string, NULL},
2644 /* 3 */ {"DeviceProductClass", string, NULL},
2645 /* 4 */ {"GatewayManufacturerOUI", string, NULL},
2646 /* 5 */ {"GatewaySerialNumber", string, NULL},
2647 /* 6 */ {"GatewayProductClass", string, NULL},
2650 subopt = tvb_get_guint8(tvb, suboptoff);
2653 if (suboptoff >= optend) {
2654 proto_tree_add_text(v_tree, tvb, optoff, 1,
2655 "Suboption %d: no room left in option for suboption length",
2659 subopt_len = tvb_get_guint8(tvb, suboptoff);
2662 if (suboptoff+subopt_len > optend) {
2663 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2664 "Suboption %d: no room left in option for suboption value",
2670 if ((subopt < 1) || (subopt >= array_length(o125_tr111_opt))) {
2671 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2672 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
2673 plurality(subopt_len, "", "s"));
2675 switch (o125_tr111_opt[subopt].ftype) {
2678 /* I may need to decode that properly one day */
2679 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2680 "Suboption %d: %s (%d byte%s)",
2681 subopt, o125_tr111_opt[subopt].text,
2682 subopt_len, plurality(subopt_len, "", "s"));
2686 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2687 "Suboption %d: %s = \"%s\"", subopt,
2688 o125_tr111_opt[subopt].text,
2689 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2693 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2697 optoff += (subopt_len + 2);
2702 dissect_vendor_cl_suboption(proto_tree *v_tree, tvbuff_t *tvb,
2703 int optoff, int optend)
2705 int suboptoff = optoff;
2709 proto_tree *subtree;
2712 static struct opt_info o125_cl_opt[]= {
2713 /* 0 */ {"nop", special, NULL}, /* dummy */
2714 /* 1 */ {"Option Request = ", val_u_byte, NULL},
2715 /* 2 */ {"TFTP Server Addresses : ", ipv4_list, NULL},
2716 /* 3 */ {"eRouter Container Option : ", bytes, NULL},
2717 /* 4 */ {"MIB Environment Indicator Option = ", special, NULL},
2718 /* 5 */ {"Modem Capabilities : ", special, NULL},
2721 static const value_string pkt_mib_env_ind_opt_vals[] = {
2722 { 0x00, "Reserved" },
2723 { 0x01, "CableLabs" },
2725 { 0x03, "EuroCableLabs" },
2729 subopt = tvb_get_guint8(tvb, suboptoff);
2732 if (suboptoff >= optend) {
2733 proto_tree_add_text(v_tree, tvb, optoff, 1,
2734 "Suboption %d: no room left in option for suboption length",
2738 subopt_len = tvb_get_guint8(tvb, suboptoff);
2741 if (suboptoff+subopt_len > optend) {
2742 proto_tree_add_text(v_tree, tvb, optoff, optend-optoff,
2743 "Suboption %d: no room left in option for suboption value",
2748 if ((subopt < 1) || (subopt >= array_length(o125_cl_opt))) {
2749 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2750 "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
2751 plurality(subopt_len, "", "s"));
2753 switch (o125_cl_opt[subopt].ftype) {
2756 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2757 "Suboption %d: %s%s (%d byte%s)", subopt,
2758 o125_cl_opt[subopt].text,
2759 tvb_bytes_to_str(tvb, suboptoff, subopt_len),
2760 subopt_len, plurality(subopt_len, "", "s"));
2764 ti = proto_tree_add_text(v_tree, tvb, optoff, 2,
2765 "Suboption %d %s", subopt, o125_cl_opt[subopt].text);
2767 if ((subopt_len % 4) != 0) {
2768 proto_item_append_text(ti,
2769 "Invalid length for suboption %d (%d byte%s)", subopt, subopt_len,
2770 plurality(subopt_len, "", "s"));
2772 subtree = proto_item_add_subtree(ti, ett_bootp_option);
2773 for (i = 0; i < subopt_len; i+=4) {
2774 proto_tree_add_text(subtree, tvb, suboptoff+i, 4, "IP Address: %s",
2775 ip_to_str(tvb_get_ptr(tvb, (suboptoff+i), 4)));
2782 val = tvb_get_guint8(tvb, suboptoff);
2783 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2784 "Suboption %d: %s%s", subopt,
2785 o125_cl_opt[subopt].text,
2786 val_to_str(tvb_get_guint8(tvb, suboptoff),
2787 pkt_mib_env_ind_opt_vals, "unknown"));
2790 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2791 "Suboption %d: %s%s (%d byte%s)",
2792 subopt, o125_cl_opt[subopt].text,
2793 tvb_bytes_to_str(tvb, suboptoff, subopt_len),
2794 subopt_len, plurality(subopt_len, "", "s"));
2799 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2800 "Suboption %d: %s\"%s\"", subopt,
2801 o125_cl_opt[subopt].text,
2802 tvb_format_stringzpad(tvb, suboptoff, subopt_len));
2806 val = tvb_get_guint8(tvb, suboptoff);
2807 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2808 "Suboption %d: %s%d", subopt,
2809 o125_cl_opt[subopt].text, val);
2813 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,
2814 "Suboption %d: %s%d", subopt,
2815 o125_cl_opt[subopt].text,
2816 tvb_get_ntohs(tvb, suboptoff));
2820 proto_tree_add_text(v_tree, tvb, optoff, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
2824 optoff += (subopt_len + 2);
2828 /* PacketCable Multimedia Terminal Adapter device capabilities (option 60).
2829 Ref: PKT-SP-I05-021127 sections 8.2 and 10 */
2831 #define PKT_MDC_TLV_OFF 10
2834 /* These are ASCII-encoded hexadecimal digits. We use the raw hex equivalent for
2836 #define PKT_MDC_VERSION 0x3031 /* "01" */
2837 #define PKT_MDC_TEL_END 0x3032 /* "02" */
2838 #define PKT_MDC_TGT 0x3033 /* "03" */
2839 #define PKT_MDC_HTTP_ACC 0x3034 /* "04" */
2840 #define PKT_MDC_SYSLOG 0x3035 /* "05" */
2841 #define PKT_MDC_NCS 0x3036 /* "06" */
2842 #define PKT_MDC_PRI_LINE 0x3037 /* "07" */
2843 #define PKT_MDC_VENDOR_TLV 0x3038 /* "08" */
2844 #define PKT_MDC_NVRAM_STOR 0x3039 /* "09" */
2845 #define PKT_MDC_PROV_REP 0x3041 /* "0A" */
2846 #define PKT_MDC_PROV_REP_LC 0x3061 /* "0A" */
2847 #define PKT_MDC_SUPP_CODECS 0x3042 /* "0B" */
2848 #define PKT_MDC_SUPP_CODECS_LC 0x3062 /* "0b" */
2849 #define PKT_MDC_SILENCE 0x3043 /* "0C" */
2850 #define PKT_MDC_SILENCE_LC 0x3063 /* "0c" */
2851 #define PKT_MDC_ECHO_CANCEL 0x3044 /* "0D" */
2852 #define PKT_MDC_ECHO_CANCEL_LC 0x3064 /* "0d" */
2853 #define PKT_MDC_RSVP 0x3045 /* "0E" */
2854 #define PKT_MDC_RSVP_LC 0x3065 /* "0e" */
2855 #define PKT_MDC_UGS_AD 0x3046 /* "0F" */
2856 #define PKT_MDC_UGS_AD_LC 0x3066 /* "0f" */
2857 #define PKT_MDC_IF_INDEX 0x3130 /* "10" */
2858 #define PKT_MDC_FLOW_LOG 0x3131 /* "11" */
2859 #define PKT_MDC_PROV_FLOWS 0x3132 /* "12" */
2860 /* PacketCable 1.5: */
2861 #define PKT_MDC_T38_VERSION 0x3133 /* "13" */
2862 #define PKT_MDC_T38_EC 0x3134 /* "14" */
2863 #define PKT_MDC_RFC2833_DTMF 0x3135 /* "15" */
2864 #define PKT_MDC_VOICE_METRICS 0x3136 /* "16" */
2865 #define PKT_MDC_MIBS 0x3137 /* "17" */
2866 #define PKT_MDC_MGPI 0x3138 /* "18" */
2867 #define PKT_MDC_V152 0x3139 /* "19" */
2869 static const value_string pkt_mdc_type_vals[] = {
2870 { PKT_MDC_VERSION, "PacketCable Version" },
2871 { PKT_MDC_TEL_END, "Number Of Telephony Endpoints" },
2872 { PKT_MDC_TGT, "TGT Support" },
2873 { PKT_MDC_HTTP_ACC, "HTTP Download File Access Method Support" },
2874 { PKT_MDC_SYSLOG, "MTA-24 Event SYSLOG Notification Support" },
2875 { PKT_MDC_NCS, "NCS Service Flow Support" },
2876 { PKT_MDC_PRI_LINE, "Primary Line Support" },
2877 { PKT_MDC_VENDOR_TLV, "Vendor Specific TLV Type(s)" },
2878 { PKT_MDC_NVRAM_STOR, "NVRAM Ticket/Session Keys Storage Support" },
2879 { PKT_MDC_PROV_REP, "Provisioning Event Reporting Support" },
2880 { PKT_MDC_PROV_REP_LC, "Provisioning Event Reporting Support" },
2881 { PKT_MDC_SUPP_CODECS, "Supported CODEC(s)" },
2882 { PKT_MDC_SUPP_CODECS_LC, "Supported CODEC(s)" },
2883 { PKT_MDC_SILENCE, "Silence Suppression Support" },
2884 { PKT_MDC_SILENCE_LC, "Silence Suppression Support" },
2885 { PKT_MDC_ECHO_CANCEL, "Echo Cancellation Support" },
2886 { PKT_MDC_ECHO_CANCEL_LC, "Echo Cancellation Support" },
2887 { PKT_MDC_RSVP, "RSVP Support/ Reserved" },
2888 { PKT_MDC_RSVP_LC, "RSVP Support/ Reserved" },
2889 { PKT_MDC_UGS_AD, "UGS-AD Support" },
2890 { PKT_MDC_UGS_AD_LC, "UGS-AD Support" },
2891 { PKT_MDC_IF_INDEX, "MTA's \"ifIndex\" starting number in \"ifTable\"" },
2892 { PKT_MDC_FLOW_LOG, "Provisioning Flow Logging Support" },
2893 { PKT_MDC_PROV_FLOWS, "Supported Provisioning Flows" },
2894 /* PacketCable 1.5: */
2895 { PKT_MDC_T38_VERSION, "T38 Version Support" },
2896 { PKT_MDC_T38_EC, "T38 Error Correction Support" },
2897 { PKT_MDC_RFC2833_DTMF, "RFC 2833 DTMF Support" },
2898 { PKT_MDC_VOICE_METRICS, "Voice Metrics Support" },
2899 { PKT_MDC_MIBS, "MIB Support" },
2900 { PKT_MDC_MGPI, "Multiple Grants Per Interval Support" },
2901 { PKT_MDC_V152, "V.152 Support" },
2905 static const value_string pkt_mdc_version_vals[] = {
2906 { 0x3030, "PacketCable 1.0" },
2907 { 0x3031, "PacketCable 1.1/1.5" }, /* 1.5 replaces 1.1-1.3 */
2908 { 0x3032, "PacketCable 1.2" },
2909 { 0x3033, "PacketCable 1.3" },
2913 static const value_string pkt_mdc_boolean_vals[] = {
2919 static const value_string pkt_mdc_codec_vals[] = {
2920 { 0x3031, "other" }, /* "01" */
2921 { 0x3032, "unknown" },
2922 { 0x3033, "G.729" },
2923 { 0x3034, "reserved" },
2924 { 0x3035, "G.729E" },
2926 { 0x3037, "G.726-32" },
2927 { 0x3038, "G.728" },
2928 { 0x3039, "PCMA" }, /* "09" */
2929 { 0x3041, "G.726-16" }, /* "0A" */
2930 { 0x3042, "G.726-24" },
2931 { 0x3043, "G.726-40" },
2934 { 0x3046, "telephone-event" }, /* "0F" */
2938 static const value_string pkt_mdc_t38_version_vals[] = {
2939 { 0x3030, "Unsupported" },
2940 { 0x3031, "T.38 Version Zero" }, /* default */
2941 { 0x3032, "T.38 Version One" },
2942 { 0x3033, "T.38 Version Two" },
2943 { 0x3035, "T.38 Version Three" },
2947 static const value_string pkt_mdc_t38_ec_vals[] = {
2949 { 0x3031, "Redundancy" }, /* default */
2954 static const value_string pkt_mdc_mib_orgs[] = {
2955 { 0x3030, "CableLabs" },
2957 { 0x3032, "Reserved" },
2958 { 0x3033, "Reserved" },
2959 { 0x3034, "Reserved" },
2960 { 0x3035, "Reserved" },
2961 { 0x3036, "Reserved" },
2962 { 0x3037, "Reserved" },
2963 { 0x3038, "Reserved" },
2964 { 0x3039, "Reserved" },
2968 /* DOCSIS Cable Modem device capabilities (option 60). */
2969 #define DOCS_CM_TLV_OFF 12
2971 #define DOCS_CM_CONCAT_SUP 0x3031 /* "01" */
2972 #define DOCS_CM_DOCSIS_VER 0x3032 /* "02" */
2973 #define DOCS_CM_FRAG_SUP 0x3033 /* "03" */
2974 #define DOCS_CM_PHS_SUP 0x3034 /* "04" */
2975 #define DOCS_CM_IGMP_SUP 0x3035 /* "05" */
2976 #define DOCS_CM_PRIV_SUP 0x3036 /* "06" */
2977 #define DOCS_CM_DSAID_SUP 0x3037 /* "07" */
2978 #define DOCS_CM_USID_SUP 0x3038 /* "08" */
2979 #define DOCS_CM_FILT_SUP 0x3039 /* "09" */
2980 #define DOCS_CM_TET_MI 0x3041 /* "0A" */
2981 #define DOCS_CM_TET_MI_LC 0x3061 /* "0a" */
2982 #define DOCS_CM_TET 0x3042 /* "0B" */
2983 #define DOCS_CM_TET_LC 0x3062 /* "0b" */
2984 #define DOCS_CM_DCC_SUP 0x3043 /* "0C" */
2985 #define DOCS_CM_DCC_SUP_LC 0x3063 /* "0c" */
2986 #define DOCS_CM_IPFILT_SUP 0x3044 /* "0D" */
2987 #define DOCS_CM_IPFILT_SUP_LC 0x3064 /* "0d" */
2988 #define DOCS_CM_LLCFILT_SUP 0x3045 /* "0E" */
2989 #define DOCS_CM_LLCFILT_SUP_LC 0x3065 /* "0e" */
2991 static const value_string docs_cm_type_vals[] = {
2992 { DOCS_CM_CONCAT_SUP, "Concatenation Support" },
2993 { DOCS_CM_DOCSIS_VER, "DOCSIS Version" },
2994 { DOCS_CM_FRAG_SUP, "Fragmentation Support" },
2995 { DOCS_CM_PHS_SUP, "PHS Support" },
2996 { DOCS_CM_IGMP_SUP, "IGMP Support" },
2997 { DOCS_CM_PRIV_SUP, "Privacy Support" },
2998 { DOCS_CM_DSAID_SUP, "Downstream SAID Support" },
2999 { DOCS_CM_USID_SUP, "Upstream SID Support" },
3000 { DOCS_CM_FILT_SUP, "Optional Filtering Support" },
3001 { DOCS_CM_TET_MI, "Transmit Equalizer Taps per Modulation Interval" },
3002 { DOCS_CM_TET_MI_LC, "Transmit Equalizer Taps per Modulation Interval" },
3003 { DOCS_CM_TET, "Number of Transmit Equalizer Taps" },
3004 { DOCS_CM_TET_LC, "Number of Transmit Equalizer Taps" },
3005 { DOCS_CM_DCC_SUP, "DCC Support" },
3006 { DOCS_CM_DCC_SUP_LC, "DCC Support" },
3007 { DOCS_CM_IPFILT_SUP, "IP Filters Support" },
3008 { DOCS_CM_IPFILT_SUP_LC, "IP Filters Support" },
3009 { DOCS_CM_LLCFILT_SUP, "LLC Filters Support" },
3010 { DOCS_CM_LLCFILT_SUP_LC, "LLC Filters Support" },
3014 static const value_string docs_cm_version_vals[] = {
3015 { 0x3030, "DOCSIS 1.0" },
3016 { 0x3031, "DOCSIS 1.1" },
3017 { 0x3032, "DOCSIS 2.0" },
3018 { 0x3033, "DOCSIS 3.0" },
3022 static const value_string docs_cm_privacy_vals[] = {
3023 { 0x3030, "BPI Support" },
3024 { 0x3031, "BPI Plus Support" },
3029 static const value_string pkt_mdc_supp_flow_vals[] = {
3030 { 1 << 0, "Secure Flow (Full Secure Provisioning Flow)" },
3031 { 1 << 1, "Hybrid Flow" },
3032 { 1 << 2, "Basic Flow" },
3036 #define PKT_MDC_MIB_CL 0x3030
3037 static const value_string pkt_mdc_cl_mib_vals[] = {
3038 { 1 << 0, "PacketCable 1.5 MTA MIB" },
3039 { 1 << 1, "PacketCable 1.5 Signaling MIB" },
3040 { 1 << 2, "PacketCable 1.5 Management Event MIB" },
3041 { 1 << 3, "PacketCable 1.5 MTA Extension MIB" },
3042 { 1 << 4, "PacketCable 1.5 Signaling Extension MIB" },
3043 { 1 << 5, "PacketCable 1.5 MEM Extension MIB" },
3044 { 1 << 6, "Reserved" },
3045 { 1 << 7, "Reserved" },
3049 #define PKT_MDC_MIB_IETF 0x3031
3050 static const value_string pkt_mdc_ietf_mib_vals[] = {
3051 { 1 << 0, "IETF MTA MIB" },
3052 { 1 << 1, "IETF Signaling MIB" },
3053 { 1 << 2, "IETF Management Event MIB" },
3054 { 1 << 3, "Reserved" },
3055 { 1 << 4, "Reserved" },
3056 { 1 << 5, "Reserved" },
3057 { 1 << 6, "Reserved" },
3058 { 1 << 7, "Reserved" },
3064 dissect_packetcable_mta_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
3067 unsigned long flow_val = 0;
3068 int off = PKT_MDC_TLV_OFF + voff;
3069 int subopt_off, max_len;
3070 guint tlv_len, i, mib_val;
3071 guint8 asc_val[3] = " ", flow_val_str[5];
3073 proto_item *ti, *mib_ti;
3074 proto_tree *subtree, *subtree2;
3076 tvb_memcpy (tvb, asc_val, off, 2);
3077 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len > 0xff) {
3078 proto_tree_add_text(v_tree, tvb, off, len - off,
3079 "Bogus length: %s", asc_val);
3082 proto_tree_add_uint_format_value(v_tree, hf_bootp_pkt_mtacap_len, tvb, off, 2,
3083 tlv_len, "%d", tlv_len);
3086 while (off - voff < len) {
3088 raw_val = tvb_get_ntohs (tvb, off);
3091 tvb_memcpy(tvb, asc_val, off + 2, 2);
3092 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len < 1) {
3093 proto_tree_add_text(v_tree, tvb, off, len - off,
3094 "[Bogus length: %s]", asc_val);
3099 ti = proto_tree_add_text(v_tree,
3100 tvb, off, (tlv_len * 2) + 4,
3102 tvb_format_text(tvb, off, 2),
3103 val_to_str(raw_val, pkt_mdc_type_vals, "unknown"));
3106 case PKT_MDC_VERSION:
3107 raw_val = tvb_get_ntohs(tvb, off + 4);
3108 proto_item_append_text(ti,
3110 val_to_str(raw_val, pkt_mdc_version_vals, "Reserved"),
3111 tvb_format_stringzpad(tvb, off + 4, 2) );
3114 case PKT_MDC_TEL_END:
3115 case PKT_MDC_IF_INDEX:
3116 proto_item_append_text(ti,
3118 tvb_format_stringzpad(tvb, off + 4, 2) );
3122 case PKT_MDC_HTTP_ACC:
3123 case PKT_MDC_SYSLOG:
3125 case PKT_MDC_PRI_LINE:
3126 case PKT_MDC_NVRAM_STOR:
3127 case PKT_MDC_PROV_REP:
3128 case PKT_MDC_PROV_REP_LC:
3129 case PKT_MDC_SILENCE:
3130 case PKT_MDC_SILENCE_LC:
3131 case PKT_MDC_ECHO_CANCEL:
3132 case PKT_MDC_ECHO_CANCEL_LC:
3134 case PKT_MDC_RSVP_LC:
3135 case PKT_MDC_UGS_AD:
3136 case PKT_MDC_UGS_AD_LC:
3137 case PKT_MDC_FLOW_LOG:
3138 case PKT_MDC_RFC2833_DTMF:
3139 case PKT_MDC_VOICE_METRICS:
3142 raw_val = tvb_get_ntohs(tvb, off + 4);
3143 proto_item_append_text(ti,
3145 val_to_str(raw_val, pkt_mdc_boolean_vals, "unknown"),
3146 tvb_format_stringzpad(tvb, off + 4, 2) );
3149 case PKT_MDC_SUPP_CODECS:
3150 case PKT_MDC_SUPP_CODECS_LC:
3151 for (i = 0; i < tlv_len; i++) {
3152 raw_val = tvb_get_ntohs(tvb, off + 4 + (i * 2) );
3153 proto_item_append_text(ti,
3155 plurality(i + 1, "", ", "),
3156 val_to_str(raw_val, pkt_mdc_codec_vals, "unknown"),
3157 tvb_format_stringzpad(tvb, off + 4 + (i * 2), 2) );
3161 case PKT_MDC_PROV_FLOWS:
3162 tvb_memcpy(tvb, flow_val_str, off + 4, 4);
3163 flow_val_str[4] = '\0';
3164 flow_val = strtoul((gchar*)flow_val_str, NULL, 16);
3165 proto_item_append_text(ti,
3166 "0x%04lx", flow_val);
3169 case PKT_MDC_T38_VERSION:
3170 raw_val = tvb_get_ntohs(tvb, off + 4);
3171 proto_item_append_text(ti,
3173 val_to_str(raw_val, pkt_mdc_t38_version_vals, "unknown"),
3174 tvb_format_stringzpad(tvb, off + 4, 2) );
3177 case PKT_MDC_T38_EC:
3178 raw_val = tvb_get_ntohs(tvb, off + 4);
3179 proto_item_append_text(ti,
3181 val_to_str(raw_val, pkt_mdc_t38_ec_vals, "unknown"),
3182 tvb_format_stringzpad(tvb, off + 4, 2) );
3188 case PKT_MDC_VENDOR_TLV:
3190 proto_item_append_text(ti,
3192 tvb_format_stringzpad(tvb, off + 4, tlv_len * 2) );
3196 subtree = proto_item_add_subtree(ti, ett_bootp_option);
3197 if (raw_val == PKT_MDC_PROV_FLOWS) {
3198 for (i = 0 ; i < 3; i++) {
3199 if (flow_val & pkt_mdc_supp_flow_vals[i].value) {
3200 decode_bitfield_value(bit_fld, flow_val, pkt_mdc_supp_flow_vals[i].value, 16);
3201 proto_tree_add_text(subtree, tvb, off + 4, 4, "%s%s",
3202 bit_fld, pkt_mdc_supp_flow_vals[i].strptr);
3205 } else if (raw_val == PKT_MDC_MIBS) {
3206 /* 17 06 02 00 38 02 01 07 */
3207 subopt_off = off + 4;
3208 max_len = subopt_off + (tlv_len * 2);
3209 while (subopt_off < max_len) {
3210 raw_val = tvb_get_ntohs(tvb, subopt_off);
3211 if (raw_val != 0x3032) { /* We only know how to handle a length of 2 */
3212 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3213 proto_tree_add_text(subtree, tvb, subopt_off, 2,
3214 "[Bogus length: %s]", asc_val);
3219 raw_val = tvb_get_ntohs(tvb, subopt_off);
3220 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3222 mib_ti = proto_tree_add_text(subtree, tvb, subopt_off, 2, "%s (%s)",
3223 val_to_str(raw_val, pkt_mdc_mib_orgs, "Unknown"), asc_val);
3224 if (subopt_off > off + 4 + 2) {
3225 proto_item_append_text(ti, ", ");
3227 proto_item_append_text(ti, "%s", val_to_str(raw_val, pkt_mdc_mib_orgs, "Unknown"));
3230 tvb_memcpy(tvb, asc_val, subopt_off, 2);
3231 if (sscanf((gchar*)asc_val, "%x", &mib_val) != 1) {
3232 proto_tree_add_text(v_tree, tvb, subopt_off, 2,
3233 "[Bogus bitfield: %s]", asc_val);
3238 case PKT_MDC_MIB_CL:
3239 subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option);
3241 for (i = 0; i < 8; i++) {
3242 if (mib_val & pkt_mdc_cl_mib_vals[i].value) {
3243 decode_bitfield_value(bit_fld, mib_val, pkt_mdc_cl_mib_vals[i].value, 8);
3244 proto_tree_add_text(subtree2, tvb, subopt_off, 2,
3245 "%s%s", bit_fld, pkt_mdc_cl_mib_vals[i].strptr);
3250 case PKT_MDC_MIB_IETF:
3251 subtree2 = proto_item_add_subtree(mib_ti, ett_bootp_option);
3253 for (i = 0; i < 8; i++) {
3254 if (mib_val & pkt_mdc_ietf_mib_vals[i].value) {
3255 decode_bitfield_value(bit_fld, mib_val, pkt_mdc_ietf_mib_vals[i].value, 8);
3256 proto_tree_add_text(subtree2, tvb, subopt_off, 2,
3257 "%s%s", bit_fld, pkt_mdc_ietf_mib_vals[i].strptr);
3269 off += (tlv_len * 2) + 4;
3275 dissect_docsis_cm_cap(proto_tree *v_tree, tvbuff_t *tvb, int voff, int len)
3277 unsigned long raw_val;
3278 int off = DOCS_CM_TLV_OFF + voff;
3280 guint8 asc_val[4] = " ";
3283 tvb_memcpy (tvb, asc_val, off, 2);
3284 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len < 1) {
3285 proto_tree_add_text(v_tree, tvb, off, len - off,
3286 "Bogus length: %s", asc_val);
3289 proto_tree_add_uint_format_value(v_tree, hf_bootp_docsis_cmcap_len, tvb, off, 2,
3290 tlv_len, "%d", tlv_len);
3293 while (off - voff < len) {
3295 raw_val = tvb_get_ntohs (tvb, off);
3298 tvb_memcpy(tvb, asc_val, off + 2, 2);
3299 if (sscanf((gchar*)asc_val, "%x", &tlv_len) != 1 || tlv_len > 0xff) {
3300 proto_tree_add_text(v_tree, tvb, off, len - off,
3301 "[Bogus length: %s]", asc_val);
3305 ti = proto_tree_add_text(v_tree, tvb, off,
3308 tvb_format_text(tvb, off, 2),
3309 val_to_str(raw_val, docs_cm_type_vals, "unknown"));
3312 case DOCS_CM_CONCAT_SUP:
3313 case DOCS_CM_FRAG_SUP:
3314 case DOCS_CM_PHS_SUP:
3315 case DOCS_CM_IGMP_SUP:
3316 case DOCS_CM_DCC_SUP:
3317 case DOCS_CM_DCC_SUP_LC:
3318 for (i = 0; i < tlv_len; i++) {
3319 raw_val = tvb_get_ntohs(tvb, off + 4 + (i * 2) );
3320 proto_item_append_text(ti,
3322 plurality(i + 1, "", ", "),
3323 val_to_str(raw_val, pkt_mdc_boolean_vals, "unknown"),
3324 tvb_format_text(tvb, off + 4 + (i * 2), 2) );
3328 case DOCS_CM_DOCSIS_VER:
3329 raw_val = tvb_get_ntohs(tvb, off + 4);
3330 proto_item_append_text(ti,
3332 val_to_str(raw_val, docs_cm_version_vals, "Reserved"),
3333 tvb_format_text(tvb, off + 4, 2) );
3336 case DOCS_CM_PRIV_SUP:
3337 raw_val = tvb_get_ntohs(tvb, off + 4);
3338 proto_item_append_text(ti,
3340 val_to_str(raw_val, docs_cm_privacy_vals, "Reserved"),
3341 tvb_format_text(tvb, off + 4, 2) );
3344 case DOCS_CM_DSAID_SUP:
3345 case DOCS_CM_USID_SUP:
3346 case DOCS_CM_TET_MI:
3347 case DOCS_CM_TET_MI_LC:
3349 case DOCS_CM_TET_LC:
3350 tvb_memcpy (tvb, asc_val, off + 4, 2);
3351 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3352 proto_item_append_text(ti,
3356 case DOCS_CM_IPFILT_SUP:
3357 case DOCS_CM_IPFILT_SUP_LC:
3358 case DOCS_CM_LLCFILT_SUP:
3359 case DOCS_CM_LLCFILT_SUP_LC:
3360 tvb_memcpy (tvb, asc_val, off + 4, 4);
3361 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3362 proto_item_append_text(ti,
3366 case DOCS_CM_FILT_SUP:
3367 tvb_memcpy (tvb, asc_val, off + 4, 2);
3368 raw_val = strtoul((gchar*)asc_val, NULL, 16);
3370 proto_item_append_text(ti,
3371 "802.1p filtering");
3372 if (raw_val & 0x02) {
3374 proto_item_append_text(ti, ", ");
3375 proto_item_append_text(ti,
3376 "802.1Q filtering");
3378 if (!(raw_val & 0x03))
3379 proto_item_append_text(ti,
3381 proto_item_append_text(ti,
3382 " (0x%02lx)", raw_val);
3386 off += (tlv_len * 2) + 4;
3392 /* Definitions specific to PKT-SP-PROV-I05-021127 begin with "PKT_CCC_I05".
3393 Definitions specific to IETF draft 5 and RFC 3495 begin with "PKT_CCC_IETF".
3394 Shared definitions begin with "PKT_CCC".
3396 #define PKT_CCC_PRI_DHCP 1
3397 #define PKT_CCC_SEC_DHCP 2
3398 #define PKT_CCC_I05_SNMP 3
3399 #define PKT_CCC_IETF_PROV_SRV 3
3400 #define PKT_CCC_I05_PRI_DNS 4
3401 #define PKT_CCC_IETF_AS_KRB 4
3402 #define PKT_CCC_I05_SEC_DNS 5
3403 #define PKT_CCC_IETF_AP_KRB 5
3404 #define PKT_CCC_KRB_REALM 6
3405 #define PKT_CCC_TGT_FLAG 7
3406 #define PKT_CCC_PROV_TIMER 8
3407 #define PKT_CCC_CMS_FQDN 9
3408 #define PKT_CCC_IETF_SEC_TKT 9
3409 #define PKT_CCC_AS_KRB 10
3410 #define PKT_CCC_AP_KRB 11
3411 #define PKT_CCC_MTA_KRB_CLEAR 12
3413 static const value_string pkt_i05_ccc_opt_vals[] = {
3414 { PKT_CCC_PRI_DHCP, "Primary DHCP Server" },
3415 { PKT_CCC_SEC_DHCP, "Secondary DHCP Server" },
3416 { PKT_CCC_I05_SNMP, "SNMP Entity" },
3417 { PKT_CCC_I05_PRI_DNS, "Primary DNS Server" },
3418 { PKT_CCC_I05_SEC_DNS, "Secondary DNS Server" },
3419 { PKT_CCC_KRB_REALM, "Kerberos Realm" },
3420 { PKT_CCC_TGT_FLAG, "MTA should fetch TGT?" },
3421 { PKT_CCC_PROV_TIMER, "Provisioning Timer" },
3422 { PKT_CCC_CMS_FQDN, "CMS FQDN" },
3423 { PKT_CCC_AS_KRB, "AS-REQ/AS-REP Backoff and Retry" },
3424 { PKT_CCC_AP_KRB, "AP-REQ/AP-REP Backoff and Retry" },
3425 { PKT_CCC_MTA_KRB_CLEAR, "MTA should clear Kerberos tickets?" },
3429 static const value_string pkt_draft5_ccc_opt_vals[] = {
3430 { PKT_CCC_PRI_DHCP, "TSP's Primary DHCP Server" },
3431 { PKT_CCC_SEC_DHCP, "TSP's Secondary DHCP Server" },
3432 { PKT_CCC_IETF_PROV_SRV, "TSP's Provisioning Server" },
3433 { PKT_CCC_IETF_AS_KRB, "TSP's AS-REQ/AS-REP Backoff and Retry" },
3434 { PKT_CCC_IETF_AP_KRB, "TSP's AP-REQ/AP-REP Backoff and Retry" },
3435 { PKT_CCC_KRB_REALM, "TSP's Kerberos Realm Name" },
3436 { PKT_CCC_TGT_FLAG, "TSP's Ticket Granting Server Utilization" },
3437 { PKT_CCC_PROV_TIMER, "TSP's Provisioning Timer Value" },
3438 { PKT_CCC_IETF_SEC_TKT, "PacketCable Security Ticket Control" },
3442 static const value_string pkt_i05_ccc_ticket_ctl_vals[] = {
3443 { 1, "Invalidate Provisioning Application Server's ticket" },
3444 { 2, "Invalidate all CMS Application Server tickets" },
3445 { 3, "Invalidate all Application Server tickets" },
3450 dissect_packetcable_i05_ccc(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
3453 int suboptoff = optoff;
3454 guint8 subopt, subopt_len, fetch_tgt, timer_val, ticket_ctl;
3455 proto_tree *pkt_s_tree;
3458 subopt = tvb_get_guint8(tvb, optoff);
3461 if (suboptoff >= optend) {
3462 proto_tree_add_text(v_tree, tvb, optoff, 1,
3463 "Suboption %d: no room left in option for suboption length",
3467 subopt_len = tvb_get_guint8(tvb, optoff);
3470 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
3471 "Suboption %u: %s: ", subopt,
3472 val_to_str(subopt, pkt_i05_ccc_opt_vals, "unknown/reserved") );
3476 case PKT_CCC_PRI_DHCP: /* String values */
3477 case PKT_CCC_SEC_DHCP:
3478 case PKT_CCC_I05_SNMP:
3479 case PKT_CCC_I05_PRI_DNS:
3480 case PKT_CCC_I05_SEC_DNS:
3481 case PKT_CCC_KRB_REALM:
3482 case PKT_CCC_CMS_FQDN:
3483 proto_item_append_text(vti, "%s (%u byte%s)",
3484 tvb_format_stringzpad(tvb, suboptoff, subopt_len),
3486 plurality(subopt_len, "", "s") );
3487 suboptoff += subopt_len;
3490 case PKT_CCC_TGT_FLAG:
3491 if (suboptoff+1 > optend) {
3492 proto_item_append_text(vti,
3493 "no room left in option for suboption value");
3496 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
3497 proto_item_append_text(vti, "%s (%u byte%s%s)",
3498 fetch_tgt ? "Yes" : "No",
3500 plurality(subopt_len, "", "s"),
3501 subopt_len != 1 ? " [Invalid]" : "");
3502 suboptoff += subopt_len;
3505 case PKT_CCC_PROV_TIMER:
3506 if (suboptoff+1 > optend) {
3507 proto_item_append_text(vti,
3508 "no room left in option for suboption value");
3511 timer_val = tvb_get_guint8(tvb, suboptoff);
3512 proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
3513 timer_val > 30 ? " [Invalid]" : "",
3515 plurality(subopt_len, "", "s"),
3516 subopt_len != 1 ? " [Invalid]" : "");
3517 suboptoff += subopt_len;
3520 case PKT_CCC_AS_KRB:
3521 if (suboptoff+12 > optend) {
3522 proto_item_append_text(vti,
3523 "no room left in option for suboption value");
3526 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3527 plurality(subopt_len, "", "s"),
3528 subopt_len != 12 ? " [Invalid]" : "");
3529 if (subopt_len == 12) {
3530 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3531 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3532 "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u",
3533 tvb_get_ntohl(tvb, suboptoff));
3534 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3535 "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u",
3536 tvb_get_ntohl(tvb, suboptoff + 4));
3537 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3538 "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u",
3539 tvb_get_ntohl(tvb, suboptoff + 8));
3541 suboptoff += subopt_len;
3544 case PKT_CCC_AP_KRB:
3545 if (suboptoff+12 > optend) {
3546 proto_item_append_text(vti,
3547 "no room left in option for suboption value");
3550 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3551 plurality(subopt_len, "", "s"),
3552 subopt_len != 12 ? " [Invalid]" : "");
3553 if (subopt_len == 12) {
3554 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3555 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3556 "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u",
3557 tvb_get_ntohl(tvb, suboptoff));
3558 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3559 "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u",
3560 tvb_get_ntohl(tvb, suboptoff + 4));
3561 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3562 "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u",
3563 tvb_get_ntohl(tvb, suboptoff + 8));
3565 suboptoff += subopt_len;
3568 case PKT_CCC_MTA_KRB_CLEAR:
3569 if (suboptoff+1 > optend) {
3570 proto_item_append_text(vti,
3571 "no room left in option for suboption value");
3574 ticket_ctl = tvb_get_guint8(tvb, suboptoff);
3575 proto_item_append_text(vti, "%s (%u) (%u byte%s%s)",
3576 val_to_str (ticket_ctl, pkt_i05_ccc_ticket_ctl_vals, "unknown/invalid"),
3579 plurality(subopt_len, "", "s"),
3580 subopt_len != 1 ? " [Invalid]" : "");
3581 suboptoff += subopt_len;
3585 suboptoff += subopt_len;
3593 static const value_string sec_tcm_vals[] = {
3594 { 1 << 0, "PacketCable Provisioning Server" },
3595 { 1 << 1, "All PacketCable Call Management Servers" },
3600 dissect_packetcable_ietf_ccc(proto_tree *v_tree, tvbuff_t *tvb, int optoff,
3601 int optend, int revision)
3603 int suboptoff = optoff;
3604 guint8 subopt, subopt_len;
3606 guint8 prov_type, fetch_tgt, timer_val;
3608 proto_tree *pkt_s_tree;
3610 int max_timer_val = 255, i;
3611 const guchar *dns_name;
3614 subopt = tvb_get_guint8(tvb, suboptoff);
3617 if (suboptoff >= optend) {
3618 proto_tree_add_text(v_tree, tvb, optoff, 1,
3619 "Suboption %d: no room left in option for suboption length",
3623 subopt_len = tvb_get_guint8(tvb, suboptoff);
3626 vti = proto_tree_add_text(v_tree, tvb, optoff, subopt_len + 2,
3627 "Suboption %u: %s: ", subopt,
3628 val_to_str(subopt, pkt_draft5_ccc_opt_vals, "unknown/reserved") );
3632 case PKT_CCC_PRI_DHCP: /* IPv4 values */
3633 case PKT_CCC_SEC_DHCP:
3634 if (suboptoff+4 > optend) {
3635 proto_item_append_text(vti,
3636 "no room left in option for suboption value");
3639 ipv4addr = tvb_get_ipv4(tvb, suboptoff);
3640 proto_item_append_text(vti, "%s (%u byte%s%s)",
3641 ip_to_str((guint8 *)&ipv4addr),
3643 plurality(subopt_len, "", "s"),
3644 subopt_len != 4 ? " [Invalid]" : "");
3645 suboptoff += subopt_len;
3648 case PKT_CCC_IETF_PROV_SRV:
3649 if (suboptoff+1 > optend) {
3650 proto_item_append_text(vti,
3651 "no room left in option for suboption value");
3654 prov_type = tvb_get_guint8(tvb, suboptoff);
3656 switch (prov_type) {
3659 get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name);
3660 proto_item_append_text(vti, "%s (%u byte%s)", dns_name,
3661 subopt_len - 1, plurality(subopt_len, "", "s") );
3665 if (suboptoff+4 > optend) {
3666 proto_item_append_text(vti,
3667 "no room left in option for suboption value");
3670 ipv4addr = tvb_get_ipv4(tvb, suboptoff);
3671 proto_item_append_text(vti, "%s (%u byte%s%s)",
3672 ip_to_str((guint8 *)&ipv4addr),
3674 plurality(subopt_len, "", "s"),
3675 subopt_len != 5 ? " [Invalid]" : "");
3679 proto_item_append_text(vti, "Invalid type: %u (%u byte%s)",
3682 plurality(subopt_len, "", "s") );
3685 suboptoff += subopt_len - 1;
3688 case PKT_CCC_IETF_AS_KRB:
3689 if (suboptoff+12 > optend) {
3690 proto_item_append_text(vti,
3691 "no room left in option for suboption value");
3694 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3695 plurality(subopt_len, "", "s"),
3696 subopt_len != 12 ? " [Invalid]" : "");
3697 if (subopt_len == 12) {
3698 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3699 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3700 "pktcMtaDevRealmUnsolicitedKeyNomTimeout: %u",
3701 tvb_get_ntohl(tvb, suboptoff));
3702 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3703 "pktcMtaDevRealmUnsolicitedKeyMaxTimeout: %u",
3704 tvb_get_ntohl(tvb, suboptoff + 4));
3705 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3706 "pktcMtaDevRealmUnsolicitedKeyMaxRetries: %u",
3707 tvb_get_ntohl(tvb, suboptoff + 8));
3709 suboptoff += subopt_len;
3712 case PKT_CCC_IETF_AP_KRB:
3713 proto_item_append_text(vti, "(%u byte%s%s)", subopt_len,
3714 plurality(subopt_len, "", "s"),
3715 subopt_len != 12 ? " [Invalid]" : "");
3716 if (subopt_len == 12) {
3717 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3718 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 4,
3719 "pktcMtaDevProvUnsolicitedKeyNomTimeout: %u",
3720 tvb_get_ntohl(tvb, suboptoff));
3721 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 4, 4,
3722 "pktcMtaDevProvUnsolicitedKeyMaxTimeout: %u",
3723 tvb_get_ntohl(tvb, suboptoff + 4));
3724 proto_tree_add_text(pkt_s_tree, tvb, suboptoff + 8, 4,
3725 "pktcMtaDevProvUnsolicitedKeyMaxRetries: %u",
3726 tvb_get_ntohl(tvb, suboptoff + 8));
3728 suboptoff += subopt_len;
3731 case PKT_CCC_KRB_REALM: /* String values */
3732 get_dns_name(tvb, suboptoff, subopt_len, suboptoff, &dns_name);
3733 proto_item_append_text(vti, "%s (%u byte%s)", dns_name,
3734 subopt_len, plurality(subopt_len, "", "s") );
3735 suboptoff += subopt_len;
3738 case PKT_CCC_TGT_FLAG:
3739 if (suboptoff+1 > optend) {
3740 proto_item_append_text(vti,
3741 "no room left in option for suboption value");
3744 fetch_tgt = tvb_get_guint8(tvb, suboptoff);
3745 proto_item_append_text(vti, "%s (%u byte%s%s)",
3746 fetch_tgt ? "Yes" : "No",
3748 plurality(subopt_len, "", "s"),
3749 subopt_len != 1 ? " [Invalid]" : "");
3753 case PKT_CCC_PROV_TIMER:
3754 if (suboptoff+1 > optend) {
3755 proto_item_append_text(vti,
3756 "no room left in option for suboption value");
3759 if (revision == PACKETCABLE_CCC_DRAFT5)
3761 timer_val = tvb_get_guint8(tvb, suboptoff);
3762 proto_item_append_text(vti, "%u%s (%u byte%s%s)", timer_val,
3763 timer_val > max_timer_val ? " [Invalid]" : "",
3765 plurality(subopt_len, "", "s"),
3766 subopt_len != 1 ? " [Invalid]" : "");
3770 case PKT_CCC_IETF_SEC_TKT:
3771 if (suboptoff+2 > optend) {
3772 proto_item_append_text(vti,
3773 "no room left in option for suboption value");
3776 sec_tcm = tvb_get_ntohs(tvb, suboptoff);
3777 proto_item_append_text(vti, "0x%04x (%u byte%s%s)", sec_tcm, subopt_len,
3778 plurality(subopt_len, "", "s"),
3779 subopt_len != 2 ? " [Invalid]" : "");
3780 if (subopt_len == 2) {
3781 pkt_s_tree = proto_item_add_subtree(vti, ett_bootp_option);
3782 for (i = 0; i < 2; i++) {
3783 if (sec_tcm & sec_tcm_vals[i].value) {
3784 decode_bitfield_value(bit_fld, sec_tcm, sec_tcm_vals[i].value, 16);
3785 proto_tree_add_text(pkt_s_tree, tvb, suboptoff, 2, "%sInvalidate %s",
3786 bit_fld, sec_tcm_vals[i].strptr);
3790 suboptoff += subopt_len;
3794 suboptoff += subopt_len;
3800 #define BOOTREQUEST 1
3803 static const value_string op_vals[] = {
3804 { BOOTREQUEST, "Boot Request" },
3805 { BOOTREPLY, "Boot Reply" },
3810 dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3812 proto_tree *bp_tree;
3814 proto_tree *flag_tree;
3815 proto_item *fi, *hidden_item;
3818 const guint8 *haddr;
3819 int voff, eoff, tmpvoff; /* vendor offset, end offset */
3822 const char *dhcp_type = NULL;
3823 const guint8 *vendor_class_id = NULL;
3824 guint16 flags, secs;
3826 guint8 overload = 0; /* DHCP option overload */
3828 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOOTP");
3830 * In case we throw an exception fetching the opcode, etc.
3832 col_clear(pinfo->cinfo, COL_INFO);
3834 op = tvb_get_guint8(tvb, 0);
3835 htype = tvb_get_guint8(tvb, 1);
3836 hlen = tvb_get_guint8(tvb, 2);
3840 if ((htype == ARPHRD_ETHER || htype == ARPHRD_IEEE802)
3842 if (check_col(pinfo->cinfo, COL_INFO)) {
3843 col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s (%s)",
3844 arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
3846 get_ether_name(tvb_get_ptr(tvb, 28, hlen)));
3850 if (check_col(pinfo->cinfo, COL_INFO)) {
3851 col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s",
3852 arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
3859 col_set_str(pinfo->cinfo, COL_INFO, "Boot Reply");
3863 if (check_col(pinfo->cinfo, COL_INFO))
3864 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BOOTP message type (%u)", op);
3868 voff = VENDOR_INFO_OFFSET;
3870 /* rfc2132 says it SHOULD exist, not that it MUST exist */
3871 if (tvb_bytes_exist(tvb, voff, 4) &&
3872 (tvb_get_ntohl(tvb, voff) == 0x63825363)) {
3877 eoff = tvb_reported_length(tvb);
3880 * In the first pass, we just look for the DHCP message type
3881 * and Vendor class identifier options.
3885 while (tmpvoff < eoff && !at_end) {
3886 offset_delta = bootp_option(tvb, 0, tmpvoff, eoff, TRUE, &at_end,
3887 &dhcp_type, &vendor_class_id, &overload);
3888 if (offset_delta <= 0) {
3889 THROW(ReportedBoundsError);
3891 tmpvoff += offset_delta;
3895 * If there was a DHCP message type option, flag this packet
3898 if (dhcp_type != NULL) {
3900 * Yes, this is a DHCP packet, and "dhcp_type" is the
3903 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCP");
3904 if (check_col(pinfo->cinfo, COL_INFO))
3905 col_add_fstr(pinfo->cinfo, COL_INFO, "DHCP %-8s - Transaction ID 0x%x",
3906 dhcp_type, tvb_get_ntohl(tvb, 4));
3907 tap_queue_packet( bootp_dhcp_tap, pinfo, dhcp_type);
3911 * OK, now build the protocol tree.
3914 ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, FALSE);
3915 bp_tree = proto_item_add_subtree(ti, ett_bootp);
3917 proto_tree_add_uint(bp_tree, hf_bootp_type, tvb,
3920 proto_tree_add_uint_format_value(bp_tree, hf_bootp_hw_type, tvb,
3924 arphrdtype_to_str(htype,
3925 "Unknown (0x%02x)"));
3926 proto_tree_add_uint(bp_tree, hf_bootp_hw_len, tvb,
3928 proto_tree_add_item(bp_tree, hf_bootp_hops, tvb,
3930 proto_tree_add_item(bp_tree, hf_bootp_id, tvb,
3933 * Windows (98, XP and Vista tested) sends the "secs" value on
3934 * the wire formatted as little-endian. See if the LE value
3937 secs = tvb_get_letohs(tvb, 8);
3938 if (secs > 0 && secs <= 0xff) {
3939 ti = proto_tree_add_uint_format_value(bp_tree, hf_bootp_secs, tvb,
3940 8, 2, secs, "%u", secs);
3941 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_NOTE,
3942 "Seconds elapsed (%u) appears to be encoded as little-endian", secs);
3944 proto_tree_add_item(bp_tree, hf_bootp_secs, tvb,
3949 * If we're not building the protocol tree, we don't need to
3950 * make a second pass.
3955 flags = tvb_get_ntohs(tvb, 10);
3956 fi = proto_tree_add_uint(bp_tree, hf_bootp_flags, tvb,
3958 proto_item_append_text(fi, " (%s)",
3959 (flags & BOOTP_BC) ? "Broadcast" : "Unicast");
3960 flag_tree = proto_item_add_subtree(fi, ett_bootp_flags);
3961 proto_tree_add_boolean(flag_tree, hf_bootp_flags_broadcast, tvb,
3963 proto_tree_add_uint(flag_tree, hf_bootp_flags_reserved, tvb,
3965 proto_tree_add_item(bp_tree, hf_bootp_ip_client, tvb,
3967 proto_tree_add_item(bp_tree, hf_bootp_ip_your, tvb,
3969 proto_tree_add_item(bp_tree, hf_bootp_ip_server, tvb,
3971 proto_tree_add_item(bp_tree, hf_bootp_ip_relay, tvb,
3974 if (hlen > 0 && hlen <= 16) {
3975 haddr = tvb_get_ptr(tvb, 28, hlen);
3976 if ((htype == ARPHRD_ETHER || htype == ARPHRD_IEEE802)
3978 proto_tree_add_item(bp_tree, hf_bootp_hw_ether_addr, tvb, 28, 6, FALSE);
3980 /* The chaddr element is 16 bytes in length,
3981 although only the first hlen bytes are used */
3982 proto_tree_add_bytes_format_value(bp_tree, hf_bootp_hw_addr, tvb, 28, 16,
3984 "%s", arphrdaddr_to_str(haddr, hlen, htype));
3985 if ((16 - hlen) > 0)
3986 proto_tree_add_item(bp_tree, hf_bootp_hw_addr_padding, tvb, 28+hlen, 16-hlen, FALSE);
3988 proto_tree_add_text(bp_tree, tvb,
3989 28, 16, "Client address not given");
3992 /* The server host name is optional */
3993 if (tvb_get_guint8(tvb, SERVER_NAME_OFFSET) != '\0') {
3994 if (overload & OPT_OVERLOAD_SNAME) {
3995 proto_tree_add_text (bp_tree, tvb,
3996 SERVER_NAME_OFFSET, SERVER_NAME_LEN,
3997 "Server name option overloaded by DHCP");
3999 proto_tree_add_item(bp_tree, hf_bootp_server, tvb,
4001 SERVER_NAME_LEN, FALSE);
4004 proto_tree_add_string_format(bp_tree, hf_bootp_server, tvb,
4007 (const gchar*)tvb_get_ptr(tvb, SERVER_NAME_OFFSET, 1),
4008 "Server host name not given");
4012 if (tvb_get_guint8(tvb, FILE_NAME_OFFSET) != '\0') {
4013 if (overload & OPT_OVERLOAD_FILE) {
4014 proto_tree_add_text (bp_tree, tvb,
4015 FILE_NAME_OFFSET, FILE_NAME_LEN,
4016 "Boot file name option overloaded by DHCP");
4018 proto_tree_add_item(bp_tree, hf_bootp_file, tvb,
4020 FILE_NAME_LEN, FALSE);
4023 proto_tree_add_string_format(bp_tree, hf_bootp_file, tvb,
4026 (const gchar*)tvb_get_ptr(tvb, FILE_NAME_OFFSET, 1),
4027 "Boot file name not given");
4030 voff = VENDOR_INFO_OFFSET;
4031 if (dhcp_type != NULL) {
4032 hidden_item = proto_tree_add_boolean(bp_tree, hf_bootp_dhcp, tvb, 0, 0, 1);
4033 PROTO_ITEM_SET_HIDDEN(hidden_item);
4035 if (tvb_bytes_exist(tvb, voff, 4) &&
4036 (tvb_get_ntohl(tvb, voff) == 0x63825363)) {
4037 ip_addr = tvb_get_ipv4(tvb, voff);
4038 proto_tree_add_ipv4_format_value(bp_tree, hf_bootp_cookie, tvb,
4039 voff, 4, ip_addr, "(OK)");
4042 proto_tree_add_text(bp_tree, tvb,
4043 voff, 64, "Bootp vendor specific options");
4048 while (voff < eoff && !at_end) {
4049 offset_delta = bootp_option(tvb, bp_tree, voff, eoff, FALSE, &at_end,
4050 &dhcp_type, &vendor_class_id, &overload);
4051 if (offset_delta <= 0) {
4052 THROW(ReportedBoundsError);
4054 voff += offset_delta;
4058 * Padding after the end option.
4060 proto_tree_add_text(bp_tree, tvb, voff, eoff - voff, "Padding");
4065 bootp_init_protocol(void)
4067 gchar **optionstrings = NULL;
4068 gchar **optiondetail = NULL;
4072 /* first copy default_bootp_opt[] to bootp_opt[]. This resets all values to default */
4073 for(i=0; i<BOOTP_OPT_NUM; i++)
4075 bootp_opt[i].text = default_bootp_opt[i].text;
4076 bootp_opt[i].ftype = default_bootp_opt[i].ftype;
4077 bootp_opt[i].data = default_bootp_opt[i].data;
4080 /* now split semicolon seperated fields groups */
4081 optionstrings = ep_strsplit(pref_optionstring, ";", -1);
4082 for (i=0;optionstrings[i]!=NULL;i++)
4084 /* input string should have 3 fields:
4085 1 - bootp option - uint8 1-254, not being a special
4086 2 - option name - string
4087 3 - option type - defined in enum represented as a string
4090 /* now split field groups to usable data */
4091 optiondetail = ep_strsplit(optionstrings[i], ",",-1);
4092 /* verify array has 3 or more entries, any entries beyond 3 are ingnored */
4093 for(ii=0;(optiondetail[ii]!=NULL);ii++)
4097 if (ii < 3) continue; /* not enough values. Go again */
4098 ii = atoi(optiondetail[0]); /* get the bootp option number */
4099 if (ii==0 || ii>=BOOTP_OPT_NUM-1) continue; /* not a number or out of range. Go again */
4100 if (bootp_opt[ii].ftype == special) continue; /* don't mess with specials. Go again */
4101 bootp_opt[ii].text = se_strdup(optiondetail[1]); /* store a permanent ("seasonal") copy */
4102 type = optiondetail[2]; /* A string to be converted to an ftype enum */
4103 /* XXX This if statement could be extended to allow for additinonal types */
4104 if (g_ascii_strcasecmp(type,"string") == 0)
4106 bootp_opt[ii].ftype = string;
4107 } else if (g_ascii_strcasecmp(type,"ipv4") == 0)
4109 bootp_opt[ii].ftype = ipv4;
4110 } else if (g_ascii_strcasecmp(type,"bytes") == 0)
4112 bootp_opt[ii].ftype = bytes;
4115 bootp_opt[ii].ftype = opaque;
4121 proto_register_bootp(void)
4123 static hf_register_info hf[] = {
4125 { "Frame is DHCP", "bootp.dhcp", FT_BOOLEAN,
4126 BASE_NONE, NULL, 0x0,
4130 { "Message type", "bootp.type", FT_UINT8,
4131 BASE_DEC, VALS(op_vals), 0x0,
4134 { &hf_bootp_hw_type,
4135 { "Hardware type", "bootp.hw.type", FT_UINT8,
4136 BASE_HEX, NULL, 0x0,
4140 { "Hardware address length", "bootp.hw.len", FT_UINT8,
4141 BASE_DEC, NULL, 0x0,
4145 { "Hops", "bootp.hops", FT_UINT8,
4146 BASE_DEC, NULL, 0x0,
4150 { "Transaction ID", "bootp.id", FT_UINT32,
4151 BASE_HEX, NULL, 0x0,
4155 { "Seconds elapsed", "bootp.secs", FT_UINT16,
4156 BASE_DEC, NULL, 0x0,
4160 { "Bootp flags", "bootp.flags", FT_UINT16,
4161 BASE_HEX, NULL, 0x0,
4164 { &hf_bootp_flags_broadcast,
4165 { "Broadcast flag", "bootp.flags.bc", FT_BOOLEAN,
4166 16, TFS(&flag_set_broadcast), BOOTP_BC,
4169 { &hf_bootp_flags_reserved,
4170 { "Reserved flags", "bootp.flags.reserved", FT_UINT16,
4171 BASE_HEX, NULL, BOOTP_MBZ,
4174 { &hf_bootp_ip_client,
4175 { "Client IP address", "bootp.ip.client",FT_IPv4,
4176 BASE_NONE, NULL, 0x0,
4179 { &hf_bootp_ip_your,
4180 { "Your (client) IP address", "bootp.ip.your", FT_IPv4,
4181 BASE_NONE, NULL, 0x0,
4184 { &hf_bootp_ip_server,
4185 { "Next server IP address", "bootp.ip.server",FT_IPv4,
4186 BASE_NONE, NULL, 0x0,
4189 { &hf_bootp_ip_relay,
4190 { "Relay agent IP address", "bootp.ip.relay", FT_IPv4,
4191 BASE_NONE, NULL, 0x0,
4194 { &hf_bootp_hw_addr,
4195 { "Client hardware address", "bootp.hw.addr", FT_BYTES,
4196 BASE_NONE, NULL, 0x0,
4199 { &hf_bootp_hw_addr_padding,
4200 { "Client hardware address padding", "bootp.hw.addr_padding", FT_BYTES,
4201 BASE_NONE, NULL, 0x0,
4204 { &hf_bootp_hw_ether_addr,
4205 { "Client MAC address", "bootp.hw.mac_addr", FT_ETHER,
4206 BASE_NONE, NULL, 0x0,
4210 { "Server host name", "bootp.server", FT_STRING,
4211 BASE_NONE, NULL, 0x0,
4215 { "Boot file name", "bootp.file", FT_STRING,
4216 BASE_NONE, NULL, 0x0,
4220 { "Magic cookie", "bootp.cookie", FT_IPv4,
4221 BASE_NONE, NULL, 0x0,
4225 { "Bootp Vendor Options", "bootp.vendor", FT_BYTES,
4226 BASE_NONE, NULL, 0x0,
4230 { "Server", "bootp.fqdn.s", FT_BOOLEAN,
4231 8, TFS(&tfs_fqdn_s), F_FQDN_S,
4232 "If true, server should do DDNS update", HFILL }},
4235 { "Server overrides", "bootp.fqdn.o", FT_BOOLEAN,
4236 8, TFS(&tfs_fqdn_o), F_FQDN_O,
4237 "If true, server insists on doing DDNS update", HFILL }},
4240 { "Encoding", "bootp.fqdn.e", FT_BOOLEAN,
4241 8, TFS(&tfs_fqdn_e), F_FQDN_E,
4242 "If true, name is binary encoded", HFILL }},
4245 { "Server DDNS", "bootp.fqdn.n", FT_BOOLEAN,
4246 8, TFS(&tfs_fqdn_n), F_FQDN_N,
4247 "If true, server should not do any DDNS updates", HFILL }},
4249 { &hf_bootp_fqdn_mbz,
4250 { "Reserved flags", "bootp.fqdn.mbz",FT_UINT8,
4251 BASE_HEX, NULL, F_FQDN_MBZ,
4254 { &hf_bootp_fqdn_rcode1,
4255 { "A-RR result", "bootp.fqdn.rcode1", FT_UINT8,
4256 BASE_DEC, NULL, 0x0,
4257 "Result code of A-RR update", HFILL }},
4259 { &hf_bootp_fqdn_rcode2,
4260 { "PTR-RR result", "bootp.fqdn.rcode2", FT_UINT8,
4261 BASE_DEC, NULL, 0x0,
4262 "Result code of PTR-RR update", HFILL }},
4264 { &hf_bootp_fqdn_name,
4265 { "Client name", "bootp.fqdn.name", FT_STRING,
4266 BASE_NONE, NULL, 0x0,
4267 "Name to register via DDNS", HFILL }},
4269 { &hf_bootp_fqdn_asciiname,
4270 { "Client name", "bootp.fqdn.name", FT_STRING,
4271 BASE_NONE, NULL, 0x0,
4272 "Name to register via DDNS", HFILL }},
4274 { &hf_bootp_pkt_mtacap_len,
4275 { "MTA DC Length", "bootp.vendor.pktc.mtacap_len", FT_UINT8,
4276 BASE_DEC, NULL, 0x0,
4277 "PacketCable MTA Device Capabilities Length", HFILL }},
4279 { &hf_bootp_docsis_cmcap_len,
4280 { "CM DC Length", "bootp.vendor.docsis.cmcap_len", FT_UINT8,
4281 BASE_DEC, NULL, 0x0,
4282 "DOCSIS Cable Modem Device Capabilities Length", HFILL }},
4284 { &hf_bootp_alu_vid,
4285 { "Voice VLAN ID", "bootp.vendor.alu.vid", FT_UINT16,
4286 BASE_DEC, NULL, 0x0,
4287 "Alcatel-Lucent VLAN ID to define Voice VLAN", HFILL }},
4289 { &hf_bootp_alu_tftp1,
4290 { "Spatial Redundancy TFTP1", "bootp.vendor.alu.tftp1" , FT_IPv4,
4291 BASE_NONE, NULL, 0x0,
4294 { &hf_bootp_alu_tftp2,
4295 { "Spatial Redundancy TFTP2", "bootp.vendor.alu.tftp2" ,FT_IPv4,
4296 BASE_NONE, NULL, 0x0,
4299 { &hf_bootp_client_identifier_uuid,
4300 { "Client Identifier (UUID)", "bootp.client_id_uuid", FT_GUID,
4301 BASE_NONE, NULL, 0x0,
4302 "Client Machine Identifier (UUID)", HFILL }},
4304 { &hf_bootp_client_network_id_major_ver,
4305 { "Client Network ID Major Version", "bootp.client_network_id_major", FT_UINT8,
4306 BASE_DEC, NULL, 0x0,
4307 "Client Machine Identifier, Major Version", HFILL }},
4309 { &hf_bootp_client_network_id_minor_ver,
4310 { "Client Network ID Minor Version", "bootp.client_network_id_minor", FT_UINT8,
4311 BASE_DEC, NULL, 0x0,
4312 "Client Machine Identifier, Major Version", HFILL }},
4314 { &hf_bootp_option_type,
4315 { "Option", "bootp.option.type", FT_UINT8,
4316 BASE_DEC, NULL, 0x0,
4317 "Bootp/Dhcp option type", HFILL }},
4319 { &hf_bootp_option_length,
4320 { "Length", "bootp.option.length", FT_UINT8,
4321 BASE_DEC, NULL, 0x0,
4322 "Bootp/Dhcp option length", HFILL }},
4324 { &hf_bootp_option_value,
4325 { "Value", "bootp.option.value", FT_BYTES,
4326 BASE_NONE, NULL, 0x0,
4327 "Bootp/Dhcp option value", HFILL }},
4331 static gint *ett[] = {
4338 module_t *bootp_module;
4340 proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP",
4342 proto_register_field_array(proto_bootp, hf, array_length(hf));
4343 proto_register_subtree_array(ett, array_length(ett));
4344 bootp_dhcp_tap = register_tap("bootp");
4346 /* register init routine to setup the custom bootp options */
4347 register_init_routine(&bootp_init_protocol);
4349 /* Allow dissector to find be found by name. */
4350 register_dissector("bootp", dissect_bootp, proto_bootp);
4352 bootp_module = prefs_register_protocol(proto_bootp, NULL);
4354 prefs_register_bool_preference(bootp_module, "novellserverstring",
4355 "Decode Option 85 as String",
4356 "Novell Servers option 85 can be configured as a string instead of address",
4359 prefs_register_enum_preference(bootp_module, "pkt.ccc.protocol_version",
4360 "PacketCable CCC protocol version",
4361 "The PacketCable CCC protocol version",
4362 &pkt_ccc_protocol_version,
4363 pkt_ccc_protocol_versions,
4366 prefs_register_uint_preference(bootp_module, "pkt.ccc.option",
4367 "PacketCable CCC option",
4368 "Option Number for PacketCable CableLabs Client Configuration",
4372 prefs_register_string_preference(bootp_module, "displayasstring",
4373 "Custom BootP/DHCP Options (Excl. suboptions)",
4374 "Format: OptionNumber,OptionName,OptionType[;Format].\n"
4375 "Example: 176,MyOption,string;242,NewOption,ipv4.\n"
4376 "OptionNumbers: 1-254, but no special options. "
4377 "OptionType: string, ipv4 and bytes",
4378 &pref_optionstring );
4382 proto_reg_handoff_bootp(void)
4384 dissector_handle_t bootp_handle;
4386 bootp_handle = create_dissector_handle(dissect_bootp, proto_bootp);
4387 dissector_add("udp.port", UDP_PORT_BOOTPS, bootp_handle);
4388 dissector_add("udp.port", UDP_PORT_BOOTPC, bootp_handle);