diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-02-05 00:33:45 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-02-06 21:35:58 +0000 |
commit | 63479adf638710b6fd272be5b4b0df23bda2daac (patch) | |
tree | 0d7fd0d6b0de10ffc163b270e387aa814305e364 /wiretap/pcap-common.c | |
parent | 1dc06a2681495b3bb2c75fc871f156f06b973260 (diff) |
Make some routines take a struct wtap_pkthdr * as an argument.
For some routines that take multiple arguments that come from a struct
wtap_pkthdr, pass a pointer to the struct wtap_pkthdr in question,
rather than the separate arguments. Do this even if we're passing
expressions that were earlier assigned to the struct wtap_pkthdr fields
in question. This simplifies the calling sequences and ensures that the
right values are picked up by the called routine; in at least one case
we were *not* passing the right values (the code to handle Simple Packet
Blocks in pcap-ng files).
Also, call the byte-swapping routines for pseudo-header fields only if
we need to do byte-swapping.
Change-Id: I3a8badfcfeb0237dfc1d1014185a67f18c0f2ebe
Reviewed-on: https://code.wireshark.org/review/119
Reviewed-by: Evan Huus <eapache@gmail.com>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'wiretap/pcap-common.c')
-rw-r--r-- | wiretap/pcap-common.c | 203 |
1 files changed, 105 insertions, 98 deletions
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c index 01fadec39b..f262e2be9d 100644 --- a/wiretap/pcap-common.c +++ b/wiretap/pcap-common.c @@ -1185,113 +1185,122 @@ struct usb_device_setup_hdr { sizeof(*fieldp)) static void -pcap_process_linux_usb_pseudoheader(guint packet_size, gboolean byte_swapped, - gboolean header_len_64_bytes, guint8 *pd) +pcap_byteswap_linux_usb_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd, + gboolean header_len_64_bytes) { - struct linux_usb_phdr *phdr; + guint packet_size; + struct linux_usb_phdr *usb_phdr; struct linux_usb_isodesc *pisodesc; gint32 iso_numdesc, i; - if (byte_swapped) { - /* - * Greasy hack, but we never directly direference any of - * the fields in *phdr, we just get offsets of and - * addresses of its members, so it's safe. - */ - phdr = (struct linux_usb_phdr *)(void *)pd; + /* + * Minimum of captured and actual length (just in case the + * actual length < the captured length, which Should Never + * Happen). + */ + packet_size = phdr->caplen; + if (packet_size > phdr->len) + packet_size = phdr->len; - if (packet_size < END_OFFSETOF(phdr, &phdr->id)) - return; - PBSWAP64((guint8 *)&phdr->id); - if (packet_size < END_OFFSETOF(phdr, &phdr->bus_id)) + /* + * Greasy hack, but we never directly dereference any of + * the fields in *usb_phdr, we just get offsets of and + * addresses of its members and byte-swap it with a + * byte-at-a-time macro, so it's alignment-safe. + */ + usb_phdr = (struct linux_usb_phdr *)(void *)pd; + + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->id)) + return; + PBSWAP64((guint8 *)&usb_phdr->id); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->bus_id)) + return; + PBSWAP16((guint8 *)&usb_phdr->bus_id); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->ts_sec)) + return; + PBSWAP64((guint8 *)&usb_phdr->ts_sec); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->ts_usec)) + return; + PBSWAP32((guint8 *)&usb_phdr->ts_usec); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->status)) + return; + PBSWAP32((guint8 *)&usb_phdr->status); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->urb_len)) + return; + PBSWAP32((guint8 *)&usb_phdr->urb_len); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->data_len)) + return; + PBSWAP32((guint8 *)&usb_phdr->data_len); + + if (usb_phdr->transfer_type == URB_ISOCHRONOUS) { + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->s.iso.error_count)) return; - PBSWAP16((guint8 *)&phdr->bus_id); - if (packet_size < END_OFFSETOF(phdr, &phdr->ts_sec)) + PBSWAP32((guint8 *)&usb_phdr->s.iso.error_count); + + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->s.iso.numdesc)) return; - PBSWAP64((guint8 *)&phdr->ts_sec); - if (packet_size < END_OFFSETOF(phdr, &phdr->ts_usec)) + PBSWAP32((guint8 *)&usb_phdr->s.iso.numdesc); + } + + if (header_len_64_bytes) { + /* + * This is either the "version 1" header, with + * 16 bytes of additional fields at the end, or + * a "version 0" header from a memory-mapped + * capture, with 16 bytes of zeroed-out padding + * at the end. Byte swap them as if this were + * a "version 1" header. + * + * Yes, the first argument to END_OFFSETOF() should + * be usb_phdr, not usb_phdr_ext; we want the offset of + * the additional fields from the beginning of + * the packet. + */ + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->interval)) return; - PBSWAP32((guint8 *)&phdr->ts_usec); - if (packet_size < END_OFFSETOF(phdr, &phdr->status)) + PBSWAP32((guint8 *)&usb_phdr->interval); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->start_frame)) return; - PBSWAP32((guint8 *)&phdr->status); - if (packet_size < END_OFFSETOF(phdr, &phdr->urb_len)) + PBSWAP32((guint8 *)&usb_phdr->start_frame); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->xfer_flags)) return; - PBSWAP32((guint8 *)&phdr->urb_len); - if (packet_size < END_OFFSETOF(phdr, &phdr->data_len)) + PBSWAP32((guint8 *)&usb_phdr->xfer_flags); + if (packet_size < END_OFFSETOF(usb_phdr, &usb_phdr->ndesc)) return; - PBSWAP32((guint8 *)&phdr->data_len); - - if (phdr->transfer_type == URB_ISOCHRONOUS) { - if (packet_size < END_OFFSETOF(phdr, &phdr->s.iso.error_count)) - return; - PBSWAP32((guint8 *)&phdr->s.iso.error_count); - - if (packet_size < END_OFFSETOF(phdr, &phdr->s.iso.numdesc)) - return; - PBSWAP32((guint8 *)&phdr->s.iso.numdesc); + PBSWAP32((guint8 *)&usb_phdr->ndesc); + } - } + if (usb_phdr->transfer_type == URB_ISOCHRONOUS) { + /* swap the values in struct linux_usb_isodesc */ + /* + * See previous "Greasy hack" comment. + */ if (header_len_64_bytes) { + pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 64); + } else { + pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 48); + } + iso_numdesc = usb_phdr->s.iso.numdesc; + for (i = 0; i < iso_numdesc; i++) { /* - * This is either the "version 1" header, with - * 16 bytes of additional fields at the end, or - * a "version 0" header from a memory-mapped - * capture, with 16 bytes of zeroed-out padding - * at the end. Byte swap them as if this were - * a "version 1" header. - * - * Yes, the first argument to END_OFFSETOF() should - * be phdr, not phdr_ext; we want the offset of - * the additional fields from the beginning of - * the packet. + * Always check if we have enough data from the + * beginning of the packet (usb_phdr). */ - if (packet_size < END_OFFSETOF(phdr, &phdr->interval)) + if (packet_size < END_OFFSETOF(usb_phdr, &pisodesc->iso_status)) return; - PBSWAP32((guint8 *)&phdr->interval); - if (packet_size < END_OFFSETOF(phdr, &phdr->start_frame)) + PBSWAP32((guint8 *)&pisodesc->iso_status); + if (packet_size < END_OFFSETOF(usb_phdr, &pisodesc->iso_off)) return; - PBSWAP32((guint8 *)&phdr->start_frame); - if (packet_size < END_OFFSETOF(phdr, &phdr->xfer_flags)) + PBSWAP32((guint8 *)&pisodesc->iso_off); + if (packet_size < END_OFFSETOF(usb_phdr, &pisodesc->iso_len)) return; - PBSWAP32((guint8 *)&phdr->xfer_flags); - if (packet_size < END_OFFSETOF(phdr, &phdr->ndesc)) + PBSWAP32((guint8 *)&pisodesc->iso_len); + if (packet_size < END_OFFSETOF(usb_phdr, &pisodesc->_pad)) return; - PBSWAP32((guint8 *)&phdr->ndesc); - } - - if (phdr->transfer_type == URB_ISOCHRONOUS) { - /* swap the values in struct linux_usb_isodesc */ + PBSWAP32((guint8 *)&pisodesc->_pad); - /* - * See previous "Greasy hack" comment. - */ - if (header_len_64_bytes) { - pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 64); - } else { - pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 48); - } - iso_numdesc = phdr->s.iso.numdesc; - for (i = 0; i < iso_numdesc; i++) { - /* always check if we have enough data from the - * beginnig of the packet (phdr) - */ - if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_status)) - return; - PBSWAP32((guint8 *)&pisodesc->iso_status); - if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_off)) - return; - PBSWAP32((guint8 *)&pisodesc->iso_off); - if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_len)) - return; - PBSWAP32((guint8 *)&pisodesc->iso_len); - if (packet_size < END_OFFSETOF(phdr, &pisodesc->_pad)) - return; - PBSWAP32((guint8 *)&pisodesc->_pad); - - pisodesc++; - } + pisodesc++; } } } @@ -1790,8 +1799,7 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, void pcap_read_post_process(int file_type, int wtap_encap, - union wtap_pseudo_header *pseudo_header, - guint8 *pd, guint packet_size, gboolean bytes_swapped, int fcs_len) + struct wtap_pkthdr *phdr, guint8 *pd, gboolean bytes_swapped, int fcs_len) { switch (wtap_encap) { @@ -1803,7 +1811,7 @@ pcap_read_post_process(int file_type, int wtap_encap, * Guess the traffic type based on the packet * contents. */ - atm_guess_traffic_type(pd, packet_size, pseudo_header); + atm_guess_traffic_type(phdr, pd); } else { /* * SunATM. @@ -1812,24 +1820,23 @@ pcap_read_post_process(int file_type, int wtap_encap, * type of LANE traffic it is based on the packet * contents. */ - if (pseudo_header->atm.type == TRAF_LANE) - atm_guess_lane_type(pd, packet_size, - pseudo_header); + if (phdr->pseudo_header.atm.type == TRAF_LANE) + atm_guess_lane_type(phdr, pd); } break; case WTAP_ENCAP_ETHERNET: - pseudo_header->eth.fcs_len = fcs_len; + phdr->pseudo_header.eth.fcs_len = fcs_len; break; case WTAP_ENCAP_USB_LINUX: - pcap_process_linux_usb_pseudoheader(packet_size, - bytes_swapped, FALSE, pd); + if (bytes_swapped) + pcap_byteswap_linux_usb_pseudoheader(phdr, pd, FALSE); break; case WTAP_ENCAP_USB_LINUX_MMAPPED: - pcap_process_linux_usb_pseudoheader(packet_size, - bytes_swapped, TRUE, pd); + if (bytes_swapped) + pcap_byteswap_linux_usb_pseudoheader(phdr, pd, TRUE); break; case WTAP_ENCAP_NETANALYZER: @@ -1838,7 +1845,7 @@ pcap_read_post_process(int file_type, int wtap_encap, * dissector calls the "Ethernet with FCS" * dissector, but we might as well set it. */ - pseudo_header->eth.fcs_len = 4; + phdr->pseudo_header.eth.fcs_len = 4; break; default: |