1/* $NetBSD: shmif_dumpbus.c,v 1.7 2011/03/14 11:13:22 pooka Exp $ */ 2 3/*- 4 * Copyright (c) 2010 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28/* 29 * Convert shmif bus traffic to a pcap file which can be then 30 * examined with tcpdump -r, wireshark, etc. 31 */ 32 33#include <sys/types.h> 34#include <sys/mman.h> 35#include <sys/stat.h> 36 37#include <machine/bswap.h> 38 39#include <assert.h> 40#include <err.h> 41#include <fcntl.h> 42#include <inttypes.h> 43#include <pcap.h> 44#include <stdbool.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#include <unistd.h> 49 50#include "shmifvar.h" 51 52__dead static void 53usage(void) 54{ 55 56 fprintf(stderr, "usage: %s [-h] [-p pcapfile] buspath\n",getprogname()); 57 exit(1); 58} 59 60#define BUFSIZE 64*1024 61#define SWAPME(a) (doswap ? bswap32(a) : (a)) 62#define SWAPME64(a) (doswap ? bswap64(a) : (a)) 63int 64main(int argc, char *argv[]) 65{ 66 struct stat sb; 67 void *busmem; 68 const char *pcapfile = NULL; 69 uint32_t curbus, buslast; 70 struct shmif_mem *bmem; 71 int fd, i, ch; 72 int bonus; 73 char *buf; 74 bool hflag = false, doswap = false, isstdout; 75 pcap_dumper_t *pdump; 76 77 setprogname(argv[0]); 78 while ((ch = getopt(argc, argv, "hp:")) != -1) { 79 switch (ch) { 80 case 'h': 81 hflag = true; 82 break; 83 case 'p': 84 pcapfile = optarg; 85 break; 86 default: 87 usage(); 88 } 89 } 90 91 argc -= optind; 92 argv += optind; 93 94 if (argc != 1) 95 usage(); 96 97 buf = malloc(BUFSIZE); 98 if (buf == NULL) 99 err(1, "malloc"); 100 101 fd = open(argv[0], O_RDONLY); 102 if (fd == -1) 103 err(1, "open bus"); 104 105 if (fstat(fd, &sb) == -1) 106 err(1, "stat"); 107 108 busmem = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0); 109 if (busmem == MAP_FAILED) 110 err(1, "mmap"); 111 bmem = busmem; 112 113 if (bmem->shm_magic != SHMIF_MAGIC) { 114 if (bmem->shm_magic != bswap32(SHMIF_MAGIC)) 115 errx(1, "%s not a shmif bus", argv[0]); 116 doswap = 1; 117 } 118 if (SWAPME(bmem->shm_version) != SHMIF_VERSION) 119 errx(1, "bus vesrsion %d, program %d", 120 SWAPME(bmem->shm_version), SHMIF_VERSION); 121 printf("bus version %d, lock: %d, generation: %" PRIu64 122 ", firstoff: 0x%04x, lastoff: 0x%04x\n", 123 SWAPME(bmem->shm_version), SWAPME(bmem->shm_lock), 124 SWAPME64(bmem->shm_gen), 125 SWAPME(bmem->shm_first), SWAPME(bmem->shm_last)); 126 127 if (hflag) 128 exit(0); 129 130 if (pcapfile) { 131 isstdout = strcmp(pcapfile, "-") == 0; 132 pcap_t *pcap = pcap_open_dead(DLT_EN10MB, 1518); 133 pdump = pcap_dump_open(pcap, pcapfile); 134 if (pdump == NULL) 135 err(1, "cannot open pcap dump file"); 136 } else { 137 /* XXXgcc */ 138 isstdout = false; 139 pdump = NULL; 140 } 141 142 curbus = SWAPME(bmem->shm_first); 143 buslast = SWAPME(bmem->shm_last); 144 if (curbus == BUSMEM_DATASIZE) 145 curbus = 0; 146 147 bonus = 0; 148 if (buslast < curbus) 149 bonus = 1; 150 151 i = 0; 152 while (curbus <= buslast || bonus) { 153 struct pcap_pkthdr packhdr; 154 struct shmif_pkthdr sp; 155 uint32_t oldoff; 156 uint32_t curlen; 157 bool wrap; 158 159 assert(curbus < sb.st_size); 160 161 wrap = false; 162 oldoff = curbus; 163 curbus = shmif_busread(bmem, &sp, oldoff, sizeof(sp), &wrap); 164 if (wrap) 165 bonus = 0; 166 167 assert(curbus < sb.st_size); 168 curlen = SWAPME(sp.sp_len); 169 170 if (curlen == 0) { 171 continue; 172 } 173 174 if (!(pcapfile && isstdout)) 175 printf("packet %d, offset 0x%04x, length 0x%04x, " 176 "ts %d/%06d\n", i++, curbus, 177 curlen, SWAPME(sp.sp_sec), SWAPME(sp.sp_usec)); 178 179 if (!pcapfile) { 180 curbus = shmif_busread(bmem, 181 buf, curbus, curlen, &wrap); 182 if (wrap) 183 bonus = 0; 184 continue; 185 } 186 187 memset(&packhdr, 0, sizeof(packhdr)); 188 packhdr.caplen = packhdr.len = curlen; 189 packhdr.ts.tv_sec = SWAPME(sp.sp_sec); 190 packhdr.ts.tv_usec = SWAPME(sp.sp_usec); 191 assert(curlen <= BUFSIZE); 192 193 curbus = shmif_busread(bmem, buf, curbus, curlen, &wrap); 194 pcap_dump((u_char *)pdump, &packhdr, (u_char *)buf); 195 if (wrap) 196 bonus = 0; 197 } 198 199 if (pcapfile) 200 pcap_dump_close(pdump); 201 202 return 0; 203} 204