On Mon, 30 Jan 2012 22:49:22 +0900 (JST)
YASUOKA Masahiko <[email protected]> wrote:
> pipex hook in udp_usrreq() mistakenly assumed that `inp' is
> connected. The hook could not use the destination address properly,
> so it failed to find the pipex session. This bug caused LCP keepalive
> failures on L2TP from client that does LCP keepalive and uses sequence
> number on the L2TP data channel (xl2tpd + pppd).
>
> The diff includes kernel header file changes.
>
> ok?
Oops. Let me update the diff.
The given struct sockaddr object of
pipex_l2tp_userland_lookup_session() became passed from the userland,
so its address family must be checked.
ok?
Index: sys/net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.25
diff -u -p -r1.25 pipex.c
--- sys/net/pipex.c 23 Jan 2012 03:36:21 -0000 1.25
+++ sys/net/pipex.c 30 Jan 2012 14:37:31 -0000
@@ -2210,13 +2210,16 @@ pipex_l2tp_userland_lookup_session_ipv6(
}
#endif
-Static struct pipex_session *
+struct pipex_session *
pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
{
struct pipex_l2tp_header l2tp;
struct pipex_hash_head *list;
struct pipex_session *session;
uint16_t session_id, tunnel_id, flags;
+
+ if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+ return (NULL);
/* pullup */
if (m0->m_pkthdr.len < sizeof(l2tp)) {
Index: sys/net/pipex.h
===================================================================
RCS file: /cvs/src/sys/net/pipex.h,v
retrieving revision 1.11
diff -u -p -r1.11 pipex.h
--- sys/net/pipex.h 23 Jan 2012 03:36:21 -0000 1.11
+++ sys/net/pipex.h 30 Jan 2012 14:37:31 -0000
@@ -210,6 +210,7 @@ struct pipex_session *pipex_pptp_lookup
struct mbuf *pipex_pptp_input (struct mbuf *, struct pipex_session
*);
struct pipex_session *pipex_pptp_userland_lookup_session_ipv4 (struct mbuf *,
struct in_addr);
struct pipex_session *pipex_pptp_userland_lookup_session_ipv6 (struct mbuf *,
struct in6_addr);
+struct pipex_session *pipex_l2tp_userland_lookup_session(struct mbuf *,
struct sockaddr *);
struct mbuf *pipex_pptp_userland_output (struct mbuf *, struct
pipex_session *);
struct pipex_session *pipex_l2tp_lookup_session (struct mbuf *, int);
struct mbuf *pipex_l2tp_input (struct mbuf *, int off, struct
pipex_session *);
Index: sys/net/pipex_local.h
===================================================================
RCS file: /cvs/src/sys/net/pipex_local.h,v
retrieving revision 1.14
diff -u -p -r1.14 pipex_local.h
--- sys/net/pipex_local.h 25 Nov 2011 13:05:06 -0000 1.14
+++ sys/net/pipex_local.h 30 Jan 2012 14:37:31 -0000
@@ -406,7 +406,6 @@ Static struct pipex_session *pipex_pptp
#ifdef PIPEX_L2TP
Static void pipex_l2tp_output (struct mbuf *, struct
pipex_session *);
-Static struct pipex_session *pipex_l2tp_userland_lookup_session(struct mbuf
*, struct sockaddr *);
#endif
#ifdef PIPEX_MPPE
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.145
diff -u -p -r1.145 udp_usrreq.c
--- sys/netinet/udp_usrreq.c 8 Jul 2011 18:30:17 -0000 1.145
+++ sys/netinet/udp_usrreq.c 30 Jan 2012 14:37:32 -0000
@@ -1198,6 +1198,12 @@ udp_usrreq(struct socket *so, int req, s
#ifdef PIPEX
if (inp->inp_pipex) {
struct pipex_session *session;
+
+ if (addr != NULL)
+ session =
+ pipex_l2tp_userland_lookup_session(m,
+ mtod(addr, struct sockaddr *));
+ else
#ifdef INET6
if (inp->inp_flags & INP_IPV6)
session =