1214455Srpaulo/*
2214455Srpaulo * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3214455Srpaulo *	The Regents of the University of California.  All rights reserved.
4214455Srpaulo *
5214455Srpaulo * Redistribution and use in source and binary forms, with or without
6214455Srpaulo * modification, are permitted provided that: (1) source code distributions
7214455Srpaulo * retain the above copyright notice and this paragraph in its entirety, (2)
8214455Srpaulo * distributions including binary code include the above copyright notice and
9214455Srpaulo * this paragraph in its entirety in the documentation or other materials
10214455Srpaulo * provided with the distribution, and (3) all advertising materials mentioning
11214455Srpaulo * features or use of this software display the following acknowledgement:
12214455Srpaulo * ``This product includes software developed by the University of California,
13214455Srpaulo * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14214455Srpaulo * the University nor the names of its contributors may be used to endorse
15214455Srpaulo * or promote products derived from this software without specific prior
16214455Srpaulo * written permission.
17214455Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18214455Srpaulo * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19214455Srpaulo * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20214455Srpaulo */
21214455Srpaulo
22214455Srpaulo#ifndef lint
23214455Srpaulostatic const char copyright[] =
24214455Srpaulo    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
25214455SrpauloThe Regents of the University of California.  All rights reserved.\n";
26214455Srpaulo#endif
27214455Srpaulo
28214455Srpaulo#include <pcap.h>
29214455Srpaulo#include <stdio.h>
30214455Srpaulo#include <stdlib.h>
31214455Srpaulo#include <string.h>
32214455Srpaulo#include <stdarg.h>
33214455Srpaulo#include <unistd.h>
34214455Srpaulo#include <errno.h>
35214455Srpaulo
36214455Srpaulo#define MAXIMUM_SNAPLEN		65535
37214455Srpaulo
38214455Srpaulostatic char *program_name;
39214455Srpaulo
40214455Srpaulo/* Forwards */
41214455Srpaulostatic void usage(void) __attribute__((noreturn));
42214455Srpaulostatic void error(const char *, ...);
43214455Srpaulostatic void warning(const char *, ...);
44214455Srpaulo
45214455Srpauloextern int optind;
46214455Srpauloextern int opterr;
47214455Srpauloextern char *optarg;
48214455Srpaulo
49214455Srpauloint
50214455Srpaulomain(int argc, char **argv)
51214455Srpaulo{
52214455Srpaulo	register int op;
53214455Srpaulo	register char *cp, *device;
54214455Srpaulo	int dorfmon, dopromisc, snaplen, useactivate, bufsize;
55214455Srpaulo	char ebuf[PCAP_ERRBUF_SIZE];
56214455Srpaulo	pcap_t *pd;
57214455Srpaulo	int status = 0;
58214455Srpaulo
59214455Srpaulo	device = NULL;
60214455Srpaulo	dorfmon = 0;
61214455Srpaulo	dopromisc = 0;
62214455Srpaulo	snaplen = MAXIMUM_SNAPLEN;
63214455Srpaulo	bufsize = 0;
64214455Srpaulo	useactivate = 0;
65214455Srpaulo	if ((cp = strrchr(argv[0], '/')) != NULL)
66214455Srpaulo		program_name = cp + 1;
67214455Srpaulo	else
68214455Srpaulo		program_name = argv[0];
69214455Srpaulo
70214455Srpaulo	opterr = 0;
71214455Srpaulo	while ((op = getopt(argc, argv, "i:Ips:aB:")) != -1) {
72214455Srpaulo		switch (op) {
73214455Srpaulo
74214455Srpaulo		case 'i':
75214455Srpaulo			device = optarg;
76214455Srpaulo			break;
77214455Srpaulo
78214455Srpaulo		case 'I':
79214455Srpaulo			dorfmon = 1;
80214455Srpaulo			useactivate = 1;	/* required for rfmon */
81214455Srpaulo			break;
82214455Srpaulo
83214455Srpaulo		case 'p':
84214455Srpaulo			dopromisc = 1;
85214455Srpaulo			break;
86214455Srpaulo
87214455Srpaulo		case 's': {
88214455Srpaulo			char *end;
89214455Srpaulo
90214455Srpaulo			snaplen = strtol(optarg, &end, 0);
91214455Srpaulo			if (optarg == end || *end != '\0'
92214455Srpaulo			    || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
93214455Srpaulo				error("invalid snaplen %s", optarg);
94214455Srpaulo			else if (snaplen == 0)
95214455Srpaulo				snaplen = MAXIMUM_SNAPLEN;
96214455Srpaulo			break;
97214455Srpaulo		}
98214455Srpaulo
99214455Srpaulo		case 'B':
100214455Srpaulo			bufsize = atoi(optarg)*1024;
101214455Srpaulo			if (bufsize <= 0)
102214455Srpaulo				error("invalid packet buffer size %s", optarg);
103214455Srpaulo			useactivate = 1;	/* required for bufsize */
104214455Srpaulo			break;
105214455Srpaulo
106214455Srpaulo		case 'a':
107214455Srpaulo			useactivate = 1;
108214455Srpaulo			break;
109214455Srpaulo
110214455Srpaulo		default:
111214455Srpaulo			usage();
112214455Srpaulo			/* NOTREACHED */
113214455Srpaulo		}
114214455Srpaulo	}
115214455Srpaulo
116214455Srpaulo	if (useactivate) {
117214455Srpaulo		pd = pcap_create(device, ebuf);
118214455Srpaulo		if (pd == NULL)
119214455Srpaulo			error("%s", ebuf);
120214455Srpaulo		status = pcap_set_snaplen(pd, snaplen);
121214455Srpaulo		if (status != 0)
122214455Srpaulo			error("%s: pcap_set_snaplen failed: %s",
123214455Srpaulo			    device, pcap_statustostr(status));
124214455Srpaulo		if (dopromisc) {
125214455Srpaulo			status = pcap_set_promisc(pd, 1);
126214455Srpaulo			if (status != 0)
127214455Srpaulo				error("%s: pcap_set_promisc failed: %s",
128214455Srpaulo				    device, pcap_statustostr(status));
129214455Srpaulo		}
130214455Srpaulo		if (dorfmon) {
131214455Srpaulo			status = pcap_set_rfmon(pd, 1);
132214455Srpaulo			if (status != 0)
133214455Srpaulo				error("%s: pcap_set_rfmon failed: %s",
134214455Srpaulo				    device, pcap_statustostr(status));
135214455Srpaulo		}
136214455Srpaulo		status = pcap_set_timeout(pd, 1000);
137214455Srpaulo		if (status != 0)
138214455Srpaulo			error("%s: pcap_set_timeout failed: %s",
139214455Srpaulo			    device, pcap_statustostr(status));
140214455Srpaulo		if (bufsize != 0) {
141214455Srpaulo			status = pcap_set_buffer_size(pd, bufsize);
142214455Srpaulo			if (status != 0)
143214455Srpaulo				error("%s: pcap_set_buffer_size failed: %s",
144214455Srpaulo				    device, pcap_statustostr(status));
145214455Srpaulo		}
146214455Srpaulo		status = pcap_activate(pd);
147214455Srpaulo		if (status < 0) {
148214455Srpaulo			/*
149214455Srpaulo			 * pcap_activate() failed.
150214455Srpaulo			 */
151214455Srpaulo			error("%s: %s\n(%s)", device,
152214455Srpaulo			    pcap_statustostr(status), pcap_geterr(pd));
153214455Srpaulo		} else if (status > 0) {
154214455Srpaulo			/*
155214455Srpaulo			 * pcap_activate() succeeded, but it's warning us
156214455Srpaulo			 * of a problem it had.
157214455Srpaulo			 */
158214455Srpaulo			warning("%s: %s\n(%s)", device,
159214455Srpaulo			    pcap_statustostr(status), pcap_geterr(pd));
160214455Srpaulo		}
161214455Srpaulo	} else {
162214455Srpaulo		*ebuf = '\0';
163214455Srpaulo		pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
164214455Srpaulo		if (pd == NULL)
165214455Srpaulo			error("%s", ebuf);
166214455Srpaulo		else if (*ebuf)
167214455Srpaulo			warning("%s", ebuf);
168214455Srpaulo	}
169214455Srpaulo	pcap_close(pd);
170214455Srpaulo	exit(status < 0 ? 1 : 0);
171214455Srpaulo}
172214455Srpaulo
173214455Srpaulostatic void
174214455Srpaulousage(void)
175214455Srpaulo{
176214455Srpaulo	(void)fprintf(stderr,
177214455Srpaulo	    "Usage: %s [ -Ipa ] [ -i interface ] [ -s snaplen ] [ -B bufsize ]\n",
178214455Srpaulo	    program_name);
179214455Srpaulo	exit(1);
180214455Srpaulo}
181214455Srpaulo
182214455Srpaulo/* VARARGS */
183214455Srpaulostatic void
184214455Srpauloerror(const char *fmt, ...)
185214455Srpaulo{
186214455Srpaulo	va_list ap;
187214455Srpaulo
188214455Srpaulo	(void)fprintf(stderr, "%s: ", program_name);
189214455Srpaulo	va_start(ap, fmt);
190214455Srpaulo	(void)vfprintf(stderr, fmt, ap);
191214455Srpaulo	va_end(ap);
192214455Srpaulo	if (*fmt) {
193214455Srpaulo		fmt += strlen(fmt);
194214455Srpaulo		if (fmt[-1] != '\n')
195214455Srpaulo			(void)fputc('\n', stderr);
196214455Srpaulo	}
197214455Srpaulo	exit(1);
198214455Srpaulo	/* NOTREACHED */
199214455Srpaulo}
200214455Srpaulo
201214455Srpaulo/* VARARGS */
202214455Srpaulostatic void
203214455Srpaulowarning(const char *fmt, ...)
204214455Srpaulo{
205214455Srpaulo	va_list ap;
206214455Srpaulo
207214455Srpaulo	(void)fprintf(stderr, "%s: WARNING: ", program_name);
208214455Srpaulo	va_start(ap, fmt);
209214455Srpaulo	(void)vfprintf(stderr, fmt, ap);
210214455Srpaulo	va_end(ap);
211214455Srpaulo	if (*fmt) {
212214455Srpaulo		fmt += strlen(fmt);
213214455Srpaulo		if (fmt[-1] != '\n')
214214455Srpaulo			(void)fputc('\n', stderr);
215214455Srpaulo	}
216214455Srpaulo}
217