source: rtems-libbsd/freebsd/contrib/tcpdump/tcpdump.c @ 21abaef

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 21abaef was 21abaef, checked in by Christian Mauderer <Christian.Mauderer@…>, on Jul 15, 2016 at 5:32:56 AM

freebsd: Don't use new wrappers for old ports.

Some of the commands have been adapted manually. So the wrapper
currently don't necessarily work as expected. For example ifconfig calls
malloc outside of the program call.

  • Property mode set to 100644
File size: 56.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 *
23 * Support for splitting captures into multiple files with a maximum
24 * file size:
25 *
26 * Copyright (c) 2001
27 *      Seth Webster <swebster@sst.ll.mit.edu>
28 */
29
30#if 0
31#ifndef lint
32static const char copyright[] _U_ =
33    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
34The Regents of the University of California.  All rights reserved.\n";
35static const char rcsid[] _U_ =
36    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.283 2008-09-25 21:45:50 guy Exp $ (LBL)";
37#endif
38#endif
39
40/* $FreeBSD$ */
41
42#ifdef __rtems__
43#define __need_getopt_newlib
44#include <getopt.h>
45#define setpriority(a, b, c)
46#define RTEMS_BSD_PROGRAM_NO_OPEN_WRAP
47#define RTEMS_BSD_PROGRAM_NO_SOCKET_WRAP
48#define RTEMS_BSD_PROGRAM_NO_CLOSE_WRAP
49#define RTEMS_BSD_PROGRAM_NO_FOPEN_WRAP
50#define RTEMS_BSD_PROGRAM_NO_FCLOSE_WRAP
51#define RTEMS_BSD_PROGRAM_NO_MALLOC_WRAP
52#define RTEMS_BSD_PROGRAM_NO_CALLOC_WRAP
53#define RTEMS_BSD_PROGRAM_NO_REALLOC_WRAP
54#define RTEMS_BSD_PROGRAM_NO_FREE_WRAP
55#include <machine/rtems-bsd-program.h>
56#include <machine/rtems-bsd-commands.h>
57#include <rtems.h>
58#endif /* __rtems__ */
59
60/*
61 * tcpdump - monitor tcp/ip traffic on an ethernet.
62 *
63 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
64 * Mercilessly hacked and occasionally improved since then via the
65 * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
66 */
67
68#ifdef HAVE_CONFIG_H
69#include "config.h"
70#endif
71
72#include <tcpdump-stdinc.h>
73
74#ifdef WIN32
75#include "getopt.h"
76#include "w32_fzs.h"
77extern int strcasecmp (const char *__s1, const char *__s2);
78extern int SIZE_BUF;
79#define off_t long
80#define uint UINT
81#endif /* WIN32 */
82
83#ifdef HAVE_SMI_H
84#include <smi.h>
85#endif
86
87#include <pcap.h>
88#include <signal.h>
89#include <stdio.h>
90#include <stdlib.h>
91#include <string.h>
92#include <limits.h>
93#ifndef WIN32
94#include <sys/wait.h>
95#include <rtems/bsd/sys/resource.h>
96#include <pwd.h>
97#include <grp.h>
98#include <errno.h>
99#endif /* WIN32 */
100
101/* capabilities convinience library */
102#ifdef HAVE_CAP_NG_H
103#include <cap-ng.h>
104#endif /* HAVE_CAP_NG_H */
105
106#include "netdissect.h"
107#include "interface.h"
108#include "addrtoname.h"
109#include "machdep.h"
110#include "setsignal.h"
111#include "gmt2local.h"
112#include "pcap-missing.h"
113
114#ifndef PATH_MAX
115#define PATH_MAX 1024
116#endif
117
118#ifdef SIGINFO
119#define SIGNAL_REQ_INFO SIGINFO
120#elif SIGUSR1
121#define SIGNAL_REQ_INFO SIGUSR1
122#endif
123
124#ifdef __rtems__
125/*
126 * Run the PCAP loop in a separate task and have the shell thread block on the
127 * input.
128 */
129typedef struct
130{
131    volatile bool running;
132    pcap_t *pd;
133    int cnt;
134    pcap_handler cb;
135    u_char *ud;
136    int ret;
137} rtems_pcap_loop_args;
138
139static void
140rtems_pcap_loop_thread (rtems_task_argument arg)
141{
142    rtems_pcap_loop_args* pcap_loop_arg = (rtems_pcap_loop_args*) arg;
143
144    pcap_loop_arg->ret = pcap_loop(pcap_loop_arg->pd,
145                                   pcap_loop_arg->cnt,
146                                   pcap_loop_arg->cb,
147                                   pcap_loop_arg->ud);
148
149    pcap_loop_arg->running = false;
150
151    rtems_task_delete(RTEMS_SELF);
152}
153
154static int
155rtems_pcap_loop(pcap_t *pd, int cnt, pcap_handler cb, u_char *ud)
156{
157    rtems_status_code   sc;
158    rtems_task_priority priority;
159    rtems_name          name;
160    rtems_id            id;
161
162    rtems_pcap_loop_args pcap_loop_args;
163
164    pcap_loop_args.running = true;
165    pcap_loop_args.pd = pd;
166    pcap_loop_args.cnt = cnt;
167    pcap_loop_args.cb = cb;
168    pcap_loop_args.ud = ud;
169    pcap_loop_args.ret = 0;
170
171    sc = rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
172
173    if (sc != RTEMS_SUCCESSFUL) {
174        fprintf(stderr, "error: cannot get current priority: %s\n",
175                rtems_status_text (sc));
176        return -1;
177    }
178
179    name = rtems_build_name('T', 'C', 'P', 'D');
180
181    sc = rtems_task_create (name, priority, 8 * 1024,
182                            RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
183                            RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
184                            &id);
185
186    if (sc != RTEMS_SUCCESSFUL)
187    {
188        fprintf(stderr, "error: cannot create helper thread: %s\n",
189                rtems_status_text (sc));
190        return -1;
191    }
192
193    sc = rtems_task_start (id,
194                           rtems_pcap_loop_thread,
195                           &pcap_loop_args);
196    if (sc != RTEMS_SUCCESSFUL)
197    {
198        fprintf(stderr, "error: cannot start helper thread: %s\n",
199                rtems_status_text (sc));
200        rtems_task_delete (id);
201        return -1;
202    }
203
204    printf("Press ENTER to end\n");
205
206    while (true)
207    {
208        int c = getchar ();
209
210        if ((c == '\r') || (c == '\n') || (c == 'q') || (c == 'Q'))
211        {
212            pcap_breakloop(pd);
213            while (true)
214            {
215                if (!pcap_loop_args.running)
216                    break;
217                usleep(10000);
218            }
219            break;
220        }
221    }
222
223    return pcap_loop_args.ret;
224}
225#define pcap_loop rtems_pcap_loop
226#endif /* __rtems__ */
227
228netdissect_options Gndo;
229netdissect_options *gndo = &Gndo;
230
231static int dflag;                       /* print filter code */
232static int Lflag;                       /* list available data link types and exit */
233#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
234static int Jflag;                       /* list available time stamp types */
235#endif
236static char *zflag = NULL;              /* compress each savefile using a specified command (like gzip or bzip2) */
237
238static int infodelay;
239static int infoprint;
240
241char *program_name;
242
243int32_t thiszone;               /* seconds offset from gmt to local time */
244
245/* Forwards */
246static RETSIGTYPE cleanup(int);
247static RETSIGTYPE child_cleanup(int);
248static void usage(void) __attribute__((noreturn));
249static void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn));
250
251static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
252static void ndo_default_print(netdissect_options *, const u_char *, u_int);
253static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);
254static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
255static void droproot(const char *, const char *);
256static void ndo_error(netdissect_options *ndo, const char *fmt, ...)
257     __attribute__ ((noreturn, format (printf, 2, 3)));
258static void ndo_warning(netdissect_options *ndo, const char *fmt, ...);
259
260#ifdef SIGNAL_REQ_INFO
261RETSIGTYPE requestinfo(int);
262#endif
263
264#if defined(USE_WIN32_MM_TIMER)
265  #include <MMsystem.h>
266  static UINT timer_id;
267  static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR);
268#elif defined(HAVE_ALARM)
269  static void verbose_stats_dump(int sig);
270#endif
271
272static void info(int);
273static u_int packets_captured;
274
275struct printer {
276        if_printer f;
277        int type;
278};
279
280
281struct ndo_printer {
282        if_ndo_printer f;
283        int type;
284};
285
286
287static const struct printer printers[] = {
288#if !__rtems__
289        { arcnet_if_print,      DLT_ARCNET },
290#endif
291#ifdef DLT_ARCNET_LINUX
292        { arcnet_linux_if_print, DLT_ARCNET_LINUX },
293#endif
294#if !__rtems__
295        { token_if_print,       DLT_IEEE802 },
296#endif
297#ifdef DLT_LANE8023
298        { lane_if_print,        DLT_LANE8023 },
299#endif
300#ifdef DLT_CIP
301        { cip_if_print,         DLT_CIP },
302#endif
303#ifdef DLT_ATM_CLIP
304        { cip_if_print,         DLT_ATM_CLIP },
305#endif
306        { sl_if_print,          DLT_SLIP },
307#ifdef DLT_SLIP_BSDOS
308        { sl_bsdos_if_print,    DLT_SLIP_BSDOS },
309#endif
310        { ppp_if_print,         DLT_PPP },
311#ifdef DLT_PPP_WITHDIRECTION
312        { ppp_if_print,         DLT_PPP_WITHDIRECTION },
313#endif
314#ifdef DLT_PPP_BSDOS
315        { ppp_bsdos_if_print,   DLT_PPP_BSDOS },
316#endif
317#if !__rtems__
318        { fddi_if_print,        DLT_FDDI },
319#endif
320        { null_if_print,        DLT_NULL },
321#ifdef DLT_LOOP
322        { null_if_print,        DLT_LOOP },
323#endif
324        { raw_if_print,         DLT_RAW },
325#if !__rtems__
326        { atm_if_print,         DLT_ATM_RFC1483 },
327#endif
328#ifdef DLT_C_HDLC
329        { chdlc_if_print,       DLT_C_HDLC },
330#endif
331#ifdef DLT_HDLC
332        { chdlc_if_print,       DLT_HDLC },
333#endif
334#ifdef DLT_PPP_SERIAL
335        { ppp_hdlc_if_print,    DLT_PPP_SERIAL },
336#endif
337#ifdef DLT_PPP_ETHER
338        { pppoe_if_print,       DLT_PPP_ETHER },
339#endif
340#ifdef DLT_LINUX_SLL
341        { sll_if_print,         DLT_LINUX_SLL },
342#endif
343#ifdef DLT_IEEE802_11
344        { ieee802_11_if_print,  DLT_IEEE802_11},
345#endif
346#ifdef DLT_LTALK
347        { ltalk_if_print,       DLT_LTALK },
348#endif
349#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H)
350        { pflog_if_print,       DLT_PFLOG },
351#endif
352#ifdef DLT_FR
353        { fr_if_print,          DLT_FR },
354#endif
355#ifdef DLT_FRELAY
356        { fr_if_print,          DLT_FRELAY },
357#endif
358#ifdef DLT_SUNATM
359        { sunatm_if_print,      DLT_SUNATM },
360#endif
361#ifdef DLT_IP_OVER_FC
362        { ipfc_if_print,        DLT_IP_OVER_FC },
363#endif
364#ifdef DLT_PRISM_HEADER
365        { prism_if_print,       DLT_PRISM_HEADER },
366#endif
367#ifdef DLT_IEEE802_11_RADIO
368        { ieee802_11_radio_if_print,    DLT_IEEE802_11_RADIO },
369#endif
370#ifdef DLT_ENC
371        { enc_if_print,         DLT_ENC },
372#endif
373#ifdef DLT_SYMANTEC_FIREWALL
374        { symantec_if_print,    DLT_SYMANTEC_FIREWALL },
375#endif
376#ifdef DLT_APPLE_IP_OVER_IEEE1394
377        { ap1394_if_print,      DLT_APPLE_IP_OVER_IEEE1394 },
378#endif
379#ifdef DLT_IEEE802_11_RADIO_AVS
380        { ieee802_11_radio_avs_if_print,        DLT_IEEE802_11_RADIO_AVS },
381#endif
382#ifdef DLT_JUNIPER_ATM1
383        { juniper_atm1_print,   DLT_JUNIPER_ATM1 },
384#endif
385#ifdef DLT_JUNIPER_ATM2
386        { juniper_atm2_print,   DLT_JUNIPER_ATM2 },
387#endif
388#ifdef DLT_JUNIPER_MFR
389        { juniper_mfr_print,    DLT_JUNIPER_MFR },
390#endif
391#ifdef DLT_JUNIPER_MLFR
392        { juniper_mlfr_print,   DLT_JUNIPER_MLFR },
393#endif
394#ifdef DLT_JUNIPER_MLPPP
395        { juniper_mlppp_print,  DLT_JUNIPER_MLPPP },
396#endif
397#ifdef DLT_JUNIPER_PPPOE
398        { juniper_pppoe_print,  DLT_JUNIPER_PPPOE },
399#endif
400#ifdef DLT_JUNIPER_PPPOE_ATM
401        { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },
402#endif
403#ifdef DLT_JUNIPER_GGSN
404        { juniper_ggsn_print,   DLT_JUNIPER_GGSN },
405#endif
406#ifdef DLT_JUNIPER_ES
407        { juniper_es_print,     DLT_JUNIPER_ES },
408#endif
409#ifdef DLT_JUNIPER_MONITOR
410        { juniper_monitor_print, DLT_JUNIPER_MONITOR },
411#endif
412#ifdef DLT_JUNIPER_SERVICES
413        { juniper_services_print, DLT_JUNIPER_SERVICES },
414#endif
415#ifdef DLT_JUNIPER_ETHER
416        { juniper_ether_print,  DLT_JUNIPER_ETHER },
417#endif
418#ifdef DLT_JUNIPER_PPP
419        { juniper_ppp_print,    DLT_JUNIPER_PPP },
420#endif
421#ifdef DLT_JUNIPER_FRELAY
422        { juniper_frelay_print, DLT_JUNIPER_FRELAY },
423#endif
424#ifdef DLT_JUNIPER_CHDLC
425        { juniper_chdlc_print,  DLT_JUNIPER_CHDLC },
426#endif
427#ifdef DLT_MFR
428        { mfr_if_print,         DLT_MFR },
429#endif
430#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
431        { bt_if_print,          DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
432#endif
433#ifdef HAVE_PCAP_USB_H
434#ifdef DLT_USB_LINUX
435        { usb_linux_48_byte_print, DLT_USB_LINUX},
436#endif /* DLT_USB_LINUX */
437#ifdef DLT_USB_LINUX_MMAPPED
438        { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED},
439#endif /* DLT_USB_LINUX_MMAPPED */
440#endif /* HAVE_PCAP_USB_H */
441#ifdef DLT_IPV4
442        { raw_if_print,         DLT_IPV4 },
443#endif
444#ifdef DLT_IPV6
445        { raw_if_print,         DLT_IPV6 },
446#endif
447        { NULL,                 0 },
448};
449
450static const struct ndo_printer ndo_printers[] = {
451        { ether_if_print,       DLT_EN10MB },
452#ifdef DLT_IPNET
453        { ipnet_if_print,       DLT_IPNET },
454#endif
455#ifdef DLT_IEEE802_15_4
456        { ieee802_15_4_if_print, DLT_IEEE802_15_4 },
457#endif
458#ifdef DLT_IEEE802_15_4_NOFCS
459        { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
460#endif
461#ifdef DLT_PPI
462        { ppi_if_print,         DLT_PPI },
463#endif
464#ifdef DLT_NETANALYZER
465        { netanalyzer_if_print, DLT_NETANALYZER },
466#endif
467#ifdef DLT_NETANALYZER_TRANSPARENT
468        { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
469#endif
470        { NULL,                 0 },
471};
472
473if_printer
474lookup_printer(int type)
475{
476        const struct printer *p;
477
478        for (p = printers; p->f; ++p)
479                if (type == p->type)
480                        return p->f;
481
482        return NULL;
483        /* NOTREACHED */
484}
485
486if_ndo_printer
487lookup_ndo_printer(int type)
488{
489        const struct ndo_printer *p;
490
491        for (p = ndo_printers; p->f; ++p)
492                if (type == p->type)
493                        return p->f;
494
495        return NULL;
496        /* NOTREACHED */
497}
498
499static pcap_t *pd;
500
501static int supports_monitor_mode;
502
503#ifdef __rtems__
504#define optind getopt_data.optind
505#define optarg getopt_data.optarg
506#define opterr getopt_data.opterr
507#define optopt getopt_data.optopt
508#define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data)
509#else
510extern int optind;
511extern int opterr;
512extern char *optarg;
513#endif
514
515struct print_info {
516        netdissect_options *ndo;
517        union {
518                if_printer     printer;
519                if_ndo_printer ndo_printer;
520        } p;
521        int ndo_type;
522};
523
524struct dump_info {
525        char    *WFileName;
526        char    *CurrentFileName;
527        pcap_t  *pd;
528        pcap_dumper_t *p;
529};
530
531#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
532static void
533show_tstamp_types_and_exit(const char *device, pcap_t *pd)
534{
535        int n_tstamp_types;
536        int *tstamp_types = 0;
537        const char *tstamp_type_name;
538        int i;
539
540        n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types);
541        if (n_tstamp_types < 0)
542                error("%s", pcap_geterr(pd));
543
544        if (n_tstamp_types == 0) {
545                fprintf(stderr, "Time stamp type cannot be set for %s\n",
546                    device);
547                exit(0);
548        }
549        fprintf(stderr, "Time stamp types for %s (use option -j to set):\n",
550            device);
551        for (i = 0; i < n_tstamp_types; i++) {
552                tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]);
553                if (tstamp_type_name != NULL) {
554                        (void) fprintf(stderr, "  %s (%s)\n", tstamp_type_name,
555                            pcap_tstamp_type_val_to_description(tstamp_types[i]));
556                } else {
557                        (void) fprintf(stderr, "  %d\n", tstamp_types[i]);
558                }
559        }
560        pcap_free_tstamp_types(tstamp_types);
561        exit(0);
562}
563#endif
564
565static void
566show_dlts_and_exit(const char *device, pcap_t *pd)
567{
568        int n_dlts;
569        int *dlts = 0;
570        const char *dlt_name;
571
572        n_dlts = pcap_list_datalinks(pd, &dlts);
573        if (n_dlts < 0)
574                error("%s", pcap_geterr(pd));
575        else if (n_dlts == 0 || !dlts)
576                error("No data link types.");
577
578        /*
579         * If the interface is known to support monitor mode, indicate
580         * whether these are the data link types available when not in
581         * monitor mode, if -I wasn't specified, or when in monitor mode,
582         * when -I was specified (the link-layer types available in
583         * monitor mode might be different from the ones available when
584         * not in monitor mode).
585         */
586        if (supports_monitor_mode)
587                (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n",
588                    device,
589                    Iflag ? "when in monitor mode" : "when not in monitor mode");
590        else
591                (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n",
592                    device);
593
594        while (--n_dlts >= 0) {
595                dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]);
596                if (dlt_name != NULL) {
597                        (void) fprintf(stderr, "  %s (%s)", dlt_name,
598                            pcap_datalink_val_to_description(dlts[n_dlts]));
599
600                        /*
601                         * OK, does tcpdump handle that type?
602                         */
603                        if (lookup_printer(dlts[n_dlts]) == NULL
604                            && lookup_ndo_printer(dlts[n_dlts]) == NULL)
605                                (void) fprintf(stderr, " (printing not supported)");
606                        fprintf(stderr, "\n");
607                } else {
608                        (void) fprintf(stderr, "  DLT %d (printing not supported)\n",
609                            dlts[n_dlts]);
610                }
611        }
612#ifdef HAVE_PCAP_FREE_DATALINKS
613        pcap_free_datalinks(dlts);
614#endif
615        exit(0);
616}
617
618/*
619 * Set up flags that might or might not be supported depending on the
620 * version of libpcap we're using.
621 */
622#if defined(HAVE_PCAP_CREATE) || defined(WIN32)
623#define B_FLAG          "B:"
624#define B_FLAG_USAGE    " [ -B size ]"
625#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
626#define B_FLAG
627#define B_FLAG_USAGE
628#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
629
630#ifdef HAVE_PCAP_CREATE
631#define I_FLAG          "I"
632#else /* HAVE_PCAP_CREATE */
633#define I_FLAG
634#endif /* HAVE_PCAP_CREATE */
635
636#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
637#define j_FLAG          "j:"
638#define j_FLAG_USAGE    " [ -j tstamptype ]"
639#define J_FLAG          "J"
640#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
641#define j_FLAG
642#define j_FLAG_USAGE
643#define J_FLAG
644#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
645
646#ifdef HAVE_PCAP_FINDALLDEVS
647#ifndef HAVE_PCAP_IF_T
648#undef HAVE_PCAP_FINDALLDEVS
649#endif
650#endif
651
652#ifdef HAVE_PCAP_FINDALLDEVS
653#define D_FLAG  "D"
654#else
655#define D_FLAG
656#endif
657
658#ifdef HAVE_PCAP_DUMP_FLUSH
659#define U_FLAG  "U"
660#else
661#define U_FLAG
662#endif
663
664#ifndef WIN32
665/* Drop root privileges and chroot if necessary */
666static void
667droproot(const char *username, const char *chroot_dir)
668{
669        struct passwd *pw = NULL;
670
671        if (chroot_dir && !username) {
672                fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n");
673                exit(1);
674        }
675
676        pw = getpwnam(username);
677        if (pw) {
678                if (chroot_dir) {
679                        if (chroot(chroot_dir) != 0 || chdir ("/") != 0) {
680                                fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n",
681                                    chroot_dir, pcap_strerror(errno));
682                                exit(1);
683                        }
684                }
685#ifdef HAVE_CAP_NG_H
686                int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG);
687                if (ret < 0) {
688                        printf("error : ret %d\n", ret);
689                }
690                /* We don't need CAP_SETUID and CAP_SETGID */
691                capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID);
692                capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID);
693                capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID);
694                capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID);
695                capng_apply(CAPNG_SELECT_BOTH);
696
697#else
698#ifndef __rtems__
699                if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
700                    setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
701                        fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
702                            username,
703                            (unsigned long)pw->pw_uid,
704                            (unsigned long)pw->pw_gid,
705                            pcap_strerror(errno));
706                        exit(1);
707                }
708#endif
709#endif /* HAVE_CAP_NG_H */
710        }
711        else {
712                fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n",
713                    username);
714                exit(1);
715        }
716}
717#endif /* WIN32 */
718
719static int
720getWflagChars(int x)
721{
722        int c = 0;
723
724        x -= 1;
725        while (x > 0) {
726                c += 1;
727                x /= 10;
728        }
729
730        return c;
731}
732
733
734static void
735MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
736{
737        char *filename = malloc(PATH_MAX + 1);
738        if (filename == NULL)
739            error("Makefilename: malloc");
740
741        /* Process with strftime if Gflag is set. */
742        if (Gflag != 0) {
743          struct tm *local_tm;
744
745          /* Convert Gflag_time to a usable format */
746          if ((local_tm = localtime(&Gflag_time)) == NULL) {
747                  error("MakeTimedFilename: localtime");
748          }
749
750          /* There's no good way to detect an error in strftime since a return
751           * value of 0 isn't necessarily failure.
752           */
753          strftime(filename, PATH_MAX, orig_name, local_tm);
754        } else {
755          strncpy(filename, orig_name, PATH_MAX);
756        }
757
758        if (cnt == 0 && max_chars == 0)
759                strncpy(buffer, filename, PATH_MAX + 1);
760        else
761                if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX)
762                  /* Report an error if the filename is too large */
763                  error("too many output files or filename is too long (> %d)", PATH_MAX);
764        free(filename);
765}
766
767static int tcpdump_printf(netdissect_options *ndo _U_,
768                          const char *fmt, ...)
769{
770
771  va_list args;
772  int ret;
773
774  va_start(args, fmt);
775  ret=vfprintf(stdout, fmt, args);
776  va_end(args);
777
778  return ret;
779}
780
781static struct print_info
782get_print_info(int type)
783{
784        struct print_info printinfo;
785
786        printinfo.ndo_type = 1;
787        printinfo.ndo = gndo;
788        printinfo.p.ndo_printer = lookup_ndo_printer(type);
789        if (printinfo.p.ndo_printer == NULL) {
790                printinfo.p.printer = lookup_printer(type);
791                printinfo.ndo_type = 0;
792                if (printinfo.p.printer == NULL) {
793                        gndo->ndo_dltname = pcap_datalink_val_to_name(type);
794                        if (gndo->ndo_dltname != NULL)
795                                error("packet printing is not supported for link type %s: use -w",
796                                      gndo->ndo_dltname);
797                        else
798                                error("packet printing is not supported for link type %d: use -w", type);
799                }
800        }
801        return (printinfo);
802}
803
804static char *
805get_next_file(FILE *VFile, char *ptr)
806{
807        char *ret;
808
809        ret = fgets(ptr, PATH_MAX, VFile);
810        if (!ret)
811                return NULL;
812
813        if (ptr[strlen(ptr) - 1] == '\n')
814                ptr[strlen(ptr) - 1] = '\0';
815
816        return ret;
817}
818
819#ifdef __rtems__
820static int main(int argc, char **argv);
821
822int rtems_bsd_command_tcpdump(int argc, char *argv[])
823{
824        int exit_code;
825
826        rtems_bsd_program_lock();
827
828  dflag = 0;
829  Lflag = 0;
830#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
831  Jflag = 0;
832#endif
833  zflag = NULL;
834  infodelay = 0;
835  infoprint = 0;
836  program_name = NULL;
837  thiszone = 0;
838  packets_captured = 0;
839  pd = 0;
840  supports_monitor_mode = 0;
841
842        exit_code = rtems_bsd_program_call_main("tcpdump", main, argc, argv);
843
844        rtems_bsd_program_unlock();
845
846        return exit_code;
847}
848#endif /* __rtems__ */
849int
850#ifndef __rtems__
851main(int argc, char *const *argv)
852#else /* __rtems__ */
853main(int argc, char **argv)
854#endif /* __rtems__ */
855{
856        register int cnt, op, i;
857        bpf_u_int32 localnet, netmask;
858        register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName;
859        pcap_handler callback;
860        int type;
861        int dlt;
862        int new_dlt;
863        const char *dlt_name;
864        struct bpf_program fcode;
865#ifndef WIN32
866        RETSIGTYPE (*oldhandler)(int);
867#endif
868        struct print_info printinfo;
869        struct dump_info dumpinfo;
870        u_char *pcap_userdata;
871        char ebuf[PCAP_ERRBUF_SIZE];
872        char VFileLine[PATH_MAX + 1];
873        char *username = NULL;
874        char *chroot_dir = NULL;
875        char *ret = NULL;
876        char *end;
877#ifdef HAVE_PCAP_FINDALLDEVS
878        pcap_if_t *devpointer;
879        int devnum;
880#endif
881        int status;
882        FILE *VFile;
883#ifdef __rtems__
884        struct getopt_data getopt_data;
885        memset(&getopt_data, 0, sizeof(getopt_data));
886#endif
887#ifdef WIN32
888        if(wsockinit() != 0) return 1;
889#endif /* WIN32 */
890
891        jflag=-1;       /* not set */
892        gndo->ndo_Oflag=1;
893        gndo->ndo_Rflag=1;
894        gndo->ndo_dlt=-1;
895        gndo->ndo_default_print=ndo_default_print;
896        gndo->ndo_printf=tcpdump_printf;
897        gndo->ndo_error=ndo_error;
898        gndo->ndo_warning=ndo_warning;
899        gndo->ndo_snaplen = DEFAULT_SNAPLEN;
900
901        cnt = -1;
902        device = NULL;
903        infile = NULL;
904        RFileName = NULL;
905        VFileName = NULL;
906        VFile = NULL;
907        WFileName = NULL;
908        dlt = -1;
909        if ((cp = strrchr(argv[0], '/')) != NULL)
910                program_name = cp + 1;
911        else
912                program_name = argv[0];
913
914        if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
915                error("%s", ebuf);
916
917#ifdef LIBSMI
918        smiInit("tcpdump");
919#endif
920
921        while (
922            (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "V:vw:W:xXy:Yz:Z:")) != -1)
923                switch (op) {
924
925                case 'a':
926                        /* compatibility for old -a */
927                        break;
928
929                case 'A':
930                        ++Aflag;
931                        break;
932
933                case 'b':
934                        ++bflag;
935                        break;
936
937#if defined(HAVE_PCAP_CREATE) || defined(WIN32)
938                case 'B':
939                        Bflag = atoi(optarg)*1024;
940                        if (Bflag <= 0)
941                                error("invalid packet buffer size %s", optarg);
942                        break;
943#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
944
945                case 'c':
946                        cnt = atoi(optarg);
947                        if (cnt <= 0)
948                                error("invalid packet count %s", optarg);
949                        break;
950
951                case 'C':
952                        Cflag = atoi(optarg) * 1000000;
953                        if (Cflag < 0)
954                                error("invalid file size %s", optarg);
955                        break;
956
957                case 'd':
958                        ++dflag;
959                        break;
960
961#ifdef HAVE_PCAP_FINDALLDEVS
962                case 'D':
963                        if (pcap_findalldevs(&devpointer, ebuf) < 0)
964                                error("%s", ebuf);
965                        else {
966                                for (i = 0; devpointer != 0; i++) {
967                                        printf("%d.%s", i+1, devpointer->name);
968                                        if (devpointer->description != NULL)
969                                                printf(" (%s)", devpointer->description);
970                                        printf("\n");
971                                        devpointer = devpointer->next;
972                                }
973                        }
974                        return 0;
975#endif /* HAVE_PCAP_FINDALLDEVS */
976
977                case 'L':
978                        Lflag++;
979                        break;
980
981                case 'e':
982                        ++eflag;
983                        break;
984
985                case 'E':
986#ifndef HAVE_LIBCRYPTO
987                        warning("crypto code not compiled in");
988#endif
989                        gndo->ndo_espsecret = optarg;
990                        break;
991
992                case 'f':
993                        ++fflag;
994                        break;
995
996                case 'F':
997                        infile = optarg;
998                        break;
999
1000                case 'G':
1001                        Gflag = atoi(optarg);
1002                        if (Gflag < 0)
1003                                error("invalid number of seconds %s", optarg);
1004
1005                        /* We will create one file initially. */
1006                        Gflag_count = 0;
1007
1008                        /* Grab the current time for rotation use. */
1009                        if ((Gflag_time = time(NULL)) == (time_t)-1) {
1010                                error("main: can't get current time: %s",
1011                                    pcap_strerror(errno));
1012                        }
1013                        break;
1014
1015                case 'h':
1016                        usage();
1017                        break;
1018
1019                case 'H':
1020                        ++Hflag;
1021                        break;
1022
1023                case 'i':
1024                        if (optarg[0] == '0' && optarg[1] == 0)
1025                                error("Invalid adapter index");
1026
1027#ifdef HAVE_PCAP_FINDALLDEVS
1028                        /*
1029                         * If the argument is a number, treat it as
1030                         * an index into the list of adapters, as
1031                         * printed by "tcpdump -D".
1032                         *
1033                         * This should be OK on UNIX systems, as interfaces
1034                         * shouldn't have names that begin with digits.
1035                         * It can be useful on Windows, where more than
1036                         * one interface can have the same name.
1037                         */
1038                        devnum = strtol(optarg, &end, 10);
1039                        if (optarg != end && *end == '\0') {
1040                                if (devnum < 0)
1041                                        error("Invalid adapter index");
1042
1043                                if (pcap_findalldevs(&devpointer, ebuf) < 0)
1044                                        error("%s", ebuf);
1045                                else {
1046                                        /*
1047                                         * Look for the devnum-th entry
1048                                         * in the list of devices
1049                                         * (1-based).
1050                                         */
1051                                        for (i = 0;
1052                                            i < devnum-1 && devpointer != NULL;
1053                                            i++, devpointer = devpointer->next)
1054                                                ;
1055                                        if (devpointer == NULL)
1056                                                error("Invalid adapter index");
1057                                }
1058                                device = devpointer->name;
1059                                break;
1060                        }
1061#endif /* HAVE_PCAP_FINDALLDEVS */
1062                        device = optarg;
1063                        break;
1064
1065#ifdef HAVE_PCAP_CREATE
1066                case 'I':
1067                        ++Iflag;
1068                        break;
1069#endif /* HAVE_PCAP_CREATE */
1070
1071#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
1072                case 'j':
1073                        jflag = pcap_tstamp_type_name_to_val(optarg);
1074                        if (jflag < 0)
1075                                error("invalid time stamp type %s", optarg);
1076                        break;
1077
1078                case 'J':
1079                        Jflag++;
1080                        break;
1081#endif
1082
1083                case 'l':
1084#ifdef WIN32
1085                        /*
1086                         * _IOLBF is the same as _IOFBF in Microsoft's C
1087                         * libraries; the only alternative they offer
1088                         * is _IONBF.
1089                         *
1090                         * XXX - this should really be checking for MSVC++,
1091                         * not WIN32, if, for example, MinGW has its own
1092                         * C library that is more UNIX-compatible.
1093                         */
1094                        setvbuf(stdout, NULL, _IONBF, 0);
1095#else /* WIN32 */
1096#ifdef HAVE_SETLINEBUF
1097                        setlinebuf(stdout);
1098#else
1099                        setvbuf(stdout, NULL, _IOLBF, 0);
1100#endif
1101#endif /* WIN32 */
1102                        break;
1103
1104                case 'K':
1105                        ++Kflag;
1106                        break;
1107
1108                case 'm':
1109#ifdef LIBSMI
1110                        if (smiLoadModule(optarg) == 0) {
1111                                error("could not load MIB module %s", optarg);
1112                        }
1113                        sflag = 1;
1114#else
1115                        (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
1116                                      program_name, optarg);
1117                        (void)fprintf(stderr, "(no libsmi support)\n");
1118#endif
1119                        break;
1120
1121                case 'M':
1122                        /* TCP-MD5 shared secret */
1123#ifndef HAVE_LIBCRYPTO
1124                        warning("crypto code not compiled in");
1125#endif
1126                        sigsecret = optarg;
1127                        break;
1128
1129                case 'n':
1130                        ++nflag;
1131                        break;
1132
1133                case 'N':
1134                        ++Nflag;
1135                        break;
1136
1137                case 'O':
1138                        Oflag = 0;
1139                        break;
1140
1141                case 'p':
1142                        ++pflag;
1143                        break;
1144
1145                case 'q':
1146                        ++qflag;
1147                        ++suppress_default_print;
1148                        break;
1149
1150                case 'r':
1151                        RFileName = optarg;
1152                        break;
1153
1154                case 'R':
1155                        Rflag = 0;
1156                        break;
1157
1158                case 's':
1159                        snaplen = strtol(optarg, &end, 0);
1160                        if (optarg == end || *end != '\0'
1161                            || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
1162                                error("invalid snaplen %s", optarg);
1163                        else if (snaplen == 0)
1164                                snaplen = MAXIMUM_SNAPLEN;
1165                        break;
1166
1167                case 'S':
1168                        ++Sflag;
1169                        break;
1170
1171                case 't':
1172                        ++tflag;
1173                        break;
1174
1175                case 'T':
1176                        if (strcasecmp(optarg, "vat") == 0)
1177                                packettype = PT_VAT;
1178                        else if (strcasecmp(optarg, "wb") == 0)
1179                                packettype = PT_WB;
1180                        else if (strcasecmp(optarg, "rpc") == 0)
1181                                packettype = PT_RPC;
1182                        else if (strcasecmp(optarg, "rtp") == 0)
1183                                packettype = PT_RTP;
1184                        else if (strcasecmp(optarg, "rtcp") == 0)
1185                                packettype = PT_RTCP;
1186                        else if (strcasecmp(optarg, "snmp") == 0)
1187                                packettype = PT_SNMP;
1188                        else if (strcasecmp(optarg, "cnfp") == 0)
1189                                packettype = PT_CNFP;
1190                        else if (strcasecmp(optarg, "tftp") == 0)
1191                                packettype = PT_TFTP;
1192                        else if (strcasecmp(optarg, "aodv") == 0)
1193                                packettype = PT_AODV;
1194                        else if (strcasecmp(optarg, "carp") == 0)
1195                                packettype = PT_CARP;
1196                        else if (strcasecmp(optarg, "radius") == 0)
1197                                packettype = PT_RADIUS;
1198                        else if (strcasecmp(optarg, "zmtp1") == 0)
1199                                packettype = PT_ZMTP1;
1200                        else if (strcasecmp(optarg, "vxlan") == 0)
1201                                packettype = PT_VXLAN;
1202                        else
1203                                error("unknown packet type `%s'", optarg);
1204                        break;
1205
1206                case 'u':
1207                        ++uflag;
1208                        break;
1209
1210#ifdef HAVE_PCAP_DUMP_FLUSH
1211                case 'U':
1212                        ++Uflag;
1213                        break;
1214#endif
1215
1216                case 'v':
1217                        ++vflag;
1218                        break;
1219
1220                case 'V':
1221                        VFileName = optarg;
1222                        break;
1223
1224                case 'w':
1225                        WFileName = optarg;
1226                        break;
1227
1228                case 'W':
1229                        Wflag = atoi(optarg);
1230                        if (Wflag < 0)
1231                                error("invalid number of output files %s", optarg);
1232                        WflagChars = getWflagChars(Wflag);
1233                        break;
1234
1235                case 'x':
1236                        ++xflag;
1237                        ++suppress_default_print;
1238                        break;
1239
1240                case 'X':
1241                        ++Xflag;
1242                        ++suppress_default_print;
1243                        break;
1244
1245                case 'y':
1246                        gndo->ndo_dltname = optarg;
1247                        gndo->ndo_dlt =
1248                          pcap_datalink_name_to_val(gndo->ndo_dltname);
1249                        if (gndo->ndo_dlt < 0)
1250                                error("invalid data link type %s", gndo->ndo_dltname);
1251                        break;
1252
1253#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
1254                case 'Y':
1255                        {
1256                        /* Undocumented flag */
1257#ifdef HAVE_PCAP_DEBUG
1258                        extern int pcap_debug;
1259                        pcap_debug = 1;
1260#else
1261                        extern int yydebug;
1262                        yydebug = 1;
1263#endif
1264                        }
1265                        break;
1266#endif
1267                case 'z':
1268                        if (optarg) {
1269                                zflag = strdup(optarg);
1270                        } else {
1271                                usage();
1272                                /* NOTREACHED */
1273                        }
1274                        break;
1275
1276                case 'Z':
1277                        if (optarg) {
1278                                username = strdup(optarg);
1279                        }
1280                        else {
1281                                usage();
1282                                /* NOTREACHED */
1283                        }
1284                        break;
1285
1286                default:
1287                        usage();
1288                        /* NOTREACHED */
1289                }
1290
1291        switch (tflag) {
1292
1293        case 0: /* Default */
1294        case 4: /* Default + Date*/
1295                thiszone = gmt2local(0);
1296                break;
1297
1298        case 1: /* No time stamp */
1299        case 2: /* Unix timeval style */
1300        case 3: /* Microseconds since previous packet */
1301        case 5: /* Microseconds since first packet */
1302                break;
1303
1304        default: /* Not supported */
1305                error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
1306                break;
1307        }
1308
1309        if (fflag != 0 && (VFileName != NULL || RFileName != NULL))
1310                error("-f can not be used with -V or -r");
1311
1312        if (VFileName != NULL && RFileName != NULL)
1313                error("-V and -r are mutually exclusive.");
1314
1315#ifdef WITH_CHROOT
1316        /* if run as root, prepare for chrooting */
1317        if (getuid() == 0 || geteuid() == 0) {
1318                /* future extensibility for cmd-line arguments */
1319                if (!chroot_dir)
1320                        chroot_dir = WITH_CHROOT;
1321        }
1322#endif
1323
1324#ifdef WITH_USER
1325        /* if run as root, prepare for dropping root privileges */
1326        if (getuid() == 0 || geteuid() == 0) {
1327                /* Run with '-Z root' to restore old behaviour */
1328                if (!username)
1329                        username = WITH_USER;
1330        }
1331#endif
1332
1333        if (RFileName != NULL || VFileName != NULL) {
1334                /*
1335                 * If RFileName is non-null, it's the pathname of a
1336                 * savefile to read.  If VFileName is non-null, it's
1337                 * the pathname of a file containing a list of pathnames
1338                 * (one per line) of savefiles to read.
1339                 *
1340                 * In either case, we're reading a savefile, not doing
1341                 * a live capture.
1342                 */
1343#ifndef WIN32
1344                /*
1345                 * We don't need network access, so relinquish any set-UID
1346                 * or set-GID privileges we have (if any).
1347                 *
1348                 * We do *not* want set-UID privileges when opening a
1349                 * trace file, as that might let the user read other
1350                 * people's trace files (especially if we're set-UID
1351                 * root).
1352                 */
1353                if (setgid(getgid()) != 0 || setuid(getuid()) != 0 )
1354                        fprintf(stderr, "Warning: setgid/setuid failed !\n");
1355#endif /* WIN32 */
1356                if (VFileName != NULL) {
1357                        if (VFileName[0] == '-' && VFileName[1] == '\0')
1358                                VFile = stdin;
1359                        else
1360                                VFile = fopen(VFileName, "r");
1361
1362                        if (VFile == NULL)
1363                                error("Unable to open file: %s\n", strerror(errno));
1364
1365                        ret = get_next_file(VFile, VFileLine);
1366                        if (!ret)
1367                                error("Nothing in %s\n", VFileName);
1368                        RFileName = VFileLine;
1369                }
1370
1371                pd = pcap_open_offline(RFileName, ebuf);
1372                if (pd == NULL)
1373                        error("%s", ebuf);
1374                dlt = pcap_datalink(pd);
1375                dlt_name = pcap_datalink_val_to_name(dlt);
1376                if (dlt_name == NULL) {
1377                        fprintf(stderr, "reading from file %s, link-type %u\n",
1378                            RFileName, dlt);
1379                } else {
1380                        fprintf(stderr,
1381                            "reading from file %s, link-type %s (%s)\n",
1382                            RFileName, dlt_name,
1383                            pcap_datalink_val_to_description(dlt));
1384                }
1385                localnet = 0;
1386                netmask = 0;
1387        } else {
1388                /*
1389                 * We're doing a live capture.
1390                 */
1391                if (device == NULL) {
1392                        device = pcap_lookupdev(ebuf);
1393                        if (device == NULL)
1394                                error("%s", ebuf);
1395                }
1396#ifdef WIN32
1397                /*
1398                 * Print a message to the standard error on Windows.
1399                 * XXX - why do it here, with a different message?
1400                 */
1401                if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char
1402                {                                               //a Unicode string has a \0 as second byte (so strlen() is 1)
1403                        fprintf(stderr, "%s: listening on %ws\n", program_name, device);
1404                }
1405                else
1406                {
1407                        fprintf(stderr, "%s: listening on %s\n", program_name, device);
1408                }
1409
1410                fflush(stderr);
1411#endif /* WIN32 */
1412#ifdef HAVE_PCAP_CREATE
1413                pd = pcap_create(device, ebuf);
1414                if (pd == NULL)
1415                        error("%s", ebuf);
1416#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
1417                if (Jflag)
1418                        show_tstamp_types_and_exit(device, pd);
1419#endif
1420                /*
1421                 * Is this an interface that supports monitor mode?
1422                 */
1423                if (pcap_can_set_rfmon(pd) == 1)
1424                        supports_monitor_mode = 1;
1425                else
1426                        supports_monitor_mode = 0;
1427                status = pcap_set_snaplen(pd, snaplen);
1428                if (status != 0)
1429                        error("%s: Can't set snapshot length: %s",
1430                            device, pcap_statustostr(status));
1431                status = pcap_set_promisc(pd, !pflag);
1432                if (status != 0)
1433                        error("%s: Can't set promiscuous mode: %s",
1434                            device, pcap_statustostr(status));
1435                if (Iflag) {
1436                        status = pcap_set_rfmon(pd, 1);
1437                        if (status != 0)
1438                                error("%s: Can't set monitor mode: %s",
1439                                    device, pcap_statustostr(status));
1440                }
1441                status = pcap_set_timeout(pd, 1000);
1442                if (status != 0)
1443                        error("%s: pcap_set_timeout failed: %s",
1444                            device, pcap_statustostr(status));
1445                if (Bflag != 0) {
1446                        status = pcap_set_buffer_size(pd, Bflag);
1447                        if (status != 0)
1448                                error("%s: Can't set buffer size: %s",
1449                                    device, pcap_statustostr(status));
1450                }
1451#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
1452                if (jflag != -1) {
1453                        status = pcap_set_tstamp_type(pd, jflag);
1454                        if (status < 0)
1455                                error("%s: Can't set time stamp type: %s",
1456                                    device, pcap_statustostr(status));
1457                }
1458#endif
1459                status = pcap_activate(pd);
1460                if (status < 0) {
1461                        /*
1462                         * pcap_activate() failed.
1463                         */
1464                        cp = pcap_geterr(pd);
1465                        if (status == PCAP_ERROR)
1466                                error("%s", cp);
1467                        else if ((status == PCAP_ERROR_NO_SUCH_DEVICE ||
1468                                  status == PCAP_ERROR_PERM_DENIED) &&
1469                                 *cp != '\0')
1470                                error("%s: %s\n(%s)", device,
1471                                    pcap_statustostr(status), cp);
1472                        else
1473                                error("%s: %s", device,
1474                                    pcap_statustostr(status));
1475                } else if (status > 0) {
1476                        /*
1477                         * pcap_activate() succeeded, but it's warning us
1478                         * of a problem it had.
1479                         */
1480                        cp = pcap_geterr(pd);
1481                        if (status == PCAP_WARNING)
1482                                warning("%s", cp);
1483                        else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
1484                                 *cp != '\0')
1485                                warning("%s: %s\n(%s)", device,
1486                                    pcap_statustostr(status), cp);
1487                        else
1488                                warning("%s: %s", device,
1489                                    pcap_statustostr(status));
1490                }
1491#else
1492                *ebuf = '\0';
1493                pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
1494                if (pd == NULL)
1495                        error("%s", ebuf);
1496                else if (*ebuf)
1497                        warning("%s", ebuf);
1498#endif /* HAVE_PCAP_CREATE */
1499                /*
1500                 * Let user own process after socket has been opened.
1501                 */
1502#ifndef WIN32
1503                if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
1504                        fprintf(stderr, "Warning: setgid/setuid failed !\n");
1505#endif /* WIN32 */
1506#if !defined(HAVE_PCAP_CREATE) && defined(WIN32)
1507                if(Bflag != 0)
1508                        if(pcap_setbuff(pd, Bflag)==-1){
1509                                error("%s", pcap_geterr(pd));
1510                        }
1511#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */
1512                if (Lflag)
1513                        show_dlts_and_exit(device, pd);
1514                if (gndo->ndo_dlt >= 0) {
1515#ifdef HAVE_PCAP_SET_DATALINK
1516                        if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0)
1517                                error("%s", pcap_geterr(pd));
1518#else
1519                        /*
1520                         * We don't actually support changing the
1521                         * data link type, so we only let them
1522                         * set it to what it already is.
1523                         */
1524                        if (gndo->ndo_dlt != pcap_datalink(pd)) {
1525                                error("%s is not one of the DLTs supported by this device\n",
1526                                      gndo->ndo_dltname);
1527                        }
1528#endif
1529                        (void)fprintf(stderr, "%s: data link type %s\n",
1530                                      program_name, gndo->ndo_dltname);
1531                        (void)fflush(stderr);
1532                }
1533                i = pcap_snapshot(pd);
1534                if (snaplen < i) {
1535                        warning("snaplen raised from %d to %d", snaplen, i);
1536                        snaplen = i;
1537                }
1538                if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
1539                        localnet = 0;
1540                        netmask = 0;
1541                        warning("%s", ebuf);
1542                }
1543        }
1544        if (infile)
1545                cmdbuf = read_infile(infile);
1546        else
1547                cmdbuf = copy_argv(&argv[optind]);
1548
1549        if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
1550                error("%s", pcap_geterr(pd));
1551        if (dflag) {
1552                bpf_dump(&fcode, dflag);
1553                pcap_close(pd);
1554                free(cmdbuf);
1555                exit(0);
1556        }
1557        init_addrtoname(localnet, netmask);
1558        init_checksum();
1559
1560#ifndef WIN32
1561        (void)setsignal(SIGPIPE, cleanup);
1562        (void)setsignal(SIGTERM, cleanup);
1563        (void)setsignal(SIGINT, cleanup);
1564#endif /* WIN32 */
1565#if defined(HAVE_FORK) || defined(HAVE_VFORK)
1566        (void)setsignal(SIGCHLD, child_cleanup);
1567#endif
1568        /* Cooperate with nohup(1) */
1569#ifndef WIN32
1570        if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
1571                (void)setsignal(SIGHUP, oldhandler);
1572#endif /* WIN32 */
1573
1574#ifndef WIN32
1575        /*
1576         * If a user name was specified with "-Z", attempt to switch to
1577         * that user's UID.  This would probably be used with sudo,
1578         * to allow tcpdump to be run in a special restricted
1579         * account (if you just want to allow users to open capture
1580         * devices, and can't just give users that permission,
1581         * you'd make tcpdump set-UID or set-GID).
1582         *
1583         * Tcpdump doesn't necessarily write only to one savefile;
1584         * the general only way to allow a -Z instance to write to
1585         * savefiles as the user under whose UID it's run, rather
1586         * than as the user specified with -Z, would thus be to switch
1587         * to the original user ID before opening a capture file and
1588         * then switch back to the -Z user ID after opening the savefile.
1589         * Switching to the -Z user ID only after opening the first
1590         * savefile doesn't handle the general case.
1591         */
1592
1593#ifdef HAVE_CAP_NG_H
1594        /* We are running as root and we will be writing to savefile */
1595        if ((getuid() == 0 || geteuid() == 0) && WFileName) {
1596                if (username) {
1597                        /* Drop all capabilities from effective set */
1598                        capng_clear(CAPNG_EFFECTIVE);
1599                        /* Add capabilities we will need*/
1600                        capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID);
1601                        capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID);
1602                        capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE);
1603
1604                        capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID);
1605                        capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID);
1606                        capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
1607
1608                        capng_apply(CAPNG_SELECT_BOTH);
1609                }
1610        }
1611#endif /* HAVE_CAP_NG_H */
1612
1613        if (getuid() == 0 || geteuid() == 0) {
1614                if (username || chroot_dir)
1615                        droproot(username, chroot_dir);
1616
1617        }
1618#endif /* WIN32 */
1619
1620        if (pcap_setfilter(pd, &fcode) < 0)
1621                error("%s", pcap_geterr(pd));
1622        if (WFileName) {
1623                pcap_dumper_t *p;
1624                /* Do not exceed the default PATH_MAX for files. */
1625                dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1);
1626
1627                if (dumpinfo.CurrentFileName == NULL)
1628                        error("malloc of dumpinfo.CurrentFileName");
1629
1630                /* We do not need numbering for dumpfiles if Cflag isn't set. */
1631                if (Cflag != 0)
1632                  MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);
1633                else
1634                  MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
1635
1636                p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
1637#ifdef HAVE_CAP_NG_H
1638        /* Give up capabilities, clear Effective set */
1639        capng_clear(CAPNG_EFFECTIVE);
1640#endif
1641                if (p == NULL)
1642                        error("%s", pcap_geterr(pd));
1643                if (Cflag != 0 || Gflag != 0) {
1644                        callback = dump_packet_and_trunc;
1645                        dumpinfo.WFileName = WFileName;
1646                        dumpinfo.pd = pd;
1647                        dumpinfo.p = p;
1648                        pcap_userdata = (u_char *)&dumpinfo;
1649                } else {
1650                        callback = dump_packet;
1651                        pcap_userdata = (u_char *)p;
1652                }
1653#ifdef HAVE_PCAP_DUMP_FLUSH
1654                if (Uflag)
1655                        pcap_dump_flush(p);
1656#endif
1657        } else {
1658                type = pcap_datalink(pd);
1659                printinfo = get_print_info(type);
1660                callback = print_packet;
1661                pcap_userdata = (u_char *)&printinfo;
1662        }
1663
1664#ifdef SIGNAL_REQ_INFO
1665        /*
1666         * We can't get statistics when reading from a file rather
1667         * than capturing from a device.
1668         */
1669        if (RFileName == NULL)
1670                (void)setsignal(SIGNAL_REQ_INFO, requestinfo);
1671#endif
1672
1673        if (vflag > 0 && WFileName) {
1674                /*
1675                 * When capturing to a file, "-v" means tcpdump should,
1676                 * every 10 secodns, "v"erbosely report the number of
1677                 * packets captured.
1678                 */
1679#ifdef USE_WIN32_MM_TIMER
1680                /* call verbose_stats_dump() each 1000 +/-100msec */
1681                timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC);
1682                setvbuf(stderr, NULL, _IONBF, 0);
1683#elif defined(HAVE_ALARM)
1684                (void)setsignal(SIGALRM, verbose_stats_dump);
1685                alarm(1);
1686#endif
1687        }
1688
1689#ifndef WIN32
1690        if (RFileName == NULL) {
1691                /*
1692                 * Live capture (if -V was specified, we set RFileName
1693                 * to a file from the -V file).  Print a message to
1694                 * the standard error on UN*X.
1695                 */
1696                if (!vflag && !WFileName) {
1697                        (void)fprintf(stderr,
1698                            "%s: verbose output suppressed, use -v or -vv for full protocol decode\n",
1699                            program_name);
1700                } else
1701                        (void)fprintf(stderr, "%s: ", program_name);
1702                dlt = pcap_datalink(pd);
1703                dlt_name = pcap_datalink_val_to_name(dlt);
1704                if (dlt_name == NULL) {
1705                        (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n",
1706                            device, dlt, snaplen);
1707                } else {
1708                        (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n",
1709                            device, dlt_name,
1710                            pcap_datalink_val_to_description(dlt), snaplen);
1711                }
1712                (void)fflush(stderr);
1713        }
1714#endif /* WIN32 */
1715        do {
1716                status = pcap_loop(pd, cnt, callback, pcap_userdata);
1717                if (WFileName == NULL) {
1718                        /*
1719                         * We're printing packets.  Flush the printed output,
1720                         * so it doesn't get intermingled with error output.
1721                         */
1722                        if (status == -2) {
1723                                /*
1724                                 * We got interrupted, so perhaps we didn't
1725                                 * manage to finish a line we were printing.
1726                                 * Print an extra newline, just in case.
1727                                 */
1728                                putchar('\n');
1729                        }
1730                        (void)fflush(stdout);
1731                }
1732                if (status == -1) {
1733                        /*
1734                         * Error.  Report it.
1735                         */
1736                        (void)fprintf(stderr, "%s: pcap_loop: %s\n",
1737                            program_name, pcap_geterr(pd));
1738                }
1739                if (RFileName == NULL) {
1740                        /*
1741                         * We're doing a live capture.  Report the capture
1742                         * statistics.
1743                         */
1744                        info(1);
1745                }
1746                pcap_close(pd);
1747                if (VFileName != NULL) {
1748                        ret = get_next_file(VFile, VFileLine);
1749                        if (ret) {
1750                                RFileName = VFileLine;
1751                                pd = pcap_open_offline(RFileName, ebuf);
1752                                if (pd == NULL)
1753                                        error("%s", ebuf);
1754                                new_dlt = pcap_datalink(pd);
1755                                if (WFileName && new_dlt != dlt)
1756                                        error("%s: new dlt does not match original", RFileName);
1757                                printinfo = get_print_info(new_dlt);
1758                                dlt_name = pcap_datalink_val_to_name(new_dlt);
1759                                if (dlt_name == NULL) {
1760                                        fprintf(stderr, "reading from file %s, link-type %u\n",
1761                                        RFileName, new_dlt);
1762                                } else {
1763                                        fprintf(stderr,
1764                                        "reading from file %s, link-type %s (%s)\n",
1765                                        RFileName, dlt_name,
1766                                        pcap_datalink_val_to_description(new_dlt));
1767                                }
1768                                if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
1769                                        error("%s", pcap_geterr(pd));
1770                                if (pcap_setfilter(pd, &fcode) < 0)
1771                                        error("%s", pcap_geterr(pd));
1772                        }
1773                }
1774        }
1775        while (ret != NULL);
1776
1777        free(cmdbuf);
1778        exit(status == -1 ? 1 : 0);
1779}
1780
1781/* make a clean exit on interrupts */
1782static RETSIGTYPE
1783cleanup(int signo _U_)
1784{
1785#ifdef USE_WIN32_MM_TIMER
1786        if (timer_id)
1787                timeKillEvent(timer_id);
1788        timer_id = 0;
1789#elif defined(HAVE_ALARM)
1790        alarm(0);
1791#endif
1792
1793#ifdef HAVE_PCAP_BREAKLOOP
1794        /*
1795         * We have "pcap_breakloop()"; use it, so that we do as little
1796         * as possible in the signal handler (it's probably not safe
1797         * to do anything with standard I/O streams in a signal handler -
1798         * the ANSI C standard doesn't say it is).
1799         */
1800        pcap_breakloop(pd);
1801#else
1802        /*
1803         * We don't have "pcap_breakloop()"; this isn't safe, but
1804         * it's the best we can do.  Print the summary if we're
1805         * not reading from a savefile - i.e., if we're doing a
1806         * live capture - and exit.
1807         */
1808        if (pd != NULL && pcap_file(pd) == NULL) {
1809                /*
1810                 * We got interrupted, so perhaps we didn't
1811                 * manage to finish a line we were printing.
1812                 * Print an extra newline, just in case.
1813                 */
1814                putchar('\n');
1815                (void)fflush(stdout);
1816                info(1);
1817        }
1818        exit(0);
1819#endif
1820}
1821
1822/*
1823  On windows, we do not use a fork, so we do not care less about
1824  waiting a child processes to die
1825 */
1826#if defined(HAVE_FORK) || defined(HAVE_VFORK)
1827static RETSIGTYPE
1828child_cleanup(int signo _U_)
1829{
1830  wait(NULL);
1831}
1832#endif /* HAVE_FORK && HAVE_VFORK */
1833
1834static void
1835info(register int verbose)
1836{
1837        struct pcap_stat stat;
1838
1839        /*
1840         * Older versions of libpcap didn't set ps_ifdrop on some
1841         * platforms; initialize it to 0 to handle that.
1842         */
1843        stat.ps_ifdrop = 0;
1844        if (pcap_stats(pd, &stat) < 0) {
1845                (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd));
1846                infoprint = 0;
1847                return;
1848        }
1849
1850        if (!verbose)
1851                fprintf(stderr, "%s: ", program_name);
1852
1853        (void)fprintf(stderr, "%u packet%s captured", packets_captured,
1854            PLURAL_SUFFIX(packets_captured));
1855        if (!verbose)
1856                fputs(", ", stderr);
1857        else
1858                putc('\n', stderr);
1859        (void)fprintf(stderr, "%u packet%s received by filter", stat.ps_recv,
1860            PLURAL_SUFFIX(stat.ps_recv));
1861        if (!verbose)
1862                fputs(", ", stderr);
1863        else
1864                putc('\n', stderr);
1865        (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop,
1866            PLURAL_SUFFIX(stat.ps_drop));
1867        if (stat.ps_ifdrop != 0) {
1868                if (!verbose)
1869                        fputs(", ", stderr);
1870                else
1871                        putc('\n', stderr);
1872                (void)fprintf(stderr, "%u packet%s dropped by interface\n",
1873                    stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop));
1874        } else
1875                putc('\n', stderr);
1876        infoprint = 0;
1877}
1878
1879#if defined(HAVE_FORK) || defined(HAVE_VFORK)
1880static void
1881compress_savefile(const char *filename)
1882{
1883# ifdef HAVE_FORK
1884        if (fork())
1885# else
1886        if (vfork())
1887# endif
1888                return;
1889        /*
1890         * Set to lowest priority so that this doesn't disturb the capture
1891         */
1892#ifdef NZERO
1893        setpriority(PRIO_PROCESS, 0, NZERO - 1);
1894#else
1895        setpriority(PRIO_PROCESS, 0, 19);
1896#endif
1897        if (execlp(zflag, zflag, filename, (char *)NULL) == -1)
1898                fprintf(stderr,
1899                        "compress_savefile:execlp(%s, %s): %s\n",
1900                        zflag,
1901                        filename,
1902                        strerror(errno));
1903# ifdef HAVE_FORK
1904        exit(1);
1905# else
1906        _exit(1);
1907# endif
1908}
1909#else  /* HAVE_FORK && HAVE_VFORK */
1910static void
1911compress_savefile(const char *filename)
1912{
1913        fprintf(stderr,
1914                "compress_savefile failed. Functionality not implemented under your system\n");
1915}
1916#endif /* HAVE_FORK && HAVE_VFORK */
1917
1918static void
1919dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
1920{
1921        struct dump_info *dump_info;
1922
1923        ++packets_captured;
1924
1925        ++infodelay;
1926
1927        dump_info = (struct dump_info *)user;
1928
1929        /*
1930         * XXX - this won't force the file to rotate on the specified time
1931         * boundary, but it will rotate on the first packet received after the
1932         * specified Gflag number of seconds. Note: if a Gflag time boundary
1933         * and a Cflag size boundary coincide, the time rotation will occur
1934         * first thereby cancelling the Cflag boundary (since the file should
1935         * be 0).
1936         */
1937        if (Gflag != 0) {
1938                /* Check if it is time to rotate */
1939                time_t t;
1940
1941                /* Get the current time */
1942                if ((t = time(NULL)) == (time_t)-1) {
1943                        error("dump_and_trunc_packet: can't get current_time: %s",
1944                            pcap_strerror(errno));
1945                }
1946
1947
1948                /* If the time is greater than the specified window, rotate */
1949                if (t - Gflag_time >= Gflag) {
1950                        /* Update the Gflag_time */
1951                        Gflag_time = t;
1952                        /* Update Gflag_count */
1953                        Gflag_count++;
1954                        /*
1955                         * Close the current file and open a new one.
1956                         */
1957                        pcap_dump_close(dump_info->p);
1958
1959                        /*
1960                         * Compress the file we just closed, if the user asked for it
1961                         */
1962                        if (zflag != NULL)
1963                                compress_savefile(dump_info->CurrentFileName);
1964
1965                        /*
1966                         * Check to see if we've exceeded the Wflag (when
1967                         * not using Cflag).
1968                         */
1969                        if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
1970                                (void)fprintf(stderr, "Maximum file limit reached: %d\n",
1971                                    Wflag);
1972                                exit(0);
1973                                /* NOTREACHED */
1974                        }
1975                        if (dump_info->CurrentFileName != NULL)
1976                                free(dump_info->CurrentFileName);
1977                        /* Allocate space for max filename + \0. */
1978                        dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1);
1979                        if (dump_info->CurrentFileName == NULL)
1980                                error("dump_packet_and_trunc: malloc");
1981                        /*
1982                         * This is always the first file in the Cflag
1983                         * rotation: e.g. 0
1984                         * We also don't need numbering if Cflag is not set.
1985                         */
1986                        if (Cflag != 0)
1987                                MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0,
1988                                    WflagChars);
1989                        else
1990                                MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
1991
1992#ifdef HAVE_CAP_NG_H
1993                        capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
1994                        capng_apply(CAPNG_EFFECTIVE);
1995#endif /* HAVE_CAP_NG_H */
1996                        dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
1997#ifdef HAVE_CAP_NG_H
1998                        capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
1999                        capng_apply(CAPNG_EFFECTIVE);
2000#endif /* HAVE_CAP_NG_H */
2001                        if (dump_info->p == NULL)
2002                                error("%s", pcap_geterr(pd));
2003                }
2004        }
2005
2006        /*
2007         * XXX - this won't prevent capture files from getting
2008         * larger than Cflag - the last packet written to the
2009         * file could put it over Cflag.
2010         */
2011        if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) {
2012                /*
2013                 * Close the current file and open a new one.
2014                 */
2015                pcap_dump_close(dump_info->p);
2016
2017                /*
2018                 * Compress the file we just closed, if the user asked for it
2019                 */
2020                if (zflag != NULL)
2021                        compress_savefile(dump_info->CurrentFileName);
2022
2023                Cflag_count++;
2024                if (Wflag > 0) {
2025                        if (Cflag_count >= Wflag)
2026                                Cflag_count = 0;
2027                }
2028                if (dump_info->CurrentFileName != NULL)
2029                        free(dump_info->CurrentFileName);
2030                dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1);
2031                if (dump_info->CurrentFileName == NULL)
2032                        error("dump_packet_and_trunc: malloc");
2033                MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
2034                dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
2035                if (dump_info->p == NULL)
2036                        error("%s", pcap_geterr(pd));
2037        }
2038
2039        pcap_dump((u_char *)dump_info->p, h, sp);
2040#ifdef HAVE_PCAP_DUMP_FLUSH
2041        if (Uflag)
2042                pcap_dump_flush(dump_info->p);
2043#endif
2044
2045        --infodelay;
2046        if (infoprint)
2047                info(0);
2048}
2049
2050static void
2051dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
2052{
2053        ++packets_captured;
2054
2055        ++infodelay;
2056
2057        pcap_dump(user, h, sp);
2058#ifdef HAVE_PCAP_DUMP_FLUSH
2059        if (Uflag)
2060                pcap_dump_flush((pcap_dumper_t *)user);
2061#endif
2062
2063        --infodelay;
2064        if (infoprint)
2065                info(0);
2066}
2067
2068static void
2069print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
2070{
2071        struct print_info *print_info;
2072        u_int hdrlen;
2073
2074        ++packets_captured;
2075
2076        ++infodelay;
2077        ts_print(&h->ts);
2078
2079        print_info = (struct print_info *)user;
2080
2081        /*
2082         * Some printers want to check that they're not walking off the
2083         * end of the packet.
2084         * Rather than pass it all the way down, we set this global.
2085         */
2086        snapend = sp + h->caplen;
2087
2088        if(print_info->ndo_type) {
2089                hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp);
2090        } else {
2091                hdrlen = (*print_info->p.printer)(h, sp);
2092        }
2093
2094        if (Xflag) {
2095                /*
2096                 * Print the raw packet data in hex and ASCII.
2097                 */
2098                if (Xflag > 1) {
2099                        /*
2100                         * Include the link-layer header.
2101                         */
2102                        hex_and_ascii_print("\n\t", sp, h->caplen);
2103                } else {
2104                        /*
2105                         * Don't include the link-layer header - and if
2106                         * we have nothing past the link-layer header,
2107                         * print nothing.
2108                         */
2109                        if (h->caplen > hdrlen)
2110                                hex_and_ascii_print("\n\t", sp + hdrlen,
2111                                    h->caplen - hdrlen);
2112                }
2113        } else if (xflag) {
2114                /*
2115                 * Print the raw packet data in hex.
2116                 */
2117                if (xflag > 1) {
2118                        /*
2119                         * Include the link-layer header.
2120                         */
2121                        hex_print("\n\t", sp, h->caplen);
2122                } else {
2123                        /*
2124                         * Don't include the link-layer header - and if
2125                         * we have nothing past the link-layer header,
2126                         * print nothing.
2127                         */
2128                        if (h->caplen > hdrlen)
2129                                hex_print("\n\t", sp + hdrlen,
2130                                    h->caplen - hdrlen);
2131                }
2132        } else if (Aflag) {
2133                /*
2134                 * Print the raw packet data in ASCII.
2135                 */
2136                if (Aflag > 1) {
2137                        /*
2138                         * Include the link-layer header.
2139                         */
2140                        ascii_print(sp, h->caplen);
2141                } else {
2142                        /*
2143                         * Don't include the link-layer header - and if
2144                         * we have nothing past the link-layer header,
2145                         * print nothing.
2146                         */
2147                        if (h->caplen > hdrlen)
2148                                ascii_print(sp + hdrlen, h->caplen - hdrlen);
2149                }
2150        }
2151
2152        putchar('\n');
2153
2154        --infodelay;
2155        if (infoprint)
2156                info(0);
2157}
2158
2159#ifdef WIN32
2160        /*
2161         * XXX - there should really be libpcap calls to get the version
2162         * number as a string (the string would be generated from #defines
2163         * at run time, so that it's not generated from string constants
2164         * in the library, as, on many UNIX systems, those constants would
2165         * be statically linked into the application executable image, and
2166         * would thus reflect the version of libpcap on the system on
2167         * which the application was *linked*, not the system on which it's
2168         * *running*.
2169         *
2170         * That routine should be documented, unlike the "version[]"
2171         * string, so that UNIX vendors providing their own libpcaps
2172         * don't omit it (as a couple of vendors have...).
2173         *
2174         * Packet.dll should perhaps also export a routine to return the
2175         * version number of the Packet.dll code, to supply the
2176         * "Wpcap_version" information on Windows.
2177         */
2178        char WDversion[]="current-cvs.tcpdump.org";
2179#if !defined(HAVE_GENERATED_VERSION)
2180        char version[]="current-cvs.tcpdump.org";
2181#endif
2182        char pcap_version[]="current-cvs.tcpdump.org";
2183        char Wpcap_version[]="3.1";
2184#endif
2185
2186/*
2187 * By default, print the specified data out in hex and ASCII.
2188 */
2189static void
2190ndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length)
2191{
2192        hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */
2193}
2194
2195void
2196default_print(const u_char *bp, u_int length)
2197{
2198        ndo_default_print(gndo, bp, length);
2199}
2200
2201#ifdef SIGNAL_REQ_INFO
2202RETSIGTYPE requestinfo(int signo _U_)
2203{
2204        if (infodelay)
2205                ++infoprint;
2206        else
2207                info(0);
2208}
2209#endif
2210
2211/*
2212 * Called once each second in verbose mode while dumping to file
2213 */
2214#ifdef USE_WIN32_MM_TIMER
2215void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
2216                                  DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
2217{
2218        struct pcap_stat stat;
2219
2220        if (infodelay == 0 && pcap_stats(pd, &stat) >= 0)
2221                fprintf(stderr, "Got %u\r", packets_captured);
2222}
2223#elif defined(HAVE_ALARM)
2224static void verbose_stats_dump(int sig _U_)
2225{
2226        struct pcap_stat stat;
2227
2228        if (infodelay == 0 && pcap_stats(pd, &stat) >= 0)
2229                fprintf(stderr, "Got %u\r", packets_captured);
2230        alarm(1);
2231}
2232#endif
2233
2234static void
2235usage(void)
2236{
2237#ifdef __rtems__
2238  #define version "RTEMS Version"
2239#else
2240        extern char version[];
2241#endif /* __rtems__ */
2242#ifndef HAVE_PCAP_LIB_VERSION
2243#if defined(WIN32) || defined(HAVE_PCAP_VERSION)
2244        extern char pcap_version[];
2245#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */
2246        static char pcap_version[] = "unknown";
2247#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */
2248#endif /* HAVE_PCAP_LIB_VERSION */
2249
2250#ifdef HAVE_PCAP_LIB_VERSION
2251#ifdef WIN32
2252        (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version);
2253#else /* WIN32 */
2254        (void)fprintf(stderr, "%s version %s\n", program_name, version);
2255#endif /* WIN32 */
2256        (void)fprintf(stderr, "%s\n",pcap_lib_version());
2257#else /* HAVE_PCAP_LIB_VERSION */
2258#ifdef WIN32
2259        (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version);
2260        (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version);
2261#else /* WIN32 */
2262        (void)fprintf(stderr, "%s version %s\n", program_name, version);
2263        (void)fprintf(stderr, "libpcap version %s\n", pcap_version);
2264#endif /* WIN32 */
2265#endif /* HAVE_PCAP_LIB_VERSION */
2266        (void)fprintf(stderr,
2267"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name);
2268        (void)fprintf(stderr,
2269"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
2270        (void)fprintf(stderr,
2271"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ]\n");
2272        (void)fprintf(stderr,
2273"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]\n");
2274        (void)fprintf(stderr,
2275"\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ]\n");
2276        (void)fprintf(stderr,
2277"\t\t[ -Z user ] [ expression ]\n");
2278        exit(1);
2279}
2280
2281
2282
2283/* VARARGS */
2284static void
2285ndo_error(netdissect_options *ndo _U_, const char *fmt, ...)
2286{
2287        va_list ap;
2288
2289        (void)fprintf(stderr, "%s: ", program_name);
2290        va_start(ap, fmt);
2291        (void)vfprintf(stderr, fmt, ap);
2292        va_end(ap);
2293        if (*fmt) {
2294                fmt += strlen(fmt);
2295                if (fmt[-1] != '\n')
2296                        (void)fputc('\n', stderr);
2297        }
2298        exit(1);
2299        /* NOTREACHED */
2300}
2301
2302/* VARARGS */
2303static void
2304ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...)
2305{
2306        va_list ap;
2307
2308        (void)fprintf(stderr, "%s: WARNING: ", program_name);
2309        va_start(ap, fmt);
2310        (void)vfprintf(stderr, fmt, ap);
2311        va_end(ap);
2312        if (*fmt) {
2313                fmt += strlen(fmt);
2314                if (fmt[-1] != '\n')
2315                        (void)fputc('\n', stderr);
2316        }
2317}
Note: See TracBrowser for help on using the repository browser.