summaryrefslogtreecommitdiffstats
path: root/src/extra/pktbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/extra/pktbuff.c')
-rw-r--r--src/extra/pktbuff.c159
1 files changed, 122 insertions, 37 deletions
diff --git a/src/extra/pktbuff.c b/src/extra/pktbuff.c
index c95384f..40d2250 100644
--- a/src/extra/pktbuff.c
+++ b/src/extra/pktbuff.c
@@ -23,12 +23,58 @@
/**
* \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.
+ * These functions provide the user-space network packet buffer.
+ * This abstraction is strongly inspired by Linux kernel network buffer,
+ * the so-called sk_buff.
+ *
+ * \manonly
+.SH SYNOPSIS
+.nf
+\fB
+#include <libmnl/libmnl.h>
+#include <libnetfilter_queue/pktbuff.h>
+\endmanonly
*
* @{
*/
+static int __pktb_setup(int family, struct pkt_buff *pktb)
+{
+ struct ethhdr *ethhdr;
+
+ switch (family) {
+ case AF_INET:
+ case AF_INET6:
+ pktb->network_header = pktb->data;
+ break;
+ case AF_BRIDGE:
+ ethhdr = (struct ethhdr *)pktb->data;
+ pktb->mac_header = pktb->data;
+
+ switch(ethhdr->h_proto) {
+ case ETH_P_IP:
+ case ETH_P_IPV6:
+ pktb->network_header = pktb->data + ETH_HLEN;
+ break;
+ default:
+ /* This protocol is unsupported. */
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void pktb_setup_metadata(struct pkt_buff *pktb, void *pkt_data,
+ size_t len, size_t extra)
+{
+ pktb->len = len;
+ pktb->data_len = len + extra;
+ pktb->data = pkt_data;
+}
+
/**
* pktb_alloc - allocate a new packet buffer
* \param family Indicate what family. Currently supported families are
@@ -38,7 +84,12 @@
* \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 (if requested).
+ * some extra memory room in the tail (if requested). This function copies
+ * the memory area provided as a pointer to packet data into the packet buffer
+ * structure.
+ *
+ * The extra length provides extra packet data room at the tail of the packet
+ * buffer in case you need to mangle it.
*
* \return Pointer to a new userspace packet buffer or NULL on failure.
* \par Errors
@@ -52,7 +103,6 @@ EXPORT_SYMBOL
struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra)
{
struct pkt_buff *pktb;
- struct ethhdr *ethhdr;
void *pkt_data;
pktb = calloc(1, sizeof(struct pkt_buff) + len + extra);
@@ -63,34 +113,44 @@ struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra)
pkt_data = (uint8_t *)pktb + sizeof(struct pkt_buff);
memcpy(pkt_data, data, len);
- pktb->len = len;
- pktb->data_len = len + extra;
+ pktb_setup_metadata(pktb, pkt_data, len, extra);
- pktb->data = pkt_data;
- pktb->tail = pktb->data + len;
+ if (__pktb_setup(family, pktb) < 0) {
+ free(pktb);
+ return NULL;
+ }
- switch(family) {
- case AF_INET:
- case AF_INET6:
- pktb->network_header = pktb->data;
- break;
- case AF_BRIDGE:
- ethhdr = (struct ethhdr *)pktb->data;
- pktb->mac_header = pktb->data;
+ return pktb;
+}
+
+/**
+ * pktb_setup_raw - set up a packet buffer from memory area
+ * \param pktb Pointer to memory of length pktb_head_size() bytes
+ * \param family Supported families are AF_BRIDGE, AF_INET & AF_INET6.
+ * \param data Pointer to packet data
+ * \param len Packet data length
+ * \param extra Extra memory available after packet data (for mangling).
+ *
+ * Use this function to set up a packet buffer from a memory area, minimum size
+ * of such memory area must be pktb_head_size(). This function attaches the
+ * packet data that is provided to the packet buffer (data is not copied). Use
+ * this function as an alternative to the pktb_alloc() interface for more
+ * control on memory management.
+ *
+ * \return Pointer to a new userspace packet buffer or NULL on failure.
+ * \par Errors
+ * __EPROTONOSUPPORT__ _family_ was __AF_BRIDGE__ and this is not an IP packet
+ * (v4 or v6)
+ */
+EXPORT_SYMBOL
+struct pkt_buff *pktb_setup_raw(void *pktb, int family, void *data,
+ size_t len, size_t extra)
+{
+ memset(pktb, 0, sizeof (struct pkt_buff));
+ pktb_setup_metadata(pktb, data, len, extra);
+ if (__pktb_setup(family, pktb) < 0)
+ pktb = NULL;
- switch(ethhdr->h_proto) {
- case ETH_P_IP:
- case ETH_P_IPV6:
- pktb->network_header = pktb->data + ETH_HLEN;
- break;
- default:
- /* This protocol is unsupported. */
- errno = EPROTONOSUPPORT;
- free(pktb);
- return NULL;
- }
- break;
- }
return pktb;
}
@@ -140,21 +200,37 @@ void pktb_free(struct pkt_buff *pktb)
* \n
* 1. Functions to get values of members of opaque __struct pktbuff__, described
* below
- * \n
+ *
* 2. Internal functions, described in Module __Internal functions__
*
+ * \manonly
+.SH SYNOPSIS
+.nf
+\fB
+#include <libmnl/libmnl.h>
+#include <libnetfilter_queue/pktbuff.h>
+\endmanonly
+ *
* @{
*/
/**
- * \defgroup uselessfns Internal functions
+ * \defgroup do_not_use Internal functions
*
- * \warning Do not use these functions. Instead, always use the mangle
+ * Do not use these functions. Instead, always use the mangle
* function appropriate to the level at which you are working.
* \n
* pktb_mangle() uses all the below functions except _pktb_pull_, which is not
* used by anything.
*
+ * \manonly
+.SH SYNOPSIS
+.nf
+\fB
+#include <libmnl/libmnl.h>
+#include <libnetfilter_queue/pktbuff.h>
+\endmanonly
+ *
* @{
*/
@@ -190,7 +266,6 @@ void pktb_pull(struct pkt_buff *pktb, unsigned int len)
EXPORT_SYMBOL
void pktb_put(struct pkt_buff *pktb, unsigned int len)
{
- pktb->tail += len;
pktb->len += len;
}
@@ -203,7 +278,6 @@ EXPORT_SYMBOL
void pktb_trim(struct pkt_buff *pktb, unsigned int len)
{
pktb->len = len;
- pktb->tail = pktb->data + len;
}
/**
@@ -279,7 +353,6 @@ static int pktb_expand_tail(struct pkt_buff *pktb, int extra)
return 0;
pktb->len += extra;
- pktb->tail = pktb->tail + extra;
return 1;
}
@@ -310,7 +383,7 @@ static int enlarge_pkt(struct pkt_buff *pktb, unsigned int extra)
* excess of \b rep_len over \b match_len
\warning pktb_mangle does not update any checksums. Developers should use the
appropriate mangler for the protocol level: nfq_ip_mangle(),
- nfq_tcp_mangle_ipv4() or nfq_udp_mangle_ipv4(). IPv6 versions are planned.
+ nfq_tcp_mangle_ipv4(), nfq_udp_mangle_ipv4() or IPv6 variants.
\n
It is appropriate to use pktb_mangle to change the MAC header.
*/
@@ -334,7 +407,7 @@ int pktb_mangle(struct pkt_buff *pktb,
/* move post-replacement */
memmove(data + match_offset + rep_len,
data + match_offset + match_len,
- pktb->tail - (pktb->network_header + dataoff +
+ pktb_tail(pktb) - (pktb->network_header + dataoff +
match_offset + match_len));
/* insert data from buffer */
@@ -366,5 +439,17 @@ bool pktb_mangled(const struct pkt_buff *pktb)
}
/**
+ * pktb_head_size - get number of bytes needed for a packet buffer
+ * (control part only)
+ * \return size of struct pkt_buff
+ */
+
+EXPORT_SYMBOL
+size_t pktb_head_size(void)
+{
+ return sizeof(struct pkt_buff);
+}
+
+/**
* @}
*/