1 /* $NetBSD: shmif_dumpbus.c,v 1.1 2011/01/12 16:14:24 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 <assert.h> 38 #include <err.h> 39 #include <fcntl.h> 40 #include <inttypes.h> 41 #include <pcap.h> 42 #include <stdbool.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "shmifvar.h" 49 50 static void 51 usage(void) 52 { 53 54 fprintf(stderr, "usage: %s [-h] [-p pcapfile] buspath\n",getprogname()); 55 exit(1); 56 } 57 58 #define BUFSIZE 64*1024 59 int 60 main(int argc, char *argv[]) 61 { 62 struct stat sb; 63 void *busmem; 64 const char *pcapfile = NULL; 65 uint32_t curbus, buslast; 66 struct shmif_mem *bmem; 67 int fd, pfd, i, ch; 68 int bonus; 69 char *buf; 70 bool hflag = false; 71 72 setprogname(argv[0]); 73 while ((ch = getopt(argc, argv, "hp:")) != -1) { 74 switch (ch) { 75 case 'h': 76 hflag = true; 77 break; 78 case 'p': 79 pcapfile = optarg; 80 break; 81 default: 82 usage(); 83 } 84 } 85 86 argc -= optind; 87 argv += optind; 88 89 if (argc != 1) 90 usage(); 91 92 buf = malloc(BUFSIZE); 93 if (buf == NULL) 94 err(1, "malloc"); 95 96 fd = open(argv[0], O_RDONLY); 97 if (fd == -1) 98 err(1, "open bus"); 99 100 if (fstat(fd, &sb) == -1) 101 err(1, "stat"); 102 103 busmem = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0); 104 if (busmem == MAP_FAILED) 105 err(1, "mmap"); 106 bmem = busmem; 107 108 if (bmem->shm_magic != SHMIF_MAGIC) 109 errx(1, "%s not a shmif bus", argv[0]); 110 if (bmem->shm_version != SHMIF_VERSION) 111 errx(1, "bus vesrsion %d, program %d", 112 bmem->shm_version, SHMIF_VERSION); 113 printf("bus version %d, lock: %d, generation: %" PRIu64 114 ", firstoff: 0x%04x, lastoff: 0x%04x\n", 115 bmem->shm_version, bmem->shm_lock, bmem->shm_gen, 116 bmem->shm_first, bmem->shm_last); 117 118 if (hflag) 119 exit(0); 120 121 if (pcapfile) { 122 struct pcap_file_header phdr; 123 124 if (strcmp(pcapfile, "-") == 0) { 125 pfd = STDOUT_FILENO; 126 } else { 127 pfd = open(pcapfile, O_RDWR | O_CREAT | O_TRUNC, 0777); 128 if (pfd == -1) 129 err(1, "create pcap dump"); 130 } 131 132 memset(&phdr, 0, sizeof(phdr)); 133 phdr.magic = 0xa1b2c3d4; /* tcpdump magic */ 134 phdr.version_major = PCAP_VERSION_MAJOR; 135 phdr.version_minor = PCAP_VERSION_MINOR; 136 phdr.snaplen = 1518; 137 phdr.linktype = DLT_EN10MB; 138 139 if (write(pfd, &phdr, sizeof(phdr)) != sizeof(phdr)) 140 err(1, "phdr write"); 141 } else { 142 pfd = 0; /* XXXgcc */ 143 } 144 145 curbus = bmem->shm_first; 146 buslast = bmem->shm_last; 147 if (curbus == BUSMEM_DATASIZE) 148 curbus = 0; 149 150 bonus = 0; 151 if (buslast < curbus) 152 bonus = 1; 153 154 i = 0; 155 while (curbus <= buslast || bonus) { 156 struct pcap_pkthdr packhdr; 157 struct shmif_pkthdr sp; 158 uint32_t oldoff; 159 bool wrap; 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 if (sp.sp_len == 0) 168 continue; 169 170 printf("packet %d, offset 0x%04x, length 0x%04x, ts %d/%06d\n", 171 i++, curbus, sp.sp_len, sp.sp_sec, sp.sp_usec); 172 173 if (!pcapfile || sp.sp_len == 0) { 174 curbus = shmif_busread(bmem, 175 buf, curbus, sp.sp_len, &wrap); 176 if (wrap) 177 bonus = 0; 178 continue; 179 } 180 181 memset(&packhdr, 0, sizeof(packhdr)); 182 packhdr.caplen = packhdr.len = sp.sp_len; 183 packhdr.ts.tv_sec = sp.sp_sec; 184 packhdr.ts.tv_usec = sp.sp_usec; 185 186 if (write(pfd, &packhdr, sizeof(packhdr)) != sizeof(packhdr)) 187 err(1, "error writing packethdr"); 188 curbus = shmif_busread(bmem, buf, curbus, sp.sp_len, &wrap); 189 if (write(pfd, buf, sp.sp_len) != (ssize_t)sp.sp_len) 190 err(1, "write packet"); 191 if (wrap) 192 bonus = 0; 193 } 194 195 return 0; 196 } 197