From f40eabb01163f383e2471942da45f32361031e39 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 14 May 2012 13:14:14 +0200 Subject: add pkt_buff and protocol helper functions Signed-off-by: Pablo Neira Ayuso --- src/extra/pktbuff.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 src/extra/pktbuff.c (limited to 'src/extra/pktbuff.c') diff --git a/src/extra/pktbuff.c b/src/extra/pktbuff.c new file mode 100644 index 0000000..809953b --- /dev/null +++ b/src/extra/pktbuff.c @@ -0,0 +1,142 @@ +/* + * (C) 2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This code has been sponsored by Vyatta Inc. + */ + +#include +#include /* for memcpy */ + +#include +#include +#include + +#include "internal.h" + +/** + * \defgroup pktbuff User-space network packet buffer + * + * This library provides the user-space network packet buffer. This abstraction + * is strongly inspired by Linux kernel network buffer, the so-called sk_buff. + */ + +/** + * pktb_alloc - allocate a new packet buffer + * \param family Indicate what family, eg. AF_BRIDGE, AF_INET, AF_INET6, ... + * \param data Pointer to packet data + * \param len Packet length + * \param extra Extra memory in the tail to be allocated (for mangling) + * + * This function returns a packet buffer that contains the packet data and + * some extra memory room in the tail (in case of requested). + * + * \return a pointer to a new queue handle or NULL on failure. + */ +struct pkt_buff * +pktb_alloc(int family, void *data, size_t len, size_t extra) +{ + struct pkt_buff *pktb; + void *pkt_data; + + pktb = calloc(1, sizeof(struct pkt_buff) + len + extra); + if (pktb == NULL) + return NULL; + + /* Better make sure alignment is correct. */ + pkt_data = (uint8_t *)pktb + sizeof(struct pkt_buff); + memcpy(pkt_data, data, len); + + pktb->len = len; + pktb->data_len = len + extra; + + pktb->head = pkt_data; + pktb->data = pkt_data; + pktb->tail = pktb->head + len; + + switch(family) { + case AF_INET: + pktb->network_header = pktb->data; + break; + case AF_BRIDGE: { + struct ethhdr *ethhdr = (struct ethhdr *)pktb->data; + + pktb->mac_header = pktb->data; + + switch(ethhdr->h_proto) { + case ETH_P_IP: + pktb->network_header = pktb->data + ETH_HLEN; + break; + default: + /* This protocol is unsupported. */ + free(pktb); + return NULL; + } + break; + } + } + return pktb; +} + +uint8_t *pktb_data(struct pkt_buff *pktb) +{ + return pktb->data; +} + +uint32_t pktb_len(struct pkt_buff *pktb) +{ + return pktb->len; +} + +void pktb_free(struct pkt_buff *pktb) +{ + free(pktb); +} + +void pktb_push(struct pkt_buff *pktb, unsigned int len) +{ + pktb->data += len; +} + +void pktb_pull(struct pkt_buff *pktb, unsigned int len) +{ + pktb->data -= len; +} + +void pktb_put(struct pkt_buff *pktb, unsigned int len) +{ + pktb->tail += len; +} + +void pktb_trim(struct pkt_buff *pktb, unsigned int len) +{ + pktb->len = len; +} + +unsigned int pktb_tailroom(struct pkt_buff *pktb) +{ + return pktb->data_len - pktb->len; +} + +uint8_t *pktb_mac_header(struct pkt_buff *pktb) +{ + return pktb->mac_header; +} + +uint8_t *pktb_network_header(struct pkt_buff *pktb) +{ + return pktb->network_header; +} + +uint8_t *pktb_transport_header(struct pkt_buff *pktb) +{ + return pktb->transport_header; +} + +/** + * @} + */ -- cgit v1.2.3