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