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); 233