]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ipfilter/lib/ipft_pc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ipfilter / lib / ipft_pc.c
1 /*      $FreeBSD$       */
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)
14 static const char rcsid[] = "@(#)$Id$";
15 #endif
16
17 struct  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
29 static  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
37 typedef 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
47 typedef 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
54 static  int     ipcap_open __P((char *));
55 static  int     ipcap_close __P((void));
56 static  int     ipcap_readip __P((mb_t *, char **, int *));
57 static  int     ipcap_read_rec __P((packetheader_t *));
58 static  void    iswap_hdr __P((fileheader_t *));
59
60 static  int     pfd = -1, swapped = 0;
61 static  struct llc      *llcp = NULL;
62
63 struct  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
70 static  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
81 static  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
127 static  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  */
137 static  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  */
176 static  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  */
205 static  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 }