* [PATCH libnetfilter_queue 2/2] src: add mangle functions for IPv6, IPv6/TCP and IPv6/UDP
2019-12-20 5:53 [PATCH libnetfilter_queue 0/2] Add mangle functions for IPv6, IPv6/TCP and IPv6/UDP Duncan Roe
2019-12-20 5:53 ` [PATCH libnetfilter_queue 1/2] src: more IPv6 checksum fixes Duncan Roe
@ 2019-12-20 5:53 ` Duncan Roe
2019-12-30 11:33 ` Pablo Neira Ayuso
1 sibling, 1 reply; 7+ messages in thread
From: Duncan Roe @ 2019-12-20 5:53 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
.../libnetfilter_queue/libnetfilter_queue_ipv6.h | 1 +
.../libnetfilter_queue/libnetfilter_queue_tcp.h | 1 +
.../libnetfilter_queue/libnetfilter_queue_udp.h | 1 +
| 29 ++++++++++++++++
| 40 ++++++++++++++++++++++
| 39 +++++++++++++++++++++
6 files changed, 111 insertions(+)
diff --git a/include/libnetfilter_queue/libnetfilter_queue_ipv6.h b/include/libnetfilter_queue/libnetfilter_queue_ipv6.h
index 93452ce..c0a7d37 100644
--- a/include/libnetfilter_queue/libnetfilter_queue_ipv6.h
+++ b/include/libnetfilter_queue/libnetfilter_queue_ipv6.h
@@ -6,6 +6,7 @@ struct ip6_hdr;
struct ip6_hdr *nfq_ip6_get_hdr(struct pkt_buff *pktb);
int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *iph, uint8_t target);
+int nfq_ip6_mangle(struct pkt_buff *pktb, unsigned int dataoff,unsigned int match_offset, unsigned int match_len,const char *rep_buffer, unsigned int rep_len);
int nfq_ip6_snprintf(char *buf, size_t size, const struct ip6_hdr *ip6h);
#endif
diff --git a/include/libnetfilter_queue/libnetfilter_queue_tcp.h b/include/libnetfilter_queue/libnetfilter_queue_tcp.h
index c66dfb6..997d997 100644
--- a/include/libnetfilter_queue/libnetfilter_queue_tcp.h
+++ b/include/libnetfilter_queue/libnetfilter_queue_tcp.h
@@ -14,6 +14,7 @@ void nfq_tcp_compute_checksum_ipv4(struct tcphdr *tcph, struct iphdr *iph);
void nfq_tcp_compute_checksum_ipv6(struct tcphdr *tcph, struct ip6_hdr *ip6h);
int nfq_tcp_mangle_ipv4(struct pkt_buff *pkt, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
+int nfq_tcp_mangle_ipv6(struct pkt_buff *pkt, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcp);
diff --git a/include/libnetfilter_queue/libnetfilter_queue_udp.h b/include/libnetfilter_queue/libnetfilter_queue_udp.h
index f4b6c49..f9fd609 100644
--- a/include/libnetfilter_queue/libnetfilter_queue_udp.h
+++ b/include/libnetfilter_queue/libnetfilter_queue_udp.h
@@ -11,6 +11,7 @@ void nfq_udp_compute_checksum_ipv4(struct udphdr *udph, struct iphdr *iph);
void nfq_udp_compute_checksum_ipv6(struct udphdr *udph, struct ip6_hdr *ip6h);
int nfq_udp_mangle_ipv4(struct pkt_buff *pkt, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
+int nfq_udp_mangle_ipv6(struct pkt_buff *pktb, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
int nfq_udp_snprintf(char *buf, size_t size, const struct udphdr *udp);
--git a/src/extra/ipv6.c b/src/extra/ipv6.c
index f685b3b..6e8820c 100644
--- a/src/extra/ipv6.c
+++ b/src/extra/ipv6.c
@@ -116,6 +116,35 @@ int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h,
return cur ? 1 : 0;
}
+/**
+ * nfq_ip6_mangle - mangle IPv6 packet buffer
+ * \param pktb: Pointer to user-space network packet buffer
+ * \param dataoff: Offset to layer 4 header
+ * \param match_offset: Offset to content that you want to mangle
+ * \param match_len: Length of the existing content you want to mangle
+ * \param rep_buffer: Pointer to data you want to use to replace current content
+ * \param rep_len: Length of data you want to use to replace current content
+ * \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
+ * \note This function updates the IPv6 length (if necessary)
+ */
+EXPORT_SYMBOL
+int nfq_ip6_mangle(struct pkt_buff *pktb, unsigned int dataoff,
+ unsigned int match_offset, unsigned int match_len,
+ const char *rep_buffer, unsigned int rep_len)
+{
+ struct ip6_hdr *ip6h = (struct ip6_hdr *)pktb->network_header;
+
+ if (!pktb_mangle(pktb, dataoff, match_offset, match_len, rep_buffer,
+ rep_len))
+ return 0;
+
+ /* Fix IPv6 hdr length information */
+ ip6h->ip6_plen =
+ htons(pktb->tail - pktb->network_header - sizeof *ip6h);
+
+ return 1;
+}
+
/**
* nfq_ip6_snprintf - print IPv6 header into one buffer in iptables LOG format
* \param buf: Pointer to buffer that is used to print the object
--git a/src/extra/tcp.c b/src/extra/tcp.c
index 136d7ea..8119843 100644
--- a/src/extra/tcp.c
+++ b/src/extra/tcp.c
@@ -21,6 +21,7 @@
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
+#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
#include <libnetfilter_queue/pktbuff.h>
#include "internal.h"
@@ -206,6 +207,45 @@ int nfq_tcp_mangle_ipv4(struct pkt_buff *pkt,
return 1;
}
+/**
+ * nfq_tcp_mangle_ipv6 - Mangle TCP/IPv6 packet buffer
+ * \param pktb: Pointer to network packet buffer
+ * \param match_offset: Offset from start of TCP data of content that you want
+ * to mangle
+ * \param match_len: Length of the existing content you want to mangle
+ * \param rep_buffer: Pointer to data you want to use to replace current content
+ * \param rep_len: Length of data you want to use to replace current content
+ * \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
+ * \note This function updates the IPv6 length and recalculates the TCP
+ * checksum for you.
+ * \warning After changing the length of a TCP message, the application will
+ * need to mangle sequence numbers in both directions until another change
+ * puts them in sync again
+ */
+EXPORT_SYMBOL
+int nfq_tcp_mangle_ipv6(struct pkt_buff *pktb,
+ unsigned int match_offset, unsigned int match_len,
+ const char *rep_buffer, unsigned int rep_len)
+{
+ struct ip6_hdr *ip6h;
+ struct tcphdr *tcph;
+
+ ip6h = (struct ip6_hdr *)pktb->network_header;
+ tcph = (struct tcphdr *)(pktb->transport_header);
+ if (!tcph)
+ return 0;
+
+ if (!nfq_ip6_mangle(pktb,
+ pktb->transport_header - pktb->network_header +
+ tcph->doff * 4,
+ match_offset, match_len, rep_buffer, rep_len))
+ return 0;
+
+ nfq_tcp_compute_checksum_ipv6(tcph, ip6h);
+
+ return 1;
+}
+
/**
* @}
*/
--git a/src/extra/udp.c b/src/extra/udp.c
index 34dbf2a..9eee1c7 100644
--- a/src/extra/udp.c
+++ b/src/extra/udp.c
@@ -20,6 +20,7 @@
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <libnetfilter_queue/libnetfilter_queue_udp.h>
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
+#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
#include <libnetfilter_queue/pktbuff.h>
#include "internal.h"
@@ -159,6 +160,44 @@ int nfq_udp_mangle_ipv4(struct pkt_buff *pktb,
return 1;
}
+/**
+ * nfq_udp_mangle_ipv6 - Mangle UDP/IPv6 packet buffer
+ * \param pktb: Pointer to network packet buffer
+ * \param match_offset: Offset from start of UDP data of content that you want
+ * to mangle
+ * \param match_len: Length of the existing content you want to mangle
+ * \param rep_buffer: Pointer to data you want to use to replace current content
+ * \param rep_len: Length of data you want to use to replace current content
+ * \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
+ * \note This function updates the IPv6 and UDP lengths and recalculates the UDP
+ * checksum for you.
+ */
+EXPORT_SYMBOL
+int nfq_udp_mangle_ipv6(struct pkt_buff *pktb,
+ unsigned int match_offset, unsigned int match_len,
+ const char *rep_buffer, unsigned int rep_len)
+{
+ struct ip6_hdr *ip6h;
+ struct udphdr *udph;
+
+ ip6h = (struct ip6_hdr *)pktb->network_header;
+ udph = (struct udphdr *)(pktb->transport_header);
+ if (!udph)
+ return 0;
+
+ udph->len = htons(ntohs(udph->len) + rep_len - match_len);
+
+ if (!nfq_ip6_mangle(pktb,
+ pktb->transport_header - pktb->network_header +
+ sizeof(struct udphdr),
+ match_offset, match_len, rep_buffer, rep_len))
+ return 0;
+
+ nfq_udp_compute_checksum_ipv6(udph, ip6h);
+
+ return 1;
+}
+
/**
* nfq_pkt_snprintf_udp_hdr - print udp header into one buffer in a humnan
* readable way
--
2.14.5
^ permalink raw reply related [flat|nested] 7+ messages in thread