1*fd558d18SJames Chapman /***************************************************************************** 2*fd558d18SJames Chapman * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets 3*fd558d18SJames Chapman * 4*fd558d18SJames Chapman * PPPoX --- Generic PPP encapsulation socket family 5*fd558d18SJames Chapman * PPPoL2TP --- PPP over L2TP (RFC 2661) 6*fd558d18SJames Chapman * 7*fd558d18SJames Chapman * Version: 2.0.0 8*fd558d18SJames Chapman * 9*fd558d18SJames Chapman * Authors: James Chapman (jchapman@katalix.com) 10*fd558d18SJames Chapman * 11*fd558d18SJames Chapman * Based on original work by Martijn van Oosterhout <kleptog@svana.org> 12*fd558d18SJames Chapman * 13*fd558d18SJames Chapman * License: 14*fd558d18SJames Chapman * This program is free software; you can redistribute it and/or 15*fd558d18SJames Chapman * modify it under the terms of the GNU General Public License 16*fd558d18SJames Chapman * as published by the Free Software Foundation; either version 17*fd558d18SJames Chapman * 2 of the License, or (at your option) any later version. 18*fd558d18SJames Chapman * 19*fd558d18SJames Chapman */ 20*fd558d18SJames Chapman 21*fd558d18SJames Chapman /* This driver handles only L2TP data frames; control frames are handled by a 22*fd558d18SJames Chapman * userspace application. 23*fd558d18SJames Chapman * 24*fd558d18SJames Chapman * To send data in an L2TP session, userspace opens a PPPoL2TP socket and 25*fd558d18SJames Chapman * attaches it to a bound UDP socket with local tunnel_id / session_id and 26*fd558d18SJames Chapman * peer tunnel_id / session_id set. Data can then be sent or received using 27*fd558d18SJames Chapman * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket 28*fd558d18SJames Chapman * can be read or modified using ioctl() or [gs]etsockopt() calls. 29*fd558d18SJames Chapman * 30*fd558d18SJames Chapman * When a PPPoL2TP socket is connected with local and peer session_id values 31*fd558d18SJames Chapman * zero, the socket is treated as a special tunnel management socket. 32*fd558d18SJames Chapman * 33*fd558d18SJames Chapman * Here's example userspace code to create a socket for sending/receiving data 34*fd558d18SJames Chapman * over an L2TP session:- 35*fd558d18SJames Chapman * 36*fd558d18SJames Chapman * struct sockaddr_pppol2tp sax; 37*fd558d18SJames Chapman * int fd; 38*fd558d18SJames Chapman * int session_fd; 39*fd558d18SJames Chapman * 40*fd558d18SJames Chapman * fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); 41*fd558d18SJames Chapman * 42*fd558d18SJames Chapman * sax.sa_family = AF_PPPOX; 43*fd558d18SJames Chapman * sax.sa_protocol = PX_PROTO_OL2TP; 44*fd558d18SJames Chapman * sax.pppol2tp.fd = tunnel_fd; // bound UDP socket 45*fd558d18SJames Chapman * sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr; 46*fd558d18SJames Chapman * sax.pppol2tp.addr.sin_port = addr->sin_port; 47*fd558d18SJames Chapman * sax.pppol2tp.addr.sin_family = AF_INET; 48*fd558d18SJames Chapman * sax.pppol2tp.s_tunnel = tunnel_id; 49*fd558d18SJames Chapman * sax.pppol2tp.s_session = session_id; 50*fd558d18SJames Chapman * sax.pppol2tp.d_tunnel = peer_tunnel_id; 51*fd558d18SJames Chapman * sax.pppol2tp.d_session = peer_session_id; 52*fd558d18SJames Chapman * 53*fd558d18SJames Chapman * session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax)); 54*fd558d18SJames Chapman * 55*fd558d18SJames Chapman * A pppd plugin that allows PPP traffic to be carried over L2TP using 56*fd558d18SJames Chapman * this driver is available from the OpenL2TP project at 57*fd558d18SJames Chapman * http://openl2tp.sourceforge.net. 58*fd558d18SJames Chapman */ 59*fd558d18SJames Chapman 60*fd558d18SJames Chapman #include <linux/module.h> 61*fd558d18SJames Chapman #include <linux/string.h> 62*fd558d18SJames Chapman #include <linux/list.h> 63*fd558d18SJames Chapman #include <linux/uaccess.h> 64*fd558d18SJames Chapman 65*fd558d18SJames Chapman #include <linux/kernel.h> 66*fd558d18SJames Chapman #include <linux/spinlock.h> 67*fd558d18SJames Chapman #include <linux/kthread.h> 68*fd558d18SJames Chapman #include <linux/sched.h> 69*fd558d18SJames Chapman #include <linux/slab.h> 70*fd558d18SJames Chapman #include <linux/errno.h> 71*fd558d18SJames Chapman #include <linux/jiffies.h> 72*fd558d18SJames Chapman 73*fd558d18SJames Chapman #include <linux/netdevice.h> 74*fd558d18SJames Chapman #include <linux/net.h> 75*fd558d18SJames Chapman #include <linux/inetdevice.h> 76*fd558d18SJames Chapman #include <linux/skbuff.h> 77*fd558d18SJames Chapman #include <linux/init.h> 78*fd558d18SJames Chapman #include <linux/ip.h> 79*fd558d18SJames Chapman #include <linux/udp.h> 80*fd558d18SJames Chapman #include <linux/if_pppox.h> 81*fd558d18SJames Chapman #include <linux/if_pppol2tp.h> 82*fd558d18SJames Chapman #include <net/sock.h> 83*fd558d18SJames Chapman #include <linux/ppp_channel.h> 84*fd558d18SJames Chapman #include <linux/ppp_defs.h> 85*fd558d18SJames Chapman #include <linux/if_ppp.h> 86*fd558d18SJames Chapman #include <linux/file.h> 87*fd558d18SJames Chapman #include <linux/hash.h> 88*fd558d18SJames Chapman #include <linux/sort.h> 89*fd558d18SJames Chapman #include <linux/proc_fs.h> 90*fd558d18SJames Chapman #include <linux/nsproxy.h> 91*fd558d18SJames Chapman #include <net/net_namespace.h> 92*fd558d18SJames Chapman #include <net/netns/generic.h> 93*fd558d18SJames Chapman #include <net/dst.h> 94*fd558d18SJames Chapman #include <net/ip.h> 95*fd558d18SJames Chapman #include <net/udp.h> 96*fd558d18SJames Chapman #include <net/xfrm.h> 97*fd558d18SJames Chapman 98*fd558d18SJames Chapman #include <asm/byteorder.h> 99*fd558d18SJames Chapman #include <asm/atomic.h> 100*fd558d18SJames Chapman 101*fd558d18SJames Chapman #include "l2tp_core.h" 102*fd558d18SJames Chapman 103*fd558d18SJames Chapman #define PPPOL2TP_DRV_VERSION "V2.0" 104*fd558d18SJames Chapman 105*fd558d18SJames Chapman /* Space for UDP, L2TP and PPP headers */ 106*fd558d18SJames Chapman #define PPPOL2TP_HEADER_OVERHEAD 40 107*fd558d18SJames Chapman 108*fd558d18SJames Chapman #define PRINTK(_mask, _type, _lvl, _fmt, args...) \ 109*fd558d18SJames Chapman do { \ 110*fd558d18SJames Chapman if ((_mask) & (_type)) \ 111*fd558d18SJames Chapman printk(_lvl "PPPOL2TP: " _fmt, ##args); \ 112*fd558d18SJames Chapman } while (0) 113*fd558d18SJames Chapman 114*fd558d18SJames Chapman /* Number of bytes to build transmit L2TP headers. 115*fd558d18SJames Chapman * Unfortunately the size is different depending on whether sequence numbers 116*fd558d18SJames Chapman * are enabled. 117*fd558d18SJames Chapman */ 118*fd558d18SJames Chapman #define PPPOL2TP_L2TP_HDR_SIZE_SEQ 10 119*fd558d18SJames Chapman #define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ 6 120*fd558d18SJames Chapman 121*fd558d18SJames Chapman /* Private data of each session. This data lives at the end of struct 122*fd558d18SJames Chapman * l2tp_session, referenced via session->priv[]. 123*fd558d18SJames Chapman */ 124*fd558d18SJames Chapman struct pppol2tp_session { 125*fd558d18SJames Chapman int owner; /* pid that opened the socket */ 126*fd558d18SJames Chapman 127*fd558d18SJames Chapman struct sock *sock; /* Pointer to the session 128*fd558d18SJames Chapman * PPPoX socket */ 129*fd558d18SJames Chapman struct sock *tunnel_sock; /* Pointer to the tunnel UDP 130*fd558d18SJames Chapman * socket */ 131*fd558d18SJames Chapman int flags; /* accessed by PPPIOCGFLAGS. 132*fd558d18SJames Chapman * Unused. */ 133*fd558d18SJames Chapman }; 134*fd558d18SJames Chapman 135*fd558d18SJames Chapman static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); 136*fd558d18SJames Chapman 137*fd558d18SJames Chapman static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; 138*fd558d18SJames Chapman static const struct proto_ops pppol2tp_ops; 139*fd558d18SJames Chapman 140*fd558d18SJames Chapman /* Helpers to obtain tunnel/session contexts from sockets. 141*fd558d18SJames Chapman */ 142*fd558d18SJames Chapman static inline struct l2tp_session *pppol2tp_sock_to_session(struct sock *sk) 143*fd558d18SJames Chapman { 144*fd558d18SJames Chapman struct l2tp_session *session; 145*fd558d18SJames Chapman 146*fd558d18SJames Chapman if (sk == NULL) 147*fd558d18SJames Chapman return NULL; 148*fd558d18SJames Chapman 149*fd558d18SJames Chapman sock_hold(sk); 150*fd558d18SJames Chapman session = (struct l2tp_session *)(sk->sk_user_data); 151*fd558d18SJames Chapman if (session == NULL) { 152*fd558d18SJames Chapman sock_put(sk); 153*fd558d18SJames Chapman goto out; 154*fd558d18SJames Chapman } 155*fd558d18SJames Chapman 156*fd558d18SJames Chapman BUG_ON(session->magic != L2TP_SESSION_MAGIC); 157*fd558d18SJames Chapman 158*fd558d18SJames Chapman out: 159*fd558d18SJames Chapman return session; 160*fd558d18SJames Chapman } 161*fd558d18SJames Chapman 162*fd558d18SJames Chapman /***************************************************************************** 163*fd558d18SJames Chapman * Receive data handling 164*fd558d18SJames Chapman *****************************************************************************/ 165*fd558d18SJames Chapman 166*fd558d18SJames Chapman static int pppol2tp_recv_payload_hook(struct sk_buff *skb) 167*fd558d18SJames Chapman { 168*fd558d18SJames Chapman /* Skip PPP header, if present. In testing, Microsoft L2TP clients 169*fd558d18SJames Chapman * don't send the PPP header (PPP header compression enabled), but 170*fd558d18SJames Chapman * other clients can include the header. So we cope with both cases 171*fd558d18SJames Chapman * here. The PPP header is always FF03 when using L2TP. 172*fd558d18SJames Chapman * 173*fd558d18SJames Chapman * Note that skb->data[] isn't dereferenced from a u16 ptr here since 174*fd558d18SJames Chapman * the field may be unaligned. 175*fd558d18SJames Chapman */ 176*fd558d18SJames Chapman if (!pskb_may_pull(skb, 2)) 177*fd558d18SJames Chapman return 1; 178*fd558d18SJames Chapman 179*fd558d18SJames Chapman if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03)) 180*fd558d18SJames Chapman skb_pull(skb, 2); 181*fd558d18SJames Chapman 182*fd558d18SJames Chapman return 0; 183*fd558d18SJames Chapman } 184*fd558d18SJames Chapman 185*fd558d18SJames Chapman /* Receive message. This is the recvmsg for the PPPoL2TP socket. 186*fd558d18SJames Chapman */ 187*fd558d18SJames Chapman static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, 188*fd558d18SJames Chapman struct msghdr *msg, size_t len, 189*fd558d18SJames Chapman int flags) 190*fd558d18SJames Chapman { 191*fd558d18SJames Chapman int err; 192*fd558d18SJames Chapman struct sk_buff *skb; 193*fd558d18SJames Chapman struct sock *sk = sock->sk; 194*fd558d18SJames Chapman 195*fd558d18SJames Chapman err = -EIO; 196*fd558d18SJames Chapman if (sk->sk_state & PPPOX_BOUND) 197*fd558d18SJames Chapman goto end; 198*fd558d18SJames Chapman 199*fd558d18SJames Chapman msg->msg_namelen = 0; 200*fd558d18SJames Chapman 201*fd558d18SJames Chapman err = 0; 202*fd558d18SJames Chapman skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 203*fd558d18SJames Chapman flags & MSG_DONTWAIT, &err); 204*fd558d18SJames Chapman if (!skb) 205*fd558d18SJames Chapman goto end; 206*fd558d18SJames Chapman 207*fd558d18SJames Chapman if (len > skb->len) 208*fd558d18SJames Chapman len = skb->len; 209*fd558d18SJames Chapman else if (len < skb->len) 210*fd558d18SJames Chapman msg->msg_flags |= MSG_TRUNC; 211*fd558d18SJames Chapman 212*fd558d18SJames Chapman err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); 213*fd558d18SJames Chapman if (likely(err == 0)) 214*fd558d18SJames Chapman err = len; 215*fd558d18SJames Chapman 216*fd558d18SJames Chapman kfree_skb(skb); 217*fd558d18SJames Chapman end: 218*fd558d18SJames Chapman return err; 219*fd558d18SJames Chapman } 220*fd558d18SJames Chapman 221*fd558d18SJames Chapman static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) 222*fd558d18SJames Chapman { 223*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 224*fd558d18SJames Chapman struct sock *sk = NULL; 225*fd558d18SJames Chapman 226*fd558d18SJames Chapman /* If the socket is bound, send it in to PPP's input queue. Otherwise 227*fd558d18SJames Chapman * queue it on the session socket. 228*fd558d18SJames Chapman */ 229*fd558d18SJames Chapman sk = ps->sock; 230*fd558d18SJames Chapman if (sk == NULL) 231*fd558d18SJames Chapman goto no_sock; 232*fd558d18SJames Chapman 233*fd558d18SJames Chapman if (sk->sk_state & PPPOX_BOUND) { 234*fd558d18SJames Chapman struct pppox_sock *po; 235*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, 236*fd558d18SJames Chapman "%s: recv %d byte data frame, passing to ppp\n", 237*fd558d18SJames Chapman session->name, data_len); 238*fd558d18SJames Chapman 239*fd558d18SJames Chapman /* We need to forget all info related to the L2TP packet 240*fd558d18SJames Chapman * gathered in the skb as we are going to reuse the same 241*fd558d18SJames Chapman * skb for the inner packet. 242*fd558d18SJames Chapman * Namely we need to: 243*fd558d18SJames Chapman * - reset xfrm (IPSec) information as it applies to 244*fd558d18SJames Chapman * the outer L2TP packet and not to the inner one 245*fd558d18SJames Chapman * - release the dst to force a route lookup on the inner 246*fd558d18SJames Chapman * IP packet since skb->dst currently points to the dst 247*fd558d18SJames Chapman * of the UDP tunnel 248*fd558d18SJames Chapman * - reset netfilter information as it doesn't apply 249*fd558d18SJames Chapman * to the inner packet either 250*fd558d18SJames Chapman */ 251*fd558d18SJames Chapman secpath_reset(skb); 252*fd558d18SJames Chapman skb_dst_drop(skb); 253*fd558d18SJames Chapman nf_reset(skb); 254*fd558d18SJames Chapman 255*fd558d18SJames Chapman po = pppox_sk(sk); 256*fd558d18SJames Chapman ppp_input(&po->chan, skb); 257*fd558d18SJames Chapman } else { 258*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO, 259*fd558d18SJames Chapman "%s: socket not bound\n", session->name); 260*fd558d18SJames Chapman 261*fd558d18SJames Chapman /* Not bound. Nothing we can do, so discard. */ 262*fd558d18SJames Chapman session->stats.rx_errors++; 263*fd558d18SJames Chapman kfree_skb(skb); 264*fd558d18SJames Chapman } 265*fd558d18SJames Chapman 266*fd558d18SJames Chapman return; 267*fd558d18SJames Chapman 268*fd558d18SJames Chapman no_sock: 269*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO, 270*fd558d18SJames Chapman "%s: no socket\n", session->name); 271*fd558d18SJames Chapman kfree_skb(skb); 272*fd558d18SJames Chapman } 273*fd558d18SJames Chapman 274*fd558d18SJames Chapman static void pppol2tp_session_sock_hold(struct l2tp_session *session) 275*fd558d18SJames Chapman { 276*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 277*fd558d18SJames Chapman 278*fd558d18SJames Chapman if (ps->sock) 279*fd558d18SJames Chapman sock_hold(ps->sock); 280*fd558d18SJames Chapman } 281*fd558d18SJames Chapman 282*fd558d18SJames Chapman static void pppol2tp_session_sock_put(struct l2tp_session *session) 283*fd558d18SJames Chapman { 284*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 285*fd558d18SJames Chapman 286*fd558d18SJames Chapman if (ps->sock) 287*fd558d18SJames Chapman sock_put(ps->sock); 288*fd558d18SJames Chapman } 289*fd558d18SJames Chapman 290*fd558d18SJames Chapman /************************************************************************ 291*fd558d18SJames Chapman * Transmit handling 292*fd558d18SJames Chapman ***********************************************************************/ 293*fd558d18SJames Chapman 294*fd558d18SJames Chapman /* Tell how big L2TP headers are for a particular session. This 295*fd558d18SJames Chapman * depends on whether sequence numbers are being used. 296*fd558d18SJames Chapman */ 297*fd558d18SJames Chapman static inline int pppol2tp_l2tp_header_len(struct l2tp_session *session) 298*fd558d18SJames Chapman { 299*fd558d18SJames Chapman if (session->send_seq) 300*fd558d18SJames Chapman return PPPOL2TP_L2TP_HDR_SIZE_SEQ; 301*fd558d18SJames Chapman 302*fd558d18SJames Chapman return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; 303*fd558d18SJames Chapman } 304*fd558d18SJames Chapman 305*fd558d18SJames Chapman /* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here 306*fd558d18SJames Chapman * when a user application does a sendmsg() on the session socket. L2TP and 307*fd558d18SJames Chapman * PPP headers must be inserted into the user's data. 308*fd558d18SJames Chapman */ 309*fd558d18SJames Chapman static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, 310*fd558d18SJames Chapman size_t total_len) 311*fd558d18SJames Chapman { 312*fd558d18SJames Chapman static const unsigned char ppph[2] = { 0xff, 0x03 }; 313*fd558d18SJames Chapman struct sock *sk = sock->sk; 314*fd558d18SJames Chapman struct sk_buff *skb; 315*fd558d18SJames Chapman int error; 316*fd558d18SJames Chapman struct l2tp_session *session; 317*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 318*fd558d18SJames Chapman struct pppol2tp_session *ps; 319*fd558d18SJames Chapman 320*fd558d18SJames Chapman error = -ENOTCONN; 321*fd558d18SJames Chapman if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) 322*fd558d18SJames Chapman goto error; 323*fd558d18SJames Chapman 324*fd558d18SJames Chapman /* Get session and tunnel contexts */ 325*fd558d18SJames Chapman error = -EBADF; 326*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 327*fd558d18SJames Chapman if (session == NULL) 328*fd558d18SJames Chapman goto error; 329*fd558d18SJames Chapman 330*fd558d18SJames Chapman ps = l2tp_session_priv(session); 331*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); 332*fd558d18SJames Chapman if (tunnel == NULL) 333*fd558d18SJames Chapman goto error_put_sess; 334*fd558d18SJames Chapman 335*fd558d18SJames Chapman /* Allocate a socket buffer */ 336*fd558d18SJames Chapman error = -ENOMEM; 337*fd558d18SJames Chapman skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) + 338*fd558d18SJames Chapman sizeof(struct udphdr) + session->hdr_len + 339*fd558d18SJames Chapman sizeof(ppph) + total_len, 340*fd558d18SJames Chapman 0, GFP_KERNEL); 341*fd558d18SJames Chapman if (!skb) 342*fd558d18SJames Chapman goto error_put_sess_tun; 343*fd558d18SJames Chapman 344*fd558d18SJames Chapman /* Reserve space for headers. */ 345*fd558d18SJames Chapman skb_reserve(skb, NET_SKB_PAD); 346*fd558d18SJames Chapman skb_reset_network_header(skb); 347*fd558d18SJames Chapman skb_reserve(skb, sizeof(struct iphdr)); 348*fd558d18SJames Chapman skb_reset_transport_header(skb); 349*fd558d18SJames Chapman skb_reserve(skb, sizeof(struct udphdr)); 350*fd558d18SJames Chapman 351*fd558d18SJames Chapman /* Add PPP header */ 352*fd558d18SJames Chapman skb->data[0] = ppph[0]; 353*fd558d18SJames Chapman skb->data[1] = ppph[1]; 354*fd558d18SJames Chapman skb_put(skb, 2); 355*fd558d18SJames Chapman 356*fd558d18SJames Chapman /* Copy user data into skb */ 357*fd558d18SJames Chapman error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); 358*fd558d18SJames Chapman if (error < 0) { 359*fd558d18SJames Chapman kfree_skb(skb); 360*fd558d18SJames Chapman goto error_put_sess_tun; 361*fd558d18SJames Chapman } 362*fd558d18SJames Chapman skb_put(skb, total_len); 363*fd558d18SJames Chapman 364*fd558d18SJames Chapman l2tp_xmit_skb(session, skb, session->hdr_len); 365*fd558d18SJames Chapman 366*fd558d18SJames Chapman sock_put(ps->tunnel_sock); 367*fd558d18SJames Chapman 368*fd558d18SJames Chapman return error; 369*fd558d18SJames Chapman 370*fd558d18SJames Chapman error_put_sess_tun: 371*fd558d18SJames Chapman sock_put(ps->tunnel_sock); 372*fd558d18SJames Chapman error_put_sess: 373*fd558d18SJames Chapman sock_put(sk); 374*fd558d18SJames Chapman error: 375*fd558d18SJames Chapman return error; 376*fd558d18SJames Chapman } 377*fd558d18SJames Chapman 378*fd558d18SJames Chapman /* Transmit function called by generic PPP driver. Sends PPP frame 379*fd558d18SJames Chapman * over PPPoL2TP socket. 380*fd558d18SJames Chapman * 381*fd558d18SJames Chapman * This is almost the same as pppol2tp_sendmsg(), but rather than 382*fd558d18SJames Chapman * being called with a msghdr from userspace, it is called with a skb 383*fd558d18SJames Chapman * from the kernel. 384*fd558d18SJames Chapman * 385*fd558d18SJames Chapman * The supplied skb from ppp doesn't have enough headroom for the 386*fd558d18SJames Chapman * insertion of L2TP, UDP and IP headers so we need to allocate more 387*fd558d18SJames Chapman * headroom in the skb. This will create a cloned skb. But we must be 388*fd558d18SJames Chapman * careful in the error case because the caller will expect to free 389*fd558d18SJames Chapman * the skb it supplied, not our cloned skb. So we take care to always 390*fd558d18SJames Chapman * leave the original skb unfreed if we return an error. 391*fd558d18SJames Chapman */ 392*fd558d18SJames Chapman static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) 393*fd558d18SJames Chapman { 394*fd558d18SJames Chapman static const u8 ppph[2] = { 0xff, 0x03 }; 395*fd558d18SJames Chapman struct sock *sk = (struct sock *) chan->private; 396*fd558d18SJames Chapman struct sock *sk_tun; 397*fd558d18SJames Chapman int hdr_len; 398*fd558d18SJames Chapman struct l2tp_session *session; 399*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 400*fd558d18SJames Chapman struct pppol2tp_session *ps; 401*fd558d18SJames Chapman int old_headroom; 402*fd558d18SJames Chapman int new_headroom; 403*fd558d18SJames Chapman 404*fd558d18SJames Chapman if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) 405*fd558d18SJames Chapman goto abort; 406*fd558d18SJames Chapman 407*fd558d18SJames Chapman /* Get session and tunnel contexts from the socket */ 408*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 409*fd558d18SJames Chapman if (session == NULL) 410*fd558d18SJames Chapman goto abort; 411*fd558d18SJames Chapman 412*fd558d18SJames Chapman ps = l2tp_session_priv(session); 413*fd558d18SJames Chapman sk_tun = ps->tunnel_sock; 414*fd558d18SJames Chapman if (sk_tun == NULL) 415*fd558d18SJames Chapman goto abort_put_sess; 416*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(sk_tun); 417*fd558d18SJames Chapman if (tunnel == NULL) 418*fd558d18SJames Chapman goto abort_put_sess; 419*fd558d18SJames Chapman 420*fd558d18SJames Chapman /* What header length is configured for this session? */ 421*fd558d18SJames Chapman hdr_len = pppol2tp_l2tp_header_len(session); 422*fd558d18SJames Chapman 423*fd558d18SJames Chapman old_headroom = skb_headroom(skb); 424*fd558d18SJames Chapman if (skb_cow_head(skb, sizeof(ppph))) 425*fd558d18SJames Chapman goto abort_put_sess_tun; 426*fd558d18SJames Chapman 427*fd558d18SJames Chapman new_headroom = skb_headroom(skb); 428*fd558d18SJames Chapman skb->truesize += new_headroom - old_headroom; 429*fd558d18SJames Chapman 430*fd558d18SJames Chapman /* Setup PPP header */ 431*fd558d18SJames Chapman __skb_push(skb, sizeof(ppph)); 432*fd558d18SJames Chapman skb->data[0] = ppph[0]; 433*fd558d18SJames Chapman skb->data[1] = ppph[1]; 434*fd558d18SJames Chapman 435*fd558d18SJames Chapman l2tp_xmit_skb(session, skb, hdr_len); 436*fd558d18SJames Chapman 437*fd558d18SJames Chapman sock_put(sk_tun); 438*fd558d18SJames Chapman sock_put(sk); 439*fd558d18SJames Chapman return 1; 440*fd558d18SJames Chapman 441*fd558d18SJames Chapman abort_put_sess_tun: 442*fd558d18SJames Chapman sock_put(sk_tun); 443*fd558d18SJames Chapman abort_put_sess: 444*fd558d18SJames Chapman sock_put(sk); 445*fd558d18SJames Chapman abort: 446*fd558d18SJames Chapman /* Free the original skb */ 447*fd558d18SJames Chapman kfree_skb(skb); 448*fd558d18SJames Chapman return 1; 449*fd558d18SJames Chapman } 450*fd558d18SJames Chapman 451*fd558d18SJames Chapman /***************************************************************************** 452*fd558d18SJames Chapman * Session (and tunnel control) socket create/destroy. 453*fd558d18SJames Chapman *****************************************************************************/ 454*fd558d18SJames Chapman 455*fd558d18SJames Chapman /* Called by l2tp_core when a session socket is being closed. 456*fd558d18SJames Chapman */ 457*fd558d18SJames Chapman static void pppol2tp_session_close(struct l2tp_session *session) 458*fd558d18SJames Chapman { 459*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 460*fd558d18SJames Chapman struct sock *sk = ps->sock; 461*fd558d18SJames Chapman struct sk_buff *skb; 462*fd558d18SJames Chapman 463*fd558d18SJames Chapman BUG_ON(session->magic != L2TP_SESSION_MAGIC); 464*fd558d18SJames Chapman 465*fd558d18SJames Chapman if (session->session_id == 0) 466*fd558d18SJames Chapman goto out; 467*fd558d18SJames Chapman 468*fd558d18SJames Chapman if (sk != NULL) { 469*fd558d18SJames Chapman lock_sock(sk); 470*fd558d18SJames Chapman 471*fd558d18SJames Chapman if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { 472*fd558d18SJames Chapman pppox_unbind_sock(sk); 473*fd558d18SJames Chapman sk->sk_state = PPPOX_DEAD; 474*fd558d18SJames Chapman sk->sk_state_change(sk); 475*fd558d18SJames Chapman } 476*fd558d18SJames Chapman 477*fd558d18SJames Chapman /* Purge any queued data */ 478*fd558d18SJames Chapman skb_queue_purge(&sk->sk_receive_queue); 479*fd558d18SJames Chapman skb_queue_purge(&sk->sk_write_queue); 480*fd558d18SJames Chapman while ((skb = skb_dequeue(&session->reorder_q))) { 481*fd558d18SJames Chapman kfree_skb(skb); 482*fd558d18SJames Chapman sock_put(sk); 483*fd558d18SJames Chapman } 484*fd558d18SJames Chapman 485*fd558d18SJames Chapman release_sock(sk); 486*fd558d18SJames Chapman } 487*fd558d18SJames Chapman 488*fd558d18SJames Chapman out: 489*fd558d18SJames Chapman return; 490*fd558d18SJames Chapman } 491*fd558d18SJames Chapman 492*fd558d18SJames Chapman /* Really kill the session socket. (Called from sock_put() if 493*fd558d18SJames Chapman * refcnt == 0.) 494*fd558d18SJames Chapman */ 495*fd558d18SJames Chapman static void pppol2tp_session_destruct(struct sock *sk) 496*fd558d18SJames Chapman { 497*fd558d18SJames Chapman struct l2tp_session *session; 498*fd558d18SJames Chapman 499*fd558d18SJames Chapman if (sk->sk_user_data != NULL) { 500*fd558d18SJames Chapman session = sk->sk_user_data; 501*fd558d18SJames Chapman if (session == NULL) 502*fd558d18SJames Chapman goto out; 503*fd558d18SJames Chapman 504*fd558d18SJames Chapman sk->sk_user_data = NULL; 505*fd558d18SJames Chapman BUG_ON(session->magic != L2TP_SESSION_MAGIC); 506*fd558d18SJames Chapman l2tp_session_dec_refcount(session); 507*fd558d18SJames Chapman } 508*fd558d18SJames Chapman 509*fd558d18SJames Chapman out: 510*fd558d18SJames Chapman return; 511*fd558d18SJames Chapman } 512*fd558d18SJames Chapman 513*fd558d18SJames Chapman /* Called when the PPPoX socket (session) is closed. 514*fd558d18SJames Chapman */ 515*fd558d18SJames Chapman static int pppol2tp_release(struct socket *sock) 516*fd558d18SJames Chapman { 517*fd558d18SJames Chapman struct sock *sk = sock->sk; 518*fd558d18SJames Chapman struct l2tp_session *session; 519*fd558d18SJames Chapman int error; 520*fd558d18SJames Chapman 521*fd558d18SJames Chapman if (!sk) 522*fd558d18SJames Chapman return 0; 523*fd558d18SJames Chapman 524*fd558d18SJames Chapman error = -EBADF; 525*fd558d18SJames Chapman lock_sock(sk); 526*fd558d18SJames Chapman if (sock_flag(sk, SOCK_DEAD) != 0) 527*fd558d18SJames Chapman goto error; 528*fd558d18SJames Chapman 529*fd558d18SJames Chapman pppox_unbind_sock(sk); 530*fd558d18SJames Chapman 531*fd558d18SJames Chapman /* Signal the death of the socket. */ 532*fd558d18SJames Chapman sk->sk_state = PPPOX_DEAD; 533*fd558d18SJames Chapman sock_orphan(sk); 534*fd558d18SJames Chapman sock->sk = NULL; 535*fd558d18SJames Chapman 536*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 537*fd558d18SJames Chapman 538*fd558d18SJames Chapman /* Purge any queued data */ 539*fd558d18SJames Chapman skb_queue_purge(&sk->sk_receive_queue); 540*fd558d18SJames Chapman skb_queue_purge(&sk->sk_write_queue); 541*fd558d18SJames Chapman if (session != NULL) { 542*fd558d18SJames Chapman struct sk_buff *skb; 543*fd558d18SJames Chapman while ((skb = skb_dequeue(&session->reorder_q))) { 544*fd558d18SJames Chapman kfree_skb(skb); 545*fd558d18SJames Chapman sock_put(sk); 546*fd558d18SJames Chapman } 547*fd558d18SJames Chapman sock_put(sk); 548*fd558d18SJames Chapman } 549*fd558d18SJames Chapman 550*fd558d18SJames Chapman release_sock(sk); 551*fd558d18SJames Chapman 552*fd558d18SJames Chapman /* This will delete the session context via 553*fd558d18SJames Chapman * pppol2tp_session_destruct() if the socket's refcnt drops to 554*fd558d18SJames Chapman * zero. 555*fd558d18SJames Chapman */ 556*fd558d18SJames Chapman sock_put(sk); 557*fd558d18SJames Chapman 558*fd558d18SJames Chapman return 0; 559*fd558d18SJames Chapman 560*fd558d18SJames Chapman error: 561*fd558d18SJames Chapman release_sock(sk); 562*fd558d18SJames Chapman return error; 563*fd558d18SJames Chapman } 564*fd558d18SJames Chapman 565*fd558d18SJames Chapman static struct proto pppol2tp_sk_proto = { 566*fd558d18SJames Chapman .name = "PPPOL2TP", 567*fd558d18SJames Chapman .owner = THIS_MODULE, 568*fd558d18SJames Chapman .obj_size = sizeof(struct pppox_sock), 569*fd558d18SJames Chapman }; 570*fd558d18SJames Chapman 571*fd558d18SJames Chapman static int pppol2tp_backlog_recv(struct sock *sk, struct sk_buff *skb) 572*fd558d18SJames Chapman { 573*fd558d18SJames Chapman int rc; 574*fd558d18SJames Chapman 575*fd558d18SJames Chapman rc = l2tp_udp_encap_recv(sk, skb); 576*fd558d18SJames Chapman if (rc) 577*fd558d18SJames Chapman kfree_skb(skb); 578*fd558d18SJames Chapman 579*fd558d18SJames Chapman return NET_RX_SUCCESS; 580*fd558d18SJames Chapman } 581*fd558d18SJames Chapman 582*fd558d18SJames Chapman /* socket() handler. Initialize a new struct sock. 583*fd558d18SJames Chapman */ 584*fd558d18SJames Chapman static int pppol2tp_create(struct net *net, struct socket *sock) 585*fd558d18SJames Chapman { 586*fd558d18SJames Chapman int error = -ENOMEM; 587*fd558d18SJames Chapman struct sock *sk; 588*fd558d18SJames Chapman 589*fd558d18SJames Chapman sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto); 590*fd558d18SJames Chapman if (!sk) 591*fd558d18SJames Chapman goto out; 592*fd558d18SJames Chapman 593*fd558d18SJames Chapman sock_init_data(sock, sk); 594*fd558d18SJames Chapman 595*fd558d18SJames Chapman sock->state = SS_UNCONNECTED; 596*fd558d18SJames Chapman sock->ops = &pppol2tp_ops; 597*fd558d18SJames Chapman 598*fd558d18SJames Chapman sk->sk_backlog_rcv = pppol2tp_backlog_recv; 599*fd558d18SJames Chapman sk->sk_protocol = PX_PROTO_OL2TP; 600*fd558d18SJames Chapman sk->sk_family = PF_PPPOX; 601*fd558d18SJames Chapman sk->sk_state = PPPOX_NONE; 602*fd558d18SJames Chapman sk->sk_type = SOCK_STREAM; 603*fd558d18SJames Chapman sk->sk_destruct = pppol2tp_session_destruct; 604*fd558d18SJames Chapman 605*fd558d18SJames Chapman error = 0; 606*fd558d18SJames Chapman 607*fd558d18SJames Chapman out: 608*fd558d18SJames Chapman return error; 609*fd558d18SJames Chapman } 610*fd558d18SJames Chapman 611*fd558d18SJames Chapman /* connect() handler. Attach a PPPoX socket to a tunnel UDP socket 612*fd558d18SJames Chapman */ 613*fd558d18SJames Chapman static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, 614*fd558d18SJames Chapman int sockaddr_len, int flags) 615*fd558d18SJames Chapman { 616*fd558d18SJames Chapman struct sock *sk = sock->sk; 617*fd558d18SJames Chapman struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; 618*fd558d18SJames Chapman struct pppox_sock *po = pppox_sk(sk); 619*fd558d18SJames Chapman struct l2tp_session *session = NULL; 620*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 621*fd558d18SJames Chapman struct pppol2tp_session *ps; 622*fd558d18SJames Chapman struct dst_entry *dst; 623*fd558d18SJames Chapman struct l2tp_session_cfg cfg = { 0, }; 624*fd558d18SJames Chapman int error = 0; 625*fd558d18SJames Chapman 626*fd558d18SJames Chapman lock_sock(sk); 627*fd558d18SJames Chapman 628*fd558d18SJames Chapman error = -EINVAL; 629*fd558d18SJames Chapman if (sp->sa_protocol != PX_PROTO_OL2TP) 630*fd558d18SJames Chapman goto end; 631*fd558d18SJames Chapman 632*fd558d18SJames Chapman /* Check for already bound sockets */ 633*fd558d18SJames Chapman error = -EBUSY; 634*fd558d18SJames Chapman if (sk->sk_state & PPPOX_CONNECTED) 635*fd558d18SJames Chapman goto end; 636*fd558d18SJames Chapman 637*fd558d18SJames Chapman /* We don't supporting rebinding anyway */ 638*fd558d18SJames Chapman error = -EALREADY; 639*fd558d18SJames Chapman if (sk->sk_user_data) 640*fd558d18SJames Chapman goto end; /* socket is already attached */ 641*fd558d18SJames Chapman 642*fd558d18SJames Chapman /* Don't bind if s_tunnel is 0 */ 643*fd558d18SJames Chapman error = -EINVAL; 644*fd558d18SJames Chapman if (sp->pppol2tp.s_tunnel == 0) 645*fd558d18SJames Chapman goto end; 646*fd558d18SJames Chapman 647*fd558d18SJames Chapman /* Special case: create tunnel context if s_session and 648*fd558d18SJames Chapman * d_session is 0. Otherwise look up tunnel using supplied 649*fd558d18SJames Chapman * tunnel id. 650*fd558d18SJames Chapman */ 651*fd558d18SJames Chapman if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) { 652*fd558d18SJames Chapman error = l2tp_tunnel_create(sock_net(sk), sp->pppol2tp.fd, 2, sp->pppol2tp.s_tunnel, sp->pppol2tp.d_tunnel, NULL, &tunnel); 653*fd558d18SJames Chapman if (error < 0) 654*fd558d18SJames Chapman goto end; 655*fd558d18SJames Chapman } else { 656*fd558d18SJames Chapman tunnel = l2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel); 657*fd558d18SJames Chapman 658*fd558d18SJames Chapman /* Error if we can't find the tunnel */ 659*fd558d18SJames Chapman error = -ENOENT; 660*fd558d18SJames Chapman if (tunnel == NULL) 661*fd558d18SJames Chapman goto end; 662*fd558d18SJames Chapman 663*fd558d18SJames Chapman /* Error if socket is not prepped */ 664*fd558d18SJames Chapman if (tunnel->sock == NULL) 665*fd558d18SJames Chapman goto end; 666*fd558d18SJames Chapman } 667*fd558d18SJames Chapman 668*fd558d18SJames Chapman if (tunnel->recv_payload_hook == NULL) 669*fd558d18SJames Chapman tunnel->recv_payload_hook = pppol2tp_recv_payload_hook; 670*fd558d18SJames Chapman 671*fd558d18SJames Chapman /* Check that this session doesn't already exist */ 672*fd558d18SJames Chapman error = -EEXIST; 673*fd558d18SJames Chapman session = l2tp_session_find(tunnel, sp->pppol2tp.s_session); 674*fd558d18SJames Chapman if (session != NULL) 675*fd558d18SJames Chapman goto end; 676*fd558d18SJames Chapman 677*fd558d18SJames Chapman /* Default MTU must allow space for UDP/L2TP/PPP 678*fd558d18SJames Chapman * headers. 679*fd558d18SJames Chapman */ 680*fd558d18SJames Chapman cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; 681*fd558d18SJames Chapman cfg.hdr_len = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; 682*fd558d18SJames Chapman cfg.debug = tunnel->debug; 683*fd558d18SJames Chapman 684*fd558d18SJames Chapman /* Allocate and initialize a new session context. */ 685*fd558d18SJames Chapman session = l2tp_session_create(sizeof(struct pppol2tp_session), 686*fd558d18SJames Chapman tunnel, sp->pppol2tp.s_session, 687*fd558d18SJames Chapman sp->pppol2tp.d_session, &cfg); 688*fd558d18SJames Chapman if (session == NULL) { 689*fd558d18SJames Chapman error = -ENOMEM; 690*fd558d18SJames Chapman goto end; 691*fd558d18SJames Chapman } 692*fd558d18SJames Chapman 693*fd558d18SJames Chapman ps = l2tp_session_priv(session); 694*fd558d18SJames Chapman ps->owner = current->pid; 695*fd558d18SJames Chapman ps->sock = sk; 696*fd558d18SJames Chapman ps->tunnel_sock = tunnel->sock; 697*fd558d18SJames Chapman 698*fd558d18SJames Chapman session->recv_skb = pppol2tp_recv; 699*fd558d18SJames Chapman session->session_close = pppol2tp_session_close; 700*fd558d18SJames Chapman 701*fd558d18SJames Chapman /* We need to know each time a skb is dropped from the reorder 702*fd558d18SJames Chapman * queue. 703*fd558d18SJames Chapman */ 704*fd558d18SJames Chapman session->ref = pppol2tp_session_sock_hold; 705*fd558d18SJames Chapman session->deref = pppol2tp_session_sock_put; 706*fd558d18SJames Chapman 707*fd558d18SJames Chapman /* If PMTU discovery was enabled, use the MTU that was discovered */ 708*fd558d18SJames Chapman dst = sk_dst_get(sk); 709*fd558d18SJames Chapman if (dst != NULL) { 710*fd558d18SJames Chapman u32 pmtu = dst_mtu(__sk_dst_get(sk)); 711*fd558d18SJames Chapman if (pmtu != 0) 712*fd558d18SJames Chapman session->mtu = session->mru = pmtu - 713*fd558d18SJames Chapman PPPOL2TP_HEADER_OVERHEAD; 714*fd558d18SJames Chapman dst_release(dst); 715*fd558d18SJames Chapman } 716*fd558d18SJames Chapman 717*fd558d18SJames Chapman /* Special case: if source & dest session_id == 0x0000, this 718*fd558d18SJames Chapman * socket is being created to manage the tunnel. Just set up 719*fd558d18SJames Chapman * the internal context for use by ioctl() and sockopt() 720*fd558d18SJames Chapman * handlers. 721*fd558d18SJames Chapman */ 722*fd558d18SJames Chapman if ((session->session_id == 0) && 723*fd558d18SJames Chapman (session->peer_session_id == 0)) { 724*fd558d18SJames Chapman error = 0; 725*fd558d18SJames Chapman goto out_no_ppp; 726*fd558d18SJames Chapman } 727*fd558d18SJames Chapman 728*fd558d18SJames Chapman /* The only header we need to worry about is the L2TP 729*fd558d18SJames Chapman * header. This size is different depending on whether 730*fd558d18SJames Chapman * sequence numbers are enabled for the data channel. 731*fd558d18SJames Chapman */ 732*fd558d18SJames Chapman po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; 733*fd558d18SJames Chapman 734*fd558d18SJames Chapman po->chan.private = sk; 735*fd558d18SJames Chapman po->chan.ops = &pppol2tp_chan_ops; 736*fd558d18SJames Chapman po->chan.mtu = session->mtu; 737*fd558d18SJames Chapman 738*fd558d18SJames Chapman error = ppp_register_net_channel(sock_net(sk), &po->chan); 739*fd558d18SJames Chapman if (error) 740*fd558d18SJames Chapman goto end; 741*fd558d18SJames Chapman 742*fd558d18SJames Chapman out_no_ppp: 743*fd558d18SJames Chapman /* This is how we get the session context from the socket. */ 744*fd558d18SJames Chapman sk->sk_user_data = session; 745*fd558d18SJames Chapman sk->sk_state = PPPOX_CONNECTED; 746*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 747*fd558d18SJames Chapman "%s: created\n", session->name); 748*fd558d18SJames Chapman 749*fd558d18SJames Chapman end: 750*fd558d18SJames Chapman release_sock(sk); 751*fd558d18SJames Chapman 752*fd558d18SJames Chapman return error; 753*fd558d18SJames Chapman } 754*fd558d18SJames Chapman 755*fd558d18SJames Chapman /* getname() support. 756*fd558d18SJames Chapman */ 757*fd558d18SJames Chapman static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, 758*fd558d18SJames Chapman int *usockaddr_len, int peer) 759*fd558d18SJames Chapman { 760*fd558d18SJames Chapman int len = sizeof(struct sockaddr_pppol2tp); 761*fd558d18SJames Chapman struct sockaddr_pppol2tp sp; 762*fd558d18SJames Chapman int error = 0; 763*fd558d18SJames Chapman struct l2tp_session *session; 764*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 765*fd558d18SJames Chapman struct sock *sk = sock->sk; 766*fd558d18SJames Chapman struct inet_sock *inet; 767*fd558d18SJames Chapman struct pppol2tp_session *pls; 768*fd558d18SJames Chapman 769*fd558d18SJames Chapman error = -ENOTCONN; 770*fd558d18SJames Chapman if (sk == NULL) 771*fd558d18SJames Chapman goto end; 772*fd558d18SJames Chapman if (sk->sk_state != PPPOX_CONNECTED) 773*fd558d18SJames Chapman goto end; 774*fd558d18SJames Chapman 775*fd558d18SJames Chapman error = -EBADF; 776*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 777*fd558d18SJames Chapman if (session == NULL) 778*fd558d18SJames Chapman goto end; 779*fd558d18SJames Chapman 780*fd558d18SJames Chapman pls = l2tp_session_priv(session); 781*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(pls->tunnel_sock); 782*fd558d18SJames Chapman if (tunnel == NULL) { 783*fd558d18SJames Chapman error = -EBADF; 784*fd558d18SJames Chapman goto end_put_sess; 785*fd558d18SJames Chapman } 786*fd558d18SJames Chapman 787*fd558d18SJames Chapman memset(&sp, 0, len); 788*fd558d18SJames Chapman sp.sa_family = AF_PPPOX; 789*fd558d18SJames Chapman sp.sa_protocol = PX_PROTO_OL2TP; 790*fd558d18SJames Chapman sp.pppol2tp.fd = tunnel->fd; 791*fd558d18SJames Chapman sp.pppol2tp.pid = pls->owner; 792*fd558d18SJames Chapman sp.pppol2tp.s_tunnel = tunnel->tunnel_id; 793*fd558d18SJames Chapman sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id; 794*fd558d18SJames Chapman sp.pppol2tp.s_session = session->session_id; 795*fd558d18SJames Chapman sp.pppol2tp.d_session = session->peer_session_id; 796*fd558d18SJames Chapman inet = inet_sk(sk); 797*fd558d18SJames Chapman sp.pppol2tp.addr.sin_family = AF_INET; 798*fd558d18SJames Chapman sp.pppol2tp.addr.sin_port = inet->inet_dport; 799*fd558d18SJames Chapman sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr; 800*fd558d18SJames Chapman 801*fd558d18SJames Chapman memcpy(uaddr, &sp, len); 802*fd558d18SJames Chapman 803*fd558d18SJames Chapman *usockaddr_len = len; 804*fd558d18SJames Chapman 805*fd558d18SJames Chapman sock_put(pls->tunnel_sock); 806*fd558d18SJames Chapman end_put_sess: 807*fd558d18SJames Chapman sock_put(sk); 808*fd558d18SJames Chapman error = 0; 809*fd558d18SJames Chapman 810*fd558d18SJames Chapman end: 811*fd558d18SJames Chapman return error; 812*fd558d18SJames Chapman } 813*fd558d18SJames Chapman 814*fd558d18SJames Chapman /**************************************************************************** 815*fd558d18SJames Chapman * ioctl() handlers. 816*fd558d18SJames Chapman * 817*fd558d18SJames Chapman * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP 818*fd558d18SJames Chapman * sockets. However, in order to control kernel tunnel features, we allow 819*fd558d18SJames Chapman * userspace to create a special "tunnel" PPPoX socket which is used for 820*fd558d18SJames Chapman * control only. Tunnel PPPoX sockets have session_id == 0 and simply allow 821*fd558d18SJames Chapman * the user application to issue L2TP setsockopt(), getsockopt() and ioctl() 822*fd558d18SJames Chapman * calls. 823*fd558d18SJames Chapman ****************************************************************************/ 824*fd558d18SJames Chapman 825*fd558d18SJames Chapman static void pppol2tp_copy_stats(struct pppol2tp_ioc_stats *dest, 826*fd558d18SJames Chapman struct l2tp_stats *stats) 827*fd558d18SJames Chapman { 828*fd558d18SJames Chapman dest->tx_packets = stats->tx_packets; 829*fd558d18SJames Chapman dest->tx_bytes = stats->tx_bytes; 830*fd558d18SJames Chapman dest->tx_errors = stats->tx_errors; 831*fd558d18SJames Chapman dest->rx_packets = stats->rx_packets; 832*fd558d18SJames Chapman dest->rx_bytes = stats->rx_bytes; 833*fd558d18SJames Chapman dest->rx_seq_discards = stats->rx_seq_discards; 834*fd558d18SJames Chapman dest->rx_oos_packets = stats->rx_oos_packets; 835*fd558d18SJames Chapman dest->rx_errors = stats->rx_errors; 836*fd558d18SJames Chapman } 837*fd558d18SJames Chapman 838*fd558d18SJames Chapman /* Session ioctl helper. 839*fd558d18SJames Chapman */ 840*fd558d18SJames Chapman static int pppol2tp_session_ioctl(struct l2tp_session *session, 841*fd558d18SJames Chapman unsigned int cmd, unsigned long arg) 842*fd558d18SJames Chapman { 843*fd558d18SJames Chapman struct ifreq ifr; 844*fd558d18SJames Chapman int err = 0; 845*fd558d18SJames Chapman struct sock *sk; 846*fd558d18SJames Chapman int val = (int) arg; 847*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 848*fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 849*fd558d18SJames Chapman struct pppol2tp_ioc_stats stats; 850*fd558d18SJames Chapman 851*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, 852*fd558d18SJames Chapman "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n", 853*fd558d18SJames Chapman session->name, cmd, arg); 854*fd558d18SJames Chapman 855*fd558d18SJames Chapman sk = ps->sock; 856*fd558d18SJames Chapman sock_hold(sk); 857*fd558d18SJames Chapman 858*fd558d18SJames Chapman switch (cmd) { 859*fd558d18SJames Chapman case SIOCGIFMTU: 860*fd558d18SJames Chapman err = -ENXIO; 861*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 862*fd558d18SJames Chapman break; 863*fd558d18SJames Chapman 864*fd558d18SJames Chapman err = -EFAULT; 865*fd558d18SJames Chapman if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) 866*fd558d18SJames Chapman break; 867*fd558d18SJames Chapman ifr.ifr_mtu = session->mtu; 868*fd558d18SJames Chapman if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq))) 869*fd558d18SJames Chapman break; 870*fd558d18SJames Chapman 871*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 872*fd558d18SJames Chapman "%s: get mtu=%d\n", session->name, session->mtu); 873*fd558d18SJames Chapman err = 0; 874*fd558d18SJames Chapman break; 875*fd558d18SJames Chapman 876*fd558d18SJames Chapman case SIOCSIFMTU: 877*fd558d18SJames Chapman err = -ENXIO; 878*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 879*fd558d18SJames Chapman break; 880*fd558d18SJames Chapman 881*fd558d18SJames Chapman err = -EFAULT; 882*fd558d18SJames Chapman if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) 883*fd558d18SJames Chapman break; 884*fd558d18SJames Chapman 885*fd558d18SJames Chapman session->mtu = ifr.ifr_mtu; 886*fd558d18SJames Chapman 887*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 888*fd558d18SJames Chapman "%s: set mtu=%d\n", session->name, session->mtu); 889*fd558d18SJames Chapman err = 0; 890*fd558d18SJames Chapman break; 891*fd558d18SJames Chapman 892*fd558d18SJames Chapman case PPPIOCGMRU: 893*fd558d18SJames Chapman err = -ENXIO; 894*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 895*fd558d18SJames Chapman break; 896*fd558d18SJames Chapman 897*fd558d18SJames Chapman err = -EFAULT; 898*fd558d18SJames Chapman if (put_user(session->mru, (int __user *) arg)) 899*fd558d18SJames Chapman break; 900*fd558d18SJames Chapman 901*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 902*fd558d18SJames Chapman "%s: get mru=%d\n", session->name, session->mru); 903*fd558d18SJames Chapman err = 0; 904*fd558d18SJames Chapman break; 905*fd558d18SJames Chapman 906*fd558d18SJames Chapman case PPPIOCSMRU: 907*fd558d18SJames Chapman err = -ENXIO; 908*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 909*fd558d18SJames Chapman break; 910*fd558d18SJames Chapman 911*fd558d18SJames Chapman err = -EFAULT; 912*fd558d18SJames Chapman if (get_user(val, (int __user *) arg)) 913*fd558d18SJames Chapman break; 914*fd558d18SJames Chapman 915*fd558d18SJames Chapman session->mru = val; 916*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 917*fd558d18SJames Chapman "%s: set mru=%d\n", session->name, session->mru); 918*fd558d18SJames Chapman err = 0; 919*fd558d18SJames Chapman break; 920*fd558d18SJames Chapman 921*fd558d18SJames Chapman case PPPIOCGFLAGS: 922*fd558d18SJames Chapman err = -EFAULT; 923*fd558d18SJames Chapman if (put_user(ps->flags, (int __user *) arg)) 924*fd558d18SJames Chapman break; 925*fd558d18SJames Chapman 926*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 927*fd558d18SJames Chapman "%s: get flags=%d\n", session->name, ps->flags); 928*fd558d18SJames Chapman err = 0; 929*fd558d18SJames Chapman break; 930*fd558d18SJames Chapman 931*fd558d18SJames Chapman case PPPIOCSFLAGS: 932*fd558d18SJames Chapman err = -EFAULT; 933*fd558d18SJames Chapman if (get_user(val, (int __user *) arg)) 934*fd558d18SJames Chapman break; 935*fd558d18SJames Chapman ps->flags = val; 936*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 937*fd558d18SJames Chapman "%s: set flags=%d\n", session->name, ps->flags); 938*fd558d18SJames Chapman err = 0; 939*fd558d18SJames Chapman break; 940*fd558d18SJames Chapman 941*fd558d18SJames Chapman case PPPIOCGL2TPSTATS: 942*fd558d18SJames Chapman err = -ENXIO; 943*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 944*fd558d18SJames Chapman break; 945*fd558d18SJames Chapman 946*fd558d18SJames Chapman memset(&stats, 0, sizeof(stats)); 947*fd558d18SJames Chapman stats.tunnel_id = tunnel->tunnel_id; 948*fd558d18SJames Chapman stats.session_id = session->session_id; 949*fd558d18SJames Chapman pppol2tp_copy_stats(&stats, &session->stats); 950*fd558d18SJames Chapman if (copy_to_user((void __user *) arg, &stats, 951*fd558d18SJames Chapman sizeof(stats))) 952*fd558d18SJames Chapman break; 953*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 954*fd558d18SJames Chapman "%s: get L2TP stats\n", session->name); 955*fd558d18SJames Chapman err = 0; 956*fd558d18SJames Chapman break; 957*fd558d18SJames Chapman 958*fd558d18SJames Chapman default: 959*fd558d18SJames Chapman err = -ENOSYS; 960*fd558d18SJames Chapman break; 961*fd558d18SJames Chapman } 962*fd558d18SJames Chapman 963*fd558d18SJames Chapman sock_put(sk); 964*fd558d18SJames Chapman 965*fd558d18SJames Chapman return err; 966*fd558d18SJames Chapman } 967*fd558d18SJames Chapman 968*fd558d18SJames Chapman /* Tunnel ioctl helper. 969*fd558d18SJames Chapman * 970*fd558d18SJames Chapman * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data 971*fd558d18SJames Chapman * specifies a session_id, the session ioctl handler is called. This allows an 972*fd558d18SJames Chapman * application to retrieve session stats via a tunnel socket. 973*fd558d18SJames Chapman */ 974*fd558d18SJames Chapman static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel, 975*fd558d18SJames Chapman unsigned int cmd, unsigned long arg) 976*fd558d18SJames Chapman { 977*fd558d18SJames Chapman int err = 0; 978*fd558d18SJames Chapman struct sock *sk; 979*fd558d18SJames Chapman struct pppol2tp_ioc_stats stats; 980*fd558d18SJames Chapman 981*fd558d18SJames Chapman PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, 982*fd558d18SJames Chapman "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", 983*fd558d18SJames Chapman tunnel->name, cmd, arg); 984*fd558d18SJames Chapman 985*fd558d18SJames Chapman sk = tunnel->sock; 986*fd558d18SJames Chapman sock_hold(sk); 987*fd558d18SJames Chapman 988*fd558d18SJames Chapman switch (cmd) { 989*fd558d18SJames Chapman case PPPIOCGL2TPSTATS: 990*fd558d18SJames Chapman err = -ENXIO; 991*fd558d18SJames Chapman if (!(sk->sk_state & PPPOX_CONNECTED)) 992*fd558d18SJames Chapman break; 993*fd558d18SJames Chapman 994*fd558d18SJames Chapman if (copy_from_user(&stats, (void __user *) arg, 995*fd558d18SJames Chapman sizeof(stats))) { 996*fd558d18SJames Chapman err = -EFAULT; 997*fd558d18SJames Chapman break; 998*fd558d18SJames Chapman } 999*fd558d18SJames Chapman if (stats.session_id != 0) { 1000*fd558d18SJames Chapman /* resend to session ioctl handler */ 1001*fd558d18SJames Chapman struct l2tp_session *session = 1002*fd558d18SJames Chapman l2tp_session_find(tunnel, stats.session_id); 1003*fd558d18SJames Chapman if (session != NULL) 1004*fd558d18SJames Chapman err = pppol2tp_session_ioctl(session, cmd, arg); 1005*fd558d18SJames Chapman else 1006*fd558d18SJames Chapman err = -EBADR; 1007*fd558d18SJames Chapman break; 1008*fd558d18SJames Chapman } 1009*fd558d18SJames Chapman #ifdef CONFIG_XFRM 1010*fd558d18SJames Chapman stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0; 1011*fd558d18SJames Chapman #endif 1012*fd558d18SJames Chapman pppol2tp_copy_stats(&stats, &tunnel->stats); 1013*fd558d18SJames Chapman if (copy_to_user((void __user *) arg, &stats, sizeof(stats))) { 1014*fd558d18SJames Chapman err = -EFAULT; 1015*fd558d18SJames Chapman break; 1016*fd558d18SJames Chapman } 1017*fd558d18SJames Chapman PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1018*fd558d18SJames Chapman "%s: get L2TP stats\n", tunnel->name); 1019*fd558d18SJames Chapman err = 0; 1020*fd558d18SJames Chapman break; 1021*fd558d18SJames Chapman 1022*fd558d18SJames Chapman default: 1023*fd558d18SJames Chapman err = -ENOSYS; 1024*fd558d18SJames Chapman break; 1025*fd558d18SJames Chapman } 1026*fd558d18SJames Chapman 1027*fd558d18SJames Chapman sock_put(sk); 1028*fd558d18SJames Chapman 1029*fd558d18SJames Chapman return err; 1030*fd558d18SJames Chapman } 1031*fd558d18SJames Chapman 1032*fd558d18SJames Chapman /* Main ioctl() handler. 1033*fd558d18SJames Chapman * Dispatch to tunnel or session helpers depending on the socket. 1034*fd558d18SJames Chapman */ 1035*fd558d18SJames Chapman static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, 1036*fd558d18SJames Chapman unsigned long arg) 1037*fd558d18SJames Chapman { 1038*fd558d18SJames Chapman struct sock *sk = sock->sk; 1039*fd558d18SJames Chapman struct l2tp_session *session; 1040*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1041*fd558d18SJames Chapman struct pppol2tp_session *ps; 1042*fd558d18SJames Chapman int err; 1043*fd558d18SJames Chapman 1044*fd558d18SJames Chapman if (!sk) 1045*fd558d18SJames Chapman return 0; 1046*fd558d18SJames Chapman 1047*fd558d18SJames Chapman err = -EBADF; 1048*fd558d18SJames Chapman if (sock_flag(sk, SOCK_DEAD) != 0) 1049*fd558d18SJames Chapman goto end; 1050*fd558d18SJames Chapman 1051*fd558d18SJames Chapman err = -ENOTCONN; 1052*fd558d18SJames Chapman if ((sk->sk_user_data == NULL) || 1053*fd558d18SJames Chapman (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)))) 1054*fd558d18SJames Chapman goto end; 1055*fd558d18SJames Chapman 1056*fd558d18SJames Chapman /* Get session context from the socket */ 1057*fd558d18SJames Chapman err = -EBADF; 1058*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 1059*fd558d18SJames Chapman if (session == NULL) 1060*fd558d18SJames Chapman goto end; 1061*fd558d18SJames Chapman 1062*fd558d18SJames Chapman /* Special case: if session's session_id is zero, treat ioctl as a 1063*fd558d18SJames Chapman * tunnel ioctl 1064*fd558d18SJames Chapman */ 1065*fd558d18SJames Chapman ps = l2tp_session_priv(session); 1066*fd558d18SJames Chapman if ((session->session_id == 0) && 1067*fd558d18SJames Chapman (session->peer_session_id == 0)) { 1068*fd558d18SJames Chapman err = -EBADF; 1069*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); 1070*fd558d18SJames Chapman if (tunnel == NULL) 1071*fd558d18SJames Chapman goto end_put_sess; 1072*fd558d18SJames Chapman 1073*fd558d18SJames Chapman err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); 1074*fd558d18SJames Chapman sock_put(ps->tunnel_sock); 1075*fd558d18SJames Chapman goto end_put_sess; 1076*fd558d18SJames Chapman } 1077*fd558d18SJames Chapman 1078*fd558d18SJames Chapman err = pppol2tp_session_ioctl(session, cmd, arg); 1079*fd558d18SJames Chapman 1080*fd558d18SJames Chapman end_put_sess: 1081*fd558d18SJames Chapman sock_put(sk); 1082*fd558d18SJames Chapman end: 1083*fd558d18SJames Chapman return err; 1084*fd558d18SJames Chapman } 1085*fd558d18SJames Chapman 1086*fd558d18SJames Chapman /***************************************************************************** 1087*fd558d18SJames Chapman * setsockopt() / getsockopt() support. 1088*fd558d18SJames Chapman * 1089*fd558d18SJames Chapman * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP 1090*fd558d18SJames Chapman * sockets. In order to control kernel tunnel features, we allow userspace to 1091*fd558d18SJames Chapman * create a special "tunnel" PPPoX socket which is used for control only. 1092*fd558d18SJames Chapman * Tunnel PPPoX sockets have session_id == 0 and simply allow the user 1093*fd558d18SJames Chapman * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls. 1094*fd558d18SJames Chapman *****************************************************************************/ 1095*fd558d18SJames Chapman 1096*fd558d18SJames Chapman /* Tunnel setsockopt() helper. 1097*fd558d18SJames Chapman */ 1098*fd558d18SJames Chapman static int pppol2tp_tunnel_setsockopt(struct sock *sk, 1099*fd558d18SJames Chapman struct l2tp_tunnel *tunnel, 1100*fd558d18SJames Chapman int optname, int val) 1101*fd558d18SJames Chapman { 1102*fd558d18SJames Chapman int err = 0; 1103*fd558d18SJames Chapman 1104*fd558d18SJames Chapman switch (optname) { 1105*fd558d18SJames Chapman case PPPOL2TP_SO_DEBUG: 1106*fd558d18SJames Chapman tunnel->debug = val; 1107*fd558d18SJames Chapman PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1108*fd558d18SJames Chapman "%s: set debug=%x\n", tunnel->name, tunnel->debug); 1109*fd558d18SJames Chapman break; 1110*fd558d18SJames Chapman 1111*fd558d18SJames Chapman default: 1112*fd558d18SJames Chapman err = -ENOPROTOOPT; 1113*fd558d18SJames Chapman break; 1114*fd558d18SJames Chapman } 1115*fd558d18SJames Chapman 1116*fd558d18SJames Chapman return err; 1117*fd558d18SJames Chapman } 1118*fd558d18SJames Chapman 1119*fd558d18SJames Chapman /* Session setsockopt helper. 1120*fd558d18SJames Chapman */ 1121*fd558d18SJames Chapman static int pppol2tp_session_setsockopt(struct sock *sk, 1122*fd558d18SJames Chapman struct l2tp_session *session, 1123*fd558d18SJames Chapman int optname, int val) 1124*fd558d18SJames Chapman { 1125*fd558d18SJames Chapman int err = 0; 1126*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 1127*fd558d18SJames Chapman 1128*fd558d18SJames Chapman switch (optname) { 1129*fd558d18SJames Chapman case PPPOL2TP_SO_RECVSEQ: 1130*fd558d18SJames Chapman if ((val != 0) && (val != 1)) { 1131*fd558d18SJames Chapman err = -EINVAL; 1132*fd558d18SJames Chapman break; 1133*fd558d18SJames Chapman } 1134*fd558d18SJames Chapman session->recv_seq = val ? -1 : 0; 1135*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1136*fd558d18SJames Chapman "%s: set recv_seq=%d\n", session->name, session->recv_seq); 1137*fd558d18SJames Chapman break; 1138*fd558d18SJames Chapman 1139*fd558d18SJames Chapman case PPPOL2TP_SO_SENDSEQ: 1140*fd558d18SJames Chapman if ((val != 0) && (val != 1)) { 1141*fd558d18SJames Chapman err = -EINVAL; 1142*fd558d18SJames Chapman break; 1143*fd558d18SJames Chapman } 1144*fd558d18SJames Chapman session->send_seq = val ? -1 : 0; 1145*fd558d18SJames Chapman { 1146*fd558d18SJames Chapman struct sock *ssk = ps->sock; 1147*fd558d18SJames Chapman struct pppox_sock *po = pppox_sk(ssk); 1148*fd558d18SJames Chapman po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : 1149*fd558d18SJames Chapman PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; 1150*fd558d18SJames Chapman } 1151*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1152*fd558d18SJames Chapman "%s: set send_seq=%d\n", session->name, session->send_seq); 1153*fd558d18SJames Chapman break; 1154*fd558d18SJames Chapman 1155*fd558d18SJames Chapman case PPPOL2TP_SO_LNSMODE: 1156*fd558d18SJames Chapman if ((val != 0) && (val != 1)) { 1157*fd558d18SJames Chapman err = -EINVAL; 1158*fd558d18SJames Chapman break; 1159*fd558d18SJames Chapman } 1160*fd558d18SJames Chapman session->lns_mode = val ? -1 : 0; 1161*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1162*fd558d18SJames Chapman "%s: set lns_mode=%d\n", session->name, session->lns_mode); 1163*fd558d18SJames Chapman break; 1164*fd558d18SJames Chapman 1165*fd558d18SJames Chapman case PPPOL2TP_SO_DEBUG: 1166*fd558d18SJames Chapman session->debug = val; 1167*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1168*fd558d18SJames Chapman "%s: set debug=%x\n", session->name, session->debug); 1169*fd558d18SJames Chapman break; 1170*fd558d18SJames Chapman 1171*fd558d18SJames Chapman case PPPOL2TP_SO_REORDERTO: 1172*fd558d18SJames Chapman session->reorder_timeout = msecs_to_jiffies(val); 1173*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1174*fd558d18SJames Chapman "%s: set reorder_timeout=%d\n", session->name, session->reorder_timeout); 1175*fd558d18SJames Chapman break; 1176*fd558d18SJames Chapman 1177*fd558d18SJames Chapman default: 1178*fd558d18SJames Chapman err = -ENOPROTOOPT; 1179*fd558d18SJames Chapman break; 1180*fd558d18SJames Chapman } 1181*fd558d18SJames Chapman 1182*fd558d18SJames Chapman return err; 1183*fd558d18SJames Chapman } 1184*fd558d18SJames Chapman 1185*fd558d18SJames Chapman /* Main setsockopt() entry point. 1186*fd558d18SJames Chapman * Does API checks, then calls either the tunnel or session setsockopt 1187*fd558d18SJames Chapman * handler, according to whether the PPPoL2TP socket is a for a regular 1188*fd558d18SJames Chapman * session or the special tunnel type. 1189*fd558d18SJames Chapman */ 1190*fd558d18SJames Chapman static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, 1191*fd558d18SJames Chapman char __user *optval, unsigned int optlen) 1192*fd558d18SJames Chapman { 1193*fd558d18SJames Chapman struct sock *sk = sock->sk; 1194*fd558d18SJames Chapman struct l2tp_session *session; 1195*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1196*fd558d18SJames Chapman struct pppol2tp_session *ps; 1197*fd558d18SJames Chapman int val; 1198*fd558d18SJames Chapman int err; 1199*fd558d18SJames Chapman 1200*fd558d18SJames Chapman if (level != SOL_PPPOL2TP) 1201*fd558d18SJames Chapman return udp_prot.setsockopt(sk, level, optname, optval, optlen); 1202*fd558d18SJames Chapman 1203*fd558d18SJames Chapman if (optlen < sizeof(int)) 1204*fd558d18SJames Chapman return -EINVAL; 1205*fd558d18SJames Chapman 1206*fd558d18SJames Chapman if (get_user(val, (int __user *)optval)) 1207*fd558d18SJames Chapman return -EFAULT; 1208*fd558d18SJames Chapman 1209*fd558d18SJames Chapman err = -ENOTCONN; 1210*fd558d18SJames Chapman if (sk->sk_user_data == NULL) 1211*fd558d18SJames Chapman goto end; 1212*fd558d18SJames Chapman 1213*fd558d18SJames Chapman /* Get session context from the socket */ 1214*fd558d18SJames Chapman err = -EBADF; 1215*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 1216*fd558d18SJames Chapman if (session == NULL) 1217*fd558d18SJames Chapman goto end; 1218*fd558d18SJames Chapman 1219*fd558d18SJames Chapman /* Special case: if session_id == 0x0000, treat as operation on tunnel 1220*fd558d18SJames Chapman */ 1221*fd558d18SJames Chapman ps = l2tp_session_priv(session); 1222*fd558d18SJames Chapman if ((session->session_id == 0) && 1223*fd558d18SJames Chapman (session->peer_session_id == 0)) { 1224*fd558d18SJames Chapman err = -EBADF; 1225*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); 1226*fd558d18SJames Chapman if (tunnel == NULL) 1227*fd558d18SJames Chapman goto end_put_sess; 1228*fd558d18SJames Chapman 1229*fd558d18SJames Chapman err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); 1230*fd558d18SJames Chapman sock_put(ps->tunnel_sock); 1231*fd558d18SJames Chapman } else 1232*fd558d18SJames Chapman err = pppol2tp_session_setsockopt(sk, session, optname, val); 1233*fd558d18SJames Chapman 1234*fd558d18SJames Chapman err = 0; 1235*fd558d18SJames Chapman 1236*fd558d18SJames Chapman end_put_sess: 1237*fd558d18SJames Chapman sock_put(sk); 1238*fd558d18SJames Chapman end: 1239*fd558d18SJames Chapman return err; 1240*fd558d18SJames Chapman } 1241*fd558d18SJames Chapman 1242*fd558d18SJames Chapman /* Tunnel getsockopt helper. Called with sock locked. 1243*fd558d18SJames Chapman */ 1244*fd558d18SJames Chapman static int pppol2tp_tunnel_getsockopt(struct sock *sk, 1245*fd558d18SJames Chapman struct l2tp_tunnel *tunnel, 1246*fd558d18SJames Chapman int optname, int *val) 1247*fd558d18SJames Chapman { 1248*fd558d18SJames Chapman int err = 0; 1249*fd558d18SJames Chapman 1250*fd558d18SJames Chapman switch (optname) { 1251*fd558d18SJames Chapman case PPPOL2TP_SO_DEBUG: 1252*fd558d18SJames Chapman *val = tunnel->debug; 1253*fd558d18SJames Chapman PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1254*fd558d18SJames Chapman "%s: get debug=%x\n", tunnel->name, tunnel->debug); 1255*fd558d18SJames Chapman break; 1256*fd558d18SJames Chapman 1257*fd558d18SJames Chapman default: 1258*fd558d18SJames Chapman err = -ENOPROTOOPT; 1259*fd558d18SJames Chapman break; 1260*fd558d18SJames Chapman } 1261*fd558d18SJames Chapman 1262*fd558d18SJames Chapman return err; 1263*fd558d18SJames Chapman } 1264*fd558d18SJames Chapman 1265*fd558d18SJames Chapman /* Session getsockopt helper. Called with sock locked. 1266*fd558d18SJames Chapman */ 1267*fd558d18SJames Chapman static int pppol2tp_session_getsockopt(struct sock *sk, 1268*fd558d18SJames Chapman struct l2tp_session *session, 1269*fd558d18SJames Chapman int optname, int *val) 1270*fd558d18SJames Chapman { 1271*fd558d18SJames Chapman int err = 0; 1272*fd558d18SJames Chapman 1273*fd558d18SJames Chapman switch (optname) { 1274*fd558d18SJames Chapman case PPPOL2TP_SO_RECVSEQ: 1275*fd558d18SJames Chapman *val = session->recv_seq; 1276*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1277*fd558d18SJames Chapman "%s: get recv_seq=%d\n", session->name, *val); 1278*fd558d18SJames Chapman break; 1279*fd558d18SJames Chapman 1280*fd558d18SJames Chapman case PPPOL2TP_SO_SENDSEQ: 1281*fd558d18SJames Chapman *val = session->send_seq; 1282*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1283*fd558d18SJames Chapman "%s: get send_seq=%d\n", session->name, *val); 1284*fd558d18SJames Chapman break; 1285*fd558d18SJames Chapman 1286*fd558d18SJames Chapman case PPPOL2TP_SO_LNSMODE: 1287*fd558d18SJames Chapman *val = session->lns_mode; 1288*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1289*fd558d18SJames Chapman "%s: get lns_mode=%d\n", session->name, *val); 1290*fd558d18SJames Chapman break; 1291*fd558d18SJames Chapman 1292*fd558d18SJames Chapman case PPPOL2TP_SO_DEBUG: 1293*fd558d18SJames Chapman *val = session->debug; 1294*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1295*fd558d18SJames Chapman "%s: get debug=%d\n", session->name, *val); 1296*fd558d18SJames Chapman break; 1297*fd558d18SJames Chapman 1298*fd558d18SJames Chapman case PPPOL2TP_SO_REORDERTO: 1299*fd558d18SJames Chapman *val = (int) jiffies_to_msecs(session->reorder_timeout); 1300*fd558d18SJames Chapman PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, 1301*fd558d18SJames Chapman "%s: get reorder_timeout=%d\n", session->name, *val); 1302*fd558d18SJames Chapman break; 1303*fd558d18SJames Chapman 1304*fd558d18SJames Chapman default: 1305*fd558d18SJames Chapman err = -ENOPROTOOPT; 1306*fd558d18SJames Chapman } 1307*fd558d18SJames Chapman 1308*fd558d18SJames Chapman return err; 1309*fd558d18SJames Chapman } 1310*fd558d18SJames Chapman 1311*fd558d18SJames Chapman /* Main getsockopt() entry point. 1312*fd558d18SJames Chapman * Does API checks, then calls either the tunnel or session getsockopt 1313*fd558d18SJames Chapman * handler, according to whether the PPPoX socket is a for a regular session 1314*fd558d18SJames Chapman * or the special tunnel type. 1315*fd558d18SJames Chapman */ 1316*fd558d18SJames Chapman static int pppol2tp_getsockopt(struct socket *sock, int level, 1317*fd558d18SJames Chapman int optname, char __user *optval, int __user *optlen) 1318*fd558d18SJames Chapman { 1319*fd558d18SJames Chapman struct sock *sk = sock->sk; 1320*fd558d18SJames Chapman struct l2tp_session *session; 1321*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1322*fd558d18SJames Chapman int val, len; 1323*fd558d18SJames Chapman int err; 1324*fd558d18SJames Chapman struct pppol2tp_session *ps; 1325*fd558d18SJames Chapman 1326*fd558d18SJames Chapman if (level != SOL_PPPOL2TP) 1327*fd558d18SJames Chapman return udp_prot.getsockopt(sk, level, optname, optval, optlen); 1328*fd558d18SJames Chapman 1329*fd558d18SJames Chapman if (get_user(len, (int __user *) optlen)) 1330*fd558d18SJames Chapman return -EFAULT; 1331*fd558d18SJames Chapman 1332*fd558d18SJames Chapman len = min_t(unsigned int, len, sizeof(int)); 1333*fd558d18SJames Chapman 1334*fd558d18SJames Chapman if (len < 0) 1335*fd558d18SJames Chapman return -EINVAL; 1336*fd558d18SJames Chapman 1337*fd558d18SJames Chapman err = -ENOTCONN; 1338*fd558d18SJames Chapman if (sk->sk_user_data == NULL) 1339*fd558d18SJames Chapman goto end; 1340*fd558d18SJames Chapman 1341*fd558d18SJames Chapman /* Get the session context */ 1342*fd558d18SJames Chapman err = -EBADF; 1343*fd558d18SJames Chapman session = pppol2tp_sock_to_session(sk); 1344*fd558d18SJames Chapman if (session == NULL) 1345*fd558d18SJames Chapman goto end; 1346*fd558d18SJames Chapman 1347*fd558d18SJames Chapman /* Special case: if session_id == 0x0000, treat as operation on tunnel */ 1348*fd558d18SJames Chapman ps = l2tp_session_priv(session); 1349*fd558d18SJames Chapman if ((session->session_id == 0) && 1350*fd558d18SJames Chapman (session->peer_session_id == 0)) { 1351*fd558d18SJames Chapman err = -EBADF; 1352*fd558d18SJames Chapman tunnel = l2tp_sock_to_tunnel(ps->tunnel_sock); 1353*fd558d18SJames Chapman if (tunnel == NULL) 1354*fd558d18SJames Chapman goto end_put_sess; 1355*fd558d18SJames Chapman 1356*fd558d18SJames Chapman err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); 1357*fd558d18SJames Chapman sock_put(ps->tunnel_sock); 1358*fd558d18SJames Chapman } else 1359*fd558d18SJames Chapman err = pppol2tp_session_getsockopt(sk, session, optname, &val); 1360*fd558d18SJames Chapman 1361*fd558d18SJames Chapman err = -EFAULT; 1362*fd558d18SJames Chapman if (put_user(len, (int __user *) optlen)) 1363*fd558d18SJames Chapman goto end_put_sess; 1364*fd558d18SJames Chapman 1365*fd558d18SJames Chapman if (copy_to_user((void __user *) optval, &val, len)) 1366*fd558d18SJames Chapman goto end_put_sess; 1367*fd558d18SJames Chapman 1368*fd558d18SJames Chapman err = 0; 1369*fd558d18SJames Chapman 1370*fd558d18SJames Chapman end_put_sess: 1371*fd558d18SJames Chapman sock_put(sk); 1372*fd558d18SJames Chapman end: 1373*fd558d18SJames Chapman return err; 1374*fd558d18SJames Chapman } 1375*fd558d18SJames Chapman 1376*fd558d18SJames Chapman /***************************************************************************** 1377*fd558d18SJames Chapman * /proc filesystem for debug 1378*fd558d18SJames Chapman *****************************************************************************/ 1379*fd558d18SJames Chapman 1380*fd558d18SJames Chapman static unsigned int pppol2tp_net_id; 1381*fd558d18SJames Chapman 1382*fd558d18SJames Chapman #ifdef CONFIG_PROC_FS 1383*fd558d18SJames Chapman 1384*fd558d18SJames Chapman struct pppol2tp_seq_data { 1385*fd558d18SJames Chapman struct seq_net_private p; 1386*fd558d18SJames Chapman int tunnel_idx; /* current tunnel */ 1387*fd558d18SJames Chapman int session_idx; /* index of session within current tunnel */ 1388*fd558d18SJames Chapman struct l2tp_tunnel *tunnel; 1389*fd558d18SJames Chapman struct l2tp_session *session; /* NULL means get next tunnel */ 1390*fd558d18SJames Chapman }; 1391*fd558d18SJames Chapman 1392*fd558d18SJames Chapman static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) 1393*fd558d18SJames Chapman { 1394*fd558d18SJames Chapman pd->tunnel = l2tp_tunnel_find_nth(net, pd->tunnel_idx); 1395*fd558d18SJames Chapman pd->tunnel_idx++; 1396*fd558d18SJames Chapman } 1397*fd558d18SJames Chapman 1398*fd558d18SJames Chapman static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd) 1399*fd558d18SJames Chapman { 1400*fd558d18SJames Chapman pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx); 1401*fd558d18SJames Chapman pd->session_idx++; 1402*fd558d18SJames Chapman if (pd->session == NULL) { 1403*fd558d18SJames Chapman pd->session_idx = 0; 1404*fd558d18SJames Chapman pppol2tp_next_tunnel(net, pd); 1405*fd558d18SJames Chapman } 1406*fd558d18SJames Chapman } 1407*fd558d18SJames Chapman 1408*fd558d18SJames Chapman static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) 1409*fd558d18SJames Chapman { 1410*fd558d18SJames Chapman struct pppol2tp_seq_data *pd = SEQ_START_TOKEN; 1411*fd558d18SJames Chapman loff_t pos = *offs; 1412*fd558d18SJames Chapman struct net *net; 1413*fd558d18SJames Chapman 1414*fd558d18SJames Chapman if (!pos) 1415*fd558d18SJames Chapman goto out; 1416*fd558d18SJames Chapman 1417*fd558d18SJames Chapman BUG_ON(m->private == NULL); 1418*fd558d18SJames Chapman pd = m->private; 1419*fd558d18SJames Chapman net = seq_file_net(m); 1420*fd558d18SJames Chapman 1421*fd558d18SJames Chapman if (pd->tunnel == NULL) 1422*fd558d18SJames Chapman pppol2tp_next_tunnel(net, pd); 1423*fd558d18SJames Chapman else 1424*fd558d18SJames Chapman pppol2tp_next_session(net, pd); 1425*fd558d18SJames Chapman 1426*fd558d18SJames Chapman /* NULL tunnel and session indicates end of list */ 1427*fd558d18SJames Chapman if ((pd->tunnel == NULL) && (pd->session == NULL)) 1428*fd558d18SJames Chapman pd = NULL; 1429*fd558d18SJames Chapman 1430*fd558d18SJames Chapman out: 1431*fd558d18SJames Chapman return pd; 1432*fd558d18SJames Chapman } 1433*fd558d18SJames Chapman 1434*fd558d18SJames Chapman static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos) 1435*fd558d18SJames Chapman { 1436*fd558d18SJames Chapman (*pos)++; 1437*fd558d18SJames Chapman return NULL; 1438*fd558d18SJames Chapman } 1439*fd558d18SJames Chapman 1440*fd558d18SJames Chapman static void pppol2tp_seq_stop(struct seq_file *p, void *v) 1441*fd558d18SJames Chapman { 1442*fd558d18SJames Chapman /* nothing to do */ 1443*fd558d18SJames Chapman } 1444*fd558d18SJames Chapman 1445*fd558d18SJames Chapman static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v) 1446*fd558d18SJames Chapman { 1447*fd558d18SJames Chapman struct l2tp_tunnel *tunnel = v; 1448*fd558d18SJames Chapman 1449*fd558d18SJames Chapman seq_printf(m, "\nTUNNEL '%s', %c %d\n", 1450*fd558d18SJames Chapman tunnel->name, 1451*fd558d18SJames Chapman (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N', 1452*fd558d18SJames Chapman atomic_read(&tunnel->ref_count) - 1); 1453*fd558d18SJames Chapman seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n", 1454*fd558d18SJames Chapman tunnel->debug, 1455*fd558d18SJames Chapman (unsigned long long)tunnel->stats.tx_packets, 1456*fd558d18SJames Chapman (unsigned long long)tunnel->stats.tx_bytes, 1457*fd558d18SJames Chapman (unsigned long long)tunnel->stats.tx_errors, 1458*fd558d18SJames Chapman (unsigned long long)tunnel->stats.rx_packets, 1459*fd558d18SJames Chapman (unsigned long long)tunnel->stats.rx_bytes, 1460*fd558d18SJames Chapman (unsigned long long)tunnel->stats.rx_errors); 1461*fd558d18SJames Chapman } 1462*fd558d18SJames Chapman 1463*fd558d18SJames Chapman static void pppol2tp_seq_session_show(struct seq_file *m, void *v) 1464*fd558d18SJames Chapman { 1465*fd558d18SJames Chapman struct l2tp_session *session = v; 1466*fd558d18SJames Chapman struct l2tp_tunnel *tunnel = session->tunnel; 1467*fd558d18SJames Chapman struct pppol2tp_session *ps = l2tp_session_priv(session); 1468*fd558d18SJames Chapman u32 ip = 0; 1469*fd558d18SJames Chapman u16 port = 0; 1470*fd558d18SJames Chapman 1471*fd558d18SJames Chapman if (tunnel->sock) { 1472*fd558d18SJames Chapman struct inet_sock *inet = inet_sk(tunnel->sock); 1473*fd558d18SJames Chapman ip = ntohl(inet->inet_saddr); 1474*fd558d18SJames Chapman port = ntohs(inet->inet_sport); 1475*fd558d18SJames Chapman } 1476*fd558d18SJames Chapman 1477*fd558d18SJames Chapman seq_printf(m, " SESSION '%s' %08X/%d %04X/%04X -> " 1478*fd558d18SJames Chapman "%04X/%04X %d %c\n", 1479*fd558d18SJames Chapman session->name, ip, port, 1480*fd558d18SJames Chapman tunnel->tunnel_id, 1481*fd558d18SJames Chapman session->session_id, 1482*fd558d18SJames Chapman tunnel->peer_tunnel_id, 1483*fd558d18SJames Chapman session->peer_session_id, 1484*fd558d18SJames Chapman ps->sock->sk_state, 1485*fd558d18SJames Chapman (session == ps->sock->sk_user_data) ? 1486*fd558d18SJames Chapman 'Y' : 'N'); 1487*fd558d18SJames Chapman seq_printf(m, " %d/%d/%c/%c/%s %08x %u\n", 1488*fd558d18SJames Chapman session->mtu, session->mru, 1489*fd558d18SJames Chapman session->recv_seq ? 'R' : '-', 1490*fd558d18SJames Chapman session->send_seq ? 'S' : '-', 1491*fd558d18SJames Chapman session->lns_mode ? "LNS" : "LAC", 1492*fd558d18SJames Chapman session->debug, 1493*fd558d18SJames Chapman jiffies_to_msecs(session->reorder_timeout)); 1494*fd558d18SJames Chapman seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n", 1495*fd558d18SJames Chapman session->nr, session->ns, 1496*fd558d18SJames Chapman (unsigned long long)session->stats.tx_packets, 1497*fd558d18SJames Chapman (unsigned long long)session->stats.tx_bytes, 1498*fd558d18SJames Chapman (unsigned long long)session->stats.tx_errors, 1499*fd558d18SJames Chapman (unsigned long long)session->stats.rx_packets, 1500*fd558d18SJames Chapman (unsigned long long)session->stats.rx_bytes, 1501*fd558d18SJames Chapman (unsigned long long)session->stats.rx_errors); 1502*fd558d18SJames Chapman } 1503*fd558d18SJames Chapman 1504*fd558d18SJames Chapman static int pppol2tp_seq_show(struct seq_file *m, void *v) 1505*fd558d18SJames Chapman { 1506*fd558d18SJames Chapman struct pppol2tp_seq_data *pd = v; 1507*fd558d18SJames Chapman 1508*fd558d18SJames Chapman /* display header on line 1 */ 1509*fd558d18SJames Chapman if (v == SEQ_START_TOKEN) { 1510*fd558d18SJames Chapman seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n"); 1511*fd558d18SJames Chapman seq_puts(m, "TUNNEL name, user-data-ok session-count\n"); 1512*fd558d18SJames Chapman seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); 1513*fd558d18SJames Chapman seq_puts(m, " SESSION name, addr/port src-tid/sid " 1514*fd558d18SJames Chapman "dest-tid/sid state user-data-ok\n"); 1515*fd558d18SJames Chapman seq_puts(m, " mtu/mru/rcvseq/sendseq/lns debug reorderto\n"); 1516*fd558d18SJames Chapman seq_puts(m, " nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); 1517*fd558d18SJames Chapman goto out; 1518*fd558d18SJames Chapman } 1519*fd558d18SJames Chapman 1520*fd558d18SJames Chapman /* Show the tunnel or session context. 1521*fd558d18SJames Chapman */ 1522*fd558d18SJames Chapman if (pd->session == NULL) 1523*fd558d18SJames Chapman pppol2tp_seq_tunnel_show(m, pd->tunnel); 1524*fd558d18SJames Chapman else 1525*fd558d18SJames Chapman pppol2tp_seq_session_show(m, pd->session); 1526*fd558d18SJames Chapman 1527*fd558d18SJames Chapman out: 1528*fd558d18SJames Chapman return 0; 1529*fd558d18SJames Chapman } 1530*fd558d18SJames Chapman 1531*fd558d18SJames Chapman static const struct seq_operations pppol2tp_seq_ops = { 1532*fd558d18SJames Chapman .start = pppol2tp_seq_start, 1533*fd558d18SJames Chapman .next = pppol2tp_seq_next, 1534*fd558d18SJames Chapman .stop = pppol2tp_seq_stop, 1535*fd558d18SJames Chapman .show = pppol2tp_seq_show, 1536*fd558d18SJames Chapman }; 1537*fd558d18SJames Chapman 1538*fd558d18SJames Chapman /* Called when our /proc file is opened. We allocate data for use when 1539*fd558d18SJames Chapman * iterating our tunnel / session contexts and store it in the private 1540*fd558d18SJames Chapman * data of the seq_file. 1541*fd558d18SJames Chapman */ 1542*fd558d18SJames Chapman static int pppol2tp_proc_open(struct inode *inode, struct file *file) 1543*fd558d18SJames Chapman { 1544*fd558d18SJames Chapman return seq_open_net(inode, file, &pppol2tp_seq_ops, 1545*fd558d18SJames Chapman sizeof(struct pppol2tp_seq_data)); 1546*fd558d18SJames Chapman } 1547*fd558d18SJames Chapman 1548*fd558d18SJames Chapman static const struct file_operations pppol2tp_proc_fops = { 1549*fd558d18SJames Chapman .owner = THIS_MODULE, 1550*fd558d18SJames Chapman .open = pppol2tp_proc_open, 1551*fd558d18SJames Chapman .read = seq_read, 1552*fd558d18SJames Chapman .llseek = seq_lseek, 1553*fd558d18SJames Chapman .release = seq_release_net, 1554*fd558d18SJames Chapman }; 1555*fd558d18SJames Chapman 1556*fd558d18SJames Chapman #endif /* CONFIG_PROC_FS */ 1557*fd558d18SJames Chapman 1558*fd558d18SJames Chapman /***************************************************************************** 1559*fd558d18SJames Chapman * Network namespace 1560*fd558d18SJames Chapman *****************************************************************************/ 1561*fd558d18SJames Chapman 1562*fd558d18SJames Chapman static __net_init int pppol2tp_init_net(struct net *net) 1563*fd558d18SJames Chapman { 1564*fd558d18SJames Chapman struct proc_dir_entry *pde; 1565*fd558d18SJames Chapman int err = 0; 1566*fd558d18SJames Chapman 1567*fd558d18SJames Chapman pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops); 1568*fd558d18SJames Chapman if (!pde) { 1569*fd558d18SJames Chapman err = -ENOMEM; 1570*fd558d18SJames Chapman goto out; 1571*fd558d18SJames Chapman } 1572*fd558d18SJames Chapman 1573*fd558d18SJames Chapman out: 1574*fd558d18SJames Chapman return err; 1575*fd558d18SJames Chapman } 1576*fd558d18SJames Chapman 1577*fd558d18SJames Chapman static __net_exit void pppol2tp_exit_net(struct net *net) 1578*fd558d18SJames Chapman { 1579*fd558d18SJames Chapman proc_net_remove(net, "pppol2tp"); 1580*fd558d18SJames Chapman } 1581*fd558d18SJames Chapman 1582*fd558d18SJames Chapman static struct pernet_operations pppol2tp_net_ops = { 1583*fd558d18SJames Chapman .init = pppol2tp_init_net, 1584*fd558d18SJames Chapman .exit = pppol2tp_exit_net, 1585*fd558d18SJames Chapman .id = &pppol2tp_net_id, 1586*fd558d18SJames Chapman }; 1587*fd558d18SJames Chapman 1588*fd558d18SJames Chapman /***************************************************************************** 1589*fd558d18SJames Chapman * Init and cleanup 1590*fd558d18SJames Chapman *****************************************************************************/ 1591*fd558d18SJames Chapman 1592*fd558d18SJames Chapman static const struct proto_ops pppol2tp_ops = { 1593*fd558d18SJames Chapman .family = AF_PPPOX, 1594*fd558d18SJames Chapman .owner = THIS_MODULE, 1595*fd558d18SJames Chapman .release = pppol2tp_release, 1596*fd558d18SJames Chapman .bind = sock_no_bind, 1597*fd558d18SJames Chapman .connect = pppol2tp_connect, 1598*fd558d18SJames Chapman .socketpair = sock_no_socketpair, 1599*fd558d18SJames Chapman .accept = sock_no_accept, 1600*fd558d18SJames Chapman .getname = pppol2tp_getname, 1601*fd558d18SJames Chapman .poll = datagram_poll, 1602*fd558d18SJames Chapman .listen = sock_no_listen, 1603*fd558d18SJames Chapman .shutdown = sock_no_shutdown, 1604*fd558d18SJames Chapman .setsockopt = pppol2tp_setsockopt, 1605*fd558d18SJames Chapman .getsockopt = pppol2tp_getsockopt, 1606*fd558d18SJames Chapman .sendmsg = pppol2tp_sendmsg, 1607*fd558d18SJames Chapman .recvmsg = pppol2tp_recvmsg, 1608*fd558d18SJames Chapman .mmap = sock_no_mmap, 1609*fd558d18SJames Chapman .ioctl = pppox_ioctl, 1610*fd558d18SJames Chapman }; 1611*fd558d18SJames Chapman 1612*fd558d18SJames Chapman static struct pppox_proto pppol2tp_proto = { 1613*fd558d18SJames Chapman .create = pppol2tp_create, 1614*fd558d18SJames Chapman .ioctl = pppol2tp_ioctl 1615*fd558d18SJames Chapman }; 1616*fd558d18SJames Chapman 1617*fd558d18SJames Chapman static int __init pppol2tp_init(void) 1618*fd558d18SJames Chapman { 1619*fd558d18SJames Chapman int err; 1620*fd558d18SJames Chapman 1621*fd558d18SJames Chapman err = register_pernet_device(&pppol2tp_net_ops); 1622*fd558d18SJames Chapman if (err) 1623*fd558d18SJames Chapman goto out; 1624*fd558d18SJames Chapman 1625*fd558d18SJames Chapman err = proto_register(&pppol2tp_sk_proto, 0); 1626*fd558d18SJames Chapman if (err) 1627*fd558d18SJames Chapman goto out_unregister_pppol2tp_pernet; 1628*fd558d18SJames Chapman 1629*fd558d18SJames Chapman err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto); 1630*fd558d18SJames Chapman if (err) 1631*fd558d18SJames Chapman goto out_unregister_pppol2tp_proto; 1632*fd558d18SJames Chapman 1633*fd558d18SJames Chapman printk(KERN_INFO "PPPoL2TP kernel driver, %s\n", 1634*fd558d18SJames Chapman PPPOL2TP_DRV_VERSION); 1635*fd558d18SJames Chapman 1636*fd558d18SJames Chapman out: 1637*fd558d18SJames Chapman return err; 1638*fd558d18SJames Chapman out_unregister_pppol2tp_proto: 1639*fd558d18SJames Chapman proto_unregister(&pppol2tp_sk_proto); 1640*fd558d18SJames Chapman out_unregister_pppol2tp_pernet: 1641*fd558d18SJames Chapman unregister_pernet_device(&pppol2tp_net_ops); 1642*fd558d18SJames Chapman goto out; 1643*fd558d18SJames Chapman } 1644*fd558d18SJames Chapman 1645*fd558d18SJames Chapman static void __exit pppol2tp_exit(void) 1646*fd558d18SJames Chapman { 1647*fd558d18SJames Chapman unregister_pppox_proto(PX_PROTO_OL2TP); 1648*fd558d18SJames Chapman proto_unregister(&pppol2tp_sk_proto); 1649*fd558d18SJames Chapman unregister_pernet_device(&pppol2tp_net_ops); 1650*fd558d18SJames Chapman } 1651*fd558d18SJames Chapman 1652*fd558d18SJames Chapman module_init(pppol2tp_init); 1653*fd558d18SJames Chapman module_exit(pppol2tp_exit); 1654*fd558d18SJames Chapman 1655*fd558d18SJames Chapman MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); 1656*fd558d18SJames Chapman MODULE_DESCRIPTION("PPP over L2TP over UDP"); 1657*fd558d18SJames Chapman MODULE_LICENSE("GPL"); 1658*fd558d18SJames Chapman MODULE_VERSION(PPPOL2TP_DRV_VERSION); 1659