From owner-freebsd-net@FreeBSD.ORG Sat Jul 17 18:51:24 2004 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5C00716A4CE for ; Sat, 17 Jul 2004 18:51:24 +0000 (GMT) Received: from mail.sandvine.com (sandvine.com [199.243.201.138]) by mx1.FreeBSD.org (Postfix) with ESMTP id E1DA243D1F for ; Sat, 17 Jul 2004 18:51:23 +0000 (GMT) (envelope-from don@sandvine.com) Received: by mail.sandvine.com with Internet Mail Service (5.5.2657.72) id ; Sat, 17 Jul 2004 14:51:23 -0400 Message-ID: From: Don Bowman To: "'net@freebsd.org'" Date: Sat, 17 Jul 2004 14:51:21 -0400 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2657.72) Content-Type: text/plain; charset="iso-8859-1" Subject: Question on SOCK_RAW, implement a bpf->other host tee X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Jul 2004 18:51:24 -0000 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 #include #include #include #include #include #include #include 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); }