For bpf I was using the attached sample I found while googling around. I
use the following commands to build, bake and run it.

x86_64-rumprun-netbsd-gcc -o bpfsample bpfsample.c
rumpbake hw_generic bpfsample.bin bpfsample
rumprun qemu -i -I 'qnet0,vioif,-net tap,script=no,ifname=tap0' -W
qnet0,inet,static,10.10.10.100/24 bpfsample.bin

It launches and runs but failes to open /dev/bpf0 with the error "No such
file or directory".

If I change the code to use /dev/bpf it seems to open the device okay but
fails in set_options with "Device not configured". Using another piece of
code to list the interfaces, the only one I see is lo0 which is the loop
back. I am guessing I need to do something to configure qnet0 but have yet
to figure that part out. Any help is greatly appreciated.

-Chris


On Sun, Oct 25, 2015 at 5:47 PM, Antti Kantee <[email protected]> wrote:

> On 25/10/15 21:28, Chris Mock wrote:
>
>> I am trying to develop an application that can be ran using rumprun and is
>> capable of sending/receiving raw network packets. Given that I still need
>> to use the existing tcp/ip stack, I was trying to adapt some examples I
>> found for bpf and raw sockets to accomplish this. However, I have not had
>> much luck getting these to work, and was hoping someone could point me to
>> a
>> simple working example to accomplish raw packet manipulation. It doesn't
>> have to be bpf or raw sockets, those just seemed easiest.
>>
>
> I don't recall anyone ever reporting that they tried that with Rumprun,
> but then again I can't think of a reason why using bpf would not work.
>
> Can you elaborate on what you tried?  Perhaps someone will be able to
> repeat your results and get raw network access working.
>
>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <err.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <net/if.h>
#include <net/if_ether.h>

#include <errno.h>

#include <sys/ioctl.h>
#include <net/bpf.h>

int open_dev(void);
int check_dlt(int fd);
int set_options(int fd, char *iface);
int set_filter(int fd);
void read_packets(int fd);

int main(int argc, char *argv[])
{
    int fd = 0;
    char *iface = NULL;


    iface = strdup(argc < 2 ? "qnet0" : argv[1]);
    if (iface == NULL)
        err(EXIT_FAILURE, "strdup");

    fd = open_dev();
    if (fd < 0)
        err(EXIT_FAILURE, "open_dev");

    if (set_options(fd, iface) < 0)
        err(EXIT_FAILURE, "set_options");

    if (check_dlt(fd) < 0)
        err(EXIT_FAILURE, "check_dlt");

    if (set_filter(fd) < 0)
        err(EXIT_FAILURE, "set_filter");

    read_packets(fd);

    err(EXIT_FAILURE, "read_packets");
}

int open_dev()
{
    int fd = -1;
    char dev[32];
    int i = 0;


    /* Open the bpf device */
    for (i = 0; i < 255; i++) {
        (void)snprintf(dev, sizeof(dev), "/dev/bpf", i);

        (void)printf("Trying to open: %s\n", dev);

        fd = open(dev, O_RDWR);
        if (fd > -1)
            return fd;

        switch (errno) {
            case EBUSY:
                break;
            default:
                return -1;
        }
    }

    errno = ENOENT;
    return -1;
}

int check_dlt(int fd)
{
    u_int32_t dlt = 0;


    /* Ensure we are dumping the datalink we expect */
    if(ioctl(fd, BIOCGDLT, &dlt) < 0)
        return -1;

    (void)fprintf(stdout, "datalink type=%u\n", dlt);

    switch (dlt) {
        case DLT_EN10MB:
            return 0;
        default:
            (void)fprintf(stderr, "Unsupported datalink type:%u", dlt);
            errno = EINVAL;
            return -1;
    }
}

int set_options(int fd, char *iface)
{
    struct ifreq ifr;
    u_int32_t enable = 1;


    /* Associate the bpf device with an interface */
    (void)strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);

    if(ioctl(fd, BIOCSETIF, &ifr) < 0)
        return -1;

    /* Set header complete mode */
    if(ioctl(fd, BIOCSHDRCMPLT, &enable) < 0)
        return -1;

    /* Monitor packets sent from our interface */
    if(ioctl(fd, BIOCSSEESENT, &enable) < 0)
        return -1;

    /* Return immediately when a packet received */
    if(ioctl(fd, BIOCIMMEDIATE, &enable) < 0)
        return -1;

    return 0;
}

int set_filter(int fd)
{
    struct bpf_program fcode = {0};

    /* dump ssh packets only */
    struct bpf_insn insns[] = {
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 10),
        BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 8),
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
        BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 6, 0),
        BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
        BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 2, 0),
        BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 0, 1),
        BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
        BPF_STMT(BPF_RET+BPF_K, 0),
    };


    /* Set the filter */
    fcode.bf_len = sizeof(insns) / sizeof(struct bpf_insn);
    fcode.bf_insns = &insns[0];

    if(ioctl(fd, BIOCSETF, &fcode) < 0)
        return -1;

    return 0;
}

void read_packets(int fd)
{
    char *buf = NULL;
    char *p = NULL;
    size_t blen = 0;
    ssize_t n = 0;
    struct bpf_hdr *bh = NULL;
    struct ether_header *eh = NULL;


    if(ioctl(fd, BIOCGBLEN, &blen) < 0)
        return;

    if ( (buf = malloc(blen)) == NULL)
        return;

    (void)printf("reading packets ...\n");

    for ( ; ; ) {
        (void)memset(buf, '\0', blen);

        n = read(fd, buf, blen);

        if (n <= 0)
            return;

        p = buf;
        while (p < buf + n) {
            bh = (struct bpf_hdr *)p;

            /* Start of ethernet frame */
            eh = (struct ether_header *)(p + bh->bh_hdrlen);

            (void)printf("%02x:%02x:%02x:%02x:%02x:%02x -> "
                    "%02x:%02x:%02x:%02x:%02x:%02x "
                    "[type=%u]\n",
                    eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],
                    eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5],

                    eh->ether_dhost[0], eh->ether_dhost[1], eh->ether_dhost[2],
                    eh->ether_dhost[3], eh->ether_dhost[4], eh->ether_dhost[5],

                    eh->ether_type);

            p += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
        }
    }
}

Reply via email to