inet_shutdown(sk->sk_socket, SEND_SHUTDOWN);
sock_put(sk);
}
-
- /* Don't let the session go away before our socket does */
- l2tp_session_inc_refcount(session);
}
/* Really kill the session socket. (Called from sock_put() if
if (session != NULL) {
struct pppol2tp_session *ps;
- __l2tp_session_unhash(session);
- l2tp_session_queue_purge(session);
+ l2tp_session_delete(session);
ps = l2tp_session_priv(session);
mutex_lock(&ps->sk_lock);
}
#endif
+static void pppol2tp_session_init(struct l2tp_session *session)
+{
+ struct pppol2tp_session *ps;
+ struct dst_entry *dst;
+
+ session->recv_skb = pppol2tp_recv;
+ session->session_close = pppol2tp_session_close;
+#if IS_ENABLED(CONFIG_L2TP_DEBUGFS)
+ session->show = pppol2tp_show;
+#endif
+
+ ps = l2tp_session_priv(session);
+ mutex_init(&ps->sk_lock);
+ ps->tunnel_sock = session->tunnel->sock;
+ ps->owner = current->pid;
+
+ /* If PMTU discovery was enabled, use the MTU that was discovered */
+ dst = sk_dst_get(session->tunnel->sock);
+ if (dst) {
+ u32 pmtu = dst_mtu(dst);
+
+ if (pmtu) {
+ session->mtu = pmtu - PPPOL2TP_HEADER_OVERHEAD;
+ session->mru = pmtu - PPPOL2TP_HEADER_OVERHEAD;
+ }
+ dst_release(dst);
+ }
+}
+
/* connect() handler. Attach a PPPoX socket to a tunnel UDP socket
*/
static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
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;
goto end;
}
+ pppol2tp_session_init(session);
ps = l2tp_session_priv(session);
- mutex_init(&ps->sk_lock);
l2tp_session_inc_refcount(session);
mutex_lock(&ps->sk_lock);
drop_refcnt = true;
}
- ps->owner = current->pid;
- ps->tunnel_sock = tunnel->sock;
-
- session->recv_skb = pppol2tp_recv;
- session->session_close = pppol2tp_session_close;
-#if IS_ENABLED(CONFIG_L2TP_DEBUGFS)
- session->show = pppol2tp_show;
-#endif
-
- /* If PMTU discovery was enabled, use the MTU that was discovered */
- dst = sk_dst_get(tunnel->sock);
- if (dst != NULL) {
- u32 pmtu = dst_mtu(dst);
-
- if (pmtu != 0)
- session->mtu = session->mru = pmtu -
- PPPOL2TP_HEADER_OVERHEAD;
- dst_release(dst);
- }
-
/* Special case: if source & dest session_id == 0x0000, this
* socket is being created to manage the tunnel. Just set up
* the internal context for use by ioctl() and sockopt()
rcu_assign_pointer(ps->sk, sk);
mutex_unlock(&ps->sk_lock);
+ /* Keep the reference we've grabbed on the session: sk doesn't expect
+ * the session to disappear. pppol2tp_session_destruct() is responsible
+ * for dropping it.
+ */
+ drop_refcnt = false;
+
sk->sk_state = PPPOX_CONNECTED;
l2tp_info(session, L2TP_MSG_CONTROL, "%s: created\n",
session->name);
{
int error;
struct l2tp_session *session;
- struct pppol2tp_session *ps;
/* Error if tunnel socket is not prepped */
if (!tunnel->sock) {
goto err;
}
- ps = l2tp_session_priv(session);
- mutex_init(&ps->sk_lock);
- ps->tunnel_sock = tunnel->sock;
+ pppol2tp_session_init(session);
error = l2tp_session_register(session, tunnel);
if (error < 0)