root/net/netfilter/xt_addrtype.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. match_lookup_rt6
  2. match_type6
  3. addrtype_mt6
  4. match_type
  5. addrtype_mt_v0
  6. addrtype_mt_v1
  7. addrtype_mt_checkentry_v1
  8. addrtype_mt_init
  9. addrtype_mt_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  iptables module to match inet_addr_type() of an ip.
   4  *
   5  *  Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
   6  *  (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
   7  */
   8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/skbuff.h>
  12 #include <linux/netdevice.h>
  13 #include <linux/ip.h>
  14 #include <net/route.h>
  15 
  16 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  17 #include <net/ipv6.h>
  18 #include <net/ip6_route.h>
  19 #include <net/ip6_fib.h>
  20 #endif
  21 
  22 #include <linux/netfilter_ipv6.h>
  23 #include <linux/netfilter/xt_addrtype.h>
  24 #include <linux/netfilter/x_tables.h>
  25 
  26 MODULE_LICENSE("GPL");
  27 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  28 MODULE_DESCRIPTION("Xtables: address type match");
  29 MODULE_ALIAS("ipt_addrtype");
  30 MODULE_ALIAS("ip6t_addrtype");
  31 
  32 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  33 static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
  34                             const struct in6_addr *addr, u16 mask)
  35 {
  36         struct flowi6 flow;
  37         struct rt6_info *rt;
  38         u32 ret = 0;
  39         int route_err;
  40 
  41         memset(&flow, 0, sizeof(flow));
  42         flow.daddr = *addr;
  43         if (dev)
  44                 flow.flowi6_oif = dev->ifindex;
  45 
  46         if (dev && (mask & XT_ADDRTYPE_LOCAL)) {
  47                 if (nf_ipv6_chk_addr(net, addr, dev, true))
  48                         ret = XT_ADDRTYPE_LOCAL;
  49         }
  50 
  51         route_err = nf_ip6_route(net, (struct dst_entry **)&rt,
  52                                  flowi6_to_flowi(&flow), false);
  53         if (route_err)
  54                 return XT_ADDRTYPE_UNREACHABLE;
  55 
  56         if (rt->rt6i_flags & RTF_REJECT)
  57                 ret = XT_ADDRTYPE_UNREACHABLE;
  58 
  59         if (dev == NULL && rt->rt6i_flags & RTF_LOCAL)
  60                 ret |= XT_ADDRTYPE_LOCAL;
  61         if (ipv6_anycast_destination((struct dst_entry *)rt, addr))
  62                 ret |= XT_ADDRTYPE_ANYCAST;
  63 
  64         dst_release(&rt->dst);
  65         return ret;
  66 }
  67 
  68 static bool match_type6(struct net *net, const struct net_device *dev,
  69                                 const struct in6_addr *addr, u16 mask)
  70 {
  71         int addr_type = ipv6_addr_type(addr);
  72 
  73         if ((mask & XT_ADDRTYPE_MULTICAST) &&
  74             !(addr_type & IPV6_ADDR_MULTICAST))
  75                 return false;
  76         if ((mask & XT_ADDRTYPE_UNICAST) && !(addr_type & IPV6_ADDR_UNICAST))
  77                 return false;
  78         if ((mask & XT_ADDRTYPE_UNSPEC) && addr_type != IPV6_ADDR_ANY)
  79                 return false;
  80 
  81         if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
  82              XT_ADDRTYPE_UNREACHABLE) & mask)
  83                 return !!(mask & match_lookup_rt6(net, dev, addr, mask));
  84         return true;
  85 }
  86 
  87 static bool
  88 addrtype_mt6(struct net *net, const struct net_device *dev,
  89         const struct sk_buff *skb, const struct xt_addrtype_info_v1 *info)
  90 {
  91         const struct ipv6hdr *iph = ipv6_hdr(skb);
  92         bool ret = true;
  93 
  94         if (info->source)
  95                 ret &= match_type6(net, dev, &iph->saddr, info->source) ^
  96                        (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
  97         if (ret && info->dest)
  98                 ret &= match_type6(net, dev, &iph->daddr, info->dest) ^
  99                        !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
 100         return ret;
 101 }
 102 #endif
 103 
 104 static inline bool match_type(struct net *net, const struct net_device *dev,
 105                               __be32 addr, u_int16_t mask)
 106 {
 107         return !!(mask & (1 << inet_dev_addr_type(net, dev, addr)));
 108 }
 109 
 110 static bool
 111 addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
 112 {
 113         struct net *net = xt_net(par);
 114         const struct xt_addrtype_info *info = par->matchinfo;
 115         const struct iphdr *iph = ip_hdr(skb);
 116         bool ret = true;
 117 
 118         if (info->source)
 119                 ret &= match_type(net, NULL, iph->saddr, info->source) ^
 120                        info->invert_source;
 121         if (info->dest)
 122                 ret &= match_type(net, NULL, iph->daddr, info->dest) ^
 123                        info->invert_dest;
 124 
 125         return ret;
 126 }
 127 
 128 static bool
 129 addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
 130 {
 131         struct net *net = xt_net(par);
 132         const struct xt_addrtype_info_v1 *info = par->matchinfo;
 133         const struct iphdr *iph;
 134         const struct net_device *dev = NULL;
 135         bool ret = true;
 136 
 137         if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
 138                 dev = xt_in(par);
 139         else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
 140                 dev = xt_out(par);
 141 
 142 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 143         if (xt_family(par) == NFPROTO_IPV6)
 144                 return addrtype_mt6(net, dev, skb, info);
 145 #endif
 146         iph = ip_hdr(skb);
 147         if (info->source)
 148                 ret &= match_type(net, dev, iph->saddr, info->source) ^
 149                        (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
 150         if (ret && info->dest)
 151                 ret &= match_type(net, dev, iph->daddr, info->dest) ^
 152                        !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
 153         return ret;
 154 }
 155 
 156 static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
 157 {
 158         const char *errmsg = "both incoming and outgoing interface limitation cannot be selected";
 159         struct xt_addrtype_info_v1 *info = par->matchinfo;
 160 
 161         if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN &&
 162             info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
 163                 goto err;
 164 
 165         if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
 166             (1 << NF_INET_LOCAL_IN)) &&
 167             info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
 168                 errmsg = "output interface limitation not valid in PREROUTING and INPUT";
 169                 goto err;
 170         }
 171 
 172         if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
 173             (1 << NF_INET_LOCAL_OUT)) &&
 174             info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) {
 175                 errmsg = "input interface limitation not valid in POSTROUTING and OUTPUT";
 176                 goto err;
 177         }
 178 
 179 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 180         if (par->family == NFPROTO_IPV6) {
 181                 if ((info->source | info->dest) & XT_ADDRTYPE_BLACKHOLE) {
 182                         errmsg = "ipv6 BLACKHOLE matching not supported";
 183                         goto err;
 184                 }
 185                 if ((info->source | info->dest) >= XT_ADDRTYPE_PROHIBIT) {
 186                         errmsg = "ipv6 PROHIBIT (THROW, NAT ..) matching not supported";
 187                         goto err;
 188                 }
 189                 if ((info->source | info->dest) & XT_ADDRTYPE_BROADCAST) {
 190                         errmsg = "ipv6 does not support BROADCAST matching";
 191                         goto err;
 192                 }
 193         }
 194 #endif
 195         return 0;
 196 err:
 197         pr_info_ratelimited("%s\n", errmsg);
 198         return -EINVAL;
 199 }
 200 
 201 static struct xt_match addrtype_mt_reg[] __read_mostly = {
 202         {
 203                 .name           = "addrtype",
 204                 .family         = NFPROTO_IPV4,
 205                 .match          = addrtype_mt_v0,
 206                 .matchsize      = sizeof(struct xt_addrtype_info),
 207                 .me             = THIS_MODULE
 208         },
 209         {
 210                 .name           = "addrtype",
 211                 .family         = NFPROTO_UNSPEC,
 212                 .revision       = 1,
 213                 .match          = addrtype_mt_v1,
 214                 .checkentry     = addrtype_mt_checkentry_v1,
 215                 .matchsize      = sizeof(struct xt_addrtype_info_v1),
 216                 .me             = THIS_MODULE
 217         }
 218 };
 219 
 220 static int __init addrtype_mt_init(void)
 221 {
 222         return xt_register_matches(addrtype_mt_reg,
 223                                    ARRAY_SIZE(addrtype_mt_reg));
 224 }
 225 
 226 static void __exit addrtype_mt_exit(void)
 227 {
 228         xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
 229 }
 230 
 231 module_init(addrtype_mt_init);
 232 module_exit(addrtype_mt_exit);

/* [<][>][^][v][top][bottom][index][help] */