Blame view

net/netfilter/xt_addrtype.c 6.55 KB
1da177e4c   Linus Torvalds   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   Laszlo Attila Toth   [NETFILTER]: ipt_...
5
   *  (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
1da177e4c   Linus Torvalds   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   Jan Engelhardt   netfilter: xt ext...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   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   Igor Maravić   net:netfilter: us...
18
  #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
2f5dc6312   Florian Westphal   netfilter: xt_add...
19
20
21
22
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
  #include <net/ip6_fib.h>
  #endif
2a7851bff   Florian Westphal   netfilter: add nf...
23
  #include <linux/netfilter_ipv6.h>
de81bbea1   Florian Westphal   netfilter: ipt_ad...
24
  #include <linux/netfilter/xt_addrtype.h>
6709dbbb1   Jan Engelhardt   [NETFILTER]: {ip,...
25
  #include <linux/netfilter/x_tables.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
de81bbea1   Florian Westphal   netfilter: ipt_ad...
29
30
  MODULE_DESCRIPTION("Xtables: address type match");
  MODULE_ALIAS("ipt_addrtype");
2f5dc6312   Florian Westphal   netfilter: xt_add...
31
  MODULE_ALIAS("ip6t_addrtype");
c0cd11566   Igor Maravić   net:netfilter: us...
32
  #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
b7225041e   Florian Westphal   netfilter: xt_add...
33
  static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
2a7851bff   Florian Westphal   netfilter: add nf...
34
  			    const struct in6_addr *addr, u16 mask)
2f5dc6312   Florian Westphal   netfilter: xt_add...
35
  {
b7225041e   Florian Westphal   netfilter: xt_add...
36
37
38
  	const struct nf_afinfo *afinfo;
  	struct flowi6 flow;
  	struct rt6_info *rt;
2a7851bff   Florian Westphal   netfilter: add nf...
39
  	u32 ret = 0;
b7225041e   Florian Westphal   netfilter: xt_add...
40
  	int route_err;
2f5dc6312   Florian Westphal   netfilter: xt_add...
41

b7225041e   Florian Westphal   netfilter: xt_add...
42
  	memset(&flow, 0, sizeof(flow));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
43
  	flow.daddr = *addr;
b7225041e   Florian Westphal   netfilter: xt_add...
44
45
  	if (dev)
  		flow.flowi6_oif = dev->ifindex;
b7225041e   Florian Westphal   netfilter: xt_add...
46
  	afinfo = nf_get_afinfo(NFPROTO_IPV6);
2a7851bff   Florian Westphal   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   Florian Westphal   netfilter: xt_add...
55
  		route_err = afinfo->route(net, (struct dst_entry **)&rt,
2a7851bff   Florian Westphal   netfilter: add nf...
56
57
  					  flowi6_to_flowi(&flow), false);
  	} else {
b7225041e   Florian Westphal   netfilter: xt_add...
58
  		route_err = 1;
2a7851bff   Florian Westphal   netfilter: add nf...
59
  	}
b7225041e   Florian Westphal   netfilter: xt_add...
60
61
  
  	if (route_err)
2f5dc6312   Florian Westphal   netfilter: xt_add...
62
63
64
65
  		return XT_ADDRTYPE_UNREACHABLE;
  
  	if (rt->rt6i_flags & RTF_REJECT)
  		ret = XT_ADDRTYPE_UNREACHABLE;
2f5dc6312   Florian Westphal   netfilter: xt_add...
66

2a7851bff   Florian Westphal   netfilter: add nf...
67
  	if (dev == NULL && rt->rt6i_flags & RTF_LOCAL)
2f5dc6312   Florian Westphal   netfilter: xt_add...
68
  		ret |= XT_ADDRTYPE_LOCAL;
2647a9b07   Martin KaFai Lau   ipv6: Remove exte...
69
  	if (ipv6_anycast_destination((struct dst_entry *)rt, addr))
2f5dc6312   Florian Westphal   netfilter: xt_add...
70
  		ret |= XT_ADDRTYPE_ANYCAST;
b7225041e   Florian Westphal   netfilter: xt_add...
71

b7225041e   Florian Westphal   netfilter: xt_add...
72
  	dst_release(&rt->dst);
2f5dc6312   Florian Westphal   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   Florian Westphal   netfilter: xt_add...
90
  	     XT_ADDRTYPE_UNREACHABLE) & mask)
2a7851bff   Florian Westphal   netfilter: add nf...
91
  		return !!(mask & match_lookup_rt6(net, dev, addr, mask));
2f5dc6312   Florian Westphal   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   Linus Torvalds   Linux-2.6.12-rc2
111

d4ec52bae   Alexey Dobriyan   netfilter: netns-...
112
113
  static inline bool match_type(struct net *net, const struct net_device *dev,
  			      __be32 addr, u_int16_t mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
d4ec52bae   Alexey Dobriyan   netfilter: netns-...
115
  	return !!(mask & (1 << inet_dev_addr_type(net, dev, addr)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
117
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
118
  addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  {
613dbd957   Pablo Neira Ayuso   netfilter: x_tabl...
120
  	struct net *net = xt_net(par);
de81bbea1   Florian Westphal   netfilter: ipt_ad...
121
  	const struct xt_addrtype_info *info = par->matchinfo;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
122
  	const struct iphdr *iph = ip_hdr(skb);
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
123
  	bool ret = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  
  	if (info->source)
d4ec52bae   Alexey Dobriyan   netfilter: netns-...
126
  		ret &= match_type(net, NULL, iph->saddr, info->source) ^
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
127
  		       info->invert_source;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  	if (info->dest)
d4ec52bae   Alexey Dobriyan   netfilter: netns-...
129
  		ret &= match_type(net, NULL, iph->daddr, info->dest) ^
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
130
  		       info->invert_dest;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
131

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
  	return ret;
  }
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
134
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
135
  addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
136
  {
613dbd957   Pablo Neira Ayuso   netfilter: x_tabl...
137
  	struct net *net = xt_net(par);
de81bbea1   Florian Westphal   netfilter: ipt_ad...
138
  	const struct xt_addrtype_info_v1 *info = par->matchinfo;
2f5dc6312   Florian Westphal   netfilter: xt_add...
139
  	const struct iphdr *iph;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
140
141
  	const struct net_device *dev = NULL;
  	bool ret = true;
de81bbea1   Florian Westphal   netfilter: ipt_ad...
142
  	if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
613dbd957   Pablo Neira Ayuso   netfilter: x_tabl...
143
  		dev = xt_in(par);
de81bbea1   Florian Westphal   netfilter: ipt_ad...
144
  	else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
613dbd957   Pablo Neira Ayuso   netfilter: x_tabl...
145
  		dev = xt_out(par);
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
146

c0cd11566   Igor Maravić   net:netfilter: us...
147
  #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
613dbd957   Pablo Neira Ayuso   netfilter: x_tabl...
148
  	if (xt_family(par) == NFPROTO_IPV6)
2f5dc6312   Florian Westphal   netfilter: xt_add...
149
150
151
  		return addrtype_mt6(net, dev, skb, info);
  #endif
  	iph = ip_hdr(skb);
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
152
  	if (info->source)
d4ec52bae   Alexey Dobriyan   netfilter: netns-...
153
  		ret &= match_type(net, dev, iph->saddr, info->source) ^
de81bbea1   Florian Westphal   netfilter: ipt_ad...
154
  		       (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
155
  	if (ret && info->dest)
d4ec52bae   Alexey Dobriyan   netfilter: netns-...
156
  		ret &= match_type(net, dev, iph->daddr, info->dest) ^
de81bbea1   Florian Westphal   netfilter: ipt_ad...
157
  		       !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
158
159
  	return ret;
  }
b0f38452f   Jan Engelhardt   netfilter: xtable...
160
  static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
161
  {
de81bbea1   Florian Westphal   netfilter: ipt_ad...
162
  	struct xt_addrtype_info_v1 *info = par->matchinfo;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
163

de81bbea1   Florian Westphal   netfilter: ipt_ad...
164
165
  	if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN &&
  	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
ff67e4e42   Jan Engelhardt   netfilter: xt ext...
166
167
168
  		pr_info("both incoming and outgoing "
  			"interface limitation cannot be selected
  ");
bd414ee60   Jan Engelhardt   netfilter: xtable...
169
  		return -EINVAL;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
170
  	}
9b4fce7a3   Jan Engelhardt   netfilter: xtable...
171
172
  	if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
  	    (1 << NF_INET_LOCAL_IN)) &&
de81bbea1   Florian Westphal   netfilter: ipt_ad...
173
  	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
ff67e4e42   Jan Engelhardt   netfilter: xt ext...
174
175
176
  		pr_info("output interface limitation "
  			"not valid in PREROUTING and INPUT
  ");
bd414ee60   Jan Engelhardt   netfilter: xtable...
177
  		return -EINVAL;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
178
  	}
9b4fce7a3   Jan Engelhardt   netfilter: xtable...
179
180
  	if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
  	    (1 << NF_INET_LOCAL_OUT)) &&
de81bbea1   Florian Westphal   netfilter: ipt_ad...
181
  	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) {
ff67e4e42   Jan Engelhardt   netfilter: xt ext...
182
183
184
  		pr_info("input interface limitation "
  			"not valid in POSTROUTING and OUTPUT
  ");
bd414ee60   Jan Engelhardt   netfilter: xtable...
185
  		return -EINVAL;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
186
  	}
c0cd11566   Igor Maravić   net:netfilter: us...
187
  #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
2f5dc6312   Florian Westphal   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   Phil Oester   netfilter: xt_add...
195
196
  			pr_err("ipv6 PROHIBIT (THROW, NAT ..) matching not supported
  ");
2f5dc6312   Florian Westphal   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   Jan Engelhardt   netfilter: xtable...
206
  	return 0;
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
207
208
209
210
211
  }
  
  static struct xt_match addrtype_mt_reg[] __read_mostly = {
  	{
  		.name		= "addrtype",
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
212
  		.family		= NFPROTO_IPV4,
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
213
  		.match		= addrtype_mt_v0,
de81bbea1   Florian Westphal   netfilter: ipt_ad...
214
  		.matchsize	= sizeof(struct xt_addrtype_info),
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
215
216
217
218
  		.me		= THIS_MODULE
  	},
  	{
  		.name		= "addrtype",
2f5dc6312   Florian Westphal   netfilter: xt_add...
219
  		.family		= NFPROTO_UNSPEC,
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
220
221
222
  		.revision	= 1,
  		.match		= addrtype_mt_v1,
  		.checkentry	= addrtype_mt_checkentry_v1,
de81bbea1   Florian Westphal   netfilter: ipt_ad...
223
  		.matchsize	= sizeof(struct xt_addrtype_info_v1),
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
224
225
  		.me		= THIS_MODULE
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  };
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
227
  static int __init addrtype_mt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  {
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
229
230
  	return xt_register_matches(addrtype_mt_reg,
  				   ARRAY_SIZE(addrtype_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
232
  static void __exit addrtype_mt_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  {
e2cf5ecbe   Laszlo Attila Toth   [NETFILTER]: ipt_...
234
  	xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
236
237
  module_init(addrtype_mt_init);
  module_exit(addrtype_mt_exit);