From d07cba10c1f05d221fdb2e7403d61269751548c9 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Tue, 3 Nov 1998 07:45:10 +0000 Subject: [PATCH] Add a routine to convert Ethernet packet types to strings. Use that routine in "ethertype()". Have "dissect_arp()" handle hardware addresses that aren't 6-byte Ethernet addresses and protocol addresses that aren't 4-byte IPv4 addresses - currently, it just prints the first 16 hex digits, but it could be made to handle other types specially just as it handles 6-byte Ethernet and 4-byte IPv4 addresses. Have it decode a more complete set of hardware address types. svn path=/trunk/; revision=78 --- ethertype.c | 61 +++++------ packet-arp.c | 283 +++++++++++++++++++++++++++++++++++++-------------- packet.h | 17 +--- 3 files changed, 234 insertions(+), 127 deletions(-) diff --git a/ethertype.c b/ethertype.c index c1cc01f76b..25a6f7f653 100644 --- a/ethertype.c +++ b/ethertype.c @@ -2,7 +2,7 @@ * Routines for calling the right protocol for the ethertype. * This is called by both packet-eth.c (Ethernet II) and packet-llc.c (SNAP) * - * $Id: ethertype.c,v 1.7 1998/10/16 06:46:16 guy Exp $ + * $Id: ethertype.c,v 1.8 1998/11/03 07:45:09 guy Exp $ * * Gilbert Ramirez * @@ -44,74 +44,59 @@ #include "packet.h" #include "etypes.h" +gchar * +ethertype_to_str(guint16 etype, const char *fmt) +{ + static const value_string etype_vals[] = { + {ETHERTYPE_IP, "IP" }, + {ETHERTYPE_IPv6, "IPv6" }, + {ETHERTYPE_ARP, "ARP" }, + {ETHERTYPE_REVARP, "RARP" }, + {ETHERTYPE_ATALK, "Appletalk" }, + {ETHERTYPE_AARP, "AARP" }, + {ETHERTYPE_IPX, "Netware IPX/SPX"}, + {ETHERTYPE_VINES, "Vines" }, + {0, NULL } }; + + return val_to_str(etype, etype_vals, fmt); +} + void ethertype(guint16 etype, int offset, const u_char *pd, frame_data *fd, GtkTree *tree, GtkWidget *fh_tree) { + if (tree) { + add_item_to_tree(fh_tree, offset - 2, 2, "Type: %s (0x%04x)", + ethertype_to_str(etype, "Unknown"), etype); + } switch (etype) { case ETHERTYPE_IP: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, "Type: IP (0x%04x)", - etype); - } dissect_ip(pd, offset, fd, tree); break; case ETHERTYPE_IPv6: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, "Type: IPv6 (0x%04x)", - etype); - } dissect_ipv6(pd, offset, fd, tree); break; case ETHERTYPE_ARP: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: ARP (0x%04x)", etype); - } dissect_arp(pd, offset, fd, tree); break; case ETHERTYPE_REVARP: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: RARP (0x%04x)", etype); - } dissect_arp(pd, offset, fd, tree); break; case ETHERTYPE_ATALK: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: AppleTalk (0x%04x)", etype); - } dissect_ddp(pd, offset, fd, tree); break; case ETHERTYPE_AARP: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: AARP (0x%04x)", etype); - } dissect_aarp(pd, offset, fd, tree); break; case ETHERTYPE_IPX: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: Netware IPX/SPX (0x%04x)", etype); - } dissect_ipx(pd, offset, fd, tree); break; case ETHERTYPE_VINES: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type Vines (0x%04x)", etype); - } dissect_vines(pd, offset, fd, tree); break; default: - if (tree) { - add_item_to_tree(fh_tree, offset - 2, 2, - "Type: Unknown (0x%04x)", etype); - dissect_data(pd, offset, fd, tree); - } + dissect_data(pd, offset, fd, tree); if (fd->win_info[COL_NUM]) { sprintf(fd->win_info[COL_PROTOCOL], "0x%04x", etype); } break; } diff --git a/packet-arp.c b/packet-arp.c index 5af5b554fb..02e35f51c9 100644 --- a/packet-arp.c +++ b/packet-arp.c @@ -1,7 +1,7 @@ /* packet-arp.c * Routines for ARP packet disassembly * - * $Id: packet-arp.c,v 1.7 1998/10/16 01:18:30 gerald Exp $ + * $Id: packet-arp.c,v 1.8 1998/11/03 07:45:10 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -44,92 +44,225 @@ #include "packet.h" #include "etypes.h" +/* Definitions taken from Linux "linux/if_arp.h" header file, and from + + http://www.isi.edu/in-notes/iana/assignments/arp-parameters + + */ + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet */ +#define ARPHRD_AX25 3 /* AX.25 Level 2 */ +#define ARPHRD_PRONET 4 /* PROnet token ring */ +#define ARPHRD_CHAOS 5 /* Chaosnet */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */ +#define ARPHRD_ARCNET 7 /* ARCnet */ +#define ARPHRD_HYPERCH 8 /* Hyperchannel */ +#define ARPHRD_LANSTAR 9 /* Lanstar */ +#define ARPHRD_AUTONET 10 /* Autonet Short Address */ +#define ARPHRD_LOCALTLK 11 /* Localtalk */ +#define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */ +#define ARPHRD_ULTRALNK 13 /* Ultra link */ +#define ARPHRD_SMDS 14 /* SMDS */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI */ +#define ARPHRD_ATM 16 /* ATM */ +#define ARPHRD_HDLC 17 /* HDLC */ +#define ARPHRD_FIBREC 18 /* Fibre Channel */ +#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */ +#define ARPHRD_SERIAL 20 /* Serial Line */ +#define ARPHRD_ATM2 21 /* ATM */ +#define ARPHRD_MS188220 22 /* MIL-STD-188-220 */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */ +#define ARPHRD_MAPOS 25 /* MAPOS */ +#define ARPHRD_TWINAX 26 /* Twinaxial */ +#define ARPHRD_EUI_64 27 /* EUI-64 */ + +/* Max string length for displaying unknown type of ARP address. */ +#define MAX_ADDR_STR_LEN 16 + +static gchar * +arpaddr_to_str(guint8 *ad, int ad_len) { + static gchar str[3][MAX_ADDR_STR_LEN+3+1]; + static gchar *cur; + gchar *p; + int len; + static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + p = cur; + len = MAX_ADDR_STR_LEN; + while (ad_len > 0 && len > 0) { + *p++ = hex[(*ad) >> 4]; + *p++ = hex[(*ad) & 0xF]; + len -= 2; + ad++; + ad_len--; + } + if (ad_len != 0) { + /* Note that we're not showing the full address. */ + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + *p = '\0'; + return cur; +} + +static gchar * +arphrdaddr_to_str(guint8 *ad, int ad_len, guint16 type) { + if (type == ARPHRD_ETHER && ad_len == 6) { + /* Ethernet address. */ + return ether_to_str(ad); + } + return arpaddr_to_str(ad, ad_len); +} + +static gchar * +arpproaddr_to_str(guint8 *ad, int ad_len, guint16 type) { + if (type == ETHERTYPE_IP && ad_len == 4) { + /* IP address. */ + return ip_to_str(ad); + } + return arpaddr_to_str(ad, ad_len); +} + +/* Offsets of fields within an ARP packet. */ +#define AR_HRD 0 +#define AR_PRO 2 +#define AR_HLN 4 +#define AR_PLN 5 +#define AR_OP 6 + void dissect_arp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { - e_ether_arp ea; + guint16 ar_hrd; + guint16 ar_pro; + guint8 ar_hln; + guint8 ar_pln; + guint16 ar_op; GtkWidget *arp_tree, *ti; gchar *op_str; - static value_string op_vals[] = { {ARPOP_REQUEST, "ARP request" }, - {ARPOP_REPLY, "ARP reply" }, - {ARPOP_RREQUEST, "RARP request"}, - {ARPOP_RREPLY, "RARP reply" }, - {0, NULL } }; + int sha_offset, spa_offset, tha_offset, tpa_offset; + gchar *sha_str, *spa_str, *tha_str, *tpa_str; + static const value_string op_vals[] = { + {ARPOP_REQUEST, "ARP request" }, + {ARPOP_REPLY, "ARP reply" }, + {ARPOP_RREQUEST, "RARP request"}, + {ARPOP_RREPLY, "RARP reply" }, + {0, NULL } }; + static const value_string hrd_vals[] = { + {ARPHRD_NETROM, "NET/ROM pseudo" }, + {ARPHRD_ETHER, "Ethernet" }, + {ARPHRD_EETHER, "Experimental Ethernet"}, + {ARPHRD_AX25, "AX.25" }, + {ARPHRD_PRONET, "ProNET" }, + {ARPHRD_CHAOS, "Chaos" }, + {ARPHRD_IEEE802, "IEEE 802" }, + {ARPHRD_ARCNET, "ARCNET" }, + {ARPHRD_HYPERCH, "Hyperchannel" }, + {ARPHRD_LANSTAR, "Lanstar" }, + {ARPHRD_AUTONET, "Autonet Short Address"}, + {ARPHRD_LOCALTLK, "Localtalk" }, + {ARPHRD_LOCALNET, "LocalNet" }, + {ARPHRD_ULTRALNK, "Ultra link" }, + {ARPHRD_SMDS, "SMDS" }, + {ARPHRD_DLCI, "Frame Relay DLCI" }, + {ARPHRD_ATM, "ATM" }, + {ARPHRD_HDLC, "HDLC" }, + {ARPHRD_FIBREC, "Fibre Channel" }, + {ARPHRD_ATM2225, "ATM (RFC 2225)" }, + {ARPHRD_SERIAL, "Serial Line" }, + {ARPHRD_ATM2, "ATM" }, + {ARPHRD_MS188220, "MIL-STD-188-220" }, + {ARPHRD_METRICOM, "Metricom STRIP" }, + {ARPHRD_IEEE1394, "IEEE 1394.1995" }, + {ARPHRD_MAPOS, "MAPOS" }, + {ARPHRD_TWINAX, "Twinaxial" }, + {ARPHRD_EUI_64, "EUI-64" }, + {0, NULL } }; /* To do: Check for {cap len,pkt len} < struct len */ - ea.ar_hrd = pntohs(&pd[offset]); - ea.ar_pro = pntohs(&pd[offset + 2]); - ea.ar_hln = (guint8) pd[offset + 4]; - ea.ar_pln = (guint8) pd[offset + 5]; - ea.ar_op = pntohs(&pd[offset + 6]); - memcpy(&ea.arp_sha, &pd[offset + 8], 6); - memcpy(&ea.arp_spa, &pd[offset + 14], 4); - memcpy(&ea.arp_tha, &pd[offset + 18], 6); - memcpy(&ea.arp_tpa, &pd[offset + 24], 4); - - if (fd->win_info[COL_NUM]) { strcpy(fd->win_info[COL_PROTOCOL], "ARP"); } - - if (tree) { - if ((op_str = match_strval(ea.ar_op, op_vals))) - ti = add_item_to_tree(GTK_WIDGET(tree), offset, 28, op_str); - else - ti = add_item_to_tree(GTK_WIDGET(tree), offset, 28, - "Unknown ARP (opcode 0x%04x)", ea.ar_op); - arp_tree = gtk_tree_new(); - add_subtree(ti, arp_tree, ETT_ARP); - add_item_to_tree(arp_tree, offset, 2, - "Hardware type: 0x%04x", ea.ar_hrd); - add_item_to_tree(arp_tree, offset + 2, 2, - "Protocol type: 0x%04x", ea.ar_pro); - add_item_to_tree(arp_tree, offset + 4, 1, - "Hardware size: 0x%02x", ea.ar_hln); - add_item_to_tree(arp_tree, offset + 5, 1, - "Protocol size: 0x%02x", ea.ar_pln); - add_item_to_tree(arp_tree, offset + 6, 2, - "Opcode: 0x%04x (%s)", ea.ar_op, op_str ? op_str : "Unknown"); - add_item_to_tree(arp_tree, offset + 8, 6, - "Sender ether: %s", ether_to_str((guint8 *) ea.arp_sha)); - add_item_to_tree(arp_tree, offset + 14, 4, - "Sender IP: %s", ip_to_str((guint8 *) ea.arp_spa)); - add_item_to_tree(arp_tree, offset + 18, 6, - "Target ether: %s", ether_to_str((guint8 *) ea.arp_tha)); - add_item_to_tree(arp_tree, offset + 24, 4, - "Target IP: %s", ip_to_str((guint8 *) ea.arp_tpa)); - } + ar_hrd = pntohs(&pd[offset + AR_HRD]); + ar_pro = pntohs(&pd[offset + AR_PRO]); + ar_hln = (guint8) pd[offset + AR_HLN]; + ar_pln = (guint8) pd[offset + AR_PLN]; + ar_op = pntohs(&pd[offset + AR_OP]); - if (ea.ar_pro != ETHERTYPE_IP && fd->win_info[COL_NUM]) { - sprintf(fd->win_info[COL_INFO], "h/w %d (%d) prot %d (%d) op 0x%04x", - ea.ar_hrd, ea.ar_hln, ea.ar_pro, ea.ar_pln, ea.ar_op); - return; - } - switch (ea.ar_op) { - case ARPOP_REQUEST: - if (fd->win_info[COL_NUM]) { + /* Extract the addresses. */ + sha_offset = offset + 8; + sha_str = arphrdaddr_to_str((guint8 *) &pd[sha_offset], ar_hln, ar_hrd); + spa_offset = sha_offset + ar_hln; + spa_str = arpproaddr_to_str((guint8 *) &pd[spa_offset], ar_pln, ar_pro); + tha_offset = spa_offset + ar_pln; + tha_str = arphrdaddr_to_str((guint8 *) &pd[tha_offset], ar_hln, ar_hrd); + tpa_offset = tha_offset + ar_hln; + tpa_str = arpproaddr_to_str((guint8 *) &pd[tpa_offset], ar_pln, ar_pro); + + if (fd->win_info[COL_NUM]) { + switch (ar_op) { + case ARPOP_REQUEST: + strcpy(fd->win_info[COL_PROTOCOL], "ARP"); sprintf(fd->win_info[COL_INFO], "Who has %s? Tell %s", - ip_to_str((guint8 *) ea.arp_tpa), ip_to_str((guint8 *) ea.arp_spa)); - } - break; - case ARPOP_REPLY: - if (fd->win_info[COL_NUM]) { + tpa_str, spa_str); + break; + case ARPOP_REPLY: + strcpy(fd->win_info[COL_PROTOCOL], "ARP"); sprintf(fd->win_info[COL_INFO], "%s is at %s", - ip_to_str((guint8 *) ea.arp_spa), - ether_to_str((guint8 *) ea.arp_sha)); - } - break; - case ARPOP_RREQUEST: - if (fd->win_info[COL_NUM]) { + spa_str, sha_str); + break; + case ARPOP_RREQUEST: strcpy(fd->win_info[COL_PROTOCOL], "RARP"); sprintf(fd->win_info[COL_INFO], "Who is %s? Tell %s", - ether_to_str((guint8 *) ea.arp_tha), - ether_to_str((guint8 *) ea.arp_sha)); - } - break; - case ARPOP_RREPLY: - if (fd->win_info[COL_NUM]) { + tha_str, sha_str); + break; + case ARPOP_RREPLY: strcpy(fd->win_info[COL_PROTOCOL], "RARP"); sprintf(fd->win_info[COL_INFO], "%s is at %s", - ether_to_str((guint8 *) ea.arp_sha), - ip_to_str((guint8 *) ea.arp_spa)); - } - break; + sha_str, spa_str); + break; + default: + strcpy(fd->win_info[COL_PROTOCOL], "ARP"); + sprintf(fd->win_info[COL_INFO], "Unknown ARP opcode 0x%04x", ar_op); + break; + } + } + + if (tree) { + if ((op_str = match_strval(ar_op, op_vals))) + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 8 + 2*ar_hln + 2*ar_pln, + op_str); + else + ti = add_item_to_tree(GTK_WIDGET(tree), offset, 8 + 2*ar_hln + 2*ar_pln, + "Unknown ARP (opcode 0x%04x)", ar_op); + arp_tree = gtk_tree_new(); + add_subtree(ti, arp_tree, ETT_ARP); + add_item_to_tree(arp_tree, offset + AR_HRD, 2, + "Hardware type: %s", val_to_str(ar_hrd, hrd_vals, "Unknown (0x%04x)")); + add_item_to_tree(arp_tree, offset + AR_PRO, 2, + "Protocol type: %s", ethertype_to_str(ar_pro, "Unknown (0x%04x)")); + add_item_to_tree(arp_tree, offset + AR_HLN, 1, + "Hardware size: %d", ar_hln); + add_item_to_tree(arp_tree, offset + AR_PLN, 1, + "Protocol size: %d", ar_pln); + add_item_to_tree(arp_tree, offset + AR_OP, 2, + "Opcode: 0x%04x (%s)", ar_op, op_str ? op_str : "Unknown"); + add_item_to_tree(arp_tree, sha_offset, ar_hln, + "Sender hardware address: %s", sha_str); + add_item_to_tree(arp_tree, spa_offset, ar_pln, + "Sender protocol address: %s", spa_str); + add_item_to_tree(arp_tree, tha_offset, ar_hln, + "Target hardware address: %s", tha_str); + add_item_to_tree(arp_tree, tpa_offset, ar_pln, + "Target protocol address: %s", tpa_str); } } diff --git a/packet.h b/packet.h index 770893246b..c2fab52aab 100644 --- a/packet.h +++ b/packet.h @@ -1,7 +1,7 @@ /* packet.h * Definitions for packet disassembly structures and routines * - * $Id: packet.h,v 1.22 1998/10/28 01:16:49 guy Exp $ + * $Id: packet.h,v 1.23 1998/11/03 07:45:10 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -92,18 +92,6 @@ typedef struct _value_string { /* ARP / RARP structs and definitions */ -typedef struct _e_ether_arp { - guint16 ar_hrd; - guint16 ar_pro; - guint8 ar_hln; - guint8 ar_pln; - guint16 ar_op; - guint8 arp_sha[6]; - guint8 arp_spa[4]; - guint8 arp_tha[6]; - guint8 arp_tpa[4]; -} e_ether_arp; - #ifndef ARPOP_REQUEST #define ARPOP_REQUEST 1 /* ARP request. */ #endif @@ -543,7 +531,8 @@ void dissect_udp(const u_char *, int, frame_data *, GtkTree *); void dissect_vines(const u_char *, int, frame_data *, GtkTree *); void dissect_vspp(const u_char *, int, frame_data *, GtkTree *); -/* This function is in ethertype.c */ +/* These functions are in ethertype.c */ +gchar *ethertype_to_str(guint16 etype, const char *fmt); void ethertype(guint16 etype, int offset, const u_char *pd, frame_data *fd, GtkTree *tree, GtkWidget *fh_tree);