/* $NetBSD: shmif_dumpbus.c,v 1.8 2011/09/16 15:39:29 joerg Exp $ */ /*- * Copyright (c) 2010 Antti Kantee. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Convert shmif bus traffic to a pcap file which can be then * examined with tcpdump -r, wireshark, etc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shmifvar.h" __dead static void usage(void) { fprintf(stderr, "usage: %s [-h] [-p pcapfile] buspath\n",getprogname()); exit(1); } #define BUFSIZE 64*1024 #define SWAPME(a) (doswap ? bswap32(a) : (a)) #define SWAPME64(a) (doswap ? bswap64(a) : (a)) int main(int argc, char *argv[]) { struct stat sb; void *busmem; const char *pcapfile = NULL; uint32_t curbus, buslast; struct shmif_mem *bmem; int fd, i, ch; int bonus; char *buf; bool hflag = false, doswap = false, isstdout; pcap_dumper_t *pdump; setprogname(argv[0]); while ((ch = getopt(argc, argv, "hp:")) != -1) { switch (ch) { case 'h': hflag = true; break; case 'p': pcapfile = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); buf = malloc(BUFSIZE); if (buf == NULL) err(1, "malloc"); fd = open(argv[0], O_RDONLY); if (fd == -1) err(1, "open bus"); if (fstat(fd, &sb) == -1) err(1, "stat"); busmem = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0); if (busmem == MAP_FAILED) err(1, "mmap"); bmem = busmem; if (bmem->shm_magic != SHMIF_MAGIC) { if (bmem->shm_magic != bswap32(SHMIF_MAGIC)) errx(1, "%s not a shmif bus", argv[0]); doswap = 1; } if (SWAPME(bmem->shm_version) != SHMIF_VERSION) errx(1, "bus vesrsion %d, program %d", SWAPME(bmem->shm_version), SHMIF_VERSION); printf("bus version %d, lock: %d, generation: %" PRIu64 ", firstoff: 0x%04x, lastoff: 0x%04x\n", SWAPME(bmem->shm_version), SWAPME(bmem->shm_lock), SWAPME64(bmem->shm_gen), SWAPME(bmem->shm_first), SWAPME(bmem->shm_last)); if (hflag) exit(0); if (pcapfile) { isstdout = strcmp(pcapfile, "-") == 0; pcap_t *pcap = pcap_open_dead(DLT_EN10MB, 1518); pdump = pcap_dump_open(pcap, pcapfile); if (pdump == NULL) err(1, "cannot open pcap dump file"); } else { /* XXXgcc */ isstdout = false; pdump = NULL; } curbus = SWAPME(bmem->shm_first); buslast = SWAPME(bmem->shm_last); if (curbus == BUSMEM_DATASIZE) curbus = 0; bonus = 0; if (buslast < curbus) bonus = 1; i = 0; while (curbus <= buslast || bonus) { struct pcap_pkthdr packhdr; struct shmif_pkthdr sp; uint32_t oldoff; uint32_t curlen; bool wrap; assert(curbus < sb.st_size); wrap = false; oldoff = curbus; curbus = shmif_busread(bmem, &sp, oldoff, sizeof(sp), &wrap); if (wrap) bonus = 0; assert(curbus < sb.st_size); curlen = SWAPME(sp.sp_len); if (curlen == 0) { continue; } if (!(pcapfile && isstdout)) printf("packet %d, offset 0x%04x, length 0x%04x, " "ts %d/%06d\n", i++, curbus, curlen, SWAPME(sp.sp_sec), SWAPME(sp.sp_usec)); if (!pcapfile) { curbus = shmif_busread(bmem, buf, curbus, curlen, &wrap); if (wrap) bonus = 0; continue; } memset(&packhdr, 0, sizeof(packhdr)); packhdr.caplen = packhdr.len = curlen; packhdr.ts.tv_sec = SWAPME(sp.sp_sec); packhdr.ts.tv_usec = SWAPME(sp.sp_usec); assert(curlen <= BUFSIZE); curbus = shmif_busread(bmem, buf, curbus, curlen, &wrap); pcap_dump((u_char *)pdump, &packhdr, (u_char *)buf); if (wrap) bonus = 0; } if (pcapfile) pcap_dump_close(pdump); return 0; }