Ethereal-dev: [Ethereal-dev] Patch to support vISDN
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Daniele Orlandi <daniele@xxxxxxxxxxx>
Date: Mon, 20 Feb 2006 13:58:08 +0100
Hello, The attached patch adds support for LAPD frames captured using vISDN thru libpcap. The support has already been included in libpcap. The patch adds a new wiretap encapsulation, the necessary glue to decode SLL-encapsulated frames, and some minor change in the LAPD dissector in order to support the remote-to-remote frames captured on the ISDN E-Channel. Please apply ethereal-encap-table.diff before, as it fixes a misalignment in the encapsulation names table. Let me know if the patch needs some adjustment. Thank you, Bye, -- Daniele Orlandi
diff -ur ethereal/wiretap/wtap.c ethereal-encap-table/wiretap/wtap.c --- ethereal/wiretap/wtap.c 2006-02-20 11:58:18.000000000 +0100 +++ ethereal-encap-table/wiretap/wtap.c 2006-02-20 12:40:33.000000000 +0100 @@ -286,6 +286,9 @@ /* WTAP_ENCAP_NETTL_RAW_ICMPV6 */ { "Raw ICMPv6 with nettl headers", "raw-icmpv6-nettl" }, + /* UNUSED */ + { "", "" }, + /* WTAP_ENCAP_GPRS_LLC */ { "GPRS LLC", "gprs-llc" }, @@ -328,6 +331,9 @@ /* WTAP_ENCAP_NETTL_X25 */ { "X25 with nettl headers", "x25-nettl" }, + /* WTAP_ENCAP_K12 */ + { "K12 protocol analyzer", "k12" }, + /* WTAP_ENCAP_JUNIPER_MLPPP */ { "Juniper MLPPP", "juniper-mlppp" },
diff -ur ethereal-encap-table/capture-wpcap.c ethereal-visdn/capture-wpcap.c --- ethereal-encap-table/capture-wpcap.c 2006-02-20 11:58:22.000000000 +0100 +++ ethereal-visdn/capture-wpcap.c 2006-02-20 12:03:29.000000000 +0100 @@ -359,6 +359,9 @@ #ifdef DLT_LINUX_IRDA DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), #endif +#ifdef DLT_LINUX_LAPD + DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"), +#endif #ifdef DLT_LANE8023 DLT_CHOICE(DLT_LANE8023, "Linux 802.3 LANE"), #endif diff -ur ethereal-encap-table/epan/column.c ethereal-visdn/epan/column.c --- ethereal-encap-table/epan/column.c 2006-02-20 11:57:58.000000000 +0100 +++ ethereal-visdn/epan/column.c 2006-02-20 12:07:17.000000000 +0100 @@ -50,7 +50,7 @@ "%rd", "%ud", "%hd", "%rhd", "%uhd", "%nd", "%rnd", "%und", "%S", "%rS", "%uS", "%D", "%rD", "%uD", "%p", "%i", "%L", "%B", "%XO", "%XR", "%I", "%c", "%Xs", - "%Xd", "%V", "%x", "%e", "%H", "%P", "%y", "%v" + "%Xd", "%V", "%x", "%e", "%H", "%P", "%y", "%v", "%E" }; if (fmt < 0 || fmt >= NUM_COL_FMTS) @@ -109,6 +109,7 @@ "HP-UX Device ID", "DCE/RPC call (cn_call_id / dg_seqnum)", "802.1Q VLAN id", + "TEI", }; const gchar * @@ -209,6 +210,9 @@ case COL_8021Q_VLAN_ID: fmt_list[COL_8021Q_VLAN_ID] = TRUE; break; + case COL_TEI: + fmt_list[COL_TEI] = TRUE; + break; default: break; } @@ -429,6 +433,9 @@ case COL_8021Q_VLAN_ID: return "0000"; break; + case COL_TEI: + return "127"; + break; default: /* COL_INFO */ return "Source port: kerberos-master Destination port: kerberos-master"; break; @@ -578,6 +585,9 @@ case 'v': return COL_8021Q_VLAN_ID; break; + case 'E': + return COL_TEI; + break; } cptr++; } diff -ur ethereal-encap-table/epan/column_info.h ethereal-visdn/epan/column_info.h --- ethereal-encap-table/epan/column_info.h 2006-02-20 11:57:59.000000000 +0100 +++ ethereal-visdn/epan/column_info.h 2006-02-20 12:08:13.000000000 +0100 @@ -99,6 +99,7 @@ COL_HPUX_DEVID, /* HP-UX Nettl Device ID */ COL_DCE_CALL, /* DCE/RPC call id OR datagram sequence number */ COL_8021Q_VLAN_ID, /* 802.1Q vlan ID */ + COL_TEI, /* q.921 TEI */ NUM_COL_FMTS /* Should always be last */ }; diff -ur ethereal-encap-table/epan/dissectors/packet-frame.c ethereal-visdn/epan/dissectors/packet-frame.c --- ethereal-encap-table/epan/dissectors/packet-frame.c 2006-02-20 11:57:56.000000000 +0100 +++ ethereal-visdn/epan/dissectors/packet-frame.c 2006-02-20 12:03:29.000000000 +0100 @@ -141,6 +141,13 @@ pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ? P2P_DIR_SENT : P2P_DIR_RECV; break; + + case WTAP_ENCAP_LINUX_LAPD: + pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 || + pinfo->pseudo_header->lapd.pkttype == 4) ? + P2P_DIR_SENT : P2P_DIR_RECV; + break; + case WTAP_ENCAP_MTP2_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ? P2P_DIR_SENT : P2P_DIR_RECV; Only in ethereal-visdn/epan/dissectors: packet-frame.c.orig diff -ur ethereal-encap-table/epan/dissectors/packet-lapd.c ethereal-visdn/epan/dissectors/packet-lapd.c --- ethereal-encap-table/epan/dissectors/packet-lapd.c 2006-02-20 11:57:56.000000000 +0100 +++ ethereal-visdn/epan/dissectors/packet-lapd.c 2006-02-20 12:03:29.000000000 +0100 @@ -80,6 +80,7 @@ #define LAPD_CR 0x0200 /* Command/Response bit */ #define LAPD_EA1 0x0100 /* First Address Extension bit */ #define LAPD_TEI 0x00fe /* Terminal Endpoint Identifier */ +#define LAPD_TEI_SHIFT 1 #define LAPD_EA2 0x0001 /* Second Address Extension bit */ static const value_string lapd_sapi_vals[] = { @@ -123,9 +124,11 @@ proto_item *lapd_ti, *addr_ti; guint16 control; int lapd_header_len; - guint16 address, cr, sapi; - gboolean is_response; + guint16 address, cr, sapi, tei; + gboolean is_response = 0; tvbuff_t *next_tvb; + char *srcname = "?"; + char *dstname = "?"; if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPD"); @@ -134,25 +137,61 @@ address = tvb_get_ntohs(tvb, 0); cr = address & LAPD_CR; + tei = (address & LAPD_TEI) >> LAPD_TEI_SHIFT; sapi = (address & LAPD_SAPI) >> LAPD_SAPI_SHIFT; lapd_header_len = 2; /* address */ - if (pinfo->p2p_dir == P2P_DIR_SENT) { - is_response = cr ? TRUE : FALSE; - if(check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_set_str(pinfo->cinfo, COL_RES_DL_DST, "Network"); - if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "User"); + if (check_col(pinfo->cinfo, COL_TEI)) + col_add_fstr(pinfo->cinfo, COL_TEI, "%u", tei); + + if (pinfo->fd->lnk_t == WTAP_ENCAP_LINUX_LAPD) { + /* frame is captured via libpcap */ + if (pinfo->pseudo_header->lapd.pkttype == 4 /*PACKET_OUTGOING*/) { + if (pinfo->pseudo_header->lapd.we_network) { + is_response = cr ? FALSE : TRUE; + srcname = "Local Network"; + dstname = "Remote User"; + } else { + srcname = "Local User"; + dstname = "Remote Network"; + } + } + else if (pinfo->pseudo_header->lapd.pkttype == 3 /*PACKET_OTHERHOST*/) { + // We must be a TE, sniffing what other TE transmit + + is_response = cr ? TRUE : FALSE; + srcname = "Remote User"; + dstname = "Remote Network"; + } + else { + // The frame is incoming + if (pinfo->pseudo_header->lapd.we_network) { + is_response = cr ? TRUE : FALSE; + srcname = "Remote User"; + dstname = "Local Network"; + } else { + is_response = cr ? FALSE : TRUE; + srcname = "Remote Network"; + dstname = "Local User"; + } + } } - else { - /* XXX - what if the direction is unknown? */ + else if (pinfo->p2p_dir == P2P_DIR_SENT) { is_response = cr ? FALSE : TRUE; - if(check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_set_str(pinfo->cinfo, COL_RES_DL_DST, "User"); - if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "Network"); + srcname = "Network"; + dstname = "User"; + } + else if (pinfo->p2p_dir == P2P_DIR_RECV) { + is_response = cr ? TRUE : FALSE; + srcname = "User"; + dstname = "Network"; } + if(check_col(pinfo->cinfo, COL_RES_DL_SRC)) + col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname); + if(check_col(pinfo->cinfo, COL_RES_DL_DST)) + col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname); + if (tree) { lapd_ti = proto_tree_add_item(tree, proto_lapd, tvb, 0, -1, FALSE); @@ -293,4 +332,9 @@ { data_handle = find_dissector("data"); tei_handle = find_dissector("tei"); + + dissector_handle_t lapd_handle; + + lapd_handle = create_dissector_handle(dissect_lapd, proto_lapd); + dissector_add("wtap_encap", WTAP_ENCAP_LINUX_LAPD, lapd_handle); } diff -ur ethereal-encap-table/wiretap/libpcap.c ethereal-visdn/wiretap/libpcap.c --- ethereal-encap-table/wiretap/libpcap.c 2006-02-20 11:58:18.000000000 +0100 +++ ethereal-visdn/wiretap/libpcap.c 2006-02-20 12:38:41.000000000 +0100 @@ -81,6 +81,21 @@ guint16 link_number; }; +#ifndef ETH_P_LAPD +#define ETH_P_LAPD 0x0030 +#endif + +/* + * The fake link-layer header of LAPD packets + */ +struct lapd_sll_hdr { + guint16 sll_pkttype; /* packet type */ + guint16 sll_hatype; + guint16 sll_halen; + guint8 sll_addr[8]; + guint16 sll_protocol; /* protocol, should be ETH_P_LAPD */ +}; + /* See source to the "libpcap" library for information on the "libpcap" file format. */ @@ -119,6 +134,10 @@ union wtap_pseudo_header *pseudo_header); static gboolean libpcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); +static gboolean libpcap_get_lapd_pseudoheader(const struct lapd_sll_hdr *lapd_phdr, + union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); +static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh, + union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err); static void libpcap_close(wtap *wth); @@ -379,6 +398,8 @@ { 172, WTAP_GCOM_TIE1 }, { 173, WTAP_GCOM_SERIAL }, + { 177, WTAP_ENCAP_LINUX_LAPD }, + /* Ethernet frames prepended with meta-information */ { 178, WTAP_ENCAP_JUNIPER_ETHER }, /* PPP frames prepended with meta-information */ @@ -1296,6 +1317,29 @@ packet_size -= sizeof (struct mtp2_hdr); wth->data_offset += sizeof (struct mtp2_hdr); break; + + case WTAP_ENCAP_LINUX_LAPD: + if (packet_size < sizeof (struct lapd_sll_hdr)) { + /* + * Uh-oh, the packet isn't big enough to even + * have a pseudo-header. + */ + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("libpcap: LAPD file has a %u-byte packet, too small to have even a LAPD pseudo-header\n", + packet_size); + return FALSE; + } + if (!libpcap_read_lapd_pseudoheader(wth->fh, &wth->pseudo_header, + err, err_info)) + return FALSE; /* Read error */ + + /* + * Don't count the pseudo-header as part of the packet. + */ + orig_size -= sizeof (struct lapd_sll_hdr); + packet_size -= sizeof (struct lapd_sll_hdr); + wth->data_offset += sizeof (struct lapd_sll_hdr); + break; } buffer_assure_space(wth->frame_buffer, packet_size); @@ -1406,6 +1450,14 @@ return FALSE; } break; + + case WTAP_ENCAP_LINUX_LAPD: + if (!libpcap_read_lapd_pseudoheader(wth->random_fh, pseudo_header, + err, err_info)) { + /* Read error */ + return FALSE; + } + break; } /* @@ -1760,6 +1812,43 @@ } static gboolean +libpcap_get_lapd_pseudoheader(const struct lapd_sll_hdr *lapd_phdr, + union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info) +{ + if (pntohs(&lapd_phdr->sll_protocol) != ETH_P_LAPD) { + *err = WTAP_ERR_BAD_RECORD; + if (err_info != NULL) + *err_info = g_strdup("libpcap: LAPD capture has a packet with an invalid sll_protocol field\n"); + return FALSE; + } + + pseudo_header->lapd.pkttype = pntohs(&lapd_phdr->sll_pkttype); + pseudo_header->lapd.we_network = !!lapd_phdr->sll_addr[0]; + + return TRUE; +} + +static gboolean +libpcap_read_lapd_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, + int *err, gchar **err_info) +{ + struct lapd_sll_hdr lapd_phdr; + int bytes_read; + + errno = WTAP_ERR_CANT_READ; + bytes_read = file_read(&lapd_phdr, 1, sizeof (struct lapd_sll_hdr), fh); + if (bytes_read != sizeof (struct lapd_sll_hdr)) { + *err = file_error(fh); + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + + return libpcap_get_lapd_pseudoheader(&lapd_phdr, pseudo_header, err, + err_info); +} + +static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err) { int bytes_read; @@ -1944,6 +2033,28 @@ whdr->caplen -= sizeof (struct mtp2_hdr); pd += sizeof (struct mtp2_hdr); } + else if (linktype == WTAP_ENCAP_LINUX_LAPD) { + if (whdr->caplen < sizeof (struct lapd_sll_hdr)) { + /* + * Uh-oh, the packet isn't big enough to even + * have a pseudo-header. + */ + g_message("libpcap: LAPD capture has a %u-byte packet, too small to have even an LAPD pseudo-header\n", + whdr->caplen); + *err = WTAP_ERR_BAD_RECORD; + return NULL; + } + if (!libpcap_get_lapd_pseudoheader((const struct lapd_sll_hdr *)pd, + pseudo_header, err, NULL)) + return NULL; + + /* + * Don't count the pseudo-header as part of the packet. + */ + whdr->len -= sizeof (struct lapd_sll_hdr); + whdr->caplen -= sizeof (struct lapd_sll_hdr); + pd += sizeof (struct lapd_sll_hdr); + } return pd; } #endif @@ -2056,6 +2167,7 @@ size_t nwritten; struct sunatm_hdr atm_hdr; struct irda_sll_hdr irda_hdr; + struct lapd_sll_hdr lapd_hdr; struct mtp2_hdr mtp2_hdr; int hdrsize; @@ -2063,6 +2175,8 @@ hdrsize = sizeof (struct sunatm_hdr); else if (wdh->encap == WTAP_ENCAP_IRDA) hdrsize = sizeof (struct irda_sll_hdr); + else if (wdh->encap == WTAP_ENCAP_LINUX_LAPD) + hdrsize = sizeof (struct lapd_sll_hdr); else hdrsize = 0; @@ -2224,6 +2338,24 @@ } wdh->bytes_dumped += sizeof(mtp2_hdr); } + else if (wdh->encap == WTAP_ENCAP_LINUX_LAPD) { + /* + * Write the LAPD header. + */ + memset(&lapd_hdr, 0, sizeof(lapd_hdr)); + lapd_hdr.sll_pkttype = phtons(&pseudo_header->lapd.pkttype); + lapd_hdr.sll_protocol = g_htons(ETH_P_LAPD); + lapd_hdr.sll_addr[0] = pseudo_header->lapd.we_network?0x01:0x00; + nwritten = fwrite(&lapd_hdr, 1, sizeof(lapd_hdr), wdh->fh); + if (nwritten != sizeof(lapd_hdr)) { + if (nwritten == 0 && ferror(wdh->fh)) + *err = errno; + else + *err = WTAP_ERR_SHORT_WRITE; + return FALSE; + } + wdh->bytes_dumped += sizeof(lapd_hdr); + } nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen); if (nwritten != phdr->caplen) { diff -ur ethereal-encap-table/wiretap/wtap.c ethereal-visdn/wiretap/wtap.c --- ethereal-encap-table/wiretap/wtap.c 2006-02-20 12:40:33.000000000 +0100 +++ ethereal-visdn/wiretap/wtap.c 2006-02-20 12:03:29.000000000 +0100 @@ -351,6 +351,9 @@ /* WTAP_ENCAP_JUNIPER_CHDLC */ { "Juniper C-HDLC", "juniper-chdlc" }, + + /* WTAP_ENCAP_LINUX_LAPD */ + { "LAPD", "lapd" }, }; /* Name that should be somewhat descriptive. */ diff -ur ethereal-encap-table/wiretap/wtap.h ethereal-visdn/wiretap/wtap.h --- ethereal-encap-table/wiretap/wtap.h 2006-02-20 11:58:18.000000000 +0100 +++ ethereal-visdn/wiretap/wtap.h 2006-02-20 12:04:31.000000000 +0100 @@ -178,9 +178,10 @@ #define WTAP_ENCAP_JUNIPER_FRELAY 86 #define WTAP_ENCAP_JUNIPER_CHDLC 87 #define WTAP_ENCAP_JUNIPER_GGSN 88 +#define WTAP_ENCAP_LINUX_LAPD 89 /* last WTAP_ENCAP_ value + 1 */ -#define WTAP_NUM_ENCAP_TYPES 89 +#define WTAP_NUM_ENCAP_TYPES 90 /* File types that can be read by wiretap. We support writing some many of these file types, too, so we @@ -496,6 +497,11 @@ #define K12_PORT_DS1 0x00100008 #define K12_PORT_ATMPVC 0x01020000 +struct lapd_phdr { + guint16 pkttype; /* packet type */ + guint8 we_network; +}; + union wtap_pseudo_header { struct eth_phdr eth; struct x25_phdr x25; @@ -509,6 +515,7 @@ struct nettl_phdr nettl; struct mtp2_phdr mtp2; struct k12_phdr k12; + struct lapd_phdr lapd; }; struct wtap_nstime {
- Prev by Date: [Ethereal-dev] Too many pcap_open_live calls during capture loop
- Next by Date: [Ethereal-dev] IPsec dissector to decrypt ESP Payload
- Previous by thread: Re: [Ethereal-dev] Too many pcap_open_live calls during capture loop
- Next by thread: [Ethereal-dev] IPsec dissector to decrypt ESP Payload
- Index(es):