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