summaryrefslogtreecommitdiff
path: root/sys/net/pipex.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/pipex.c')
-rw-r--r--sys/net/pipex.c326
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)