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 1268cf6c252SPaul Traina pcap_snapshot(pcap_t *p) 1278cf6c252SPaul Traina { 1288cf6c252SPaul Traina return (p->snapshot); 1298cf6c252SPaul Traina } 1308cf6c252SPaul Traina 1318cf6c252SPaul Traina int 1328cf6c252SPaul Traina pcap_is_swapped(pcap_t *p) 1338cf6c252SPaul Traina { 1348cf6c252SPaul Traina return (p->sf.swapped); 1358cf6c252SPaul Traina } 1368cf6c252SPaul Traina 1378cf6c252SPaul Traina int 1388cf6c252SPaul Traina pcap_major_version(pcap_t *p) 1398cf6c252SPaul Traina { 1408cf6c252SPaul Traina return (p->sf.version_major); 1418cf6c252SPaul Traina } 1428cf6c252SPaul Traina 1438cf6c252SPaul Traina int 1448cf6c252SPaul Traina pcap_minor_version(pcap_t *p) 1458cf6c252SPaul Traina { 1468cf6c252SPaul Traina return (p->sf.version_minor); 1478cf6c252SPaul Traina } 1488cf6c252SPaul Traina 1498cf6c252SPaul Traina FILE * 1508cf6c252SPaul Traina pcap_file(pcap_t *p) 1518cf6c252SPaul Traina { 1528cf6c252SPaul Traina return (p->sf.rfile); 1538cf6c252SPaul Traina } 1548cf6c252SPaul Traina 1558cf6c252SPaul Traina int 1568cf6c252SPaul Traina pcap_fileno(pcap_t *p) 1578cf6c252SPaul Traina { 1588cf6c252SPaul Traina return (p->fd); 1598cf6c252SPaul Traina } 1608cf6c252SPaul Traina 1618cf6c252SPaul Traina void 1628cf6c252SPaul Traina pcap_perror(pcap_t *p, char *prefix) 1638cf6c252SPaul Traina { 1648cf6c252SPaul Traina fprintf(stderr, "%s: %s\n", prefix, p->errbuf); 1658cf6c252SPaul Traina } 1668cf6c252SPaul Traina 1678cf6c252SPaul Traina char * 1688cf6c252SPaul Traina pcap_geterr(pcap_t *p) 1698cf6c252SPaul Traina { 1708cf6c252SPaul Traina return (p->errbuf); 1718cf6c252SPaul Traina } 1728cf6c252SPaul Traina 1738cf6c252SPaul Traina /* 1740a94d38fSBill Fenner * NOTE: in the future, these may need to call platform-dependent routines, 1750a94d38fSBill Fenner * e.g. on platforms with memory-mapped packet-capture mechanisms where 1760a94d38fSBill Fenner * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive. 1770a94d38fSBill Fenner */ 1780a94d38fSBill Fenner int 1790a94d38fSBill Fenner pcap_getnonblock(pcap_t *p, char *errbuf) 1800a94d38fSBill Fenner { 1810a94d38fSBill Fenner int fdflags; 1820a94d38fSBill Fenner 1830a94d38fSBill Fenner if (p->sf.rfile != NULL) { 1840a94d38fSBill Fenner /* 1850a94d38fSBill Fenner * This is a savefile, not a live capture file, so 1860a94d38fSBill Fenner * never say it's in non-blocking mode. 1870a94d38fSBill Fenner */ 1880a94d38fSBill Fenner return (0); 1890a94d38fSBill Fenner } 1900a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 1910a94d38fSBill Fenner if (fdflags == -1) { 1920a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 1930a94d38fSBill Fenner pcap_strerror(errno)); 1940a94d38fSBill Fenner return (-1); 1950a94d38fSBill Fenner } 1960a94d38fSBill Fenner if (fdflags & O_NONBLOCK) 1970a94d38fSBill Fenner return (1); 1980a94d38fSBill Fenner else 1990a94d38fSBill Fenner return (0); 2000a94d38fSBill Fenner } 2010a94d38fSBill Fenner 2020a94d38fSBill Fenner int 2030a94d38fSBill Fenner pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) 2040a94d38fSBill Fenner { 2050a94d38fSBill Fenner int fdflags; 2060a94d38fSBill Fenner 2070a94d38fSBill Fenner if (p->sf.rfile != NULL) { 2080a94d38fSBill Fenner /* 2090a94d38fSBill Fenner * This is a savefile, not a live capture file, so 2100a94d38fSBill Fenner * ignore requests to put it in non-blocking mode. 2110a94d38fSBill Fenner */ 2120a94d38fSBill Fenner return (0); 2130a94d38fSBill Fenner } 2140a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0); 2150a94d38fSBill Fenner if (fdflags == -1) { 2160a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 2170a94d38fSBill Fenner pcap_strerror(errno)); 2180a94d38fSBill Fenner return (-1); 2190a94d38fSBill Fenner } 2200a94d38fSBill Fenner if (nonblock) 2210a94d38fSBill Fenner fdflags |= O_NONBLOCK; 2220a94d38fSBill Fenner else 2230a94d38fSBill Fenner fdflags &= ~O_NONBLOCK; 2240a94d38fSBill Fenner if (fcntl(p->fd, F_SETFL, fdflags) == -1) { 2250a94d38fSBill Fenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", 2260a94d38fSBill Fenner pcap_strerror(errno)); 2270a94d38fSBill Fenner return (-1); 2280a94d38fSBill Fenner } 2290a94d38fSBill Fenner return (0); 2300a94d38fSBill Fenner } 2310a94d38fSBill Fenner 2320a94d38fSBill Fenner /* 2338cf6c252SPaul Traina * Not all systems have strerror(). 2348cf6c252SPaul Traina */ 2358cf6c252SPaul Traina char * 2368cf6c252SPaul Traina pcap_strerror(int errnum) 2378cf6c252SPaul Traina { 2388cf6c252SPaul Traina #ifdef HAVE_STRERROR 2398cf6c252SPaul Traina return (strerror(errnum)); 2408cf6c252SPaul Traina #else 2418cf6c252SPaul Traina extern int sys_nerr; 2428cf6c252SPaul Traina extern const char *const sys_errlist[]; 2438cf6c252SPaul Traina static char ebuf[20]; 2448cf6c252SPaul Traina 2458cf6c252SPaul Traina if ((unsigned int)errnum < sys_nerr) 2468cf6c252SPaul Traina return ((char *)sys_errlist[errnum]); 247dc2c7305SBill Fenner (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 2488cf6c252SPaul Traina return(ebuf); 2498cf6c252SPaul Traina #endif 2508cf6c252SPaul Traina } 2518cf6c252SPaul Traina 252dc2c7305SBill Fenner pcap_t * 253dc2c7305SBill Fenner pcap_open_dead(int linktype, int snaplen) 254dc2c7305SBill Fenner { 255dc2c7305SBill Fenner pcap_t *p; 256dc2c7305SBill Fenner 257dc2c7305SBill Fenner p = malloc(sizeof(*p)); 258dc2c7305SBill Fenner if (p == NULL) 259dc2c7305SBill Fenner return NULL; 260dc2c7305SBill Fenner memset (p, 0, sizeof(*p)); 261dc2c7305SBill Fenner p->fd = -1; 262dc2c7305SBill Fenner p->snapshot = snaplen; 263dc2c7305SBill Fenner p->linktype = linktype; 264dc2c7305SBill Fenner return p; 265dc2c7305SBill Fenner } 266dc2c7305SBill Fenner 2678cf6c252SPaul Traina void 2688cf6c252SPaul Traina pcap_close(pcap_t *p) 2698cf6c252SPaul Traina { 2708cf6c252SPaul Traina /*XXX*/ 271dc2c7305SBill Fenner if (p->fd >= 0) { 272dc2c7305SBill Fenner #ifdef linux 273dc2c7305SBill Fenner pcap_close_linux(p); 274dc2c7305SBill Fenner #endif 2758cf6c252SPaul Traina close(p->fd); 276dc2c7305SBill Fenner } 2778cf6c252SPaul Traina if (p->sf.rfile != NULL) { 278dc2c7305SBill Fenner if (p->sf.rfile != stdin) 2798cf6c252SPaul Traina (void)fclose(p->sf.rfile); 2808cf6c252SPaul Traina if (p->sf.base != NULL) 2818cf6c252SPaul Traina free(p->sf.base); 2828cf6c252SPaul Traina } else if (p->buffer != NULL) 2838cf6c252SPaul Traina free(p->buffer); 2848cf6c252SPaul Traina 285dc2c7305SBill Fenner pcap_freecode(&p->fcode); 2868cf6c252SPaul Traina free(p); 2878cf6c252SPaul Traina } 288