Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193941
b: refs/heads/master
c: e0d4435
h: refs/heads/master
i:
  193939: e9c71ae
v: v3
  • Loading branch information
James Chapman authored and David S. Miller committed Apr 3, 2010
1 parent 9540cd6 commit 97b42ea
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 47 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f7faffa3ff8ef6ae712ef16312b8a2aa7a1c95fe
refs/heads/master: e0d4435f93905f517003cfa7328a36ea19788147
14 changes: 14 additions & 0 deletions trunk/include/linux/if_pppol2tp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ struct pppol2tp_addr {
__u16 d_tunnel, d_session; /* For sending outgoing packets */
};

/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
* bits. So we need a different sockaddr structure.
*/
struct pppol2tpv3_addr {
pid_t pid; /* pid that owns the fd.
* 0 => current */
int fd; /* FD of UDP or IP socket to use */

struct sockaddr_in addr; /* IP address and port to send to */

__u32 s_tunnel, s_session; /* For matching incoming packets */
__u32 d_tunnel, d_session; /* For sending outgoing packets */
};

/* Socket options:
* DEBUG - bitmask of debug message categories
* SENDSEQ - 0 => don't send packets with sequence numbers
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/linux/if_pppox.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ struct sockaddr_pppol2tp {
struct pppol2tp_addr pppol2tp;
}__attribute__ ((packed));

/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
* bits. So we need a different sockaddr structure.
*/
struct sockaddr_pppol2tpv3 {
sa_family_t sa_family; /* address family, AF_PPPOX */
unsigned int sa_protocol; /* protocol identifier */
struct pppol2tpv3_addr pppol2tp;
} __attribute__ ((packed));

/*********************************************************************
*
* ioctl interface for defining forwarding of connections
Expand Down
120 changes: 74 additions & 46 deletions trunk/net/l2tp/l2tp_ppp.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,17 +291,6 @@ static void pppol2tp_session_sock_put(struct l2tp_session *session)
* Transmit handling
***********************************************************************/

/* Tell how big L2TP headers are for a particular session. This
* depends on whether sequence numbers are being used.
*/
static inline int pppol2tp_l2tp_header_len(struct l2tp_session *session)
{
if (session->send_seq)
return PPPOL2TP_L2TP_HDR_SIZE_SEQ;

return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
}

/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here
* when a user application does a sendmsg() on the session socket. L2TP and
* PPP headers must be inserted into the user's data.
Expand Down Expand Up @@ -394,7 +383,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
static const u8 ppph[2] = { 0xff, 0x03 };
struct sock *sk = (struct sock *) chan->private;
struct sock *sk_tun;
int hdr_len;
struct l2tp_session *session;
struct l2tp_tunnel *tunnel;
struct pppol2tp_session *ps;
Expand All @@ -417,9 +405,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
if (tunnel == NULL)
goto abort_put_sess;

/* What header length is configured for this session? */
hdr_len = pppol2tp_l2tp_header_len(session);

old_headroom = skb_headroom(skb);
if (skb_cow_head(skb, sizeof(ppph)))
goto abort_put_sess_tun;
Expand All @@ -432,7 +417,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
skb->data[0] = ppph[0];
skb->data[1] = ppph[1];

l2tp_xmit_skb(session, skb, hdr_len);
l2tp_xmit_skb(session, skb, session->hdr_len);

sock_put(sk_tun);
sock_put(sk);
Expand Down Expand Up @@ -615,13 +600,18 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
{
struct sock *sk = sock->sk;
struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
struct sockaddr_pppol2tpv3 *sp3 = (struct sockaddr_pppol2tpv3 *) uservaddr;
struct pppox_sock *po = pppox_sk(sk);
struct l2tp_session *session = NULL;
struct l2tp_tunnel *tunnel;
struct pppol2tp_session *ps;
struct dst_entry *dst;
struct l2tp_session_cfg cfg = { 0, };
int error = 0;
u32 tunnel_id, peer_tunnel_id;
u32 session_id, peer_session_id;
int ver = 2;
int fd;

lock_sock(sk);

Expand All @@ -639,21 +629,40 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
if (sk->sk_user_data)
goto end; /* socket is already attached */

/* Don't bind if s_tunnel is 0 */
/* Get params from socket address. Handle L2TPv2 and L2TPv3 */
if (sockaddr_len == sizeof(struct sockaddr_pppol2tp)) {
fd = sp->pppol2tp.fd;
tunnel_id = sp->pppol2tp.s_tunnel;
peer_tunnel_id = sp->pppol2tp.d_tunnel;
session_id = sp->pppol2tp.s_session;
peer_session_id = sp->pppol2tp.d_session;
} else if (sockaddr_len == sizeof(struct sockaddr_pppol2tpv3)) {
ver = 3;
fd = sp3->pppol2tp.fd;
tunnel_id = sp3->pppol2tp.s_tunnel;
peer_tunnel_id = sp3->pppol2tp.d_tunnel;
session_id = sp3->pppol2tp.s_session;
peer_session_id = sp3->pppol2tp.d_session;
} else {
error = -EINVAL;
goto end; /* bad socket address */
}

/* Don't bind if tunnel_id is 0 */
error = -EINVAL;
if (sp->pppol2tp.s_tunnel == 0)
if (tunnel_id == 0)
goto end;

/* Special case: create tunnel context if s_session and
* d_session is 0. Otherwise look up tunnel using supplied
/* Special case: create tunnel context if session_id and
* peer_session_id is 0. Otherwise look up tunnel using supplied
* tunnel id.
*/
if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
error = l2tp_tunnel_create(sock_net(sk), sp->pppol2tp.fd, 2, sp->pppol2tp.s_tunnel, sp->pppol2tp.d_tunnel, NULL, &tunnel);
if ((session_id == 0) && (peer_session_id == 0)) {
error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, NULL, &tunnel);
if (error < 0)
goto end;
} else {
tunnel = l2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel);
tunnel = l2tp_tunnel_find(sock_net(sk), tunnel_id);

/* Error if we can't find the tunnel */
error = -ENOENT;
Expand All @@ -670,20 +679,21 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,

/* Check that this session doesn't already exist */
error = -EEXIST;
session = l2tp_session_find(sock_net(sk), tunnel, sp->pppol2tp.s_session);
session = l2tp_session_find(sock_net(sk), tunnel, session_id);
if (session != NULL)
goto end;

/* Default MTU must allow space for UDP/L2TP/PPP
* headers.
*/
cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
/* Default MTU values. */
if (cfg.mtu == 0)
cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
if (cfg.mru == 0)
cfg.mru = cfg.mtu;
cfg.debug = tunnel->debug;

/* Allocate and initialize a new session context. */
session = l2tp_session_create(sizeof(struct pppol2tp_session),
tunnel, sp->pppol2tp.s_session,
sp->pppol2tp.d_session, &cfg);
tunnel, session_id,
peer_session_id, &cfg);
if (session == NULL) {
error = -ENOMEM;
goto end;
Expand Down Expand Up @@ -756,8 +766,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
int *usockaddr_len, int peer)
{
int len = sizeof(struct sockaddr_pppol2tp);
struct sockaddr_pppol2tp sp;
int len = 0;
int error = 0;
struct l2tp_session *session;
struct l2tp_tunnel *tunnel;
Expand All @@ -783,21 +792,40 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
goto end_put_sess;
}

memset(&sp, 0, len);
sp.sa_family = AF_PPPOX;
sp.sa_protocol = PX_PROTO_OL2TP;
sp.pppol2tp.fd = tunnel->fd;
sp.pppol2tp.pid = pls->owner;
sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
sp.pppol2tp.s_session = session->session_id;
sp.pppol2tp.d_session = session->peer_session_id;
inet = inet_sk(sk);
sp.pppol2tp.addr.sin_family = AF_INET;
sp.pppol2tp.addr.sin_port = inet->inet_dport;
sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;

memcpy(uaddr, &sp, len);
if (tunnel->version == 2) {
struct sockaddr_pppol2tp sp;
len = sizeof(sp);
memset(&sp, 0, len);
sp.sa_family = AF_PPPOX;
sp.sa_protocol = PX_PROTO_OL2TP;
sp.pppol2tp.fd = tunnel->fd;
sp.pppol2tp.pid = pls->owner;
sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
sp.pppol2tp.s_session = session->session_id;
sp.pppol2tp.d_session = session->peer_session_id;
sp.pppol2tp.addr.sin_family = AF_INET;
sp.pppol2tp.addr.sin_port = inet->inet_dport;
sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
memcpy(uaddr, &sp, len);
} else if (tunnel->version == 3) {
struct sockaddr_pppol2tpv3 sp;
len = sizeof(sp);
memset(&sp, 0, len);
sp.sa_family = AF_PPPOX;
sp.sa_protocol = PX_PROTO_OL2TP;
sp.pppol2tp.fd = tunnel->fd;
sp.pppol2tp.pid = pls->owner;
sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
sp.pppol2tp.s_session = session->session_id;
sp.pppol2tp.d_session = session->peer_session_id;
sp.pppol2tp.addr.sin_family = AF_INET;
sp.pppol2tp.addr.sin_port = inet->inet_dport;
sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
memcpy(uaddr, &sp, len);
}

*usockaddr_len = len;

Expand Down

0 comments on commit 97b42ea

Please sign in to comment.