Ethereal-dev: [ethereal-dev] Patch to make capture counts work right on non-Ethernet
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: guy@xxxxxxxxxx (Guy Harris)
Date: Wed, 3 Feb 1999 19:52:02 -0800 (PST)
In the dialog box Ethereal puts up while doing a capture, the counts are wrong if you're capturing on an FDDI interface, and probably if you're capturing on any other non-Ethernet interface (or even if it's on Ethernet and there's 802.3 traffic). Here's a fix that adds some "capture_XXX" routines that dissect packets enough to figure out whether they're IPv4 packets or not and, if they are, to figure out the IP type, and that has the capture code call the top-level capture routines for the various link types. Those routines could conceivably do other things, e.g. dissecting the packets some more and updating a display of captured packets. This change *does* lengthen the code path when capturing; note that Microsoft's Network Monitor, by default, has all sorts of stuff it displays while capturing (% network utilization, frames/sec, bytes/sec,a nd broacasts/sec bars, counts of packets that went between particular MAC addresses, etc.), but also has a "dedicated capture" mode where it iconifies its main window and leaves up only a dialog box with a count of frames captured and buttons to stop the capture, etc.. The intent of that mode is to minimize the CPU used by Network Monitor; if the fixed Ethereal dialog box uses too much CPU, we may want to have it just display a total packet count. I'll check this into CVS in a few days if nobody comments on it.... Index: capture.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/capture.c,v retrieving revision 1.17 diff -c -r1.17 capture.c *** capture.c 1999/02/02 02:53:24 1.17 --- capture.c 1999/02/04 02:39:24 *************** *** 394,407 **** bpf_u_int32 netnum, netmask; time_t upd_time, cur_time; ! ld.go = TRUE; ! ld.count = 0; ! ld.max = cf.count; ! ld.tcp = 0; ! ld.udp = 0; ! ld.ospf = 0; ! ld.other = 0; ! ld.pdh = NULL; close_cap_file(&cf, info_bar, file_ctx); --- 394,408 ---- bpf_u_int32 netnum, netmask; time_t upd_time, cur_time; ! ld.go = TRUE; ! ld.counts.total = 0; ! ld.max = cf.count; ! ld.linktype = DLT_NULL; ! ld.counts.tcp = 0; ! ld.counts.udp = 0; ! ld.counts.ospf = 0; ! ld.counts.other = 0; ! ld.pdh = NULL; close_cap_file(&cf, info_bar, file_ctx); *************** *** 420,425 **** --- 421,427 ---- return; } } + ld.linktype = pcap_datalink(pch); if (cf.cfilter) { if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) { *************** *** 488,507 **** upd_time = cur_time; ! sprintf(label_str, "Count: %d", ld.count); gtk_label_set(GTK_LABEL(count_lb), label_str); ! sprintf(label_str, "TCP: %d (%.1f%%)", ld.tcp, pct(ld.tcp, ld.count)); gtk_label_set(GTK_LABEL(tcp_lb), label_str); ! sprintf(label_str, "UDP: %d (%.1f%%)", ld.udp, pct(ld.udp, ld.count)); gtk_label_set(GTK_LABEL(udp_lb), label_str); ! sprintf(label_str, "OSPF: %d (%.1f%%)", ld.ospf, pct(ld.ospf, ld.count)); gtk_label_set(GTK_LABEL(ospf_lb), label_str); ! sprintf(label_str, "Other: %d (%.1f%%)", ld.other, ! pct(ld.other, ld.count)); gtk_label_set(GTK_LABEL(other_lb), label_str); } } --- 490,512 ---- upd_time = cur_time; ! sprintf(label_str, "Count: %d", ld.counts.total); gtk_label_set(GTK_LABEL(count_lb), label_str); ! sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp, ! pct(ld.counts.tcp, ld.counts.total)); gtk_label_set(GTK_LABEL(tcp_lb), label_str); ! sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp, ! pct(ld.counts.udp, ld.counts.total)); gtk_label_set(GTK_LABEL(udp_lb), label_str); ! sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf, ! pct(ld.counts.ospf, ld.counts.total)); gtk_label_set(GTK_LABEL(ospf_lb), label_str); ! sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other, ! pct(ld.counts.other, ld.counts.total)); gtk_label_set(GTK_LABEL(other_lb), label_str); } } *************** *** 544,591 **** capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr, const u_char *pd) { - guint16 etype; - guint8 iptype = 0; - gint offset = 14; - loop_data *ld = (loop_data *) user; ! if ((++ld->count >= ld->max) && (ld->max > 0)) { ld->go = FALSE; } /* Currently, pcap_dumper_t is a FILE *. Let's hope that doesn't change. */ if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd); - - etype = etype = (pd[12] << 8) | pd[13]; - if (etype <= IEEE_802_3_MAX_LEN) { - etype = (pd[20] << 8) | pd[21]; - offset = 22; - } ! switch(etype){ ! case ETHERTYPE_IP: ! iptype = pd[offset + 9]; ! switch (iptype) { ! case IP_PROTO_TCP: ! ld->tcp++; ! break; ! case IP_PROTO_UDP: ! ld->udp++; ! break; ! case IP_PROTO_OSPF: ! ld->ospf++; ! break; ! default: ! ld->other++; ! } ! break; ! case ETHERTYPE_IPX: ! case ETHERTYPE_IPv6: ! case ETHERTYPE_ATALK: ! case ETHERTYPE_VINES: ! case ETHERTYPE_ARP: ! default: ! ld->other++; } } --- 549,581 ---- capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr, const u_char *pd) { loop_data *ld = (loop_data *) user; ! if ((++ld->counts.total >= ld->max) && (ld->max > 0)) { ld->go = FALSE; } /* Currently, pcap_dumper_t is a FILE *. Let's hope that doesn't change. */ if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd); ! switch (ld->linktype) { ! case DLT_EN10MB : ! capture_eth(pd, phdr->caplen, &ld->counts); ! break; ! case DLT_FDDI : ! capture_fddi(pd, phdr->caplen, &ld->counts); ! break; ! case DLT_IEEE802 : ! capture_tr(pd, phdr->caplen, &ld->counts); ! break; ! case DLT_NULL : ! capture_null(pd, phdr->caplen, &ld->counts); ! break; ! case DLT_PPP : ! capture_ppp(pd, phdr->caplen, &ld->counts); ! break; ! case DLT_RAW : ! capture_raw(pd, phdr->caplen, &ld->counts); ! break; } } Index: capture.h =================================================================== RCS file: /usr/local/cvsroot/ethereal/capture.h,v retrieving revision 1.3 diff -c -r1.3 capture.h *** capture.h 1998/09/29 21:39:29 1.3 --- capture.h 1999/02/04 02:39:24 *************** *** 28,39 **** typedef struct _loop_data { gint go; - gint count; gint max; ! gint tcp; ! gint udp; ! gint ospf; ! gint other; pcap_dumper_t *pdh; } loop_data; --- 28,36 ---- typedef struct _loop_data { gint go; gint max; ! gint linktype; ! packet_counts counts; pcap_dumper_t *pdh; } loop_data; Index: ethereal.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/ethereal.c,v retrieving revision 1.20 diff -c -r1.20 ethereal.c *** ethereal.c 1999/01/04 07:39:14 1.20 --- ethereal.c 1999/02/04 02:39:29 *************** *** 65,72 **** #endif #include "ethereal.h" - #include "capture.h" #include "packet.h" #include "file.h" #include "menu.h" #include "etypes.h" --- 65,72 ---- #endif #include "ethereal.h" #include "packet.h" + #include "capture.h" #include "file.h" #include "menu.h" #include "etypes.h" Index: ethertype.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/ethertype.c,v retrieving revision 1.11 diff -c -r1.11 ethertype.c *** ethertype.c 1998/12/19 00:12:19 1.11 --- ethertype.c 1999/02/04 02:39:29 *************** *** 62,67 **** --- 62,81 ---- } void + capture_ethertype(guint16 etype, int offset, + const u_char *pd, guint32 cap_len, packet_counts *ld) + { + switch (etype) { + case ETHERTYPE_IP: + capture_ip(pd, offset, cap_len, ld); + break; + default: + ld->other++; + break; + } + } + + void ethertype(guint16 etype, int offset, const u_char *pd, frame_data *fd, GtkTree *tree, GtkWidget *fh_tree) *************** *** 107,110 **** if (check_col(fd, COL_PROTOCOL)) { col_add_fstr(fd, COL_PROTOCOL, "0x%04x", etype); } break; } ! } --- 121,124 ---- if (check_col(fd, COL_PROTOCOL)) { col_add_fstr(fd, COL_PROTOCOL, "0x%04x", etype); } break; } ! } Index: menu.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/menu.c,v retrieving revision 1.12 diff -c -r1.12 menu.c *** menu.c 1998/12/27 20:46:45 1.12 --- menu.c 1999/02/04 02:39:30 *************** *** 36,43 **** #include "ethereal.h" #include "menu.h" - #include "capture.h" #include "packet.h" #include "prefs.h" #include "print.h" #include "follow.h" --- 36,43 ---- #include "ethereal.h" #include "menu.h" #include "packet.h" + #include "capture.h" #include "prefs.h" #include "print.h" #include "follow.h" Index: packet-eth.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-eth.c,v retrieving revision 1.7 diff -c -r1.7 packet-eth.c *** packet-eth.c 1998/11/17 04:28:52 1.7 --- packet-eth.c 1999/02/04 02:39:30 *************** *** 56,61 **** --- 56,101 ---- #define ETHERNET_SNAP 3 void + capture_eth(const u_char *pd, guint32 cap_len, packet_counts *ld) { + guint16 etype; + int offset = 14; + int ethhdr_type; /* the type of ethernet frame */ + + etype = (pd[12] << 8) | pd[13]; + + /* either ethernet802.3 or ethernet802.2 */ + if (etype <= IEEE_802_3_MAX_LEN) { + + /* Is there an 802.2 layer? I can tell by looking at the first 2 + bytes after the 802.3 header. If they are 0xffff, then what + follows the 802.3 header is an IPX payload, meaning no 802.2. + (IPX/SPX is they only thing that can be contained inside a + straight 802.3 packet). A non-0xffff value means that there's an + 802.2 layer inside the 802.3 layer */ + if (pd[14] == 0xff && pd[15] == 0xff) { + ethhdr_type = ETHERNET_802_3; + } + else { + ethhdr_type = ETHERNET_802_2; + } + } else { + ethhdr_type = ETHERNET_II; + } + + switch (ethhdr_type) { + case ETHERNET_802_3: + ld->other++; /* IPX */ + break; + case ETHERNET_802_2: + capture_llc(pd, offset, cap_len, ld); + break; + case ETHERNET_II: + capture_ethertype(etype, offset, pd, cap_len, ld); + break; + } + } + + void dissect_eth(const u_char *pd, frame_data *fd, GtkTree *tree) { guint16 etype, length; int offset = 14; *************** *** 126,142 **** } } - /* either ethernet802.3 or ethernet802.2 */ switch (ethhdr_type) { ! case ETHERNET_802_3: ! dissect_ipx(pd, offset, fd, tree); ! return; ! case ETHERNET_802_2: ! dissect_llc(pd, offset, fd, tree); ! return; } - - /* Ethernet_II */ - ethertype(etype, offset, pd, fd, tree, fh_tree); } --- 166,181 ---- } } switch (ethhdr_type) { ! case ETHERNET_802_3: ! dissect_ipx(pd, offset, fd, tree); ! break; ! case ETHERNET_802_2: ! dissect_llc(pd, offset, fd, tree); ! break; ! case ETHERNET_II: ! ethertype(etype, offset, pd, fd, tree, fh_tree); ! break; } } Index: packet-fddi.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-fddi.c,v retrieving revision 1.8 diff -c -r1.8 packet-fddi.c *** packet-fddi.c 1998/11/17 04:28:53 1.8 --- packet-fddi.c 1999/02/04 02:39:30 *************** *** 133,138 **** --- 133,181 ---- } } + void + capture_fddi(const u_char *pd, guint32 cap_len, packet_counts *ld) { + int offset = 0, fc; + + if (cap_len < FDDI_HEADER_SIZE) { + ld->other++; + return; + } + offset = FDDI_HEADER_SIZE; + + fc = (int) pd[FDDI_P_FC]; + + switch (fc) { + + /* From now, only 802.2 SNAP (Async. LCC frame) is supported */ + + case FDDI_FC_LLC_ASYNC + 0 : + case FDDI_FC_LLC_ASYNC + 1 : + case FDDI_FC_LLC_ASYNC + 2 : + case FDDI_FC_LLC_ASYNC + 3 : + case FDDI_FC_LLC_ASYNC + 4 : + case FDDI_FC_LLC_ASYNC + 5 : + case FDDI_FC_LLC_ASYNC + 6 : + case FDDI_FC_LLC_ASYNC + 7 : + case FDDI_FC_LLC_ASYNC + 8 : + case FDDI_FC_LLC_ASYNC + 9 : + case FDDI_FC_LLC_ASYNC + 10 : + case FDDI_FC_LLC_ASYNC + 11 : + case FDDI_FC_LLC_ASYNC + 12 : + case FDDI_FC_LLC_ASYNC + 13 : + case FDDI_FC_LLC_ASYNC + 14 : + case FDDI_FC_LLC_ASYNC + 15 : + capture_llc(pd, offset, cap_len, ld); + return; + + default : + ld->other++; + return; + + } /* fc */ + + } /* capture_fddi */ + void dissect_fddi(const u_char *pd, frame_data *fd, GtkTree *tree) { int offset = 0, fc; *************** *** 211,214 **** } /* fc */ } /* dissect_fddi */ - --- 254,256 ---- Index: packet-ip.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-ip.c,v retrieving revision 1.13 diff -c -r1.13 packet-ip.c *** packet-ip.c 1998/12/29 04:05:35 1.13 --- packet-ip.c 1999/02/04 02:39:31 *************** *** 47,52 **** --- 47,69 ---- extern packet_info pi; + void + capture_ip(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld) { + switch (pd[offset + 9]) { + case IP_PROTO_TCP: + ld->tcp++; + break; + case IP_PROTO_UDP: + ld->udp++; + break; + case IP_PROTO_OSPF: + ld->ospf++; + break; + default: + ld->other++; + } + } + static void dissect_ipopt_security(GtkWidget *opt_tree, const char *name, const u_char *opd, int offset, guint optlen) Index: packet-llc.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-llc.c,v retrieving revision 1.10 diff -c -r1.10 packet-llc.c *** packet-llc.c 1998/11/17 04:28:56 1.10 --- packet-llc.c 1999/02/04 02:39:31 *************** *** 43,78 **** struct sap_info { guint8 sap; ! void (*func) (const u_char *, int, frame_data *, GtkTree *); char *text; }; static struct sap_info saps[] = { ! { 0x00, NULL, "NULL LSAP" }, ! { 0x02, NULL, "LLC Sub-Layer Management Individual" }, ! { 0x03, NULL, "LLC Sub-Layer Management Group" }, ! { 0x04, NULL, "SNA Path Control Individual" }, ! { 0x05, NULL, "SNA Path Control Group" }, ! { 0x06, dissect_ip, "TCP/IP" }, ! { 0x08, NULL, "SNA" }, ! { 0x0C, NULL, "SNA" }, ! { 0x42, NULL, "Spanning Tree BPDU" }, ! { 0x7F, NULL, "ISO 802.2" }, ! { 0x80, NULL, "XNS" }, ! { 0xAA, NULL, "SNAP" }, ! /*{ 0xBA, dissect_vines, "Banyan Vines" }, ! { 0xBC, dissect_vines, "Banyan Vines" },*/ ! { 0xBA, NULL, "Banyan Vines" }, ! { 0xBC, NULL, "Banyan Vines" }, ! { 0xE0, dissect_ipx, "NetWare" }, ! { 0xF0, NULL, "NetBIOS" }, ! { 0xF4, NULL, "IBM Net Management Individual" }, ! { 0xF5, NULL, "IBM Net Management Group" }, ! { 0xF8, NULL, "Remote Program Load" }, ! { 0xFC, NULL, "Remote Program Load" }, ! { 0xFE, dissect_osi, "ISO Network Layer" }, ! { 0xFF, NULL, "Global LSAP" }, ! { 0x00, NULL, NULL } }; --- 43,79 ---- struct sap_info { guint8 sap; ! void (*capture_func) (const u_char *, int, guint32, packet_counts *); ! void (*dissect_func) (const u_char *, int, frame_data *, GtkTree *); char *text; }; static struct sap_info saps[] = { ! { 0x00, NULL, NULL, "NULL LSAP" }, ! { 0x02, NULL, NULL, "LLC Sub-Layer Management Individual" }, ! { 0x03, NULL, NULL, "LLC Sub-Layer Management Group" }, ! { 0x04, NULL, NULL, "SNA Path Control Individual" }, ! { 0x05, NULL, NULL, "SNA Path Control Group" }, ! { 0x06, capture_ip, dissect_ip, "TCP/IP" }, ! { 0x08, NULL, NULL, "SNA" }, ! { 0x0C, NULL, NULL, "SNA" }, ! { 0x42, NULL, NULL, "Spanning Tree BPDU" }, ! { 0x7F, NULL, NULL, "ISO 802.2" }, ! { 0x80, NULL, NULL, "XNS" }, ! { 0xAA, NULL, NULL, "SNAP" }, ! /*{ 0xBA, NULL, dissect_vines, "Banyan Vines" }, ! { 0xBC, NULL, dissect_vines, "Banyan Vines" },*/ ! { 0xBA, NULL, NULL, "Banyan Vines" }, ! { 0xBC, NULL, NULL, "Banyan Vines" }, ! { 0xE0, NULL, dissect_ipx, "NetWare" }, ! { 0xF0, NULL, NULL, "NetBIOS" }, ! { 0xF4, NULL, NULL, "IBM Net Management Individual" }, ! { 0xF5, NULL, NULL, "IBM Net Management Group" }, ! { 0xF8, NULL, NULL, "Remote Program Load" }, ! { 0xFC, NULL, NULL, "Remote Program Load" }, ! { 0xFE, NULL, dissect_osi, "ISO Network Layer" }, ! { 0xFF, NULL, NULL, "Global LSAP" }, ! { 0x00, NULL, NULL, NULL } }; *************** *** 90,107 **** } static void* ! sap_func(u_char sap) { int i=0; while (saps[i].text != NULL) { if (saps[i].sap == sap) { ! return saps[i].func; } i++; } return dissect_data; } static char* llc_org(const u_char *ptr) { --- 91,121 ---- } static void* ! sap_capture_func(u_char sap) { int i=0; while (saps[i].text != NULL) { if (saps[i].sap == sap) { ! return saps[i].capture_func; } i++; } return dissect_data; } + static void* + sap_dissect_func(u_char sap) { + int i=0; + + while (saps[i].text != NULL) { + if (saps[i].sap == sap) { + return saps[i].dissect_func; + } + i++; + } + return dissect_data; + } + static char* llc_org(const u_char *ptr) { *************** *** 118,123 **** --- 132,166 ---- } void + capture_llc(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld) { + + guint16 etype; + int is_snap; + void (*capture) (const u_char *, int, guint32, packet_counts *); + + is_snap = (pd[offset] == 0xAA) && (pd[offset+1] == 0xAA); + if (is_snap) { + etype = (pd[offset+6] << 8) | pd[offset+7]; + offset += 8; + capture_ethertype(etype, offset, pd, cap_len, ld); + } + else { + capture = sap_capture_func(pd[offset]); + + /* non-SNAP */ + offset += 3; + + if (capture) { + capture(pd, offset, cap_len, ld); + } + else { + ld->other++; + } + + } + } + + void dissect_llc(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) { GtkWidget *llc_tree = NULL, *ti; *************** *** 168,174 **** col_add_fstr(fd, COL_INFO, "802.2 LLC (%s)", sap_text(pd[offset])); } ! dissect = sap_func(pd[offset]); /* non-SNAP */ offset += 3; --- 211,217 ---- col_add_fstr(fd, COL_INFO, "802.2 LLC (%s)", sap_text(pd[offset])); } ! dissect = sap_dissect_func(pd[offset]); /* non-SNAP */ offset += 3; Index: packet-null.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-null.c,v retrieving revision 1.5 diff -c -r1.5 packet-null.c *** packet-null.c 1998/11/17 04:29:00 1.5 --- packet-null.c 1999/02/04 02:39:31 *************** *** 40,45 **** --- 40,76 ---- #include "packet.h" void + capture_null( const u_char *pd, guint32 cap_len, packet_counts *ld ) { + e_nullhdr nh; + + memcpy((char *)&nh.null_family, (char *)&pd[2], sizeof(nh.null_family)); + + /* + From what I've read in various sources, this is supposed to be an + address family, e.g. AF_INET. However, a FreeBSD ISDN PPP dump that + Andreas Klemm sent to ethereal-dev has a packet type of DLT_NULL, and + the family bits look like PPP's protocol field. A dump of the loopback + interface on my Linux box also has a link type of DLT_NULL (as it should + be), but the family bits look like ethernet's protocol type. To + further confuse matters, nobody seems to be paying attention to byte + order. + - gcc + */ + + switch (nh.null_family) { + case 0x0008: + case 0x0800: + case 0x0021: + case 0x2100: + capture_ip(pd, 4, cap_len, ld); + break; + default: + ld->other++; + break; + } + } + + void dissect_null( const u_char *pd, frame_data *fd, GtkTree *tree ) { e_nullhdr nh; GtkWidget *ti, *fh_tree; Index: packet-ppp.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-ppp.c,v retrieving revision 1.8 diff -c -r1.8 packet-ppp.c *** packet-ppp.c 1998/11/17 04:29:03 1.8 --- packet-ppp.c 1999/02/04 02:39:32 *************** *** 62,67 **** --- 62,79 ---- #define PPP_CBCP 0xc029 /* Callback Control Protocol */ void + capture_ppp( const u_char *pd, guint32 cap_len, packet_counts *ld ) { + switch (pntohs(&pd[2])) { + case PPP_IP: + capture_ip(pd, 4, cap_len, ld); + break; + default: + ld->other++; + break; + } + } + + void dissect_ppp( const u_char *pd, frame_data *fd, GtkTree *tree ) { e_ppphdr ph; GtkWidget *ti, *fh_tree; Index: packet-raw.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-raw.c,v retrieving revision 1.7 diff -c -r1.7 packet-raw.c *** packet-raw.c 1998/11/17 04:29:04 1.7 --- packet-raw.c 1999/02/04 02:39:32 *************** *** 39,44 **** --- 39,61 ---- #include "packet.h" void + capture_raw( const u_char *pd, guint32 cap_len, packet_counts *ld ) { + + /* So far, the only time we get raw connection types are with Linux and + * Irix PPP connections. We can't tell what type of data is coming down + * the line, so our safest bet is IP. - GCC + */ + + /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header + * sometimes. This check should be removed when 2.2 is out. + */ + if (pd[0] == 0xff && pd[1] == 0x03) + capture_ip(pd, 4, cap_len, ld); + else + capture_ip(pd, 0, cap_len, ld); + } + + void dissect_raw( const u_char *pd, frame_data *fd, GtkTree *tree ) { GtkWidget *ti, *fh_tree; *************** *** 76,79 **** else dissect_ip(pd, 0, fd, tree); } ! --- 93,96 ---- else dissect_ip(pd, 0, fd, tree); } ! Index: packet-tr.c =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet-tr.c,v retrieving revision 1.9 diff -c -r1.9 packet-tr.c *** packet-tr.c 1999/01/08 04:42:43 1.9 --- packet-tr.c 1999/02/04 02:39:33 *************** *** 75,80 **** --- 75,174 ---- void + capture_tr(const u_char *pd, guint32 cap_len, packet_counts *ld) { + + int offset = 14; + + int source_routed = 0; + int frame_type; + guint8 trn_rif_bytes; + guint8 actual_rif_bytes; + + /* The trn_hdr struct, as separate variables */ + guint8 trn_fc; /* field control field */ + guint8 trn_shost[6]; /* source host */ + + /* get the data */ + memcpy(&trn_fc, &pd[1], sizeof(guint8)); + memcpy(trn_shost, &pd[8], 6 * sizeof(guint8)); + + frame_type = (trn_fc & 192) >> 6; + + /* if the high bit on the first byte of src hwaddr is 1, then + this packet is source-routed */ + source_routed = trn_shost[0] & 128; + + trn_rif_bytes = pd[14] & 31; + + /* sometimes we have a RCF but no RIF... half source-routed? */ + /* I'll check for 2 bytes of RIF and the 0x70 byte */ + if (!source_routed) { + if (trn_rif_bytes == 2) { + source_routed = 1; + } + /* the Linux 2.0 TR code strips source-route bits in + * order to test for SR. This can be removed from most + * packets with oltr, but not all. So, I try to figure out + * which packets should have been SR here. I'll check to + * see if there's a SNAP or IPX field right after + * my RIF fields. + */ + else if ( ( + pd[0x0e + trn_rif_bytes] == 0xaa && + pd[0x0f + trn_rif_bytes] == 0xaa && + pd[0x10 + trn_rif_bytes] == 0x03) || + ( + pd[0x0e + trn_rif_bytes] == 0xe0 && + pd[0x0f + trn_rif_bytes] == 0xe0) ) { + + source_routed = 1; + } + /* else { + printf("0e+%d = %02X 0f+%d = %02X\n", trn_rif_bytes, pd[0x0e + trn_rif_bytes], + trn_rif_bytes, pd[0x0f + trn_rif_bytes]); + } */ + + } + + if (source_routed) { + actual_rif_bytes = trn_rif_bytes; + } + else { + trn_rif_bytes = 0; + actual_rif_bytes = 0; + } + + /* this is a silly hack for Linux 2.0.x. Read the comment below, + in front of the other #ifdef linux. If we're sniffing our own NIC, + we get a full RIF, sometimes with garbage */ + if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) || + (!source_routed && frame_type == 1)) { + /* look for SNAP or IPX only */ + if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) || + (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) { + actual_rif_bytes = 18; + } + } + offset += actual_rif_bytes; + + /* The package is either MAC or LLC */ + switch (frame_type) { + /* MAC */ + case 0: + ld->other++; + break; + case 1: + capture_llc(pd, offset, cap_len, ld); + break; + default: + /* non-MAC, non-LLC, i.e., "Reserved" */ + ld->other++; + break; + } + } + + + void dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) { GtkWidget *fh_tree, *ti; Index: packet.h =================================================================== RCS file: /usr/local/cvsroot/ethereal/packet.h,v retrieving revision 1.34 diff -c -r1.34 packet.h *** packet.h 1999/01/28 21:29:36 1.34 --- packet.h 1999/02/04 02:39:34 *************** *** 68,73 **** --- 68,81 ---- #define COL_MAX_LEN 256 + typedef struct _packet_counts { + gint tcp; + gint udp; + gint ospf; + gint other; + gint total; + } packet_counts; + typedef struct _frame_data { guint32 pkt_len; /* Packet length */ guint32 cap_len; /* Amount actually captured */ *************** *** 529,534 **** --- 537,563 ---- /* * Routines in packet-*.c + * Routines should take three args: packet data *, cap_len, packet_counts * + * They should never modify the packet data. + */ + void capture_eth(const u_char *, guint32, packet_counts *); + void capture_fddi(const u_char *, guint32, packet_counts *); + void capture_null(const u_char *, guint32, packet_counts *); + void capture_ppp(const u_char *, guint32, packet_counts *); + void capture_raw(const u_char *, guint32, packet_counts *); + void capture_tr(const u_char *, guint32, packet_counts *); + + /* + * Routines in packet-*.c + * Routines should take four args: packet data *, offset, cap_len, + * packet_counts * + * They should never modify the packet data. + */ + void capture_llc(const u_char *, int, guint32, packet_counts *); + void capture_ip(const u_char *, int, guint32, packet_counts *); + + /* + * Routines in packet-*.c * Routines should take three args: packet data *, frame_data *, tree * * They should never modify the packet data. */ *************** *** 582,587 **** --- 611,618 ---- /* These functions are in ethertype.c */ gchar *ethertype_to_str(guint16 etype, const char *fmt); + void capture_ethertype(guint16 etype, int offset, + const u_char *pd, guint32 cap_len, packet_counts *ld); void ethertype(guint16 etype, int offset, const u_char *pd, frame_data *fd, GtkTree *tree, GtkWidget *fh_tree);
- Prev by Date: [ethereal-dev] patch for IP bitfields
- Next by Date: [ethereal-dev] Table-driven packet dissection?
- Previous by thread: [ethereal-dev] patch for IP bitfields
- Next by thread: [ethereal-dev] Table-driven packet dissection?
- Index(es):