1*6f9cba8fSJoseph Mingrone /*
2*6f9cba8fSJoseph Mingrone * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3*6f9cba8fSJoseph Mingrone * The Regents of the University of California. All rights reserved.
4*6f9cba8fSJoseph Mingrone *
5*6f9cba8fSJoseph Mingrone * Redistribution and use in source and binary forms, with or without
6*6f9cba8fSJoseph Mingrone * modification, are permitted provided that: (1) source code distributions
7*6f9cba8fSJoseph Mingrone * retain the above copyright notice and this paragraph in its entirety, (2)
8*6f9cba8fSJoseph Mingrone * distributions including binary code include the above copyright notice and
9*6f9cba8fSJoseph Mingrone * this paragraph in its entirety in the documentation or other materials
10*6f9cba8fSJoseph Mingrone * provided with the distribution, and (3) all advertising materials mentioning
11*6f9cba8fSJoseph Mingrone * features or use of this software display the following acknowledgement:
12*6f9cba8fSJoseph Mingrone * ``This product includes software developed by the University of California,
13*6f9cba8fSJoseph Mingrone * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*6f9cba8fSJoseph Mingrone * the University nor the names of its contributors may be used to endorse
15*6f9cba8fSJoseph Mingrone * or promote products derived from this software without specific prior
16*6f9cba8fSJoseph Mingrone * written permission.
17*6f9cba8fSJoseph Mingrone * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*6f9cba8fSJoseph Mingrone * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*6f9cba8fSJoseph Mingrone * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*6f9cba8fSJoseph Mingrone */
21*6f9cba8fSJoseph Mingrone
22*6f9cba8fSJoseph Mingrone #include "varattrs.h"
23*6f9cba8fSJoseph Mingrone
24*6f9cba8fSJoseph Mingrone #ifndef lint
25*6f9cba8fSJoseph Mingrone static const char copyright[] _U_ =
26*6f9cba8fSJoseph Mingrone "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
27*6f9cba8fSJoseph Mingrone The Regents of the University of California. All rights reserved.\n";
28*6f9cba8fSJoseph Mingrone #endif
29*6f9cba8fSJoseph Mingrone
30*6f9cba8fSJoseph Mingrone #include <stdio.h>
31*6f9cba8fSJoseph Mingrone #include <stdlib.h>
32*6f9cba8fSJoseph Mingrone #include <string.h>
33*6f9cba8fSJoseph Mingrone #include <stdarg.h>
34*6f9cba8fSJoseph Mingrone #include <limits.h>
35*6f9cba8fSJoseph Mingrone #ifdef _WIN32
36*6f9cba8fSJoseph Mingrone #include "getopt.h"
37*6f9cba8fSJoseph Mingrone #else
38*6f9cba8fSJoseph Mingrone #include <unistd.h>
39*6f9cba8fSJoseph Mingrone #endif
40*6f9cba8fSJoseph Mingrone #include <errno.h>
41*6f9cba8fSJoseph Mingrone #ifndef _WIN32
42*6f9cba8fSJoseph Mingrone #include <signal.h>
43*6f9cba8fSJoseph Mingrone #endif
44*6f9cba8fSJoseph Mingrone #include <sys/types.h>
45*6f9cba8fSJoseph Mingrone
46*6f9cba8fSJoseph Mingrone #include <pcap.h>
47*6f9cba8fSJoseph Mingrone
48*6f9cba8fSJoseph Mingrone #include "pcap/funcattrs.h"
49*6f9cba8fSJoseph Mingrone
50*6f9cba8fSJoseph Mingrone #ifdef _WIN32
51*6f9cba8fSJoseph Mingrone #include "portability.h"
52*6f9cba8fSJoseph Mingrone #endif
53*6f9cba8fSJoseph Mingrone
54*6f9cba8fSJoseph Mingrone static char *program_name;
55*6f9cba8fSJoseph Mingrone
56*6f9cba8fSJoseph Mingrone /* Forwards */
57*6f9cba8fSJoseph Mingrone static void PCAP_NORETURN usage(void);
58*6f9cba8fSJoseph Mingrone static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
59*6f9cba8fSJoseph Mingrone static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
60*6f9cba8fSJoseph Mingrone static char *copy_argv(char **);
61*6f9cba8fSJoseph Mingrone
62*6f9cba8fSJoseph Mingrone static pcap_t *pd;
63*6f9cba8fSJoseph Mingrone
64*6f9cba8fSJoseph Mingrone #ifdef _WIN32
65*6f9cba8fSJoseph Mingrone static BOOL WINAPI
stop_capture(DWORD ctrltype _U_)66*6f9cba8fSJoseph Mingrone stop_capture(DWORD ctrltype _U_)
67*6f9cba8fSJoseph Mingrone {
68*6f9cba8fSJoseph Mingrone pcap_breakloop(pd);
69*6f9cba8fSJoseph Mingrone return TRUE;
70*6f9cba8fSJoseph Mingrone }
71*6f9cba8fSJoseph Mingrone #else
72*6f9cba8fSJoseph Mingrone static void
stop_capture(int signum _U_)73*6f9cba8fSJoseph Mingrone stop_capture(int signum _U_)
74*6f9cba8fSJoseph Mingrone {
75*6f9cba8fSJoseph Mingrone pcap_breakloop(pd);
76*6f9cba8fSJoseph Mingrone }
77*6f9cba8fSJoseph Mingrone #endif
78*6f9cba8fSJoseph Mingrone
79*6f9cba8fSJoseph Mingrone static long
parse_interface_number(const char * device)80*6f9cba8fSJoseph Mingrone parse_interface_number(const char *device)
81*6f9cba8fSJoseph Mingrone {
82*6f9cba8fSJoseph Mingrone const char *p;
83*6f9cba8fSJoseph Mingrone long devnum;
84*6f9cba8fSJoseph Mingrone char *end;
85*6f9cba8fSJoseph Mingrone
86*6f9cba8fSJoseph Mingrone /*
87*6f9cba8fSJoseph Mingrone * Search for a colon, terminating any scheme at the beginning
88*6f9cba8fSJoseph Mingrone * of the device.
89*6f9cba8fSJoseph Mingrone */
90*6f9cba8fSJoseph Mingrone p = strchr(device, ':');
91*6f9cba8fSJoseph Mingrone if (p != NULL) {
92*6f9cba8fSJoseph Mingrone /*
93*6f9cba8fSJoseph Mingrone * We found it. Is it followed by "//"?
94*6f9cba8fSJoseph Mingrone */
95*6f9cba8fSJoseph Mingrone p++; /* skip the : */
96*6f9cba8fSJoseph Mingrone if (strncmp(p, "//", 2) == 0) {
97*6f9cba8fSJoseph Mingrone /*
98*6f9cba8fSJoseph Mingrone * Yes. Search for the next /, at the end of the
99*6f9cba8fSJoseph Mingrone * authority part of the URL.
100*6f9cba8fSJoseph Mingrone */
101*6f9cba8fSJoseph Mingrone p += 2; /* skip the // */
102*6f9cba8fSJoseph Mingrone p = strchr(p, '/');
103*6f9cba8fSJoseph Mingrone if (p != NULL) {
104*6f9cba8fSJoseph Mingrone /*
105*6f9cba8fSJoseph Mingrone * OK, past the / is the path.
106*6f9cba8fSJoseph Mingrone */
107*6f9cba8fSJoseph Mingrone device = p + 1;
108*6f9cba8fSJoseph Mingrone }
109*6f9cba8fSJoseph Mingrone }
110*6f9cba8fSJoseph Mingrone }
111*6f9cba8fSJoseph Mingrone devnum = strtol(device, &end, 10);
112*6f9cba8fSJoseph Mingrone if (device != end && *end == '\0') {
113*6f9cba8fSJoseph Mingrone /*
114*6f9cba8fSJoseph Mingrone * It's all-numeric, but is it a valid number?
115*6f9cba8fSJoseph Mingrone */
116*6f9cba8fSJoseph Mingrone if (devnum <= 0) {
117*6f9cba8fSJoseph Mingrone /*
118*6f9cba8fSJoseph Mingrone * No, it's not an ordinal.
119*6f9cba8fSJoseph Mingrone */
120*6f9cba8fSJoseph Mingrone error("Invalid adapter index");
121*6f9cba8fSJoseph Mingrone }
122*6f9cba8fSJoseph Mingrone return (devnum);
123*6f9cba8fSJoseph Mingrone } else {
124*6f9cba8fSJoseph Mingrone /*
125*6f9cba8fSJoseph Mingrone * It's not all-numeric; return -1, so our caller
126*6f9cba8fSJoseph Mingrone * knows that.
127*6f9cba8fSJoseph Mingrone */
128*6f9cba8fSJoseph Mingrone return (-1);
129*6f9cba8fSJoseph Mingrone }
130*6f9cba8fSJoseph Mingrone }
131*6f9cba8fSJoseph Mingrone
132*6f9cba8fSJoseph Mingrone static char *
find_interface_by_number(long devnum)133*6f9cba8fSJoseph Mingrone find_interface_by_number(long devnum)
134*6f9cba8fSJoseph Mingrone {
135*6f9cba8fSJoseph Mingrone pcap_if_t *dev, *devlist;
136*6f9cba8fSJoseph Mingrone long i;
137*6f9cba8fSJoseph Mingrone char ebuf[PCAP_ERRBUF_SIZE];
138*6f9cba8fSJoseph Mingrone char *device;
139*6f9cba8fSJoseph Mingrone int status;
140*6f9cba8fSJoseph Mingrone
141*6f9cba8fSJoseph Mingrone status = pcap_findalldevs(&devlist, ebuf);
142*6f9cba8fSJoseph Mingrone if (status < 0)
143*6f9cba8fSJoseph Mingrone error("%s", ebuf);
144*6f9cba8fSJoseph Mingrone /*
145*6f9cba8fSJoseph Mingrone * Look for the devnum-th entry in the list of devices (1-based).
146*6f9cba8fSJoseph Mingrone */
147*6f9cba8fSJoseph Mingrone for (i = 0, dev = devlist; i < devnum-1 && dev != NULL;
148*6f9cba8fSJoseph Mingrone i++, dev = dev->next)
149*6f9cba8fSJoseph Mingrone ;
150*6f9cba8fSJoseph Mingrone if (dev == NULL)
151*6f9cba8fSJoseph Mingrone error("Invalid adapter index");
152*6f9cba8fSJoseph Mingrone device = strdup(dev->name);
153*6f9cba8fSJoseph Mingrone pcap_freealldevs(devlist);
154*6f9cba8fSJoseph Mingrone return (device);
155*6f9cba8fSJoseph Mingrone }
156*6f9cba8fSJoseph Mingrone
157*6f9cba8fSJoseph Mingrone static pcap_t *
open_interface(const char * device,int snaplen_set,int snaplen,char * ebuf)158*6f9cba8fSJoseph Mingrone open_interface(const char *device, int snaplen_set, int snaplen, char *ebuf)
159*6f9cba8fSJoseph Mingrone {
160*6f9cba8fSJoseph Mingrone pcap_t *pc;
161*6f9cba8fSJoseph Mingrone int status;
162*6f9cba8fSJoseph Mingrone char *cp;
163*6f9cba8fSJoseph Mingrone
164*6f9cba8fSJoseph Mingrone pc = pcap_create(device, ebuf);
165*6f9cba8fSJoseph Mingrone if (pc == NULL) {
166*6f9cba8fSJoseph Mingrone /*
167*6f9cba8fSJoseph Mingrone * If this failed with "No such device", that means
168*6f9cba8fSJoseph Mingrone * the interface doesn't exist; return NULL, so that
169*6f9cba8fSJoseph Mingrone * the caller can see whether the device name is
170*6f9cba8fSJoseph Mingrone * actually an interface index.
171*6f9cba8fSJoseph Mingrone */
172*6f9cba8fSJoseph Mingrone if (strstr(ebuf, "No such device") != NULL)
173*6f9cba8fSJoseph Mingrone return (NULL);
174*6f9cba8fSJoseph Mingrone error("%s", ebuf);
175*6f9cba8fSJoseph Mingrone }
176*6f9cba8fSJoseph Mingrone if (snaplen_set) {
177*6f9cba8fSJoseph Mingrone status = pcap_set_snaplen(pc, snaplen);
178*6f9cba8fSJoseph Mingrone if (status != 0)
179*6f9cba8fSJoseph Mingrone error("%s: pcap_set_snaplen failed: %s",
180*6f9cba8fSJoseph Mingrone device, pcap_statustostr(status));
181*6f9cba8fSJoseph Mingrone }
182*6f9cba8fSJoseph Mingrone status = pcap_set_timeout(pc, 100);
183*6f9cba8fSJoseph Mingrone if (status != 0)
184*6f9cba8fSJoseph Mingrone error("%s: pcap_set_timeout failed: %s",
185*6f9cba8fSJoseph Mingrone device, pcap_statustostr(status));
186*6f9cba8fSJoseph Mingrone status = pcap_activate(pc);
187*6f9cba8fSJoseph Mingrone if (status < 0) {
188*6f9cba8fSJoseph Mingrone /*
189*6f9cba8fSJoseph Mingrone * pcap_activate() failed.
190*6f9cba8fSJoseph Mingrone */
191*6f9cba8fSJoseph Mingrone cp = pcap_geterr(pc);
192*6f9cba8fSJoseph Mingrone if (status == PCAP_ERROR)
193*6f9cba8fSJoseph Mingrone error("%s", cp);
194*6f9cba8fSJoseph Mingrone else if (status == PCAP_ERROR_NO_SUCH_DEVICE) {
195*6f9cba8fSJoseph Mingrone /*
196*6f9cba8fSJoseph Mingrone * Return an error for our caller to handle.
197*6f9cba8fSJoseph Mingrone */
198*6f9cba8fSJoseph Mingrone snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
199*6f9cba8fSJoseph Mingrone device, pcap_statustostr(status), cp);
200*6f9cba8fSJoseph Mingrone } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
201*6f9cba8fSJoseph Mingrone error("%s: %s\n(%s)", device,
202*6f9cba8fSJoseph Mingrone pcap_statustostr(status), cp);
203*6f9cba8fSJoseph Mingrone else
204*6f9cba8fSJoseph Mingrone error("%s: %s", device,
205*6f9cba8fSJoseph Mingrone pcap_statustostr(status));
206*6f9cba8fSJoseph Mingrone pcap_close(pc);
207*6f9cba8fSJoseph Mingrone return (NULL);
208*6f9cba8fSJoseph Mingrone } else if (status > 0) {
209*6f9cba8fSJoseph Mingrone /*
210*6f9cba8fSJoseph Mingrone * pcap_activate() succeeded, but it's warning us
211*6f9cba8fSJoseph Mingrone * of a problem it had.
212*6f9cba8fSJoseph Mingrone */
213*6f9cba8fSJoseph Mingrone cp = pcap_geterr(pc);
214*6f9cba8fSJoseph Mingrone if (status == PCAP_WARNING)
215*6f9cba8fSJoseph Mingrone warning("%s", cp);
216*6f9cba8fSJoseph Mingrone else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
217*6f9cba8fSJoseph Mingrone *cp != '\0')
218*6f9cba8fSJoseph Mingrone warning("%s: %s\n(%s)", device,
219*6f9cba8fSJoseph Mingrone pcap_statustostr(status), cp);
220*6f9cba8fSJoseph Mingrone else
221*6f9cba8fSJoseph Mingrone warning("%s: %s", device,
222*6f9cba8fSJoseph Mingrone pcap_statustostr(status));
223*6f9cba8fSJoseph Mingrone }
224*6f9cba8fSJoseph Mingrone return (pc);
225*6f9cba8fSJoseph Mingrone }
226*6f9cba8fSJoseph Mingrone
227*6f9cba8fSJoseph Mingrone #define COMMAND_OPTIONS "DLi:s:w:y:"
228*6f9cba8fSJoseph Mingrone
229*6f9cba8fSJoseph Mingrone int
main(int argc,char ** argv)230*6f9cba8fSJoseph Mingrone main(int argc, char **argv)
231*6f9cba8fSJoseph Mingrone {
232*6f9cba8fSJoseph Mingrone int op;
233*6f9cba8fSJoseph Mingrone char *cp, *cmdbuf = NULL, *device, *end, *savefile = NULL;
234*6f9cba8fSJoseph Mingrone int snaplen = 0;
235*6f9cba8fSJoseph Mingrone int snaplen_set = 0;
236*6f9cba8fSJoseph Mingrone pcap_if_t *devlist;
237*6f9cba8fSJoseph Mingrone long devnum;
238*6f9cba8fSJoseph Mingrone int show_interfaces = 0;
239*6f9cba8fSJoseph Mingrone int show_dlt_types = 0;
240*6f9cba8fSJoseph Mingrone int ndlts;
241*6f9cba8fSJoseph Mingrone int *dlts;
242*6f9cba8fSJoseph Mingrone bpf_u_int32 localnet, netmask;
243*6f9cba8fSJoseph Mingrone struct bpf_program fcode;
244*6f9cba8fSJoseph Mingrone char ebuf[PCAP_ERRBUF_SIZE];
245*6f9cba8fSJoseph Mingrone #ifndef _WIN32
246*6f9cba8fSJoseph Mingrone struct sigaction action;
247*6f9cba8fSJoseph Mingrone #endif
248*6f9cba8fSJoseph Mingrone int dlt;
249*6f9cba8fSJoseph Mingrone const char *dlt_name = NULL;
250*6f9cba8fSJoseph Mingrone int status;
251*6f9cba8fSJoseph Mingrone pcap_dumper_t *pdd;
252*6f9cba8fSJoseph Mingrone
253*6f9cba8fSJoseph Mingrone device = NULL;
254*6f9cba8fSJoseph Mingrone if ((cp = strrchr(argv[0], '/')) != NULL)
255*6f9cba8fSJoseph Mingrone program_name = cp + 1;
256*6f9cba8fSJoseph Mingrone else
257*6f9cba8fSJoseph Mingrone program_name = argv[0];
258*6f9cba8fSJoseph Mingrone
259*6f9cba8fSJoseph Mingrone opterr = 0;
260*6f9cba8fSJoseph Mingrone while ((op = getopt(argc, argv, COMMAND_OPTIONS)) != -1) {
261*6f9cba8fSJoseph Mingrone switch (op) {
262*6f9cba8fSJoseph Mingrone
263*6f9cba8fSJoseph Mingrone case 'D':
264*6f9cba8fSJoseph Mingrone show_interfaces = 1;
265*6f9cba8fSJoseph Mingrone break;
266*6f9cba8fSJoseph Mingrone
267*6f9cba8fSJoseph Mingrone case 'L':
268*6f9cba8fSJoseph Mingrone show_dlt_types = 1;
269*6f9cba8fSJoseph Mingrone break;
270*6f9cba8fSJoseph Mingrone
271*6f9cba8fSJoseph Mingrone case 'i':
272*6f9cba8fSJoseph Mingrone device = optarg;
273*6f9cba8fSJoseph Mingrone break;
274*6f9cba8fSJoseph Mingrone
275*6f9cba8fSJoseph Mingrone case 's':
276*6f9cba8fSJoseph Mingrone snaplen = (int)strtol(optarg, &end, 0);
277*6f9cba8fSJoseph Mingrone if (optarg == end || *end != '\0' || snaplen < 0)
278*6f9cba8fSJoseph Mingrone error("invalid snaplen %s (must be >= 0)",
279*6f9cba8fSJoseph Mingrone optarg);
280*6f9cba8fSJoseph Mingrone snaplen_set = 1;
281*6f9cba8fSJoseph Mingrone break;
282*6f9cba8fSJoseph Mingrone
283*6f9cba8fSJoseph Mingrone case 'w':
284*6f9cba8fSJoseph Mingrone savefile = optarg;
285*6f9cba8fSJoseph Mingrone break;
286*6f9cba8fSJoseph Mingrone
287*6f9cba8fSJoseph Mingrone case 'y':
288*6f9cba8fSJoseph Mingrone dlt_name = optarg;
289*6f9cba8fSJoseph Mingrone break;
290*6f9cba8fSJoseph Mingrone
291*6f9cba8fSJoseph Mingrone default:
292*6f9cba8fSJoseph Mingrone usage();
293*6f9cba8fSJoseph Mingrone /* NOTREACHED */
294*6f9cba8fSJoseph Mingrone }
295*6f9cba8fSJoseph Mingrone }
296*6f9cba8fSJoseph Mingrone
297*6f9cba8fSJoseph Mingrone if (show_interfaces) {
298*6f9cba8fSJoseph Mingrone pcap_if_t *dev;
299*6f9cba8fSJoseph Mingrone int i;
300*6f9cba8fSJoseph Mingrone
301*6f9cba8fSJoseph Mingrone if (pcap_findalldevs(&devlist, ebuf) < 0)
302*6f9cba8fSJoseph Mingrone error("%s", ebuf);
303*6f9cba8fSJoseph Mingrone for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) {
304*6f9cba8fSJoseph Mingrone printf("%d.%s", i+1, dev->name);
305*6f9cba8fSJoseph Mingrone if (dev->description != NULL)
306*6f9cba8fSJoseph Mingrone printf(" (%s)", dev->description);
307*6f9cba8fSJoseph Mingrone printf("\n");
308*6f9cba8fSJoseph Mingrone }
309*6f9cba8fSJoseph Mingrone pcap_freealldevs(devlist);
310*6f9cba8fSJoseph Mingrone return (0);
311*6f9cba8fSJoseph Mingrone }
312*6f9cba8fSJoseph Mingrone
313*6f9cba8fSJoseph Mingrone if (device == NULL) {
314*6f9cba8fSJoseph Mingrone if (pcap_findalldevs(&devlist, ebuf) == -1)
315*6f9cba8fSJoseph Mingrone error("%s", ebuf);
316*6f9cba8fSJoseph Mingrone if (devlist == NULL)
317*6f9cba8fSJoseph Mingrone error("no interfaces available for capture");
318*6f9cba8fSJoseph Mingrone device = strdup(devlist->name);
319*6f9cba8fSJoseph Mingrone pcap_freealldevs(devlist);
320*6f9cba8fSJoseph Mingrone }
321*6f9cba8fSJoseph Mingrone if (show_dlt_types) {
322*6f9cba8fSJoseph Mingrone pd = pcap_create(device, ebuf);
323*6f9cba8fSJoseph Mingrone if (pd == NULL)
324*6f9cba8fSJoseph Mingrone error("%s", ebuf);
325*6f9cba8fSJoseph Mingrone status = pcap_activate(pd);
326*6f9cba8fSJoseph Mingrone if (status < 0) {
327*6f9cba8fSJoseph Mingrone /*
328*6f9cba8fSJoseph Mingrone * pcap_activate() failed.
329*6f9cba8fSJoseph Mingrone */
330*6f9cba8fSJoseph Mingrone error("%s: %s\n(%s)", device,
331*6f9cba8fSJoseph Mingrone pcap_statustostr(status), pcap_geterr(pd));
332*6f9cba8fSJoseph Mingrone }
333*6f9cba8fSJoseph Mingrone ndlts = pcap_list_datalinks(pd, &dlts);
334*6f9cba8fSJoseph Mingrone if (ndlts < 0) {
335*6f9cba8fSJoseph Mingrone /*
336*6f9cba8fSJoseph Mingrone * pcap_list_datalinks() failed.
337*6f9cba8fSJoseph Mingrone */
338*6f9cba8fSJoseph Mingrone error("%s: %s\n(%s)", device,
339*6f9cba8fSJoseph Mingrone pcap_statustostr(status), pcap_geterr(pd));
340*6f9cba8fSJoseph Mingrone }
341*6f9cba8fSJoseph Mingrone for (int i = 0; i < ndlts; i++) {
342*6f9cba8fSJoseph Mingrone dlt_name = pcap_datalink_val_to_name(dlts[i]);
343*6f9cba8fSJoseph Mingrone if (dlt_name == NULL)
344*6f9cba8fSJoseph Mingrone printf("DLT %d", dlts[i]);
345*6f9cba8fSJoseph Mingrone else
346*6f9cba8fSJoseph Mingrone printf("%s", dlt_name);
347*6f9cba8fSJoseph Mingrone printf("\n");
348*6f9cba8fSJoseph Mingrone }
349*6f9cba8fSJoseph Mingrone pcap_free_datalinks(dlts);
350*6f9cba8fSJoseph Mingrone pcap_close(pd);
351*6f9cba8fSJoseph Mingrone return 0;
352*6f9cba8fSJoseph Mingrone }
353*6f9cba8fSJoseph Mingrone
354*6f9cba8fSJoseph Mingrone if (savefile == NULL)
355*6f9cba8fSJoseph Mingrone error("no savefile specified");
356*6f9cba8fSJoseph Mingrone
357*6f9cba8fSJoseph Mingrone *ebuf = '\0';
358*6f9cba8fSJoseph Mingrone
359*6f9cba8fSJoseph Mingrone pd = open_interface(device, snaplen_set, snaplen, ebuf);
360*6f9cba8fSJoseph Mingrone if (pd == NULL) {
361*6f9cba8fSJoseph Mingrone /*
362*6f9cba8fSJoseph Mingrone * That failed because the interface couldn't be found.
363*6f9cba8fSJoseph Mingrone *
364*6f9cba8fSJoseph Mingrone * If we can get a list of interfaces, and the interface name
365*6f9cba8fSJoseph Mingrone * is purely numeric, try to use it as a 1-based index
366*6f9cba8fSJoseph Mingrone * in the list of interfaces.
367*6f9cba8fSJoseph Mingrone */
368*6f9cba8fSJoseph Mingrone devnum = parse_interface_number(device);
369*6f9cba8fSJoseph Mingrone if (devnum == -1) {
370*6f9cba8fSJoseph Mingrone /*
371*6f9cba8fSJoseph Mingrone * It's not a number; just report
372*6f9cba8fSJoseph Mingrone * the open error and fail.
373*6f9cba8fSJoseph Mingrone */
374*6f9cba8fSJoseph Mingrone error("%s", ebuf);
375*6f9cba8fSJoseph Mingrone }
376*6f9cba8fSJoseph Mingrone
377*6f9cba8fSJoseph Mingrone /*
378*6f9cba8fSJoseph Mingrone * OK, it's a number; try to find the
379*6f9cba8fSJoseph Mingrone * interface with that index, and try
380*6f9cba8fSJoseph Mingrone * to open it.
381*6f9cba8fSJoseph Mingrone *
382*6f9cba8fSJoseph Mingrone * find_interface_by_number() exits if it
383*6f9cba8fSJoseph Mingrone * couldn't be found.
384*6f9cba8fSJoseph Mingrone */
385*6f9cba8fSJoseph Mingrone device = find_interface_by_number(devnum);
386*6f9cba8fSJoseph Mingrone pd = open_interface(device, snaplen_set, snaplen, ebuf);
387*6f9cba8fSJoseph Mingrone if (pd == NULL)
388*6f9cba8fSJoseph Mingrone error("%s", ebuf);
389*6f9cba8fSJoseph Mingrone }
390*6f9cba8fSJoseph Mingrone
391*6f9cba8fSJoseph Mingrone if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
392*6f9cba8fSJoseph Mingrone localnet = 0;
393*6f9cba8fSJoseph Mingrone netmask = 0;
394*6f9cba8fSJoseph Mingrone warning("%s", ebuf);
395*6f9cba8fSJoseph Mingrone }
396*6f9cba8fSJoseph Mingrone
397*6f9cba8fSJoseph Mingrone if (dlt_name != NULL) {
398*6f9cba8fSJoseph Mingrone dlt = pcap_datalink_name_to_val(dlt_name);
399*6f9cba8fSJoseph Mingrone if (dlt == PCAP_ERROR)
400*6f9cba8fSJoseph Mingrone error("%s isn't a valid DLT name", dlt_name);
401*6f9cba8fSJoseph Mingrone if (pcap_set_datalink(pd, dlt) == PCAP_ERROR)
402*6f9cba8fSJoseph Mingrone error("%s: %s", device, pcap_geterr(pd));
403*6f9cba8fSJoseph Mingrone }
404*6f9cba8fSJoseph Mingrone
405*6f9cba8fSJoseph Mingrone /*
406*6f9cba8fSJoseph Mingrone * Don't set a filter unless we were given one on the
407*6f9cba8fSJoseph Mingrone * command line; if capturing doesn't work, or doesn't
408*6f9cba8fSJoseph Mingrone * use the snapshot length, without a filter, that's
409*6f9cba8fSJoseph Mingrone * a bug.
410*6f9cba8fSJoseph Mingrone */
411*6f9cba8fSJoseph Mingrone if (optind < argc) {
412*6f9cba8fSJoseph Mingrone cmdbuf = copy_argv(&argv[optind]);
413*6f9cba8fSJoseph Mingrone
414*6f9cba8fSJoseph Mingrone if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
415*6f9cba8fSJoseph Mingrone error("%s", pcap_geterr(pd));
416*6f9cba8fSJoseph Mingrone
417*6f9cba8fSJoseph Mingrone if (pcap_setfilter(pd, &fcode) < 0)
418*6f9cba8fSJoseph Mingrone error("%s", pcap_geterr(pd));
419*6f9cba8fSJoseph Mingrone }
420*6f9cba8fSJoseph Mingrone
421*6f9cba8fSJoseph Mingrone pdd = pcap_dump_open(pd, savefile);
422*6f9cba8fSJoseph Mingrone if (pdd == NULL)
423*6f9cba8fSJoseph Mingrone error("%s", pcap_geterr(pd));
424*6f9cba8fSJoseph Mingrone
425*6f9cba8fSJoseph Mingrone #ifdef _WIN32
426*6f9cba8fSJoseph Mingrone SetConsoleCtrlHandler(stop_capture, TRUE);
427*6f9cba8fSJoseph Mingrone #else
428*6f9cba8fSJoseph Mingrone action.sa_handler = stop_capture;
429*6f9cba8fSJoseph Mingrone sigemptyset(&action.sa_mask);
430*6f9cba8fSJoseph Mingrone action.sa_flags = 0;
431*6f9cba8fSJoseph Mingrone if (sigaction(SIGINT, &action, NULL) == -1)
432*6f9cba8fSJoseph Mingrone error("Can't catch SIGINT: %s\n", strerror(errno));
433*6f9cba8fSJoseph Mingrone #endif
434*6f9cba8fSJoseph Mingrone
435*6f9cba8fSJoseph Mingrone printf("Listening on %s, link-type ", device);
436*6f9cba8fSJoseph Mingrone dlt = pcap_datalink(pd);
437*6f9cba8fSJoseph Mingrone dlt_name = pcap_datalink_val_to_name(dlt);
438*6f9cba8fSJoseph Mingrone if (dlt_name == NULL)
439*6f9cba8fSJoseph Mingrone printf("DLT %d", dlt);
440*6f9cba8fSJoseph Mingrone else
441*6f9cba8fSJoseph Mingrone printf("%s", dlt_name);
442*6f9cba8fSJoseph Mingrone printf("\n");
443*6f9cba8fSJoseph Mingrone for (;;) {
444*6f9cba8fSJoseph Mingrone status = pcap_dispatch(pd, -1, pcap_dump, (u_char *)pdd);
445*6f9cba8fSJoseph Mingrone if (status < 0)
446*6f9cba8fSJoseph Mingrone break;
447*6f9cba8fSJoseph Mingrone if (status != 0) {
448*6f9cba8fSJoseph Mingrone printf("%d packets seen\n", status);
449*6f9cba8fSJoseph Mingrone struct pcap_stat ps;
450*6f9cba8fSJoseph Mingrone pcap_stats(pd, &ps);
451*6f9cba8fSJoseph Mingrone printf("%d ps_recv, %d ps_drop, %d ps_ifdrop\n",
452*6f9cba8fSJoseph Mingrone ps.ps_recv, ps.ps_drop, ps.ps_ifdrop);
453*6f9cba8fSJoseph Mingrone }
454*6f9cba8fSJoseph Mingrone }
455*6f9cba8fSJoseph Mingrone if (status == -2) {
456*6f9cba8fSJoseph Mingrone /*
457*6f9cba8fSJoseph Mingrone * We got interrupted, so perhaps we didn't
458*6f9cba8fSJoseph Mingrone * manage to finish a line we were printing.
459*6f9cba8fSJoseph Mingrone * Print an extra newline, just in case.
460*6f9cba8fSJoseph Mingrone */
461*6f9cba8fSJoseph Mingrone putchar('\n');
462*6f9cba8fSJoseph Mingrone printf("Broken out of loop from SIGINT handler\n");
463*6f9cba8fSJoseph Mingrone }
464*6f9cba8fSJoseph Mingrone (void)fflush(stdout);
465*6f9cba8fSJoseph Mingrone if (status == -1) {
466*6f9cba8fSJoseph Mingrone /*
467*6f9cba8fSJoseph Mingrone * Error. Report it.
468*6f9cba8fSJoseph Mingrone */
469*6f9cba8fSJoseph Mingrone (void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
470*6f9cba8fSJoseph Mingrone program_name, pcap_geterr(pd));
471*6f9cba8fSJoseph Mingrone }
472*6f9cba8fSJoseph Mingrone pcap_close(pd);
473*6f9cba8fSJoseph Mingrone if (cmdbuf != NULL) {
474*6f9cba8fSJoseph Mingrone pcap_freecode(&fcode);
475*6f9cba8fSJoseph Mingrone free(cmdbuf);
476*6f9cba8fSJoseph Mingrone }
477*6f9cba8fSJoseph Mingrone exit(status == -1 ? 1 : 0);
478*6f9cba8fSJoseph Mingrone }
479*6f9cba8fSJoseph Mingrone
480*6f9cba8fSJoseph Mingrone static void
usage(void)481*6f9cba8fSJoseph Mingrone usage(void)
482*6f9cba8fSJoseph Mingrone {
483*6f9cba8fSJoseph Mingrone (void)fprintf(stderr, "Usage: %s -D -L [ -i interface ] [ -s snaplen ] [ -w file ] [ -y dlt ] [expression]\n",
484*6f9cba8fSJoseph Mingrone program_name);
485*6f9cba8fSJoseph Mingrone exit(1);
486*6f9cba8fSJoseph Mingrone }
487*6f9cba8fSJoseph Mingrone
488*6f9cba8fSJoseph Mingrone /* VARARGS */
489*6f9cba8fSJoseph Mingrone static void
error(const char * fmt,...)490*6f9cba8fSJoseph Mingrone error(const char *fmt, ...)
491*6f9cba8fSJoseph Mingrone {
492*6f9cba8fSJoseph Mingrone va_list ap;
493*6f9cba8fSJoseph Mingrone
494*6f9cba8fSJoseph Mingrone (void)fprintf(stderr, "%s: ", program_name);
495*6f9cba8fSJoseph Mingrone va_start(ap, fmt);
496*6f9cba8fSJoseph Mingrone (void)vfprintf(stderr, fmt, ap);
497*6f9cba8fSJoseph Mingrone va_end(ap);
498*6f9cba8fSJoseph Mingrone if (*fmt) {
499*6f9cba8fSJoseph Mingrone fmt += strlen(fmt);
500*6f9cba8fSJoseph Mingrone if (fmt[-1] != '\n')
501*6f9cba8fSJoseph Mingrone (void)fputc('\n', stderr);
502*6f9cba8fSJoseph Mingrone }
503*6f9cba8fSJoseph Mingrone exit(1);
504*6f9cba8fSJoseph Mingrone /* NOTREACHED */
505*6f9cba8fSJoseph Mingrone }
506*6f9cba8fSJoseph Mingrone
507*6f9cba8fSJoseph Mingrone /* VARARGS */
508*6f9cba8fSJoseph Mingrone static void
warning(const char * fmt,...)509*6f9cba8fSJoseph Mingrone warning(const char *fmt, ...)
510*6f9cba8fSJoseph Mingrone {
511*6f9cba8fSJoseph Mingrone va_list ap;
512*6f9cba8fSJoseph Mingrone
513*6f9cba8fSJoseph Mingrone (void)fprintf(stderr, "%s: WARNING: ", program_name);
514*6f9cba8fSJoseph Mingrone va_start(ap, fmt);
515*6f9cba8fSJoseph Mingrone (void)vfprintf(stderr, fmt, ap);
516*6f9cba8fSJoseph Mingrone va_end(ap);
517*6f9cba8fSJoseph Mingrone if (*fmt) {
518*6f9cba8fSJoseph Mingrone fmt += strlen(fmt);
519*6f9cba8fSJoseph Mingrone if (fmt[-1] != '\n')
520*6f9cba8fSJoseph Mingrone (void)fputc('\n', stderr);
521*6f9cba8fSJoseph Mingrone }
522*6f9cba8fSJoseph Mingrone }
523*6f9cba8fSJoseph Mingrone
524*6f9cba8fSJoseph Mingrone /*
525*6f9cba8fSJoseph Mingrone * Copy arg vector into a new buffer, concatenating arguments with spaces.
526*6f9cba8fSJoseph Mingrone */
527*6f9cba8fSJoseph Mingrone static char *
copy_argv(register char ** argv)528*6f9cba8fSJoseph Mingrone copy_argv(register char **argv)
529*6f9cba8fSJoseph Mingrone {
530*6f9cba8fSJoseph Mingrone register char **p;
531*6f9cba8fSJoseph Mingrone register size_t len = 0;
532*6f9cba8fSJoseph Mingrone char *buf;
533*6f9cba8fSJoseph Mingrone char *src, *dst;
534*6f9cba8fSJoseph Mingrone
535*6f9cba8fSJoseph Mingrone p = argv;
536*6f9cba8fSJoseph Mingrone if (*p == 0)
537*6f9cba8fSJoseph Mingrone return 0;
538*6f9cba8fSJoseph Mingrone
539*6f9cba8fSJoseph Mingrone while (*p)
540*6f9cba8fSJoseph Mingrone len += strlen(*p++) + 1;
541*6f9cba8fSJoseph Mingrone
542*6f9cba8fSJoseph Mingrone buf = (char *)malloc(len);
543*6f9cba8fSJoseph Mingrone if (buf == NULL)
544*6f9cba8fSJoseph Mingrone error("copy_argv: malloc");
545*6f9cba8fSJoseph Mingrone
546*6f9cba8fSJoseph Mingrone p = argv;
547*6f9cba8fSJoseph Mingrone dst = buf;
548*6f9cba8fSJoseph Mingrone while ((src = *p++) != NULL) {
549*6f9cba8fSJoseph Mingrone while ((*dst++ = *src++) != '\0')
550*6f9cba8fSJoseph Mingrone ;
551*6f9cba8fSJoseph Mingrone dst[-1] = ' ';
552*6f9cba8fSJoseph Mingrone }
553*6f9cba8fSJoseph Mingrone dst[-1] = '\0';
554*6f9cba8fSJoseph Mingrone
555*6f9cba8fSJoseph Mingrone return buf;
556*6f9cba8fSJoseph Mingrone }
557