1 /* Kernel module to match L2TP header parameters. */
3 /* (C) 2013 James Chapman <jchapman@katalix.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/module.h>
12 #include <linux/skbuff.h>
13 #include <linux/if_ether.h>
15 #include <linux/ipv6.h>
18 #include <linux/l2tp.h>
20 #include <linux/netfilter_ipv4.h>
21 #include <linux/netfilter_ipv6.h>
22 #include <linux/netfilter_ipv4/ip_tables.h>
23 #include <linux/netfilter_ipv6/ip6_tables.h>
24 #include <linux/netfilter/x_tables.h>
25 #include <linux/netfilter/xt_tcpudp.h>
26 #include <linux/netfilter/xt_l2tp.h>
28 /* L2TP header masks */
29 #define L2TP_HDR_T_BIT 0x8000
30 #define L2TP_HDR_L_BIT 0x4000
31 #define L2TP_HDR_VER 0x000f
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
35 MODULE_DESCRIPTION("Xtables: L2TP header match");
36 MODULE_ALIAS("ipt_l2tp");
37 MODULE_ALIAS("ip6t_l2tp");
39 /* The L2TP fields that can be matched */
52 static bool l2tp_match(const struct xt_l2tp_info
*info
, struct l2tp_data
*data
)
54 if ((info
->flags
& XT_L2TP_TYPE
) && (info
->type
!= data
->type
))
57 if ((info
->flags
& XT_L2TP_VERSION
) && (info
->version
!= data
->version
))
60 /* Check tid only for L2TPv3 control or any L2TPv2 packets */
61 if ((info
->flags
& XT_L2TP_TID
) &&
62 ((data
->type
== XT_L2TP_TYPE_CONTROL
) || (data
->version
== 2)) &&
63 (info
->tid
!= data
->tid
))
66 /* Check sid only for L2TP data packets */
67 if ((info
->flags
& XT_L2TP_SID
) && (data
->type
== XT_L2TP_TYPE_DATA
) &&
68 (info
->sid
!= data
->sid
))
74 /* Parse L2TP header fields when UDP encapsulation is used. Handles
75 * L2TPv2 and L2TPv3. Note the L2TPv3 control and data packets have a
76 * different format. See
77 * RFC2661, Section 3.1, L2TPv2 Header Format
78 * RFC3931, Section 3.2.1, L2TPv3 Control Message Header
79 * RFC3931, Section 3.2.2, L2TPv3 Data Message Header
80 * RFC3931, Section 4.1.2.1, L2TPv3 Session Header over UDP
82 static bool l2tp_udp_mt(const struct sk_buff
*skb
, struct xt_action_param
*par
, u16 thoff
)
84 const struct xt_l2tp_info
*info
= par
->matchinfo
;
85 int uhlen
= sizeof(struct udphdr
);
86 int offs
= thoff
+ uhlen
;
90 struct l2tp_data data
= { 0, };
92 if (par
->fragoff
!= 0)
95 /* Extract L2TP header fields. The flags in the first 16 bits
96 * tell us where the other fields are.
98 lh
= skb_header_pointer(skb
, offs
, 2, &lhbuf
);
102 flags
= ntohs(lh
->val16
[0]);
103 if (flags
& L2TP_HDR_T_BIT
)
104 data
.type
= XT_L2TP_TYPE_CONTROL
;
106 data
.type
= XT_L2TP_TYPE_DATA
;
107 data
.version
= (u8
) flags
& L2TP_HDR_VER
;
109 /* Now extract the L2TP tid/sid. These are in different places
110 * for L2TPv2 (rfc2661) and L2TPv3 (rfc3931). For L2TPv2, we
111 * must also check to see if the length field is present,
112 * since this affects the offsets into the packet of the
115 if (data
.version
== 3) {
116 lh
= skb_header_pointer(skb
, offs
+ 4, 4, &lhbuf
);
119 if (data
.type
== XT_L2TP_TYPE_CONTROL
)
120 data
.tid
= ntohl(lh
->val32
);
122 data
.sid
= ntohl(lh
->val32
);
123 } else if (data
.version
== 2) {
124 if (flags
& L2TP_HDR_L_BIT
)
126 lh
= skb_header_pointer(skb
, offs
+ 2, 4, &lhbuf
);
129 data
.tid
= (u32
) ntohs(lh
->val16
[0]);
130 data
.sid
= (u32
) ntohs(lh
->val16
[1]);
134 return l2tp_match(info
, &data
);
137 /* Parse L2TP header fields for IP encapsulation (no UDP header).
138 * L2TPv3 data packets have a different form with IP encap. See
139 * RC3931, Section 4.1.1.1, L2TPv3 Session Header over IP.
140 * RC3931, Section 4.1.1.2, L2TPv3 Control and Data Traffic over IP.
142 static bool l2tp_ip_mt(const struct sk_buff
*skb
, struct xt_action_param
*par
, u16 thoff
)
144 const struct xt_l2tp_info
*info
= par
->matchinfo
;
146 union l2tp_val lhbuf
;
147 struct l2tp_data data
= { 0, };
149 /* For IP encap, the L2TP sid is the first 32-bits. */
150 lh
= skb_header_pointer(skb
, thoff
, sizeof(lhbuf
), &lhbuf
);
153 if (lh
->val32
== 0) {
154 /* Must be a control packet. The L2TP tid is further
157 data
.type
= XT_L2TP_TYPE_CONTROL
;
158 lh
= skb_header_pointer(skb
, thoff
+ 8, sizeof(lhbuf
),
162 data
.tid
= ntohl(lh
->val32
);
164 data
.sid
= ntohl(lh
->val32
);
165 data
.type
= XT_L2TP_TYPE_DATA
;
170 return l2tp_match(info
, &data
);
173 static bool l2tp_mt4(const struct sk_buff
*skb
, struct xt_action_param
*par
)
175 struct iphdr
*iph
= ip_hdr(skb
);
176 u8 ipproto
= iph
->protocol
;
178 /* l2tp_mt_check4 already restricts the transport protocol */
181 return l2tp_udp_mt(skb
, par
, par
->thoff
);
183 return l2tp_ip_mt(skb
, par
, par
->thoff
);
189 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
190 static bool l2tp_mt6(const struct sk_buff
*skb
, struct xt_action_param
*par
)
192 unsigned int thoff
= 0;
193 unsigned short fragoff
= 0;
196 ipproto
= ipv6_find_hdr(skb
, &thoff
, -1, &fragoff
, NULL
);
200 /* l2tp_mt_check6 already restricts the transport protocol */
203 return l2tp_udp_mt(skb
, par
, thoff
);
205 return l2tp_ip_mt(skb
, par
, thoff
);
212 static int l2tp_mt_check(const struct xt_mtchk_param
*par
)
214 const struct xt_l2tp_info
*info
= par
->matchinfo
;
216 /* Check for invalid flags */
217 if (info
->flags
& ~(XT_L2TP_TID
| XT_L2TP_SID
| XT_L2TP_VERSION
|
219 pr_info_ratelimited("unknown flags: %x\n", info
->flags
);
223 /* At least one of tid, sid or type=control must be specified */
224 if ((!(info
->flags
& XT_L2TP_TID
)) &&
225 (!(info
->flags
& XT_L2TP_SID
)) &&
226 ((!(info
->flags
& XT_L2TP_TYPE
)) ||
227 (info
->type
!= XT_L2TP_TYPE_CONTROL
))) {
228 pr_info_ratelimited("invalid flags combination: %x\n",
233 /* If version 2 is specified, check that incompatible params
236 if (info
->flags
& XT_L2TP_VERSION
) {
237 if ((info
->version
< 2) || (info
->version
> 3)) {
238 pr_info_ratelimited("wrong L2TP version: %u\n",
243 if (info
->version
== 2) {
244 if ((info
->flags
& XT_L2TP_TID
) &&
245 (info
->tid
> 0xffff)) {
246 pr_info_ratelimited("v2 tid > 0xffff: %u\n",
250 if ((info
->flags
& XT_L2TP_SID
) &&
251 (info
->sid
> 0xffff)) {
252 pr_info_ratelimited("v2 sid > 0xffff: %u\n",
262 static int l2tp_mt_check4(const struct xt_mtchk_param
*par
)
264 const struct xt_l2tp_info
*info
= par
->matchinfo
;
265 const struct ipt_entry
*e
= par
->entryinfo
;
266 const struct ipt_ip
*ip
= &e
->ip
;
269 ret
= l2tp_mt_check(par
);
273 if ((ip
->proto
!= IPPROTO_UDP
) &&
274 (ip
->proto
!= IPPROTO_L2TP
)) {
275 pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n");
279 if ((ip
->proto
== IPPROTO_L2TP
) &&
280 (info
->version
== 2)) {
281 pr_info_ratelimited("v2 doesn't support IP mode\n");
288 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
289 static int l2tp_mt_check6(const struct xt_mtchk_param
*par
)
291 const struct xt_l2tp_info
*info
= par
->matchinfo
;
292 const struct ip6t_entry
*e
= par
->entryinfo
;
293 const struct ip6t_ip6
*ip
= &e
->ipv6
;
296 ret
= l2tp_mt_check(par
);
300 if ((ip
->proto
!= IPPROTO_UDP
) &&
301 (ip
->proto
!= IPPROTO_L2TP
)) {
302 pr_info_ratelimited("missing protocol rule (udp|l2tpip)\n");
306 if ((ip
->proto
== IPPROTO_L2TP
) &&
307 (info
->version
== 2)) {
308 pr_info_ratelimited("v2 doesn't support IP mode\n");
316 static struct xt_match l2tp_mt_reg
[] __read_mostly
= {
320 .family
= NFPROTO_IPV4
,
322 .matchsize
= XT_ALIGN(sizeof(struct xt_l2tp_info
)),
323 .checkentry
= l2tp_mt_check4
,
324 .hooks
= ((1 << NF_INET_PRE_ROUTING
) |
325 (1 << NF_INET_LOCAL_IN
) |
326 (1 << NF_INET_LOCAL_OUT
) |
327 (1 << NF_INET_FORWARD
)),
330 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
334 .family
= NFPROTO_IPV6
,
336 .matchsize
= XT_ALIGN(sizeof(struct xt_l2tp_info
)),
337 .checkentry
= l2tp_mt_check6
,
338 .hooks
= ((1 << NF_INET_PRE_ROUTING
) |
339 (1 << NF_INET_LOCAL_IN
) |
340 (1 << NF_INET_LOCAL_OUT
) |
341 (1 << NF_INET_FORWARD
)),
347 static int __init
l2tp_mt_init(void)
349 return xt_register_matches(&l2tp_mt_reg
[0], ARRAY_SIZE(l2tp_mt_reg
));
352 static void __exit
l2tp_mt_exit(void)
354 xt_unregister_matches(&l2tp_mt_reg
[0], ARRAY_SIZE(l2tp_mt_reg
));
357 module_init(l2tp_mt_init
);
358 module_exit(l2tp_mt_exit
);