1 /* 2 * Copyright (C) 1993-2001 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * $Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $ 7 */ 8 9 /* 10 * Written to comply with the recent RFC 1761 from Sun. 11 */ 12 #include "ipf.h" 13 #include "snoop.h" 14 #include "ipt.h" 15 16 #if !defined(lint) 17 static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $"; 18 #endif 19 20 struct llc { 21 int lc_sz; /* LLC header length */ 22 int lc_to; /* LLC Type offset */ 23 int lc_tl; /* LLC Type length */ 24 }; 25 26 /* 27 * While many of these maybe the same, some do have different header formats 28 * which make this useful. 29 */ 30 static struct llc llcs[SDL_MAX+1] = { 31 { 0, 0, 0 }, /* SDL_8023 */ 32 { 0, 0, 0 }, /* SDL_8024 */ 33 { 0, 0, 0 }, /* SDL_8025 */ 34 { 0, 0, 0 }, /* SDL_8026 */ 35 { 14, 12, 2 }, /* SDL_ETHER */ 36 { 0, 0, 0 }, /* SDL_HDLC */ 37 { 0, 0, 0 }, /* SDL_CHSYNC */ 38 { 0, 0, 0 }, /* SDL_IBMCC */ 39 { 0, 0, 0 }, /* SDL_FDDI */ 40 { 0, 0, 0 }, /* SDL_OTHER */ 41 }; 42 43 static int snoop_open __P((char *)); 44 static int snoop_close __P((void)); 45 static int snoop_readip __P((char *, int, char **, int *)); 46 47 static int sfd = -1, s_type = -1; 48 static int snoop_read_rec __P((struct snooppkt *)); 49 50 struct ipread snoop = { snoop_open, snoop_close, snoop_readip, 0 }; 51 52 53 static int snoop_open(fname) 54 char *fname; 55 { 56 struct snoophdr sh; 57 int fd; 58 int s_v; 59 60 if (sfd != -1) 61 return sfd; 62 63 if (!strcmp(fname, "-")) 64 fd = 0; 65 else if ((fd = open(fname, O_RDONLY)) == -1) 66 return -1; 67 68 if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh)) 69 return -2; 70 71 s_v = (int)ntohl(sh.s_v); 72 s_type = (int)ntohl(sh.s_type); 73 74 if (s_v != SNOOP_VERSION || 75 s_type < 0 || s_type > SDL_MAX) { 76 (void) close(fd); 77 return -2; 78 } 79 80 sfd = fd; 81 printf("opened snoop file %s:\n", fname); 82 printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type); 83 84 return fd; 85 } 86 87 88 static int snoop_close() 89 { 90 return close(sfd); 91 } 92 93 94 /* 95 * read in the header (and validate) which should be the first record 96 * in a snoop file. 97 */ 98 static int snoop_read_rec(rec) 99 struct snooppkt *rec; 100 { 101 int n, plen, ilen; 102 103 if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) 104 return -2; 105 106 ilen = (int)ntohl(rec->sp_ilen); 107 plen = (int)ntohl(rec->sp_plen); 108 if (ilen > plen || plen < sizeof(*rec)) 109 return -2; 110 111 plen -= sizeof(*rec); 112 n = MIN(plen, ilen); 113 if (!n || n < 0) 114 return -3; 115 116 return plen; 117 } 118 119 120 #ifdef notyet 121 /* 122 * read an entire snoop packet record. only the data part is copied into 123 * the available buffer, with the number of bytes copied returned. 124 */ 125 static int snoop_read(buf, cnt) 126 char *buf; 127 int cnt; 128 { 129 struct snooppkt rec; 130 static char *bufp = NULL; 131 int i, n; 132 133 if ((i = snoop_read_rec(&rec)) <= 0) 134 return i; 135 136 if (!bufp) 137 bufp = malloc(i); 138 else 139 bufp = realloc(bufp, i); 140 141 if (read(sfd, bufp, i) != i) 142 return -2; 143 144 n = MIN(i, cnt); 145 bcopy(bufp, buf, n); 146 return n; 147 } 148 #endif 149 150 151 /* 152 * return only an IP packet read into buf 153 */ 154 static int snoop_readip(buf, cnt, ifn, dir) 155 char *buf, **ifn; 156 int cnt, *dir; 157 { 158 static char *bufp = NULL; 159 struct snooppkt rec; 160 struct llc *l; 161 char ty[4], *s; 162 int i, n; 163 164 do { 165 if ((i = snoop_read_rec(&rec)) <= 0) 166 return i; 167 168 if (!bufp) 169 bufp = malloc(i); 170 else 171 bufp = realloc(bufp, i); 172 s = bufp; 173 174 if (read(sfd, s, i) != i) 175 return -2; 176 177 l = &llcs[s_type]; 178 i -= l->lc_to; 179 s += l->lc_to; 180 /* 181 * XXX - bogus assumption here on the part of the time field 182 * that it won't be greater than 4 bytes and the 1st two will 183 * have the values 8 and 0 for IP. Should be a table of 184 * these too somewhere. Really only works for SDL_ETHER. 185 */ 186 bcopy(s, ty, l->lc_tl); 187 } while (ty[0] != 0x8 && ty[1] != 0); 188 189 i -= l->lc_tl; 190 s += l->lc_tl; 191 n = MIN(i, cnt); 192 bcopy(s, buf, n); 193 194 return n; 195 } 196