-/* $OpenBSD: pipex.c,v 1.152 2024/01/23 16:57:52 mvs Exp $ */
+/* $OpenBSD: pipex.c,v 1.153 2024/01/23 17:57:21 mvs Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
session_tmp) {
+ if (session->flags & PIPEX_SFLAGS_ITERATOR)
+ continue;
if (session->ownersc == ownersc) {
KASSERT((session->flags & PIPEX_SFLAGS_PPPX) == 0);
pipex_unlink_session_locked(session);
LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list,
session_tmp) {
+ if (session->flags & PIPEX_SFLAGS_ITERATOR)
+ continue;
if (session->ownersc != ownersc)
continue;
req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
/* walk through */
LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
session_tmp) {
+ if (session->flags & PIPEX_SFLAGS_ITERATOR)
+ continue;
switch (session->state) {
case PIPEX_STATE_OPENED:
if (session->timeout_sec == 0)
/***********************************************************************
* Common network I/O functions. (tunnel protocol independent)
***********************************************************************/
+
+struct pipex_session *
+pipex_iterator(struct pipex_session *session,
+ struct pipex_session_iterator *iter, void *ownersc)
+{
+ struct pipex_session *session_tmp;
+
+ mtx_enter(&pipex_list_mtx);
+
+ if (session)
+ session_tmp = LIST_NEXT(session, session_list);
+ else
+ session_tmp = LIST_FIRST(&pipex_session_list);
+
+ while (session_tmp) {
+ if (session_tmp->flags & PIPEX_SFLAGS_ITERATOR)
+ goto next;
+ if (session_tmp->ownersc != ownersc)
+ goto next;
+ break;
+next:
+ session_tmp = LIST_NEXT(session_tmp, session_list);
+ }
+
+ if (session)
+ LIST_REMOVE(iter, session_list);
+
+ if (session_tmp) {
+ LIST_INSERT_AFTER(session_tmp,
+ (struct pipex_session *)&iter, session_list);
+ refcnt_take(&session_tmp->pxs_refcnt);
+ }
+
+ mtx_leave(&pipex_list_mtx);
+
+ if (session)
+ pipex_rele_session(session);
+
+ return (session_tmp);
+}
+
void
pipex_ip_output(struct mbuf *m0, struct pipex_session *session)
{
pipex_ppp_output(m0, session, PPP_IP);
} else {
+ struct pipex_session_iterator iter = {
+ .flags = PIPEX_SFLAGS_ITERATOR,
+ };
+
struct pipex_session *session_tmp;
struct mbuf *m;
m0->m_flags &= ~(M_BCAST|M_MCAST);
- mtx_enter(&pipex_list_mtx);
-
- session_tmp = LIST_FIRST(&pipex_session_list);
- while (session_tmp != NULL) {
- struct pipex_session *session_save = NULL;
-
- if (session_tmp->ownersc != session->ownersc)
- goto next;
-
- refcnt_take(&session_tmp->pxs_refcnt);
- mtx_leave(&pipex_list_mtx);
-
+ session_tmp = pipex_iterator(NULL, &iter, session->ownersc);
+ while (session_tmp) {
m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
if (m != NULL)
pipex_ppp_output(m, session_tmp, PPP_IP);
counters_inc(session_tmp->stat_counters,
pxc_oerrors);
- mtx_enter(&pipex_list_mtx);
- session_save = session_tmp;
-next:
- session_tmp = LIST_NEXT(session_tmp, session_list);
- if (session_save != NULL)
- pipex_rele_session(session_save);
+ session_tmp = pipex_iterator(session_tmp,
+ &iter, session->ownersc);
}
- mtx_leave(&pipex_list_mtx);
-
m_freem(m0);
}
-/* $OpenBSD: pipex_local.h,v 1.50 2024/01/23 16:57:53 mvs Exp $ */
+/* $OpenBSD: pipex_local.h,v 1.51 2024/01/23 17:57:21 mvs Exp $ */
/*
* Copyright (c) 2009 Internet Initiative Japan Inc.
struct cpumem;
+/* special iterator session */
+struct pipex_session_iterator {
+ /* Fields below should be in sync with pipex_session structure */
+ struct radix_node ps4_rn[2];
+ u_int flags; /* [I] flags, see below */
+ LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */
+};
+
/* pppac ip-extension session table */
struct pipex_session {
struct radix_node ps4_rn[2];
/* [L] tree glue, and other values */
-
- struct refcnt pxs_refcnt;
- struct mutex pxs_mtx;
+ u_int flags; /* [I] flags, see below */
+#define PIPEX_SFLAGS_MULTICAST 0x01 /* virtual entry for multicast */
+#define PIPEX_SFLAGS_PPPX 0x02 /* interface is
+ point2point(pppx) */
+#define PIPEX_SFLAGS_ITERATOR 0x04 /* iterator session */
LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */
LIST_ENTRY(pipex_session) state_list; /* [L] state list chain */
LIST_ENTRY(pipex_session) id_chain; /* [L] id hash chain */
LIST_ENTRY(pipex_session) peer_addr_chain;
/* [L] peer's address hash chain */
+ struct refcnt pxs_refcnt;
+ struct mutex pxs_mtx;
+
u_int state; /* [L] pipex session state */
#define PIPEX_STATE_INITIAL 0x0000
#define PIPEX_STATE_OPENED 0x0001
uint32_t idle_time; /* [L] idle time in seconds */
- u_int flags; /* [I] flags, see below */
-#define PIPEX_SFLAGS_MULTICAST 0x01 /* virtual entry for multicast */
-#define PIPEX_SFLAGS_PPPX 0x02 /* interface is
- point2point(pppx) */
-
uint16_t protocol; /* [I] tunnel protocol (PK) */
uint16_t session_id; /* [I] session-id (PK) */
uint16_t peer_session_id; /* [I] peer's session-id */
void pipex_timer_start (void);
void pipex_timer_stop (void);
void pipex_timer (void *);
+struct pipex_session *pipex_iterator(struct pipex_session *,
+ struct pipex_session_iterator *, void *);