1190214Srpaulo/*
2190214Srpaulo * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3190214Srpaulo *	The Regents of the University of California.  All rights reserved.
4190214Srpaulo *
5190214Srpaulo * Redistribution and use in source and binary forms, with or without
6190214Srpaulo * modification, are permitted provided that: (1) source code distributions
7190214Srpaulo * retain the above copyright notice and this paragraph in its entirety, (2)
8190214Srpaulo * distributions including binary code include the above copyright notice and
9190214Srpaulo * this paragraph in its entirety in the documentation or other materials
10190214Srpaulo * provided with the distribution, and (3) all advertising materials mentioning
11190214Srpaulo * features or use of this software display the following acknowledgement:
12190214Srpaulo * ``This product includes software developed by the University of California,
13190214Srpaulo * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14190214Srpaulo * the University nor the names of its contributors may be used to endorse
15190214Srpaulo * or promote products derived from this software without specific prior
16190214Srpaulo * written permission.
17190214Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18190214Srpaulo * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19190214Srpaulo * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20190214Srpaulo */
21190214Srpaulo
22190214Srpaulo#ifndef lint
23190214Srpaulostatic const char copyright[] _U_ =
24190214Srpaulo    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
25190214SrpauloThe Regents of the University of California.  All rights reserved.\n";
26190214Srpaulostatic const char rcsid[] _U_ =
27214455Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005-08-08 17:50:13 guy Exp $ (LBL)";
28190214Srpaulo#endif
29190214Srpaulo
30190214Srpaulo#ifdef HAVE_CONFIG_H
31190214Srpaulo#include "config.h"
32190214Srpaulo#endif
33190214Srpaulo
34190214Srpaulo#include <pcap.h>
35190214Srpaulo#include <stdio.h>
36190214Srpaulo#include <stdlib.h>
37190214Srpaulo#include <string.h>
38190214Srpaulo#include <stdarg.h>
39190214Srpaulo#include <unistd.h>
40190214Srpaulo#include <fcntl.h>
41190214Srpaulo#include <errno.h>
42214455Srpaulo#include <arpa/inet.h>
43190214Srpaulo#include <sys/types.h>
44190214Srpaulo#include <sys/stat.h>
45190214Srpaulo
46190214Srpaulo#ifndef HAVE___ATTRIBUTE__
47190214Srpaulo#define __attribute__(x)
48190214Srpaulo#endif
49190214Srpaulo
50190214Srpaulostatic char *program_name;
51190214Srpaulo
52190214Srpaulo/* Forwards */
53190214Srpaulostatic void usage(void) __attribute__((noreturn));
54190214Srpaulostatic void error(const char *, ...)
55190214Srpaulo    __attribute__((noreturn, format (printf, 1, 2)));
56190214Srpaulo
57190214Srpauloextern int optind;
58190214Srpauloextern int opterr;
59190214Srpauloextern char *optarg;
60190214Srpaulo
61190214Srpaulo/*
62190214Srpaulo * On Windows, we need to open the file in binary mode, so that
63190214Srpaulo * we get all the bytes specified by the size we get from "fstat()".
64190214Srpaulo * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
65190214Srpaulo * we define it as 0 if it's not defined, so it does nothing.
66190214Srpaulo */
67190214Srpaulo#ifndef O_BINARY
68190214Srpaulo#define O_BINARY	0
69190214Srpaulo#endif
70190214Srpaulo
71190214Srpaulostatic char *
72190214Srpauloread_infile(char *fname)
73190214Srpaulo{
74190214Srpaulo	register int i, fd, cc;
75190214Srpaulo	register char *cp;
76190214Srpaulo	struct stat buf;
77190214Srpaulo
78190214Srpaulo	fd = open(fname, O_RDONLY|O_BINARY);
79190214Srpaulo	if (fd < 0)
80190214Srpaulo		error("can't open %s: %s", fname, pcap_strerror(errno));
81190214Srpaulo
82190214Srpaulo	if (fstat(fd, &buf) < 0)
83190214Srpaulo		error("can't stat %s: %s", fname, pcap_strerror(errno));
84190214Srpaulo
85190214Srpaulo	cp = malloc((u_int)buf.st_size + 1);
86190214Srpaulo	if (cp == NULL)
87190214Srpaulo		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
88190214Srpaulo			fname, pcap_strerror(errno));
89190214Srpaulo	cc = read(fd, cp, (u_int)buf.st_size);
90190214Srpaulo	if (cc < 0)
91190214Srpaulo		error("read %s: %s", fname, pcap_strerror(errno));
92190214Srpaulo	if (cc != buf.st_size)
93190214Srpaulo		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
94190214Srpaulo
95190214Srpaulo	close(fd);
96190214Srpaulo	/* replace "# comment" with spaces */
97190214Srpaulo	for (i = 0; i < cc; i++) {
98190214Srpaulo		if (cp[i] == '#')
99190214Srpaulo			while (i < cc && cp[i] != '\n')
100190214Srpaulo				cp[i++] = ' ';
101190214Srpaulo	}
102190214Srpaulo	cp[cc] = '\0';
103190214Srpaulo	return (cp);
104190214Srpaulo}
105190214Srpaulo
106190214Srpaulo/* VARARGS */
107190214Srpaulostatic void
108190214Srpauloerror(const char *fmt, ...)
109190214Srpaulo{
110190214Srpaulo	va_list ap;
111190214Srpaulo
112190214Srpaulo	(void)fprintf(stderr, "%s: ", program_name);
113190214Srpaulo	va_start(ap, fmt);
114190214Srpaulo	(void)vfprintf(stderr, fmt, ap);
115190214Srpaulo	va_end(ap);
116190214Srpaulo	if (*fmt) {
117190214Srpaulo		fmt += strlen(fmt);
118190214Srpaulo		if (fmt[-1] != '\n')
119190214Srpaulo			(void)fputc('\n', stderr);
120190214Srpaulo	}
121190214Srpaulo	exit(1);
122190214Srpaulo	/* NOTREACHED */
123190214Srpaulo}
124190214Srpaulo
125190214Srpaulo/*
126190214Srpaulo * Copy arg vector into a new buffer, concatenating arguments with spaces.
127190214Srpaulo */
128190214Srpaulostatic char *
129190214Srpaulocopy_argv(register char **argv)
130190214Srpaulo{
131190214Srpaulo	register char **p;
132190214Srpaulo	register u_int len = 0;
133190214Srpaulo	char *buf;
134190214Srpaulo	char *src, *dst;
135190214Srpaulo
136190214Srpaulo	p = argv;
137190214Srpaulo	if (*p == 0)
138190214Srpaulo		return 0;
139190214Srpaulo
140190214Srpaulo	while (*p)
141190214Srpaulo		len += strlen(*p++) + 1;
142190214Srpaulo
143190214Srpaulo	buf = (char *)malloc(len);
144190214Srpaulo	if (buf == NULL)
145190214Srpaulo		error("copy_argv: malloc");
146190214Srpaulo
147190214Srpaulo	p = argv;
148190214Srpaulo	dst = buf;
149190214Srpaulo	while ((src = *p++) != NULL) {
150190214Srpaulo		while ((*dst++ = *src++) != '\0')
151190214Srpaulo			;
152190214Srpaulo		dst[-1] = ' ';
153190214Srpaulo	}
154190214Srpaulo	dst[-1] = '\0';
155190214Srpaulo
156190214Srpaulo	return buf;
157190214Srpaulo}
158190214Srpaulo
159190214Srpauloint
160190214Srpaulomain(int argc, char **argv)
161190214Srpaulo{
162190214Srpaulo	char *cp;
163190214Srpaulo	int op;
164190214Srpaulo	int dflag;
165190214Srpaulo	char *infile;
166190214Srpaulo	int Oflag;
167190214Srpaulo	long snaplen;
168190214Srpaulo	int dlt;
169214455Srpaulo	bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN;
170190214Srpaulo	char *cmdbuf;
171190214Srpaulo	pcap_t *pd;
172190214Srpaulo	struct bpf_program fcode;
173190214Srpaulo
174190214Srpaulo#ifdef WIN32
175190214Srpaulo	if(wsockinit() != 0) return 1;
176190214Srpaulo#endif /* WIN32 */
177190214Srpaulo
178190214Srpaulo	dflag = 1;
179190214Srpaulo	infile = NULL;
180190214Srpaulo	Oflag = 1;
181190214Srpaulo	snaplen = 68;
182190214Srpaulo
183190214Srpaulo	if ((cp = strrchr(argv[0], '/')) != NULL)
184190214Srpaulo		program_name = cp + 1;
185190214Srpaulo	else
186190214Srpaulo		program_name = argv[0];
187190214Srpaulo
188190214Srpaulo	opterr = 0;
189214455Srpaulo	while ((op = getopt(argc, argv, "dF:m:Os:")) != -1) {
190190214Srpaulo		switch (op) {
191190214Srpaulo
192190214Srpaulo		case 'd':
193190214Srpaulo			++dflag;
194190214Srpaulo			break;
195190214Srpaulo
196190214Srpaulo		case 'F':
197190214Srpaulo			infile = optarg;
198190214Srpaulo			break;
199190214Srpaulo
200190214Srpaulo		case 'O':
201190214Srpaulo			Oflag = 0;
202190214Srpaulo			break;
203190214Srpaulo
204214455Srpaulo		case 'm': {
205214455Srpaulo			in_addr_t addr;
206214455Srpaulo
207214455Srpaulo			addr = inet_addr(optarg);
208214455Srpaulo			if (addr == INADDR_NONE)
209214455Srpaulo				error("invalid netmask %s", optarg);
210214455Srpaulo			netmask = addr;
211214455Srpaulo			break;
212214455Srpaulo		}
213214455Srpaulo
214190214Srpaulo		case 's': {
215190214Srpaulo			char *end;
216190214Srpaulo
217190214Srpaulo			snaplen = strtol(optarg, &end, 0);
218190214Srpaulo			if (optarg == end || *end != '\0'
219190214Srpaulo			    || snaplen < 0 || snaplen > 65535)
220190214Srpaulo				error("invalid snaplen %s", optarg);
221190214Srpaulo			else if (snaplen == 0)
222190214Srpaulo				snaplen = 65535;
223190214Srpaulo			break;
224190214Srpaulo		}
225190214Srpaulo
226190214Srpaulo		default:
227190214Srpaulo			usage();
228190214Srpaulo			/* NOTREACHED */
229190214Srpaulo		}
230190214Srpaulo	}
231190214Srpaulo
232190214Srpaulo	if (optind >= argc) {
233190214Srpaulo		usage();
234190214Srpaulo		/* NOTREACHED */
235190214Srpaulo	}
236190214Srpaulo
237190214Srpaulo	dlt = pcap_datalink_name_to_val(argv[optind]);
238190214Srpaulo	if (dlt < 0)
239190214Srpaulo		error("invalid data link type %s", argv[optind]);
240190214Srpaulo
241190214Srpaulo	if (infile)
242190214Srpaulo		cmdbuf = read_infile(infile);
243190214Srpaulo	else
244190214Srpaulo		cmdbuf = copy_argv(&argv[optind+1]);
245190214Srpaulo
246190214Srpaulo	pd = pcap_open_dead(dlt, snaplen);
247190214Srpaulo	if (pd == NULL)
248190214Srpaulo		error("Can't open fake pcap_t");
249190214Srpaulo
250214455Srpaulo	if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
251190214Srpaulo		error("%s", pcap_geterr(pd));
252190214Srpaulo	bpf_dump(&fcode, dflag);
253190214Srpaulo	pcap_close(pd);
254190214Srpaulo	exit(0);
255190214Srpaulo}
256190214Srpaulo
257190214Srpaulostatic void
258190214Srpaulousage(void)
259190214Srpaulo{
260190214Srpaulo	(void)fprintf(stderr, "%s, with %s\n", program_name,
261190214Srpaulo	    pcap_lib_version());
262190214Srpaulo	(void)fprintf(stderr,
263214455Srpaulo	    "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
264190214Srpaulo	    program_name);
265190214Srpaulo	exit(1);
266190214Srpaulo}
267