From patchwork Fri Dec 20 05:53:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Duncan Roe X-Patchwork-Id: 1213921 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=optusnet.com.au Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47fHxW3X7Nz9sPc for ; Fri, 20 Dec 2019 16:54:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726002AbfLTFyF (ORCPT ); Fri, 20 Dec 2019 00:54:05 -0500 Received: from mail105.syd.optusnet.com.au ([211.29.132.249]:49258 "EHLO mail105.syd.optusnet.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725825AbfLTFyF (ORCPT ); Fri, 20 Dec 2019 00:54:05 -0500 Received: from dimstar.local.net (n122-110-44-45.sun2.vic.optusnet.com.au [122.110.44.45]) by mail105.syd.optusnet.com.au (Postfix) with SMTP id C3FBA3A0EAB for ; Fri, 20 Dec 2019 16:53:48 +1100 (AEDT) Received: (qmail 24159 invoked by uid 501); 20 Dec 2019 05:53:48 -0000 From: Duncan Roe To: pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH libnetfilter_queue 1/2] src: more IPv6 checksum fixes Date: Fri, 20 Dec 2019 16:53:47 +1100 Message-Id: <20191220055348.24113-2-duncan_roe@optusnet.com.au> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20191220055348.24113-1-duncan_roe@optusnet.com.au> References: <20191220055348.24113-1-duncan_roe@optusnet.com.au> X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.3 cv=X6os11be c=1 sm=1 tr=0 a=4DzML1vCOQ6Odsy8BUtSXQ==:117 a=4DzML1vCOQ6Odsy8BUtSXQ==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=pxVhFHJ0LMsA:10 a=RSmzAf-M6YYA:10 a=PO7r1zJSAAAA:8 a=lGczooPpUTXbnT1JoLQA:9 a=3vHKc1QorotQFowq:21 a=VnMiHPgbUbupJygL:21 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Updated: src/extra/checksum.c: - Fix calculation of header length - Upgrade calculation of payload length: Allow for extra headers before the UDP header - Delete "sum += ... s6_addr16[i] >> 16" lines, since uint16_t >> 16 == 0 - Use upgraded payload length in pseudo-header Signed-off-by: Duncan Roe --- src/extra/checksum.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/extra/checksum.c b/src/extra/checksum.c index 42389aa..8b23997 100644 --- a/src/extra/checksum.c +++ b/src/extra/checksum.c @@ -62,21 +62,21 @@ uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr, uint16_t protonum) { uint32_t sum = 0; - uint32_t hdr_len = (uint32_t *)transport_hdr - (uint32_t *)ip6h; - uint32_t len = ip6h->ip6_plen - hdr_len; + uint32_t hdr_len = (uint8_t *)transport_hdr - (uint8_t *)ip6h; + /* Allow for extra headers before the UDP header */ + /* TODO: Deal with routing headers */ + uint32_t len = ntohs(ip6h->ip6_plen) - (hdr_len - sizeof *ip6h); uint8_t *payload = (uint8_t *)ip6h + hdr_len; int i; for (i=0; i<8; i++) { - sum += (ip6h->ip6_src.s6_addr16[i] >> 16) & 0xFFFF; sum += (ip6h->ip6_src.s6_addr16[i]) & 0xFFFF; } for (i=0; i<8; i++) { - sum += (ip6h->ip6_dst.s6_addr16[i] >> 16) & 0xFFFF; sum += (ip6h->ip6_dst.s6_addr16[i]) & 0xFFFF; } sum += htons(protonum); - sum += htons(ip6h->ip6_plen); + sum += htons(len); return nfq_checksum(sum, (uint16_t *)payload, len); } From patchwork Fri Dec 20 05:53:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Duncan Roe X-Patchwork-Id: 1213920 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=optusnet.com.au Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47fHxV5sCJz9sPJ for ; Fri, 20 Dec 2019 16:54:06 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725941AbfLTFyF (ORCPT ); Fri, 20 Dec 2019 00:54:05 -0500 Received: from mail104.syd.optusnet.com.au ([211.29.132.246]:45295 "EHLO mail104.syd.optusnet.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725853AbfLTFyF (ORCPT ); Fri, 20 Dec 2019 00:54:05 -0500 Received: from dimstar.local.net (n122-110-44-45.sun2.vic.optusnet.com.au [122.110.44.45]) by mail104.syd.optusnet.com.au (Postfix) with SMTP id CE759820004 for ; Fri, 20 Dec 2019 16:53:48 +1100 (AEDT) Received: (qmail 24163 invoked by uid 501); 20 Dec 2019 05:53:48 -0000 From: Duncan Roe To: pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH libnetfilter_queue 2/2] src: add mangle functions for IPv6, IPv6/TCP and IPv6/UDP Date: Fri, 20 Dec 2019 16:53:48 +1100 Message-Id: <20191220055348.24113-3-duncan_roe@optusnet.com.au> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20191220055348.24113-1-duncan_roe@optusnet.com.au> References: <20191220055348.24113-1-duncan_roe@optusnet.com.au> X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.3 cv=W5xGqiek c=1 sm=1 tr=0 a=4DzML1vCOQ6Odsy8BUtSXQ==:117 a=4DzML1vCOQ6Odsy8BUtSXQ==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=pxVhFHJ0LMsA:10 a=RSmzAf-M6YYA:10 a=PO7r1zJSAAAA:8 a=yqmiQjsSZ5ETotf7rwoA:9 a=yfWvxkdt8hjYQcGF:21 a=I6fXZnAS6tfgaCu6:21 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Signed-off-by: Duncan Roe --- .../libnetfilter_queue/libnetfilter_queue_ipv6.h | 1 + .../libnetfilter_queue/libnetfilter_queue_tcp.h | 1 + .../libnetfilter_queue/libnetfilter_queue_udp.h | 1 + src/extra/ipv6.c | 29 ++++++++++++++++ src/extra/tcp.c | 40 ++++++++++++++++++++++ src/extra/udp.c | 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); diff --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 diff --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 #include #include +#include #include #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; +} + /** * @} */ diff --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 #include #include +#include #include #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