nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 |
||
3 | * The Regents of the University of California. All rights reserved. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that: (1) source code distributions |
||
7 | * retain the above copyright notice and this paragraph in its entirety, (2) |
||
8 | * distributions including binary code include the above copyright notice and |
||
9 | * this paragraph in its entirety in the documentation or other materials |
||
10 | * provided with the distribution, and (3) all advertising materials mentioning |
||
11 | * features or use of this software display the following acknowledgement: |
||
12 | * ``This product includes software developed by the University of California, |
||
13 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
||
14 | * the University nor the names of its contributors may be used to endorse |
||
15 | * or promote products derived from this software without specific prior |
||
16 | * written permission. |
||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
||
18 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
||
20 | */ |
||
21 | |||
22 | #ifndef lint |
||
23 | static const char copyright[] _U_ = |
||
24 | "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ |
||
25 | The Regents of the University of California. All rights reserved.\n"; |
||
26 | #endif |
||
27 | |||
28 | #ifdef HAVE_CONFIG_H |
||
29 | #include "config.h" |
||
30 | #endif |
||
31 | |||
32 | #include <pcap.h> |
||
33 | #include <stdio.h> |
||
34 | #include <stdlib.h> |
||
35 | #include <string.h> |
||
36 | #include <stdarg.h> |
||
37 | #include <unistd.h> |
||
38 | #include <fcntl.h> |
||
39 | #include <errno.h> |
||
40 | #include <arpa/inet.h> |
||
41 | #include <sys/types.h> |
||
42 | #include <sys/stat.h> |
||
43 | |||
44 | #ifndef HAVE___ATTRIBUTE__ |
||
45 | #define __attribute__(x) |
||
46 | #endif |
||
47 | |||
48 | static char *program_name; |
||
49 | |||
50 | /* Forwards */ |
||
51 | static void usage(void) __attribute__((noreturn)); |
||
52 | static void error(const char *, ...) |
||
53 | __attribute__((noreturn, format (printf, 1, 2))); |
||
54 | static void warn(const char *, ...) |
||
55 | __attribute__((format (printf, 1, 2))); |
||
56 | |||
57 | extern int optind; |
||
58 | extern int opterr; |
||
59 | extern char *optarg; |
||
60 | #ifdef BDEBUG |
||
61 | int dflag; |
||
62 | #endif |
||
63 | |||
64 | /* |
||
65 | * On Windows, we need to open the file in binary mode, so that |
||
66 | * we get all the bytes specified by the size we get from "fstat()". |
||
67 | * On UNIX, that's not necessary. O_BINARY is defined on Windows; |
||
68 | * we define it as 0 if it's not defined, so it does nothing. |
||
69 | */ |
||
70 | #ifndef O_BINARY |
||
71 | #define O_BINARY 0 |
||
72 | #endif |
||
73 | |||
74 | static char * |
||
75 | read_infile(char *fname) |
||
76 | { |
||
77 | register int i, fd, cc; |
||
78 | register char *cp; |
||
79 | struct stat buf; |
||
80 | |||
81 | fd = open(fname, O_RDONLY|O_BINARY); |
||
82 | if (fd < 0) |
||
83 | error("can't open %s: %s", fname, pcap_strerror(errno)); |
||
84 | |||
85 | if (fstat(fd, &buf) < 0) |
||
86 | error("can't stat %s: %s", fname, pcap_strerror(errno)); |
||
87 | |||
88 | cp = malloc((u_int)buf.st_size + 1); |
||
89 | if (cp == NULL) |
||
90 | error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, |
||
91 | fname, pcap_strerror(errno)); |
||
92 | cc = read(fd, cp, (u_int)buf.st_size); |
||
93 | if (cc < 0) |
||
94 | error("read %s: %s", fname, pcap_strerror(errno)); |
||
95 | if (cc != buf.st_size) |
||
96 | error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); |
||
97 | |||
98 | close(fd); |
||
99 | /* replace "# comment" with spaces */ |
||
100 | for (i = 0; i < cc; i++) { |
||
101 | if (cp[i] == '#') |
||
102 | while (i < cc && cp[i] != '\n') |
||
103 | cp[i++] = ' '; |
||
104 | } |
||
105 | cp[cc] = '\0'; |
||
106 | return (cp); |
||
107 | } |
||
108 | |||
109 | /* VARARGS */ |
||
110 | static void |
||
111 | error(const char *fmt, ...) |
||
112 | { |
||
113 | va_list ap; |
||
114 | |||
115 | (void)fprintf(stderr, "%s: ", program_name); |
||
116 | va_start(ap, fmt); |
||
117 | (void)vfprintf(stderr, fmt, ap); |
||
118 | va_end(ap); |
||
119 | if (*fmt) { |
||
120 | fmt += strlen(fmt); |
||
121 | if (fmt[-1] != '\n') |
||
122 | (void)fputc('\n', stderr); |
||
123 | } |
||
124 | exit(1); |
||
125 | /* NOTREACHED */ |
||
126 | } |
||
127 | |||
128 | /* VARARGS */ |
||
129 | static void |
||
130 | warn(const char *fmt, ...) |
||
131 | { |
||
132 | va_list ap; |
||
133 | |||
134 | (void)fprintf(stderr, "%s: WARNING: ", program_name); |
||
135 | va_start(ap, fmt); |
||
136 | (void)vfprintf(stderr, fmt, ap); |
||
137 | va_end(ap); |
||
138 | if (*fmt) { |
||
139 | fmt += strlen(fmt); |
||
140 | if (fmt[-1] != '\n') |
||
141 | (void)fputc('\n', stderr); |
||
142 | } |
||
143 | } |
||
144 | |||
145 | /* |
||
146 | * Copy arg vector into a new buffer, concatenating arguments with spaces. |
||
147 | */ |
||
148 | static char * |
||
149 | copy_argv(register char **argv) |
||
150 | { |
||
151 | register char **p; |
||
152 | register u_int len = 0; |
||
153 | char *buf; |
||
154 | char *src, *dst; |
||
155 | |||
156 | p = argv; |
||
157 | if (*p == 0) |
||
158 | return 0; |
||
159 | |||
160 | while (*p) |
||
161 | len += strlen(*p++) + 1; |
||
162 | |||
163 | buf = (char *)malloc(len); |
||
164 | if (buf == NULL) |
||
165 | error("copy_argv: malloc"); |
||
166 | |||
167 | p = argv; |
||
168 | dst = buf; |
||
169 | while ((src = *p++) != NULL) { |
||
170 | while ((*dst++ = *src++) != '\0') |
||
171 | ; |
||
172 | dst[-1] = ' '; |
||
173 | } |
||
174 | dst[-1] = '\0'; |
||
175 | |||
176 | return buf; |
||
177 | } |
||
178 | |||
179 | int |
||
180 | main(int argc, char **argv) |
||
181 | { |
||
182 | char *cp; |
||
183 | int op; |
||
184 | #ifndef BDEBUG |
||
185 | int dflag; |
||
186 | #endif |
||
187 | char *infile; |
||
188 | int Oflag; |
||
189 | long snaplen; |
||
190 | char *p; |
||
191 | int dlt; |
||
192 | bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; |
||
193 | char *cmdbuf; |
||
194 | pcap_t *pd; |
||
195 | struct bpf_program fcode; |
||
196 | |||
197 | #ifdef WIN32 |
||
198 | if(wsockinit() != 0) return 1; |
||
199 | #endif /* WIN32 */ |
||
200 | |||
201 | #ifndef BDEBUG |
||
202 | dflag = 1; |
||
203 | #else |
||
204 | /* if optimizer debugging is enabled, output DOT graph |
||
205 | * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd |
||
206 | * convention in tcpdump command line |
||
207 | */ |
||
208 | dflag = 4; |
||
209 | #endif |
||
210 | infile = NULL; |
||
211 | Oflag = 1; |
||
212 | snaplen = 68; |
||
213 | |||
214 | if ((cp = strrchr(argv[0], '/')) != NULL) |
||
215 | program_name = cp + 1; |
||
216 | else |
||
217 | program_name = argv[0]; |
||
218 | |||
219 | opterr = 0; |
||
220 | while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) { |
||
221 | switch (op) { |
||
222 | |||
223 | case 'd': |
||
224 | ++dflag; |
||
225 | break; |
||
226 | |||
227 | case 'F': |
||
228 | infile = optarg; |
||
229 | break; |
||
230 | |||
231 | case 'O': |
||
232 | Oflag = 0; |
||
233 | break; |
||
234 | |||
235 | case 'm': { |
||
236 | in_addr_t addr; |
||
237 | |||
238 | addr = inet_addr(optarg); |
||
239 | if (addr == INADDR_NONE) |
||
240 | error("invalid netmask %s", optarg); |
||
241 | netmask = addr; |
||
242 | break; |
||
243 | } |
||
244 | |||
245 | case 's': { |
||
246 | char *end; |
||
247 | |||
248 | snaplen = strtol(optarg, &end, 0); |
||
249 | if (optarg == end || *end != '\0' |
||
250 | || snaplen < 0 || snaplen > 65535) |
||
251 | error("invalid snaplen %s", optarg); |
||
252 | else if (snaplen == 0) |
||
253 | snaplen = 65535; |
||
254 | break; |
||
255 | } |
||
256 | |||
257 | default: |
||
258 | usage(); |
||
259 | /* NOTREACHED */ |
||
260 | } |
||
261 | } |
||
262 | |||
263 | if (optind >= argc) { |
||
264 | usage(); |
||
265 | /* NOTREACHED */ |
||
266 | } |
||
267 | |||
268 | dlt = pcap_datalink_name_to_val(argv[optind]); |
||
269 | if (dlt < 0) { |
||
270 | dlt = (int)strtol(argv[optind], &p, 10); |
||
271 | if (p == argv[optind] || *p != '\0') |
||
272 | error("invalid data link type %s", argv[optind]); |
||
273 | } |
||
274 | |||
275 | if (infile) |
||
276 | cmdbuf = read_infile(infile); |
||
277 | else |
||
278 | cmdbuf = copy_argv(&argv[optind+1]); |
||
279 | |||
280 | pd = pcap_open_dead(dlt, snaplen); |
||
281 | if (pd == NULL) |
||
282 | error("Can't open fake pcap_t"); |
||
283 | |||
284 | if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) |
||
285 | error("%s", pcap_geterr(pd)); |
||
286 | |||
287 | if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) |
||
288 | warn("Filter doesn't pass validation"); |
||
289 | |||
290 | #ifdef BDEBUG |
||
291 | // replace line feed with space |
||
292 | for (cp = cmdbuf; *cp != '\0'; ++cp) { |
||
293 | if (*cp == '\r' || *cp == '\n') { |
||
294 | *cp = ' '; |
||
295 | } |
||
296 | } |
||
297 | // only show machine code if BDEBUG defined, since dflag > 3 |
||
298 | printf("machine codes for filter: %s\n", cmdbuf); |
||
299 | #endif |
||
300 | |||
301 | bpf_dump(&fcode, dflag); |
||
302 | pcap_close(pd); |
||
303 | exit(0); |
||
304 | } |
||
305 | |||
306 | static void |
||
307 | usage(void) |
||
308 | { |
||
309 | (void)fprintf(stderr, "%s, with %s\n", program_name, |
||
310 | pcap_lib_version()); |
||
311 | (void)fprintf(stderr, |
||
312 | "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n", |
||
313 | program_name); |
||
314 | exit(1); |
||
315 | } |