Ethereal-dev: [Ethereal-dev] [PATCH] packet-bootp.c: DHCP options 43, 122 and more
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Thomas Anders <thomas.anders@xxxxxxxxxxxxx>
Date: Thu, 06 May 2004 16:18:28 +0200
The attached patch adds significant enhancements to packet-bootp.c: - support vendor-specific DHCP option 43 interpretation per CableLabs standards (for compliant cable devices, identified by option 60) - support DHCP option 122 with all suboptions (RFC 3495: CableLabs Client Configuration; RFC 3594: PacketCable Security Ticket Control) - update DHCP options list: add options 117-122 (see http://www.iana.org/assignments/bootp-dhcp-parameters) - minor enhancements for DHCP options 2, 82 - minor code cleanup Works for me. Please review and apply. If you need sample captures, please contact me personally. Best regards, Thomas -- Thomas Anders (thomas.anders at blue-cable.de)
--- packet-bootp.c.FCS 2003-12-03 21:01:20.000000000 +0100 +++ packet-bootp.c 2004-05-06 16:09:28.000000000 +0200 @@ -1,6 +1,7 @@ /* packet-bootp.c * Routines for BOOTP/DHCP packet disassembly - * Gilbert Ramirez <gram@xxxxxxxxxxxxxxx> + * Copyright 1998, Gilbert Ramirez <gram@xxxxxxxxxxxxxxx> + * Copyright 2004, Thomas Anders <thomas.anders [AT] blue-cable.de> * * $Id: packet-bootp.c,v 1.77 2003/12/03 20:01:20 guy Exp $ * @@ -15,6 +16,8 @@ * RFC 3046: DHCP Relay Agent Information Option * RFC 3118: Authentication for DHCP Messages * RFC 3203: DHCP reconfigure extension + * RFC 3495: DHCP Option (122) for CableLabs Client Configuration + * RFC 3594: PacketCable Security Ticket Control Sub-Option (122.9) * BOOTP and DHCP Parameters * http://www.iana.org/assignments/bootp-dhcp-parameters * @@ -46,6 +49,7 @@ #include <epan/int-64bit.h> #include <epan/packet.h> #include "packet-arp.h" +#include "packet-dns.h" /* for get_dns_name() */ #include "prefs.h" #include "tap.h" @@ -84,10 +88,12 @@ #define BOOTP_BC 0x8000 #define BOOTP_MBZ 0x7FFF +#define PLURALIZE(n) (((n) > 1) ? "s" : "") + enum field_type { none, ipv4, string, toggle, yes_no, special, opaque, time_in_secs, val_u_byte, val_u_short, val_u_le_short, val_u_long, - val_s_long }; + val_s_long, fqdn, ipv4_or_fqdn }; struct opt_info { char *text; @@ -99,11 +105,13 @@ "Unicast" }; -#define NUM_OPT_INFOS 211 -#define NUM_O63_SUBOPTS 11 static int dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp); +static int dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb, + int optp); +static int dissect_cablelabs_clientconfig_suboption(proto_tree *v_tree, tvbuff_t *tvb, + int optp); static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp); static int bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb, @@ -216,7 +224,7 @@ static struct opt_info opt[] = { /* 0 */ { "Padding", none }, /* 1 */ { "Subnet Mask", ipv4 }, - /* 2 */ { "Time Offset", val_s_long }, + /* 2 */ { "Time Offset", time_in_secs }, /* 3 */ { "Router", ipv4 }, /* 4 */ { "Time Server", ipv4 }, /* 5 */ { "Name Server", ipv4 }, @@ -331,12 +339,12 @@ /* 114 */ { "URL", opaque }, /* 115 */ { "DHCP Failover Protocol", opaque }, /* 116 */ { "DHCP Auto-Configuration", opaque }, - /* 117 */ { "Unassigned", opaque }, - /* 118 */ { "Unassigned", opaque }, - /* 119 */ { "Unassigned", opaque }, - /* 120 */ { "Unassigned", opaque }, - /* 121 */ { "Unassigned", opaque }, - /* 122 */ { "Unassigned", opaque }, + /* 117 */ { "Name Service Search", opaque }, + /* 118 */ { "Subnet Selection Option", opaque }, + /* 119 */ { "Domain Search", opaque }, + /* 120 */ { "SIP Servers", opaque }, + /* 121 */ { "Classless Static Route", opaque }, + /* 122 */ { "CableLabs Client Configuration", special }, /* 123 */ { "Unassigned", opaque }, /* 124 */ { "Unassigned", opaque }, /* 125 */ { "Unassigned", opaque }, @@ -588,6 +596,20 @@ optp = dissect_vendor_pxeclient_suboption(v_tree, tvb, optp); } + } else if (*vendor_class_id_p != NULL && + ((strncmp(*vendor_class_id_p, "pktc", strlen("pktc")) == 0) || + (strncmp(*vendor_class_id_p, "docsis", strlen("docsis")) == 0) || + (strncmp(*vendor_class_id_p, "CableHome", strlen("CableHome")) == 0))) { + /* CableLabs standard - see www.cablelabs.com/projects */ + vti = proto_tree_add_text(bp_tree, tvb, voff, + consumed, "Option %d: %s (CableLabs)", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + + optp = voff+2; + while (optp < voff+consumed) { + optp = dissect_vendor_cablelabs_suboption(v_tree, + tvb, optp); + } } else { proto_tree_add_text(bp_tree, tvb, voff, consumed, "Option %d: %s (%d bytes)", code, text, vlen); @@ -658,7 +680,7 @@ v_tree = proto_item_add_subtree(vti, ett_bootp_option); for (i = 0; i < vlen; i++) { byte = tvb_get_guint8(tvb, voff+2+i); - if (byte < NUM_OPT_INFOS) { + if (byte < array_length(opt)) { proto_tree_add_text(v_tree, tvb, voff+2+i, 1, "%d = %s", byte, opt[byte].text); } else { @@ -781,6 +803,16 @@ } break; + case 122: /* CableLabs Client Configuration */ + vti = proto_tree_add_text(bp_tree, tvb, voff, + vlen + 2, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + optp = voff+2; + while (optp < voff+consumed) { + optp = dissect_cablelabs_clientconfig_suboption(v_tree, tvb, optp); + } + break; + case 90: /* DHCP Authentication */ case 210: /* Was this used for authentication at one time? */ vti = proto_tree_add_text(bp_tree, tvb, voff, @@ -864,7 +896,7 @@ } /* Normal cases */ - if (code < NUM_OPT_INFOS) { + if (code < array_length(opt)) { text = opt[code].text; ftype = opt[code].ftype; @@ -994,15 +1026,18 @@ switch (subopt) { case 1: proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2, - "Agent Circuit ID (%d bytes)", subopt_len); + "Agent Circuit ID: %s", + tvb_bytes_to_str(tvb, optp+2, subopt_len)); break; case 2: proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2, - "Agent Remote ID (%d bytes)", subopt_len); + "Agent Remote ID: %s", + tvb_bytes_to_str(tvb, optp+2, subopt_len)); break; default: proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2, - "Unknown agent option: %d", subopt); + "Invalid agent suboption %d (%d bytes)", + subopt, subopt_len); break; } optp += (subopt_len + 2); @@ -1046,7 +1081,6 @@ /* 71 {"PXE boot item", special} */ /* 255 {"PXE end options", special} */ }; -#define NUM_O43PXECLIENT_SUBOPTS (12) subopt = tvb_get_guint8(tvb, optp); @@ -1067,11 +1101,11 @@ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, "Suboption %d: %s (%d byte%s)" , subopt, "PXE boot item", - subopt_len, (subopt_len != 1)?"s":""); - } else if ( (subopt < 1 ) || (subopt > NUM_O43PXECLIENT_SUBOPTS) ) { + subopt_len, PLURALIZE(subopt_len)); + } else if ((subopt < 1 ) || (subopt > array_length(o43pxeclient_opt))) { proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, "Unknown suboption %d (%d byte%s)", subopt, subopt_len, - (subopt_len != 1)?"s":""); + PLURALIZE(subopt_len)); } else { switch (o43pxeclient_opt[subopt].ft) { @@ -1085,7 +1119,7 @@ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, "Suboption %d: %s (%d byte%s)" , subopt, o43pxeclient_opt[subopt].text, - subopt_len, (subopt_len != 1)?"s":""); + subopt_len, PLURALIZE(subopt_len)); break; case val_u_le_short: @@ -1129,6 +1163,104 @@ } static int +dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp) +{ + guint8 subopt; + guint8 subopt_len; + + struct o43cablelabs_opt_info { + char *text; + enum field_type ft; + }; + + static struct o43cablelabs_opt_info o43cablelabs_opt[]= { + /* 0 */ {"nop", special}, /* dummy */ + /* 1 */ {"Suboption Request List", string}, + /* 2 */ {"Device Type", string}, + /* 3 */ {"eSAFE Types", string}, + /* 4 */ {"Serial Number", string}, + /* 5 */ {"Hardware Version", string}, + /* 6 */ {"Software Version", string}, + /* 7 */ {"Boot ROM version", string}, + /* 8 */ {"Organizational Unique Identifier", string}, + /* 9 */ {"Model Number", string}, + /* 10 */ {"Vendor Name", string}, + /* *** 11-30: CableHome *** */ + /* 11 */ {"PS WAN-Man", special}, + /* 12 */ {"CM/PS System Description", string}, + /* 13 */ {"CM/PS Firmware Revision", string}, + /* 14 */ {"Firewall Policy File Version", string}, + /* 15 */ {"Unassigned (CableHome)", special}, + /* 16 */ {"Unassigned (CableHome)", special}, + /* 17 */ {"Unassigned (CableHome)", special}, + /* 18 */ {"Unassigned (CableHome)", special}, + /* 19 */ {"Unassigned (CableHome)", special}, + /* 20 */ {"Unassigned (CableHome)", special}, + /* 21 */ {"Unassigned (CableHome)", special}, + /* 22 */ {"Unassigned (CableHome)", special}, + /* 23 */ {"Unassigned (CableHome)", special}, + /* 24 */ {"Unassigned (CableHome)", special}, + /* 25 */ {"Unassigned (CableHome)", special}, + /* 26 */ {"Unassigned (CableHome)", special}, + /* 27 */ {"Unassigned (CableHome)", special}, + /* 28 */ {"Unassigned (CableHome)", special}, + /* 29 */ {"Unassigned (CableHome)", special}, + /* 30 */ {"Unassigned (CableHome)", special}, + /* *** 31-50: PacketCable *** */ + /* 31 */ {"MTA MAC Address", string}, + /* 32 */ {"Correlation ID", string}, + /* 33-50 {"Unassigned (PacketCable)", special}, */ + /* *** 51-127: CableLabs *** */ + /* 51-127 {"Unassigned (CableLabs)", special}, */ + /* *** 128-254: Vendors *** */ + /* 128-254 {"Unassigned (Vendors)", special}, */ + /* 255 {"end options", special} */ + }; + + subopt = tvb_get_guint8(tvb, optp); + + if (subopt == 0 ) { + proto_tree_add_text(v_tree, tvb, optp, 1, "Padding"); + return (optp+1); + } else if (subopt == 255) { /* End Option */ + proto_tree_add_text(v_tree, tvb, optp, 1, "End option"); + /* Make sure we skip any junk left this option */ + return (optp+255); + } + + subopt_len = tvb_get_guint8(tvb, optp+1); + + if ( (subopt < 1 ) || (subopt > array_length(o43cablelabs_opt)) ) { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len, + PLURALIZE(subopt_len)); + } else { + switch (o43cablelabs_opt[subopt].ft) { + + case string: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = \"%.*s\"", subopt, + o43cablelabs_opt[subopt].text, subopt_len, + tvb_get_ptr(tvb, optp+2, subopt_len)); + break; + + case special: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s (%d byte%s)" , + subopt, o43cablelabs_opt[subopt].text, + subopt_len, PLURALIZE(subopt_len)); + break; + + default: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt); + break; + } + } + optp += (subopt_len + 2); + return optp; +} + +static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp) { guint8 subopt; @@ -1159,7 +1291,7 @@ }; subopt = tvb_get_guint8(tvb, optp); - if (subopt > NUM_O63_SUBOPTS) { + if (subopt > array_length(o63_opt)) { proto_tree_add_text(v_tree, tvb,optp,1,"Unknown suboption %d", subopt); optp++; } else { @@ -1225,6 +1357,113 @@ return optp; } +static int +dissect_cablelabs_clientconfig_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp) +{ + guint8 subopt; + guint8 subopt_len; + guint8 flag; + char dname[MAXDNAME]; + int dname_len; + + struct o122cablelabs_opt_info { + char *text; + enum field_type ft; + }; + + static struct o122cablelabs_opt_info o122cablelabs_opt[]= { + /* 0 */ {"nop", special}, /* dummy */ + /* 1 */ {"TSP's Primary DHCP Server Address", ipv4}, + /* 2 */ {"TSP's Secondary DHCP Server Address", ipv4}, + /* 3 */ {"TSP's Provisioning Server Address", ipv4_or_fqdn}, + /* 4 */ {"TSP's AS-REQ/AS-REP Backoff and Retry", special}, + /* 5 */ {"TSP's AP-REQ/AP-REP Backoff and Retry", special}, + /* 6 */ {"TSP's Kerberos Realm Name", fqdn}, + /* 7 */ {"TSP's Ticket Granting Server Utilization", special}, + /* 8 */ {"TSP's Provisioning Timer Value", special}, + /* 9 */ {"PacketCable Security Ticket Control", special}, + /* *** 10-255: Reserved for future use *** */ + }; + + subopt = tvb_get_guint8(tvb, optp); + subopt_len = tvb_get_guint8(tvb, optp+1); + + if ((subopt < 1 ) || (subopt > array_length(o122cablelabs_opt))) { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len, + PLURALIZE(subopt_len)); + } else { + switch (o122cablelabs_opt[subopt].ft) { + + case string: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = \"%.*s\"", subopt, + o122cablelabs_opt[subopt].text, subopt_len, + tvb_get_ptr(tvb, optp+2, subopt_len)); + break; + + case special: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s (%d byte%s)" , + subopt, o122cablelabs_opt[subopt].text, + subopt_len, PLURALIZE(subopt_len)); + break; + case ipv4: + proto_tree_add_text(v_tree, tvb, optp, 6, + "Suboption %d: %s = %s", + subopt, o122cablelabs_opt[subopt].text, + ip_to_str(tvb_get_ptr(tvb, optp+2, 4))); + break; + case fqdn: + dname_len = get_dns_name(tvb, optp+2, optp+2, dname, sizeof(dname)); + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = %.*s", subopt, + o122cablelabs_opt[subopt].text, + dname_len, dname); + break; + case ipv4_or_fqdn: + flag = tvb_get_guint8(tvb, optp+2); + if (flag == 0) { /* FQDN */ + dname_len = get_dns_name(tvb, optp+3, optp+3, dname, sizeof(dname)); + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = %.*s", subopt, + o122cablelabs_opt[subopt].text, + dname_len, dname); + } else if (flag == 1) { /* IPv4 */ + proto_tree_add_text(v_tree, tvb, optp, 6, + "Suboption %d: %s = %s", + subopt, o122cablelabs_opt[subopt].text, + ip_to_str(tvb_get_ptr(tvb, optp+3, 4))); + } else { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = Invalid Value (%d byte%s)", + subopt, o122cablelabs_opt[subopt].text, + subopt_len, PLURALIZE(subopt_len)); + } + break; + case yes_no: + flag = tvb_get_guint8(tvb, optp+2); + if (flag == 0 || flag == 1) { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = %s", subopt, + o122cablelabs_opt[subopt].text, + flag == 0 ? "No" : "Yes"); + } else { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s = Invalid Value %d", + subopt, o122cablelabs_opt[subopt].text, flag); + } + break; + default: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt); + break; + } + } + optp += (subopt_len + 2); + return optp; +} + + #define BOOTREQUEST 1 #define BOOTREPLY 2
- Follow-Ups:
- Prev by Date: [Ethereal-dev] Important: remove epan/config.h from your builds
- Next by Date: [Ethereal-dev] Extend dcerpc tapping by fault/reject PDU's?
- Previous by thread: [Ethereal-dev] Important: remove epan/config.h from your builds
- Next by thread: Re: [Ethereal-dev] [PATCH] packet-bootp.c: DHCP options 43, 122 and more
- Index(es):