Member "libpcap-1.10.5/./testprogs/threadsignaltest.c" (30 Aug 2024, 9529 Bytes) of package /linux/misc/libpcap-1.10.5.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 voidcountme(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 voidwarning(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("%dpackets seen,%dpackets 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 == PCAP_ERROR_BREAK) { 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 == PCAP_ERROR) { 171 /* 172 * Error. Report it. 173 */ 174 (void)fprintf(stderr,"%s: pcap_dispatch:%s\n", 175 program_name,pcap_geterr(pd)); 176 } 177 return0; 178 } 179 180 int 181 main(int argc,char**argv) 182 { 183 registerint op; 184 registerchar*cp, *cmdbuf, *device; 185 int do_wakeup =1; 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:n")) != -1) { 204 switch(op) { 205 206 case'i': 207 device = optarg; 208 break; 209 210 case'n': 211 do_wakeup =0; 212 break; 213 214 default: 215 usage(); 216 /* NOTREACHED */ 217 } 218 } 219 220 if(device == NULL) { 221 if(pcap_findalldevs(&devlist, ebuf) == -1) 222 error("%s", ebuf); 223 if(devlist == NULL) 224 error("no interfaces available for capture"); 225 device =strdup(devlist->name); 226 pcap_freealldevs(devlist); 227 } 228 *ebuf ='\0'; 229 pd =pcap_create(device, ebuf); 230 if(pd == NULL) 231 error("%s", ebuf); 232 status =pcap_set_snaplen(pd,65535); 233 if(status !=0) 234 error("%s: pcap_set_snaplen failed:%s", 235 device,pcap_statustostr(status)); 236 status =pcap_set_timeout(pd,5*60*1000); 237 if(status !=0) 238 error("%s: pcap_set_timeout failed:%s", 239 device,pcap_statustostr(status)); 240 status =pcap_activate(pd); 241 if(status <0) { 242 /* 243 * pcap_activate() failed. 244 */ 245 error("%s:%s\n(%s)", device, 246 pcap_statustostr(status),pcap_geterr(pd)); 247 }else if(status >0) { 248 /* 249 * pcap_activate() succeeded, but it's warning us 250 * of a problem it had. 251 */ 252 warning("%s:%s\n(%s)", device, 253 pcap_statustostr(status),pcap_geterr(pd)); 254 } 255 if(pcap_lookupnet(device, &localnet, &netmask, ebuf) <0) { 256 localnet =0; 257 netmask =0; 258 warning("%s", ebuf); 259 } 260 cmdbuf =copy_argv(&argv[optind]); 261 262 if(pcap_compile(pd, &fcode, cmdbuf,1, netmask) <0) 263 error("%s",pcap_geterr(pd)); 264 265 if(pcap_setfilter(pd, &fcode) <0) 266 error("%s",pcap_geterr(pd)); 267 268 #ifdef _WIN32 269 capture_thread =CreateThread(NULL,0, capture_thread_func, device, 270 0, NULL); 271 if(capture_thread == NULL) 272 error("Can't create capture thread:%s", 273 win32_strerror(GetLastError())); 274 #else 275 status =pthread_create(&capture_thread, NULL, capture_thread_func, 276 device); 277 if(status !=0) 278 error("Can't create capture thread:%s",strerror(status)); 279 #endif 280 sleep_secs(60); 281 printf("Doing pcap_breakloop()\n"); 282 pcap_breakloop(pd); 283 if(do_wakeup) { 284 /* 285 * Force a wakeup in the capture thread. 286 * 287 * On some platforms, with some devices,, pcap_breakloop() 288 * can't do that itself. On Windows, poke the device's 289 * event handle; on UN*X, send a SIGUSR1 to the thread. 290 */ 291 #ifdef _WIN32 292 printf("Setting event\n"); 293 if(!SetEvent(pcap_getevent(pd))) 294 error("Can't set event for pcap_t:%s", 295 win32_strerror(GetLastError())); 296 #else 297 printf("Sending SIGUSR1\n"); 298 status =pthread_kill(capture_thread, SIGUSR1); 299 if(status !=0) 300 warning("Can't interrupt capture thread:%s", 301 strerror(status)); 302 #endif 303 } 304 305 /* 306 * Now wait for the capture thread to terminate. 307 */ 308 #ifdef _WIN32 309 if(WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED) 310 error("Wait for thread termination failed:%s", 311 win32_strerror(GetLastError())); 312 CloseHandle(capture_thread); 313 #else 314 status =pthread_join(capture_thread, &retval); 315 if(status !=0) 316 error("Wait for thread termination failed:%s", 317 strerror(status)); 318 #endif 319 320 pcap_close(pd); 321 pcap_freecode(&fcode); 322 exit(status == -1?1:0); 323 } 324 325 static void 326 countme(u_char *user,const struct pcap_pkthdr *h _U_,const u_char *sp _U_) 327 { 328 int*counterp = (int*)user; 329 330 (*counterp)++; 331 } 332 333 static void 334 usage(void) 335 { 336 (void)fprintf(stderr,"Usage:%s[ -n ] [ -i interface ] [ expression ]\n", 337 program_name); 338 exit(1); 339 } 340 341 /* VARARGS */ 342 static void 343 error(const char*fmt, ...) 344 { 345 va_list ap; 346 347 (void)fprintf(stderr,"%s: ", program_name); 348 va_start(ap, fmt); 349 (void)vfprintf(stderr, fmt, ap); 350 va_end(ap); 351 if(*fmt) { 352 fmt +=strlen(fmt); 353 if(fmt[-1] !='\n') 354 (void)fputc('\n', stderr); 355 } 356 exit(1); 357 /* NOTREACHED */ 358 } 359 360 /* VARARGS */ 361 static void 362 warning(const char*fmt, ...) 363 { 364 va_list ap; 365 366 (void)fprintf(stderr,"%s: WARNING: ", program_name); 367 va_start(ap, fmt); 368 (void)vfprintf(stderr, fmt, ap); 369 va_end(ap); 370 if(*fmt) { 371 fmt +=strlen(fmt); 372 if(fmt[-1] !='\n') 373 (void)fputc('\n', stderr); 374 } 375 } 376 377 /* 378 * Copy arg vector into a new buffer, concatenating arguments with spaces. 379 */ 380 static char* 381 copy_argv(registerchar**argv) 382 { 383 registerchar**p; 384 registersize_t len =0; 385 char*buf; 386 char*src, *dst; 387 388 p = argv; 389 if(*p ==0) 390 return0; 391 392 while(*p) 393 len +=strlen(*p++) +1; 394 395 buf = (char*)malloc(len); 396 if(buf == NULL) 397 error("copy_argv: malloc"); 398 399 p = argv; 400 dst = buf; 401 while((src = *p++) != NULL) { 402 while((*dst++ = *src++) !='\0') 403 ; 404 dst[-1] =' '; 405 } 406 dst[-1] ='\0'; 407 408 return buf; 409 }