Question on SOCK_RAW, implement a bpf->other host tee

From: Don Bowman (don_at_sandvine.com)
Date: 07/17/04

  • Next message: Don Bowman: "RE: Question on SOCK_RAW, implement a bpf->other host tee"
    To: "'net@freebsd.org'" <net@freebsd.org>
    Date: Sat, 17 Jul 2004 14:51:21 -0400
    
    

    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);
    }

    _______________________________________________
    freebsd-net@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-net
    To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"


  • Next message: Don Bowman: "RE: Question on SOCK_RAW, implement a bpf->other host tee"

    Relevant Pages