aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pptp.c
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2010-08-22 02:05:39 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-22 02:05:39 -0400
commit00959ade36acadc00e757f87060bf6e4501d545f (patch)
tree9bfe790d4a8b63b0e6653388da73dfd777eea8ff /drivers/net/pptp.c
parent1003489e06c04d807c783a8958f2ccc9aed7a244 (diff)
PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)
PPP: introduce "pptp" module which implements point-to-point tunneling protocol using pppox framework NET: introduce the "gre" module for demultiplexing GRE packets on version criteria (required to pptp and ip_gre may coexists) NET: ip_gre: update to use the "gre" module This patch introduces then pptp support to the linux kernel which dramatically speeds up pptp vpn connections and decreases cpu usage in comparison of existing user-space implementation (poptop/pptpclient). There is accel-pptp project (https://sourceforge.net/projects/accel-pptp/) to utilize this module, it contains plugin for pppd to use pptp in client-mode and modified pptpd (poptop) to build high-performance pptp NAS. There was many changes from initial submitted patch, most important are: 1. using rcu instead of read-write locks 2. using static bitmap instead of dynamically allocated 3. using vmalloc for memory allocation instead of BITS_PER_LONG + __get_free_pages 4. fixed many coding style issues Thanks to Eric Dumazet. Signed-off-by: Dmitry Kozlov <xeb@mail.ru> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/pptp.c')
-rw-r--r--drivers/net/pptp.c726
1 files changed, 726 insertions, 0 deletions
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
50static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
51static struct pppox_sock **callid_sock;
52
53static DEFINE_SPINLOCK(chan_lock);
54
55static struct proto pptp_sk_proto __read_mostly;
56static struct ppp_channel_ops pptp_chan_ops;
57static 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))
84struct 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
94static 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
113static 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
135static 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
157out_err:
158 spin_unlock(&chan_lock);
159 return -1;
160}
161
162static 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
171static 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
294tx_error:
295 return 1;
296}
297
298static 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;
352allow_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 }
373drop:
374 kfree_skb(skb);
375 return NET_RX_DROP;
376}
377
378static 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 }
408drop:
409 kfree_skb(skb);
410 return NET_RX_DROP;
411}
412
413static 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
434static 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
507static 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
524static 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
557static 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
566static 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;
596out:
597 return error;
598}
599
600static 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
631static struct ppp_channel_ops pptp_chan_ops = {
632 .start_xmit = pptp_xmit,
633 .ioctl = pptp_ppp_ioctl,
634};
635
636static struct proto pptp_sk_proto __read_mostly = {
637 .name = "PPTP",
638 .owner = THIS_MODULE,
639 .obj_size = sizeof(struct pppox_sock),
640};
641
642static 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
662static struct pppox_proto pppox_pptp_proto = {
663 .create = pptp_create,
664 .owner = THIS_MODULE,
665};
666
667static struct gre_protocol gre_pptp_protocol = {
668 .handler = pptp_rcv,
669};
670
671static 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
703out_unregister_sk_proto:
704 proto_unregister(&pptp_sk_proto);
705out_gre_del_protocol:
706 gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
707out_mem_free:
708 vfree(callid_sock);
709
710 return err;
711}
712
713static 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
721module_init(pptp_init_module);
722module_exit(pptp_exit_module);
723
724MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
725MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
726MODULE_LICENSE("GPL");