Back to Home
skbuffer - Linux network buffers ( by Paolo Ardoino < paolo.ardoino@gmail.com > )
skbuff are buffers used by Linux network layers ; its structure is defined in <linux/skbuff.h> .
skbuffs are linked lists as we can easily see :
/* These two members must be first . */
struct sk_buff *next; // Next buffer in list
struct sk_buff *prev; // Previous buffer in list
Follows the description of all fields of the structure taken from the header file:
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
* @prev: Previous buffer in list
* @list: List we are on
* @sk: Socket we are owned by
* @tstamp: Time we arrived
* @dev: Device we arrived on/are leaving by
* @input_dev: Device we arrived on
* @h: Transport layer header
* @nh: Network layer header
* @mac: Link layer header
* @dst: destination entry
* @sp: the security path, used for xfrm
* @cb: Control buffer. Free for use by every layer. Put private vars here
* @len: Length of actual data
* @data_len: Data length
* @mac_len: Length of link layer header
* @csum: Checksum
* @local_df: allow local fragmentation
* @cloned: Head may be cloned (check refcnt to be sure)
* @nohdr: Payload reference only, must not modify header
* @pkt_type: Packet class
* @ip_summed: Driver fed us an IP checksum
* @priority: Packet queueing priority
* @users: User count - see {datagram,tcp}.c
* @protocol: Packet protocol from driver
* @truesize: Buffer size
* @head: Head of buffer
* @data: Data head pointer
* @tail: Tail pointer
* @end: End pointer
* @destructor: Destruct function
* @nfmark: Can be used for communication between hooks
* @nfct: Associated connection, if any
* @nfctinfo: Relationship of this skb to the connection
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
* @tc_index: Traffic control index
* @tc_verd: traffic control verdict
*/
Now let's take a look to the functions we need to work with network buffers:
allow_skb() creates and initializes a new ,ready to use , sk_buff .
kfree_skb() releases the buffer .
skb_clone() makes a copy of a skb_buff .
skb_queue_head() add a buffer on the head of the list .
skb_queue_tail() add a buffer on the tail of the list .
skb_unlink() removes a skb_buff from lists , but not releases it .
skb_dequeue() takes the first ( header ) skb_buff .
Here is a simple kernel module that uses Linux network buffers to show incoming and
outgoing packets .
/*****************************************************************************/
/* SKB ( Linux Network Buffers ) test on Linux 2.6.x kernels
* This module will show show all incoming packets
* and outgoing packets from the local computer
* To get it working edit #define MYADDR setting
* the ip of your computer . This is only an example to
* show how create kernel sniffers or hijacker modules .
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/byteorder/generic.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#define DEBUG 1
// ip address of the local computer
#define MYADDR "192.168.0.3"
MODULE_AUTHOR("Paolo Ardoino");
MODULE_LICENSE("GPL");
#define MODNAME "SKBTEST"
unsigned long fromaddr;
unsigned short int fromport;
struct packet_type myskb;
// my_addr convert an ip address string from standard dot notation
// to an unsigned long
static unsigned long my_addr(char *ip)
{
unsigned long tmp;
unsigned int val;
int ctr;
tmp = 0;
for (ctr = 0; ctr < 4; ctr++) {
tmp <<= 8;
if(*ip != '\0') {
val = 0;
while (*ip != '\0' && *ip != '.') {
val *= 10;
val += *ip - '0';
ip++;
}
tmp |= val;
if (*ip != '\0') {
ip++;
}
}
}
return htonl(tmp);
}
// my_ntoa convers an unsigned long ( Internet host address )
// given in network byte order to a string in standard dot notation
static char *my_ntoa(unsigned long addr)
{
static char buff[18];
char *p;
p = (char *) &addr;
sprintf(buff, "%d.%d.%d.%d", (*p & 255), (*(p + 1) & 255), (*(p + 2) & 255), (*(p + 3) & 255));
return buff;
}
// my_pkt analyzes packets in skbuff
static int my_pkt(struct sk_buff *skb, struct device *d, struct packet_type *pt)
{
if (skb->nh.iph->protocol == IPPROTO_TCP) {
// outgoing packets
if (skb->nh.iph->saddr == fromaddr) {
#ifdef DEBUG
printk("[%s] PACKET SENT FROM LOCALHOST:%d TO %s:%d HOST\n", MODNAME, ntohs(skb->h.th->source), my_ntoa(skb->nh.iph->daddr), ntohs(skb->h.th->dest));
#endif
} else {
// incoming packets
if (skb->nh.iph->daddr == fromaddr) {
#ifdef DEBUG
printk("[%s] PACKET RECV FROM %s:%d HOST TO LOCALHOST:%d HOST\n", MODNAME, my_ntoa(skb->nh.iph->saddr), ntohs(skb->h.th->source), ntohs(skb->h.th->dest));
#endif
}
}
}
kfree_skb(skb);
return 0;
}
static int __init modinit(void)
{
printk("[%s] MODULE LOADED (by Paolo Ardoino < paolo.ardoino@gmail.com >) \n", MODNAME);
fromaddr = my_addr(MYADDR);
myskb.type = htons(ETH_P_ALL);
myskb.func = my_pkt;
myskb.dev = NULL;
dev_add_pack(&myskb);
return 0;
}
static void __exit modcleanup(void)
{
printk("[%s] CLEANUP COMPLETE\n", MODNAME);
dev_remove_pack(&myskb);
return;
}
module_init(modinit);
module_exit(modcleanup);
/*****************************************************************************/