]>
Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
74f77a6b JC |
2 | /* Kernel module to match L2TP header parameters. */ |
3 | ||
4 | /* (C) 2013 James Chapman <[email protected]> | |
74f77a6b JC |
5 | */ |
6 | ||
7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
8 | #include <linux/module.h> | |
9 | #include <linux/skbuff.h> | |
10 | #include <linux/if_ether.h> | |
11 | #include <net/ip.h> | |
12 | #include <linux/ipv6.h> | |
13 | #include <net/ipv6.h> | |
14 | #include <net/udp.h> | |
15 | #include <linux/l2tp.h> | |
16 | ||
17 | #include <linux/netfilter_ipv4.h> | |
18 | #include <linux/netfilter_ipv6.h> | |
19 | #include <linux/netfilter_ipv4/ip_tables.h> | |
20 | #include <linux/netfilter_ipv6/ip6_tables.h> | |
21 | #include <linux/netfilter/x_tables.h> | |
22 | #include <linux/netfilter/xt_tcpudp.h> | |
23 | #include <linux/netfilter/xt_l2tp.h> | |
24 | ||
25 | /* L2TP header masks */ | |
26 | #define L2TP_HDR_T_BIT 0x8000 | |
27 | #define L2TP_HDR_L_BIT 0x4000 | |
28 | #define L2TP_HDR_VER 0x000f | |
29 | ||
30 | MODULE_LICENSE("GPL"); | |
31 | MODULE_AUTHOR("James Chapman <[email protected]>"); | |
32 | MODULE_DESCRIPTION("Xtables: L2TP header match"); | |
33 | MODULE_ALIAS("ipt_l2tp"); | |
34 | MODULE_ALIAS("ip6t_l2tp"); | |
35 | ||
36 | /* The L2TP fields that can be matched */ | |
37 | struct l2tp_data { | |
38 | u32 tid; | |
39 | u32 sid; | |
40 | u8 type; | |
41 | u8 version; | |
42 | }; | |
43 | ||
44 | union l2tp_val { | |
45 | __be16 val16[2]; | |
46 | __be32 val32; | |
47 | }; | |
48 | ||
49 | static bool l2tp_match(const struct xt_l2tp_info *info, struct l2tp_data *data) | |
50 | { | |
51 | if ((info->flags & XT_L2TP_TYPE) && (info->type != data->type)) | |
52 | return false; | |
53 | ||
54 | if ((info->flags & XT_L2TP_VERSION) && (info->version != data->version)) | |
55 | return false; | |
56 | ||
57 | /* Check tid only for L2TPv3 control or any L2TPv2 packets */ | |
58 | if ((info->flags & XT_L2TP_TID) && | |
59 | ((data->type == XT_L2TP_TYPE_CONTROL) || (data->version == 2)) && | |
60 | (info->tid != data->tid)) | |
61 | return false; | |
62 | ||
63 | /* Check sid only for L2TP data packets */ | |
64 | if ((info->flags & XT_L2TP_SID) && (data->type == XT_L2TP_TYPE_DATA) && | |
65 | (info->sid != data->sid)) | |
66 | return false; | |
67 | ||
68 | return true; | |
69 | } | |
70 | ||
71 | /* Parse L2TP header fields when UDP encapsulation is used. Handles | |
72 | * L2TPv2 and L2TPv3. Note the L2TPv3 control and data packets have a | |
73 | * different format. See | |
74 | * RFC2661, Section 3.1, L2TPv2 Header Format | |
75 | * RFC3931, Section 3.2.1, L2TPv3 Control Message Header | |
76 | * RFC3931, Section 3.2.2, L2TPv3 Data Message Header | |
77 | * RFC3931, Section 4.1.2.1, L2TPv3 Session Header over UDP | |
78 | */ | |
79 | static bool l2tp_udp_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff) | |
80 | { | |
81 | const struct xt_l2tp_info *info = par->matchinfo; | |
82 | int uhlen = sizeof(struct udphdr); | |
83 | int offs = thoff + uhlen; | |
84 | union l2tp_val *lh; | |
85 | union l2tp_val lhbuf; | |
86 | u16 flags; | |
87 | struct l2tp_data data = { 0, }; | |
88 | ||
89 | if (par->fragoff != 0) | |
90 | return false; | |
91 | ||
92 | /* Extract L2TP header fields. The flags in the first 16 bits | |
93 | * tell us where the other fields are. | |
94 | */ | |
95 | lh = skb_header_pointer(skb, offs, 2, &lhbuf); | |
96 | if (lh == NULL) | |
97 | return false; | |
98 | ||
99 | flags = ntohs(lh->val16[0]); | |
100 | if (flags & L2TP_HDR_T_BIT) | |
101 | data.type = XT_L2TP_TYPE_CONTROL; | |
102 | else | |
103 | data.type = XT_L2TP_TYPE_DATA; | |
104 | data.version = (u8) flags & L2TP_HDR_VER; | |
105 | ||
106 | /* Now extract the L2TP tid/sid. These are in different places | |
107 | * for L2TPv2 (rfc2661) and L2TPv3 (rfc3931). For L2TPv2, we | |
108 | * must also check to see if the length field is present, | |
109 | * since this affects the offsets into the packet of the | |
110 | * tid/sid fields. | |
111 | */ | |
112 | if (data.version == 3) { | |
113 | lh = skb_header_pointer(skb, offs + 4, 4, &lhbuf); | |
114 | if (lh == NULL) | |
115 | return false; | |
116 | if (data.type == XT_L2TP_TYPE_CONTROL) | |
117 | data.tid = ntohl(lh->val32); | |
118 | else | |
119 | data.sid = ntohl(lh->val32); | |
120 | } else if (data.version == 2) { | |
121 | if (flags & L2TP_HDR_L_BIT) | |
122 | offs += 2; | |
123 | lh = skb_header_pointer(skb, offs + 2, 4, &lhbuf); | |
124 | if (lh == NULL) | |
125 | return false; | |
126 | data.tid = (u32) ntohs(lh->val16[0]); | |
127 | data.sid = (u32) ntohs(lh->val16[1]); | |
128 | } else | |
129 | return false; | |
130 | ||
131 | return l2tp_match(info, &data); | |
132 | } | |
133 | ||
134 | /* Parse L2TP header fields for IP encapsulation (no UDP header). | |
135 | * L2TPv3 data packets have a different form with IP encap. See | |
136 | * RC3931, Section 4.1.1.1, L2TPv3 Session Header over IP. | |
137 | * RC3931, Section 4.1.1.2, L2TPv3 Control and Data Traffic over IP. | |
138 | */ | |
139 | static bool l2tp_ip_mt(const struct sk_buff *skb, struct xt_action_param *par, u16 thoff) | |
140 | { | |
141 | const struct xt_l2tp_info *info = par->matchinfo; | |
142 | union l2tp_val *lh; | |
143 | union l2tp_val lhbuf; | |
144 | struct l2tp_data data = { 0, }; | |
145 | ||
146 | /* For IP encap, the L2TP sid is the first 32-bits. */ | |
147 | lh = skb_header_pointer(skb, thoff, sizeof(lhbuf), &lhbuf); | |
148 | if (lh == NULL) | |
149 | return false; | |
150 | if (lh->val32 == 0) { | |
151 | /* Must be a control packet. The L2TP tid is further | |
152 | * into the packet. | |
153 | */ | |
154 | data.type = XT_L2TP_TYPE_CONTROL; | |
155 | lh = skb_header_pointer(skb, thoff + 8, sizeof(lhbuf), | |
156 | &lhbuf); | |
157 | if (lh == NULL) | |
158 | return false; | |
159 | data.tid = ntohl(lh->val32); | |
160 | } else { | |
161 | data.sid = ntohl(lh->val32); | |
162 | data.type = XT_L2TP_TYPE_DATA; | |
163 | } | |
164 | ||
165 | data.version = 3; | |
166 | ||
167 | return l2tp_match(info, &data); | |
168 | } | |
169 | ||
170 | static bool l2tp_mt4(const struct sk_buff *skb, struct xt_action_param *par) | |
171 | { | |
172 | struct iphdr *iph = ip_hdr(skb); | |
173 | u8 ipproto = iph->protocol; | |
174 | ||
175 | /* l2tp_mt_check4 already restricts the transport protocol */ | |
176 | switch (ipproto) { | |
177 | case IPPROTO_UDP: | |
178 | return l2tp_udp_mt(skb, par, par->thoff); | |
179 | case IPPROTO_L2TP: | |
180 | return l2tp_ip_mt(skb, par, par->thoff); | |
181 | } | |
182 | ||
183 | return false; | |
184 | } | |
185 | ||
186 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
187 | static bool l2tp_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |
188 | { | |
189 | unsigned int thoff = 0; | |
190 | unsigned short fragoff = 0; | |
191 | int ipproto; | |
192 | ||
193 | ipproto = ipv6_find_hdr(skb, &thoff, -1, &fragoff, NULL); | |
194 | if (fragoff != 0) | |
195 | return false; | |
196 | ||
197 | /* l2tp_mt_check6 already restricts the transport protocol */ | |
198 | switch (ipproto) { | |
199 | case IPPROTO_UDP: | |
200 | return l2tp_udp_mt(skb, par, thoff); | |
201 | case IPPROTO_L2TP: | |
202 | return l2tp_ip_mt(skb, par, thoff); | |
203 | } | |
204 | ||
205 | return false; | |
206 | } | |
207 | #endif | |
208 | ||
209 | static int l2tp_mt_check(const struct xt_mtchk_param *par) | |
210 | { | |
211 | const struct xt_l2tp_info *info = par->matchinfo; | |
212 | ||
213 | /* Check for invalid flags */ | |
214 | if (info->flags & ~(XT_L2TP_TID | XT_L2TP_SID | XT_L2TP_VERSION | | |
215 | XT_L2TP_TYPE)) { | |
b2606644 | 216 | pr_info_ratelimited("unknown flags: %x\n", info->flags); |
74f77a6b JC |
217 | return -EINVAL; |
218 | } | |
219 | ||
220 | /* At least one of tid, sid or type=control must be specified */ | |
221 | if ((!(info->flags & XT_L2TP_TID)) && | |
222 | (!(info->flags & XT_L2TP_SID)) && | |
223 | ((!(info->flags & XT_L2TP_TYPE)) || | |
224 | (info->type != XT_L2TP_TYPE_CONTROL))) { | |
b2606644 FW |
225 | pr_info_ratelimited("invalid flags combination: %x\n", |
226 | info->flags); | |
74f77a6b JC |
227 | return -EINVAL; |
228 | } | |
229 | ||
230 | /* If version 2 is specified, check that incompatible params | |
231 | * are not supplied | |
232 | */ | |
233 | if (info->flags & XT_L2TP_VERSION) { | |
234 | if ((info->version < 2) || (info->version > 3)) { | |
b2606644 FW |
235 | pr_info_ratelimited("wrong L2TP version: %u\n", |
236 | info->version); | |
74f77a6b JC |
237 | return -EINVAL; |
238 | } | |
239 | ||
240 | if (info->version == 2) { | |
241 | if ((info->flags & XT_L2TP_TID) && | |
242 | (info->tid > 0xffff)) { | |
b2606644 FW |
243 | pr_info_ratelimited("v2 tid > 0xffff: %u\n", |
244 | info->tid); | |
74f77a6b JC |
245 | return -EINVAL; |
246 | } | |
247 | if ((info->flags & XT_L2TP_SID) && | |
248 | (info->sid > 0xffff)) { | |
b2606644 FW |
249 | pr_info_ratelimited("v2 sid > 0xffff: %u\n", |
250 | info->sid); | |
74f77a6b JC |
251 | return -EINVAL; |
252 | } | |
253 | } | |
254 | } | |
255 | ||
256 | return 0; | |
257 | } | |
258 | ||
259 | static int l2tp_mt_check4(const struct xt_mtchk_param *par) | |
260 | { | |
261 | const struct xt_l2tp_info *info = par->matchinfo; | |
262 | const struct ipt_entry *e = par->entryinfo; | |
263 | const struct ipt_ip *ip = &e->ip; | |
264 | int ret; | |
265 | ||
266 | ret = l2tp_mt_check(par); | |
267 | if (ret != 0) | |
268 | return ret; | |
269 | ||
270 | if ((ip->proto != IPPROTO_UDP) && | |
271 | (ip->proto != IPPROTO_L2TP)) { | |
b2606644 | 272 | pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n"); |
74f77a6b JC |
273 | return -EINVAL; |
274 | } | |
275 | ||
276 | if ((ip->proto == IPPROTO_L2TP) && | |
277 | (info->version == 2)) { | |
b2606644 | 278 | pr_info_ratelimited("v2 doesn't support IP mode\n"); |
74f77a6b JC |
279 | return -EINVAL; |
280 | } | |
281 | ||
282 | return 0; | |
283 | } | |
284 | ||
285 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
286 | static int l2tp_mt_check6(const struct xt_mtchk_param *par) | |
287 | { | |
288 | const struct xt_l2tp_info *info = par->matchinfo; | |
289 | const struct ip6t_entry *e = par->entryinfo; | |
290 | const struct ip6t_ip6 *ip = &e->ipv6; | |
291 | int ret; | |
292 | ||
293 | ret = l2tp_mt_check(par); | |
294 | if (ret != 0) | |
295 | return ret; | |
296 | ||
297 | if ((ip->proto != IPPROTO_UDP) && | |
298 | (ip->proto != IPPROTO_L2TP)) { | |
b2606644 | 299 | pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n"); |
74f77a6b JC |
300 | return -EINVAL; |
301 | } | |
302 | ||
303 | if ((ip->proto == IPPROTO_L2TP) && | |
304 | (info->version == 2)) { | |
b2606644 | 305 | pr_info_ratelimited("v2 doesn't support IP mode\n"); |
74f77a6b JC |
306 | return -EINVAL; |
307 | } | |
308 | ||
309 | return 0; | |
310 | } | |
311 | #endif | |
312 | ||
313 | static struct xt_match l2tp_mt_reg[] __read_mostly = { | |
314 | { | |
315 | .name = "l2tp", | |
316 | .revision = 0, | |
317 | .family = NFPROTO_IPV4, | |
318 | .match = l2tp_mt4, | |
319 | .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)), | |
320 | .checkentry = l2tp_mt_check4, | |
321 | .hooks = ((1 << NF_INET_PRE_ROUTING) | | |
322 | (1 << NF_INET_LOCAL_IN) | | |
323 | (1 << NF_INET_LOCAL_OUT) | | |
324 | (1 << NF_INET_FORWARD)), | |
325 | .me = THIS_MODULE, | |
326 | }, | |
327 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
328 | { | |
329 | .name = "l2tp", | |
330 | .revision = 0, | |
331 | .family = NFPROTO_IPV6, | |
332 | .match = l2tp_mt6, | |
333 | .matchsize = XT_ALIGN(sizeof(struct xt_l2tp_info)), | |
334 | .checkentry = l2tp_mt_check6, | |
335 | .hooks = ((1 << NF_INET_PRE_ROUTING) | | |
336 | (1 << NF_INET_LOCAL_IN) | | |
337 | (1 << NF_INET_LOCAL_OUT) | | |
338 | (1 << NF_INET_FORWARD)), | |
339 | .me = THIS_MODULE, | |
340 | }, | |
341 | #endif | |
342 | }; | |
343 | ||
344 | static int __init l2tp_mt_init(void) | |
345 | { | |
346 | return xt_register_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg)); | |
347 | } | |
348 | ||
349 | static void __exit l2tp_mt_exit(void) | |
350 | { | |
351 | xt_unregister_matches(&l2tp_mt_reg[0], ARRAY_SIZE(l2tp_mt_reg)); | |
352 | } | |
353 | ||
354 | module_init(l2tp_mt_init); | |
355 | module_exit(l2tp_mt_exit); |