diff options
-rw-r--r-- | MAINTAINERS | 14 | ||||
-rw-r--r-- | drivers/net/Kconfig | 11 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/pptp.c | 726 | ||||
-rw-r--r-- | include/linux/if_pppox.h | 52 | ||||
-rw-r--r-- | include/net/gre.h | 18 | ||||
-rw-r--r-- | net/ipv4/Kconfig | 7 | ||||
-rw-r--r-- | net/ipv4/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/gre.c | 151 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 14 |
10 files changed, 971 insertions, 24 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index b5b8baa1d70e..43c9efcd8e10 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6528,6 +6528,20 @@ M: "Maciej W. Rozycki" <macro@linux-mips.org> | |||
6528 | S: Maintained | 6528 | S: Maintained |
6529 | F: drivers/serial/zs.* | 6529 | F: drivers/serial/zs.* |
6530 | 6530 | ||
6531 | GRE DEMULTIPLEXER DRIVER | ||
6532 | M: Dmitry Kozlov <xeb@mail.ru> | ||
6533 | L: netdev@vger.kernel.org | ||
6534 | S: Maintained | ||
6535 | F: net/ipv4/gre.c | ||
6536 | F: include/net/gre.h | ||
6537 | |||
6538 | PPTP DRIVER | ||
6539 | M: Dmitry Kozlov <xeb@mail.ru> | ||
6540 | L: netdev@vger.kernel.org | ||
6541 | S: Maintained | ||
6542 | F: drivers/net/pptp.c | ||
6543 | W: http://sourceforge.net/projects/accel-pptp | ||
6544 | |||
6531 | THE REST | 6545 | THE REST |
6532 | M: Linus Torvalds <torvalds@linux-foundation.org> | 6546 | M: Linus Torvalds <torvalds@linux-foundation.org> |
6533 | L: linux-kernel@vger.kernel.org | 6547 | L: linux-kernel@vger.kernel.org |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5a6895320b48..9b2a72089a68 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -3192,6 +3192,17 @@ config PPPOE | |||
3192 | which contains instruction on how to use this driver (under | 3192 | which contains instruction on how to use this driver (under |
3193 | the heading "Kernel mode PPPoE"). | 3193 | the heading "Kernel mode PPPoE"). |
3194 | 3194 | ||
3195 | config PPTP | ||
3196 | tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)" | ||
3197 | depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX | ||
3198 | help | ||
3199 | Support for PPP over IPv4.(Point-to-Point Tunneling Protocol) | ||
3200 | |||
3201 | This driver requires pppd plugin to work in client mode or | ||
3202 | modified pptpd (poptop) to work in server mode. | ||
3203 | See http://accel-pptp.sourceforge.net/ for information how to | ||
3204 | utilize this module. | ||
3205 | |||
3195 | config PPPOATM | 3206 | config PPPOATM |
3196 | tristate "PPP over ATM" | 3207 | tristate "PPP over ATM" |
3197 | depends on ATM && PPP | 3208 | depends on ATM && PPP |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 56e8c27f77ce..0b371083d481 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -162,6 +162,7 @@ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o | |||
162 | obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o | 162 | obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o |
163 | obj-$(CONFIG_PPPOE) += pppox.o pppoe.o | 163 | obj-$(CONFIG_PPPOE) += pppox.o pppoe.o |
164 | obj-$(CONFIG_PPPOL2TP) += pppox.o | 164 | obj-$(CONFIG_PPPOL2TP) += pppox.o |
165 | obj-$(CONFIG_PPTP) += pppox.o pptp.o | ||
165 | 166 | ||
166 | obj-$(CONFIG_SLIP) += slip.o | 167 | obj-$(CONFIG_SLIP) += slip.o |
167 | obj-$(CONFIG_SLHC) += slhc.o | 168 | obj-$(CONFIG_SLHC) += slhc.o |
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c new file mode 100644 index 000000000000..761f0eced724 --- /dev/null +++ b/drivers/net/pptp.c | |||
@@ -0,0 +1,726 @@ | |||
1 | /* | ||
2 | * Point-to-Point Tunneling Protocol for Linux | ||
3 | * | ||
4 | * Authors: Dmitry Kozlov <xeb@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/string.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/net.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/vmalloc.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/ppp_channel.h> | ||
24 | #include <linux/ppp_defs.h> | ||
25 | #include <linux/if_pppox.h> | ||
26 | #include <linux/if_ppp.h> | ||
27 | #include <linux/notifier.h> | ||
28 | #include <linux/file.h> | ||
29 | #include <linux/in.h> | ||
30 | #include <linux/ip.h> | ||
31 | #include <linux/netfilter.h> | ||
32 | #include <linux/netfilter_ipv4.h> | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/rcupdate.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | |||
37 | #include <net/sock.h> | ||
38 | #include <net/protocol.h> | ||
39 | #include <net/ip.h> | ||
40 | #include <net/icmp.h> | ||
41 | #include <net/route.h> | ||
42 | #include <net/gre.h> | ||
43 | |||
44 | #include <linux/uaccess.h> | ||
45 | |||
46 | #define PPTP_DRIVER_VERSION "0.8.5" | ||
47 | |||
48 | #define MAX_CALLID 65535 | ||
49 | |||
50 | static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1); | ||
51 | static struct pppox_sock **callid_sock; | ||
52 | |||
53 | static DEFINE_SPINLOCK(chan_lock); | ||
54 | |||
55 | static struct proto pptp_sk_proto __read_mostly; | ||
56 | static struct ppp_channel_ops pptp_chan_ops; | ||
57 | static const struct proto_ops pptp_ops; | ||
58 | |||
59 | #define PPP_LCP_ECHOREQ 0x09 | ||
60 | #define PPP_LCP_ECHOREP 0x0A | ||
61 | #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) | ||
62 | |||
63 | #define MISSING_WINDOW 20 | ||
64 | #define WRAPPED(curseq, lastseq)\ | ||
65 | ((((curseq) & 0xffffff00) == 0) &&\ | ||
66 | (((lastseq) & 0xffffff00) == 0xffffff00)) | ||
67 | |||
68 | #define PPTP_GRE_PROTO 0x880B | ||
69 | #define PPTP_GRE_VER 0x1 | ||
70 | |||
71 | #define PPTP_GRE_FLAG_C 0x80 | ||
72 | #define PPTP_GRE_FLAG_R 0x40 | ||
73 | #define PPTP_GRE_FLAG_K 0x20 | ||
74 | #define PPTP_GRE_FLAG_S 0x10 | ||
75 | #define PPTP_GRE_FLAG_A 0x80 | ||
76 | |||
77 | #define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C) | ||
78 | #define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R) | ||
79 | #define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K) | ||
80 | #define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S) | ||
81 | #define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A) | ||
82 | |||
83 | #define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header)) | ||
84 | struct pptp_gre_header { | ||
85 | u8 flags; | ||
86 | u8 ver; | ||
87 | u16 protocol; | ||
88 | u16 payload_len; | ||
89 | u16 call_id; | ||
90 | u32 seq; | ||
91 | u32 ack; | ||
92 | } __packed; | ||
93 | |||
94 | static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) | ||
95 | { | ||
96 | struct pppox_sock *sock; | ||
97 | struct pptp_opt *opt; | ||
98 | |||
99 | rcu_read_lock(); | ||
100 | sock = rcu_dereference(callid_sock[call_id]); | ||
101 | if (sock) { | ||
102 | opt = &sock->proto.pptp; | ||
103 | if (opt->dst_addr.sin_addr.s_addr != s_addr) | ||
104 | sock = NULL; | ||
105 | else | ||
106 | sock_hold(sk_pppox(sock)); | ||
107 | } | ||
108 | rcu_read_unlock(); | ||
109 | |||
110 | return sock; | ||
111 | } | ||
112 | |||
113 | static int lookup_chan_dst(u16 call_id, __be32 d_addr) | ||
114 | { | ||
115 | struct pppox_sock *sock; | ||
116 | struct pptp_opt *opt; | ||
117 | int i; | ||
118 | |||
119 | rcu_read_lock(); | ||
120 | for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID; | ||
121 | i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) { | ||
122 | sock = rcu_dereference(callid_sock[i]); | ||
123 | if (!sock) | ||
124 | continue; | ||
125 | opt = &sock->proto.pptp; | ||
126 | if (opt->dst_addr.call_id == call_id && | ||
127 | opt->dst_addr.sin_addr.s_addr == d_addr) | ||
128 | break; | ||
129 | } | ||
130 | rcu_read_unlock(); | ||
131 | |||
132 | return i < MAX_CALLID; | ||
133 | } | ||
134 | |||
135 | static int add_chan(struct pppox_sock *sock) | ||
136 | { | ||
137 | static int call_id; | ||
138 | |||
139 | spin_lock(&chan_lock); | ||
140 | if (!sock->proto.pptp.src_addr.call_id) { | ||
141 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); | ||
142 | if (call_id == MAX_CALLID) { | ||
143 | call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); | ||
144 | if (call_id == MAX_CALLID) | ||
145 | goto out_err; | ||
146 | } | ||
147 | sock->proto.pptp.src_addr.call_id = call_id; | ||
148 | } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) | ||
149 | goto out_err; | ||
150 | |||
151 | set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); | ||
152 | rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); | ||
153 | spin_unlock(&chan_lock); | ||
154 | |||
155 | return 0; | ||
156 | |||
157 | out_err: | ||
158 | spin_unlock(&chan_lock); | ||
159 | return -1; | ||
160 | } | ||
161 | |||
162 | static void del_chan(struct pppox_sock *sock) | ||
163 | { | ||
164 | spin_lock(&chan_lock); | ||
165 | clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); | ||
166 | rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL); | ||
167 | spin_unlock(&chan_lock); | ||
168 | synchronize_rcu(); | ||
169 | } | ||
170 | |||
171 | static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | ||
172 | { | ||
173 | struct sock *sk = (struct sock *) chan->private; | ||
174 | struct pppox_sock *po = pppox_sk(sk); | ||
175 | struct pptp_opt *opt = &po->proto.pptp; | ||
176 | struct pptp_gre_header *hdr; | ||
177 | unsigned int header_len = sizeof(*hdr); | ||
178 | int err = 0; | ||
179 | int islcp; | ||
180 | int len; | ||
181 | unsigned char *data; | ||
182 | __u32 seq_recv; | ||
183 | |||
184 | |||
185 | struct rtable *rt; | ||
186 | struct net_device *tdev; | ||
187 | struct iphdr *iph; | ||
188 | int max_headroom; | ||
189 | |||
190 | if (sk_pppox(po)->sk_state & PPPOX_DEAD) | ||
191 | goto tx_error; | ||
192 | |||
193 | { | ||
194 | struct flowi fl = { .oif = 0, | ||
195 | .nl_u = { | ||
196 | .ip4_u = { | ||
197 | .daddr = opt->dst_addr.sin_addr.s_addr, | ||
198 | .saddr = opt->src_addr.sin_addr.s_addr, | ||
199 | .tos = RT_TOS(0) } }, | ||
200 | .proto = IPPROTO_GRE }; | ||
201 | err = ip_route_output_key(&init_net, &rt, &fl); | ||
202 | if (err) | ||
203 | goto tx_error; | ||
204 | } | ||
205 | tdev = rt->dst.dev; | ||
206 | |||
207 | max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2; | ||
208 | |||
209 | if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { | ||
210 | struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); | ||
211 | if (!new_skb) { | ||
212 | ip_rt_put(rt); | ||
213 | goto tx_error; | ||
214 | } | ||
215 | if (skb->sk) | ||
216 | skb_set_owner_w(new_skb, skb->sk); | ||
217 | kfree_skb(skb); | ||
218 | skb = new_skb; | ||
219 | } | ||
220 | |||
221 | data = skb->data; | ||
222 | islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7; | ||
223 | |||
224 | /* compress protocol field */ | ||
225 | if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp) | ||
226 | skb_pull(skb, 1); | ||
227 | |||
228 | /* Put in the address/control bytes if necessary */ | ||
229 | if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) { | ||
230 | data = skb_push(skb, 2); | ||
231 | data[0] = PPP_ALLSTATIONS; | ||
232 | data[1] = PPP_UI; | ||
233 | } | ||
234 | |||
235 | len = skb->len; | ||
236 | |||
237 | seq_recv = opt->seq_recv; | ||
238 | |||
239 | if (opt->ack_sent == seq_recv) | ||
240 | header_len -= sizeof(hdr->ack); | ||
241 | |||
242 | /* Push down and install GRE header */ | ||
243 | skb_push(skb, header_len); | ||
244 | hdr = (struct pptp_gre_header *)(skb->data); | ||
245 | |||
246 | hdr->flags = PPTP_GRE_FLAG_K; | ||
247 | hdr->ver = PPTP_GRE_VER; | ||
248 | hdr->protocol = htons(PPTP_GRE_PROTO); | ||
249 | hdr->call_id = htons(opt->dst_addr.call_id); | ||
250 | |||
251 | hdr->flags |= PPTP_GRE_FLAG_S; | ||
252 | hdr->seq = htonl(++opt->seq_sent); | ||
253 | if (opt->ack_sent != seq_recv) { | ||
254 | /* send ack with this message */ | ||
255 | hdr->ver |= PPTP_GRE_FLAG_A; | ||
256 | hdr->ack = htonl(seq_recv); | ||
257 | opt->ack_sent = seq_recv; | ||
258 | } | ||
259 | hdr->payload_len = htons(len); | ||
260 | |||
261 | /* Push down and install the IP header. */ | ||
262 | |||
263 | skb_reset_transport_header(skb); | ||
264 | skb_push(skb, sizeof(*iph)); | ||
265 | skb_reset_network_header(skb); | ||
266 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | ||
267 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); | ||
268 | |||
269 | iph = ip_hdr(skb); | ||
270 | iph->version = 4; | ||
271 | iph->ihl = sizeof(struct iphdr) >> 2; | ||
272 | if (ip_dont_fragment(sk, &rt->dst)) | ||
273 | iph->frag_off = htons(IP_DF); | ||
274 | else | ||
275 | iph->frag_off = 0; | ||
276 | iph->protocol = IPPROTO_GRE; | ||
277 | iph->tos = 0; | ||
278 | iph->daddr = rt->rt_dst; | ||
279 | iph->saddr = rt->rt_src; | ||
280 | iph->ttl = dst_metric(&rt->dst, RTAX_HOPLIMIT); | ||
281 | iph->tot_len = htons(skb->len); | ||
282 | |||
283 | skb_dst_drop(skb); | ||
284 | skb_dst_set(skb, &rt->dst); | ||
285 | |||
286 | nf_reset(skb); | ||
287 | |||
288 | skb->ip_summed = CHECKSUM_NONE; | ||
289 | ip_select_ident(iph, &rt->dst, NULL); | ||
290 | ip_send_check(iph); | ||
291 | |||
292 | ip_local_out(skb); | ||
293 | |||
294 | tx_error: | ||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb) | ||
299 | { | ||
300 | struct pppox_sock *po = pppox_sk(sk); | ||
301 | struct pptp_opt *opt = &po->proto.pptp; | ||
302 | int headersize, payload_len, seq; | ||
303 | __u8 *payload; | ||
304 | struct pptp_gre_header *header; | ||
305 | |||
306 | if (!(sk->sk_state & PPPOX_CONNECTED)) { | ||
307 | if (sock_queue_rcv_skb(sk, skb)) | ||
308 | goto drop; | ||
309 | return NET_RX_SUCCESS; | ||
310 | } | ||
311 | |||
312 | header = (struct pptp_gre_header *)(skb->data); | ||
313 | |||
314 | /* test if acknowledgement present */ | ||
315 | if (PPTP_GRE_IS_A(header->ver)) { | ||
316 | __u32 ack = (PPTP_GRE_IS_S(header->flags)) ? | ||
317 | header->ack : header->seq; /* ack in different place if S = 0 */ | ||
318 | |||
319 | ack = ntohl(ack); | ||
320 | |||
321 | if (ack > opt->ack_recv) | ||
322 | opt->ack_recv = ack; | ||
323 | /* also handle sequence number wrap-around */ | ||
324 | if (WRAPPED(ack, opt->ack_recv)) | ||
325 | opt->ack_recv = ack; | ||
326 | } | ||
327 | |||
328 | /* test if payload present */ | ||
329 | if (!PPTP_GRE_IS_S(header->flags)) | ||
330 | goto drop; | ||
331 | |||
332 | headersize = sizeof(*header); | ||
333 | payload_len = ntohs(header->payload_len); | ||
334 | seq = ntohl(header->seq); | ||
335 | |||
336 | /* no ack present? */ | ||
337 | if (!PPTP_GRE_IS_A(header->ver)) | ||
338 | headersize -= sizeof(header->ack); | ||
339 | /* check for incomplete packet (length smaller than expected) */ | ||
340 | if (skb->len - headersize < payload_len) | ||
341 | goto drop; | ||
342 | |||
343 | payload = skb->data + headersize; | ||
344 | /* check for expected sequence number */ | ||
345 | if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) { | ||
346 | if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) && | ||
347 | (PPP_PROTOCOL(payload) == PPP_LCP) && | ||
348 | ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP))) | ||
349 | goto allow_packet; | ||
350 | } else { | ||
351 | opt->seq_recv = seq; | ||
352 | allow_packet: | ||
353 | skb_pull(skb, headersize); | ||
354 | |||
355 | if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) { | ||
356 | /* chop off address/control */ | ||
357 | if (skb->len < 3) | ||
358 | goto drop; | ||
359 | skb_pull(skb, 2); | ||
360 | } | ||
361 | |||
362 | if ((*skb->data) & 1) { | ||
363 | /* protocol is compressed */ | ||
364 | skb_push(skb, 1)[0] = 0; | ||
365 | } | ||
366 | |||
367 | skb->ip_summed = CHECKSUM_NONE; | ||
368 | skb_set_network_header(skb, skb->head-skb->data); | ||
369 | ppp_input(&po->chan, skb); | ||
370 | |||
371 | return NET_RX_SUCCESS; | ||
372 | } | ||
373 | drop: | ||
374 | kfree_skb(skb); | ||
375 | return NET_RX_DROP; | ||
376 | } | ||
377 | |||
378 | static int pptp_rcv(struct sk_buff *skb) | ||
379 | { | ||
380 | struct pppox_sock *po; | ||
381 | struct pptp_gre_header *header; | ||
382 | struct iphdr *iph; | ||
383 | |||
384 | if (skb->pkt_type != PACKET_HOST) | ||
385 | goto drop; | ||
386 | |||
387 | if (!pskb_may_pull(skb, 12)) | ||
388 | goto drop; | ||
389 | |||
390 | iph = ip_hdr(skb); | ||
391 | |||
392 | header = (struct pptp_gre_header *)skb->data; | ||
393 | |||
394 | if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */ | ||
395 | PPTP_GRE_IS_C(header->flags) || /* flag C should be clear */ | ||
396 | PPTP_GRE_IS_R(header->flags) || /* flag R should be clear */ | ||
397 | !PPTP_GRE_IS_K(header->flags) || /* flag K should be set */ | ||
398 | (header->flags&0xF) != 0) /* routing and recursion ctrl = 0 */ | ||
399 | /* if invalid, discard this packet */ | ||
400 | goto drop; | ||
401 | |||
402 | po = lookup_chan(htons(header->call_id), iph->saddr); | ||
403 | if (po) { | ||
404 | skb_dst_drop(skb); | ||
405 | nf_reset(skb); | ||
406 | return sk_receive_skb(sk_pppox(po), skb, 0); | ||
407 | } | ||
408 | drop: | ||
409 | kfree_skb(skb); | ||
410 | return NET_RX_DROP; | ||
411 | } | ||
412 | |||
413 | static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, | ||
414 | int sockaddr_len) | ||
415 | { | ||
416 | struct sock *sk = sock->sk; | ||
417 | struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; | ||
418 | struct pppox_sock *po = pppox_sk(sk); | ||
419 | struct pptp_opt *opt = &po->proto.pptp; | ||
420 | int error = 0; | ||
421 | |||
422 | lock_sock(sk); | ||
423 | |||
424 | opt->src_addr = sp->sa_addr.pptp; | ||
425 | if (add_chan(po)) { | ||
426 | release_sock(sk); | ||
427 | error = -EBUSY; | ||
428 | } | ||
429 | |||
430 | release_sock(sk); | ||
431 | return error; | ||
432 | } | ||
433 | |||
434 | static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, | ||
435 | int sockaddr_len, int flags) | ||
436 | { | ||
437 | struct sock *sk = sock->sk; | ||
438 | struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; | ||
439 | struct pppox_sock *po = pppox_sk(sk); | ||
440 | struct pptp_opt *opt = &po->proto.pptp; | ||
441 | struct rtable *rt; | ||
442 | int error = 0; | ||
443 | |||
444 | if (sp->sa_protocol != PX_PROTO_PPTP) | ||
445 | return -EINVAL; | ||
446 | |||
447 | if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr)) | ||
448 | return -EALREADY; | ||
449 | |||
450 | lock_sock(sk); | ||
451 | /* Check for already bound sockets */ | ||
452 | if (sk->sk_state & PPPOX_CONNECTED) { | ||
453 | error = -EBUSY; | ||
454 | goto end; | ||
455 | } | ||
456 | |||
457 | /* Check for already disconnected sockets, on attempts to disconnect */ | ||
458 | if (sk->sk_state & PPPOX_DEAD) { | ||
459 | error = -EALREADY; | ||
460 | goto end; | ||
461 | } | ||
462 | |||
463 | if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) { | ||
464 | error = -EINVAL; | ||
465 | goto end; | ||
466 | } | ||
467 | |||
468 | po->chan.private = sk; | ||
469 | po->chan.ops = &pptp_chan_ops; | ||
470 | |||
471 | { | ||
472 | struct flowi fl = { | ||
473 | .nl_u = { | ||
474 | .ip4_u = { | ||
475 | .daddr = opt->dst_addr.sin_addr.s_addr, | ||
476 | .saddr = opt->src_addr.sin_addr.s_addr, | ||
477 | .tos = RT_CONN_FLAGS(sk) } }, | ||
478 | .proto = IPPROTO_GRE }; | ||
479 | security_sk_classify_flow(sk, &fl); | ||
480 | if (ip_route_output_key(&init_net, &rt, &fl)) { | ||
481 | error = -EHOSTUNREACH; | ||
482 | goto end; | ||
483 | } | ||
484 | sk_setup_caps(sk, &rt->dst); | ||
485 | } | ||
486 | po->chan.mtu = dst_mtu(&rt->dst); | ||
487 | if (!po->chan.mtu) | ||
488 | po->chan.mtu = PPP_MTU; | ||
489 | ip_rt_put(rt); | ||
490 | po->chan.mtu -= PPTP_HEADER_OVERHEAD; | ||
491 | |||
492 | po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); | ||
493 | error = ppp_register_channel(&po->chan); | ||
494 | if (error) { | ||
495 | pr_err("PPTP: failed to register PPP channel (%d)\n", error); | ||
496 | goto end; | ||
497 | } | ||
498 | |||
499 | opt->dst_addr = sp->sa_addr.pptp; | ||
500 | sk->sk_state = PPPOX_CONNECTED; | ||
501 | |||
502 | end: | ||
503 | release_sock(sk); | ||
504 | return error; | ||
505 | } | ||
506 | |||
507 | static int pptp_getname(struct socket *sock, struct sockaddr *uaddr, | ||
508 | int *usockaddr_len, int peer) | ||
509 | { | ||
510 | int len = sizeof(struct sockaddr_pppox); | ||
511 | struct sockaddr_pppox sp; | ||
512 | |||
513 | sp.sa_family = AF_PPPOX; | ||
514 | sp.sa_protocol = PX_PROTO_PPTP; | ||
515 | sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr; | ||
516 | |||
517 | memcpy(uaddr, &sp, len); | ||
518 | |||
519 | *usockaddr_len = len; | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int pptp_release(struct socket *sock) | ||
525 | { | ||
526 | struct sock *sk = sock->sk; | ||
527 | struct pppox_sock *po; | ||
528 | struct pptp_opt *opt; | ||
529 | int error = 0; | ||
530 | |||
531 | if (!sk) | ||
532 | return 0; | ||
533 | |||
534 | lock_sock(sk); | ||
535 | |||
536 | if (sock_flag(sk, SOCK_DEAD)) { | ||
537 | release_sock(sk); | ||
538 | return -EBADF; | ||
539 | } | ||
540 | |||
541 | po = pppox_sk(sk); | ||
542 | opt = &po->proto.pptp; | ||
543 | del_chan(po); | ||
544 | |||
545 | pppox_unbind_sock(sk); | ||
546 | sk->sk_state = PPPOX_DEAD; | ||
547 | |||
548 | sock_orphan(sk); | ||
549 | sock->sk = NULL; | ||
550 | |||
551 | release_sock(sk); | ||
552 | sock_put(sk); | ||
553 | |||
554 | return error; | ||
555 | } | ||
556 | |||
557 | static void pptp_sock_destruct(struct sock *sk) | ||
558 | { | ||
559 | if (!(sk->sk_state & PPPOX_DEAD)) { | ||
560 | del_chan(pppox_sk(sk)); | ||
561 | pppox_unbind_sock(sk); | ||
562 | } | ||
563 | skb_queue_purge(&sk->sk_receive_queue); | ||
564 | } | ||
565 | |||
566 | static int pptp_create(struct net *net, struct socket *sock) | ||
567 | { | ||
568 | int error = -ENOMEM; | ||
569 | struct sock *sk; | ||
570 | struct pppox_sock *po; | ||
571 | struct pptp_opt *opt; | ||
572 | |||
573 | sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto); | ||
574 | if (!sk) | ||
575 | goto out; | ||
576 | |||
577 | sock_init_data(sock, sk); | ||
578 | |||
579 | sock->state = SS_UNCONNECTED; | ||
580 | sock->ops = &pptp_ops; | ||
581 | |||
582 | sk->sk_backlog_rcv = pptp_rcv_core; | ||
583 | sk->sk_state = PPPOX_NONE; | ||
584 | sk->sk_type = SOCK_STREAM; | ||
585 | sk->sk_family = PF_PPPOX; | ||
586 | sk->sk_protocol = PX_PROTO_PPTP; | ||
587 | sk->sk_destruct = pptp_sock_destruct; | ||
588 | |||
589 | po = pppox_sk(sk); | ||
590 | opt = &po->proto.pptp; | ||
591 | |||
592 | opt->seq_sent = 0; opt->seq_recv = 0; | ||
593 | opt->ack_recv = 0; opt->ack_sent = 0; | ||
594 | |||
595 | error = 0; | ||
596 | out: | ||
597 | return error; | ||
598 | } | ||
599 | |||
600 | static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd, | ||
601 | unsigned long arg) | ||
602 | { | ||
603 | struct sock *sk = (struct sock *) chan->private; | ||
604 | struct pppox_sock *po = pppox_sk(sk); | ||
605 | struct pptp_opt *opt = &po->proto.pptp; | ||
606 | void __user *argp = (void __user *)arg; | ||
607 | int __user *p = argp; | ||
608 | int err, val; | ||
609 | |||
610 | err = -EFAULT; | ||
611 | switch (cmd) { | ||
612 | case PPPIOCGFLAGS: | ||
613 | val = opt->ppp_flags; | ||
614 | if (put_user(val, p)) | ||
615 | break; | ||
616 | err = 0; | ||
617 | break; | ||
618 | case PPPIOCSFLAGS: | ||
619 | if (get_user(val, p)) | ||
620 | break; | ||
621 | opt->ppp_flags = val & ~SC_RCV_BITS; | ||
622 | err = 0; | ||
623 | break; | ||
624 | default: | ||
625 | err = -ENOTTY; | ||
626 | } | ||
627 | |||
628 | return err; | ||
629 | } | ||
630 | |||
631 | static struct ppp_channel_ops pptp_chan_ops = { | ||
632 | .start_xmit = pptp_xmit, | ||
633 | .ioctl = pptp_ppp_ioctl, | ||
634 | }; | ||
635 | |||
636 | static struct proto pptp_sk_proto __read_mostly = { | ||
637 | .name = "PPTP", | ||
638 | .owner = THIS_MODULE, | ||
639 | .obj_size = sizeof(struct pppox_sock), | ||
640 | }; | ||
641 | |||
642 | static const struct proto_ops pptp_ops = { | ||
643 | .family = AF_PPPOX, | ||
644 | .owner = THIS_MODULE, | ||
645 | .release = pptp_release, | ||
646 | .bind = pptp_bind, | ||
647 | .connect = pptp_connect, | ||
648 | .socketpair = sock_no_socketpair, | ||
649 | .accept = sock_no_accept, | ||
650 | .getname = pptp_getname, | ||
651 | .poll = sock_no_poll, | ||
652 | .listen = sock_no_listen, | ||
653 | .shutdown = sock_no_shutdown, | ||
654 | .setsockopt = sock_no_setsockopt, | ||
655 | .getsockopt = sock_no_getsockopt, | ||
656 | .sendmsg = sock_no_sendmsg, | ||
657 | .recvmsg = sock_no_recvmsg, | ||
658 | .mmap = sock_no_mmap, | ||
659 | .ioctl = pppox_ioctl, | ||
660 | }; | ||
661 | |||
662 | static struct pppox_proto pppox_pptp_proto = { | ||
663 | .create = pptp_create, | ||
664 | .owner = THIS_MODULE, | ||
665 | }; | ||
666 | |||
667 | static struct gre_protocol gre_pptp_protocol = { | ||
668 | .handler = pptp_rcv, | ||
669 | }; | ||
670 | |||
671 | static int __init pptp_init_module(void) | ||
672 | { | ||
673 | int err = 0; | ||
674 | pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n"); | ||
675 | |||
676 | callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *), | ||
677 | GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); | ||
678 | if (!callid_sock) { | ||
679 | pr_err("PPTP: cann't allocate memory\n"); | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP); | ||
684 | if (err) { | ||
685 | pr_err("PPTP: can't add gre protocol\n"); | ||
686 | goto out_mem_free; | ||
687 | } | ||
688 | |||
689 | err = proto_register(&pptp_sk_proto, 0); | ||
690 | if (err) { | ||
691 | pr_err("PPTP: can't register sk_proto\n"); | ||
692 | goto out_gre_del_protocol; | ||
693 | } | ||
694 | |||
695 | err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto); | ||
696 | if (err) { | ||
697 | pr_err("PPTP: can't register pppox_proto\n"); | ||
698 | goto out_unregister_sk_proto; | ||
699 | } | ||
700 | |||
701 | return 0; | ||
702 | |||
703 | out_unregister_sk_proto: | ||
704 | proto_unregister(&pptp_sk_proto); | ||
705 | out_gre_del_protocol: | ||
706 | gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); | ||
707 | out_mem_free: | ||
708 | vfree(callid_sock); | ||
709 | |||
710 | return err; | ||
711 | } | ||
712 | |||
713 | static void __exit pptp_exit_module(void) | ||
714 | { | ||
715 | unregister_pppox_proto(PX_PROTO_PPTP); | ||
716 | proto_unregister(&pptp_sk_proto); | ||
717 | gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); | ||
718 | vfree(callid_sock); | ||
719 | } | ||
720 | |||
721 | module_init(pptp_init_module); | ||
722 | module_exit(pptp_exit_module); | ||
723 | |||
724 | MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol"); | ||
725 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); | ||
726 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index 1925e0c3f162..1525b2156b2a 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h | |||
@@ -40,25 +40,35 @@ | |||
40 | * PPPoE addressing definition | 40 | * PPPoE addressing definition |
41 | */ | 41 | */ |
42 | typedef __be16 sid_t; | 42 | typedef __be16 sid_t; |
43 | struct pppoe_addr{ | 43 | struct pppoe_addr { |
44 | sid_t sid; /* Session identifier */ | 44 | sid_t sid; /* Session identifier */ |
45 | unsigned char remote[ETH_ALEN]; /* Remote address */ | 45 | unsigned char remote[ETH_ALEN]; /* Remote address */ |
46 | char dev[IFNAMSIZ]; /* Local device to use */ | 46 | char dev[IFNAMSIZ]; /* Local device to use */ |
47 | }; | 47 | }; |
48 | 48 | ||
49 | /************************************************************************ | 49 | /************************************************************************ |
50 | * Protocols supported by AF_PPPOX | 50 | * PPTP addressing definition |
51 | */ | 51 | */ |
52 | struct pptp_addr { | ||
53 | u16 call_id; | ||
54 | struct in_addr sin_addr; | ||
55 | }; | ||
56 | |||
57 | /************************************************************************ | ||
58 | * Protocols supported by AF_PPPOX | ||
59 | */ | ||
52 | #define PX_PROTO_OE 0 /* Currently just PPPoE */ | 60 | #define PX_PROTO_OE 0 /* Currently just PPPoE */ |
53 | #define PX_PROTO_OL2TP 1 /* Now L2TP also */ | 61 | #define PX_PROTO_OL2TP 1 /* Now L2TP also */ |
54 | #define PX_MAX_PROTO 2 | 62 | #define PX_PROTO_PPTP 2 |
55 | 63 | #define PX_MAX_PROTO 3 | |
56 | struct sockaddr_pppox { | 64 | |
57 | sa_family_t sa_family; /* address family, AF_PPPOX */ | 65 | struct sockaddr_pppox { |
58 | unsigned int sa_protocol; /* protocol identifier */ | 66 | sa_family_t sa_family; /* address family, AF_PPPOX */ |
59 | union{ | 67 | unsigned int sa_protocol; /* protocol identifier */ |
60 | struct pppoe_addr pppoe; | 68 | union { |
61 | }sa_addr; | 69 | struct pppoe_addr pppoe; |
70 | struct pptp_addr pptp; | ||
71 | } sa_addr; | ||
62 | } __packed; | 72 | } __packed; |
63 | 73 | ||
64 | /* The use of the above union isn't viable because the size of this | 74 | /* The use of the above union isn't viable because the size of this |
@@ -101,7 +111,7 @@ struct pppoe_tag { | |||
101 | __be16 tag_type; | 111 | __be16 tag_type; |
102 | __be16 tag_len; | 112 | __be16 tag_len; |
103 | char tag_data[0]; | 113 | char tag_data[0]; |
104 | } __attribute ((packed)); | 114 | } __packed; |
105 | 115 | ||
106 | /* Tag identifiers */ | 116 | /* Tag identifiers */ |
107 | #define PTT_EOL __cpu_to_be16(0x0000) | 117 | #define PTT_EOL __cpu_to_be16(0x0000) |
@@ -150,15 +160,23 @@ struct pppoe_opt { | |||
150 | relayed to (PPPoE relaying) */ | 160 | relayed to (PPPoE relaying) */ |
151 | }; | 161 | }; |
152 | 162 | ||
163 | struct pptp_opt { | ||
164 | struct pptp_addr src_addr; | ||
165 | struct pptp_addr dst_addr; | ||
166 | u32 ack_sent, ack_recv; | ||
167 | u32 seq_sent, seq_recv; | ||
168 | int ppp_flags; | ||
169 | }; | ||
153 | #include <net/sock.h> | 170 | #include <net/sock.h> |
154 | 171 | ||
155 | struct pppox_sock { | 172 | struct pppox_sock { |
156 | /* struct sock must be the first member of pppox_sock */ | 173 | /* struct sock must be the first member of pppox_sock */ |
157 | struct sock sk; | 174 | struct sock sk; |
158 | struct ppp_channel chan; | 175 | struct ppp_channel chan; |
159 | struct pppox_sock *next; /* for hash table */ | 176 | struct pppox_sock *next; /* for hash table */ |
160 | union { | 177 | union { |
161 | struct pppoe_opt pppoe; | 178 | struct pppoe_opt pppoe; |
179 | struct pptp_opt pptp; | ||
162 | } proto; | 180 | } proto; |
163 | __be16 num; | 181 | __be16 num; |
164 | }; | 182 | }; |
diff --git a/include/net/gre.h b/include/net/gre.h new file mode 100644 index 000000000000..82665474bcb7 --- /dev/null +++ b/include/net/gre.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef __LINUX_GRE_H | ||
2 | #define __LINUX_GRE_H | ||
3 | |||
4 | #include <linux/skbuff.h> | ||
5 | |||
6 | #define GREPROTO_CISCO 0 | ||
7 | #define GREPROTO_PPTP 1 | ||
8 | #define GREPROTO_MAX 2 | ||
9 | |||
10 | struct gre_protocol { | ||
11 | int (*handler)(struct sk_buff *skb); | ||
12 | void (*err_handler)(struct sk_buff *skb, u32 info); | ||
13 | }; | ||
14 | |||
15 | int gre_add_protocol(const struct gre_protocol *proto, u8 version); | ||
16 | int gre_del_protocol(const struct gre_protocol *proto, u8 version); | ||
17 | |||
18 | #endif | ||
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 7c3a7d191249..7458bdae7e9f 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -215,8 +215,15 @@ config NET_IPIP | |||
215 | be inserted in and removed from the running kernel whenever you | 215 | be inserted in and removed from the running kernel whenever you |
216 | want). Most people won't need this and can say N. | 216 | want). Most people won't need this and can say N. |
217 | 217 | ||
218 | config NET_IPGRE_DEMUX | ||
219 | tristate "IP: GRE demultiplexer" | ||
220 | help | ||
221 | This is helper module to demultiplex GRE packets on GRE version field criteria. | ||
222 | Required by ip_gre and pptp modules. | ||
223 | |||
218 | config NET_IPGRE | 224 | config NET_IPGRE |
219 | tristate "IP: GRE tunnels over IP" | 225 | tristate "IP: GRE tunnels over IP" |
226 | depends on NET_IPGRE_DEMUX | ||
220 | help | 227 | help |
221 | Tunneling means encapsulating data of one protocol type within | 228 | Tunneling means encapsulating data of one protocol type within |
222 | another protocol and sending it over a channel that understands the | 229 | another protocol and sending it over a channel that understands the |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 80ff87ce43aa..4978d22f9a75 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_PROC_FS) += proc.o | |||
20 | obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o | 20 | obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o |
21 | obj-$(CONFIG_IP_MROUTE) += ipmr.o | 21 | obj-$(CONFIG_IP_MROUTE) += ipmr.o |
22 | obj-$(CONFIG_NET_IPIP) += ipip.o | 22 | obj-$(CONFIG_NET_IPIP) += ipip.o |
23 | obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o | ||
23 | obj-$(CONFIG_NET_IPGRE) += ip_gre.o | 24 | obj-$(CONFIG_NET_IPGRE) += ip_gre.o |
24 | obj-$(CONFIG_SYN_COOKIES) += syncookies.o | 25 | obj-$(CONFIG_SYN_COOKIES) += syncookies.o |
25 | obj-$(CONFIG_INET_AH) += ah4.o | 26 | obj-$(CONFIG_INET_AH) += ah4.o |
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c new file mode 100644 index 000000000000..b546736da2e1 --- /dev/null +++ b/net/ipv4/gre.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * GRE over IPv4 demultiplexer driver | ||
3 | * | ||
4 | * Authors: Dmitry Kozlov (xeb@mail.ru) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/kmod.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/in.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/version.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <net/protocol.h> | ||
22 | #include <net/gre.h> | ||
23 | |||
24 | |||
25 | const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly; | ||
26 | static DEFINE_SPINLOCK(gre_proto_lock); | ||
27 | |||
28 | int gre_add_protocol(const struct gre_protocol *proto, u8 version) | ||
29 | { | ||
30 | if (version >= GREPROTO_MAX) | ||
31 | goto err_out; | ||
32 | |||
33 | spin_lock(&gre_proto_lock); | ||
34 | if (gre_proto[version]) | ||
35 | goto err_out_unlock; | ||
36 | |||
37 | rcu_assign_pointer(gre_proto[version], proto); | ||
38 | spin_unlock(&gre_proto_lock); | ||
39 | return 0; | ||
40 | |||
41 | err_out_unlock: | ||
42 | spin_unlock(&gre_proto_lock); | ||
43 | err_out: | ||
44 | return -1; | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(gre_add_protocol); | ||
47 | |||
48 | int gre_del_protocol(const struct gre_protocol *proto, u8 version) | ||
49 | { | ||
50 | if (version >= GREPROTO_MAX) | ||
51 | goto err_out; | ||
52 | |||
53 | spin_lock(&gre_proto_lock); | ||
54 | if (gre_proto[version] != proto) | ||
55 | goto err_out_unlock; | ||
56 | rcu_assign_pointer(gre_proto[version], NULL); | ||
57 | spin_unlock(&gre_proto_lock); | ||
58 | synchronize_rcu(); | ||
59 | return 0; | ||
60 | |||
61 | err_out_unlock: | ||
62 | spin_unlock(&gre_proto_lock); | ||
63 | err_out: | ||
64 | return -1; | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(gre_del_protocol); | ||
67 | |||
68 | static int gre_rcv(struct sk_buff *skb) | ||
69 | { | ||
70 | const struct gre_protocol *proto; | ||
71 | u8 ver; | ||
72 | int ret; | ||
73 | |||
74 | if (!pskb_may_pull(skb, 12)) | ||
75 | goto drop; | ||
76 | |||
77 | ver = skb->data[1]&0x7f; | ||
78 | if (ver >= GREPROTO_MAX) | ||
79 | goto drop; | ||
80 | |||
81 | rcu_read_lock(); | ||
82 | proto = rcu_dereference(gre_proto[ver]); | ||
83 | if (!proto || !proto->handler) | ||
84 | goto drop_unlock; | ||
85 | ret = proto->handler(skb); | ||
86 | rcu_read_unlock(); | ||
87 | return ret; | ||
88 | |||
89 | drop_unlock: | ||
90 | rcu_read_unlock(); | ||
91 | drop: | ||
92 | kfree_skb(skb); | ||
93 | return NET_RX_DROP; | ||
94 | } | ||
95 | |||
96 | static void gre_err(struct sk_buff *skb, u32 info) | ||
97 | { | ||
98 | const struct gre_protocol *proto; | ||
99 | u8 ver; | ||
100 | |||
101 | if (!pskb_may_pull(skb, 12)) | ||
102 | goto drop; | ||
103 | |||
104 | ver = skb->data[1]&0x7f; | ||
105 | if (ver >= GREPROTO_MAX) | ||
106 | goto drop; | ||
107 | |||
108 | rcu_read_lock(); | ||
109 | proto = rcu_dereference(gre_proto[ver]); | ||
110 | if (!proto || !proto->err_handler) | ||
111 | goto drop_unlock; | ||
112 | proto->err_handler(skb, info); | ||
113 | rcu_read_unlock(); | ||
114 | return; | ||
115 | |||
116 | drop_unlock: | ||
117 | rcu_read_unlock(); | ||
118 | drop: | ||
119 | kfree_skb(skb); | ||
120 | } | ||
121 | |||
122 | static const struct net_protocol net_gre_protocol = { | ||
123 | .handler = gre_rcv, | ||
124 | .err_handler = gre_err, | ||
125 | .netns_ok = 1, | ||
126 | }; | ||
127 | |||
128 | static int __init gre_init(void) | ||
129 | { | ||
130 | pr_info("GRE over IPv4 demultiplexor driver"); | ||
131 | |||
132 | if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { | ||
133 | pr_err("gre: can't add protocol\n"); | ||
134 | return -EAGAIN; | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void __exit gre_exit(void) | ||
141 | { | ||
142 | inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); | ||
143 | } | ||
144 | |||
145 | module_init(gre_init); | ||
146 | module_exit(gre_exit); | ||
147 | |||
148 | MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver"); | ||
149 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); | ||
150 | MODULE_LICENSE("GPL"); | ||
151 | |||
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 945b20a5ad50..85176895495a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <net/net_namespace.h> | 44 | #include <net/net_namespace.h> |
45 | #include <net/netns/generic.h> | 45 | #include <net/netns/generic.h> |
46 | #include <net/rtnetlink.h> | 46 | #include <net/rtnetlink.h> |
47 | #include <net/gre.h> | ||
47 | 48 | ||
48 | #ifdef CONFIG_IPV6 | 49 | #ifdef CONFIG_IPV6 |
49 | #include <net/ipv6.h> | 50 | #include <net/ipv6.h> |
@@ -1278,10 +1279,9 @@ static void ipgre_fb_tunnel_init(struct net_device *dev) | |||
1278 | } | 1279 | } |
1279 | 1280 | ||
1280 | 1281 | ||
1281 | static const struct net_protocol ipgre_protocol = { | 1282 | static const struct gre_protocol ipgre_protocol = { |
1282 | .handler = ipgre_rcv, | 1283 | .handler = ipgre_rcv, |
1283 | .err_handler = ipgre_err, | 1284 | .err_handler = ipgre_err, |
1284 | .netns_ok = 1, | ||
1285 | }; | 1285 | }; |
1286 | 1286 | ||
1287 | static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) | 1287 | static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) |
@@ -1663,7 +1663,7 @@ static int __init ipgre_init(void) | |||
1663 | if (err < 0) | 1663 | if (err < 0) |
1664 | return err; | 1664 | return err; |
1665 | 1665 | ||
1666 | err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE); | 1666 | err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); |
1667 | if (err < 0) { | 1667 | if (err < 0) { |
1668 | printk(KERN_INFO "ipgre init: can't add protocol\n"); | 1668 | printk(KERN_INFO "ipgre init: can't add protocol\n"); |
1669 | goto add_proto_failed; | 1669 | goto add_proto_failed; |
@@ -1683,7 +1683,7 @@ out: | |||
1683 | tap_ops_failed: | 1683 | tap_ops_failed: |
1684 | rtnl_link_unregister(&ipgre_link_ops); | 1684 | rtnl_link_unregister(&ipgre_link_ops); |
1685 | rtnl_link_failed: | 1685 | rtnl_link_failed: |
1686 | inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); | 1686 | gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); |
1687 | add_proto_failed: | 1687 | add_proto_failed: |
1688 | unregister_pernet_device(&ipgre_net_ops); | 1688 | unregister_pernet_device(&ipgre_net_ops); |
1689 | goto out; | 1689 | goto out; |
@@ -1693,7 +1693,7 @@ static void __exit ipgre_fini(void) | |||
1693 | { | 1693 | { |
1694 | rtnl_link_unregister(&ipgre_tap_ops); | 1694 | rtnl_link_unregister(&ipgre_tap_ops); |
1695 | rtnl_link_unregister(&ipgre_link_ops); | 1695 | rtnl_link_unregister(&ipgre_link_ops); |
1696 | if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) | 1696 | if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) |
1697 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); | 1697 | printk(KERN_INFO "ipgre close: can't remove protocol\n"); |
1698 | unregister_pernet_device(&ipgre_net_ops); | 1698 | unregister_pernet_device(&ipgre_net_ops); |
1699 | } | 1699 | } |