Author: hselasky
Date: Fri Mar 16 17:30:22 2012
New Revision: 233039
URL: http://svn.freebsd.org/changeset/base/233039

Log:
  Create new file header format to simplify the endian and cross platform 
issues.
  This patch does not break binary compatibility with previous versions.
  
  MFC after:    1 week

Modified:
  head/usr.sbin/usbdump/usbdump.c

Modified: head/usr.sbin/usbdump/usbdump.c
==============================================================================
--- head/usr.sbin/usbdump/usbdump.c     Fri Mar 16 16:41:28 2012        
(r233038)
+++ head/usr.sbin/usbdump/usbdump.c     Fri Mar 16 17:30:22 2012        
(r233039)
@@ -95,26 +95,20 @@ struct usbcap_filehdr {
 #define        HEADER_ALIGN(x,a) (((x) + (a) - 1) & ~((a) - 1))
 
 struct header_32 {
+       /* capture timestamp */
        uint32_t ts_sec;
        uint32_t ts_usec;
+       /* data length and alignment information */
        uint32_t caplen;
        uint32_t datalen;
-       uint16_t hdrlen;
-       uint16_t dummy;
-} __packed;
-
-struct header_64 {
-       uint64_t ts_sec;
-       uint64_t ts_usec;
-       uint32_t caplen;
-       uint32_t datalen;
-       uint16_t hdrlen;
-       uint16_t dummy;
+       uint8_t hdrlen;
+       uint8_t align;
 } __packed;
 
 static int doexit = 0;
 static int pkt_captured = 0;
 static int verbose = 0;
+static int uf_minor;
 static const char *i_arg = "usbus0";
 static const char *r_arg = NULL;
 static const char *w_arg = NULL;
@@ -534,86 +528,71 @@ print_apacket(const struct header_32 *hd
 }
 
 static void
-print_packets(uint8_t *data, const int datalen)
+fix_packets(uint8_t *data, const int datalen)
 {
        struct header_32 temp;
        uint8_t *ptr;
        uint8_t *next;
+       uint32_t hdrlen;
+       uint32_t caplen;
 
        for (ptr = data; ptr < (data + datalen); ptr = next) {
 
-               /* automatically figure out endian and size of header */
-
-               if (r_arg != NULL) {
+               const struct bpf_hdr *hdr;
 
-                       const struct header_32 *hdr32;
-                       const struct header_64 *hdr64;
+               hdr = (const struct bpf_hdr *)ptr;
 
-                       hdr32 = (const struct header_32 *)ptr;
-                       hdr64 = (const struct header_64 *)ptr;
-
-                       temp.hdrlen = le16toh(hdr32->hdrlen);
-                       temp.dummy = le16toh(hdr32->dummy);
-
-                       if ((temp.hdrlen != 18 && temp.hdrlen != 20) || 
(temp.dummy != 0)) {
-                               temp.hdrlen = be16toh(hdr32->hdrlen);
-                               temp.dummy = be16toh(hdr32->dummy);
-
-                               if ((temp.hdrlen != 18 && temp.hdrlen != 20) || 
(temp.dummy != 0)) {
-                                       temp.hdrlen = le16toh(hdr64->hdrlen);
-                                       temp.dummy = le16toh(hdr64->dummy);
-
-                                       if ((temp.hdrlen != 28 && temp.hdrlen 
!= 32) || (temp.dummy != 0)) {
-                                               temp.hdrlen = 
be16toh(hdr64->hdrlen);
-                                               temp.dummy = 
be16toh(hdr64->dummy);
-
-                                               if ((temp.hdrlen != 28 && 
temp.hdrlen != 32) || (temp.dummy != 0)) {
-                                                       err(EXIT_FAILURE, 
"Invalid header detected");
-                                                       next = NULL;
-                                               } else {
-                                                       temp.ts_sec = 
be64toh(hdr64->ts_sec);
-                                                       temp.ts_usec = 
be64toh(hdr64->ts_usec);
-                                                       temp.caplen = 
be32toh(hdr64->caplen);
-                                                       temp.datalen = 
be32toh(hdr64->datalen);
-                                                       next = ptr + 
HEADER_ALIGN(temp.hdrlen + temp.caplen, 8);
-                                               }
-                                       } else {
-                                               temp.ts_sec = 
le64toh(hdr64->ts_sec);
-                                               temp.ts_usec = 
le64toh(hdr64->ts_usec);
-                                               temp.caplen = 
le32toh(hdr64->caplen);
-                                               temp.datalen = 
le32toh(hdr64->datalen);
-                                               next = ptr + 
HEADER_ALIGN(temp.hdrlen + temp.caplen, 8);
-                                       }
-                               } else {
-                                       temp.ts_sec = be32toh(hdr32->ts_sec);
-                                       temp.ts_usec = be32toh(hdr32->ts_usec);
-                                       temp.caplen = be32toh(hdr32->caplen);
-                                       temp.datalen = be32toh(hdr32->datalen);
-                                       next = ptr + HEADER_ALIGN(temp.hdrlen + 
temp.caplen, 4);
-                               }
-                       } else {
-                               temp.ts_sec = le32toh(hdr32->ts_sec);
-                               temp.ts_usec = le32toh(hdr32->ts_usec);
-                               temp.caplen = le32toh(hdr32->caplen);
-                               temp.datalen = le32toh(hdr32->datalen);
-                               next = ptr + HEADER_ALIGN(temp.hdrlen + 
temp.caplen, 4);
-                       }
+               temp.ts_sec = htole32(hdr->bh_tstamp.tv_sec);
+               temp.ts_usec = htole32(hdr->bh_tstamp.tv_usec);
+               temp.caplen = htole32(hdr->bh_caplen);
+               temp.datalen = htole32(hdr->bh_datalen);
+               temp.hdrlen = hdr->bh_hdrlen;
+               temp.align = BPF_WORDALIGN(1);
+
+               hdrlen = hdr->bh_hdrlen;
+               caplen = hdr->bh_caplen;
+
+               if ((hdrlen >= sizeof(temp)) && (hdrlen <= 255) &&
+                   ((ptr + hdrlen) <= (data + datalen))) {
+                       memcpy(ptr, &temp, sizeof(temp));
+                       memset(ptr + sizeof(temp), 0, hdrlen - sizeof(temp));
                } else {
-                       const struct bpf_hdr *hdr;
-
-                       hdr = (const struct bpf_hdr *)ptr;
-                       temp.ts_sec = hdr->bh_tstamp.tv_sec;
-                       temp.ts_usec = hdr->bh_tstamp.tv_usec;
-                       temp.caplen = hdr->bh_caplen;
-                       temp.datalen = hdr->bh_datalen;
-                       temp.hdrlen = hdr->bh_hdrlen;
-                       next = ptr + BPF_WORDALIGN(temp.hdrlen + temp.caplen);
+                       err(EXIT_FAILURE, "Invalid header length %d", hdrlen);
                }
 
+               next = ptr + BPF_WORDALIGN(hdrlen + caplen);
+
+               if (next <= ptr)
+                       err(EXIT_FAILURE, "Invalid length");
+       }
+}
+
+static void
+print_packets(uint8_t *data, const int datalen)
+{
+       struct header_32 temp;
+       uint8_t *ptr;
+       uint8_t *next;
+
+       for (ptr = data; ptr < (data + datalen); ptr = next) {
+
+               const struct header_32 *hdr32;
+
+               hdr32 = (const struct header_32 *)ptr;
+
+               temp.ts_sec = le32toh(hdr32->ts_sec);
+               temp.ts_usec = le32toh(hdr32->ts_usec);
+               temp.caplen = le32toh(hdr32->caplen);
+               temp.datalen = le32toh(hdr32->datalen);
+               temp.hdrlen = hdr32->hdrlen;
+               temp.align = hdr32->align;
+
+               next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, 
temp.align);
+
                if (next <= ptr)
-                       err(EXIT_FAILURE, "Invalid header length");
+                       err(EXIT_FAILURE, "Invalid length");
 
-               if (w_arg == NULL) {
+               if (w_arg == NULL || r_arg != NULL) {
                        print_apacket(&temp, ptr +
                            temp.hdrlen, temp.caplen);
                }
@@ -656,6 +635,9 @@ read_file(struct usbcap *p)
                        err(EXIT_FAILURE, "Could not read complete "
                            "USB data payload");
                }
+               if (uf_minor == 2)
+                       fix_packets(data, datalen);
+
                print_packets(data, datalen);
                free(data);
        }
@@ -680,6 +662,9 @@ do_loop(struct usbcap *p)
                }
                if (cc == 0)
                        continue;
+
+               fix_packets(p->buffer, cc);
+
                if (w_arg != NULL)
                        write_packets(p, p->buffer, cc);
                print_packets(p->buffer, cc);
@@ -711,7 +696,10 @@ init_rfile(struct usbcap *p)
                errx(EX_SOFTWARE, "Invalid major version(%d) "
                    "field in USB capture file header.", (int)uf.major);
        }
-       if (uf.minor != 2) {
+
+       uf_minor = uf.minor;
+
+       if (uf.minor != 3 && uf.minor != 2) {
                errx(EX_SOFTWARE, "Invalid minor version(%d) "
                    "field in USB capture file header.", (int)uf.minor);
        }
@@ -726,12 +714,12 @@ init_wfile(struct usbcap *p)
        p->wfd = open(w_arg, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
        if (p->wfd < 0) {
                err(EXIT_FAILURE, "Could not open "
-                   "'%s' for write", r_arg);
+                   "'%s' for write", w_arg);
        }
        memset(&uf, 0, sizeof(uf));
        uf.magic = htole32(USBCAP_FILEHDR_MAGIC);
        uf.major = 0;
-       uf.minor = 2;
+       uf.minor = 3;
        ret = write(p->wfd, (const void *)&uf, sizeof(uf));
        if (ret != sizeof(uf)) {
                err(EXIT_FAILURE, "Could not write "
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to