l2tp: remove ->recv_payload_hook
The tunnel reception hook is only used by l2tp_ppp for skipping PPP framing bytes. This is a session specific operation, but once a PPP session sets ->recv_payload_hook on its tunnel, all frames received by the tunnel will enter pppol2tp_recv_payload_hook(), including those targeted at Ethernet sessions (an L2TPv3 tunnel can multiplex PPP and Ethernet sessions). So this mechanism is wrong, and uselessly complex. Let's just move this functionality to the pppol2tp rx handler and drop ->recv_payload_hook. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
63135ee0a6
commit
2b139e6b1e
|
@ -619,7 +619,7 @@ discard:
|
||||||
*/
|
*/
|
||||||
void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
||||||
unsigned char *ptr, unsigned char *optr, u16 hdrflags,
|
unsigned char *ptr, unsigned char *optr, u16 hdrflags,
|
||||||
int length, int (*payload_hook)(struct sk_buff *skb))
|
int length)
|
||||||
{
|
{
|
||||||
struct l2tp_tunnel *tunnel = session->tunnel;
|
struct l2tp_tunnel *tunnel = session->tunnel;
|
||||||
int offset;
|
int offset;
|
||||||
|
@ -740,13 +740,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
||||||
|
|
||||||
__skb_pull(skb, offset);
|
__skb_pull(skb, offset);
|
||||||
|
|
||||||
/* If caller wants to process the payload before we queue the
|
|
||||||
* packet, do so now.
|
|
||||||
*/
|
|
||||||
if (payload_hook)
|
|
||||||
if ((*payload_hook)(skb))
|
|
||||||
goto discard;
|
|
||||||
|
|
||||||
/* Prepare skb for adding to the session's reorder_q. Hold
|
/* Prepare skb for adding to the session's reorder_q. Hold
|
||||||
* packets for max reorder_timeout or 1 second if not
|
* packets for max reorder_timeout or 1 second if not
|
||||||
* reordering.
|
* reordering.
|
||||||
|
@ -800,8 +793,7 @@ static int l2tp_session_queue_purge(struct l2tp_session *session)
|
||||||
* Returns 1 if the packet was not a good data packet and could not be
|
* Returns 1 if the packet was not a good data packet and could not be
|
||||||
* forwarded. All such packets are passed up to userspace to deal with.
|
* forwarded. All such packets are passed up to userspace to deal with.
|
||||||
*/
|
*/
|
||||||
static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
|
static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
|
||||||
int (*payload_hook)(struct sk_buff *skb))
|
|
||||||
{
|
{
|
||||||
struct l2tp_session *session = NULL;
|
struct l2tp_session *session = NULL;
|
||||||
unsigned char *ptr, *optr;
|
unsigned char *ptr, *optr;
|
||||||
|
@ -892,7 +884,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
|
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
|
||||||
l2tp_session_dec_refcount(session);
|
l2tp_session_dec_refcount(session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -921,7 +913,7 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||||
l2tp_dbg(tunnel, L2TP_MSG_DATA, "%s: received %d bytes\n",
|
l2tp_dbg(tunnel, L2TP_MSG_DATA, "%s: received %d bytes\n",
|
||||||
tunnel->name, skb->len);
|
tunnel->name, skb->len);
|
||||||
|
|
||||||
if (l2tp_udp_recv_core(tunnel, skb, tunnel->recv_payload_hook))
|
if (l2tp_udp_recv_core(tunnel, skb))
|
||||||
goto pass_up;
|
goto pass_up;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -180,7 +180,6 @@ struct l2tp_tunnel {
|
||||||
struct net *l2tp_net; /* the net we belong to */
|
struct net *l2tp_net; /* the net we belong to */
|
||||||
|
|
||||||
refcount_t ref_count;
|
refcount_t ref_count;
|
||||||
int (*recv_payload_hook)(struct sk_buff *skb);
|
|
||||||
void (*old_sk_destruct)(struct sock *);
|
void (*old_sk_destruct)(struct sock *);
|
||||||
struct sock *sock; /* Parent socket */
|
struct sock *sock; /* Parent socket */
|
||||||
int fd; /* Parent fd, if tunnel socket
|
int fd; /* Parent fd, if tunnel socket
|
||||||
|
@ -232,7 +231,7 @@ int l2tp_session_delete(struct l2tp_session *session);
|
||||||
void l2tp_session_free(struct l2tp_session *session);
|
void l2tp_session_free(struct l2tp_session *session);
|
||||||
void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
||||||
unsigned char *ptr, unsigned char *optr, u16 hdrflags,
|
unsigned char *ptr, unsigned char *optr, u16 hdrflags,
|
||||||
int length, int (*payload_hook)(struct sk_buff *skb));
|
int length);
|
||||||
int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);
|
int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);
|
||||||
void l2tp_session_set_header_len(struct l2tp_session *session, int version);
|
void l2tp_session_set_header_len(struct l2tp_session *session, int version);
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ static int l2tp_ip_recv(struct sk_buff *skb)
|
||||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
|
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
|
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
|
||||||
l2tp_session_dec_refcount(session);
|
l2tp_session_dec_refcount(session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -178,8 +178,7 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
|
||||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
|
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
|
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
|
||||||
tunnel->recv_payload_hook);
|
|
||||||
l2tp_session_dec_refcount(session);
|
l2tp_session_dec_refcount(session);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -183,25 +183,6 @@ out:
|
||||||
* Receive data handling
|
* Receive data handling
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static int pppol2tp_recv_payload_hook(struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
/* Skip PPP header, if present. In testing, Microsoft L2TP clients
|
|
||||||
* don't send the PPP header (PPP header compression enabled), but
|
|
||||||
* other clients can include the header. So we cope with both cases
|
|
||||||
* here. The PPP header is always FF03 when using L2TP.
|
|
||||||
*
|
|
||||||
* Note that skb->data[] isn't dereferenced from a u16 ptr here since
|
|
||||||
* the field may be unaligned.
|
|
||||||
*/
|
|
||||||
if (!pskb_may_pull(skb, 2))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((skb->data[0] == PPP_ALLSTATIONS) && (skb->data[1] == PPP_UI))
|
|
||||||
skb_pull(skb, 2);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Receive message. This is the recvmsg for the PPPoL2TP socket.
|
/* Receive message. This is the recvmsg for the PPPoL2TP socket.
|
||||||
*/
|
*/
|
||||||
static int pppol2tp_recvmsg(struct socket *sock, struct msghdr *msg,
|
static int pppol2tp_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||||
|
@ -248,6 +229,17 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
|
||||||
if (sk == NULL)
|
if (sk == NULL)
|
||||||
goto no_sock;
|
goto no_sock;
|
||||||
|
|
||||||
|
/* If the first two bytes are 0xFF03, consider that it is the PPP's
|
||||||
|
* Address and Control fields and skip them. The L2TP module has always
|
||||||
|
* worked this way, although, in theory, the use of these fields should
|
||||||
|
* be negociated and handled at the PPP layer. These fields are
|
||||||
|
* constant: 0xFF is the All-Stations Address and 0x03 the Unnumbered
|
||||||
|
* Information command with Poll/Final bit set to zero (RFC 1662).
|
||||||
|
*/
|
||||||
|
if (pskb_may_pull(skb, 2) && skb->data[0] == PPP_ALLSTATIONS &&
|
||||||
|
skb->data[1] == PPP_UI)
|
||||||
|
skb_pull(skb, 2);
|
||||||
|
|
||||||
if (sk->sk_state & PPPOX_BOUND) {
|
if (sk->sk_state & PPPOX_BOUND) {
|
||||||
struct pppox_sock *po;
|
struct pppox_sock *po;
|
||||||
|
|
||||||
|
@ -763,9 +755,6 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tunnel->recv_payload_hook == NULL)
|
|
||||||
tunnel->recv_payload_hook = pppol2tp_recv_payload_hook;
|
|
||||||
|
|
||||||
if (tunnel->peer_tunnel_id == 0)
|
if (tunnel->peer_tunnel_id == 0)
|
||||||
tunnel->peer_tunnel_id = info.peer_tunnel_id;
|
tunnel->peer_tunnel_id = info.peer_tunnel_id;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue