diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-07-09 22:46:53 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-07-09 22:46:53 +0000 |
commit | ea197eb09c13539ec5f85e37d7b55b1394abf267 (patch) | |
tree | ecfaa24e67df06e7abfaabd4d614e858a70811b7 /packet-bootp.c | |
parent | 2801bb142a708696ead65d2a9362da45d075e75a (diff) | |
download | wireshark-ea197eb09c13539ec5f85e37d7b55b1394abf267.tar.gz wireshark-ea197eb09c13539ec5f85e37d7b55b1394abf267.tar.bz2 wireshark-ea197eb09c13539ec5f85e37d7b55b1394abf267.zip |
Check the options in a BOOTP packet regardless of whether the protocol
tree is to be constructed or not; if it has the DHCP option, we want to
mark the packet as DHCP even if we're not constructing the protocol
tree.
Extract the code to process Netware/IP suboptions into a separate
routine.
svn path=/trunk/; revision=2129
Diffstat (limited to 'packet-bootp.c')
-rw-r--r-- | packet-bootp.c | 697 |
1 files changed, 352 insertions, 345 deletions
diff --git a/packet-bootp.c b/packet-bootp.c index 4c7211d58f..80d4073b08 100644 --- a/packet-bootp.c +++ b/packet-bootp.c @@ -2,7 +2,7 @@ * Routines for BOOTP/DHCP packet disassembly * Gilbert Ramirez <gram@xiexie.org> * - * $Id: packet-bootp.c,v 1.35 2000/07/08 07:52:11 guy Exp $ + * $Id: packet-bootp.c,v 1.36 2000/07/09 22:46:53 guy Exp $ * * The information used comes from: * RFC 2132: DHCP Options and BOOTP Vendor Extensions @@ -62,8 +62,6 @@ static int hf_bootp_dhcp = -1; static guint ett_bootp = -1; static guint ett_bootp_option = -1; -static char * is_dhcp ; - #define UDP_PORT_BOOTPS 67 enum field_type { none, ipv4, string, toggle, yes_no, special, opaque, @@ -79,21 +77,12 @@ struct opt_info { #define NUM_OPT_INFOS 77 #define NUM_O63_SUBOPTS 11 -/* returns the number of bytes consumed by this option */ -static int -bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) -{ - char *text; - enum field_type ftype; - u_char code = pd[voff]; - int vlen = pd[voff+1]; - u_char byte; - int i,slask,optp, consumed = vlen + 2; - u_long time_secs; - proto_tree *v_tree,*o63_v_tree; - proto_item *vti; - +static int dissect_netware_ip_suboption(proto_tree *v_tree, const u_char *pd, + int optp); +static const char * +get_dhcp_type(guint8 byte) +{ static const char *opt53_text[] = { "Unknown Message Type", "Discover", @@ -105,6 +94,29 @@ bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) "Release", "Inform" }; + int i; + + if (byte > 0 && byte < (sizeof opt53_text / sizeof opt53_text[0])) + i = byte; + else + i = 0; + return opt53_text[i]; +} + +/* Returns the number of bytes consumed by this option. */ +static int +bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) +{ + char *text; + enum field_type ftype; + u_char code = pd[voff]; + int vlen = pd[voff+1]; + u_char byte; + int i,optp, consumed = vlen + 2; + u_long time_secs; + proto_tree *v_tree; + proto_item *vti; + static const value_string nbnt_vals[] = { {0x1, "B-node" }, {0x2, "P-node" }, @@ -112,27 +124,6 @@ bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) {0x8, "H-node" }, {0, NULL } }; - struct o63_opt_info { - char *truet; - char *falset; - enum field_type ft; - }; - - static struct o63_opt_info o63_opt[]= { - /* 0 */ {"","",none}, - /* 1 */ {"NWIP does not exist on subnet","",string}, - /* 2 */ {"NWIP exist in options area","",string}, - /* 3 */ {"NWIP exists in sname/file","",string}, - /* 4 */ {"NWIP exists, but too big","",string}, - /* 5 */ {"Broadcast for nearest Netware server","Do NOT Broadcast for nearest Netware server",yes_no}, - /* 6 */ {"Preferred DSS server","",ipv4}, - /* 7 */ {"Nearest NWIP server","",ipv4}, - /* 8 */ {"Autoretries","",val_u_short}, - /* 9 */ {"Autoretry delay, secs ","",val_u_short}, - /* 10*/ {"Support NetWare/IP v1.1","Do NOT support NetWare/IP v1.1",yes_no}, - /* 11*/ {"Primary DSS ", "" , special} }; - - static struct opt_info opt[] = { /* 0 */ { "Padding", none }, /* 1 */ { "Subnet Mask", ipv4 }, @@ -213,226 +204,149 @@ bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) /* 76 */ { "StreetTalk Directory Assistance Server", ipv4 } }; - text = opt[code].text; - /* Special cases */ + /* Options whose length isn't "vlen + 2". */ switch (code) { - /* Padding */ - case 0: - /* check how much padding we have */ - for (i = voff + 1; i < eoff; i++ ) { - if (pd[i] != 0) { - break; - } + + case 0: /* Padding */ + /* check how much padding we have */ + for (i = voff + 1; i < eoff; i++ ) { + if (pd[i] != 0) { + break; } - i = i - voff; + } + i = i - voff; + if (bp_tree != NULL) proto_tree_add_text(bp_tree, NullTVB, voff, i, "Padding"); - consumed = i; - return consumed; + consumed = i; + return consumed; + break; - /* Policy Filter */ - case 21: - /* one IP address pair */ - if (vlen == 8) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s/%s", code, text, - ip_to_str((guint8*)&pd[voff+2]), - ip_to_str((guint8*)&pd[voff+6])); - } - /* > 1 IP address pair. Let's make a sub-tree */ - else { + case 255: /* End Option */ + if (bp_tree != NULL) + proto_tree_add_text(bp_tree, NullTVB, voff, 1, "End Option"); + consumed = 1; + return consumed; + } - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = voff + 2; i < voff + consumed; i += 8) { - proto_tree_add_text(v_tree, NullTVB, i, 8, "IP Address/Mask: %s/%s", - ip_to_str((guint8*)&pd[i]), - ip_to_str((guint8*)&pd[i+4])); - } - } - break; + if (bp_tree == NULL) { + /* Don't put anything in the protocol tree. */ + return consumed; + } + + text = opt[code].text; + /* Special cases */ + switch (code) { - /* Static Route */ - case 33: + case 21: /* Policy Filter */ + if (vlen == 8) { /* one IP address pair */ - if (vlen == 8) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s/%s", code, text, - ip_to_str((guint8*)&pd[voff+2]), - ip_to_str((guint8*)&pd[voff+6])); - } + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %s/%s", code, text, + ip_to_str((guint8*)&pd[voff+2]), + ip_to_str((guint8*)&pd[voff+6])); + } else { /* > 1 IP address pair. Let's make a sub-tree */ - else { - - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = voff + 2; i < voff + consumed; i += 8) { - proto_tree_add_text(v_tree, NullTVB, i, 8, - "Destination IP Address/Router: %s/%s", - ip_to_str((guint8*)&pd[i]), - ip_to_str((guint8*)&pd[i+4])); - } + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + consumed, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (i = voff + 2; i < voff + consumed; i += 8) { + proto_tree_add_text(v_tree, NullTVB, i, 8, "IP Address/Mask: %s/%s", + ip_to_str((guint8*)&pd[i]), + ip_to_str((guint8*)&pd[i+4])); } - break; - - /* Vendor-Specific Info */ - case 43: - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s", code, text); - break; + } + break; - /* NetBIOS-over-TCP/IP Node Type */ - case 46: - byte = pd[voff+2]; + case 33: /* Static Route */ + if (vlen == 8) { + /* one IP address pair */ proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s", code, text, - val_to_str(byte, nbnt_vals, - "Unknown (0x%02x)")); - break; - - /* DHCP Message Type */ - case 53: - byte = pd[voff+2]; - if (byte > 0 && byte < 9) { - i = byte; - } - else { - i = 0; - } - proto_tree_add_text(bp_tree, NullTVB, voff, 3, "Option %d: %s = DHCP %s", - code, text, opt53_text[i]); - is_dhcp = (char *) opt53_text[i]; - break; - - /* Parameter Request List */ - case 55: + "Option %d: %s = %s/%s", code, text, + ip_to_str((guint8*)&pd[voff+2]), + ip_to_str((guint8*)&pd[voff+6])); + } else { + /* > 1 IP address pair. Let's make a sub-tree */ vti = proto_tree_add_text(bp_tree, NullTVB, voff, - vlen + 2, "Option %d: %s", code, text); + consumed, "Option %d: %s", code, text); v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = 0; i < vlen; i++) { - byte = pd[voff+2+i]; - if (byte < NUM_OPT_INFOS) { - proto_tree_add_text(v_tree, NullTVB, voff+2+i, 1, "%d = %s", - byte, opt[byte].text); - } - else { - proto_tree_add_text(vti, NullTVB, voff+2+i, 1, - "Unknown Option Code: %d", byte); - } + for (i = voff + 2; i < voff + consumed; i += 8) { + proto_tree_add_text(v_tree, NullTVB, i, 8, + "Destination IP Address/Router: %s/%s", + ip_to_str((guint8*)&pd[i]), + ip_to_str((guint8*)&pd[i+4])); } - break; + } + break; - /* Client Identifier */ - case 61: - /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll - guess that the first is the hwtype, and the last 6 are - the hw addr */ - if (vlen == 7) { - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); - proto_tree_add_text(v_tree, NullTVB, voff+2, 1, - "Hardware type: %s", - arphrdtype_to_str(pd[voff+2], - "Unknown (0x%02x)")); - proto_tree_add_text(v_tree, NullTVB, voff+3, 6, - "Client hardware address: %s", - arphrdaddr_to_str((guint8*)&pd[voff+3], - 6, pd[voff+2])); - } - /* otherwise, it's opaque data */ - else { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s (%d bytes)", code, text, vlen); - } - break; + case 43: /* Vendor-Specific Info */ + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s", code, text); + break; - /* NetWare/IP options */ - case 63: - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); + case 46: /* NetBIOS-over-TCP/IP Node Type */ + byte = pd[voff+2]; + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %s", code, text, + val_to_str(byte, nbnt_vals, + "Unknown (0x%02x)")); + break; + + case 53: /* DHCP Message Type */ + proto_tree_add_text(bp_tree, NullTVB, voff, 3, "Option %d: %s = DHCP %s", + code, text, get_dhcp_type(pd[voff+2])); + break; - i=1; - optp=voff+2; - while ( optp < (voff+consumed) ) { - if (pd[optp] > NUM_O63_SUBOPTS) { - proto_tree_add_text(v_tree, NullTVB,optp,1,"Unknown suboption %d", pd[optp]); - optp++; - } else { - - switch (o63_opt[pd[optp]].ft) { - - case string: - proto_tree_add_text(v_tree, NullTVB, optp, 2, "Suboption %d: %s", pd[optp], o63_opt[pd[optp]].truet); - optp+=2; - break; - - case yes_no: - if (pd[optp+2]==1) { - proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s", pd[optp], o63_opt[pd[optp]].truet); - } else { - proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s" , pd[optp], o63_opt[pd[optp]].falset); - } - optp+=3; - break; - - case special: - proto_tree_add_text(v_tree, NullTVB, optp, 6, - "Suboption %d: %s = %s" , - pd[optp], o63_opt[pd[optp]].truet, - ip_to_str((guint8*)&pd[optp+2])); - optp=optp+6; - break; - - case val_u_short: - proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s = %d",pd[optp], o63_opt[pd[optp]].truet, pd[optp+2]); - optp+=3; - break; - - case ipv4: - /* one IP address */ - if (pd[optp+1] == 4) { - proto_tree_add_text(v_tree, NullTVB, optp, 6, - "Suboption %d : %s = %s" , - pd[optp], o63_opt[pd[optp]].truet, - ip_to_str((guint8*)&pd[optp+2])); - optp=optp+6; + case 55: /* Parameter Request List */ + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + vlen + 2, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (i = 0; i < vlen; i++) { + byte = pd[voff+2+i]; + if (byte < NUM_OPT_INFOS) { + proto_tree_add_text(v_tree, NullTVB, voff+2+i, 1, "%d = %s", + byte, opt[byte].text); + } else { + proto_tree_add_text(vti, NullTVB, voff+2+i, 1, + "Unknown Option Code: %d", byte); + } } - /* > 1 IP addresses. Let's make a sub-tree */ - else { + break; - vti = proto_tree_add_text(v_tree, NullTVB, optp, - pd[optp+1]+2, "Suboption %d: %s", - pd[optp], o63_opt[pd[optp]].truet); - o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (slask = optp + 2 ; slask < optp+pd[optp+1]; slask += 4) { - proto_tree_add_text(o63_v_tree, NullTVB, slask, 4, "IP Address: %s", - ip_to_str((guint8*)&pd[slask])); - } - optp=slask; + 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 + are the hw addr */ + if (vlen == 7) { + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + consumed, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + proto_tree_add_text(v_tree, NullTVB, voff+2, 1, + "Hardware type: %s", + arphrdtype_to_str(pd[voff+2], + "Unknown (0x%02x)")); + proto_tree_add_text(v_tree, NullTVB, voff+3, 6, + "Client hardware address: %s", + arphrdaddr_to_str((guint8*)&pd[voff+3], + 6, pd[voff+2])); + } else { + /* otherwise, it's opaque data */ + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s (%d bytes)", code, text, vlen); } break; - default: - proto_tree_add_text(v_tree, NullTVB,optp,1,"Unknown suboption %d", pd[optp]); - optp++; - break; - } - } - i++; - } - break; - /* End Option */ - case 255: - proto_tree_add_text(bp_tree, NullTVB, voff, 1, "End Option"); - consumed = 1; - return consumed; + case 63: /* NetWare/IP options */ + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + consumed, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); - default: - /* nothing */ - break; + optp = voff+2; + while (optp < voff+consumed) + optp = dissect_netware_ip_suboption(v_tree, pd, optp); + break; + + default: /* not special */ + break; } /* Normal cases */ @@ -441,116 +355,111 @@ bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) ftype = opt[code].ftype; switch (ftype) { - case special: - return consumed; - case ipv4: + case special: + return consumed; + + case ipv4: + if (vlen == 4) { /* one IP address */ - if (vlen == 4) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s", code, text, - ip_to_str((guint8*)&pd[voff+2])); - } + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %s", code, text, + ip_to_str((guint8*)&pd[voff+2])); + } else { /* > 1 IP addresses. Let's make a sub-tree */ - else { - - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = voff + 2; i < voff + consumed; i += 4) { - proto_tree_add_text(v_tree, NullTVB, i, 4, "IP Address: %s", - ip_to_str((guint8*)&pd[i])); - } + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + consumed, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (i = voff + 2; i < voff + consumed; i += 4) { + proto_tree_add_text(v_tree, NullTVB, i, 4, "IP Address: %s", + ip_to_str((guint8*)&pd[i])); } - break; - - case string: - /* Fix for non null-terminated string supplied by - * John Lines <John.Lines@aeat.co.uk> - */ - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %.*s", code, text, vlen, &pd[voff+2]); - break; + } + break; - case opaque: - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s (%d bytes)", - code, text, vlen); - break; + case string: + /* Fix for non null-terminated string supplied by + * John Lines <John.Lines@aeat.co.uk> + */ + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %.*s", code, text, vlen, &pd[voff+2]); + break; - case val_u_short: - /* one IP address */ - if (vlen == 2) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %d", code, text, - pntohs(&pd[voff+2])); - } - /* > 1 u_short */ - else { - vti = proto_tree_add_text(bp_tree, NullTVB, voff, - consumed, "Option %d: %s", code, text); - v_tree = proto_item_add_subtree(vti, ett_bootp_option); - for (i = voff + 2; i < voff + consumed; i += 2) { - proto_tree_add_text(v_tree, NullTVB, i, 4, "Value: %d", - pntohs(&pd[i])); - } - } - break; + case opaque: + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s (%d bytes)", + code, text, vlen); + break; - case val_u_long: + case val_u_short: + if (vlen == 2) { + /* one u_short */ proto_tree_add_text(bp_tree, NullTVB, voff, consumed, "Option %d: %s = %d", code, text, - pntohl(&pd[voff+2])); - break; - - case val_u_byte: - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %d", code, text, pd[voff+2]); - break; - - case toggle: - i = pd[voff+2]; - if (i != 0 && i != 1) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = Invalid Value %d", code, text, - pd[voff+2]); - } - else { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s", code, text, - pd[voff+2] == 0 ? "Disabled" : "Enabled"); + pntohs(&pd[voff+2])); + } else { + /* > 1 u_short */ + vti = proto_tree_add_text(bp_tree, NullTVB, voff, + consumed, "Option %d: %s", code, text); + v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (i = voff + 2; i < voff + consumed; i += 2) { + proto_tree_add_text(v_tree, NullTVB, i, 4, "Value: %d", + pntohs(&pd[i])); } - break; + } + break; - case yes_no: - i = pd[voff+2]; - if (i != 0 && i != 1) { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = Invalid Value %d", code, text, - pd[voff+2]); - } - else { - proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s", code, text, - pd[voff+2] == 0 ? "No" : "Yes"); - } - break; + case val_u_long: + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %d", code, text, + pntohl(&pd[voff+2])); + break; - case time_in_secs: - time_secs = pntohl(&pd[voff+2]); + case val_u_byte: + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %d", code, text, pd[voff+2]); + break; + + case toggle: + i = pd[voff+2]; + if (i != 0 && i != 1) { proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s = %s", code, text, - ((time_secs == 0xffffffff) ? - "infinity" : - time_secs_to_str(time_secs))); - break; + "Option %d: %s = Invalid Value %d", code, text, + pd[voff+2]); + } else { + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %s", code, text, + pd[voff+2] == 0 ? "Disabled" : "Enabled"); + } + break; - default: + case yes_no: + i = pd[voff+2]; + if (i != 0 && i != 1) { + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = Invalid Value %d", code, text, + pd[voff+2]); + } else { proto_tree_add_text(bp_tree, NullTVB, voff, consumed, - "Option %d: %s (%d bytes)", code, text, vlen); + "Option %d: %s = %s", code, text, + pd[voff+2] == 0 ? "No" : "Yes"); + } + break; + + case time_in_secs: + time_secs = pntohl(&pd[voff+2]); + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s = %s", code, text, + ((time_secs == 0xffffffff) ? + "infinity" : + time_secs_to_str(time_secs))); + break; + + default: + proto_tree_add_text(bp_tree, NullTVB, voff, consumed, + "Option %d: %s (%d bytes)", code, text, vlen); } - } - else { + } else { proto_tree_add_text(bp_tree, NullTVB, voff, consumed, "Unknown Option Code: %d (%d bytes)", code, vlen); } @@ -558,15 +467,107 @@ bootp_option(const u_char *pd, proto_tree *bp_tree, int voff, int eoff) return consumed; } +static int +dissect_netware_ip_suboption(proto_tree *v_tree, const u_char *pd, int optp) +{ + int slask; + proto_tree *o63_v_tree; + proto_item *vti; + + struct o63_opt_info { + char *truet; + char *falset; + enum field_type ft; + }; + + static struct o63_opt_info o63_opt[]= { + /* 0 */ {"","",none}, + /* 1 */ {"NWIP does not exist on subnet","",string}, + /* 2 */ {"NWIP exist in options area","",string}, + /* 3 */ {"NWIP exists in sname/file","",string}, + /* 4 */ {"NWIP exists, but too big","",string}, + /* 5 */ {"Broadcast for nearest Netware server","Do NOT Broadcast for nearest Netware server",yes_no}, + /* 6 */ {"Preferred DSS server","",ipv4}, + /* 7 */ {"Nearest NWIP server","",ipv4}, + /* 8 */ {"Autoretries","",val_u_short}, + /* 9 */ {"Autoretry delay, secs ","",val_u_short}, + /* 10*/ {"Support NetWare/IP v1.1","Do NOT support NetWare/IP v1.1",yes_no}, + /* 11*/ {"Primary DSS ", "" , special} + }; + + if (pd[optp] > NUM_O63_SUBOPTS) { + proto_tree_add_text(v_tree, NullTVB,optp,1,"Unknown suboption %d", pd[optp]); + optp++; + } else { + switch (o63_opt[pd[optp]].ft) { + + case string: + proto_tree_add_text(v_tree, NullTVB, optp, 2, "Suboption %d: %s", pd[optp], o63_opt[pd[optp]].truet); + optp+=2; + break; + + case yes_no: + if (pd[optp+2]==1) { + proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s", pd[optp], o63_opt[pd[optp]].truet); + } else { + proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s" , pd[optp], o63_opt[pd[optp]].falset); + } + optp+=3; + break; + + case special: + proto_tree_add_text(v_tree, NullTVB, optp, 6, + "Suboption %d: %s = %s" , + pd[optp], o63_opt[pd[optp]].truet, + ip_to_str((guint8*)&pd[optp+2])); + optp=optp+6; + break; + + case val_u_short: + proto_tree_add_text(v_tree, NullTVB, optp, 3, "Suboption %d: %s = %d",pd[optp], o63_opt[pd[optp]].truet, pd[optp+2]); + optp+=3; + break; + + case ipv4: + if (pd[optp+1] == 4) { + /* one IP address */ + proto_tree_add_text(v_tree, NullTVB, optp, 6, + "Suboption %d : %s = %s", + pd[optp], o63_opt[pd[optp]].truet, + ip_to_str((guint8*)&pd[optp+2])); + optp=optp+6; + } else { + /* > 1 IP addresses. Let's make a sub-tree */ + vti = proto_tree_add_text(v_tree, NullTVB, optp, + pd[optp+1]+2, "Suboption %d: %s", + pd[optp], o63_opt[pd[optp]].truet); + o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option); + for (slask = optp + 2 ; slask < optp+pd[optp+1]; slask += 4) { + proto_tree_add_text(o63_v_tree, NullTVB, slask, 4, "IP Address: %s", + ip_to_str((guint8*)&pd[slask])); + } + optp=slask; + } + break; + default: + proto_tree_add_text(v_tree, NullTVB,optp,1,"Unknown suboption %d", pd[optp]); + optp++; + break; + } + } + return optp; +} + static void dissect_bootp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - proto_tree *bp_tree; + proto_tree *bp_tree = NULL; proto_item *ti; - int voff, eoff; /* vender offset, end offset */ + int voff, eoff; /* vender offset, end offset */ guint32 ip_addr; + const char *dhcp_type; - is_dhcp = NULL; + dhcp_type = NULL; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "BOOTP"); @@ -674,20 +675,26 @@ dissect_bootp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) proto_tree_add_ipv4(bp_tree, hf_bootp_cookie, NullTVB, offset + 236, 4, ip_addr); } + } - voff = offset+240; - eoff = pi.captured_len; - - while (voff < eoff) { - voff += bootp_option(pd, bp_tree, voff, eoff); - } - if (is_dhcp != NULL ) { - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "DHCP"); - if (check_col(fd, COL_INFO)) - col_add_fstr(fd, COL_INFO, "DHCP %-8s - Trans. ID 0x%x", is_dhcp, pntohl(&pd[offset+4]) ); - proto_tree_add_boolean_hidden(bp_tree, hf_bootp_dhcp, NullTVB, 0, 0, 1); - } + voff = offset+240; + eoff = pi.captured_len; + while (voff < eoff) { + /* Handle the DHCP option specially here, so that we + can flag DHCP packets as such. */ + if (pd[voff] == 53) + dhcp_type = get_dhcp_type(pd[voff+2]); + voff += bootp_option(pd, bp_tree, voff, eoff); + } + if (dhcp_type != NULL ) { + if (check_col(fd, COL_PROTOCOL)) + col_add_str(fd, COL_PROTOCOL, "DHCP"); + if (check_col(fd, COL_INFO)) + col_add_fstr(fd, COL_INFO, "DHCP %-8s - Transaction ID 0x%x", + dhcp_type, pntohl(&pd[offset+4])); + if (tree) + proto_tree_add_boolean_hidden(bp_tree, hf_bootp_dhcp, + NullTVB, 0, 0, 1); } } |