1998-09-16 02:39:15 +00:00
|
|
|
/* packet-bootp.c
|
|
|
|
* Routines for BOOTP/DHCP packet disassembly
|
2001-11-13 23:55:44 +00:00
|
|
|
* Gilbert Ramirez <gram@alumni.rice.edu>
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
2003-11-18 19:56:37 +00:00
|
|
|
* $Id: packet-bootp.c,v 1.76 2003/11/18 19:56:37 guy Exp $
|
1998-09-16 03:22:19 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* The information used comes from:
|
2000-07-25 21:26:08 +00:00
|
|
|
* RFC 951: Bootstrap Protocol
|
2001-12-27 22:49:02 +00:00
|
|
|
* RFC 1497: BOOTP extensions
|
1998-09-16 02:39:15 +00:00
|
|
|
* RFC 1542: Clarifications and Extensions for the Bootstrap Protocol
|
|
|
|
* RFC 2131: Dynamic Host Configuration Protocol
|
2000-07-25 21:26:08 +00:00
|
|
|
* RFC 2132: DHCP Options and BOOTP Vendor Extensions
|
|
|
|
* RFC 2489: Procedure for Defining New DHCP Options
|
2003-11-18 19:56:37 +00:00
|
|
|
* RFC 2610: DHCP Options for Service Location Protocol
|
2001-02-13 00:01:08 +00:00
|
|
|
* RFC 3046: DHCP Relay Agent Information Option
|
2001-10-31 08:43:09 +00:00
|
|
|
* RFC 3118: Authentication for DHCP Messages
|
2003-02-07 04:25:37 +00:00
|
|
|
* RFC 3203: DHCP reconfigure extension
|
2000-07-25 21:26:08 +00:00
|
|
|
* BOOTP and DHCP Parameters
|
2001-10-31 08:43:09 +00:00
|
|
|
* http://www.iana.org/assignments/bootp-dhcp-parameters
|
1998-09-16 02:39:15 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
2001-10-29 21:56:50 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
1998-09-16 02:39:15 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2000-11-17 21:00:40 +00:00
|
|
|
#include <string.h>
|
1999-03-23 03:14:46 +00:00
|
|
|
#include <glib.h>
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/int-64bit.h>
|
|
|
|
#include <epan/packet.h>
|
1999-11-27 04:48:14 +00:00
|
|
|
#include "packet-arp.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
#include "prefs.h"
|
2003-09-02 22:47:59 +00:00
|
|
|
#include "tap.h"
|
|
|
|
|
|
|
|
static int bootp_dhcp_tap = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
static int proto_bootp = -1;
|
1999-10-08 13:57:31 +00:00
|
|
|
static int hf_bootp_type = -1;
|
|
|
|
static int hf_bootp_hw_type = -1;
|
|
|
|
static int hf_bootp_hw_len = -1;
|
|
|
|
static int hf_bootp_hops = -1;
|
|
|
|
static int hf_bootp_id = -1;
|
|
|
|
static int hf_bootp_secs = -1;
|
2002-06-19 19:39:38 +00:00
|
|
|
static int hf_bootp_flags = -1;
|
|
|
|
static int hf_bootp_flags_broadcast = -1;
|
|
|
|
static int hf_bootp_flags_reserved = -1;
|
1999-10-08 13:57:31 +00:00
|
|
|
static int hf_bootp_ip_client = -1;
|
|
|
|
static int hf_bootp_ip_your = -1;
|
|
|
|
static int hf_bootp_ip_server = -1;
|
|
|
|
static int hf_bootp_ip_relay = -1;
|
|
|
|
static int hf_bootp_hw_addr = -1;
|
|
|
|
static int hf_bootp_server = -1;
|
|
|
|
static int hf_bootp_file = -1;
|
|
|
|
static int hf_bootp_cookie = -1;
|
2002-06-19 19:39:38 +00:00
|
|
|
static int hf_bootp_vendor = -1;
|
2000-05-19 02:16:17 +00:00
|
|
|
static int hf_bootp_dhcp = -1;
|
1999-07-29 05:47:07 +00:00
|
|
|
|
1999-11-16 11:44:20 +00:00
|
|
|
static guint ett_bootp = -1;
|
2002-06-19 19:39:38 +00:00
|
|
|
static guint ett_bootp_flags = -1;
|
1999-11-16 11:44:20 +00:00
|
|
|
static guint ett_bootp_option = -1;
|
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
gboolean novell_string = FALSE;
|
|
|
|
|
2000-04-08 07:07:42 +00:00
|
|
|
#define UDP_PORT_BOOTPS 67
|
2002-05-28 20:08:09 +00:00
|
|
|
#define UDP_PORT_BOOTPC 68
|
2000-04-08 07:07:42 +00:00
|
|
|
|
2002-06-19 19:39:38 +00:00
|
|
|
#define BOOTP_BC 0x8000
|
|
|
|
#define BOOTP_MBZ 0x7FFF
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
enum field_type { none, ipv4, string, toggle, yes_no, special, opaque,
|
1999-01-28 21:29:36 +00:00
|
|
|
time_in_secs,
|
2001-05-24 19:21:15 +00:00
|
|
|
val_u_byte, val_u_short, val_u_le_short, val_u_long,
|
1998-09-16 02:39:15 +00:00
|
|
|
val_s_long };
|
|
|
|
|
|
|
|
struct opt_info {
|
|
|
|
char *text;
|
|
|
|
enum field_type ftype;
|
|
|
|
};
|
|
|
|
|
2002-06-19 19:39:38 +00:00
|
|
|
static const true_false_string flag_set_broadcast = {
|
|
|
|
"Broadcast",
|
|
|
|
"Unicast"
|
|
|
|
};
|
|
|
|
|
2001-05-01 03:54:04 +00:00
|
|
|
#define NUM_OPT_INFOS 211
|
2000-03-20 21:39:00 +00:00
|
|
|
#define NUM_O63_SUBOPTS 11
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
static int dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
|
|
|
|
int optp);
|
2001-01-03 22:49:06 +00:00
|
|
|
static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
|
2000-07-09 22:46:53 +00:00
|
|
|
int optp);
|
2001-02-13 00:01:08 +00:00
|
|
|
static int bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb,
|
|
|
|
int optp);
|
2000-03-20 21:39:00 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
static const char *
|
|
|
|
get_dhcp_type(guint8 byte)
|
|
|
|
{
|
1999-01-28 21:29:36 +00:00
|
|
|
static const char *opt53_text[] = {
|
1998-09-16 02:39:15 +00:00
|
|
|
"Unknown Message Type",
|
|
|
|
"Discover",
|
|
|
|
"Offer",
|
|
|
|
"Request",
|
|
|
|
"Decline",
|
|
|
|
"ACK",
|
|
|
|
"NAK",
|
|
|
|
"Release",
|
2003-02-13 08:29:19 +00:00
|
|
|
"Inform",
|
2003-02-07 04:25:37 +00:00
|
|
|
"Force Renew"
|
1998-09-16 02:39:15 +00:00
|
|
|
};
|
2000-07-09 22:46:53 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (byte > 0 && byte < (sizeof opt53_text / sizeof opt53_text[0]))
|
|
|
|
i = byte;
|
|
|
|
else
|
|
|
|
i = 0;
|
|
|
|
return opt53_text[i];
|
|
|
|
}
|
|
|
|
|
2001-10-31 08:43:09 +00:00
|
|
|
/* DHCP Authentication protocols */
|
|
|
|
#define AUTHEN_PROTO_CONFIG_TOKEN 0
|
|
|
|
#define AUTHEN_PROTO_DELAYED_AUTHEN 1
|
|
|
|
|
|
|
|
/* DHCP Authentication algorithms for delayed authentication */
|
|
|
|
#define AUTHEN_DELAYED_ALGO_HMAC_MD5 1
|
|
|
|
|
|
|
|
/* DHCP Authentication Replay Detection Methods */
|
|
|
|
#define AUTHEN_RDM_MONOTONIC_COUNTER 0x00
|
|
|
|
|
2002-09-28 04:12:38 +00:00
|
|
|
/* DHCP Option Overload (option code 52) */
|
|
|
|
#define OPT_OVERLOAD_FILE 1
|
|
|
|
#define OPT_OVERLOAD_SNAME 2
|
|
|
|
#define OPT_OVERLOAD_BOTH 3
|
|
|
|
|
|
|
|
/* Server name and boot file offsets and lengths */
|
|
|
|
#define SERVER_NAME_OFFSET 44
|
|
|
|
#define SERVER_NAME_LEN 64
|
|
|
|
#define FILE_NAME_OFFSET 108
|
|
|
|
#define FILE_NAME_LEN 128
|
|
|
|
#define VENDOR_INFO_OFFSET 236
|
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
/* Returns the number of bytes consumed by this option. */
|
|
|
|
static int
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
bootp_option(tvbuff_t *tvb, proto_tree *bp_tree, int voff, int eoff,
|
2001-12-27 23:53:10 +00:00
|
|
|
gboolean first_pass, gboolean *at_end, const char **dhcp_type_p,
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
const guint8 **vendor_class_id_p)
|
2000-07-09 22:46:53 +00:00
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
enum field_type ftype;
|
2002-08-02 23:36:07 +00:00
|
|
|
guchar code = tvb_get_guint8(tvb, voff);
|
2001-01-03 22:49:06 +00:00
|
|
|
int vlen;
|
2002-08-02 23:36:07 +00:00
|
|
|
guchar byte;
|
2001-01-03 22:49:06 +00:00
|
|
|
int i,optp, consumed;
|
2002-08-02 23:36:07 +00:00
|
|
|
gulong time_secs;
|
2002-09-28 04:12:38 +00:00
|
|
|
proto_tree *v_tree, *o52tree;
|
2000-07-09 22:46:53 +00:00
|
|
|
proto_item *vti;
|
2001-10-31 08:43:09 +00:00
|
|
|
guint8 protocol;
|
|
|
|
guint8 algorithm;
|
|
|
|
guint8 rdm;
|
2002-09-28 04:12:38 +00:00
|
|
|
int o52voff, o52eoff;
|
|
|
|
gboolean o52at_end;
|
2000-07-09 22:46:53 +00:00
|
|
|
|
1999-01-28 21:29:36 +00:00
|
|
|
static const value_string nbnt_vals[] = {
|
|
|
|
{0x1, "B-node" },
|
|
|
|
{0x2, "P-node" },
|
|
|
|
{0x4, "M-node" },
|
|
|
|
{0x8, "H-node" },
|
|
|
|
{0, NULL } };
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
static const value_string slpda_vals[] = {
|
|
|
|
{0x00, "Dynamic Discovery" },
|
|
|
|
{0x01, "Static Discovery" },
|
|
|
|
{0x80, "Backwards compatibility" },
|
|
|
|
{0, NULL } };
|
|
|
|
|
|
|
|
static const value_string slp_scope_vals[] = {
|
|
|
|
{0x00, "Preferred Scope" },
|
|
|
|
{0x01, "Mandatory Scope" },
|
|
|
|
{0, NULL } };
|
|
|
|
|
2001-10-31 08:43:09 +00:00
|
|
|
static const value_string authen_protocol_vals[] = {
|
|
|
|
{AUTHEN_PROTO_CONFIG_TOKEN, "configuration token" },
|
|
|
|
{AUTHEN_PROTO_DELAYED_AUTHEN, "delayed authentication" },
|
|
|
|
{0, NULL } };
|
|
|
|
|
|
|
|
static const value_string authen_da_algo_vals[] = {
|
|
|
|
{AUTHEN_DELAYED_ALGO_HMAC_MD5, "HMAC_MD5" },
|
|
|
|
{0, NULL } };
|
|
|
|
|
|
|
|
static const value_string authen_rdm_vals[] = {
|
|
|
|
{AUTHEN_RDM_MONOTONIC_COUNTER, "Monotonically-increasing counter" },
|
|
|
|
{0, NULL } };
|
|
|
|
|
2002-09-28 04:12:38 +00:00
|
|
|
static const value_string opt_overload_vals[] = {
|
|
|
|
{ OPT_OVERLOAD_FILE, "Boot file name holds options", },
|
|
|
|
{ OPT_OVERLOAD_SNAME, "Server host name holds options", },
|
|
|
|
{ OPT_OVERLOAD_BOTH, "Boot file and server host names hold options" },
|
|
|
|
{ 0, NULL } };
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
static struct opt_info opt[] = {
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 0 */ { "Padding", none },
|
|
|
|
/* 1 */ { "Subnet Mask", ipv4 },
|
|
|
|
/* 2 */ { "Time Offset", val_s_long },
|
|
|
|
/* 3 */ { "Router", ipv4 },
|
|
|
|
/* 4 */ { "Time Server", ipv4 },
|
|
|
|
/* 5 */ { "Name Server", ipv4 },
|
|
|
|
/* 6 */ { "Domain Name Server", ipv4 },
|
|
|
|
/* 7 */ { "Log Server", ipv4 },
|
|
|
|
/* 8 */ { "Cookie Server", ipv4 },
|
|
|
|
/* 9 */ { "LPR Server", ipv4 },
|
|
|
|
/* 10 */ { "Impress Server", ipv4 },
|
|
|
|
/* 11 */ { "Resource Location Server", ipv4 },
|
|
|
|
/* 12 */ { "Host Name", string },
|
|
|
|
/* 13 */ { "Boot File Size", val_u_short },
|
|
|
|
/* 14 */ { "Merit Dump File", string },
|
|
|
|
/* 15 */ { "Domain Name", string },
|
|
|
|
/* 16 */ { "Swap Server", ipv4 },
|
|
|
|
/* 17 */ { "Root Path", string },
|
|
|
|
/* 18 */ { "Extensions Path", string },
|
|
|
|
/* 19 */ { "IP Forwarding", toggle },
|
|
|
|
/* 20 */ { "Non-Local Source Routing", toggle },
|
|
|
|
/* 21 */ { "Policy Filter", special },
|
1998-09-16 02:39:15 +00:00
|
|
|
/* 22 */ { "Maximum Datagram Reassembly Size", val_u_short },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 23 */ { "Default IP Time-to-Live", val_u_byte },
|
|
|
|
/* 24 */ { "Path MTU Aging Timeout", time_in_secs },
|
|
|
|
/* 25 */ { "Path MTU Plateau Table", val_u_short },
|
|
|
|
/* 26 */ { "Interface MTU", val_u_short },
|
|
|
|
/* 27 */ { "All Subnets are Local", yes_no },
|
|
|
|
/* 28 */ { "Broadcast Address", ipv4 },
|
|
|
|
/* 29 */ { "Perform Mask Discovery", toggle },
|
|
|
|
/* 30 */ { "Mask Supplier", yes_no },
|
|
|
|
/* 31 */ { "Perform Router Discover", toggle },
|
|
|
|
/* 32 */ { "Router Solicitation Address", ipv4 },
|
|
|
|
/* 33 */ { "Static Route", special },
|
|
|
|
/* 34 */ { "Trailer Encapsulation", toggle },
|
|
|
|
/* 35 */ { "ARP Cache Timeout", time_in_secs },
|
|
|
|
/* 36 */ { "Ethernet Encapsulation", toggle },
|
|
|
|
/* 37 */ { "TCP Default TTL", val_u_byte },
|
|
|
|
/* 38 */ { "TCP Keepalive Interval", time_in_secs },
|
|
|
|
/* 39 */ { "TCP Keepalive Garbage", toggle },
|
1998-09-16 02:39:15 +00:00
|
|
|
/* 40 */ { "Network Information Service Domain", string },
|
|
|
|
/* 41 */ { "Network Information Service Servers", ipv4 },
|
|
|
|
/* 42 */ { "Network Time Protocol Servers", ipv4 },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 43 */ { "Vendor-Specific Information", special },
|
1998-09-16 02:39:15 +00:00
|
|
|
/* 44 */ { "NetBIOS over TCP/IP Name Server", ipv4 },
|
|
|
|
/* 45 */ { "NetBIOS over TCP/IP Datagram Distribution Name Server", ipv4 },
|
|
|
|
/* 46 */ { "NetBIOS over TCP/IP Node Type", special },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 47 */ { "NetBIOS over TCP/IP Scope", string },
|
|
|
|
/* 48 */ { "X Window System Font Server", ipv4 },
|
1998-09-16 02:39:15 +00:00
|
|
|
/* 49 */ { "X Window System Display Manager", ipv4 },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 50 */ { "Requested IP Address", ipv4 },
|
|
|
|
/* 51 */ { "IP Address Lease Time", time_in_secs },
|
|
|
|
/* 52 */ { "Option Overload", special },
|
|
|
|
/* 53 */ { "DHCP Message Type", special },
|
|
|
|
/* 54 */ { "Server Identifier", ipv4 },
|
|
|
|
/* 55 */ { "Parameter Request List", special },
|
|
|
|
/* 56 */ { "Message", string },
|
|
|
|
/* 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", special },
|
|
|
|
/* 61 */ { "Client identifier", special },
|
|
|
|
/* 62 */ { "Novell/Netware IP domain", string },
|
|
|
|
/* 63 */ { "Novell Options", special },
|
1998-09-16 02:39:15 +00:00
|
|
|
/* 64 */ { "Network Information Service+ Domain", string },
|
|
|
|
/* 65 */ { "Network Information Service+ Servers", ipv4 },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 66 */ { "TFTP Server Name", string },
|
|
|
|
/* 67 */ { "Bootfile name", string },
|
|
|
|
/* 68 */ { "Mobile IP Home Agent", ipv4 },
|
|
|
|
/* 69 */ { "SMTP Server", ipv4 },
|
|
|
|
/* 70 */ { "POP3 Server", ipv4 },
|
|
|
|
/* 71 */ { "NNTP Server", ipv4 },
|
|
|
|
/* 72 */ { "Default WWW Server", ipv4 },
|
|
|
|
/* 73 */ { "Default Finger Server", ipv4 },
|
|
|
|
/* 74 */ { "Default IRC Server", ipv4 },
|
|
|
|
/* 75 */ { "StreetTalk Server", ipv4 },
|
|
|
|
/* 76 */ { "StreetTalk Directory Assistance Server", ipv4 },
|
|
|
|
/* 77 */ { "User Class Information", opaque },
|
2003-11-18 19:56:37 +00:00
|
|
|
/* 78 */ { "Directory Agent Information", special },
|
|
|
|
/* 79 */ { "Service Location Agent Scope", special },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 80 */ { "Naming Authority", opaque },
|
2000-07-25 21:26:08 +00:00
|
|
|
/* 81 */ { "Client Fully Qualified Domain Name", opaque },
|
2001-02-13 00:01:08 +00:00
|
|
|
/* 82 */ { "Agent Information Option", special },
|
|
|
|
/* 83 */ { "Unassigned", opaque },
|
|
|
|
/* 84 */ { "Unassigned", opaque },
|
2003-11-18 19:56:37 +00:00
|
|
|
/* 85 */ { "Novell Directory Services Servers", special },
|
|
|
|
/* 86 */ { "Novell Directory Services Tree Name", string },
|
|
|
|
/* 87 */ { "Novell Directory Services Context", string },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 88 */ { "IEEE 1003.1 POSIX Timezone", opaque },
|
|
|
|
/* 89 */ { "Fully Qualified Domain Name", opaque },
|
2001-10-31 08:43:09 +00:00
|
|
|
/* 90 */ { "Authentication", special },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 91 */ { "Vines TCP/IP Server Option", opaque },
|
|
|
|
/* 92 */ { "Server Selection Option", opaque },
|
|
|
|
/* 93 */ { "Client System Architecture", opaque },
|
2000-07-25 21:26:08 +00:00
|
|
|
/* 94 */ { "Client Network Device Interface", opaque },
|
|
|
|
/* 95 */ { "Lightweight Directory Access Protocol", opaque },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 96 */ { "IPv6 Transitions", opaque },
|
2000-07-25 21:26:08 +00:00
|
|
|
/* 97 */ { "UUID/GUID-based Client Identifier", opaque },
|
|
|
|
/* 98 */ { "Open Group's User Authentication", opaque },
|
2003-07-29 00:35:55 +00:00
|
|
|
/* 99 */ { "Unassigned", opaque },
|
|
|
|
/* 100 */ { "Printer Name", opaque },
|
|
|
|
/* 101 */ { "MDHCP multicast address", opaque },
|
|
|
|
/* 102 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 103 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 104 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 105 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 106 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 107 */ { "Removed/unassigned", opaque },
|
|
|
|
/* 108 */ { "Swap Path Option", opaque },
|
|
|
|
/* 109 */ { "Unassigned", opaque },
|
|
|
|
/* 110 */ { "IPX Compability", opaque },
|
|
|
|
/* 111 */ { "Unassigned", opaque },
|
|
|
|
/* 112 */ { "NetInfo Parent Server Address", ipv4 },
|
|
|
|
/* 113 */ { "NetInfo Parent Server Tag", string },
|
|
|
|
/* 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 },
|
|
|
|
/* 123 */ { "Unassigned", opaque },
|
|
|
|
/* 124 */ { "Unassigned", opaque },
|
|
|
|
/* 125 */ { "Unassigned", opaque },
|
|
|
|
/* 126 */ { "Extension", opaque },
|
|
|
|
/* 127 */ { "Extension", opaque },
|
2001-05-01 03:54:04 +00:00
|
|
|
/* 128 */ { "Private", opaque },
|
|
|
|
/* 129 */ { "Private", opaque },
|
|
|
|
/* 130 */ { "Private", opaque },
|
|
|
|
/* 131 */ { "Private", opaque },
|
|
|
|
/* 132 */ { "Private", opaque },
|
|
|
|
/* 133 */ { "Private", opaque },
|
|
|
|
/* 134 */ { "Private", opaque },
|
|
|
|
/* 135 */ { "Private", opaque },
|
|
|
|
/* 136 */ { "Private", opaque },
|
|
|
|
/* 137 */ { "Private", opaque },
|
|
|
|
/* 138 */ { "Private", opaque },
|
|
|
|
/* 139 */ { "Private", opaque },
|
|
|
|
/* 140 */ { "Private", opaque },
|
|
|
|
/* 141 */ { "Private", opaque },
|
|
|
|
/* 142 */ { "Private", opaque },
|
|
|
|
/* 143 */ { "Private", opaque },
|
|
|
|
/* 144 */ { "Private", opaque },
|
|
|
|
/* 145 */ { "Private", opaque },
|
|
|
|
/* 146 */ { "Private", opaque },
|
|
|
|
/* 147 */ { "Private", opaque },
|
|
|
|
/* 148 */ { "Private", opaque },
|
|
|
|
/* 149 */ { "Private", opaque },
|
|
|
|
/* 150 */ { "Private", opaque },
|
|
|
|
/* 151 */ { "Private", opaque },
|
|
|
|
/* 152 */ { "Private", opaque },
|
|
|
|
/* 153 */ { "Private", opaque },
|
|
|
|
/* 154 */ { "Private", opaque },
|
|
|
|
/* 155 */ { "Private", opaque },
|
|
|
|
/* 156 */ { "Private", opaque },
|
|
|
|
/* 157 */ { "Private", opaque },
|
|
|
|
/* 158 */ { "Private", opaque },
|
|
|
|
/* 159 */ { "Private", opaque },
|
|
|
|
/* 160 */ { "Private", opaque },
|
|
|
|
/* 161 */ { "Private", opaque },
|
|
|
|
/* 162 */ { "Private", opaque },
|
|
|
|
/* 163 */ { "Private", opaque },
|
|
|
|
/* 164 */ { "Private", opaque },
|
|
|
|
/* 165 */ { "Private", opaque },
|
|
|
|
/* 166 */ { "Private", opaque },
|
|
|
|
/* 167 */ { "Private", opaque },
|
|
|
|
/* 168 */ { "Private", opaque },
|
|
|
|
/* 169 */ { "Private", opaque },
|
|
|
|
/* 170 */ { "Private", opaque },
|
|
|
|
/* 171 */ { "Private", opaque },
|
|
|
|
/* 172 */ { "Private", opaque },
|
|
|
|
/* 173 */ { "Private", opaque },
|
|
|
|
/* 174 */ { "Private", opaque },
|
|
|
|
/* 175 */ { "Private", opaque },
|
|
|
|
/* 176 */ { "Private", opaque },
|
|
|
|
/* 177 */ { "Private", opaque },
|
|
|
|
/* 178 */ { "Private", opaque },
|
|
|
|
/* 179 */ { "Private", opaque },
|
|
|
|
/* 180 */ { "Private", opaque },
|
|
|
|
/* 181 */ { "Private", opaque },
|
|
|
|
/* 182 */ { "Private", opaque },
|
|
|
|
/* 183 */ { "Private", opaque },
|
|
|
|
/* 184 */ { "Private", opaque },
|
|
|
|
/* 185 */ { "Private", opaque },
|
|
|
|
/* 186 */ { "Private", opaque },
|
|
|
|
/* 187 */ { "Private", opaque },
|
|
|
|
/* 188 */ { "Private", opaque },
|
|
|
|
/* 189 */ { "Private", opaque },
|
|
|
|
/* 190 */ { "Private", opaque },
|
|
|
|
/* 191 */ { "Private", opaque },
|
|
|
|
/* 192 */ { "Private", opaque },
|
|
|
|
/* 193 */ { "Private", opaque },
|
|
|
|
/* 194 */ { "Private", opaque },
|
|
|
|
/* 195 */ { "Private", opaque },
|
|
|
|
/* 196 */ { "Private", opaque },
|
|
|
|
/* 197 */ { "Private", opaque },
|
|
|
|
/* 198 */ { "Private", opaque },
|
|
|
|
/* 199 */ { "Private", opaque },
|
|
|
|
/* 200 */ { "Private", opaque },
|
|
|
|
/* 201 */ { "Private", opaque },
|
|
|
|
/* 202 */ { "Private", opaque },
|
|
|
|
/* 203 */ { "Private", opaque },
|
|
|
|
/* 204 */ { "Private", opaque },
|
|
|
|
/* 205 */ { "Private", opaque },
|
|
|
|
/* 206 */ { "Private", opaque },
|
|
|
|
/* 207 */ { "Private", opaque },
|
|
|
|
/* 208 */ { "Private", opaque },
|
|
|
|
/* 209 */ { "Private", opaque },
|
|
|
|
/* 210 */ { "Authentication", special }
|
1998-09-16 02:39:15 +00:00
|
|
|
};
|
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
/* Options whose length isn't "vlen + 2". */
|
1998-09-16 02:39:15 +00:00
|
|
|
switch (code) {
|
2000-07-09 22:46:53 +00:00
|
|
|
|
|
|
|
case 0: /* Padding */
|
|
|
|
/* check how much padding we have */
|
|
|
|
for (i = voff + 1; i < eoff; i++ ) {
|
2001-01-03 22:49:06 +00:00
|
|
|
if (tvb_get_guint8(tvb, i) != 0) {
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
i = i - voff;
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
if (!first_pass) {
|
|
|
|
if (bp_tree != NULL) {
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, i,
|
|
|
|
"Padding");
|
|
|
|
}
|
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
consumed = i;
|
|
|
|
return consumed;
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 255: /* End Option */
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
if (!first_pass) {
|
|
|
|
if (bp_tree != NULL) {
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, 1,
|
|
|
|
"End Option");
|
|
|
|
}
|
|
|
|
}
|
2001-12-27 23:53:10 +00:00
|
|
|
*at_end = TRUE;
|
2000-07-09 22:46:53 +00:00
|
|
|
consumed = 1;
|
|
|
|
return consumed;
|
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-01-03 22:49:06 +00:00
|
|
|
/*
|
|
|
|
* Get the length of the option, and the number of bytes it
|
|
|
|
* consumes (the length doesn't include the option code or
|
|
|
|
* length bytes).
|
2001-12-27 22:49:02 +00:00
|
|
|
*
|
|
|
|
* On the first pass, check first whether we have the length
|
|
|
|
* byte, so that we don't throw an exception; if we throw an
|
|
|
|
* exception in the first pass, which is only checking for options
|
|
|
|
* whose values we need in order to properly dissect the packet
|
|
|
|
* on the second pass, we won't actually dissect the options, so
|
|
|
|
* you won't be able to see which option had the problem.
|
2001-01-03 22:49:06 +00:00
|
|
|
*/
|
2001-12-27 22:49:02 +00:00
|
|
|
if (first_pass) {
|
|
|
|
if (!tvb_bytes_exist(tvb, voff+1, 1)) {
|
|
|
|
/*
|
|
|
|
* We don't have the length byte; just return 1
|
|
|
|
* as the number of bytes we consumed, to count
|
|
|
|
* the code byte.
|
|
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2001-01-03 22:49:06 +00:00
|
|
|
vlen = tvb_get_guint8(tvb, voff+1);
|
|
|
|
consumed = vlen + 2;
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* In the first pass, we don't put anything into the protocol
|
|
|
|
* tree; we just check for some options we have to look at
|
|
|
|
* in order to properly process the packet:
|
|
|
|
*
|
|
|
|
* 53 (DHCP message type) - if this is present, this is DHCP
|
|
|
|
*
|
|
|
|
* 60 (Vendor class identifier) - we need this in order to
|
|
|
|
* interpret the vendor-specific info
|
2001-12-27 22:49:02 +00:00
|
|
|
*
|
|
|
|
* We also check, before fetching anything, to make sure we
|
|
|
|
* have the entire item we're fetching, so that we don't throw
|
|
|
|
* an exception.
|
2001-05-24 19:21:15 +00:00
|
|
|
*/
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
if (first_pass) {
|
2001-12-27 22:49:02 +00:00
|
|
|
if (tvb_bytes_exist(tvb, voff+2, consumed-2)) {
|
|
|
|
switch (code) {
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
|
2001-12-27 22:49:02 +00:00
|
|
|
case 53:
|
|
|
|
*dhcp_type_p =
|
|
|
|
get_dhcp_type(tvb_get_guint8(tvb, voff+2));
|
|
|
|
break;
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
|
2001-12-27 22:49:02 +00:00
|
|
|
case 60:
|
|
|
|
*vendor_class_id_p =
|
|
|
|
tvb_get_ptr(tvb, voff+2, consumed-2);
|
|
|
|
break;
|
|
|
|
}
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't do anything else here.
|
|
|
|
*/
|
|
|
|
return consumed;
|
2001-05-24 19:21:15 +00:00
|
|
|
}
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the second pass - if there's a protocol tree to be
|
|
|
|
* built, we put stuff into it, otherwise we just return.
|
|
|
|
*/
|
2000-07-09 22:46:53 +00:00
|
|
|
if (bp_tree == NULL) {
|
|
|
|
/* Don't put anything in the protocol tree. */
|
|
|
|
return consumed;
|
|
|
|
}
|
|
|
|
|
|
|
|
text = opt[code].text;
|
|
|
|
/* Special cases */
|
|
|
|
switch (code) {
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 21: /* Policy Filter */
|
|
|
|
if (vlen == 8) {
|
1998-09-16 02:39:15 +00:00
|
|
|
/* one IP address pair */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s/%s", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+2, 4)),
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+6, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
1998-09-16 02:39:15 +00:00
|
|
|
/* > 1 IP address pair. Let's make a sub-tree */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
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) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, i, 8, "IP Address/Mask: %s/%s",
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i, 4)),
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
1999-01-28 21:29:36 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 33: /* Static Route */
|
|
|
|
if (vlen == 8) {
|
|
|
|
/* one IP address pair */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s/%s", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+2, 4)),
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+6, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
|
|
|
/* > 1 IP address pair. Let's make a sub-tree */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
consumed, "Option %d: %s", code, text);
|
1999-11-16 11:44:20 +00:00
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
2000-07-09 22:46:53 +00:00
|
|
|
for (i = voff + 2; i < voff + consumed; i += 8) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, i, 8,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Destination IP Address/Router: %s/%s",
|
2001-01-03 22:49:06 +00:00
|
|
|
ip_to_str(tvb_get_ptr(tvb, i, 4)),
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
|
1998-11-20 04:34:37 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 43: /* Vendor-Specific Info */
|
2001-05-24 19:21:15 +00:00
|
|
|
/* PXE protocol 2.1 as described in the intel specs */
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
if (*vendor_class_id_p != NULL &&
|
|
|
|
strncmp(*vendor_class_id_p, "PXEClient", strlen("PXEClient")) == 0) {
|
2001-05-24 19:21:15 +00:00
|
|
|
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);
|
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 46: /* NetBIOS-over-TCP/IP Node Type */
|
2001-01-03 22:49:06 +00:00
|
|
|
byte = tvb_get_guint8(tvb, voff+2);
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
val_to_str(byte, nbnt_vals,
|
|
|
|
"Unknown (0x%02x)"));
|
|
|
|
break;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2002-09-28 04:12:38 +00:00
|
|
|
case 52: /* Option Overload */
|
|
|
|
byte = tvb_get_guint8(tvb, voff+2);
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
val_to_str(byte, opt_overload_vals,
|
|
|
|
"Unknown (0x%02x)"));
|
|
|
|
|
|
|
|
/* Just in case we find an option 52 in sname or file */
|
|
|
|
if (voff > VENDOR_INFO_OFFSET && byte >= 1 && byte <= 3) {
|
|
|
|
o52tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
if (byte == 1 || byte == 3) { /* 'file' */
|
|
|
|
vti = proto_tree_add_text (o52tree, tvb,
|
|
|
|
FILE_NAME_OFFSET, FILE_NAME_LEN,
|
|
|
|
"Boot file name option overload");
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
o52voff = FILE_NAME_OFFSET;
|
|
|
|
o52eoff = FILE_NAME_OFFSET + FILE_NAME_LEN;
|
|
|
|
o52at_end = FALSE;
|
|
|
|
while (o52voff < o52eoff && !o52at_end) {
|
|
|
|
o52voff += bootp_option(tvb, v_tree, o52voff,
|
|
|
|
o52eoff, FALSE, &o52at_end,
|
|
|
|
dhcp_type_p, vendor_class_id_p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (byte == 2 || byte == 3) { /* 'sname' */
|
|
|
|
vti = proto_tree_add_text (o52tree, tvb,
|
|
|
|
SERVER_NAME_OFFSET, SERVER_NAME_LEN,
|
|
|
|
"Server host name option overload");
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
o52voff = SERVER_NAME_OFFSET;
|
|
|
|
o52eoff = SERVER_NAME_OFFSET + SERVER_NAME_LEN;
|
|
|
|
o52at_end = FALSE;
|
|
|
|
while (o52voff < o52eoff && !o52at_end) {
|
|
|
|
o52voff += bootp_option(tvb, v_tree, o52voff,
|
|
|
|
o52eoff, FALSE, &o52at_end,
|
|
|
|
dhcp_type_p, vendor_class_id_p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* protocol = tvb_get_guint8(tvb, voff+2);
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+2, 1, "Protocol: %s (%u)",
|
|
|
|
val_to_str(protocol, authen_protocol_vals, "Unknown"),
|
|
|
|
protocol); */
|
|
|
|
break;
|
2000-07-09 22:46:53 +00:00
|
|
|
case 53: /* DHCP Message Type */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, 3, "Option %d: %s = DHCP %s",
|
|
|
|
code, text, get_dhcp_type(tvb_get_guint8(tvb, voff+2)));
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
2000-03-20 21:39:00 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 55: /* Parameter Request List */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
vlen + 2, "Option %d: %s", code, text);
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
for (i = 0; i < vlen; i++) {
|
2001-01-03 22:49:06 +00:00
|
|
|
byte = tvb_get_guint8(tvb, voff+2+i);
|
2000-07-09 22:46:53 +00:00
|
|
|
if (byte < NUM_OPT_INFOS) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, voff+2+i, 1, "%d = %s",
|
2000-07-09 22:46:53 +00:00
|
|
|
byte, opt[byte].text);
|
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(vti, tvb, voff+2+i, 1,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Unknown Option Code: %d", byte);
|
|
|
|
}
|
2000-03-20 21:39:00 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
2000-03-20 21:39:00 +00:00
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
case 60: /* Vendor class identifier */
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
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;
|
2001-05-24 19:21:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
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) {
|
2001-01-03 22:49:06 +00:00
|
|
|
guint8 htype;
|
|
|
|
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
consumed, "Option %d: %s", code, text);
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
2001-01-03 22:49:06 +00:00
|
|
|
htype = tvb_get_guint8(tvb, voff+2);
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+2, 1,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Hardware type: %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
arphrdtype_to_str(htype,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Unknown (0x%02x)"));
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, voff+3, 6,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Client hardware address: %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
arphrdaddr_to_str(tvb_get_ptr(tvb, voff+3, 6),
|
|
|
|
6, htype));
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
|
|
|
/* otherwise, it's opaque data */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s (%d bytes)", code, text, vlen);
|
2000-03-20 21:39:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case 63: /* NetWare/IP options */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
consumed, "Option %d: %s", code, text);
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
optp = voff+2;
|
|
|
|
while (optp < voff+consumed)
|
2001-01-03 22:49:06 +00:00
|
|
|
optp = dissect_netware_ip_suboption(v_tree, tvb, optp);
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
case 78: /* SLP Directory Agent Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
|
|
|
|
byte = tvb_get_guint8(tvb, voff+2);
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
val_to_str(byte, slpda_vals,
|
|
|
|
"Unknown (0x%02x)"));
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
for (i = voff + 4; i < voff + consumed; i += 4) {
|
|
|
|
proto_tree_add_text(v_tree, tvb, i, 4, "SLPDA Address: %s",
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i, 4)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 79: /* SLP Service Scope Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
|
|
|
|
byte = tvb_get_guint8(tvb, voff+2);
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
val_to_str(byte, slp_scope_vals,
|
|
|
|
"Unknown (0x%02x)"));
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+4, consumed-4, "SLP Scope: %s",
|
|
|
|
tvb_get_ptr(tvb, voff+4, consumed-4));
|
|
|
|
break;
|
|
|
|
|
2001-02-13 00:01:08 +00:00
|
|
|
case 82: /* Relay Agent Information Option */
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s (%d bytes)",
|
|
|
|
code, text, vlen);
|
|
|
|
v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
|
|
|
optp = voff+2;
|
|
|
|
while (optp < voff+consumed) {
|
|
|
|
optp = bootp_dhcp_decode_agent_info(v_tree, tvb, optp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
case 85: /* Novell Servers */
|
|
|
|
/* Option 85 can be sent as a string */
|
|
|
|
/* Added by Greg Morris (gmorris@novell.com) */
|
|
|
|
if (novell_string && code==85) {
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = \"%.*s\"", code, text, vlen,
|
|
|
|
tvb_get_ptr(tvb, voff+2, consumed-2));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (vlen == 4) {
|
|
|
|
/* one IP address */
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+2, 4)));
|
|
|
|
} else {
|
|
|
|
/* > 1 IP addresses. Let's make a sub-tree */
|
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, 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, tvb, i, 4, "IP Address: %s",
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i, 4)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2001-10-31 08:43:09 +00:00
|
|
|
case 90: /* DHCP Authentication */
|
|
|
|
case 210: /* Was this used for authentication at one time? */
|
2001-05-01 03:54:04 +00:00
|
|
|
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);
|
2001-10-31 08:43:09 +00:00
|
|
|
|
|
|
|
protocol = tvb_get_guint8(tvb, voff+2);
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, voff+2, 1, "Protocol: %s (%u)",
|
2001-10-31 08:43:09 +00:00
|
|
|
val_to_str(protocol, authen_protocol_vals, "Unknown"),
|
|
|
|
protocol);
|
|
|
|
|
|
|
|
algorithm = tvb_get_guint8(tvb, voff+3);
|
|
|
|
switch (protocol) {
|
|
|
|
|
|
|
|
case AUTHEN_PROTO_DELAYED_AUTHEN:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+3, 1,
|
|
|
|
"Algorithm: %s (%u)",
|
|
|
|
val_to_str(algorithm, authen_da_algo_vals, "Unknown"),
|
|
|
|
algorithm);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+3, 1,
|
|
|
|
"Algorithm: %u", algorithm);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdm = tvb_get_guint8(tvb, voff+4);
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+4, 1,
|
|
|
|
"Replay Detection Method: %s (%u)",
|
|
|
|
val_to_str(rdm, authen_rdm_vals, "Unknown"),
|
|
|
|
rdm);
|
|
|
|
|
|
|
|
switch (rdm) {
|
|
|
|
|
|
|
|
case AUTHEN_RDM_MONOTONIC_COUNTER:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+5, 8,
|
2002-08-28 21:04:11 +00:00
|
|
|
"Replay Detection Value: %s",
|
2001-10-29 21:56:50 +00:00
|
|
|
u64toh(tvb_get_ptr(tvb, voff+5, 8)));
|
2001-10-31 08:43:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+5, 8,
|
2002-08-28 21:04:11 +00:00
|
|
|
"Replay Detection Value: %s",
|
2001-10-31 08:43:09 +00:00
|
|
|
tvb_bytes_to_str(tvb, voff+5, 8));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (protocol) {
|
|
|
|
|
|
|
|
case AUTHEN_PROTO_DELAYED_AUTHEN:
|
|
|
|
switch (algorithm) {
|
|
|
|
|
|
|
|
case AUTHEN_DELAYED_ALGO_HMAC_MD5:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+13, 4,
|
2002-08-28 21:04:11 +00:00
|
|
|
"Secret ID: 0x%08x",
|
2001-05-01 03:54:04 +00:00
|
|
|
tvb_get_ntohl(tvb, voff+13));
|
2001-10-31 08:43:09 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, voff+17, 16,
|
|
|
|
"HMAC MD5 Hash: %s",
|
|
|
|
tvb_bytes_to_str(tvb, voff+17, 16));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+13, vlen-11,
|
|
|
|
"Authentication Information: %s",
|
|
|
|
tvb_bytes_to_str(tvb, voff+17, vlen-11));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(v_tree, tvb, voff+13, vlen-11,
|
|
|
|
"Authentication Information: %s",
|
|
|
|
tvb_bytes_to_str(tvb, voff+17, vlen-11));
|
|
|
|
break;
|
2001-05-01 03:54:04 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
default: /* not special */
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Normal cases */
|
|
|
|
if (code < NUM_OPT_INFOS) {
|
|
|
|
text = opt[code].text;
|
|
|
|
ftype = opt[code].ftype;
|
|
|
|
|
|
|
|
switch (ftype) {
|
1998-11-20 04:34:37 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case special:
|
|
|
|
return consumed;
|
|
|
|
|
|
|
|
case ipv4:
|
|
|
|
if (vlen == 4) {
|
1998-09-16 02:39:15 +00:00
|
|
|
/* one IP address */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
ip_to_str(tvb_get_ptr(tvb, voff+2, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
1998-09-16 02:39:15 +00:00
|
|
|
/* > 1 IP addresses. Let's make a sub-tree */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
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) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, i, 4)));
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case string:
|
|
|
|
/* Fix for non null-terminated string supplied by
|
|
|
|
* John Lines <John.Lines@aeat.co.uk>
|
|
|
|
*/
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2001-05-24 19:21:15 +00:00
|
|
|
"Option %d: %s = \"%.*s\"", code, text, vlen,
|
2001-01-03 22:49:06 +00:00
|
|
|
tvb_get_ptr(tvb, voff+2, consumed-2));
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case opaque:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s (%d bytes)",
|
|
|
|
code, text, vlen);
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case val_u_short:
|
|
|
|
if (vlen == 2) {
|
2002-08-02 23:36:07 +00:00
|
|
|
/* one gushort */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
1998-09-16 02:39:15 +00:00
|
|
|
"Option %d: %s = %d", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
tvb_get_ntohs(tvb, voff+2));
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
2002-08-02 23:36:07 +00:00
|
|
|
/* > 1 gushort */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(bp_tree, tvb, voff,
|
2000-07-09 22:46:53 +00:00
|
|
|
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) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, i, 4, "Value: %d",
|
|
|
|
tvb_get_ntohs(tvb, i));
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case val_u_long:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %d", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
tvb_get_ntohl(tvb, voff+2));
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case val_u_byte:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
|
|
|
"Option %d: %s = %d", code, text,
|
|
|
|
tvb_get_guint8(tvb, voff+2));
|
2000-07-09 22:46:53 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case toggle:
|
2001-01-03 22:49:06 +00:00
|
|
|
i = tvb_get_guint8(tvb, voff+2);
|
2000-07-09 22:46:53 +00:00
|
|
|
if (i != 0 && i != 1) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = Invalid Value %d", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
i);
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
i == 0 ? "Disabled" : "Enabled");
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
1999-01-28 21:29:36 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case yes_no:
|
2001-01-03 22:49:06 +00:00
|
|
|
i = tvb_get_guint8(tvb, voff+2);
|
2000-07-09 22:46:53 +00:00
|
|
|
if (i != 0 && i != 1) {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = Invalid Value %d", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
i);
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s", code, text,
|
2001-01-03 22:49:06 +00:00
|
|
|
i == 0 ? "No" : "Yes");
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case time_in_secs:
|
2001-01-03 22:49:06 +00:00
|
|
|
time_secs = tvb_get_ntohl(tvb, voff+2);
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s = %s", code, text,
|
|
|
|
((time_secs == 0xffffffff) ?
|
|
|
|
"infinity" :
|
|
|
|
time_secs_to_str(time_secs)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Option %d: %s (%d bytes)", code, text, vlen);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, consumed,
|
1998-11-12 21:39:22 +00:00
|
|
|
"Unknown Option Code: %d (%d bytes)", code, vlen);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return consumed;
|
|
|
|
}
|
|
|
|
|
2001-02-13 00:01:08 +00:00
|
|
|
static int
|
|
|
|
bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb, int optp)
|
|
|
|
{
|
|
|
|
guint8 subopt;
|
|
|
|
guint8 subopt_len;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-02-13 00:01:08 +00:00
|
|
|
subopt = tvb_get_guint8(tvb, optp);
|
|
|
|
subopt_len = tvb_get_guint8(tvb, optp+1);
|
|
|
|
switch (subopt) {
|
|
|
|
case 1:
|
|
|
|
proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
|
|
|
|
"Agent Circuit ID (%d bytes)", subopt_len);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
|
|
|
|
"Agent Remote ID (%d bytes)", subopt_len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
|
|
|
|
"Unknown agent option: %d", subopt);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
optp += (subopt_len + 2);
|
|
|
|
return optp;
|
|
|
|
}
|
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
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;
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
struct o43pxeclient_opt_info {
|
2001-05-24 19:21:15 +00:00
|
|
|
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)
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
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);
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
if ( subopt == 71 ) { /* 71 {"PXE boot item", special} */
|
2001-05-24 19:21:15 +00:00
|
|
|
/* 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 */
|
2002-08-28 21:04:11 +00:00
|
|
|
case special:
|
2001-05-24 19:21:15 +00:00
|
|
|
/* 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;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
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;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
static int
|
2001-01-03 22:49:06 +00:00
|
|
|
dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp)
|
2000-07-09 22:46:53 +00:00
|
|
|
{
|
2001-01-03 22:49:06 +00:00
|
|
|
guint8 subopt;
|
|
|
|
guint8 subopt_len;
|
2000-07-09 22:46:53 +00:00
|
|
|
int slask;
|
|
|
|
proto_tree *o63_v_tree;
|
|
|
|
proto_item *vti;
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
struct o63_opt_info {
|
2000-07-09 22:46:53 +00:00
|
|
|
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},
|
2002-08-28 21:04:11 +00:00
|
|
|
/* 5 */ {"Broadcast for nearest Netware server","Do NOT Broadcast for nearest Netware server",yes_no},
|
2000-07-09 22:46:53 +00:00
|
|
|
/* 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}
|
|
|
|
};
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-01-03 22:49:06 +00:00
|
|
|
subopt = tvb_get_guint8(tvb, optp);
|
|
|
|
if (subopt > NUM_O63_SUBOPTS) {
|
|
|
|
proto_tree_add_text(v_tree, tvb,optp,1,"Unknown suboption %d", subopt);
|
2000-07-09 22:46:53 +00:00
|
|
|
optp++;
|
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
switch (o63_opt[subopt].ft) {
|
2000-07-09 22:46:53 +00:00
|
|
|
|
|
|
|
case string:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 2, "Suboption %d: %s", subopt, o63_opt[subopt].truet);
|
2000-07-09 22:46:53 +00:00
|
|
|
optp+=2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case yes_no:
|
2001-01-03 22:49:06 +00:00
|
|
|
if (tvb_get_guint8(tvb, optp+2)==1) {
|
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s", subopt, o63_opt[subopt].truet);
|
2000-07-09 22:46:53 +00:00
|
|
|
} else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s" , subopt, o63_opt[subopt].falset);
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
optp+=3;
|
|
|
|
break;
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
case special:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 6,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Suboption %d: %s = %s" ,
|
2001-01-03 22:49:06 +00:00
|
|
|
subopt, o63_opt[subopt].truet,
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
optp=optp+6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case val_u_short:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s = %u",
|
|
|
|
subopt, o63_opt[subopt].truet,
|
|
|
|
tvb_get_guint8(tvb, optp+2)); /* XXX - 1 byte? */
|
2000-07-09 22:46:53 +00:00
|
|
|
optp+=3;
|
|
|
|
break;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2000-07-09 22:46:53 +00:00
|
|
|
case ipv4:
|
2001-01-03 22:49:06 +00:00
|
|
|
subopt_len = tvb_get_guint8(tvb, optp+1);
|
|
|
|
if (subopt_len == 4) {
|
2000-07-09 22:46:53 +00:00
|
|
|
/* one IP address */
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb, optp, 6,
|
2000-07-09 22:46:53 +00:00
|
|
|
"Suboption %d : %s = %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
subopt, o63_opt[subopt].truet,
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
optp=optp+6;
|
|
|
|
} else {
|
|
|
|
/* > 1 IP addresses. Let's make a sub-tree */
|
2001-01-03 22:49:06 +00:00
|
|
|
vti = proto_tree_add_text(v_tree, tvb, optp,
|
|
|
|
subopt_len+2, "Suboption %d: %s",
|
|
|
|
subopt, o63_opt[subopt].truet);
|
2000-07-09 22:46:53 +00:00
|
|
|
o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
|
2001-01-03 22:49:06 +00:00
|
|
|
for (slask = optp + 2 ; slask < optp+subopt_len; slask += 4) {
|
|
|
|
proto_tree_add_text(o63_v_tree, tvb, slask, 4, "IP Address: %s",
|
|
|
|
ip_to_str(tvb_get_ptr(tvb, slask, 4)));
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
|
|
|
optp=slask;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(v_tree, tvb,optp,1,"Unknown suboption %d", subopt);
|
2000-07-09 22:46:53 +00:00
|
|
|
optp++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return optp;
|
|
|
|
}
|
|
|
|
|
2001-01-03 22:49:06 +00:00
|
|
|
#define BOOTREQUEST 1
|
|
|
|
#define BOOTREPLY 2
|
|
|
|
|
|
|
|
static const value_string op_vals[] = {
|
|
|
|
{ BOOTREQUEST, "Boot Request" },
|
|
|
|
{ BOOTREPLY, "Boot Reply" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2000-04-08 07:07:42 +00:00
|
|
|
static void
|
2001-01-03 22:49:06 +00:00
|
|
|
dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
1998-09-16 02:39:15 +00:00
|
|
|
{
|
2000-07-09 22:46:53 +00:00
|
|
|
proto_tree *bp_tree = NULL;
|
1999-03-23 03:14:46 +00:00
|
|
|
proto_item *ti;
|
2002-06-19 19:50:34 +00:00
|
|
|
proto_tree *flag_tree = NULL;
|
|
|
|
proto_item *fi;
|
2001-01-03 22:49:06 +00:00
|
|
|
guint8 op;
|
|
|
|
guint8 htype, hlen;
|
2001-03-13 21:34:28 +00:00
|
|
|
const guint8 *haddr;
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
int voff, eoff, tmpvoff; /* vendor offset, end offset */
|
1999-10-08 13:57:31 +00:00
|
|
|
guint32 ip_addr;
|
2001-12-27 23:53:10 +00:00
|
|
|
gboolean at_end;
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
const char *dhcp_type = NULL;
|
|
|
|
const guint8 *vendor_class_id = NULL;
|
2002-06-19 19:39:38 +00:00
|
|
|
guint16 flags;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOOTP");
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
2001-01-03 22:49:06 +00:00
|
|
|
/*
|
|
|
|
* In case we throw an exception fetching the opcode, etc.
|
|
|
|
*/
|
2001-12-10 00:26:21 +00:00
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2001-01-03 22:49:06 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2001-01-03 22:49:06 +00:00
|
|
|
op = tvb_get_guint8(tvb, 0);
|
|
|
|
htype = tvb_get_guint8(tvb, 1);
|
|
|
|
hlen = tvb_get_guint8(tvb, 2);
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
2001-01-03 22:49:06 +00:00
|
|
|
switch (op) {
|
|
|
|
|
|
|
|
case BOOTREQUEST:
|
2001-12-10 00:26:21 +00:00
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
|
|
|
|
hlen, htype));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BOOTREPLY:
|
2001-12-10 00:26:21 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "Boot Reply");
|
2001-01-03 22:49:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2001-12-10 00:26:21 +00:00
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BOOTP message type (%u)",
|
2001-01-03 22:49:06 +00:00
|
|
|
op);
|
|
|
|
break;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree) {
|
2002-01-24 09:20:54 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, FALSE);
|
1999-11-16 11:44:20 +00:00
|
|
|
bp_tree = proto_item_add_subtree(ti, ett_bootp);
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_uint(bp_tree, hf_bootp_type, tvb,
|
2001-01-03 22:49:06 +00:00
|
|
|
0, 1,
|
|
|
|
op);
|
|
|
|
proto_tree_add_uint_format(bp_tree, hf_bootp_hw_type, tvb,
|
|
|
|
1, 1,
|
|
|
|
htype,
|
1999-10-08 13:57:31 +00:00
|
|
|
"Hardware type: %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
arphrdtype_to_str(htype,
|
1999-10-08 13:57:31 +00:00
|
|
|
"Unknown (0x%02x)"));
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_uint(bp_tree, hf_bootp_hw_len, tvb,
|
|
|
|
2, 1, hlen);
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_hops, tvb,
|
|
|
|
3, 1, FALSE);
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_id, tvb,
|
|
|
|
4, 4, FALSE);
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_secs, tvb,
|
|
|
|
8, 2, FALSE);
|
2002-06-19 19:39:38 +00:00
|
|
|
flags = tvb_get_ntohs(tvb, 10);
|
2002-06-19 19:50:34 +00:00
|
|
|
fi = proto_tree_add_uint(bp_tree, hf_bootp_flags, tvb,
|
2002-06-19 19:39:38 +00:00
|
|
|
10, 2, flags);
|
2002-06-19 19:50:34 +00:00
|
|
|
proto_item_append_text(fi, " (%s)",
|
|
|
|
(flags & BOOTP_BC) ? "Broadcast" : "Unicast");
|
|
|
|
flag_tree = proto_item_add_subtree(fi, ett_bootp_flags);
|
2002-06-19 19:39:38 +00:00
|
|
|
proto_tree_add_boolean(flag_tree, hf_bootp_flags_broadcast, tvb,
|
|
|
|
10, 2, flags);
|
|
|
|
proto_tree_add_uint(flag_tree, hf_bootp_flags_reserved, tvb,
|
|
|
|
10, 2, flags);
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_ip_client, tvb,
|
2001-01-03 22:49:06 +00:00
|
|
|
12, 4, FALSE);
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_ip_your, tvb,
|
2001-01-03 22:49:06 +00:00
|
|
|
16, 4, FALSE);
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_ip_server, tvb,
|
|
|
|
20, 4, FALSE);
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_ip_relay, tvb,
|
|
|
|
24, 4, FALSE);
|
|
|
|
|
|
|
|
if (hlen > 0) {
|
|
|
|
haddr = tvb_get_ptr(tvb, 28, hlen);
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_bytes_format(bp_tree, hf_bootp_hw_addr, tvb,
|
2001-01-03 22:49:06 +00:00
|
|
|
28, hlen,
|
|
|
|
haddr,
|
2000-05-19 04:54:36 +00:00
|
|
|
"Client hardware address: %s",
|
2001-01-03 22:49:06 +00:00
|
|
|
arphrdaddr_to_str(haddr,
|
|
|
|
hlen,
|
|
|
|
htype));
|
2000-05-19 04:54:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb,
|
|
|
|
28, 0, "Client address not given");
|
2000-05-19 04:54:36 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
|
|
|
/* The server host name is optional */
|
2001-01-03 22:49:06 +00:00
|
|
|
if (tvb_get_guint8(tvb, 44) != '\0') {
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_server, tvb,
|
2002-09-28 04:12:38 +00:00
|
|
|
SERVER_NAME_OFFSET,
|
|
|
|
SERVER_NAME_LEN, FALSE);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_string_format(bp_tree, hf_bootp_server, tvb,
|
2002-09-28 04:12:38 +00:00
|
|
|
SERVER_NAME_OFFSET,
|
|
|
|
SERVER_NAME_LEN,
|
|
|
|
tvb_get_ptr(tvb, SERVER_NAME_OFFSET, 1),
|
1999-10-08 13:57:31 +00:00
|
|
|
"Server host name not given");
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Boot file */
|
2001-01-03 22:49:06 +00:00
|
|
|
if (tvb_get_guint8(tvb, 108) != '\0') {
|
|
|
|
proto_tree_add_item(bp_tree, hf_bootp_file, tvb,
|
2002-09-28 04:12:38 +00:00
|
|
|
FILE_NAME_OFFSET,
|
|
|
|
FILE_NAME_LEN, FALSE);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
else {
|
2001-01-03 22:49:06 +00:00
|
|
|
proto_tree_add_string_format(bp_tree, hf_bootp_file, tvb,
|
2002-09-28 04:12:38 +00:00
|
|
|
FILE_NAME_OFFSET,
|
|
|
|
FILE_NAME_LEN,
|
|
|
|
tvb_get_ptr(tvb, FILE_NAME_OFFSET, 1),
|
1999-10-08 13:57:31 +00:00
|
|
|
"Boot file name not given");
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2002-06-29 19:45:01 +00:00
|
|
|
}
|
|
|
|
|
2002-09-28 04:12:38 +00:00
|
|
|
voff = VENDOR_INFO_OFFSET;
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2002-06-29 19:45:01 +00:00
|
|
|
/* rfc2132 says it SHOULD exist, not that it MUST exist */
|
|
|
|
if (tvb_bytes_exist(tvb, voff, 4)) {
|
|
|
|
if (tvb_get_ntohl(tvb, voff) == 0x63825363) {
|
|
|
|
if (tree) {
|
|
|
|
tvb_memcpy(tvb, (void *)&ip_addr, voff, sizeof(ip_addr));
|
2002-06-19 19:39:38 +00:00
|
|
|
proto_tree_add_ipv4_format(bp_tree, hf_bootp_cookie, tvb,
|
2002-06-29 19:45:01 +00:00
|
|
|
voff, 4, ip_addr,
|
|
|
|
"Magic cookie: (OK)");
|
2002-06-19 19:39:38 +00:00
|
|
|
}
|
2002-06-29 19:45:01 +00:00
|
|
|
voff += 4;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (tree) {
|
2002-06-19 19:39:38 +00:00
|
|
|
proto_tree_add_text(bp_tree, tvb,
|
2002-06-29 19:45:01 +00:00
|
|
|
voff, 64, "Bootp vendor specific options");
|
2002-06-19 19:39:38 +00:00
|
|
|
}
|
2002-06-29 19:45:01 +00:00
|
|
|
voff += 64;
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2000-07-09 22:46:53 +00:00
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2002-06-29 19:45:01 +00:00
|
|
|
eoff = tvb_reported_length(tvb);
|
|
|
|
|
2001-05-24 19:21:15 +00:00
|
|
|
/*
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
* In the first pass, we just look for the DHCP message type
|
|
|
|
* and Vendor class identifier options.
|
2001-05-24 19:21:15 +00:00
|
|
|
*/
|
|
|
|
tmpvoff = voff;
|
2001-12-27 23:53:10 +00:00
|
|
|
at_end = FALSE;
|
|
|
|
while (tmpvoff < eoff && !at_end) {
|
|
|
|
tmpvoff += bootp_option(tvb, 0, tmpvoff, eoff, TRUE, &at_end,
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
&dhcp_type, &vendor_class_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there was a DHCP message type option, flag this packet
|
|
|
|
* as DHCP.
|
|
|
|
*/
|
|
|
|
if (dhcp_type != NULL) {
|
|
|
|
/*
|
|
|
|
* Yes, this is a DHCP packet, and "dhcp_type" is the
|
|
|
|
* packet type.
|
|
|
|
*/
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCP");
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "DHCP %-8s - Transaction ID 0x%x",
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
dhcp_type, tvb_get_ntohl(tvb, 4));
|
|
|
|
if (tree)
|
|
|
|
proto_tree_add_boolean_hidden(bp_tree, hf_bootp_dhcp,
|
|
|
|
tvb, 0, 0, 1);
|
2003-09-02 22:47:59 +00:00
|
|
|
tap_queue_packet( bootp_dhcp_tap, pinfo, (gpointer) dhcp_type);
|
2001-05-24 19:21:15 +00:00
|
|
|
}
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're not building the protocol tree, we don't need to
|
|
|
|
* make a second pass.
|
|
|
|
*/
|
|
|
|
if (tree == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, now build the protocol tree.
|
|
|
|
*/
|
2001-12-27 23:53:10 +00:00
|
|
|
at_end = FALSE;
|
|
|
|
while (voff < eoff && !at_end) {
|
|
|
|
voff += bootp_option(tvb, bp_tree, voff, eoff, FALSE, &at_end,
|
We always have to make one pass over the BOOTP options to see if the
packet is BOOTP or DHCP; have "bootp_option()" take a flag indicating
whether it's the first pass or the second and, in the first pass, don't
put anything in the protocol tree - just return, through pointers, the
DHCP packet type and the vendor class ID. On the second pass, don't
modify what those pointers point to, just use them as appropriate.
Make the vendor class ID pointer local to "dissect_bootp()", and have
"dissect_bootp()" do the first pass, set the Protocol and Info columns
appropriately if the packet is DHCP, and then, if a protocol tree is to
be built, make a second pass, handing "bootp_option()" the DHCP packet
type and vendor class ID we found.
If the vendor class ID is null, don't try to compare it with Intel's PXE
client indicator.
svn path=/trunk/; revision=3449
2001-05-25 06:56:53 +00:00
|
|
|
&dhcp_type, &vendor_class_id);
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
2001-12-27 23:53:10 +00:00
|
|
|
if (voff < eoff) {
|
|
|
|
/*
|
|
|
|
* Padding after the end option.
|
|
|
|
*/
|
|
|
|
proto_tree_add_text(bp_tree, tvb, voff, eoff - voff, "Padding");
|
|
|
|
}
|
1998-09-16 02:39:15 +00:00
|
|
|
}
|
|
|
|
|
1999-07-29 05:47:07 +00:00
|
|
|
void
|
|
|
|
proto_register_bootp(void)
|
|
|
|
{
|
1999-10-08 13:57:31 +00:00
|
|
|
static hf_register_info hf[] = {
|
2000-05-19 02:16:17 +00:00
|
|
|
{ &hf_bootp_dhcp,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Frame is DHCP", "bootp.dhcp", FT_BOOLEAN,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2002-08-28 21:04:11 +00:00
|
|
|
"", HFILL }},
|
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_type,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Message type", "bootp.type", FT_UINT8,
|
|
|
|
BASE_DEC, VALS(op_vals), 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_hw_type,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Hardware type", "bootp.hw.type", FT_UINT8,
|
|
|
|
BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_hw_len,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Hardware address length", "bootp.hw.len", FT_UINT8,
|
|
|
|
BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_hops,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Hops", "bootp.hops", FT_UINT8,
|
|
|
|
BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_id,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Transaction ID", "bootp.id", FT_UINT32,
|
|
|
|
BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_secs,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Seconds elapsed", "bootp.secs", FT_UINT16,
|
|
|
|
BASE_DEC, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2002-06-19 19:39:38 +00:00
|
|
|
{ &hf_bootp_flags,
|
|
|
|
{ "Bootp flags", "bootp.flags", FT_UINT16,
|
2001-01-03 22:49:06 +00:00
|
|
|
BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
2002-06-19 19:39:38 +00:00
|
|
|
{ &hf_bootp_flags_broadcast,
|
|
|
|
{ "Broadcast flag", "bootp.flags.bc", FT_BOOLEAN,
|
|
|
|
16, TFS(&flag_set_broadcast), BOOTP_BC,
|
|
|
|
"", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_bootp_flags_reserved,
|
|
|
|
{ "Reserved flags", "bootp.flags.reserved", FT_UINT16,
|
|
|
|
BASE_HEX, NULL, BOOTP_MBZ,
|
|
|
|
"", HFILL }},
|
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_ip_client,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Client IP address", "bootp.ip.client",FT_IPv4,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_ip_your,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Your (client) IP address", "bootp.ip.your", FT_IPv4,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_ip_server,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Next server IP address", "bootp.ip.server",FT_IPv4,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_ip_relay,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Relay agent IP address", "bootp.ip.relay", FT_IPv4,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_hw_addr,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Client hardware address", "bootp.hw.addr", FT_BYTES,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_server,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Server host name", "bootp.server", FT_STRING,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_file,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Boot file name", "bootp.file", FT_STRING,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
1999-10-12 06:21:15 +00:00
|
|
|
|
1999-10-08 13:57:31 +00:00
|
|
|
{ &hf_bootp_cookie,
|
2001-01-03 22:49:06 +00:00
|
|
|
{ "Magic cookie", "bootp.cookie", FT_IPv4,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2002-06-19 19:39:38 +00:00
|
|
|
|
|
|
|
{ &hf_bootp_vendor,
|
|
|
|
{ "Bootp Vendor Options", "bootp.vendor", FT_BYTES,
|
|
|
|
BASE_NONE, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
1999-10-08 13:57:31 +00:00
|
|
|
};
|
1999-11-16 11:44:20 +00:00
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_bootp,
|
2002-06-19 19:39:38 +00:00
|
|
|
&ett_bootp_flags,
|
1999-11-16 11:44:20 +00:00
|
|
|
&ett_bootp_option,
|
|
|
|
};
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2003-11-18 19:56:37 +00:00
|
|
|
module_t *bootp_module;
|
|
|
|
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP",
|
|
|
|
"bootp");
|
1999-10-08 13:57:31 +00:00
|
|
|
proto_register_field_array(proto_bootp, hf, array_length(hf));
|
1999-11-16 11:44:20 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2003-09-02 22:47:59 +00:00
|
|
|
bootp_dhcp_tap = register_tap("bootp");
|
2003-11-18 19:56:37 +00:00
|
|
|
|
|
|
|
bootp_module = prefs_register_protocol(proto_bootp, NULL);
|
|
|
|
|
|
|
|
prefs_register_bool_preference(bootp_module, "novellserverstring",
|
|
|
|
"Decode Option 85 as String",
|
|
|
|
"Novell Servers option 85 can be configured as a string instead of address",
|
|
|
|
&novell_string);
|
1999-07-29 05:47:07 +00:00
|
|
|
}
|
2000-04-08 07:07:42 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_bootp(void)
|
|
|
|
{
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t bootp_handle;
|
|
|
|
|
|
|
|
bootp_handle = create_dissector_handle(dissect_bootp, proto_bootp);
|
|
|
|
dissector_add("udp.port", UDP_PORT_BOOTPS, bootp_handle);
|
2002-05-28 20:08:09 +00:00
|
|
|
dissector_add("udp.port", UDP_PORT_BOOTPC, bootp_handle);
|
2000-04-08 07:07:42 +00:00
|
|
|
}
|