Chia-chi Yeh | 60df157 | 2009-06-12 01:09:30 +0800 | [diff] [blame^] | 1 | /* drivers/net/pppopns.c |
| 2 | * |
| 3 | * Driver for PPP on PPTP Network Server / PPPoPNS Socket (RFC 2637) |
| 4 | * |
| 5 | * Copyright (C) 2009 Google, Inc. |
| 6 | * Author: Chia-chi Yeh <chiachi@android.com> |
| 7 | * |
| 8 | * This software is licensed under the terms of the GNU General Public |
| 9 | * License version 2, as published by the Free Software Foundation, and |
| 10 | * may be copied, distributed, and modified under those terms. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | */ |
| 17 | |
| 18 | /* This driver handles PPTP data packets between a RAW socket and a PPP channel. |
| 19 | * The socket is created in the kernel space and connected to the same address |
| 20 | * of the control socket. To keep things simple, packets are always sent with |
| 21 | * sequence but without acknowledgement. This driver should work on both IPv4 |
| 22 | * and IPv6. */ |
| 23 | |
| 24 | #include <linux/module.h> |
| 25 | #include <linux/skbuff.h> |
| 26 | #include <linux/file.h> |
| 27 | #include <linux/net.h> |
| 28 | #include <linux/ppp_defs.h> |
| 29 | #include <linux/if.h> |
| 30 | #include <linux/if_ppp.h> |
| 31 | #include <linux/if_pppox.h> |
| 32 | #include <linux/ppp_channel.h> |
| 33 | |
| 34 | #define GRE_HEADER_SIZE 8 |
| 35 | |
| 36 | #define PPTP_GRE_MASK htons(0x2001) |
| 37 | #define PPTP_GRE_SEQ_MASK htons(0x1000) |
| 38 | #define PPTP_GRE_ACK_MASK htons(0x0080) |
| 39 | #define PPTP_GRE_TYPE htons(0x880B) |
| 40 | |
| 41 | #define PPP_ADDR 0xFF |
| 42 | #define PPP_CTRL 0x03 |
| 43 | |
| 44 | struct header { |
| 45 | __u16 bits; |
| 46 | __u16 type; |
| 47 | __u16 length; |
| 48 | __u16 call; |
| 49 | __u32 sequence; |
| 50 | } __attribute__((packed)); |
| 51 | |
| 52 | static void pppopns_recv(struct sock *sk_raw, int length) |
| 53 | { |
| 54 | struct sock *sk; |
| 55 | struct pppopns_opt *opt; |
| 56 | struct sk_buff *skb; |
| 57 | struct header *hdr; |
| 58 | |
| 59 | /* Lock sk_raw to prevent sk from being closed. */ |
| 60 | lock_sock(sk_raw); |
| 61 | sk = (struct sock *)sk_raw->sk_user_data; |
| 62 | if (!sk) { |
| 63 | release_sock(sk_raw); |
| 64 | return; |
| 65 | } |
| 66 | sock_hold(sk); |
| 67 | release_sock(sk_raw); |
| 68 | opt = &pppox_sk(sk)->proto.pns; |
| 69 | |
| 70 | /* Process packets from the receive queue. */ |
| 71 | while ((skb = skb_dequeue(&sk_raw->sk_receive_queue))) { |
| 72 | skb_pull(skb, skb_transport_header(skb) - skb->data); |
| 73 | |
| 74 | /* Drop the packet if it is too short. */ |
| 75 | if (skb->len < GRE_HEADER_SIZE) |
| 76 | goto drop; |
| 77 | |
| 78 | /* Check the header. */ |
| 79 | hdr = (struct header *)skb->data; |
| 80 | if (hdr->type != PPTP_GRE_TYPE || hdr->call != opt->local || |
| 81 | (hdr->bits & PPTP_GRE_MASK) != PPTP_GRE_MASK) |
| 82 | goto drop; |
| 83 | |
| 84 | /* Skip all fields including optional ones. */ |
| 85 | if (!skb_pull(skb, GRE_HEADER_SIZE + |
| 86 | (hdr->bits & PPTP_GRE_SEQ_MASK ? 4 : 0) + |
| 87 | (hdr->bits & PPTP_GRE_ACK_MASK ? 4 : 0))) |
| 88 | goto drop; |
| 89 | |
| 90 | /* Check the length. */ |
| 91 | if (skb->len != ntohs(hdr->length)) |
| 92 | goto drop; |
| 93 | |
| 94 | /* Skip PPP address and control if they are present. */ |
| 95 | if (skb->len >= 2 && skb->data[0] == PPP_ADDR && |
| 96 | skb->data[1] == PPP_CTRL) |
| 97 | skb_pull(skb, 2); |
| 98 | |
| 99 | /* Fix PPP protocol if it is compressed. */ |
| 100 | if (skb->len >= 1 && skb->data[0] & 1) |
| 101 | skb_push(skb, 1)[0] = 0; |
| 102 | |
| 103 | /* Deliver the packet to PPP channel. We have to lock sk to |
| 104 | * prevent another thread from calling pppox_unbind_sock(). */ |
| 105 | skb_orphan(skb); |
| 106 | lock_sock(sk); |
| 107 | ppp_input(&pppox_sk(sk)->chan, skb); |
| 108 | release_sock(sk); |
| 109 | continue; |
| 110 | drop: |
| 111 | kfree_skb(skb); |
| 112 | } |
| 113 | sock_put(sk); |
| 114 | } |
| 115 | |
| 116 | static int pppopns_xmit(struct ppp_channel *chan, struct sk_buff *skb) |
| 117 | { |
| 118 | struct sock *sk_raw = (struct sock *)chan->private; |
| 119 | struct pppopns_opt *opt = &pppox_sk(sk_raw->sk_user_data)->proto.pns; |
| 120 | struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT}; |
| 121 | struct kvec iov; |
| 122 | struct header *hdr; |
| 123 | __u16 length; |
| 124 | |
| 125 | /* Install PPP address and control. */ |
| 126 | skb_push(skb, 2); |
| 127 | skb->data[0] = PPP_ADDR; |
| 128 | skb->data[1] = PPP_CTRL; |
| 129 | length = skb->len; |
| 130 | |
| 131 | /* Install PPTP GRE header. */ |
| 132 | hdr = (struct header *)skb_push(skb, 12); |
| 133 | hdr->bits = PPTP_GRE_MASK | PPTP_GRE_SEQ_MASK; |
| 134 | hdr->type = PPTP_GRE_TYPE; |
| 135 | hdr->length = htons(length); |
| 136 | hdr->call = opt->remote; |
| 137 | hdr->sequence = htonl(opt->sequence); |
| 138 | opt->sequence++; |
| 139 | |
| 140 | /* Now send the packet via RAW socket. */ |
| 141 | iov.iov_base = skb->data; |
| 142 | iov.iov_len = skb->len; |
| 143 | kernel_sendmsg(sk_raw->sk_socket, &msg, &iov, 1, skb->len); |
| 144 | kfree_skb(skb); |
| 145 | return 1; |
| 146 | } |
| 147 | |
| 148 | /******************************************************************************/ |
| 149 | |
| 150 | static struct ppp_channel_ops pppopns_channel_ops = { |
| 151 | .start_xmit = pppopns_xmit, |
| 152 | }; |
| 153 | |
| 154 | static int pppopns_connect(struct socket *sock, struct sockaddr *useraddr, |
| 155 | int addrlen, int flags) |
| 156 | { |
| 157 | struct sock *sk = sock->sk; |
| 158 | struct pppox_sock *po = pppox_sk(sk); |
| 159 | struct sockaddr_pppopns *addr = (struct sockaddr_pppopns *)useraddr; |
| 160 | struct sockaddr_storage ss; |
| 161 | struct socket *sock_tcp = NULL; |
| 162 | struct socket *sock_raw = NULL; |
| 163 | struct sock *sk_raw; |
| 164 | int error; |
| 165 | |
| 166 | if (addrlen != sizeof(struct sockaddr_pppopns)) |
| 167 | return -EINVAL; |
| 168 | |
| 169 | lock_sock(sk); |
| 170 | error = -EALREADY; |
| 171 | if (sk->sk_state != PPPOX_NONE) |
| 172 | goto out; |
| 173 | |
| 174 | sock_tcp = sockfd_lookup(addr->tcp_socket, &error); |
| 175 | if (!sock_tcp) |
| 176 | goto out; |
| 177 | error = -EPROTONOSUPPORT; |
| 178 | if (sock_tcp->sk->sk_protocol != IPPROTO_TCP) |
| 179 | goto out; |
| 180 | addrlen = sizeof(struct sockaddr_storage); |
| 181 | error = kernel_getpeername(sock_tcp, (struct sockaddr *)&ss, &addrlen); |
| 182 | if (error) |
| 183 | goto out; |
| 184 | |
| 185 | error = sock_create(ss.ss_family, SOCK_RAW, IPPROTO_GRE, &sock_raw); |
| 186 | if (error) |
| 187 | goto out; |
| 188 | error = kernel_connect(sock_raw, (struct sockaddr *)&ss, addrlen, 0); |
| 189 | if (error) |
| 190 | goto out; |
| 191 | sk_raw = sock_raw->sk; |
| 192 | |
| 193 | po->chan.hdrlen = 14; |
| 194 | po->chan.private = sk_raw; |
| 195 | po->chan.ops = &pppopns_channel_ops; |
| 196 | po->chan.mtu = PPP_MTU - 80; |
| 197 | po->proto.pns.local = addr->local; |
| 198 | po->proto.pns.remote = addr->remote; |
| 199 | |
| 200 | error = ppp_register_channel(&po->chan); |
| 201 | if (error) |
| 202 | goto out; |
| 203 | |
| 204 | sk->sk_state = PPPOX_CONNECTED; |
| 205 | sk_raw->sk_user_data = sk; |
| 206 | sk_raw->sk_data_ready = pppopns_recv; |
| 207 | |
| 208 | out: |
| 209 | if (sock_tcp) |
| 210 | sockfd_put(sock_tcp); |
| 211 | if (error && sock_raw) |
| 212 | sock_release(sock_raw); |
| 213 | release_sock(sk); |
| 214 | return error; |
| 215 | } |
| 216 | |
| 217 | static int pppopns_release(struct socket *sock) |
| 218 | { |
| 219 | struct sock *sk = sock->sk; |
| 220 | |
| 221 | if (!sk) |
| 222 | return 0; |
| 223 | |
| 224 | lock_sock(sk); |
| 225 | if (sock_flag(sk, SOCK_DEAD)) { |
| 226 | release_sock(sk); |
| 227 | return -EBADF; |
| 228 | } |
| 229 | |
| 230 | if (sk->sk_state != PPPOX_NONE) { |
| 231 | struct sock *sk_raw = (struct sock *)pppox_sk(sk)->chan.private; |
| 232 | lock_sock(sk_raw); |
| 233 | pppox_unbind_sock(sk); |
| 234 | sk_raw->sk_user_data = NULL; |
| 235 | release_sock(sk_raw); |
| 236 | sock_release(sk_raw->sk_socket); |
| 237 | } |
| 238 | |
| 239 | sock_orphan(sk); |
| 240 | sock->sk = NULL; |
| 241 | release_sock(sk); |
| 242 | sock_put(sk); |
| 243 | return 0; |
| 244 | } |
| 245 | |
| 246 | /******************************************************************************/ |
| 247 | |
| 248 | static struct proto pppopns_proto = { |
| 249 | .name = "PPPOPNS", |
| 250 | .owner = THIS_MODULE, |
| 251 | .obj_size = sizeof(struct pppox_sock), |
| 252 | }; |
| 253 | |
| 254 | static struct proto_ops pppopns_proto_ops = { |
| 255 | .family = PF_PPPOX, |
| 256 | .owner = THIS_MODULE, |
| 257 | .release = pppopns_release, |
| 258 | .bind = sock_no_bind, |
| 259 | .connect = pppopns_connect, |
| 260 | .socketpair = sock_no_socketpair, |
| 261 | .accept = sock_no_accept, |
| 262 | .getname = sock_no_getname, |
| 263 | .poll = sock_no_poll, |
| 264 | .ioctl = pppox_ioctl, |
| 265 | .listen = sock_no_listen, |
| 266 | .shutdown = sock_no_shutdown, |
| 267 | .setsockopt = sock_no_setsockopt, |
| 268 | .getsockopt = sock_no_getsockopt, |
| 269 | .sendmsg = sock_no_sendmsg, |
| 270 | .recvmsg = sock_no_recvmsg, |
| 271 | .mmap = sock_no_mmap, |
| 272 | }; |
| 273 | |
| 274 | static int pppopns_create(struct net *net, struct socket *sock) |
| 275 | { |
| 276 | struct sock *sk; |
| 277 | |
| 278 | sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppopns_proto); |
| 279 | if (!sk) |
| 280 | return -ENOMEM; |
| 281 | |
| 282 | sock_init_data(sock, sk); |
| 283 | sock->state = SS_UNCONNECTED; |
| 284 | sock->ops = &pppopns_proto_ops; |
| 285 | sk->sk_protocol = PX_PROTO_OPNS; |
| 286 | sk->sk_state = PPPOX_NONE; |
| 287 | return 0; |
| 288 | } |
| 289 | |
| 290 | /******************************************************************************/ |
| 291 | |
| 292 | static struct pppox_proto pppopns_pppox_proto = { |
| 293 | .create = pppopns_create, |
| 294 | .owner = THIS_MODULE, |
| 295 | }; |
| 296 | |
| 297 | static int __init pppopns_init(void) |
| 298 | { |
| 299 | int error; |
| 300 | |
| 301 | error = proto_register(&pppopns_proto, 0); |
| 302 | if (error) |
| 303 | return error; |
| 304 | |
| 305 | error = register_pppox_proto(PX_PROTO_OPNS, &pppopns_pppox_proto); |
| 306 | if (error) |
| 307 | proto_unregister(&pppopns_proto); |
| 308 | return error; |
| 309 | } |
| 310 | |
| 311 | static void __exit pppopns_exit(void) |
| 312 | { |
| 313 | unregister_pppox_proto(PX_PROTO_OPNS); |
| 314 | proto_unregister(&pppopns_proto); |
| 315 | } |
| 316 | |
| 317 | module_init(pppopns_init); |
| 318 | module_exit(pppopns_exit); |
| 319 | |
| 320 | MODULE_DESCRIPTION("PPP on PPTP Network Server (PPPoPNS)"); |
| 321 | MODULE_AUTHOR("Chia-chi Yeh <chiachi@android.com>"); |
| 322 | MODULE_LICENSE("GPL"); |