diff options
Diffstat (limited to 'sys/net/pipex.c')
-rw-r--r-- | sys/net/pipex.c | 326 |
1 files changed, 71 insertions, 255 deletions
diff --git a/sys/net/pipex.c b/sys/net/pipex.c index 2e92867171b..7ce310e0adc 100644 --- a/sys/net/pipex.c +++ b/sys/net/pipex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex.c,v 1.124 2020/08/12 08:41:39 mvs Exp $ */ +/* $OpenBSD: pipex.c,v 1.125 2020/08/27 10:47:52 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -141,115 +141,55 @@ pipex_init(void) } void -pipex_iface_init(struct pipex_iface_context *pipex_iface, u_int ifindex) -{ - struct pipex_session *session; - - pipex_iface->pipexmode = 0; - pipex_iface->ifindex = ifindex; - - if (pipex_rd_head4 == NULL) { - if (!rn_inithead((void **)&pipex_rd_head4, - offsetof(struct sockaddr_in, sin_addr))) - panic("rn_inithead() failed on pipex_init()"); - } - if (pipex_rd_head6 == NULL) { - if (!rn_inithead((void **)&pipex_rd_head6, - offsetof(struct sockaddr_in6, sin6_addr))) - panic("rn_inithead() failed on pipex_init()"); - } - - /* virtual pipex_session entry for multicast */ - session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); - session->is_multicast = 1; - session->pipex_iface = pipex_iface; - session->ifindex = ifindex; - pipex_iface->multicast_session = session; -} - -Static void -pipex_iface_start(struct pipex_iface_context *pipex_iface) -{ - pipex_iface->pipexmode = 1; -} - -Static void -pipex_iface_stop(struct pipex_iface_context *pipex_iface) +pipex_destroy_all_sessions(void *ownersc) { struct pipex_session *session, *session_tmp; - pipex_iface->pipexmode = 0; - /* - * traversal all pipex sessions. - * it will become heavy if the number of pppac devices bocomes large. - */ + NET_ASSERT_LOCKED(); + LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { - if (session->pipex_iface == pipex_iface) - pipex_destroy_session(session); + if (session->ownersc == ownersc) { + KASSERT(session->is_pppx == 0); + pipex_unlink_session(session); + pipex_rele_session(session); + } } } -void -pipex_iface_fini(struct pipex_iface_context *pipex_iface) -{ - pool_put(&pipex_session_pool, pipex_iface->multicast_session); - NET_LOCK(); - pipex_iface_stop(pipex_iface); - NET_UNLOCK(); -} - int -pipex_ioctl(struct pipex_iface_context *pipex_iface, u_long cmd, caddr_t data) +pipex_ioctl(void *ownersc, u_long cmd, caddr_t data) { - int pipexmode, ret = 0; + int ret = 0; - NET_LOCK(); + NET_ASSERT_LOCKED(); switch (cmd) { case PIPEXSMODE: - pipexmode = *(int *)data; - if (pipex_iface->pipexmode != pipexmode) { - if (pipexmode) - pipex_iface_start(pipex_iface); - else - pipex_iface_stop(pipex_iface); - } break; case PIPEXGMODE: - *(int *)data = pipex_iface->pipexmode; - break; - - case PIPEXASESSION: - ret = pipex_add_session((struct pipex_session_req *)data, - pipex_iface); - break; - - case PIPEXDSESSION: - ret = pipex_close_session( - (struct pipex_session_close_req *)data, pipex_iface); + *(int *)data = 1; break; case PIPEXCSESSION: ret = pipex_config_session( - (struct pipex_session_config_req *)data, pipex_iface); + (struct pipex_session_config_req *)data, ownersc); break; case PIPEXGSTAT: ret = pipex_get_stat((struct pipex_session_stat_req *)data, - pipex_iface); + ownersc); break; case PIPEXGCLOSED: ret = pipex_get_closed((struct pipex_session_list_req *)data, - pipex_iface); + ownersc); break; default: ret = ENOTTY; break; } - NET_UNLOCK(); return (ret); } @@ -426,21 +366,43 @@ pipex_rele_session(struct pipex_session *session) } int -pipex_link_session(struct pipex_session *session, - struct pipex_iface_context *iface) +pipex_link_session(struct pipex_session *session, struct ifnet *ifp, + void *ownersc) { struct pipex_hash_head *chain; + struct radix_node *rn; NET_ASSERT_LOCKED(); - if (!iface->pipexmode) - return (ENXIO); + if (pipex_rd_head4 == NULL) { + if (!rn_inithead((void **)&pipex_rd_head4, + offsetof(struct sockaddr_in, sin_addr))) + panic("rn_inithead() failed on pipex_link_session()"); + } + if (pipex_rd_head6 == NULL) { + if (!rn_inithead((void **)&pipex_rd_head6, + offsetof(struct sockaddr_in6, sin6_addr))) + panic("rn_inithead() failed on pipex_link_session()"); + } if (pipex_lookup_by_session_id(session->protocol, session->session_id)) return (EEXIST); - session->pipex_iface = iface; - session->ifindex = iface->ifindex; + session->ownersc = ownersc; + session->ifindex = ifp->if_index; + if (ifp->if_flags & IFF_POINTOPOINT) + session->is_pppx = 1; + + if (session->is_pppx == 0 && + !in_nullhost(session->ip_address.sin_addr)) { + if (pipex_lookup_by_ip_address(session->ip_address.sin_addr) + != NULL) + return (EADDRINUSE); + rn = rn_addroute(&session->ip_address, &session->ip_netmask, + pipex_rd_head4, session->ps4_rn, RTP_STATIC); + if (rn == NULL) + return (ENOMEM); + } LIST_INSERT_HEAD(&pipex_session_list, session, session_list); chain = PIPEX_ID_HASHTABLE(session->session_id); @@ -466,9 +428,21 @@ pipex_link_session(struct pipex_session *session, void pipex_unlink_session(struct pipex_session *session) { + struct radix_node *rn; + session->ifindex = 0; NET_ASSERT_LOCKED(); + if (session->state == PIPEX_STATE_CLOSED) + return; + if (session->is_pppx == 0 && + !in_nullhost(session->ip_address.sin_addr)) { + KASSERT(pipex_rd_head4 != NULL); + rn = rn_delete(&session->ip_address, &session->ip_netmask, + pipex_rd_head4, (struct radix_node *)session); + KASSERT(rn != NULL); + } + LIST_REMOVE(session, id_chain); #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP) switch (session->protocol) { @@ -488,54 +462,6 @@ pipex_unlink_session(struct pipex_session *session) pipex_timer_stop(); } -Static int -pipex_add_session(struct pipex_session_req *req, - struct pipex_iface_context *iface) -{ - struct pipex_session *session; - struct radix_node *rn; - int error; - - if ((error = pipex_init_session(&session, req)) != 0) - goto out; - - /* commit the session */ - if (!in_nullhost(session->ip_address.sin_addr)) { - if (pipex_lookup_by_ip_address(session->ip_address.sin_addr) - != NULL) { - error = EADDRINUSE; - goto free; - } - - rn = rn_addroute(&session->ip_address, &session->ip_netmask, - pipex_rd_head4, session->ps4_rn, RTP_STATIC); - if (rn == NULL) { - error = ENOMEM; - goto free; - } - } - if (0) { /* NOT YET */ - rn = rn_addroute(&session->ip6_address, &session->ip6_prefixlen, - pipex_rd_head6, session->ps6_rn, RTP_STATIC); - if (rn == NULL) { - error = ENOMEM; - goto free; - } - } - - if ((error = pipex_link_session(session, iface)) != 0) - goto free; - - pipex_session_log(session, LOG_INFO, "PIPEX is ready."); - - return 0; - -free: - pipex_rele_session(session); -out: - return error; -} - int pipex_notify_close_session(struct pipex_session *session) { @@ -547,46 +473,8 @@ pipex_notify_close_session(struct pipex_session *session) return (0); } -int -pipex_notify_close_session_all(void) -{ - struct pipex_session *session; - - NET_ASSERT_LOCKED(); - LIST_FOREACH(session, &pipex_session_list, session_list) - if (session->state == PIPEX_STATE_OPENED) - pipex_notify_close_session(session); - return (0); -} - -Static int -pipex_close_session(struct pipex_session_close_req *req, - struct pipex_iface_context *iface) -{ - struct pipex_session *session; - - NET_ASSERT_LOCKED(); - session = pipex_lookup_by_session_id(req->pcr_protocol, - req->pcr_session_id); - if (session == NULL) - return (EINVAL); - if (session->pipex_iface != iface) - return (EINVAL); - - /* remove from close_wait list */ - if (session->state == PIPEX_STATE_CLOSE_WAIT) - LIST_REMOVE(session, state_list); - - /* get statistics before destroy the session */ - req->pcr_stat = session->stat; - session->state = PIPEX_STATE_CLOSED; - - return (0); -} - Static int -pipex_config_session(struct pipex_session_config_req *req, - struct pipex_iface_context *iface) +pipex_config_session(struct pipex_session_config_req *req, void *ownersc) { struct pipex_session *session; @@ -595,7 +483,7 @@ pipex_config_session(struct pipex_session_config_req *req, req->pcr_session_id); if (session == NULL) return (EINVAL); - if (session->pipex_iface != iface) + if (session->ownersc != ownersc) return (EINVAL); session->ip_forward = req->pcr_ip_forward; @@ -603,8 +491,7 @@ pipex_config_session(struct pipex_session_config_req *req, } Static int -pipex_get_stat(struct pipex_session_stat_req *req, - struct pipex_iface_context *iface) +pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc) { struct pipex_session *session; @@ -613,7 +500,7 @@ pipex_get_stat(struct pipex_session_stat_req *req, req->psr_session_id); if (session == NULL) return (EINVAL); - if (session->pipex_iface != iface) + if (session->ownersc != ownersc) return (EINVAL); req->psr_stat = session->stat; @@ -621,8 +508,7 @@ pipex_get_stat(struct pipex_session_stat_req *req, } Static int -pipex_get_closed(struct pipex_session_list_req *req, - struct pipex_iface_context *iface) +pipex_get_closed(struct pipex_session_list_req *req, void *ownersc) { struct pipex_session *session, *session_tmp; @@ -630,7 +516,7 @@ pipex_get_closed(struct pipex_session_list_req *req, bzero(req, sizeof(*req)); LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list, session_tmp) { - if (session->pipex_iface != iface) + if (session->ownersc != ownersc) continue; req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id; LIST_REMOVE(session, state_list); @@ -645,32 +531,14 @@ pipex_get_closed(struct pipex_session_list_req *req, return (0); } -Static int -pipex_destroy_session(struct pipex_session *session) -{ - struct radix_node *rn; - - /* remove from radix tree and hash chain */ - NET_ASSERT_LOCKED(); - - if (!in_nullhost(session->ip_address.sin_addr)) { - rn = rn_delete(&session->ip_address, &session->ip_netmask, - pipex_rd_head4, (struct radix_node *)session); - KASSERT(rn != NULL); - } - - pipex_unlink_session(session); - pipex_rele_session(session); - - return (0); -} - Static struct pipex_session * pipex_lookup_by_ip_address(struct in_addr addr) { struct pipex_session *session; struct sockaddr_in pipex_in4, pipex_in4mask; + if (pipex_rd_head4 == NULL) + return (NULL); bzero(&pipex_in4, sizeof(pipex_in4)); pipex_in4.sin_addr = addr; pipex_in4.sin_family = AF_INET; @@ -761,18 +629,15 @@ pipex_timer(void *ignored_arg) case PIPEX_STATE_CLOSE_WAIT: case PIPEX_STATE_CLOSE_WAIT2: - /* Wait PIPEXDSESSION from userland */ + /* Waiting PIPEXDSESSION from userland */ session->stat.idle_time++; if (session->stat.idle_time < PIPEX_CLOSE_TIMEOUT) continue; - - if (session->state == PIPEX_STATE_CLOSE_WAIT) - LIST_REMOVE(session, state_list); - session->state = PIPEX_STATE_CLOSED; - /* FALLTHROUGH */ - - case PIPEX_STATE_CLOSED: - pipex_destroy_session(session); + /* Release the sessions when timeout */ + pipex_unlink_session(session); + KASSERTMSG(session->is_pppx == 0, + "FIXME session must not be released when pppx"); + pipex_rele_session(session); break; default: @@ -786,55 +651,6 @@ pipex_timer(void *ignored_arg) /*********************************************************************** * Common network I/O functions. (tunnel protocol independent) ***********************************************************************/ -struct mbuf * -pipex_output(struct mbuf *m0, int af, int off, - struct pipex_iface_context *pipex_iface) -{ - struct pipex_session *session; - struct ip ip; - struct mbuf *mret; - - NET_ASSERT_LOCKED(); - session = NULL; - mret = NULL; - switch (af) { - case AF_INET: - if (m0->m_pkthdr.len >= sizeof(struct ip) + off) { - m_copydata(m0, off, sizeof(struct ip), (caddr_t)&ip); - if (IN_MULTICAST(ip.ip_dst.s_addr)) - session = pipex_iface->multicast_session; - else - session = pipex_lookup_by_ip_address(ip.ip_dst); - } - if (session != NULL) { - if (session == pipex_iface->multicast_session) { - mret = m0; - m0 = m_copym(m0, 0, M_COPYALL, M_NOWAIT); - if (m0 == NULL) { - m0 = mret; - mret = NULL; - goto drop; - } - } - - if (off > 0) - m_adj(m0, off); - - pipex_ip_output(m0, session); - return (mret); - } - break; - } - - return (m0); - -drop: - m_freem(m0); - if (session != NULL) - session->stat.oerrors++; - return(NULL); -} - Static void pipex_ip_output(struct mbuf *m0, struct pipex_session *session) { @@ -872,7 +688,7 @@ pipex_ip_output(struct mbuf *m0, struct pipex_session *session) m0->m_flags &= ~(M_BCAST|M_MCAST); LIST_FOREACH(session_tmp, &pipex_session_list, session_list) { - if (session_tmp->pipex_iface != session->pipex_iface) + if (session_tmp->ownersc != session->ownersc) continue; if (session_tmp->ip_forward == 0 && session_tmp->ip6_forward == 0) |