On Mon, 30 Jan 2012 22:49:22 +0900 (JST) YASUOKA Masahiko <yasu...@yasuoka.net> 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 =