summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-08-20 23:22:32 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2023-08-20 23:30:36 +0200
commit91d2c947b473b3540be5474c7128a5fa4ce60934 (patch)
tree057fae93bb52b981e611dad7fd018bb578a702da
parent8020c6705834cf62e9536d6bc278e3daa9bd8160 (diff)
src: add alternative API to set up packet buffer
pktb_setup_raw() is a new function to initialise a new struct pkt_buff. It takes the memory area to be used to store pkt_buff structure and the data. Data is attached to the packet buffer (not copied), ie. the packet buffer data points to the provided data pointer. pktb_head_size() is a new function to return the amount of memory to reserve for a new struct pkt_buff. Extend documentation pon pktb_alloc(). Mostly original patch from Duncan Roe <duncan_roe@optusnet.com.au>. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/libnetfilter_queue/pktbuff.h3
-rw-r--r--src/extra/pktbuff.c63
2 files changed, 61 insertions, 5 deletions
diff --git a/include/libnetfilter_queue/pktbuff.h b/include/libnetfilter_queue/pktbuff.h
index 42bc153..a4cc2a1 100644
--- a/include/libnetfilter_queue/pktbuff.h
+++ b/include/libnetfilter_queue/pktbuff.h
@@ -6,6 +6,9 @@ struct pkt_buff;
struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra);
void pktb_free(struct pkt_buff *pktb);
+struct pkt_buff *pktb_setup_raw(void *pktb, int family, void *data, size_t len, size_t extra);
+size_t pktb_head_size(void);
+
uint8_t *pktb_data(struct pkt_buff *pktb);
uint32_t pktb_len(struct pkt_buff *pktb);
diff --git a/src/extra/pktbuff.c b/src/extra/pktbuff.c
index 005172c..40d2250 100644
--- a/src/extra/pktbuff.c
+++ b/src/extra/pktbuff.c
@@ -67,6 +67,14 @@ static int __pktb_setup(int family, struct pkt_buff *pktb)
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
@@ -76,7 +84,12 @@ static int __pktb_setup(int family, struct pkt_buff *pktb)
* \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
@@ -100,10 +113,7 @@ 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->data = pkt_data;
+ pktb_setup_metadata(pktb, pkt_data, len, extra);
if (__pktb_setup(family, pktb) < 0) {
free(pktb);
@@ -114,6 +124,37 @@ struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra)
}
/**
+ * 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;
+
+ return pktb;
+}
+
+/**
* pktb_data - get pointer to network packet
* \param pktb Pointer to userspace packet buffer
* \return Pointer to start of network packet data within __pktb__
@@ -398,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);
+}
+
+/**
* @}
*/