arcsin(x)
[home] / [notes] / [Linux 2.4 protocol stack]

Notes on creating a new protocol stack for linux 2.4


There are three major structures you must populate to get a bare bones 
protocol going:

struct net_proto_family my_family_prot =
{
        AF_MY_FAMILY, //family
        my_family_create_socket,
        0, // no auth encryption etc
        0,
        0
};

first thing is to register your family with this structure which 
contains an id, a function to create a socket of the family type, 
and some other fields.
then you call:
     sock_register(&my_family_prot);
to tell the kernel about your intentions.

next you need to define the functions that do the foot work:

struct proto_ops my_proto_ops { 
        family:       AF_MY_PROTOCOL,
        release:      my_proto_op_release,
        bind:         my_proto_op_bind,
        connect:      ...,
        socketpair:   ...,
        accept:       ...,
        getname:      ...,
        ioctl:        ...,
        poll:         ...,
        listen:       ...,
        shutdown:     ...,
        setsockopt:   ...,
        getsockopt:   ...,
        sendmsg:      ...,
        recvmsg:      ...,
        mmap:         ...
}

this structure contains a protocol ID and 
pointers to functions which the kernel uses
to translate syscalls on sockets into your protocol.

the important ones to implement right off the bat are:
bind         (handles the bind system call...this should 
              setup all the handy things
getname      (handles gethostbyname calls)
sendmsg      (sendmsg, write syscalls)
recvmsg      (recvmsg, read syscalls)

the rest of the members can point to a function call that does nothing
early on.

this structure is used when you create a socket of your family type:


sock->ops = &my_proto_ops;


the next important thing you need to do is tell the net device layer about 
what sort of packets should be passed to your stack.


static struct packet_type my_packet_type =
{
        __constant_htons(ETH_P_MY_PACKET),
        NULL,   // any net device
        my_packet_rcv,
        (void*)1,
        NULL
};

the first field is an id which is a short integer identifying the header of
your packet.  look in if_ether.h for a free one you can use.  using 
one already allocated will waste lots of your time.

the second field is NULL which is a wildcard meaning that this applies 
to any interface.  the third member is a function which handles packets
received.  the fourth is a pointer to private data for the my_packet_rcv's 
benefit.  and lastly is a next field, which is for the kernel's linked list 
business.

after defining it you need to pass it off to the kernel by calling
    dev_add_pack(&my_packet_type);

(don't forget to unregister all this stuff on cleanup
if you are using a module).

finally, when you need to put packets on the wire  dev_queue_xmit(sk_buff *) 
is the magic word.  this apparently sends out your unadorned skb, so you 
have to put headers on it (ether src, ether dest, packet type) as first
14 bytes.

there are tons of other stuff necessary but these are the high points.
you'll of course need to look up all the fxn prototypes and other details.
you can look at af_ipx.c in the kernel sources for the details.  it's nice 
because it's a single file that does all the stuff.
a packet sniffer is also very useful to debug all this stuff; i used
ethereal.