Date: Sat, 17 Jul 2004 14:51:21 -0400 From: Don Bowman <don@sandvine.com> To: "'net@freebsd.org'" <net@freebsd.org> Subject: Question on SOCK_RAW, implement a bpf->other host tee Message-ID: <FE045D4D9F7AED4CBFF1B3B813C85337051D9364@mail.sandvine.com>
next in thread | raw e-mail | index | archive | help
I'm trying to implement a 'tee' which reads from bpf, and sends matching packets to another layer-2 adjacent host. I'm doing this with SOCK_RAW to try and write the packet back out. The 'sendto' passes, but i don't see a packet anywhere. Am i correct that i can hand an arbitrarily crafted IP packet into sendto, and the stack will write the ethernet header on, pick an interface, etc, based on the address in the sendto? I have swapped the ip_len, ip_off fields. The program I have is below. This is on 4.7. The handler gets called, the packet there looks correct, no error on any system call, yet no output :( Suggestions? /* * Copyright 2004 Sandvine Incorporated. All rights reserved */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <pcap.h> void usage(const char *name) { fprintf(stderr, "Usage: %s [-I input_interface] [-O output_interface] [-i output_ip(arp for mac)] [-v]\n", name); exit(1); } typedef struct { int s; struct in_addr output_ip; } context; static int verbose; static void handler(unsigned char *ct, const struct pcap_pkthdr *hdr, const unsigned char *pkt) { struct ip *ip = (struct ip *)(pkt + 14); context *ctxt = (context *)ct; struct sockaddr_in to; memset(&to,0,sizeof(to)); to.sin_family = AF_INET; to.sin_addr = ctxt->output_ip; if (verbose) { fprintf(stderr, "Send %d byte packet\n", hdr->len); } ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); if (sendto(ctxt->s, ip, hdr->len-14, 0, (struct sockaddr *)&to, sizeof(to)) != (hdr->len-14) ) { err(1, "sendto"); } } static int doit(const char *input_interface, const char *output_interface, struct in_addr output_ip) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_t *in_d, *out_d; context ctxt; int on = 1; struct bpf_program fp; in_d = pcap_open_live((char *)input_interface, 1600, 1, 20, errbuf); if (in_d == 0) { errx(1, "open of %s failed: %s", input_interface, errbuf); } ctxt.output_ip.s_addr = htonl(output_ip.s_addr); ctxt.s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); if (ctxt.s < 0) errx(1, "can't open raw socket"); if (setsockopt(ctxt.s, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) { err(1,"setsockopt"); } memset(&fp,0,sizeof(fp)); if (pcap_compile(in_d, &fp, "ip", 0, 0xfffffff0) < 0) { errx(1, "failed to compile: %s",pcap_geterr(in_d)); } if (pcap_setfilter(in_d, &fp) < 0) { errx(1, "failed to set filter"); } pcap_loop(in_d, -1, handler, (unsigned char *)&ctxt); } int main(int argc, char *argv[]) { int ch; char *input_interface = "ipfw0"; char *output_interface = "em2"; struct in_addr output_ip; output_ip.s_addr = 0; while ((ch = getopt(argc, argv, "I:O:i:vh?")) != -1) { switch (ch) { case 'I': input_interface = optarg; break; case 'O': output_interface = optarg; break; case 'i': if (inet_aton(optarg,&output_ip) < 0) { errx(1, "unknown ip %s", optarg); } break; case 'v': verbose = 1; break; case 'h': case '?': default: usage(argv[0]); } } if (verbose) fprintf(stderr, "%s->%s(%s)\n", input_interface,output_interface,inet_ntoa(output_ip)); return doit(input_interface,output_interface,output_ip); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?FE045D4D9F7AED4CBFF1B3B813C85337051D9364>