| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 1 | /* | 
|  | 2 | * L2TPv3 IP encapsulation support for IPv6 | 
|  | 3 | * | 
|  | 4 | * Copyright (c) 2012 Katalix Systems Ltd | 
|  | 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 |  | 
| Joe Perches | a4ca44f | 2012-05-16 09:55:56 +0000 | [diff] [blame] | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 
|  | 13 |  | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 14 | #include <linux/icmp.h> | 
|  | 15 | #include <linux/module.h> | 
|  | 16 | #include <linux/skbuff.h> | 
|  | 17 | #include <linux/random.h> | 
|  | 18 | #include <linux/socket.h> | 
|  | 19 | #include <linux/l2tp.h> | 
|  | 20 | #include <linux/in.h> | 
|  | 21 | #include <linux/in6.h> | 
|  | 22 | #include <net/sock.h> | 
|  | 23 | #include <net/ip.h> | 
|  | 24 | #include <net/icmp.h> | 
|  | 25 | #include <net/udp.h> | 
|  | 26 | #include <net/inet_common.h> | 
|  | 27 | #include <net/inet_hashtables.h> | 
|  | 28 | #include <net/tcp_states.h> | 
|  | 29 | #include <net/protocol.h> | 
|  | 30 | #include <net/xfrm.h> | 
|  | 31 |  | 
|  | 32 | #include <net/transp_v6.h> | 
|  | 33 | #include <net/addrconf.h> | 
|  | 34 | #include <net/ip6_route.h> | 
|  | 35 |  | 
|  | 36 | #include "l2tp_core.h" | 
|  | 37 |  | 
|  | 38 | struct l2tp_ip6_sock { | 
|  | 39 | /* inet_sock has to be the first member of l2tp_ip6_sock */ | 
|  | 40 | struct inet_sock	inet; | 
|  | 41 |  | 
|  | 42 | u32			conn_id; | 
|  | 43 | u32			peer_conn_id; | 
|  | 44 |  | 
|  | 45 | /* ipv6_pinfo has to be the last member of l2tp_ip6_sock, see | 
|  | 46 | inet6_sk_generic */ | 
|  | 47 | struct ipv6_pinfo	inet6; | 
|  | 48 | }; | 
|  | 49 |  | 
|  | 50 | static DEFINE_RWLOCK(l2tp_ip6_lock); | 
|  | 51 | static struct hlist_head l2tp_ip6_table; | 
|  | 52 | static struct hlist_head l2tp_ip6_bind_table; | 
|  | 53 |  | 
|  | 54 | static inline struct l2tp_ip6_sock *l2tp_ip6_sk(const struct sock *sk) | 
|  | 55 | { | 
|  | 56 | return (struct l2tp_ip6_sock *)sk; | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | static struct sock *__l2tp_ip6_bind_lookup(struct net *net, | 
|  | 60 | struct in6_addr *laddr, | 
|  | 61 | int dif, u32 tunnel_id) | 
|  | 62 | { | 
|  | 63 | struct hlist_node *node; | 
|  | 64 | struct sock *sk; | 
|  | 65 |  | 
|  | 66 | sk_for_each_bound(sk, node, &l2tp_ip6_bind_table) { | 
|  | 67 | struct in6_addr *addr = inet6_rcv_saddr(sk); | 
|  | 68 | struct l2tp_ip6_sock *l2tp = l2tp_ip6_sk(sk); | 
|  | 69 |  | 
|  | 70 | if (l2tp == NULL) | 
|  | 71 | continue; | 
|  | 72 |  | 
|  | 73 | if ((l2tp->conn_id == tunnel_id) && | 
|  | 74 | net_eq(sock_net(sk), net) && | 
|  | 75 | !(addr && ipv6_addr_equal(addr, laddr)) && | 
|  | 76 | !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) | 
|  | 77 | goto found; | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | sk = NULL; | 
|  | 81 | found: | 
|  | 82 | return sk; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | static inline struct sock *l2tp_ip6_bind_lookup(struct net *net, | 
|  | 86 | struct in6_addr *laddr, | 
|  | 87 | int dif, u32 tunnel_id) | 
|  | 88 | { | 
|  | 89 | struct sock *sk = __l2tp_ip6_bind_lookup(net, laddr, dif, tunnel_id); | 
|  | 90 | if (sk) | 
|  | 91 | sock_hold(sk); | 
|  | 92 |  | 
|  | 93 | return sk; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | /* When processing receive frames, there are two cases to | 
|  | 97 | * consider. Data frames consist of a non-zero session-id and an | 
|  | 98 | * optional cookie. Control frames consist of a regular L2TP header | 
|  | 99 | * preceded by 32-bits of zeros. | 
|  | 100 | * | 
|  | 101 | * L2TPv3 Session Header Over IP | 
|  | 102 | * | 
|  | 103 | *  0                   1                   2                   3 | 
|  | 104 | *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 
|  | 105 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 106 | * |                           Session ID                          | | 
|  | 107 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 108 | * |               Cookie (optional, maximum 64 bits)... | 
|  | 109 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 110 | *                                                                 | | 
|  | 111 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 112 | * | 
|  | 113 | * L2TPv3 Control Message Header Over IP | 
|  | 114 | * | 
|  | 115 | *  0                   1                   2                   3 | 
|  | 116 | *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 
|  | 117 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 118 | * |                      (32 bits of zeros)                       | | 
|  | 119 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 120 | * |T|L|x|x|S|x|x|x|x|x|x|x|  Ver  |             Length            | | 
|  | 121 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 122 | * |                     Control Connection ID                     | | 
|  | 123 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 124 | * |               Ns              |               Nr              | | 
|  | 125 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
|  | 126 | * | 
|  | 127 | * All control frames are passed to userspace. | 
|  | 128 | */ | 
|  | 129 | static int l2tp_ip6_recv(struct sk_buff *skb) | 
|  | 130 | { | 
|  | 131 | struct sock *sk; | 
|  | 132 | u32 session_id; | 
|  | 133 | u32 tunnel_id; | 
|  | 134 | unsigned char *ptr, *optr; | 
|  | 135 | struct l2tp_session *session; | 
|  | 136 | struct l2tp_tunnel *tunnel = NULL; | 
|  | 137 | int length; | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 138 |  | 
|  | 139 | /* Point to L2TP header */ | 
|  | 140 | optr = ptr = skb->data; | 
|  | 141 |  | 
|  | 142 | if (!pskb_may_pull(skb, 4)) | 
|  | 143 | goto discard; | 
|  | 144 |  | 
|  | 145 | session_id = ntohl(*((__be32 *) ptr)); | 
|  | 146 | ptr += 4; | 
|  | 147 |  | 
|  | 148 | /* RFC3931: L2TP/IP packets have the first 4 bytes containing | 
|  | 149 | * the session_id. If it is 0, the packet is a L2TP control | 
|  | 150 | * frame and the session_id value can be discarded. | 
|  | 151 | */ | 
|  | 152 | if (session_id == 0) { | 
|  | 153 | __skb_pull(skb, 4); | 
|  | 154 | goto pass_up; | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | /* Ok, this is a data packet. Lookup the session. */ | 
|  | 158 | session = l2tp_session_find(&init_net, NULL, session_id); | 
|  | 159 | if (session == NULL) | 
|  | 160 | goto discard; | 
|  | 161 |  | 
|  | 162 | tunnel = session->tunnel; | 
|  | 163 | if (tunnel == NULL) | 
|  | 164 | goto discard; | 
|  | 165 |  | 
|  | 166 | /* Trace packet contents, if enabled */ | 
|  | 167 | if (tunnel->debug & L2TP_MSG_DATA) { | 
|  | 168 | length = min(32u, skb->len); | 
|  | 169 | if (!pskb_may_pull(skb, length)) | 
|  | 170 | goto discard; | 
|  | 171 |  | 
| Joe Perches | a4ca44f | 2012-05-16 09:55:56 +0000 | [diff] [blame] | 172 | pr_debug("%s: ip recv\n", tunnel->name); | 
|  | 173 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 174 | } | 
|  | 175 |  | 
|  | 176 | l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, | 
|  | 177 | tunnel->recv_payload_hook); | 
|  | 178 | return 0; | 
|  | 179 |  | 
|  | 180 | pass_up: | 
|  | 181 | /* Get the tunnel_id from the L2TP header */ | 
|  | 182 | if (!pskb_may_pull(skb, 12)) | 
|  | 183 | goto discard; | 
|  | 184 |  | 
|  | 185 | if ((skb->data[0] & 0xc0) != 0xc0) | 
|  | 186 | goto discard; | 
|  | 187 |  | 
|  | 188 | tunnel_id = ntohl(*(__be32 *) &skb->data[4]); | 
|  | 189 | tunnel = l2tp_tunnel_find(&init_net, tunnel_id); | 
|  | 190 | if (tunnel != NULL) | 
|  | 191 | sk = tunnel->sock; | 
|  | 192 | else { | 
|  | 193 | struct ipv6hdr *iph = ipv6_hdr(skb); | 
|  | 194 |  | 
|  | 195 | read_lock_bh(&l2tp_ip6_lock); | 
|  | 196 | sk = __l2tp_ip6_bind_lookup(&init_net, &iph->daddr, | 
|  | 197 | 0, tunnel_id); | 
|  | 198 | read_unlock_bh(&l2tp_ip6_lock); | 
|  | 199 | } | 
|  | 200 |  | 
|  | 201 | if (sk == NULL) | 
|  | 202 | goto discard; | 
|  | 203 |  | 
|  | 204 | sock_hold(sk); | 
|  | 205 |  | 
|  | 206 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 
|  | 207 | goto discard_put; | 
|  | 208 |  | 
|  | 209 | nf_reset(skb); | 
|  | 210 |  | 
|  | 211 | return sk_receive_skb(sk, skb, 1); | 
|  | 212 |  | 
|  | 213 | discard_put: | 
|  | 214 | sock_put(sk); | 
|  | 215 |  | 
|  | 216 | discard: | 
|  | 217 | kfree_skb(skb); | 
|  | 218 | return 0; | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | static int l2tp_ip6_open(struct sock *sk) | 
|  | 222 | { | 
|  | 223 | /* Prevent autobind. We don't have ports. */ | 
|  | 224 | inet_sk(sk)->inet_num = IPPROTO_L2TP; | 
|  | 225 |  | 
|  | 226 | write_lock_bh(&l2tp_ip6_lock); | 
|  | 227 | sk_add_node(sk, &l2tp_ip6_table); | 
|  | 228 | write_unlock_bh(&l2tp_ip6_lock); | 
|  | 229 |  | 
|  | 230 | return 0; | 
|  | 231 | } | 
|  | 232 |  | 
|  | 233 | static void l2tp_ip6_close(struct sock *sk, long timeout) | 
|  | 234 | { | 
|  | 235 | write_lock_bh(&l2tp_ip6_lock); | 
|  | 236 | hlist_del_init(&sk->sk_bind_node); | 
|  | 237 | sk_del_node_init(sk); | 
|  | 238 | write_unlock_bh(&l2tp_ip6_lock); | 
|  | 239 |  | 
|  | 240 | sk_common_release(sk); | 
|  | 241 | } | 
|  | 242 |  | 
|  | 243 | static void l2tp_ip6_destroy_sock(struct sock *sk) | 
|  | 244 | { | 
|  | 245 | lock_sock(sk); | 
|  | 246 | ip6_flush_pending_frames(sk); | 
|  | 247 | release_sock(sk); | 
|  | 248 |  | 
|  | 249 | inet6_destroy_sock(sk); | 
|  | 250 | } | 
|  | 251 |  | 
|  | 252 | static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 
|  | 253 | { | 
|  | 254 | struct inet_sock *inet = inet_sk(sk); | 
|  | 255 | struct ipv6_pinfo *np = inet6_sk(sk); | 
|  | 256 | struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr; | 
|  | 257 | __be32 v4addr = 0; | 
|  | 258 | int addr_type; | 
|  | 259 | int err; | 
|  | 260 |  | 
| James Chapman | c51ce49 | 2012-05-29 03:30:42 +0000 | [diff] [blame] | 261 | if (!sock_flag(sk, SOCK_ZAPPED)) | 
|  | 262 | return -EINVAL; | 
|  | 263 | if (addr->l2tp_family != AF_INET6) | 
|  | 264 | return -EINVAL; | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 265 | if (addr_len < sizeof(*addr)) | 
|  | 266 | return -EINVAL; | 
|  | 267 |  | 
|  | 268 | addr_type = ipv6_addr_type(&addr->l2tp_addr); | 
|  | 269 |  | 
|  | 270 | /* l2tp_ip6 sockets are IPv6 only */ | 
|  | 271 | if (addr_type == IPV6_ADDR_MAPPED) | 
|  | 272 | return -EADDRNOTAVAIL; | 
|  | 273 |  | 
|  | 274 | /* L2TP is point-point, not multicast */ | 
|  | 275 | if (addr_type & IPV6_ADDR_MULTICAST) | 
|  | 276 | return -EADDRNOTAVAIL; | 
|  | 277 |  | 
|  | 278 | err = -EADDRINUSE; | 
|  | 279 | read_lock_bh(&l2tp_ip6_lock); | 
|  | 280 | if (__l2tp_ip6_bind_lookup(&init_net, &addr->l2tp_addr, | 
|  | 281 | sk->sk_bound_dev_if, addr->l2tp_conn_id)) | 
|  | 282 | goto out_in_use; | 
|  | 283 | read_unlock_bh(&l2tp_ip6_lock); | 
|  | 284 |  | 
|  | 285 | lock_sock(sk); | 
|  | 286 |  | 
|  | 287 | err = -EINVAL; | 
|  | 288 | if (sk->sk_state != TCP_CLOSE) | 
|  | 289 | goto out_unlock; | 
|  | 290 |  | 
|  | 291 | /* Check if the address belongs to the host. */ | 
|  | 292 | rcu_read_lock(); | 
|  | 293 | if (addr_type != IPV6_ADDR_ANY) { | 
|  | 294 | struct net_device *dev = NULL; | 
|  | 295 |  | 
|  | 296 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 
|  | 297 | if (addr_len >= sizeof(struct sockaddr_in6) && | 
|  | 298 | addr->l2tp_scope_id) { | 
|  | 299 | /* Override any existing binding, if another | 
|  | 300 | * one is supplied by user. | 
|  | 301 | */ | 
|  | 302 | sk->sk_bound_dev_if = addr->l2tp_scope_id; | 
|  | 303 | } | 
|  | 304 |  | 
|  | 305 | /* Binding to link-local address requires an | 
|  | 306 | interface */ | 
|  | 307 | if (!sk->sk_bound_dev_if) | 
|  | 308 | goto out_unlock_rcu; | 
|  | 309 |  | 
|  | 310 | err = -ENODEV; | 
|  | 311 | dev = dev_get_by_index_rcu(sock_net(sk), | 
|  | 312 | sk->sk_bound_dev_if); | 
|  | 313 | if (!dev) | 
|  | 314 | goto out_unlock_rcu; | 
|  | 315 | } | 
|  | 316 |  | 
|  | 317 | /* ipv4 addr of the socket is invalid.  Only the | 
|  | 318 | * unspecified and mapped address have a v4 equivalent. | 
|  | 319 | */ | 
|  | 320 | v4addr = LOOPBACK4_IPV6; | 
|  | 321 | err = -EADDRNOTAVAIL; | 
|  | 322 | if (!ipv6_chk_addr(sock_net(sk), &addr->l2tp_addr, dev, 0)) | 
|  | 323 | goto out_unlock_rcu; | 
|  | 324 | } | 
|  | 325 | rcu_read_unlock(); | 
|  | 326 |  | 
|  | 327 | inet->inet_rcv_saddr = inet->inet_saddr = v4addr; | 
|  | 328 | np->rcv_saddr = addr->l2tp_addr; | 
|  | 329 | np->saddr = addr->l2tp_addr; | 
|  | 330 |  | 
|  | 331 | l2tp_ip6_sk(sk)->conn_id = addr->l2tp_conn_id; | 
|  | 332 |  | 
|  | 333 | write_lock_bh(&l2tp_ip6_lock); | 
|  | 334 | sk_add_bind_node(sk, &l2tp_ip6_bind_table); | 
|  | 335 | sk_del_node_init(sk); | 
|  | 336 | write_unlock_bh(&l2tp_ip6_lock); | 
|  | 337 |  | 
| James Chapman | c51ce49 | 2012-05-29 03:30:42 +0000 | [diff] [blame] | 338 | sock_reset_flag(sk, SOCK_ZAPPED); | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 339 | release_sock(sk); | 
|  | 340 | return 0; | 
|  | 341 |  | 
|  | 342 | out_unlock_rcu: | 
|  | 343 | rcu_read_unlock(); | 
|  | 344 | out_unlock: | 
|  | 345 | release_sock(sk); | 
|  | 346 | return err; | 
|  | 347 |  | 
|  | 348 | out_in_use: | 
|  | 349 | read_unlock_bh(&l2tp_ip6_lock); | 
|  | 350 | return err; | 
|  | 351 | } | 
|  | 352 |  | 
|  | 353 | static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr, | 
|  | 354 | int addr_len) | 
|  | 355 | { | 
|  | 356 | struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *) uaddr; | 
|  | 357 | struct sockaddr_in6	*usin = (struct sockaddr_in6 *) uaddr; | 
|  | 358 | struct in6_addr	*daddr; | 
|  | 359 | int	addr_type; | 
|  | 360 | int rc; | 
|  | 361 |  | 
| James Chapman | c51ce49 | 2012-05-29 03:30:42 +0000 | [diff] [blame] | 362 | if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */ | 
|  | 363 | return -EINVAL; | 
|  | 364 |  | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 365 | if (addr_len < sizeof(*lsa)) | 
|  | 366 | return -EINVAL; | 
|  | 367 |  | 
|  | 368 | addr_type = ipv6_addr_type(&usin->sin6_addr); | 
|  | 369 | if (addr_type & IPV6_ADDR_MULTICAST) | 
|  | 370 | return -EINVAL; | 
|  | 371 |  | 
|  | 372 | if (addr_type & IPV6_ADDR_MAPPED) { | 
|  | 373 | daddr = &usin->sin6_addr; | 
|  | 374 | if (ipv4_is_multicast(daddr->s6_addr32[3])) | 
|  | 375 | return -EINVAL; | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | rc = ip6_datagram_connect(sk, uaddr, addr_len); | 
|  | 379 |  | 
|  | 380 | lock_sock(sk); | 
|  | 381 |  | 
|  | 382 | l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; | 
|  | 383 |  | 
|  | 384 | write_lock_bh(&l2tp_ip6_lock); | 
|  | 385 | hlist_del_init(&sk->sk_bind_node); | 
|  | 386 | sk_add_bind_node(sk, &l2tp_ip6_bind_table); | 
|  | 387 | write_unlock_bh(&l2tp_ip6_lock); | 
|  | 388 |  | 
|  | 389 | release_sock(sk); | 
|  | 390 |  | 
|  | 391 | return rc; | 
|  | 392 | } | 
|  | 393 |  | 
| James Chapman | c51ce49 | 2012-05-29 03:30:42 +0000 | [diff] [blame] | 394 | static int l2tp_ip6_disconnect(struct sock *sk, int flags) | 
|  | 395 | { | 
|  | 396 | if (sock_flag(sk, SOCK_ZAPPED)) | 
|  | 397 | return 0; | 
|  | 398 |  | 
|  | 399 | return udp_disconnect(sk, flags); | 
|  | 400 | } | 
|  | 401 |  | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 402 | static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr, | 
|  | 403 | int *uaddr_len, int peer) | 
|  | 404 | { | 
|  | 405 | struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)uaddr; | 
|  | 406 | struct sock *sk = sock->sk; | 
|  | 407 | struct ipv6_pinfo *np = inet6_sk(sk); | 
|  | 408 | struct l2tp_ip6_sock *lsk = l2tp_ip6_sk(sk); | 
|  | 409 |  | 
|  | 410 | lsa->l2tp_family = AF_INET6; | 
|  | 411 | lsa->l2tp_flowinfo = 0; | 
|  | 412 | lsa->l2tp_scope_id = 0; | 
|  | 413 | if (peer) { | 
|  | 414 | if (!lsk->peer_conn_id) | 
|  | 415 | return -ENOTCONN; | 
|  | 416 | lsa->l2tp_conn_id = lsk->peer_conn_id; | 
|  | 417 | lsa->l2tp_addr = np->daddr; | 
|  | 418 | if (np->sndflow) | 
|  | 419 | lsa->l2tp_flowinfo = np->flow_label; | 
|  | 420 | } else { | 
|  | 421 | if (ipv6_addr_any(&np->rcv_saddr)) | 
|  | 422 | lsa->l2tp_addr = np->saddr; | 
|  | 423 | else | 
|  | 424 | lsa->l2tp_addr = np->rcv_saddr; | 
|  | 425 |  | 
|  | 426 | lsa->l2tp_conn_id = lsk->conn_id; | 
|  | 427 | } | 
|  | 428 | if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) | 
|  | 429 | lsa->l2tp_scope_id = sk->sk_bound_dev_if; | 
|  | 430 | *uaddr_len = sizeof(*lsa); | 
|  | 431 | return 0; | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | static int l2tp_ip6_backlog_recv(struct sock *sk, struct sk_buff *skb) | 
|  | 435 | { | 
|  | 436 | int rc; | 
|  | 437 |  | 
|  | 438 | /* Charge it to the socket, dropping if the queue is full. */ | 
|  | 439 | rc = sock_queue_rcv_skb(sk, skb); | 
|  | 440 | if (rc < 0) | 
|  | 441 | goto drop; | 
|  | 442 |  | 
|  | 443 | return 0; | 
|  | 444 |  | 
|  | 445 | drop: | 
|  | 446 | IP_INC_STATS(&init_net, IPSTATS_MIB_INDISCARDS); | 
|  | 447 | kfree_skb(skb); | 
|  | 448 | return -1; | 
|  | 449 | } | 
|  | 450 |  | 
|  | 451 | static int l2tp_ip6_push_pending_frames(struct sock *sk) | 
|  | 452 | { | 
|  | 453 | struct sk_buff *skb; | 
|  | 454 | __be32 *transhdr = NULL; | 
|  | 455 | int err = 0; | 
|  | 456 |  | 
|  | 457 | skb = skb_peek(&sk->sk_write_queue); | 
|  | 458 | if (skb == NULL) | 
|  | 459 | goto out; | 
|  | 460 |  | 
|  | 461 | transhdr = (__be32 *)skb_transport_header(skb); | 
|  | 462 | *transhdr = 0; | 
|  | 463 |  | 
|  | 464 | err = ip6_push_pending_frames(sk); | 
|  | 465 |  | 
|  | 466 | out: | 
|  | 467 | return err; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | /* Userspace will call sendmsg() on the tunnel socket to send L2TP | 
|  | 471 | * control frames. | 
|  | 472 | */ | 
|  | 473 | static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, | 
|  | 474 | struct msghdr *msg, size_t len) | 
|  | 475 | { | 
|  | 476 | struct ipv6_txoptions opt_space; | 
|  | 477 | struct sockaddr_l2tpip6 *lsa = | 
|  | 478 | (struct sockaddr_l2tpip6 *) msg->msg_name; | 
|  | 479 | struct in6_addr *daddr, *final_p, final; | 
|  | 480 | struct ipv6_pinfo *np = inet6_sk(sk); | 
|  | 481 | struct ipv6_txoptions *opt = NULL; | 
|  | 482 | struct ip6_flowlabel *flowlabel = NULL; | 
|  | 483 | struct dst_entry *dst = NULL; | 
|  | 484 | struct flowi6 fl6; | 
|  | 485 | int addr_len = msg->msg_namelen; | 
|  | 486 | int hlimit = -1; | 
|  | 487 | int tclass = -1; | 
|  | 488 | int dontfrag = -1; | 
|  | 489 | int transhdrlen = 4; /* zero session-id */ | 
|  | 490 | int ulen = len + transhdrlen; | 
|  | 491 | int err; | 
|  | 492 |  | 
|  | 493 | /* Rough check on arithmetic overflow, | 
|  | 494 | better check is made in ip6_append_data(). | 
|  | 495 | */ | 
|  | 496 | if (len > INT_MAX) | 
|  | 497 | return -EMSGSIZE; | 
|  | 498 |  | 
|  | 499 | /* Mirror BSD error message compatibility */ | 
|  | 500 | if (msg->msg_flags & MSG_OOB) | 
|  | 501 | return -EOPNOTSUPP; | 
|  | 502 |  | 
|  | 503 | /* | 
|  | 504 | *	Get and verify the address. | 
|  | 505 | */ | 
|  | 506 | memset(&fl6, 0, sizeof(fl6)); | 
|  | 507 |  | 
|  | 508 | fl6.flowi6_mark = sk->sk_mark; | 
|  | 509 |  | 
|  | 510 | if (lsa) { | 
|  | 511 | if (addr_len < SIN6_LEN_RFC2133) | 
|  | 512 | return -EINVAL; | 
|  | 513 |  | 
|  | 514 | if (lsa->l2tp_family && lsa->l2tp_family != AF_INET6) | 
|  | 515 | return -EAFNOSUPPORT; | 
|  | 516 |  | 
|  | 517 | daddr = &lsa->l2tp_addr; | 
|  | 518 | if (np->sndflow) { | 
|  | 519 | fl6.flowlabel = lsa->l2tp_flowinfo & IPV6_FLOWINFO_MASK; | 
|  | 520 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { | 
|  | 521 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 
|  | 522 | if (flowlabel == NULL) | 
|  | 523 | return -EINVAL; | 
|  | 524 | daddr = &flowlabel->dst; | 
|  | 525 | } | 
|  | 526 | } | 
|  | 527 |  | 
|  | 528 | /* | 
|  | 529 | * Otherwise it will be difficult to maintain | 
|  | 530 | * sk->sk_dst_cache. | 
|  | 531 | */ | 
|  | 532 | if (sk->sk_state == TCP_ESTABLISHED && | 
|  | 533 | ipv6_addr_equal(daddr, &np->daddr)) | 
|  | 534 | daddr = &np->daddr; | 
|  | 535 |  | 
|  | 536 | if (addr_len >= sizeof(struct sockaddr_in6) && | 
|  | 537 | lsa->l2tp_scope_id && | 
|  | 538 | ipv6_addr_type(daddr) & IPV6_ADDR_LINKLOCAL) | 
|  | 539 | fl6.flowi6_oif = lsa->l2tp_scope_id; | 
|  | 540 | } else { | 
|  | 541 | if (sk->sk_state != TCP_ESTABLISHED) | 
|  | 542 | return -EDESTADDRREQ; | 
|  | 543 |  | 
|  | 544 | daddr = &np->daddr; | 
|  | 545 | fl6.flowlabel = np->flow_label; | 
|  | 546 | } | 
|  | 547 |  | 
|  | 548 | if (fl6.flowi6_oif == 0) | 
|  | 549 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 
|  | 550 |  | 
|  | 551 | if (msg->msg_controllen) { | 
|  | 552 | opt = &opt_space; | 
|  | 553 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 
|  | 554 | opt->tot_len = sizeof(struct ipv6_txoptions); | 
|  | 555 |  | 
|  | 556 | err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, | 
|  | 557 | &hlimit, &tclass, &dontfrag); | 
|  | 558 | if (err < 0) { | 
|  | 559 | fl6_sock_release(flowlabel); | 
|  | 560 | return err; | 
|  | 561 | } | 
|  | 562 | if ((fl6.flowlabel & IPV6_FLOWLABEL_MASK) && !flowlabel) { | 
|  | 563 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 
|  | 564 | if (flowlabel == NULL) | 
|  | 565 | return -EINVAL; | 
|  | 566 | } | 
|  | 567 | if (!(opt->opt_nflen|opt->opt_flen)) | 
|  | 568 | opt = NULL; | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | if (opt == NULL) | 
|  | 572 | opt = np->opt; | 
|  | 573 | if (flowlabel) | 
|  | 574 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 
|  | 575 | opt = ipv6_fixup_options(&opt_space, opt); | 
|  | 576 |  | 
|  | 577 | fl6.flowi6_proto = sk->sk_protocol; | 
|  | 578 | if (!ipv6_addr_any(daddr)) | 
|  | 579 | fl6.daddr = *daddr; | 
|  | 580 | else | 
|  | 581 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 
|  | 582 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) | 
|  | 583 | fl6.saddr = np->saddr; | 
|  | 584 |  | 
|  | 585 | final_p = fl6_update_dst(&fl6, opt, &final); | 
|  | 586 |  | 
|  | 587 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | 
|  | 588 | fl6.flowi6_oif = np->mcast_oif; | 
|  | 589 | else if (!fl6.flowi6_oif) | 
|  | 590 | fl6.flowi6_oif = np->ucast_oif; | 
|  | 591 |  | 
|  | 592 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 
|  | 593 |  | 
|  | 594 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); | 
|  | 595 | if (IS_ERR(dst)) { | 
|  | 596 | err = PTR_ERR(dst); | 
|  | 597 | goto out; | 
|  | 598 | } | 
|  | 599 |  | 
|  | 600 | if (hlimit < 0) { | 
|  | 601 | if (ipv6_addr_is_multicast(&fl6.daddr)) | 
|  | 602 | hlimit = np->mcast_hops; | 
|  | 603 | else | 
|  | 604 | hlimit = np->hop_limit; | 
|  | 605 | if (hlimit < 0) | 
|  | 606 | hlimit = ip6_dst_hoplimit(dst); | 
|  | 607 | } | 
|  | 608 |  | 
|  | 609 | if (tclass < 0) | 
|  | 610 | tclass = np->tclass; | 
|  | 611 |  | 
|  | 612 | if (dontfrag < 0) | 
|  | 613 | dontfrag = np->dontfrag; | 
|  | 614 |  | 
|  | 615 | if (msg->msg_flags & MSG_CONFIRM) | 
|  | 616 | goto do_confirm; | 
|  | 617 |  | 
|  | 618 | back_from_confirm: | 
|  | 619 | lock_sock(sk); | 
|  | 620 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 
|  | 621 | ulen, transhdrlen, hlimit, tclass, opt, | 
|  | 622 | &fl6, (struct rt6_info *)dst, | 
|  | 623 | msg->msg_flags, dontfrag); | 
|  | 624 | if (err) | 
|  | 625 | ip6_flush_pending_frames(sk); | 
|  | 626 | else if (!(msg->msg_flags & MSG_MORE)) | 
|  | 627 | err = l2tp_ip6_push_pending_frames(sk); | 
|  | 628 | release_sock(sk); | 
|  | 629 | done: | 
|  | 630 | dst_release(dst); | 
|  | 631 | out: | 
|  | 632 | fl6_sock_release(flowlabel); | 
|  | 633 |  | 
|  | 634 | return err < 0 ? err : len; | 
|  | 635 |  | 
|  | 636 | do_confirm: | 
|  | 637 | dst_confirm(dst); | 
|  | 638 | if (!(msg->msg_flags & MSG_PROBE) || len) | 
|  | 639 | goto back_from_confirm; | 
|  | 640 | err = 0; | 
|  | 641 | goto done; | 
|  | 642 | } | 
|  | 643 |  | 
|  | 644 | static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, | 
|  | 645 | struct msghdr *msg, size_t len, int noblock, | 
|  | 646 | int flags, int *addr_len) | 
|  | 647 | { | 
|  | 648 | struct inet_sock *inet = inet_sk(sk); | 
|  | 649 | struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)msg->msg_name; | 
|  | 650 | size_t copied = 0; | 
|  | 651 | int err = -EOPNOTSUPP; | 
|  | 652 | struct sk_buff *skb; | 
|  | 653 |  | 
|  | 654 | if (flags & MSG_OOB) | 
|  | 655 | goto out; | 
|  | 656 |  | 
|  | 657 | if (addr_len) | 
|  | 658 | *addr_len = sizeof(*lsa); | 
|  | 659 |  | 
|  | 660 | if (flags & MSG_ERRQUEUE) | 
|  | 661 | return ipv6_recv_error(sk, msg, len); | 
|  | 662 |  | 
|  | 663 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 
|  | 664 | if (!skb) | 
|  | 665 | goto out; | 
|  | 666 |  | 
|  | 667 | copied = skb->len; | 
|  | 668 | if (len < copied) { | 
|  | 669 | msg->msg_flags |= MSG_TRUNC; | 
|  | 670 | copied = len; | 
|  | 671 | } | 
|  | 672 |  | 
|  | 673 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 
|  | 674 | if (err) | 
|  | 675 | goto done; | 
|  | 676 |  | 
|  | 677 | sock_recv_timestamp(msg, sk, skb); | 
|  | 678 |  | 
|  | 679 | /* Copy the address. */ | 
|  | 680 | if (lsa) { | 
|  | 681 | lsa->l2tp_family = AF_INET6; | 
|  | 682 | lsa->l2tp_unused = 0; | 
|  | 683 | lsa->l2tp_addr = ipv6_hdr(skb)->saddr; | 
|  | 684 | lsa->l2tp_flowinfo = 0; | 
|  | 685 | lsa->l2tp_scope_id = 0; | 
|  | 686 | if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) | 
|  | 687 | lsa->l2tp_scope_id = IP6CB(skb)->iif; | 
|  | 688 | } | 
|  | 689 |  | 
|  | 690 | if (inet->cmsg_flags) | 
|  | 691 | ip_cmsg_recv(msg, skb); | 
|  | 692 |  | 
|  | 693 | if (flags & MSG_TRUNC) | 
|  | 694 | copied = skb->len; | 
|  | 695 | done: | 
|  | 696 | skb_free_datagram(sk, skb); | 
|  | 697 | out: | 
|  | 698 | return err ? err : copied; | 
|  | 699 | } | 
|  | 700 |  | 
|  | 701 | static struct proto l2tp_ip6_prot = { | 
|  | 702 | .name		   = "L2TP/IPv6", | 
|  | 703 | .owner		   = THIS_MODULE, | 
|  | 704 | .init		   = l2tp_ip6_open, | 
|  | 705 | .close		   = l2tp_ip6_close, | 
|  | 706 | .bind		   = l2tp_ip6_bind, | 
|  | 707 | .connect	   = l2tp_ip6_connect, | 
| James Chapman | c51ce49 | 2012-05-29 03:30:42 +0000 | [diff] [blame] | 708 | .disconnect	   = l2tp_ip6_disconnect, | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 709 | .ioctl		   = udp_ioctl, | 
|  | 710 | .destroy	   = l2tp_ip6_destroy_sock, | 
|  | 711 | .setsockopt	   = ipv6_setsockopt, | 
|  | 712 | .getsockopt	   = ipv6_getsockopt, | 
|  | 713 | .sendmsg	   = l2tp_ip6_sendmsg, | 
|  | 714 | .recvmsg	   = l2tp_ip6_recvmsg, | 
|  | 715 | .backlog_rcv	   = l2tp_ip6_backlog_recv, | 
|  | 716 | .hash		   = inet_hash, | 
|  | 717 | .unhash		   = inet_unhash, | 
|  | 718 | .obj_size	   = sizeof(struct l2tp_ip6_sock), | 
|  | 719 | #ifdef CONFIG_COMPAT | 
|  | 720 | .compat_setsockopt = compat_ipv6_setsockopt, | 
|  | 721 | .compat_getsockopt = compat_ipv6_getsockopt, | 
|  | 722 | #endif | 
|  | 723 | }; | 
|  | 724 |  | 
|  | 725 | static const struct proto_ops l2tp_ip6_ops = { | 
|  | 726 | .family		   = PF_INET6, | 
|  | 727 | .owner		   = THIS_MODULE, | 
|  | 728 | .release	   = inet6_release, | 
|  | 729 | .bind		   = inet6_bind, | 
|  | 730 | .connect	   = inet_dgram_connect, | 
|  | 731 | .socketpair	   = sock_no_socketpair, | 
|  | 732 | .accept		   = sock_no_accept, | 
|  | 733 | .getname	   = l2tp_ip6_getname, | 
|  | 734 | .poll		   = datagram_poll, | 
|  | 735 | .ioctl		   = inet6_ioctl, | 
|  | 736 | .listen		   = sock_no_listen, | 
|  | 737 | .shutdown	   = inet_shutdown, | 
|  | 738 | .setsockopt	   = sock_common_setsockopt, | 
|  | 739 | .getsockopt	   = sock_common_getsockopt, | 
|  | 740 | .sendmsg	   = inet_sendmsg, | 
|  | 741 | .recvmsg	   = sock_common_recvmsg, | 
|  | 742 | .mmap		   = sock_no_mmap, | 
|  | 743 | .sendpage	   = sock_no_sendpage, | 
|  | 744 | #ifdef CONFIG_COMPAT | 
|  | 745 | .compat_setsockopt = compat_sock_common_setsockopt, | 
|  | 746 | .compat_getsockopt = compat_sock_common_getsockopt, | 
|  | 747 | #endif | 
|  | 748 | }; | 
|  | 749 |  | 
|  | 750 | static struct inet_protosw l2tp_ip6_protosw = { | 
|  | 751 | .type		= SOCK_DGRAM, | 
|  | 752 | .protocol	= IPPROTO_L2TP, | 
|  | 753 | .prot		= &l2tp_ip6_prot, | 
|  | 754 | .ops		= &l2tp_ip6_ops, | 
|  | 755 | .no_check	= 0, | 
|  | 756 | }; | 
|  | 757 |  | 
|  | 758 | static struct inet6_protocol l2tp_ip6_protocol __read_mostly = { | 
|  | 759 | .handler	= l2tp_ip6_recv, | 
|  | 760 | }; | 
|  | 761 |  | 
|  | 762 | static int __init l2tp_ip6_init(void) | 
|  | 763 | { | 
|  | 764 | int err; | 
|  | 765 |  | 
| Joe Perches | a4ca44f | 2012-05-16 09:55:56 +0000 | [diff] [blame] | 766 | pr_info("L2TP IP encapsulation support for IPv6 (L2TPv3)\n"); | 
| Chris Elston | a32e0ee | 2012-04-29 21:48:54 +0000 | [diff] [blame] | 767 |  | 
|  | 768 | err = proto_register(&l2tp_ip6_prot, 1); | 
|  | 769 | if (err != 0) | 
|  | 770 | goto out; | 
|  | 771 |  | 
|  | 772 | err = inet6_add_protocol(&l2tp_ip6_protocol, IPPROTO_L2TP); | 
|  | 773 | if (err) | 
|  | 774 | goto out1; | 
|  | 775 |  | 
|  | 776 | inet6_register_protosw(&l2tp_ip6_protosw); | 
|  | 777 | return 0; | 
|  | 778 |  | 
|  | 779 | out1: | 
|  | 780 | proto_unregister(&l2tp_ip6_prot); | 
|  | 781 | out: | 
|  | 782 | return err; | 
|  | 783 | } | 
|  | 784 |  | 
|  | 785 | static void __exit l2tp_ip6_exit(void) | 
|  | 786 | { | 
|  | 787 | inet6_unregister_protosw(&l2tp_ip6_protosw); | 
|  | 788 | inet6_del_protocol(&l2tp_ip6_protocol, IPPROTO_L2TP); | 
|  | 789 | proto_unregister(&l2tp_ip6_prot); | 
|  | 790 | } | 
|  | 791 |  | 
|  | 792 | module_init(l2tp_ip6_init); | 
|  | 793 | module_exit(l2tp_ip6_exit); | 
|  | 794 |  | 
|  | 795 | MODULE_LICENSE("GPL"); | 
|  | 796 | MODULE_AUTHOR("Chris Elston <celston@katalix.com>"); | 
|  | 797 | MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6"); | 
|  | 798 | MODULE_VERSION("1.0"); | 
|  | 799 |  | 
|  | 800 | /* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like | 
|  | 801 | * enums | 
|  | 802 | */ | 
|  | 803 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP); |