pcap.c revision 98530
117683Spst/* 239291Sfenner * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that the following conditions 717683Spst * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer. 1017683Spst * 2. Redistributions in binary form must reproduce the above copyright 1117683Spst * notice, this list of conditions and the following disclaimer in the 1217683Spst * documentation and/or other materials provided with the distribution. 1317683Spst * 3. All advertising materials mentioning features or use of this software 1417683Spst * must display the following acknowledgement: 1517683Spst * This product includes software developed by the Computer Systems 1617683Spst * Engineering Group at Lawrence Berkeley Laboratory. 1717683Spst * 4. Neither the name of the University nor of the Laboratory may be used 1817683Spst * to endorse or promote products derived from this software without 1917683Spst * specific prior written permission. 2017683Spst * 2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2217683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2317683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2617683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2717683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2817683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2917683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3217683Spst */ 3317683Spst 3417683Spst#ifndef lint 3526175Sfennerstatic const char rcsid[] = 3698530Sfenner "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.38 2001/12/29 21:55:32 guy Exp $ (LBL)"; 3717683Spst#endif 3817683Spst 3975107Sfenner#ifdef HAVE_CONFIG_H 4075107Sfenner#include "config.h" 4175107Sfenner#endif 4275107Sfenner 4317683Spst#include <sys/types.h> 4417683Spst 4517683Spst#include <stdio.h> 4617683Spst#include <stdlib.h> 4717683Spst#include <string.h> 4817683Spst#include <unistd.h> 4998530Sfenner#include <fcntl.h> 5098530Sfenner#include <errno.h> 5117683Spst 5217683Spst#ifdef HAVE_OS_PROTO_H 5317683Spst#include "os-proto.h" 5417683Spst#endif 5517683Spst 5617683Spst#include "pcap-int.h" 5717683Spst 5817683Spstint 5917683Spstpcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 6017683Spst{ 6117683Spst 6217683Spst if (p->sf.rfile != NULL) 6317683Spst return (pcap_offline_read(p, cnt, callback, user)); 6439291Sfenner return (pcap_read(p, cnt, callback, user)); 6517683Spst} 6617683Spst 6717683Spstint 6817683Spstpcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 6917683Spst{ 7039291Sfenner register int n; 7139291Sfenner 7217683Spst for (;;) { 7339291Sfenner if (p->sf.rfile != NULL) 7439291Sfenner n = pcap_offline_read(p, cnt, callback, user); 7539291Sfenner else { 7639291Sfenner /* 7739291Sfenner * XXX keep reading until we get something 7839291Sfenner * (or an error occurs) 7939291Sfenner */ 8039291Sfenner do { 8139291Sfenner n = pcap_read(p, cnt, callback, user); 8239291Sfenner } while (n == 0); 8339291Sfenner } 8417683Spst if (n <= 0) 8517683Spst return (n); 8617683Spst if (cnt > 0) { 8717683Spst cnt -= n; 8817683Spst if (cnt <= 0) 8917683Spst return (0); 9017683Spst } 9117683Spst } 9217683Spst} 9317683Spst 9417683Spststruct singleton { 9517683Spst struct pcap_pkthdr *hdr; 9617683Spst const u_char *pkt; 9717683Spst}; 9817683Spst 9917683Spst 10017683Spststatic void 10117683Spstpcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) 10217683Spst{ 10317683Spst struct singleton *sp = (struct singleton *)userData; 10417683Spst *sp->hdr = *h; 10517683Spst sp->pkt = pkt; 10617683Spst} 10717683Spst 10817683Spstconst u_char * 10917683Spstpcap_next(pcap_t *p, struct pcap_pkthdr *h) 11017683Spst{ 11117683Spst struct singleton s; 11217683Spst 11317683Spst s.hdr = h; 11417683Spst if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) 11517683Spst return (0); 11617683Spst return (s.pkt); 11717683Spst} 11817683Spst 11917683Spstint 12017683Spstpcap_datalink(pcap_t *p) 12117683Spst{ 12217683Spst return (p->linktype); 12317683Spst} 12417683Spst 12517683Spstint 12617683Spstpcap_snapshot(pcap_t *p) 12717683Spst{ 12817683Spst return (p->snapshot); 12917683Spst} 13017683Spst 13117683Spstint 13217683Spstpcap_is_swapped(pcap_t *p) 13317683Spst{ 13417683Spst return (p->sf.swapped); 13517683Spst} 13617683Spst 13717683Spstint 13817683Spstpcap_major_version(pcap_t *p) 13917683Spst{ 14017683Spst return (p->sf.version_major); 14117683Spst} 14217683Spst 14317683Spstint 14417683Spstpcap_minor_version(pcap_t *p) 14517683Spst{ 14617683Spst return (p->sf.version_minor); 14717683Spst} 14817683Spst 14917683SpstFILE * 15017683Spstpcap_file(pcap_t *p) 15117683Spst{ 15217683Spst return (p->sf.rfile); 15317683Spst} 15417683Spst 15517683Spstint 15617683Spstpcap_fileno(pcap_t *p) 15717683Spst{ 15817683Spst return (p->fd); 15917683Spst} 16017683Spst 16117683Spstvoid 16217683Spstpcap_perror(pcap_t *p, char *prefix) 16317683Spst{ 16417683Spst fprintf(stderr, "%s: %s\n", prefix, p->errbuf); 16517683Spst} 16617683Spst 16717683Spstchar * 16817683Spstpcap_geterr(pcap_t *p) 16917683Spst{ 17017683Spst return (p->errbuf); 17117683Spst} 17217683Spst 17317683Spst/* 17498530Sfenner * NOTE: in the future, these may need to call platform-dependent routines, 17598530Sfenner * e.g. on platforms with memory-mapped packet-capture mechanisms where 17698530Sfenner * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive. 17798530Sfenner */ 17898530Sfennerint 17998530Sfennerpcap_getnonblock(pcap_t *p, char *errbuf) 18098530Sfenner{ 18198530Sfenner int fdflags; 18298530Sfenner 18398530Sfenner if (p->sf.rfile != NULL) { 18498530Sfenner /* 18598530Sfenner * This is a savefile, not a live capture file, so 18698530Sfenner * never say it's in non-blocking mode. 18798530Sfenner */ 18898530Sfenner return (0); 18998530Sfenner } 19098530Sfenner fdflags = fcntl(p->fd, F_GETFL, 0); 19198530Sfenner if (fdflags == -1) { 19298530Sfenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 19398530Sfenner pcap_strerror(errno)); 19498530Sfenner return (-1); 19598530Sfenner } 19698530Sfenner if (fdflags & O_NONBLOCK) 19798530Sfenner return (1); 19898530Sfenner else 19998530Sfenner return (0); 20098530Sfenner} 20198530Sfenner 20298530Sfennerint 20398530Sfennerpcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) 20498530Sfenner{ 20598530Sfenner int fdflags; 20698530Sfenner 20798530Sfenner if (p->sf.rfile != NULL) { 20898530Sfenner /* 20998530Sfenner * This is a savefile, not a live capture file, so 21098530Sfenner * ignore requests to put it in non-blocking mode. 21198530Sfenner */ 21298530Sfenner return (0); 21398530Sfenner } 21498530Sfenner fdflags = fcntl(p->fd, F_GETFL, 0); 21598530Sfenner if (fdflags == -1) { 21698530Sfenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", 21798530Sfenner pcap_strerror(errno)); 21898530Sfenner return (-1); 21998530Sfenner } 22098530Sfenner if (nonblock) 22198530Sfenner fdflags |= O_NONBLOCK; 22298530Sfenner else 22398530Sfenner fdflags &= ~O_NONBLOCK; 22498530Sfenner if (fcntl(p->fd, F_SETFL, fdflags) == -1) { 22598530Sfenner snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", 22698530Sfenner pcap_strerror(errno)); 22798530Sfenner return (-1); 22898530Sfenner } 22998530Sfenner return (0); 23098530Sfenner} 23198530Sfenner 23298530Sfenner/* 23317683Spst * Not all systems have strerror(). 23417683Spst */ 23517683Spstchar * 23617683Spstpcap_strerror(int errnum) 23717683Spst{ 23817683Spst#ifdef HAVE_STRERROR 23917683Spst return (strerror(errnum)); 24017683Spst#else 24117683Spst extern int sys_nerr; 24217683Spst extern const char *const sys_errlist[]; 24317683Spst static char ebuf[20]; 24417683Spst 24517683Spst if ((unsigned int)errnum < sys_nerr) 24617683Spst return ((char *)sys_errlist[errnum]); 24775107Sfenner (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); 24817683Spst return(ebuf); 24917683Spst#endif 25017683Spst} 25117683Spst 25275107Sfennerpcap_t * 25375107Sfennerpcap_open_dead(int linktype, int snaplen) 25475107Sfenner{ 25575107Sfenner pcap_t *p; 25675107Sfenner 25775107Sfenner p = malloc(sizeof(*p)); 25875107Sfenner if (p == NULL) 25975107Sfenner return NULL; 26075107Sfenner memset (p, 0, sizeof(*p)); 26175107Sfenner p->fd = -1; 26275107Sfenner p->snapshot = snaplen; 26375107Sfenner p->linktype = linktype; 26475107Sfenner return p; 26575107Sfenner} 26675107Sfenner 26717683Spstvoid 26817683Spstpcap_close(pcap_t *p) 26917683Spst{ 27017683Spst /*XXX*/ 27175107Sfenner if (p->fd >= 0) { 27275107Sfenner#ifdef linux 27375107Sfenner pcap_close_linux(p); 27475107Sfenner#endif 27517683Spst close(p->fd); 27675107Sfenner } 27717683Spst if (p->sf.rfile != NULL) { 27875107Sfenner if (p->sf.rfile != stdin) 27975107Sfenner (void)fclose(p->sf.rfile); 28017683Spst if (p->sf.base != NULL) 28117683Spst free(p->sf.base); 28217683Spst } else if (p->buffer != NULL) 28317683Spst free(p->buffer); 28417683Spst 28575107Sfenner pcap_freecode(&p->fcode); 28617683Spst free(p); 28717683Spst} 288