1/* $FreeBSD: stable/11/contrib/ipfilter/lib/ipft_pc.c 369245 2021-02-09 13:47:46Z git2svn $ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * $Id$ 9 */ 10#include "ipf.h" 11#include "ipt.h" 12 13#if !defined(lint) 14static const char rcsid[] = "@(#)$Id$"; 15#endif 16 17struct llc { 18 int lc_type; 19 int lc_sz; /* LLC header length */ 20 int lc_to; /* LLC Type offset */ 21 int lc_tl; /* LLC Type length */ 22}; 23 24/* 25 * While many of these maybe the same, some do have different header formats 26 * which make this useful. 27 */ 28 29static struct llc llcs[] = { 30 { 0, 0, 0, 0 }, /* DLT_NULL */ 31 { 1, 14, 12, 2 }, /* DLT_Ethernet */ 32 { 10, 0, 0, 0 }, /* DLT_FDDI */ 33 { 12, 0, 0, 0 }, /* DLT_RAW */ 34 { -1, -1, -1, -1 } 35}; 36 37typedef struct { 38 u_int id; 39 u_short major; 40 u_short minor; 41 u_int timezone; 42 u_int sigfigs; 43 u_int snaplen; 44 u_int type; 45} fileheader_t; 46 47typedef struct { 48 u_32_t seconds; 49 u_32_t microseconds; 50 u_32_t caplen; 51 u_32_t wirelen; 52} packetheader_t; 53 54static int ipcap_open(char *); 55static int ipcap_close(void); 56static int ipcap_readip(mb_t *, char **, int *); 57static int ipcap_read_rec(packetheader_t *); 58static void iswap_hdr(fileheader_t *); 59 60static int pfd = -1, swapped = 0; 61static struct llc *llcp = NULL; 62 63struct ipread pcap = { ipcap_open, ipcap_close, ipcap_readip, 0 }; 64 65#define SWAPLONG(y) \ 66 ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) 67#define SWAPSHORT(y) \ 68 ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) 69 70static void iswap_hdr(p) 71 fileheader_t *p; 72{ 73 p->major = SWAPSHORT(p->major); 74 p->minor = SWAPSHORT(p->minor); 75 p->timezone = SWAPLONG(p->timezone); 76 p->sigfigs = SWAPLONG(p->sigfigs); 77 p->snaplen = SWAPLONG(p->snaplen); 78 p->type = SWAPLONG(p->type); 79} 80 81static int ipcap_open(fname) 82 char *fname; 83{ 84 fileheader_t ph; 85 int fd, i; 86 87 if (pfd != -1) 88 return pfd; 89 90 if (!strcmp(fname, "-")) 91 fd = 0; 92 else if ((fd = open(fname, O_RDONLY)) == -1) 93 return -1; 94 95 if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) 96 return -2; 97 98 if (ph.id != 0xa1b2c3d4) { 99 if (SWAPLONG(ph.id) != 0xa1b2c3d4) { 100 (void) close(fd); 101 return -2; 102 } 103 swapped = 1; 104 iswap_hdr(&ph); 105 } 106 107 for (i = 0; llcs[i].lc_type != -1; i++) 108 if (llcs[i].lc_type == ph.type) { 109 llcp = llcs + i; 110 break; 111 } 112 113 if (llcp == NULL) { 114 (void) close(fd); 115 return -2; 116 } 117 118 pfd = fd; 119 printf("opened pcap file %s:\n", fname); 120 printf("\tid: %08x version: %d.%d type: %d snap %d\n", 121 ph.id, ph.major, ph.minor, ph.type, ph.snaplen); 122 123 return fd; 124} 125 126 127static int ipcap_close() 128{ 129 return close(pfd); 130} 131 132 133/* 134 * read in the header (and validate) which should be the first record 135 * in a pcap file. 136 */ 137static int ipcap_read_rec(rec) 138 packetheader_t *rec; 139{ 140 int n, p, i; 141 char *s; 142 143 s = (char *)rec; 144 n = sizeof(*rec); 145 146 while (n > 0) { 147 i = read(pfd, (char *)rec, sizeof(*rec)); 148 if (i <= 0) 149 return -2; 150 s += i; 151 n -= i; 152 } 153 154 if (swapped) { 155 rec->caplen = SWAPLONG(rec->caplen); 156 rec->wirelen = SWAPLONG(rec->wirelen); 157 rec->seconds = SWAPLONG(rec->seconds); 158 rec->microseconds = SWAPLONG(rec->microseconds); 159 } 160 p = rec->caplen; 161 n = MIN(p, rec->wirelen); 162 if (!n || n < 0) 163 return -3; 164 165 if (p < 0 || p > 65536) 166 return -4; 167 return p; 168} 169 170 171#ifdef notyet 172/* 173 * read an entire pcap packet record. only the data part is copied into 174 * the available buffer, with the number of bytes copied returned. 175 */ 176static int ipcap_read(buf, cnt) 177 char *buf; 178 int cnt; 179{ 180 packetheader_t rec; 181 static char *bufp = NULL; 182 int i, n; 183 184 if ((i = ipcap_read_rec(&rec)) <= 0) 185 return i; 186 187 if (!bufp) 188 bufp = malloc(i); 189 else 190 bufp = realloc(bufp, i); 191 192 if (read(pfd, bufp, i) != i) 193 return -2; 194 195 n = MIN(i, cnt); 196 bcopy(bufp, buf, n); 197 return n; 198} 199#endif 200 201 202/* 203 * return only an IP packet read into buf 204 */ 205static int ipcap_readip(mb, ifn, dir) 206 mb_t *mb; 207 char **ifn; 208 int *dir; 209{ 210 static char *bufp = NULL; 211 packetheader_t rec; 212 struct llc *l; 213 char *s, ty[4]; 214 int i, j, n; 215 char *buf; 216 int cnt; 217 218#if 0 219 ifn = ifn; /* gcc -Wextra */ 220 dir = dir; /* gcc -Wextra */ 221#endif 222 buf = (char *)mb->mb_buf; 223 cnt = sizeof(mb->mb_buf); 224 l = llcp; 225 226 /* do { */ 227 if ((i = ipcap_read_rec(&rec)) <= 0) 228 return i; 229 230 if (!bufp) 231 bufp = malloc(i); 232 else 233 bufp = realloc(bufp, i); 234 s = bufp; 235 236 for (j = i, n = 0; j > 0; ) { 237 n = read(pfd, s, j); 238 if (n <= 0) 239 return -2; 240 j -= n; 241 s += n; 242 } 243 s = bufp; 244 245 i -= l->lc_sz; 246 s += l->lc_to; 247 bcopy(s, ty, l->lc_tl); 248 s += l->lc_tl; 249 /* } while (ty[0] != 0x8 && ty[1] != 0); */ 250 n = MIN(i, cnt); 251 bcopy(s, buf, n); 252 mb->mb_len = n; 253 return n; 254} 255