NetBSD-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
BPF problem
Hello,
I am trying to read bpf packets. It works ok so long as read() returns
only one packet's worth of data. Otherwise, it appears the next packet
is invalid/mal-formed, and the bpf_hdr contains 0 length bh_caplen and
bh_hdrlen values, producing an infinite loop.
Any suggestions as to what I am doing wrong?
Cheers,
Josh
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
/* OpenBSD specific */
#ifdef OPENBSD
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#endif
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/sockio.h>
#include <sys/uio.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_ether.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
int bpf = 0;
char *interface = NULL;
char *filter = NULL;
struct ifreq bound_if;
int buf_len = 0;
int immediate = 1;
void process_packet(struct ether_header *eh) {
int i;
unsigned int type = ntohs(eh->ether_type);
char *src, *dst;
unsigned long len, src_port, dst_port;
struct ip *ip_header;
struct tcphdr *tcp_header;
struct udphdr *udp_header;
if (type != ETHERTYPE_IP) {
printf("Non IP packet (%x)\n", type);
return;
}
/* print out ethernet mac addresses */
for (i = 0; i < ETHER_ADDR_LEN; i++)
printf("%s%02x", (i == 0) ? "" : ":", eh->ether_shost[i]);
for (i = 0; i < ETHER_ADDR_LEN; i++)
printf("%s%02x", (i == 0) ? " -> " : ":", eh->ether_dhost[i]);
printf("\n");
ip_header = (struct ip*) ((char *)eh + ETHER_HDR_LEN);
len = ntohs(ip_header->ip_len);
src = strdup(inet_ntoa(ip_header->ip_src));
dst = strdup(inet_ntoa(ip_header->ip_dst));
if (src == NULL || dst == NULL)
err(EXIT_FAILURE, "malloc()");
switch (ip_header->ip_p) {
case IPPROTO_ICMP:
printf("ICMP: %d bytes %s -> %s\n", len, src,dst);
break;
case IPPROTO_UDP:
udp_header = (struct udphdr*) ((char *)ip_header +
sizeof(struct ip));
src_port = ntohs(udp_header->uh_sport);
dst_port = ntohs(udp_header->uh_dport);
printf("UDP: %d bytes %s:%u -> %s:%u\n",
len,src,src_port,dst,dst_port);
break;
case IPPROTO_TCP:
tcp_header = (struct tcphdr*) ((char *)ip_header +
sizeof(struct ip));
src_port = ntohs(tcp_header->th_sport);
dst_port = ntohs(tcp_header->th_dport);
printf("TCP: %d bytes %s:%u -> %s:%u\n",
len,src,src_port,dst,dst_port);
break;
default:
printf("BOLLIX: %d bytes %s -> %s\n", len,src,dst);
break;
}
free(src);
free(dst);
}
int read_packets() {
ssize_t read_bytes = 0;
struct ether_header *eth_frame;
struct bpf_hdr *bpf_packet;
struct bpf_hdr *bpf_buf = malloc(buf_len);
if (bpf_buf == NULL)
err(EXIT_FAILURE, NULL);
while(1) {
memset(bpf_buf, 0, buf_len);
read_bytes = read(bpf, bpf_buf, buf_len);
if (read_bytes == 0) {
printf("Hmmm. Sleeping for a bit.\n");
sleep(3);
continue;
}
if (read_bytes == EINVAL)
err(EXIT_FAILURE, "read()");
bpf_packet = bpf_buf;
while (read_bytes > 0) {
/*read_bytes -= BPF_WORDALIGN(bpf_packet->bh_hdrlen +
bpf_packet->bh_caplen); */
read_bytes -= bpf_packet->bh_hdrlen + bpf_packet->bh_caplen;
printf("read_bytes now %d\n", read_bytes);
eth_frame = (struct ether_header *) ((char *)bpf_packet +
bpf_packet->bh_hdrlen);
process_packet(eth_frame);
bpf_packet = (struct bpf_hdr *) (char *)bpf_packet +
(bpf_packet->bh_hdrlen + bpf_packet->bh_datalen);
/* bpf_packet = (struct bpf_hdr *) (char *)bpf_packet + */
/* BPF_WORDALIGN((bpf_packet->bh_hdrlen +
bpf_packet->bh_datalen)); */
printf("------------------------------\n");
}
}
}
void init_bpf() {
int i, ret;
char buff[100];
/* open device. */
for (i = 0; i<=99; i++) {
snprintf(buff, sizeof(buff) - 1, "/dev/bpf%i", i);
bpf = open(buff, O_RDONLY);
if (bpf != -1)
break;
}
if (bpf == -1) {
printf("Failed to open a bpf device.\n");
exit(EXIT_FAILURE);
}
snprintf(bound_if.ifr_name, IFNAMSIZ, "%s", interface);
if (ioctl(bpf, BIOCSETIF, &bound_if) == -1)
err(EXIT_FAILURE, "%s", interface);
if( ioctl(bpf, BIOCIMMEDIATE, &immediate ) == -1 )
err(EXIT_FAILURE, "%s", interface);
if( ioctl(bpf, BIOCGBLEN, &buf_len ) == -1 )
err(EXIT_FAILURE, "%s", interface);
}
void useage(char *arg0) {
printf("useage: %s interface\n", arg0);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
printf("\nnetwork rangi-o-matic version 0.2\n\n");
/* parse arguments */
if (argc < 2)
useage(argv[0]);
interface = argv[1];
init_bpf();
read_packets();
return 0;
}
Home |
Main Index |
Thread Index |
Old Index