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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since c6e5395 was c6e5395, checked in by Chris Johns <chrisj@…>, on Jun 26, 2015 at 5:20:22 AM

tcpdump: Return the PCAP loop return value. Increase the stack size.

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