diff options
author | Guy Harris <guy@alum.mit.edu> | 2003-12-18 19:07:14 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2003-12-18 19:07:14 +0000 |
commit | b8299f0b98b7ff518aceb62f998a174936cf4a50 (patch) | |
tree | 609bd927b0dcbece1639f340a78fe2d058e1fa1d /wiretap/libpcap.c | |
parent | 7993e1aa2e2c20e7b058dbb856195dd5a24ecf56 (diff) | |
download | wireshark-b8299f0b98b7ff518aceb62f998a174936cf4a50.tar.gz wireshark-b8299f0b98b7ff518aceb62f998a174936cf4a50.tar.bz2 wireshark-b8299f0b98b7ff518aceb62f998a174936cf4a50.zip |
From Jan Kiszka: IrDA support.
svn path=/trunk/; revision=9345
Diffstat (limited to 'wiretap/libpcap.c')
-rw-r--r-- | wiretap/libpcap.c | 136 |
1 files changed, 130 insertions, 6 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index 7f14a74859..cdace5f522 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -1,6 +1,6 @@ /* libpcap.c * - * $Id: libpcap.c,v 1.101 2003/12/03 22:40:39 guy Exp $ + * $Id: libpcap.c,v 1.102 2003/12/18 19:07:13 guy Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu> @@ -25,6 +25,7 @@ #endif #include <stdlib.h> +#include <string.h> #include <errno.h> #include "wtap-int.h" #include "file_wrappers.h" @@ -49,6 +50,16 @@ struct sunatm_hdr { guint16 vci; /* VCI */ }; +/* + * The fake link-layer header of IrDA packets as introduced by Jean Tourrilhes + * to libpcap. + */ +struct irda_sll_hdr { + guint16 sll_pkttype; /* packet type */ + guint8 unused[12]; /* usused SLL header fields */ + guint16 sll_protocol; /* protocol, should be 0x0017 */ +}; + /* See source to the "libpcap" library for information on the "libpcap" file format. */ @@ -75,6 +86,10 @@ static void libpcap_get_atm_pseudoheader(const struct sunatm_hdr *atm_phdr, union wtap_pseudo_header *pseudo_header); static gboolean libpcap_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err); +static gboolean libpcap_get_irda_pseudoheader(const struct irda_sll_hdr *irda_phdr, + union wtap_pseudo_header *pseudo_header, int *err); +static gboolean libpcap_read_irda_pseudoheader(FILE_T fh, + union wtap_pseudo_header *pseudo_header, int *err); static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err); static void libpcap_close(wtap *wth); @@ -261,6 +276,8 @@ static const struct { * 138 is reserved for Apple IP-over-IEEE 1394. */ + { 144, WTAP_ENCAP_IRDA }, /* IrDA capture */ + { 140, WTAP_ENCAP_MTP2 }, { 141, WTAP_ENCAP_MTP3 }, @@ -1019,6 +1036,29 @@ static gboolean libpcap_read(wtap *wth, int *err, long *data_offset) */ wth->pseudo_header.eth.fcs_len = -1; break; + + case WTAP_ENCAP_IRDA: + if (packet_size < sizeof (struct irda_sll_hdr)) { + /* + * Uh-oh, the packet isn't big enough to even + * have a pseudo-header. + */ + g_message("libpcap: IrDA file has a %u-byte packet, too small to have even an IrDA pseudo-header\n", + packet_size); + *err = WTAP_ERR_BAD_RECORD; + return FALSE; + } + if (!libpcap_read_irda_pseudoheader(wth->fh, &wth->pseudo_header, + err)) + return FALSE; /* Read error */ + + /* + * Don't count the pseudo-header as part of the packet. + */ + orig_size -= sizeof (struct irda_sll_hdr); + packet_size -= sizeof (struct irda_sll_hdr); + wth->data_offset += sizeof (struct irda_sll_hdr); + break; } buffer_assure_space(wth->frame_buffer, packet_size); @@ -1069,6 +1109,14 @@ libpcap_seek_read(wtap *wth, long seek_off, */ pseudo_header->eth.fcs_len = -1; break; + + case WTAP_ENCAP_IRDA: + if (!libpcap_read_irda_pseudoheader(wth->random_fh, pseudo_header, + err)) { + /* Read error */ + return FALSE; + } + break; } /* @@ -1315,6 +1363,40 @@ libpcap_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header } static gboolean +libpcap_get_irda_pseudoheader(const struct irda_sll_hdr *irda_phdr, + union wtap_pseudo_header *pseudo_header, int *err) +{ + if (pntohs(&irda_phdr->sll_protocol) != 0x0017) { + g_message("libpcap: IrDA capture has a packet with an invalid sll_protocol field\n"); + *err = WTAP_ERR_BAD_RECORD; + return FALSE; + } + + pseudo_header->irda.pkttype = pntohs(&irda_phdr->sll_pkttype); + + return TRUE; +} + +static gboolean +libpcap_read_irda_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, + int *err) +{ + struct irda_sll_hdr irda_phdr; + int bytes_read; + + errno = WTAP_ERR_CANT_READ; + bytes_read = file_read(&irda_phdr, 1, sizeof (struct irda_sll_hdr), fh); + if (bytes_read != sizeof (struct irda_sll_hdr)) { + *err = file_error(fh); + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + + return libpcap_get_irda_pseudoheader(&irda_phdr, pseudo_header, err); +} + +static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err) { int bytes_read; @@ -1430,6 +1512,28 @@ wtap_process_pcap_packet(gint linktype, const struct pcap_pkthdr *phdr, if (pseudo_header->atm.type == TRAF_LANE) atm_guess_lane_type(pd, whdr->caplen, pseudo_header); } + else if (linktype == WTAP_ENCAP_IRDA) { + if (whdr->caplen < sizeof (struct irda_sll_hdr)) { + /* + * Uh-oh, the packet isn't big enough to even + * have a pseudo-header. + */ + g_message("libpcap: IrDA capture has a %u-byte packet, too small to have even an IrDA pseudo-header\n", + whdr->caplen); + *err = WTAP_ERR_BAD_RECORD; + return NULL; + } + if (!libpcap_get_irda_pseudoheader((const struct irda_sll_hdr *)pd, + pseudo_header, err)) + return NULL; + + /* + * Don't count the pseudo-header as part of the packet. + */ + whdr->len -= sizeof (struct irda_sll_hdr); + whdr->caplen -= sizeof (struct irda_sll_hdr); + pd += sizeof (struct irda_sll_hdr); + } return pd; } #endif @@ -1534,17 +1638,20 @@ static gboolean libpcap_dump(wtap_dumper *wdh, size_t hdr_size; size_t nwritten; struct sunatm_hdr atm_hdr; - int atm_hdrsize; + struct irda_sll_hdr irda_hdr; + int hdrsize; if (wdh->encap == WTAP_ENCAP_ATM_PDUS) - atm_hdrsize = sizeof (struct sunatm_hdr); + hdrsize = sizeof (struct sunatm_hdr); + else if (wdh->encap == WTAP_ENCAP_IRDA) + hdrsize = sizeof (struct irda_sll_hdr); else - atm_hdrsize = 0; + hdrsize = 0; rec_hdr.hdr.ts_sec = phdr->ts.tv_sec; rec_hdr.hdr.ts_usec = phdr->ts.tv_usec; - rec_hdr.hdr.incl_len = phdr->caplen + atm_hdrsize; - rec_hdr.hdr.orig_len = phdr->len + atm_hdrsize; + rec_hdr.hdr.incl_len = phdr->caplen + hdrsize; + rec_hdr.hdr.orig_len = phdr->len + hdrsize; switch (wdh->file_type) { case WTAP_FILE_PCAP: @@ -1659,6 +1766,23 @@ static gboolean libpcap_dump(wtap_dumper *wdh, } wdh->bytes_dumped += sizeof atm_hdr; } + else if (wdh->encap == WTAP_ENCAP_IRDA) { + /* + * Write the IrDA header. + */ + memset(&irda_hdr, 0, sizeof(irda_hdr)); + irda_hdr.sll_pkttype = phtons(&pseudo_header->irda.pkttype); + irda_hdr.sll_protocol = htons(0x0017); + nwritten = fwrite(&irda_hdr, 1, sizeof(irda_hdr), wdh->fh); + if (nwritten != sizeof(irda_hdr)) { + if (nwritten == 0 && ferror(wdh->fh)) + *err = errno; + else + *err = WTAP_ERR_SHORT_WRITE; + return FALSE; + } + wdh->bytes_dumped += sizeof(irda_hdr); + } nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh); if (nwritten != phdr->caplen) { |