[erlang-questions] bpf port driver

mighty <>
Thu Feb 22 17:47:44 CET 2007


i'm very new to erlang and was looking for some help putting together a
reasonable driver around bpf. using the tuntap driver in jungerl as a
starting point, i have a driver through with which i can successfully write
to the bpf... but i'm running into troubles attempting to read from the bpf
-- i can't get anything read in from the bpf, and calling driver_select()
crashes. i've attached what i've put together so far (it's pretty rough and
minimal) minus my attempts to read() from the bpf -- any and all advice
would be greatly appreciated (i've looked around at a number of example
drivers, but am having a hard time distilling the minimum essence of getting
input from a driver into erlang). thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20070222/eb98e384/attachment.html>
-------------- next part --------------
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <net/bpf.h>
#include <errno.h>
#include <string.h>
#include <erl_driver.h>

struct bpf_data
{
    ErlDrvPort port;
    int fd;
    char dev[sizeof("/dev/bpf0")];
};

static int bpf_dev(struct bpf_data *data)
{
    int i;

    for (i=0; i<10; i++)
    {
        snprintf(data->dev, sizeof(data->dev), "/dev/bpf%u", i);

        if ((data->fd = open(data->dev, O_RDWR)) != -1)
            return 0;
    }

    return -1;
}

static int bpf_ifc(struct bpf_data *data, char *ifc)
{
    struct ifreq ifr;
    int on =1;

    strncpy(ifr.ifr_name, ifc, sizeof(ifr.ifr_name));

    if (ioctl(data->fd, BIOCSETIF, &ifr) != -1)
        if (ioctl(data->fd, BIOCPROMISC, &on) != -1)
            if (ioctl(data->fd, BIOCIMMEDIATE, &on) != -1)
                return 0;
    
    return -1;
}

static ErlDrvData bpf_open(ErlDrvPort port, char *buf)
{
    struct bpf_data *data;

    while (*buf++ != ' ');

    if ((data = (struct bpf_data *)driver_alloc(sizeof(struct bpf_data))))
    {
        if (bpf_dev(data) != -1)
        {
            if (bpf_ifc(data, buf) != -1)
                return (ErlDrvData)data;
            
            close(data->fd);
        }

        driver_free((void *)data);
    }

    return ERL_DRV_ERROR_GENERAL;
}

static void bpf_close(ErlDrvData handle)
{
    struct bpf_data *data;

    if ((data = (struct bpf_data *)handle))
    {
        close(data->fd);

        driver_free((void *)data);
    }
}

static void bpf_output(ErlDrvData handle, char *buf, int len)
{
    struct bpf_data *data;

    if ((data = (struct bpf_data *)handle))
        if (write(data->fd, buf, len) < 0)
            driver_failure_posix(data->port, errno);
}

ErlDrvEntry bpf_driver_entry = 
{
    0,
    bpf_open,
    bpf_close,
    bpf_output,
    0,
    0,
    "bpf_drv",
    0,
    0,
    0,
    0
};

DRIVER_INIT(bpf)
{
    return &bpf_driver_entry;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bpf.erl
Type: application/octet-stream
Size: 277 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20070222/eb98e384/attachment.obj>


More information about the erlang-questions mailing list