Updated diff. The idea is to use already existing pipex API for pipex_session creation and destruction. pppx_if now holds a reference to pipex_session.
Index: sys/net/if_pppx.c =================================================================== RCS file: /cvs/src/sys/net/if_pppx.c,v retrieving revision 1.78 diff -u -p -r1.78 if_pppx.c --- sys/net/if_pppx.c 1 Apr 2020 07:15:59 -0000 1.78 +++ sys/net/if_pppx.c 1 Apr 2020 09:50:19 -0000 @@ -155,7 +155,7 @@ struct pppx_if { int pxi_unit; struct ifnet pxi_if; struct pppx_dev *pxi_dev; - struct pipex_session pxi_session; + struct pipex_session *pxi_session; struct pipex_iface_context pxi_ifcontext; }; @@ -655,15 +655,10 @@ int pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) { struct pppx_if *pxi; - struct pipex_session *session; - struct pipex_hash_head *chain; struct ifnet *ifp; int unit, error = 0; struct in_ifaddr *ia; struct sockaddr_in ifaddr; -#ifdef PIPEX_PPPOE - struct ifnet *over_ifp = NULL; -#endif /* * XXX: As long as `session' is allocated as part of a `pxi' @@ -673,157 +668,16 @@ pppx_add_session(struct pppx_dev *pxd, s if (req->pr_timeout_sec != 0) return (EINVAL); - switch (req->pr_protocol) { -#ifdef PIPEX_PPPOE - case PIPEX_PROTO_PPPOE: - over_ifp = ifunit(req->pr_proto.pppoe.over_ifname); - if (over_ifp == NULL) - return (EINVAL); - if (req->pr_peer_address.ss_family != AF_UNSPEC) - return (EINVAL); - break; -#endif -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) - case PIPEX_PROTO_PPTP: - case PIPEX_PROTO_L2TP: - switch (req->pr_peer_address.ss_family) { - case AF_INET: - if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in)) - return (EINVAL); - break; -#ifdef INET6 - case AF_INET6: - if (req->pr_peer_address.ss_len != sizeof(struct sockaddr_in6)) - return (EINVAL); - break; -#endif - default: - return (EPROTONOSUPPORT); - } - if (req->pr_peer_address.ss_family != - req->pr_local_address.ss_family || - req->pr_peer_address.ss_len != - req->pr_local_address.ss_len) - return (EINVAL); - break; -#endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */ - default: - return (EPROTONOSUPPORT); - } - pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO); - if (pxi == NULL) - return (ENOMEM); - - session = &pxi->pxi_session; ifp = &pxi->pxi_if; - /* fake a pipex interface context */ - session->pipex_iface = &pxi->pxi_ifcontext; - session->pipex_iface->ifnet_this = ifp; - session->pipex_iface->pipexmode = PIPEX_ENABLED; - - /* setup session */ - session->state = PIPEX_STATE_OPENED; - session->protocol = req->pr_protocol; - session->session_id = req->pr_session_id; - session->peer_session_id = req->pr_peer_session_id; - session->peer_mru = req->pr_peer_mru; - session->timeout_sec = req->pr_timeout_sec; - session->ppp_flags = req->pr_ppp_flags; - session->ppp_id = req->pr_ppp_id; - - session->ip_forward = 1; - - session->ip_address.sin_family = AF_INET; - session->ip_address.sin_len = sizeof(struct sockaddr_in); - session->ip_address.sin_addr = req->pr_ip_address; - - session->ip_netmask.sin_family = AF_INET; - session->ip_netmask.sin_len = sizeof(struct sockaddr_in); - session->ip_netmask.sin_addr = req->pr_ip_netmask; - - if (session->ip_netmask.sin_addr.s_addr == 0L) - session->ip_netmask.sin_addr.s_addr = 0xffffffffL; - session->ip_address.sin_addr.s_addr &= - session->ip_netmask.sin_addr.s_addr; - - if (req->pr_peer_address.ss_len > 0) - memcpy(&session->peer, &req->pr_peer_address, - MIN(req->pr_peer_address.ss_len, sizeof(session->peer))); - if (req->pr_local_address.ss_len > 0) - memcpy(&session->local, &req->pr_local_address, - MIN(req->pr_local_address.ss_len, sizeof(session->local))); -#ifdef PIPEX_PPPOE - if (req->pr_protocol == PIPEX_PROTO_PPPOE) - session->proto.pppoe.over_ifidx = over_ifp->if_index; -#endif -#ifdef PIPEX_PPTP - if (req->pr_protocol == PIPEX_PROTO_PPTP) { - struct pipex_pptp_session *sess_pptp = &session->proto.pptp; - - sess_pptp->snd_gap = 0; - sess_pptp->rcv_gap = 0; - sess_pptp->snd_una = req->pr_proto.pptp.snd_una; - sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt; - sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt; - sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked; - - sess_pptp->winsz = req->pr_proto.pptp.winsz; - sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz; - sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz; - /* last ack number */ - sess_pptp->ul_snd_una = sess_pptp->snd_una - 1; - } -#endif -#ifdef PIPEX_L2TP - if (req->pr_protocol == PIPEX_PROTO_L2TP) { - struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp; - - /* session keys */ - sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id; - sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id; - - /* protocol options */ - sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags; - - /* initial state of dynamic context */ - sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0; - sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt; - sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt; - sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una; - sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked; - /* last ack number */ - sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1; - } -#endif -#ifdef PIPEX_MPPE - if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) - pipex_session_init_mppe_recv(session, - req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits, - req->pr_mppe_recv.master_key); - if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) - pipex_session_init_mppe_send(session, - req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits, - req->pr_mppe_send.master_key); - - if (pipex_session_is_mppe_required(session)) { - if (!pipex_session_is_mppe_enabled(session) || - !pipex_session_is_mppe_accepted(session)) { - pool_put(pppx_if_pl, pxi); - return (EINVAL); - } - } -#endif - /* try to set the interface up */ rw_enter_write(&pppx_ifs_lk); unit = pppx_if_next_unit(); if (unit < 0) { - pool_put(pppx_if_pl, pxi); - error = ENOMEM; rw_exit_write(&pppx_ifs_lk); - goto out; + error = ENOMEM; + goto err_free_iface; } pxi->pxi_unit = unit; @@ -833,10 +687,9 @@ pppx_add_session(struct pppx_dev *pxd, s /* this is safe without splnet since we're not modifying it */ if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) { - pool_put(pppx_if_pl, pxi); - error = EADDRINUSE; rw_exit_write(&pppx_ifs_lk); - goto out; + error = EADDRINUSE; + goto err_free_iface; } if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL) @@ -856,24 +709,21 @@ pppx_add_session(struct pppx_dev *pxd, s ifp->if_softc = pxi; /* ifp->if_rdomain = req->pr_rdomain; */ - /* hook up pipex context */ - chain = PIPEX_ID_HASHTABLE(session->session_id); - LIST_INSERT_HEAD(chain, session, id_chain); - LIST_INSERT_HEAD(&pipex_session_list, session, session_list); -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) - switch (req->pr_protocol) { - case PIPEX_PROTO_PPTP: - case PIPEX_PROTO_L2TP: - chain = PIPEX_PEER_ADDR_HASHTABLE( - pipex_sockaddr_hash_key(&session->peer.sa)); - LIST_INSERT_HEAD(chain, session, peer_addr_chain); - break; + /* pipex interface context */ + pipex_iface_init(&pxi->pxi_ifcontext, ifp); + pipex_iface_start(&pxi->pxi_ifcontext); + + error = pipex_add_session(req, &pxi->pxi_ifcontext); + if (error) { + goto err_free_pipex; } -#endif - /* if first session is added, start timer */ - if (LIST_NEXT(session, session_list) == NULL) - pipex_timer_start(); + pxi->pxi_session = pipex_lookup_by_session_id( + pxi->pxi_key.pxik_protocol, pxi->pxi_key.pxik_session_id); + if (pxi->pxi_session == NULL) { + error = EINVAL; + goto err_free_pipex; + } /* XXXSMP breaks atomicity */ NET_UNLOCK(); @@ -928,7 +778,20 @@ pppx_add_session(struct pppx_dev *pxd, s pxi->pxi_ready = 1; rw_exit_write(&pppx_ifs_lk); -out: + return (error); + +err_free_pipex: + NET_UNLOCK(); + pipex_iface_fini(&pxi->pxi_ifcontext); + NET_LOCK(); +err_free_iface: + rw_enter_write(&pppx_ifs_lk); + if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) + panic("%s: pppx_ifs modified while lock was held", __func__); + LIST_REMOVE(pxi, pxi_list); + rw_exit_write(&pppx_ifs_lk); + pool_put(pppx_if_pl, pxi); + return (error); } @@ -941,7 +804,7 @@ pppx_del_session(struct pppx_dev *pxd, s if (pxi == NULL) return (EINVAL); - req->pcr_stat = pxi->pxi_session.stat; + req->pcr_stat = pxi->pxi_session->stat; pppx_if_destroy(pxd, pxi); return (0); @@ -970,29 +833,19 @@ pppx_if_destroy(struct pppx_dev *pxd, st struct pipex_session *session; NET_ASSERT_LOCKED(); - session = &pxi->pxi_session; + session = pxi->pxi_session; ifp = &pxi->pxi_if; - LIST_REMOVE(session, id_chain); - LIST_REMOVE(session, session_list); -#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) - switch (session->protocol) { - case PIPEX_PROTO_PPTP: - case PIPEX_PROTO_L2TP: - LIST_REMOVE(session, peer_addr_chain); - break; - } -#endif - - /* if final session is destroyed, stop timer */ - if (LIST_EMPTY(&pipex_session_list)) - pipex_timer_stop(); - /* XXXSMP breaks atomicity */ NET_UNLOCK(); if_detach(ifp); NET_LOCK(); + pipex_destroy_session(session); + NET_UNLOCK(); + pipex_iface_fini(&pxi->pxi_ifcontext); + NET_LOCK(); + rw_enter_write(&pppx_ifs_lk); if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) panic("%s: pppx_ifs modified while lock was held", __func__); @@ -1024,7 +877,7 @@ pppx_if_start(struct ifnet *ifp) ifp->if_obytes += m->m_pkthdr.len; ifp->if_opackets++; - pipex_ppp_output(m, &pxi->pxi_session, proto); + pipex_ppp_output(m, pxi->pxi_session, proto); } } @@ -1084,7 +937,7 @@ pppx_if_output(struct ifnet *ifp, struct } th = mtod(m, struct pppx_hdr *); th->pppx_proto = 0; /* not used */ - th->pppx_id = pxi->pxi_session.ppp_id; + th->pppx_id = pxi->pxi_session->ppp_id; rw_enter_read(&pppx_devs_lk); error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m); if (error == 0) { @@ -1123,7 +976,7 @@ pppx_if_ioctl(struct ifnet *ifp, u_long case SIOCSIFMTU: if (ifr->ifr_mtu < 512 || - ifr->ifr_mtu > pxi->pxi_session.peer_mru) + ifr->ifr_mtu > pxi->pxi_session->peer_mru) error = EINVAL; else ifp->if_mtu = ifr->ifr_mtu;