"Fossies" - the Fresh Open Source Software Archive

Member "libpcap-1.9.1/./testprogs/threadsignaltest.c" (30 Sep 2019, 9256 Bytes) of package /linux/misc/libpcap-1.9.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "threadsignaltest.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
    3  *  The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that: (1) source code distributions
    7  * retain the above copyright notice and this paragraph in its entirety, (2)
    8  * distributions including binary code include the above copyright notice and
    9  * this paragraph in its entirety in the documentation or other materials
   10  * provided with the distribution, and (3) all advertising materials mentioning
   11  * features or use of this software display the following acknowledgement:
   12  * ``This product includes software developed by the University of California,
   13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
   14  * the University nor the names of its contributors may be used to endorse
   15  * or promote products derived from this software without specific prior
   16  * written permission.
   17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
   18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   20  */
   21 
   22 #include "varattrs.h"
   23 
   24 #ifndef lint
   25 static const char copyright[] _U_ =
   26     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
   27 The Regents of the University of California.  All rights reserved.\n";
   28 #endif
   29 
   30 #include <stdio.h>
   31 #include <stdlib.h>
   32 #include <string.h>
   33 #include <stdarg.h>
   34 #include <limits.h>
   35 #ifdef _WIN32
   36   #include <winsock2.h>
   37   #include <windows.h>
   38 
   39   #define THREAD_HANDLE         HANDLE
   40   #define THREAD_FUNC_ARG_TYPE      LPVOID
   41   #define THREAD_FUNC_RETURN_TYPE   DWORD __stdcall
   42 
   43   #include "getopt.h"
   44 #else
   45   #include <pthread.h>
   46   #include <signal.h>
   47   #include <unistd.h>
   48 
   49   #define THREAD_HANDLE         pthread_t
   50   #define THREAD_FUNC_ARG_TYPE      void *
   51   #define THREAD_FUNC_RETURN_TYPE   void *
   52 #endif
   53 #include <errno.h>
   54 #include <sys/types.h>
   55 
   56 #include <pcap.h>
   57 
   58 #include "pcap/funcattrs.h"
   59 
   60 #ifdef _WIN32
   61   #include "portability.h"
   62 #endif
   63 
   64 static char *program_name;
   65 
   66 /* Forwards */
   67 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
   68 static void PCAP_NORETURN usage(void);
   69 static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
   70 static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
   71 static char *copy_argv(char **);
   72 
   73 static pcap_t *pd;
   74 
   75 #ifdef _WIN32
   76 /*
   77  * Generate a string for a Win32-specific error (i.e. an error generated when
   78  * calling a Win32 API).
   79  * For errors occurred during standard C calls, we still use pcap_strerror()
   80  */
   81 #define ERRBUF_SIZE 1024
   82 static const char *
   83 win32_strerror(DWORD error)
   84 {
   85   static char errbuf[ERRBUF_SIZE+1];
   86   size_t errlen;
   87 
   88   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
   89                 ERRBUF_SIZE, NULL);
   90 
   91   /*
   92    * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
   93    * message.  Get rid of it.
   94    */
   95   errlen = strlen(errbuf);
   96   if (errlen >= 2) {
   97     errbuf[errlen - 1] = '\0';
   98     errbuf[errlen - 2] = '\0';
   99     errlen -= 2;
  100   }
  101   return errbuf;
  102 }
  103 #else
  104 static void
  105 catch_sigusr1(int sig _U_)
  106 {
  107     printf("Got SIGUSR1\n");
  108 }
  109 #endif
  110 
  111 static void
  112 sleep_secs(int secs)
  113 {
  114 #ifdef _WIN32
  115     Sleep(secs*1000);
  116 #else
  117     unsigned secs_remaining;
  118 
  119     if (secs <= 0)
  120         return;
  121     secs_remaining = secs;
  122     while (secs_remaining != 0)
  123         secs_remaining = sleep(secs_remaining);
  124 #endif
  125 }
  126 
  127 static THREAD_FUNC_RETURN_TYPE
  128 capture_thread_func(THREAD_FUNC_ARG_TYPE arg)
  129 {
  130     char *device = arg;
  131     int packet_count;
  132     int status;
  133 #ifndef _WIN32
  134     struct sigaction action;
  135     sigset_t mask;
  136 #endif
  137 
  138 #ifndef _WIN32
  139     sigemptyset(&mask);
  140     action.sa_handler = catch_sigusr1;
  141     action.sa_mask = mask;
  142     action.sa_flags = 0;
  143     if (sigaction(SIGUSR1, &action, NULL) == -1)
  144         error("Can't catch SIGUSR1: %s", strerror(errno));
  145 #endif
  146 
  147     printf("Listening on %s\n", device);
  148     for (;;) {
  149         packet_count = 0;
  150         status = pcap_dispatch(pd, -1, countme,
  151             (u_char *)&packet_count);
  152         if (status < 0)
  153             break;
  154         if (status != 0) {
  155             printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
  156                 status, packet_count);
  157         } else
  158             printf("No packets seen by pcap_dispatch\n");
  159     }
  160     if (status == -2) {
  161         /*
  162          * We got interrupted, so perhaps we didn't
  163          * manage to finish a line we were printing.
  164          * Print an extra newline, just in case.
  165          */
  166         putchar('\n');
  167         printf("Loop got broken\n");
  168     }
  169     (void)fflush(stdout);
  170     if (status == -1) {
  171         /*
  172          * Error.  Report it.
  173          */
  174         (void)fprintf(stderr, "%s: pcap_loop: %s\n",
  175             program_name, pcap_geterr(pd));
  176     }
  177     return 0;
  178 }
  179 
  180 int
  181 main(int argc, char **argv)
  182 {
  183     register int op;
  184     register char *cp, *cmdbuf, *device;
  185     int immediate = 0;
  186     pcap_if_t *devlist;
  187     bpf_u_int32 localnet, netmask;
  188     struct bpf_program fcode;
  189     char ebuf[PCAP_ERRBUF_SIZE];
  190     int status;
  191     THREAD_HANDLE capture_thread;
  192 #ifndef _WIN32
  193     void *retval;
  194 #endif
  195 
  196     device = NULL;
  197     if ((cp = strrchr(argv[0], '/')) != NULL)
  198         program_name = cp + 1;
  199     else
  200         program_name = argv[0];
  201 
  202     opterr = 0;
  203     while ((op = getopt(argc, argv, "i:")) != -1) {
  204         switch (op) {
  205 
  206         case 'i':
  207             device = optarg;
  208             break;
  209 
  210         default:
  211             usage();
  212             /* NOTREACHED */
  213         }
  214     }
  215 
  216     if (device == NULL) {
  217         if (pcap_findalldevs(&devlist, ebuf) == -1)
  218             error("%s", ebuf);
  219         if (devlist == NULL)
  220             error("no interfaces available for capture");
  221         device = strdup(devlist->name);
  222         pcap_freealldevs(devlist);
  223     }
  224     *ebuf = '\0';
  225     pd = pcap_create(device, ebuf);
  226     if (pd == NULL)
  227         error("%s", ebuf);
  228     status = pcap_set_snaplen(pd, 65535);
  229     if (status != 0)
  230         error("%s: pcap_set_snaplen failed: %s",
  231                 device, pcap_statustostr(status));
  232     if (immediate) {
  233         status = pcap_set_immediate_mode(pd, 1);
  234         if (status != 0)
  235             error("%s: pcap_set_immediate_mode failed: %s",
  236                 device, pcap_statustostr(status));
  237     }
  238     status = pcap_set_timeout(pd, 5*60*1000);
  239     if (status != 0)
  240         error("%s: pcap_set_timeout failed: %s",
  241             device, pcap_statustostr(status));
  242     status = pcap_activate(pd);
  243     if (status < 0) {
  244         /*
  245          * pcap_activate() failed.
  246          */
  247         error("%s: %s\n(%s)", device,
  248             pcap_statustostr(status), pcap_geterr(pd));
  249     } else if (status > 0) {
  250         /*
  251          * pcap_activate() succeeded, but it's warning us
  252          * of a problem it had.
  253          */
  254         warning("%s: %s\n(%s)", device,
  255             pcap_statustostr(status), pcap_geterr(pd));
  256     }
  257     if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
  258         localnet = 0;
  259         netmask = 0;
  260         warning("%s", ebuf);
  261     }
  262     cmdbuf = copy_argv(&argv[optind]);
  263 
  264     if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
  265         error("%s", pcap_geterr(pd));
  266 
  267     if (pcap_setfilter(pd, &fcode) < 0)
  268         error("%s", pcap_geterr(pd));
  269 
  270 #ifdef _WIN32
  271     capture_thread = CreateThread(NULL, 0, capture_thread_func, device,
  272         0, NULL);
  273     if (capture_thread == NULL)
  274         error("Can't create capture thread: %s",
  275             win32_strerror(GetLastError()));
  276 #else
  277     status = pthread_create(&capture_thread, NULL, capture_thread_func,
  278         device);
  279     if (status != 0)
  280         error("Can't create capture thread: %s", strerror(status));
  281 #endif
  282     sleep_secs(60);
  283     pcap_breakloop(pd);
  284 #ifdef _WIN32
  285     printf("Setting event\n");
  286     if (!SetEvent(pcap_getevent(pd)))
  287         error("Can't set event for pcap_t: %s",
  288             win32_strerror(GetLastError()));
  289     if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED)
  290         error("Wait for thread termination failed: %s",
  291             win32_strerror(GetLastError()));
  292     CloseHandle(capture_thread);
  293 #else
  294     printf("Sending SIGUSR1\n");
  295     status = pthread_kill(capture_thread, SIGUSR1);
  296     if (status != 0)
  297         warning("Can't interrupt capture thread: %s", strerror(status));
  298     status = pthread_join(capture_thread, &retval);
  299     if (status != 0)
  300         error("Wait for thread termination failed: %s",
  301             strerror(status));
  302 #endif
  303 
  304     pcap_close(pd);
  305     pcap_freecode(&fcode);
  306     exit(status == -1 ? 1 : 0);
  307 }
  308 
  309 static void
  310 countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
  311 {
  312     int *counterp = (int *)user;
  313 
  314     (*counterp)++;
  315 }
  316 
  317 static void
  318 usage(void)
  319 {
  320     (void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n",
  321         program_name);
  322     exit(1);
  323 }
  324 
  325 /* VARARGS */
  326 static void
  327 error(const char *fmt, ...)
  328 {
  329     va_list ap;
  330 
  331     (void)fprintf(stderr, "%s: ", program_name);
  332     va_start(ap, fmt);
  333     (void)vfprintf(stderr, fmt, ap);
  334     va_end(ap);
  335     if (*fmt) {
  336         fmt += strlen(fmt);
  337         if (fmt[-1] != '\n')
  338             (void)fputc('\n', stderr);
  339     }
  340     exit(1);
  341     /* NOTREACHED */
  342 }
  343 
  344 /* VARARGS */
  345 static void
  346 warning(const char *fmt, ...)
  347 {
  348     va_list ap;
  349 
  350     (void)fprintf(stderr, "%s: WARNING: ", program_name);
  351     va_start(ap, fmt);
  352     (void)vfprintf(stderr, fmt, ap);
  353     va_end(ap);
  354     if (*fmt) {
  355         fmt += strlen(fmt);
  356         if (fmt[-1] != '\n')
  357             (void)fputc('\n', stderr);
  358     }
  359 }
  360 
  361 /*
  362  * Copy arg vector into a new buffer, concatenating arguments with spaces.
  363  */
  364 static char *
  365 copy_argv(register char **argv)
  366 {
  367     register char **p;
  368     register u_int len = 0;
  369     char *buf;
  370     char *src, *dst;
  371 
  372     p = argv;
  373     if (*p == 0)
  374         return 0;
  375 
  376     while (*p)
  377         len += strlen(*p++) + 1;
  378 
  379     buf = (char *)malloc(len);
  380     if (buf == NULL)
  381         error("copy_argv: malloc");
  382 
  383     p = argv;
  384     dst = buf;
  385     while ((src = *p++) != NULL) {
  386         while ((*dst++ = *src++) != '\0')
  387             ;
  388         dst[-1] = ' ';
  389     }
  390     dst[-1] = '\0';
  391 
  392     return buf;
  393 }