]> git.ipfire.org Git - thirdparty/xtables-addons.git/commitdiff
xt_ipp2p: add IPv6 support
authorJan Engelhardt <jengelh@inai.de>
Mon, 13 Sep 2021 09:20:51 +0000 (10:20 +0100)
committerJan Engelhardt <jengelh@inai.de>
Mon, 13 Sep 2021 11:05:03 +0000 (13:05 +0200)
extensions/libxt_ipp2p.c
extensions/xt_ipp2p.c

index 74be4bee95ea82d1fddff2038a57dc15e3c0bd9e..38b3be3eed0d5bde6b7c0088691b13bb7a995775 100644 (file)
@@ -230,7 +230,7 @@ static struct xtables_match ipp2p_mt_reg = {
        .version       = XTABLES_VERSION,
        .name          = "ipp2p",
        .revision      = 1,
-       .family        = NFPROTO_IPV4,
+       .family        = NFPROTO_UNSPEC,
        .size          = XT_ALIGN(sizeof(struct ipt_p2p_info)),
        .userspacesize = XT_ALIGN(sizeof(struct ipt_p2p_info)),
        .help          = ipp2p_mt_help,
index 3c0fb2d733050d65e7c225f901ac080633d22d4d..7785b57b0365349053f7428c4d8502c1fba11b72 100644 (file)
@@ -21,6 +21,7 @@ MODULE_LICENSE("GPL");
 
 union ipp2p_addr {
        __be32 ip;
+       struct in6_addr in6;
 };
 
 struct ipp2p_result_printer {
@@ -827,14 +828,23 @@ static const struct {
 };
 
 static void
-ipp2p_print_result_tcp(const union ipp2p_addr *saddr, short sport,
-                       const union ipp2p_addr *daddr, short dport,
-                       bool p2p_result, unsigned int hlen)
+ipp2p_print_result_tcp4(const union ipp2p_addr *saddr, short sport,
+                        const union ipp2p_addr *daddr, short dport,
+                        bool p2p_result, unsigned int hlen)
 {
        printk("IPP2P.debug:TCP-match: %d from: %pI4:%hu to: %pI4:%hu Length: %u\n",
               p2p_result, &saddr->ip, sport, &daddr->ip, dport, hlen);
 }
 
+static void
+ipp2p_print_result_tcp6(const union ipp2p_addr *saddr, short sport,
+                        const union ipp2p_addr *daddr, short dport,
+                        bool p2p_result, unsigned int hlen)
+{
+       printk("IPP2P.debug:TCP-match: %d from: %pI6:%hu to: %pI6:%hu Length: %u\n",
+              p2p_result, &saddr->in6, sport, &daddr->in6, dport, hlen);
+}
+
 static bool
 ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
              const unsigned char *haystack, unsigned int hlen,
@@ -876,14 +886,23 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
 }
 
 static void
-ipp2p_print_result_udp(const union ipp2p_addr *saddr, short sport,
-                       const union ipp2p_addr *daddr, short dport,
-                       bool p2p_result, unsigned int hlen)
+ipp2p_print_result_udp4(const union ipp2p_addr *saddr, short sport,
+                        const union ipp2p_addr *daddr, short dport,
+                        bool p2p_result, unsigned int hlen)
 {
        printk("IPP2P.debug:UDP-match: %d from: %pI4:%hu to: %pI4:%hu Length: %u\n",
               p2p_result, &saddr->ip, sport, &daddr->ip, dport, hlen);
 }
 
+static void
+ipp2p_print_result_udp6(const union ipp2p_addr *saddr, short sport,
+                        const union ipp2p_addr *daddr, short dport,
+                        bool p2p_result, unsigned int hlen)
+{
+       printk("IPP2P.debug:UDP-match: %d from: %pI6:%hu to: %pI6:%hu Length: %u\n",
+              p2p_result, &saddr->in6, sport, &daddr->in6, dport, hlen);
+}
+
 static bool
 ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph,
              const unsigned char *haystack, unsigned int hlen,
@@ -924,13 +943,20 @@ static bool
 ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
        const struct ipt_p2p_info *info = par->matchinfo;
-       const struct iphdr *ip = ip_hdr(skb);
        struct ipp2p_result_printer printer;
        union ipp2p_addr saddr, daddr;
        const unsigned char *haystack;  /* packet data */
        unsigned int hlen;              /* packet data length */
+       uint8_t family = xt_family(par);
+       int protocol;
 
-       /* must not be a fragment */
+       /*
+        * must not be a fragment
+        *
+        * NB, `par->fragoff` may be zero for a fragmented IPv6 packet.
+        * However, in that case the later call to `ipv6_find_hdr` will not find
+        * a transport protocol, and so we will return 0 there.
+        */
        if (par->fragoff != 0) {
                if (info->debug)
                        printk("IPP2P.match: offset found %d\n", par->fragoff);
@@ -944,24 +970,37 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
                return 0;
        }
 
-       haystack = skb_transport_header(skb);
-       hlen     = ntohs(ip->tot_len) - skb_transport_offset(skb);
+       if (family == NFPROTO_IPV4) {
+               const struct iphdr *ip = ip_hdr(skb);
+               saddr.ip = ip->saddr;
+               daddr.ip = ip->daddr;
+               protocol = ip->protocol;
+               hlen = ip_transport_len(skb);
+       } else {
+               const struct ipv6hdr *ip = ipv6_hdr(skb);
+               int thoff = 0;
 
-       saddr.ip = ip->saddr;
-       daddr.ip = ip->daddr;
+               saddr.in6 = ip->saddr;
+               daddr.in6 = ip->daddr;
+               protocol = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
+               if (protocol < 0)
+                       return 0;
+               hlen = ipv6_transport_len(skb);
+       }
 
        printer.saddr = &saddr;
        printer.daddr = &daddr;
+       haystack = skb_transport_header(skb);
 
-       switch (ip->protocol) {
+       switch (protocol) {
        case IPPROTO_TCP:       /* what to do with a TCP packet */
        {
                const struct tcphdr *tcph = tcp_hdr(skb);
 
                printer.sport = ntohs(tcph->source);
                printer.dport = ntohs(tcph->dest);
-               printer.print = ipp2p_print_result_tcp;
-
+               printer.print = family == NFPROTO_IPV6 ?
+                               ipp2p_print_result_tcp6 : ipp2p_print_result_tcp4;
                return ipp2p_mt_tcp(info, tcph, haystack, hlen, &printer);
        }
        case IPPROTO_UDP:       /* what to do with a UDP packet */
@@ -971,8 +1010,8 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
                printer.sport = ntohs(udph->source);
                printer.dport = ntohs(udph->dest);
-               printer.print = ipp2p_print_result_udp;
-
+               printer.print = family == NFPROTO_IPV6 ?
+                               ipp2p_print_result_udp6 : ipp2p_print_result_udp4;
                return ipp2p_mt_udp(info, udph, haystack, hlen, &printer);
        }
        default:
@@ -980,23 +1019,33 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
        }
 }
 
-static struct xt_match ipp2p_mt_reg __read_mostly = {
-       .name       = "ipp2p",
-       .revision   = 1,
-       .family     = NFPROTO_IPV4,
-       .match      = ipp2p_mt,
-       .matchsize  = sizeof(struct ipt_p2p_info),
-       .me         = THIS_MODULE,
+static struct xt_match ipp2p_mt_reg[] __read_mostly = {
+       {
+               .name       = "ipp2p",
+               .revision   = 1,
+               .family     = NFPROTO_IPV4,
+               .match      = ipp2p_mt,
+               .matchsize  = sizeof(struct ipt_p2p_info),
+               .me         = THIS_MODULE,
+       },
+       {
+               .name       = "ipp2p",
+               .revision   = 1,
+               .family     = NFPROTO_IPV6,
+               .match      = ipp2p_mt,
+               .matchsize  = sizeof(struct ipt_p2p_info),
+               .me         = THIS_MODULE,
+       },
 };
 
 static int __init ipp2p_mt_init(void)
 {
-       return xt_register_match(&ipp2p_mt_reg);
+       return xt_register_matches(ipp2p_mt_reg, ARRAY_SIZE(ipp2p_mt_reg));
 }
 
 static void __exit ipp2p_mt_exit(void)
 {
-       xt_unregister_match(&ipp2p_mt_reg);
+       xt_unregister_matches(ipp2p_mt_reg, ARRAY_SIZE(ipp2p_mt_reg));
 }
 
 module_init(ipp2p_mt_init);