Ethereal-dev: [Ethereal-dev] Patch: Toplevel PXEClient decoding (dhcp)
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Joerg Mayer <jmayer@xxxxxxxxx>
Date: Thu, 24 May 2001 15:53:13 +0200
Hello, I've added handling of PXEClient dhcp request. In order to do so, I had to move dhcp option parsing to a 2 pass operation. Ciao Jörg -- Joerg Mayer <jmayer@xxxxxxxxx> I found out that "pro" means "instead of" (as in proconsul). Now I know what proactive means.
Changelog: <jmayer@xxxxxxxxx> Toplevel of PXEClient decoding added Index: ethereal/packet-bootp.c =================================================================== RCS file: /cvsroot/ethereal/packet-bootp.c,v retrieving revision 1.51 diff -u -u -r1.51 packet-bootp.c --- packet-bootp.c 2001/05/03 07:02:50 1.51 +++ packet-bootp.c 2001/05/24 13:47:00 @@ -68,11 +68,13 @@ static guint ett_bootp = -1; static guint ett_bootp_option = -1; +static guint8 *vendor_class_id = NULL; + #define UDP_PORT_BOOTPS 67 enum field_type { none, ipv4, string, toggle, yes_no, special, opaque, time_in_secs, - val_u_byte, val_u_short, val_u_long, + val_u_byte, val_u_short, val_u_le_short, val_u_long, val_s_long }; struct opt_info { @@ -83,6 +85,8 @@ #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_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, @@ -195,7 +199,7 @@ /* 57 */ { "Maximum DHCP Message Size", val_u_short }, /* 58 */ { "Renewal Time Value", time_in_secs }, /* 59 */ { "Rebinding Time Value", time_in_secs }, - /* 60 */ { "Vendor class identifier", opaque }, + /* 60 */ { "Vendor class identifier", special }, /* 61 */ { "Client identifier", special }, /* 62 */ { "Novell/Netware IP domain", string }, /* 63 */ { "Novell Options", special }, @@ -379,6 +383,14 @@ */ vlen = tvb_get_guint8(tvb, voff+1); consumed = vlen + 2; + /* Handling of options we need to scan for first: + * 60 (Vendor class identifier) + * This is ugly but I don't have any better ideas + * -- Joerg Mayer + */ + if ( (code == 60) && (bp_tree == NULL) ) { + vendor_class_id = tvb_get_ptr(tvb, voff+2, consumed-2); + } if (bp_tree == NULL) { /* Don't put anything in the protocol tree. */ return consumed; @@ -430,8 +442,21 @@ break; case 43: /* Vendor-Specific Info */ - proto_tree_add_text(bp_tree, tvb, voff, consumed, - "Option %d: %s", code, text); + /* PXE protocol 2.1 as described in the intel specs */ + if (!strncmp(vendor_class_id, "PXEClient", strlen("PXEClient"))) { + vti = proto_tree_add_text(bp_tree, tvb, voff, + consumed, "Option %d: %s (PXEClient)", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + + optp = voff+2; + while (optp < voff+consumed) { + optp = dissect_vendor_pxeclient_suboption(v_tree, + tvb, optp); + } + } else { + proto_tree_add_text(bp_tree, tvb, voff, consumed, + "Option %d: %s (%d bytes)", code, text, vlen); + } break; case 46: /* NetBIOS-over-TCP/IP Node Type */ @@ -463,6 +488,13 @@ } break; + case 60: /* Vendor class identifier */ + proto_tree_add_text(bp_tree, tvb, voff, consumed, + "Option %d: %s = \"%.*s\"", code, text, +vlen, + tvb_get_ptr(tvb, voff+2, consumed-2)); + break; + case 61: /* Client Identifier */ /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll guess that the first is the hwtype, and the last 6 @@ -588,7 +620,7 @@ * John Lines <John.Lines@xxxxxxxxxx> */ proto_tree_add_text(bp_tree, tvb, voff, consumed, - "Option %d: %s = %.*s", code, text, vlen, + "Option %d: %s = \"%.*s\"", code, text, vlen, tvb_get_ptr(tvb, voff+2, consumed-2)); break; @@ -702,6 +734,125 @@ } static int +dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp) +{ + guint8 subopt; + guint8 subopt_len; + int slask; + proto_tree *o43pxeclient_v_tree; + proto_item *vti; + + struct o43pxeclient_opt_info { + char *text; + enum field_type ft; + }; + + static struct o43pxeclient_opt_info o43pxeclient_opt[]= { + /* 0 */ {"nop", special}, /* dummy */ + /* 1 */ {"PXE mtftp IP", ipv4}, + /* 2 */ {"PXE mtftp client port", val_u_le_short}, + /* 3 */ {"PXE mtftp server port",val_u_le_short}, + /* 4 */ {"PXE mtftp timeout", val_u_byte}, + /* 5 */ {"PXE mtftp delay", val_u_byte}, + /* 6 */ {"PXE discovery control", val_u_byte}, + /* + * Correct: b0 (lsb): disable broadcast discovery + * b1: disable multicast discovery + * b2: only use/accept servers in boot servers + * b3: download bootfile without prompt/menu/disc + */ + /* 7 */ {"PXE multicast address", ipv4}, + /* 8 */ {"PXE boot servers", special}, + /* 9 */ {"PXE boot menu", special}, + /* 10 */ {"PXE menu prompt", special}, + /* 11 */ {"PXE multicast address alloc", special}, + /* 12 */ {"PXE credential types", special}, + /* 71 {"PXE boot item", special} */ + /* 255 {"PXE end options", special} */ + }; +#define NUM_O43PXECLIENT_SUBOPTS (12) + + 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 PXEClient option"); + /* Make sure we skip any junk left this option */ + return (optp+255); + } + + subopt_len = tvb_get_guint8(tvb, optp+1); + + if ( subopt == 71 ) { /* 71 {"PXE boot item", special} */ + /* case special */ + /* I may need to decode that properly one day */ + 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) ) { + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Unknown suboption %d (%d byte%s)", subopt, subopt_len, + (subopt_len != 1)?"s":""); + } else { + switch (o43pxeclient_opt[subopt].ft) { + +/* XXX case string: + proto_tree_add_text(v_tree, tvb, optp, subopt_len+2, + "Suboption %d: %s", subopt, o43pxeclient_opt[subopt].text); + break; + XXX */ + case special: + /* I may need to decode that properly one day */ + 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":""); + break; + + case val_u_le_short: + proto_tree_add_text(v_tree, tvb, optp, 4, "Suboption %d: %s = %u", + subopt, o43pxeclient_opt[subopt].text, + tvb_get_letohs(tvb, optp+2)); + break; + + case val_u_byte: + proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s = %u", + subopt, o43pxeclient_opt[subopt].text, + tvb_get_guint8(tvb, optp+2)); + break; + + case ipv4: + if (subopt_len == 4) { + /* one IP address */ + proto_tree_add_text(v_tree, tvb, optp, 6, + "Suboption %d : %s = %s", + subopt, o43pxeclient_opt[subopt].text, + ip_to_str(tvb_get_ptr(tvb, optp+2, 4))); + } else { + /* > 1 IP addresses. Let's make a sub-tree */ + vti = proto_tree_add_text(v_tree, tvb, optp, + subopt_len+2, "Suboption %d: %s", + subopt, o43pxeclient_opt[subopt].text); + o43pxeclient_v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (slask = optp + 2 ; slask < optp+subopt_len; slask += 4) { + proto_tree_add_text(o43pxeclient_v_tree, tvb, slask, 4, "IP Address: %s", + ip_to_str(tvb_get_ptr(tvb, slask, 4))); + } + } + 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; @@ -815,7 +966,7 @@ guint8 op; guint8 htype, hlen; const guint8 *haddr; - int voff, eoff; /* vender offset, end offset */ + int voff, eoff, tmpvoff; /* vender offset, end offset */ guint32 ip_addr; gboolean is_dhcp = FALSE; const char *dhcp_type; @@ -939,6 +1090,17 @@ voff = 240; eoff = tvb_reported_length(tvb); + /* + * If we are displaying the details, we need two passes: + * the first to find out about vendor specific options, + * the second to do the actual decoding (option 60 is needed + * to decode option 43 ) + */ + tmpvoff = voff; + if (bp_tree) { + while (tmpvoff < eoff ) + tmpvoff += bootp_option(tvb, 0, tmpvoff, eoff); + } while (voff < eoff) { /* Handle the DHCP option specially here, so that we can flag DHCP packets as such. */
- Follow-Ups:
- Re: [Ethereal-dev] Patch: Toplevel PXEClient decoding (dhcp)
- From: Guy Harris
- Re: [Ethereal-dev] Patch: Toplevel PXEClient decoding (dhcp)
- Prev by Date: Re: [Ethereal-dev] RFC: new TVBUFF type
- Next by Date: [Ethereal-dev] new DSI packet dissector
- Previous by thread: Re: [Ethereal-dev] Dissector for MTP3
- Next by thread: Re: [Ethereal-dev] Patch: Toplevel PXEClient decoding (dhcp)
- Index(es):