18cf6c252SPaul Traina /* 2a4b5b39fSBill Fenner * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 38cf6c252SPaul Traina * The Regents of the University of California. All rights reserved. 48cf6c252SPaul Traina * 58cf6c252SPaul Traina * Redistribution and use in source and binary forms, with or without 68cf6c252SPaul Traina * modification, are permitted provided that the following conditions 78cf6c252SPaul Traina * are met: 88cf6c252SPaul Traina * 1. Redistributions of source code must retain the above copyright 98cf6c252SPaul Traina * notice, this list of conditions and the following disclaimer. 108cf6c252SPaul Traina * 2. Redistributions in binary form must reproduce the above copyright 118cf6c252SPaul Traina * notice, this list of conditions and the following disclaimer in the 128cf6c252SPaul Traina * documentation and/or other materials provided with the distribution. 138cf6c252SPaul Traina * 3. All advertising materials mentioning features or use of this software 148cf6c252SPaul Traina * must display the following acknowledgement: 158cf6c252SPaul Traina * This product includes software developed by the Computer Systems 168cf6c252SPaul Traina * Engineering Group at Lawrence Berkeley Laboratory. 178cf6c252SPaul Traina * 4. Neither the name of the University nor of the Laboratory may be used 188cf6c252SPaul Traina * to endorse or promote products derived from this software without 198cf6c252SPaul Traina * specific prior written permission. 208cf6c252SPaul Traina * 218cf6c252SPaul Traina * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228cf6c252SPaul Traina * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238cf6c252SPaul Traina * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248cf6c252SPaul Traina * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258cf6c252SPaul Traina * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268cf6c252SPaul Traina * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278cf6c252SPaul Traina * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288cf6c252SPaul Traina * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298cf6c252SPaul Traina * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308cf6c252SPaul Traina * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318cf6c252SPaul Traina * SUCH DAMAGE. 328cf6c252SPaul Traina */ 338cf6c252SPaul Traina 348cf6c252SPaul Traina #ifndef lint 353052b236SBill Fenner static const char rcsid[] = 360a94d38fSBill Fenner "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.38 2001/12/29 21:55:32 guy Exp $ (LBL)"; 37dc2c7305SBill Fenner #endif 38dc2c7305SBill Fenner 39dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 40dc2c7305SBill Fenner #include "config.h" 418cf6c252SPaul Traina #endif 428cf6c252SPaul Traina 438cf6c252SPaul Traina #include <sys/types.h> 448cf6c252SPaul Traina 458cf6c252SPaul Traina #include <stdio.h> 468cf6c252SPaul Traina #include <stdlib.h> 478cf6c252SPaul Traina #include <string.h> 488cf6c252SPaul Traina #include <unistd.h> 490a94d38fSBill Fenner #include <fcntl.h> 500a94d38fSBill Fenner #include <errno.h> 518cf6c252SPaul Traina 528cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 538cf6c252SPaul Traina #include "os-proto.h" 548cf6c252SPaul Traina #endif 558cf6c252SPaul Traina 568cf6c252SPaul Traina #include "pcap-int.h" 578cf6c252SPaul Traina 588cf6c252SPaul Traina int 598cf6c252SPaul Traina pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 608cf6c252SPaul Traina { 618cf6c252SPaul Traina 628cf6c252SPaul Traina if (p->sf.rfile != NULL) 638cf6c252SPaul Traina return (pcap_offline_read(p, cnt, callback, user)); 64a4b5b39fSBill Fenner return (pcap_read(p, cnt, callback, user)); 658cf6c252SPaul Traina } 668cf6c252SPaul Traina 678cf6c252SPaul Traina int 688cf6c252SPaul Traina pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 698cf6c252SPaul Traina { 70a4b5b39fSBill Fenner register int n; 71a4b5b39fSBill Fenner 728cf6c252SPaul Traina for (;;) { 73a4b5b39fSBill Fenner if (p->sf.rfile != NULL) 74a4b5b39fSBill Fenner n = pcap_offline_read(p, cnt, callback, user); 75a4b5b39fSBill Fenner else { 76a4b5b39fSBill Fenner /* 77a4b5b39fSBill Fenner * XXX keep reading until we get something 78a4b5b39fSBill Fenner * (or an error occurs) 79a4b5b39fSBill Fenner */ 80a4b5b39fSBill Fenner do { 81a4b5b39fSBill Fenner n = pcap_read(p, cnt, callback, user); 82a4b5b39fSBill Fenner } while (n == 0); 83a4b5b39fSBill Fenner } 848cf6c252SPaul Traina if (n <= 0) 858cf6c252SPaul Traina return (n); 868cf6c252SPaul Traina if (cnt > 0) { 878cf6c252SPaul Traina cnt -= n; 888cf6c252SPaul Traina if (cnt <= 0) 898cf6c252SPaul Traina return (0); 908cf6c252SPaul Traina } 918cf6c252SPaul Traina } 928cf6c252SPaul Traina } 938cf6c252SPaul Traina 948cf6c252SPaul Traina struct singleton { 958cf6c252SPaul Traina struct pcap_pkthdr *hdr; 968cf6c252SPaul Traina const u_char *pkt; 978cf6c252SPaul Traina }; 988cf6c252SPaul Traina 998cf6c252SPaul Traina 1008cf6c252SPaul Traina static void 1018cf6c252SPaul Traina pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) 1028cf6c252SPaul Traina { 1038cf6c252SPaul Traina struct singleton *sp = (struct singleton *)userData; 1048cf6c252SPaul Traina *sp->hdr = *h; 1058cf6c252SPaul Traina sp->pkt = pkt; 1068cf6c252SPaul Traina } 1078cf6c252SPaul Traina 1088cf6c252SPaul Traina const u_char * 1098cf6c252SPaul Traina pcap_next(pcap_t *p, struct pcap_pkthdr *h) 1108cf6c252SPaul Traina { 1118cf6c252SPaul Traina struct singleton s; 1128cf6c252SPaul Traina 1138cf6c252SPaul Traina s.hdr = h; 1148cf6c252SPaul Traina if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) 1158cf6c252SPaul Traina return (0); 1168cf6c252SPaul Traina return (s.pkt); 1178cf6c252SPaul Traina } 1188cf6c252SPaul Traina 1198cf6c252SPaul Traina int 1208cf6c252SPaul Traina pcap_datalink(pcap_t *p) 1218cf6c252SPaul Traina { 1228cf6c252SPaul Traina return (p->linktype); 1238cf6c252SPaul Traina } 1248cf6c252SPaul Traina 1258cf6c252SPaul Traina int 12609f33d61SBill Fenner pcap_list_datalinks(pcap_t *p, int **dlt_buffer) 12709f33d61SBill Fenner { 12809f33d61SBill Fenner if (p->dlt_count <= 0) { 12909f33d61SBill Fenner *dlt_buffer = NULL; 13009f33d61SBill Fenner return -1; 13109f33d61SBill Fenner } 13209f33d61SBill Fenner *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count); 13309f33d61SBill Fenner if (*dlt_buffer == NULL) { 13409f33d61SBill Fenner (void)snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", 13509f33d61SBill Fenner pcap_strerror(errno)); 13609f33d61SBill Fenner return -1; 13709f33d61SBill Fenner } 13809f33d61SBill Fenner (void)memcpy(*dlt_buffer, p->dlt_list, 13909f33d61SBill Fenner sizeof(**dlt_buffer) * p->dlt_count); 14009f33d61SBill Fenner return (p->dlt_count); 14109f33d61SBill Fenner } 14209f33d61SBill Fenner 14309f33d61SBill Fenner int 1448cf6c252SPaul Traina pcap_snapshot(pcap_t *p) 1458cf6c252SPaul Traina { 1468cf6c252SPaul Traina return (p->snapshot); 1478cf6c252SPaul Traina } 1488cf6c252SPaul Traina 1498cf6c252SPaul Traina int 1508cf6c252SPaul Traina pcap_is_swapped(pcap_t *p) 1518cf6c252SPaul Traina { 1528cf6c252SPaul Traina return (p->sf.swapped); 1538cf6c252SPaul Traina } 1548cf6c252SPaul Traina 1558cf6c252SPaul Traina int 1568cf6c252SPaul Traina pcap_major_version(pcap_t *p) 1578cf6c252SPaul Traina { 1588cf6c252SPaul Traina return (p->sf.version_major); 1598cf6c252SPaul Traina } 1608cf6c252SPaul Traina 1618cf6c252SPaul Traina int 1628cf6c252SPaul Traina pcap_minor_version(pcap_t *p) 1638cf6c252SPaul Traina { 1648cf6c252SPaul Traina return (p->sf.version_minor); 1658cf6c252SPaul Traina } 1668cf6c252SPaul Traina 1678cf6c252SPaul Traina FILE * 1688cf6c252SPaul Traina pcap_file(pcap_t *p) 1698cf6c252SPaul Traina { 1708cf6c252SPaul Traina return (p->sf.rfile); 1718cf6c252SPaul Traina } 1728cf6c252SPaul Traina 1738cf6c252SPaul Traina int 1748cf6c252SPaul Traina pcap_fileno(pcap_t *p) 1758cf6c252SPaul Traina { 1768cf6c252SPaul Traina return (p->fd); 1778cf6c252SPaul Traina } 1788cf6c252SPaul Traina 1798cf6c252SPaul Traina void 1808cf6c252SPaul Traina pcap_perror(pcap_t *p, char *prefix) 1818cf6c252SPaul Traina { 1828cf6c252SPaul Traina fprintf(stderr, "%s: %s\n", prefix, p->errbuf); 1838cf6c252SPaul Traina } 1848cf6c252SPaul Traina 1858cf6c252SPaul Traina char * 1868cf6c252SPaul Traina pcap_geterr(pcap_t *p) 1878cf6c252SPaul Traina { 1888cf6c252SPaul Traina return (p->errbuf); 1898cf6c252SPaul Traina } 1908cf6c252SPaul Traina 1918cf6c252SPaul Traina /* 1920a94d38fSBill Fenner * NOTE: in the future, these may need to call platform-dependent routines, 1930a94d38fSBill Fenner * e.g. on platforms with memory-mapped packet-capture mechanisms where 1940a94d38fSBill Fenner * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive. 1950a94d38fSBill Fenner */ 1960a94d38fSBill Fenner int 1970a94d38fSBill Fenner pcap_getnonblock(pcap_t *p, char *errbuf) 1980a94d38fSBill Fenner { 1990a94d38fSBill Fenner int fdflags; 2000a94d38fSBill Fenner 2010a94d38fSBill Fenner if (p->sf.rfile != NULL) { 2020a94d38fSBill Fenner /* 2030a94d38fSBill Fenner * This is a savefile, not a live capture file, so 2040a94d38fSBill Fenner * never say it's in non-blocking mode. 2050a94d38fSBill Fenner */ 2060a94d38fSBill Fenner return (0); 2070a94d38fSBill Fenner } 2080a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 2090a94d38fSBill Fenner if (fdflags == -1) { 2100a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 2110a94d38fSBill Fenner pcap_strerror(errno)); 2120a94d38fSBill Fenner return (-1); 2130a94d38fSBill Fenner } 2140a94d38fSBill Fenner if (fdflags & O_NONBLOCK) 2150a94d38fSBill Fenner return (1); 2160a94d38fSBill Fenner else 2170a94d38fSBill Fenner return (0); 2180a94d38fSBill Fenner } 2190a94d38fSBill Fenner 2200a94d38fSBill Fenner int 2210a94d38fSBill Fenner pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) 2220a94d38fSBill Fenner { 2230a94d38fSBill Fenner int fdflags; 2240a94d38fSBill Fenner 2250a94d38fSBill Fenner if (p->sf.rfile != NULL) { 2260a94d38fSBill Fenner /* 2270a94d38fSBill Fenner * This is a savefile, not a live capture file, so 2280a94d38fSBill Fenner * ignore requests to put it in non-blocking mode. 2290a94d38fSBill Fenner */ 2300a94d38fSBill Fenner return (0); 2310a94d38fSBill Fenner } 2320a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 2330a94d38fSBill Fenner if (fdflags == -1) { 2340a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 2350a94d38fSBill Fenner pcap_strerror(errno)); 2360a94d38fSBill Fenner return (-1); 2370a94d38fSBill Fenner } 2380a94d38fSBill Fenner if (nonblock) 2390a94d38fSBill Fenner fdflags |= O_NONBLOCK; 2400a94d38fSBill Fenner else 2410a94d38fSBill Fenner fdflags &= ~O_NONBLOCK; 2420a94d38fSBill Fenner if (fcntl(p->fd, F_SETFL, fdflags) == -1) { 2430a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", 2440a94d38fSBill Fenner pcap_strerror(errno)); 2450a94d38fSBill Fenner return (-1); 2460a94d38fSBill Fenner } 2470a94d38fSBill Fenner return (0); 2480a94d38fSBill Fenner } 2490a94d38fSBill Fenner 2500a94d38fSBill Fenner /* 2518cf6c252SPaul Traina * Not all systems have strerror(). 2528cf6c252SPaul Traina */ 2538cf6c252SPaul Traina char * 2548cf6c252SPaul Traina pcap_strerror(int errnum) 2558cf6c252SPaul Traina { 2568cf6c252SPaul Traina #ifdef HAVE_STRERROR 2578cf6c252SPaul Traina return (strerror(errnum)); 2588cf6c252SPaul Traina #else 2598cf6c252SPaul Traina extern int sys_nerr; 2608cf6c252SPaul Traina extern const char *const sys_errlist[]; 2618cf6c252SPaul Traina static char ebuf[20]; 2628cf6c252SPaul Traina 2638cf6c252SPaul Traina if ((unsigned int)errnum < sys_nerr) 2648cf6c252SPaul Traina return ((char *)sys_errlist[errnum]); 265dc2c7305SBill Fenner (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 2668cf6c252SPaul Traina return(ebuf); 2678cf6c252SPaul Traina #endif 2688cf6c252SPaul Traina } 2698cf6c252SPaul Traina 270dc2c7305SBill Fenner pcap_t * 271dc2c7305SBill Fenner pcap_open_dead(int linktype, int snaplen) 272dc2c7305SBill Fenner { 273dc2c7305SBill Fenner pcap_t *p; 274dc2c7305SBill Fenner 275dc2c7305SBill Fenner p = malloc(sizeof(*p)); 276dc2c7305SBill Fenner if (p == NULL) 277dc2c7305SBill Fenner return NULL; 278dc2c7305SBill Fenner memset (p, 0, sizeof(*p)); 279dc2c7305SBill Fenner p->fd = -1; 280dc2c7305SBill Fenner p->snapshot = snaplen; 281dc2c7305SBill Fenner p->linktype = linktype; 282dc2c7305SBill Fenner return p; 283dc2c7305SBill Fenner } 284dc2c7305SBill Fenner 2858cf6c252SPaul Traina void 2868cf6c252SPaul Traina pcap_close(pcap_t *p) 2878cf6c252SPaul Traina { 2888cf6c252SPaul Traina /*XXX*/ 289dc2c7305SBill Fenner if (p->fd >= 0) { 290dc2c7305SBill Fenner #ifdef linux 291dc2c7305SBill Fenner pcap_close_linux(p); 292dc2c7305SBill Fenner #endif 2938cf6c252SPaul Traina close(p->fd); 294dc2c7305SBill Fenner } 2958cf6c252SPaul Traina if (p->sf.rfile != NULL) { 296dc2c7305SBill Fenner if (p->sf.rfile != stdin) 2978cf6c252SPaul Traina (void)fclose(p->sf.rfile); 2988cf6c252SPaul Traina if (p->sf.base != NULL) 2998cf6c252SPaul Traina free(p->sf.base); 3008cf6c252SPaul Traina } else if (p->buffer != NULL) 3018cf6c252SPaul Traina free(p->buffer); 30209f33d61SBill Fenner if (p->dlt_list != NULL) 30309f33d61SBill Fenner free(p->dlt_list); 3048cf6c252SPaul Traina 305dc2c7305SBill Fenner pcap_freecode(&p->fcode); 3068cf6c252SPaul Traina free(p); 3078cf6c252SPaul Traina } 308