1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4170268Sdarrenr * Copyright (C) 2000-2003 by Darren Reed. 5145510Sdarrenr * 6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145510Sdarrenr * 8170268Sdarrenr * $Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $ 9145510Sdarrenr */ 10145510Sdarrenr 11145510Sdarrenr/* 12145510Sdarrenr * Written to comply with the recent RFC 1761 from Sun. 13145510Sdarrenr */ 14145510Sdarrenr#include "ipf.h" 15145510Sdarrenr#include "snoop.h" 16145510Sdarrenr#include "ipt.h" 17145510Sdarrenr 18145510Sdarrenr#if !defined(lint) 19170268Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $"; 20145510Sdarrenr#endif 21145510Sdarrenr 22145510Sdarrenrstruct llc { 23145510Sdarrenr int lc_sz; /* LLC header length */ 24145510Sdarrenr int lc_to; /* LLC Type offset */ 25145510Sdarrenr int lc_tl; /* LLC Type length */ 26145510Sdarrenr}; 27145510Sdarrenr 28145510Sdarrenr/* 29145510Sdarrenr * While many of these maybe the same, some do have different header formats 30145510Sdarrenr * which make this useful. 31145510Sdarrenr */ 32145510Sdarrenrstatic struct llc llcs[SDL_MAX+1] = { 33145510Sdarrenr { 0, 0, 0 }, /* SDL_8023 */ 34145510Sdarrenr { 0, 0, 0 }, /* SDL_8024 */ 35145510Sdarrenr { 0, 0, 0 }, /* SDL_8025 */ 36145510Sdarrenr { 0, 0, 0 }, /* SDL_8026 */ 37145510Sdarrenr { 14, 12, 2 }, /* SDL_ETHER */ 38145510Sdarrenr { 0, 0, 0 }, /* SDL_HDLC */ 39145510Sdarrenr { 0, 0, 0 }, /* SDL_CHSYNC */ 40145510Sdarrenr { 0, 0, 0 }, /* SDL_IBMCC */ 41145510Sdarrenr { 0, 0, 0 }, /* SDL_FDDI */ 42145510Sdarrenr { 0, 0, 0 }, /* SDL_OTHER */ 43145510Sdarrenr}; 44145510Sdarrenr 45145510Sdarrenrstatic int snoop_open __P((char *)); 46145510Sdarrenrstatic int snoop_close __P((void)); 47145510Sdarrenrstatic int snoop_readip __P((char *, int, char **, int *)); 48145510Sdarrenr 49145510Sdarrenrstatic int sfd = -1, s_type = -1; 50145510Sdarrenrstatic int snoop_read_rec __P((struct snooppkt *)); 51145510Sdarrenr 52145510Sdarrenrstruct ipread snoop = { snoop_open, snoop_close, snoop_readip, 0 }; 53145510Sdarrenr 54145510Sdarrenr 55145510Sdarrenrstatic int snoop_open(fname) 56145510Sdarrenrchar *fname; 57145510Sdarrenr{ 58145510Sdarrenr struct snoophdr sh; 59145510Sdarrenr int fd; 60145510Sdarrenr int s_v; 61145510Sdarrenr 62145510Sdarrenr if (sfd != -1) 63145510Sdarrenr return sfd; 64145510Sdarrenr 65145510Sdarrenr if (!strcmp(fname, "-")) 66145510Sdarrenr fd = 0; 67145510Sdarrenr else if ((fd = open(fname, O_RDONLY)) == -1) 68145510Sdarrenr return -1; 69145510Sdarrenr 70145510Sdarrenr if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh)) 71145510Sdarrenr return -2; 72145510Sdarrenr 73145510Sdarrenr s_v = (int)ntohl(sh.s_v); 74145510Sdarrenr s_type = (int)ntohl(sh.s_type); 75145510Sdarrenr 76145510Sdarrenr if (s_v != SNOOP_VERSION || 77145510Sdarrenr s_type < 0 || s_type > SDL_MAX) { 78145510Sdarrenr (void) close(fd); 79145510Sdarrenr return -2; 80145510Sdarrenr } 81145510Sdarrenr 82145510Sdarrenr sfd = fd; 83145510Sdarrenr printf("opened snoop file %s:\n", fname); 84145510Sdarrenr printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type); 85145510Sdarrenr 86145510Sdarrenr return fd; 87145510Sdarrenr} 88145510Sdarrenr 89145510Sdarrenr 90145510Sdarrenrstatic int snoop_close() 91145510Sdarrenr{ 92145510Sdarrenr return close(sfd); 93145510Sdarrenr} 94145510Sdarrenr 95145510Sdarrenr 96145510Sdarrenr/* 97145510Sdarrenr * read in the header (and validate) which should be the first record 98145510Sdarrenr * in a snoop file. 99145510Sdarrenr */ 100145510Sdarrenrstatic int snoop_read_rec(rec) 101145510Sdarrenrstruct snooppkt *rec; 102145510Sdarrenr{ 103145510Sdarrenr int n, plen, ilen; 104145510Sdarrenr 105145510Sdarrenr if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) 106145510Sdarrenr return -2; 107145510Sdarrenr 108145510Sdarrenr ilen = (int)ntohl(rec->sp_ilen); 109145510Sdarrenr plen = (int)ntohl(rec->sp_plen); 110145510Sdarrenr if (ilen > plen || plen < sizeof(*rec)) 111145510Sdarrenr return -2; 112145510Sdarrenr 113145510Sdarrenr plen -= sizeof(*rec); 114145510Sdarrenr n = MIN(plen, ilen); 115145510Sdarrenr if (!n || n < 0) 116145510Sdarrenr return -3; 117145510Sdarrenr 118145510Sdarrenr return plen; 119145510Sdarrenr} 120145510Sdarrenr 121145510Sdarrenr 122145510Sdarrenr#ifdef notyet 123145510Sdarrenr/* 124145510Sdarrenr * read an entire snoop packet record. only the data part is copied into 125145510Sdarrenr * the available buffer, with the number of bytes copied returned. 126145510Sdarrenr */ 127145510Sdarrenrstatic int snoop_read(buf, cnt) 128145510Sdarrenrchar *buf; 129145510Sdarrenrint cnt; 130145510Sdarrenr{ 131145510Sdarrenr struct snooppkt rec; 132145510Sdarrenr static char *bufp = NULL; 133145510Sdarrenr int i, n; 134145510Sdarrenr 135145510Sdarrenr if ((i = snoop_read_rec(&rec)) <= 0) 136145510Sdarrenr return i; 137145510Sdarrenr 138145510Sdarrenr if (!bufp) 139145510Sdarrenr bufp = malloc(i); 140145510Sdarrenr else 141145510Sdarrenr bufp = realloc(bufp, i); 142145510Sdarrenr 143145510Sdarrenr if (read(sfd, bufp, i) != i) 144145510Sdarrenr return -2; 145145510Sdarrenr 146145510Sdarrenr n = MIN(i, cnt); 147145510Sdarrenr bcopy(bufp, buf, n); 148145510Sdarrenr return n; 149145510Sdarrenr} 150145510Sdarrenr#endif 151145510Sdarrenr 152145510Sdarrenr 153145510Sdarrenr/* 154145510Sdarrenr * return only an IP packet read into buf 155145510Sdarrenr */ 156145510Sdarrenrstatic int snoop_readip(buf, cnt, ifn, dir) 157145510Sdarrenrchar *buf, **ifn; 158145510Sdarrenrint cnt, *dir; 159145510Sdarrenr{ 160145510Sdarrenr static char *bufp = NULL; 161145510Sdarrenr struct snooppkt rec; 162145510Sdarrenr struct llc *l; 163145510Sdarrenr char ty[4], *s; 164145510Sdarrenr int i, n; 165145510Sdarrenr 166145510Sdarrenr do { 167145510Sdarrenr if ((i = snoop_read_rec(&rec)) <= 0) 168145510Sdarrenr return i; 169145510Sdarrenr 170145510Sdarrenr if (!bufp) 171145510Sdarrenr bufp = malloc(i); 172145510Sdarrenr else 173145510Sdarrenr bufp = realloc(bufp, i); 174145510Sdarrenr s = bufp; 175145510Sdarrenr 176145510Sdarrenr if (read(sfd, s, i) != i) 177145510Sdarrenr return -2; 178145510Sdarrenr 179145510Sdarrenr l = &llcs[s_type]; 180145510Sdarrenr i -= l->lc_to; 181145510Sdarrenr s += l->lc_to; 182145510Sdarrenr /* 183145510Sdarrenr * XXX - bogus assumption here on the part of the time field 184145510Sdarrenr * that it won't be greater than 4 bytes and the 1st two will 185145510Sdarrenr * have the values 8 and 0 for IP. Should be a table of 186145510Sdarrenr * these too somewhere. Really only works for SDL_ETHER. 187145510Sdarrenr */ 188145510Sdarrenr bcopy(s, ty, l->lc_tl); 189145510Sdarrenr } while (ty[0] != 0x8 && ty[1] != 0); 190145510Sdarrenr 191145510Sdarrenr i -= l->lc_tl; 192145510Sdarrenr s += l->lc_tl; 193145510Sdarrenr n = MIN(i, cnt); 194145510Sdarrenr bcopy(s, buf, n); 195145510Sdarrenr 196145510Sdarrenr return n; 197145510Sdarrenr} 198