1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/*
* $Id: linux.c,v 1.5 2009/02/03 12:51:50 c4chris Exp $
*
* Christian Iseli
* Ludwig Institute for Cancer Research
* UNIL - BEP
* CH-1015 Lausanne
* Switzerland
*
*/
#include "os.h"
#ifdef USE_LINUX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <errno.h>
#include "nfswatch.h"
#include "externs.h"
static void
linux_get_def_dev(char **device)
{
int n, s;
struct ifreq *ifrp;
struct ifconf ifc;
char buf[BUFSIZ];
/*
* Grab a socket.
*/
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
error("socket");
finish(-1);
}
ifc.ifc_buf = buf;
ifc.ifc_len = sizeof(buf);
/*
* See what devices we've got.
*/
if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
error("ioctl: SIOCGIFCONF");
finish(-1);
}
/*
* Take the first device we encounter.
*/
ifrp = ifc.ifc_req;
for (n = ifc.ifc_len/sizeof(struct ifreq); n > 0; n--,ifrp++) {
/*
* Skip the loopback interface.
*/
if (strcmp(ifrp->ifr_name, "lo") == 0)
continue;
*device = strdup(ifrp->ifr_name);
break;
}
(void) close(s);
}
/*
* setup_linux_dev - set up the network interface tap.
*/
int
setup_linux_dev(char **device, linux_socket_handle_p_t ls)
{
char errbuf[PCAP_ERRBUF_SIZE];
/*
* If the interface device was not specified,
* get the default one.
*/
if (device != NULL && *device == NULL) {
linux_get_def_dev(device);
if (*device == NULL) {
error("linux: couldn't determine default device");
finish(-1);
}
}
errbuf[0] = 0;
if (device == NULL) {
ls->pcap = pcap_open_live(NULL, 65536, 0, 10, errbuf);
ls->device = "any";
} else {
ls->pcap = pcap_open_live(*device, 65536, 1, 10, errbuf);
ls->device = *device;
}
if (ls->pcap == NULL) {
fprintf(stderr, "Failed to open device: %s\n", errbuf);
finish(-1);
}
if (errbuf[0] != 0)
fprintf(stderr, "Warning: %s\n", errbuf);
ls->s = pcap_get_selectable_fd(ls->pcap);
if (ls->s == -1) {
fprintf(stderr, "Failed to get a selectable file descriptor\n");
finish(-1);
}
/* Determine link type. */
ls->linktype = pcap_datalink(ls->pcap);
ls->offset = 2;
/* Grab a big enough buffer. */
ls->bufsize = 65536;
ls->buffer = (u_char *)malloc(ls->bufsize + ls->offset);
if (ls->buffer == NULL) {
perror("malloc");
finish(-1);
}
return(ls->s);
}
int
linux_read_packet(linux_socket_handle_p_t ls)
{
u_char *bp;
int res;
struct pcap_pkthdr *hdr;
const u_char *data;
/* Receive a single packet from the kernel */
bp = ls->buffer + ls->offset;
res = pcap_next_ex(ls->pcap, &hdr, &data);
if (res == -1) {
pcap_perror(ls->pcap, "Error reading packet: ");
return -1;
}
if (res <= 0)
return 0;
memcpy(bp, data, hdr->caplen);
ls->len = hdr->caplen;
ls->ts = hdr->ts;
ls->bp = bp;
return 1;
}
#endif /* USE_LINUX */
|