diff options
Diffstat (limited to 'drivers/net/wan/hdlc_ppp.c')
-rw-r--r-- | drivers/net/wan/hdlc_ppp.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c new file mode 100644 index 000000000000..7cd6195a2e46 --- /dev/null +++ b/drivers/net/wan/hdlc_ppp.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * Generic HDLC support routines for Linux | ||
3 | * Point-to-point protocol support | ||
4 | * | ||
5 | * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of version 2 of the GNU General Public License | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/poll.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/if_arp.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/skbuff.h> | ||
20 | #include <linux/pkt_sched.h> | ||
21 | #include <linux/inetdevice.h> | ||
22 | #include <linux/lapb.h> | ||
23 | #include <linux/rtnetlink.h> | ||
24 | #include <linux/hdlc.h> | ||
25 | |||
26 | |||
27 | static int ppp_open(struct net_device *dev) | ||
28 | { | ||
29 | hdlc_device *hdlc = dev_to_hdlc(dev); | ||
30 | void *old_ioctl; | ||
31 | int result; | ||
32 | |||
33 | dev->priv = &hdlc->state.ppp.syncppp_ptr; | ||
34 | hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; | ||
35 | hdlc->state.ppp.pppdev.dev = dev; | ||
36 | |||
37 | old_ioctl = dev->do_ioctl; | ||
38 | hdlc->state.ppp.old_change_mtu = dev->change_mtu; | ||
39 | sppp_attach(&hdlc->state.ppp.pppdev); | ||
40 | /* sppp_attach nukes them. We don't need syncppp's ioctl */ | ||
41 | dev->do_ioctl = old_ioctl; | ||
42 | hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; | ||
43 | dev->type = ARPHRD_PPP; | ||
44 | result = sppp_open(dev); | ||
45 | if (result) { | ||
46 | sppp_detach(dev); | ||
47 | return result; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | |||
54 | |||
55 | static void ppp_close(struct net_device *dev) | ||
56 | { | ||
57 | hdlc_device *hdlc = dev_to_hdlc(dev); | ||
58 | |||
59 | sppp_close(dev); | ||
60 | sppp_detach(dev); | ||
61 | dev->rebuild_header = NULL; | ||
62 | dev->change_mtu = hdlc->state.ppp.old_change_mtu; | ||
63 | dev->mtu = HDLC_MAX_MTU; | ||
64 | dev->hard_header_len = 16; | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | static unsigned short ppp_type_trans(struct sk_buff *skb, | ||
70 | struct net_device *dev) | ||
71 | { | ||
72 | return __constant_htons(ETH_P_WAN_PPP); | ||
73 | } | ||
74 | |||
75 | |||
76 | |||
77 | int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) | ||
78 | { | ||
79 | hdlc_device *hdlc = dev_to_hdlc(dev); | ||
80 | int result; | ||
81 | |||
82 | switch (ifr->ifr_settings.type) { | ||
83 | case IF_GET_PROTO: | ||
84 | ifr->ifr_settings.type = IF_PROTO_PPP; | ||
85 | return 0; /* return protocol only, no settable parameters */ | ||
86 | |||
87 | case IF_PROTO_PPP: | ||
88 | if(!capable(CAP_NET_ADMIN)) | ||
89 | return -EPERM; | ||
90 | |||
91 | if(dev->flags & IFF_UP) | ||
92 | return -EBUSY; | ||
93 | |||
94 | /* no settable parameters */ | ||
95 | |||
96 | result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); | ||
97 | if (result) | ||
98 | return result; | ||
99 | |||
100 | hdlc_proto_detach(hdlc); | ||
101 | memset(&hdlc->proto, 0, sizeof(hdlc->proto)); | ||
102 | |||
103 | hdlc->proto.open = ppp_open; | ||
104 | hdlc->proto.close = ppp_close; | ||
105 | hdlc->proto.type_trans = ppp_type_trans; | ||
106 | hdlc->proto.id = IF_PROTO_PPP; | ||
107 | dev->hard_start_xmit = hdlc->xmit; | ||
108 | dev->hard_header = NULL; | ||
109 | dev->type = ARPHRD_PPP; | ||
110 | dev->addr_len = 0; | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | return -EINVAL; | ||
115 | } | ||