summaryrefslogtreecommitdiffstats
path: root/sys/net/if_spppsubr.c
diff options
context:
space:
mode:
authorrik <rik@FreeBSD.org>2004-12-12 14:54:15 +0000
committerrik <rik@FreeBSD.org>2004-12-12 14:54:15 +0000
commita09ae8d2bf0fca60091670de2c7a81a8335f82c8 (patch)
treeff8a4d488990fc99db4c6cf0d6e23b283298a427 /sys/net/if_spppsubr.c
parent729dda8f41bc7c5ec5b66365091b7cb2217b9cfa (diff)
downloadFreeBSD-src-a09ae8d2bf0fca60091670de2c7a81a8335f82c8.zip
FreeBSD-src-a09ae8d2bf0fca60091670de2c7a81a8335f82c8.tar.gz
Make sppp MPSAFE.
MPSAFE could be turned off by IFF_NEEDSGIANT. Silence on: net@, current@, hackers@. No objections: joerg
Diffstat (limited to 'sys/net/if_spppsubr.c')
-rw-r--r--sys/net/if_spppsubr.c339
1 files changed, 229 insertions, 110 deletions
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 7101975..98f634c 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -92,12 +92,8 @@
#include <net/if_sppp.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle)
-# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2)
# define IOCTL_CMD_T u_long
#else
-# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg)
-# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2)
# define IOCTL_CMD_T int
#endif
@@ -259,11 +255,6 @@ struct cp {
void (*scr)(struct sppp *sp);
};
-static struct sppp *spppq;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-static struct callout_handle keepalive_ch;
-#endif
-
#if defined(__FreeBSD__) && __FreeBSD__ >= 3 && __FreeBSD_version < 501113
#define SPP_FMT "%s%d: "
#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit
@@ -272,6 +263,26 @@ static struct callout_handle keepalive_ch;
#define SPP_ARGS(ifp) (ifp)->if_xname
#endif
+#define SPPP_LOCK(sp) \
+ do { \
+ if (!((sp)->pp_if.if_flags & IFF_NEEDSGIANT)) \
+ mtx_lock (&(sp)->mtx); \
+ } while (0)
+#define SPPP_UNLOCK(sp) \
+ do { \
+ if (!((sp)->pp_if.if_flags & IFF_NEEDSGIANT)) \
+ mtx_unlock (&(sp)->mtx); \
+ } while (0)
+
+#define SPPP_LOCK_ASSERT(sp) \
+ do { \
+ if (!((sp)->pp_if.if_flags & IFF_NEEDSGIANT)) \
+ mtx_assert (&(sp)->mtx, MA_OWNED); \
+ } while (0)
+#define SPPP_LOCK_OWNED(sp) \
+ (!((sp)->pp_if.if_flags & IFF_NEEDSGIANT) && \
+ mtx_owned (&sp->mtx))
+
#ifdef INET
/*
* The following disgusting hack gets around the problem that IP TOS
@@ -318,6 +329,9 @@ static void sppp_to_event(const struct cp *cp, struct sppp *sp);
static void sppp_null(struct sppp *sp);
+static void sppp_pp_up(struct sppp *sp);
+static void sppp_pp_down(struct sppp *sp);
+
static void sppp_lcp_init(struct sppp *sp);
static void sppp_lcp_up(struct sppp *sp);
static void sppp_lcp_down(struct sppp *sp);
@@ -415,6 +429,9 @@ static void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src);
static void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src);
#endif
+/* if_start () wrapper */
+static void sppp_ifstart (struct ifnet *ifp);
+
/* our control protocol descriptors */
static const struct cp lcp = {
PPP_LCP, IDX_LCP, CP_LCP, "lcp",
@@ -512,7 +529,10 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
struct sppp *sp = (struct sppp *)ifp;
u_char *iphdr;
int hlen, vjlen, do_account = 0;
- int debug = ifp->if_flags & IFF_DEBUG;
+ int debug;
+
+ SPPP_LOCK(sp);
+ debug = ifp->if_flags & IFF_DEBUG;
if (ifp->if_flags & IFF_UP)
/* Count received bytes, add FCS and one flag */
@@ -526,6 +546,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
SPP_ARGS(ifp), m->m_pkthdr.len);
drop:
m_freem (m);
+ SPPP_UNLOCK(sp);
drop2:
++ifp->if_ierrors;
++ifp->if_iqdrops;
@@ -566,22 +587,26 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
case PPP_LCP:
sppp_cp_input(&lcp, sp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
case PPP_PAP:
if (sp->pp_phase >= PHASE_AUTHENTICATE)
sppp_pap_input(sp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
case PPP_CHAP:
if (sp->pp_phase >= PHASE_AUTHENTICATE)
sppp_chap_input(sp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
#ifdef INET
case PPP_IPCP:
if (sp->pp_phase == PHASE_NETWORK)
sppp_cp_input(&ipcp, sp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
case PPP_IP:
if (sp->state[IDX_IPCP] == STATE_OPENED) {
@@ -612,8 +637,10 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
*/
m_adj(m, vjlen);
M_PREPEND(m, hlen, M_DONTWAIT);
- if (m == NULL)
+ if (m == NULL) {
+ SPPP_UNLOCK(sp);
goto drop2;
+ }
bcopy(iphdr, mtod(m, u_char *), hlen);
isr = NETISR_IP;
}
@@ -642,6 +669,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
if (sp->pp_phase == PHASE_NETWORK)
sppp_cp_input(&ipv6cp, sp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
case PPP_IPV6:
@@ -679,6 +707,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
case CISCO_KEEPALIVE:
sppp_cisco_input ((struct sppp*) ifp, m);
m_freem (m);
+ SPPP_UNLOCK(sp);
return;
#ifdef INET
case ETHERTYPE_IP:
@@ -714,6 +743,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
if (! (ifp->if_flags & IFF_UP) || isr == -1)
goto drop;
+ SPPP_UNLOCK(sp);
/* Check queue. */
if (netisr_queue(isr, m)) { /* (0) on success. */
if (debug)
@@ -721,6 +751,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
SPP_ARGS(ifp));
goto drop2;
}
+
if (do_account)
/*
* Do only account for network packets, not for control
@@ -730,6 +761,32 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
sp->pp_last_recv = time_second;
}
+static void
+sppp_ifstart_sched(void *dummy)
+{
+ struct sppp *sp = dummy;
+
+ sp->if_start(&sp->pp_if);
+}
+
+/* if_start () wrapper function. We use it to schedule real if_start () for
+ * execution. We can't call it directly
+ */
+static void
+sppp_ifstart(struct ifnet *ifp)
+{
+ struct sppp *sp = (struct sppp*) ifp;
+
+ if (SPPP_LOCK_OWNED(sp)) {
+ if (callout_pending(&sp->ifstart_callout))
+ return;
+ callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched,
+ (void *)sp);
+ } else {
+ sp->if_start(ifp);
+ }
+}
+
/*
* Enqueue transmit packet.
*/
@@ -745,6 +802,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
int debug = ifp->if_flags & IFF_DEBUG;
s = splimp();
+ SPPP_LOCK(sp);
if ((ifp->if_flags & IFF_UP) == 0 ||
(ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) {
@@ -752,6 +810,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
drop:
#endif
m_freem (m);
+ SPPP_UNLOCK(sp);
splx (s);
return (ENETDOWN);
}
@@ -800,6 +859,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */
{
m_freem(m);
+ SPPP_UNLOCK(sp);
splx(s);
if(ip->ip_p == IPPROTO_TCP)
return(EADDRNOTAVAIL);
@@ -829,8 +889,8 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
/*
* Do IP Header compression
*/
- if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) &&
- ip->ip_p == IPPROTO_TCP)
+ if (sp->pp_mode != IFF_CISCO &&
+ (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP)
switch (sl_compress_tcp(m, ip, sp->pp_comp,
sp->ipcp.compress_cid)) {
case TYPE_COMPRESSED_TCP:
@@ -844,6 +904,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
break;
default:
m_freem(m);
+ SPPP_UNLOCK(sp);
splx(s);
return (EINVAL);
}
@@ -865,6 +926,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n",
SPP_ARGS(ifp));
++ifp->if_oerrors;
+ SPPP_UNLOCK(sp);
splx (s);
return (ENOBUFS);
}
@@ -931,6 +993,7 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
default:
m_freem (m);
++ifp->if_oerrors;
+ SPPP_UNLOCK(sp);
splx (s);
return (EAFNOSUPPORT);
}
@@ -945,9 +1008,11 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
IFQ_HANDOFF_ADJ(ifp, m, 3, error);
if (error) {
++ifp->if_oerrors;
+ SPPP_UNLOCK(sp);
splx (s);
return (rv? rv: ENOBUFS);
}
+ SPPP_UNLOCK(sp);
splx (s);
/*
* Unlike in sppp_input(), we can always bump the timestamp
@@ -964,13 +1029,14 @@ sppp_attach(struct ifnet *ifp)
{
struct sppp *sp = (struct sppp*) ifp;
+ /* Initialize mtx lock */
+ mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE);
+
/* Initialize keepalive handler. */
- if (spppq == NULL)
- TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch);
-
- /* Insert new entry into the keepalive list. */
- sp->pp_next = spppq;
- spppq = sp;
+ callout_init(&sp->keepalive_callout,
+ (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
+ callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive,
+ (void *)sp);
sp->pp_if.if_mtu = PP_MTU;
sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
@@ -987,8 +1053,8 @@ sppp_attach(struct ifnet *ifp)
bzero(&sp->pp_seq[0], sizeof(sp->pp_seq));
bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq));
sp->pp_phase = PHASE_DEAD;
- sp->pp_up = lcp.Up;
- sp->pp_down = lcp.Down;
+ sp->pp_up = sppp_pp_up;
+ sp->pp_down = sppp_pp_down;
if(!mtx_initialized(&sp->pp_cpq.ifq_mtx))
mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF);
if(!mtx_initialized(&sp->pp_fastq.ifq_mtx))
@@ -1001,6 +1067,10 @@ sppp_attach(struct ifnet *ifp)
#ifdef INET6
sp->confflags |= CONF_ENABLE_IPV6;
#endif
+ callout_init(&sp->ifstart_callout,
+ (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
+ sp->if_start = ifp->if_start;
+ ifp->if_start = sppp_ifstart;
sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK);
sl_compress_init(sp->pp_comp, -1);
sppp_lcp_init(sp);
@@ -1013,32 +1083,31 @@ sppp_attach(struct ifnet *ifp)
void
sppp_detach(struct ifnet *ifp)
{
- struct sppp **q, *p, *sp = (struct sppp*) ifp;
+ struct sppp *sp = (struct sppp*) ifp;
int i;
- /* Remove the entry from the keepalive list. */
- for (q = &spppq; (p = *q); q = &p->pp_next)
- if (p == sp) {
- *q = p->pp_next;
- break;
- }
+ KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized"));
/* Stop keepalive handler. */
- if (spppq == NULL)
- UNTIMEOUT(sppp_keepalive, 0, keepalive_ch);
+ if (!callout_drain(&sp->keepalive_callout))
+ callout_stop(&sp->keepalive_callout);
- for (i = 0; i < IDX_COUNT; i++)
- UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]);
- UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
+ for (i = 0; i < IDX_COUNT; i++) {
+ if (!callout_drain(&sp->ch[i]))
+ callout_stop(&sp->ch[i]);
+ }
+ if (!callout_drain(&sp->pap_my_to_ch))
+ callout_stop(&sp->pap_my_to_ch);
mtx_destroy(&sp->pp_cpq.ifq_mtx);
mtx_destroy(&sp->pp_fastq.ifq_mtx);
+ mtx_destroy(&sp->mtx);
}
/*
* Flush the interface output queue.
*/
-void
-sppp_flush(struct ifnet *ifp)
+static void
+sppp_flush_unlocked(struct ifnet *ifp)
{
struct sppp *sp = (struct sppp*) ifp;
@@ -1047,6 +1116,16 @@ sppp_flush(struct ifnet *ifp)
sppp_qflush (&sp->pp_cpq);
}
+void
+sppp_flush(struct ifnet *ifp)
+{
+ struct sppp *sp = (struct sppp*) ifp;
+
+ SPPP_LOCK(sp);
+ sppp_flush_unlocked (ifp);
+ SPPP_UNLOCK(sp);
+}
+
/*
* Check if the output queue is empty.
*/
@@ -1057,8 +1136,10 @@ sppp_isempty(struct ifnet *ifp)
int empty, s;
s = splimp();
+ SPPP_LOCK(sp);
empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
!sp->pp_if.if_snd.ifq_head;
+ SPPP_UNLOCK(sp);
splx(s);
return (empty);
}
@@ -1074,6 +1155,7 @@ sppp_dequeue(struct ifnet *ifp)
int s;
s = splimp();
+ SPPP_LOCK(sp);
/*
* Process only the control protocol queue until we have at
* least one NCP open.
@@ -1087,6 +1169,7 @@ sppp_dequeue(struct ifnet *ifp)
if (m == NULL)
IF_DEQUEUE (&sp->pp_if.if_snd, m);
}
+ SPPP_UNLOCK(sp);
splx(s);
return m;
}
@@ -1101,13 +1184,16 @@ sppp_pick(struct ifnet *ifp)
struct mbuf *m;
int s;
- s= splimp ();
+ s = splimp ();
+ SPPP_LOCK(sp);
m = sp->pp_cpq.ifq_head;
if (m == NULL &&
- (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO))
+ (sp->pp_phase == PHASE_NETWORK ||
+ sp->pp_mode == IFF_CISCO))
if ((m = sp->pp_fastq.ifq_head) == NULL)
m = sp->pp_if.if_snd.ifq_head;
+ SPPP_UNLOCK(sp);
splx (s);
return (m);
}
@@ -1123,6 +1209,7 @@ sppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data)
int s, rv, going_up, going_down, newmode;
s = splimp();
+ SPPP_LOCK(sp);
rv = 0;
switch (cmd) {
case SIOCAIFADDR:
@@ -1159,7 +1246,7 @@ sppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data)
lcp.Close(sp);
else if (sp->pp_tlf)
(sp->pp_tlf)(sp);
- sppp_flush(ifp);
+ sppp_flush_unlocked(ifp);
ifp->if_flags &= ~IFF_RUNNING;
sp->pp_mode = newmode;
}
@@ -1220,6 +1307,7 @@ sppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data)
default:
rv = ENOTTY;
}
+ SPPP_UNLOCK(sp);
splx(s);
return rv;
}
@@ -1977,6 +2065,7 @@ sppp_to_event(const struct cp *cp, struct sppp *sp)
int s;
s = splimp();
+ SPPP_LOCK(sp);
if (debug)
log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n",
SPP_ARGS(ifp), cp->name,
@@ -2008,8 +2097,8 @@ sppp_to_event(const struct cp *cp, struct sppp *sp)
case STATE_STOPPING:
sppp_cp_send(sp, cp->proto, TERM_REQ,
++sp->pp_seq[cp->protoidx], 0, 0);
- TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout,
- sp->ch[cp->protoidx]);
+ callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
+ cp->TO, (void *)sp);
break;
case STATE_REQ_SENT:
case STATE_ACK_RCVD:
@@ -2019,11 +2108,12 @@ sppp_to_event(const struct cp *cp, struct sppp *sp)
break;
case STATE_ACK_SENT:
(cp->scr)(sp);
- TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout,
- sp->ch[cp->protoidx]);
+ callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
+ cp->TO, (void *)sp);
break;
}
+ SPPP_UNLOCK(sp);
splx(s);
}
@@ -2036,7 +2126,8 @@ sppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate)
{
sp->state[cp->protoidx] = newstate;
- UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]);
+ callout_stop (&sp->ch[cp->protoidx]);
+
switch (newstate) {
case STATE_INITIAL:
case STATE_STARTING:
@@ -2049,8 +2140,8 @@ sppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate)
case STATE_REQ_SENT:
case STATE_ACK_RCVD:
case STATE_ACK_SENT:
- TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout,
- sp->ch[cp->protoidx]);
+ callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
+ cp->TO, (void *)sp);
break;
}
}
@@ -2063,6 +2154,22 @@ sppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate)
*--------------------------------------------------------------------------*
*/
static void
+sppp_pp_up(struct sppp *sp)
+{
+ SPPP_LOCK(sp);
+ lcp.Up(sp);
+ SPPP_UNLOCK(sp);
+}
+
+static void
+sppp_pp_down(struct sppp *sp)
+{
+ SPPP_LOCK(sp);
+ lcp.Down(sp);
+ SPPP_UNLOCK(sp);
+}
+
+static void
sppp_lcp_init(struct sppp *sp)
{
sp->lcp.opts = (1 << LCP_OPT_MAGIC);
@@ -2079,9 +2186,8 @@ sppp_lcp_init(struct sppp *sp)
sp->lcp.max_terminate = 2;
sp->lcp.max_configure = 10;
sp->lcp.max_failure = 10;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- callout_handle_init(&sp->ch[IDX_LCP]);
-#endif
+ callout_init(&sp->ch[IDX_LCP],
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
}
static void
@@ -2775,9 +2881,8 @@ sppp_ipcp_init(struct sppp *sp)
sp->fail_counter[IDX_IPCP] = 0;
sp->pp_seq[IDX_IPCP] = 0;
sp->pp_rseq[IDX_IPCP] = 0;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- callout_handle_init(&sp->ch[IDX_IPCP]);
-#endif
+ callout_init(&sp->ch[IDX_IPCP],
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
}
static void
@@ -3260,12 +3365,8 @@ sppp_ipv6cp_init(struct sppp *sp)
sp->fail_counter[IDX_IPV6CP] = 0;
sp->pp_seq[IDX_IPV6CP] = 0;
sp->pp_rseq[IDX_IPV6CP] = 0;
-#if defined(__NetBSD__)
- callout_init(&sp->ch[IDX_IPV6CP]);
-#endif
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- callout_handle_init(&sp->ch[IDX_IPV6CP]);
-#endif
+ callout_init(&sp->ch[IDX_IPV6CP],
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
}
static void
@@ -3916,6 +4017,7 @@ sppp_chap_input(struct sppp *sp, struct mbuf *m)
log(-1, "\n");
}
x = splimp();
+ SPPP_LOCK(sp);
sp->pp_flags &= ~PP_NEEDAUTH;
if (sp->myauth.proto == PPP_CHAP &&
(sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) &&
@@ -3925,9 +4027,11 @@ sppp_chap_input(struct sppp *sp, struct mbuf *m)
* complete yet. Leave it to tlu to proceed
* to network phase.
*/
+ SPPP_UNLOCK(sp);
splx(x);
break;
}
+ SPPP_UNLOCK(sp);
splx(x);
sppp_phase_network(sp);
break;
@@ -4062,9 +4166,8 @@ sppp_chap_init(struct sppp *sp)
sp->fail_counter[IDX_CHAP] = 0;
sp->pp_seq[IDX_CHAP] = 0;
sp->pp_rseq[IDX_CHAP] = 0;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- callout_handle_init(&sp->ch[IDX_CHAP]);
-#endif
+ callout_init(&sp->ch[IDX_CHAP],
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
}
static void
@@ -4095,6 +4198,7 @@ sppp_chap_TO(void *cookie)
int s;
s = splimp();
+ SPPP_LOCK(sp);
if (debug)
log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n",
SPP_ARGS(ifp),
@@ -4123,6 +4227,7 @@ sppp_chap_TO(void *cookie)
break;
}
+ SPPP_UNLOCK(sp);
splx(s);
}
@@ -4147,7 +4252,7 @@ sppp_chap_tlu(struct sppp *sp)
* a number between 300 and 810 seconds.
*/
i = 300 + ((unsigned)(random() & 0xff00) >> 7);
- TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]);
+ callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp);
}
if (debug) {
@@ -4162,6 +4267,7 @@ sppp_chap_tlu(struct sppp *sp)
}
x = splimp();
+ SPPP_LOCK(sp);
/* indicate to LCP that we need to be closed down */
sp->lcp.protos |= (1 << IDX_CHAP);
@@ -4171,9 +4277,11 @@ sppp_chap_tlu(struct sppp *sp)
* complete yet. Defer the transition to network
* phase.
*/
+ SPPP_UNLOCK(sp);
splx(x);
return;
}
+ SPPP_UNLOCK(sp);
splx(x);
/*
@@ -4191,7 +4299,7 @@ sppp_chap_tld(struct sppp *sp)
if (debug)
log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp));
- UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]);
+ callout_stop(&sp->ch[IDX_CHAP]);
sp->lcp.protos &= ~(1 << IDX_CHAP);
lcp.Close(sp);
@@ -4327,7 +4435,7 @@ sppp_pap_input(struct sppp *sp, struct mbuf *m)
/* ack and nak are his authproto */
case PAP_ACK:
- UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
+ callout_stop(&sp->pap_my_to_ch);
if (debug) {
log(LOG_DEBUG, SPP_FMT "pap success",
SPP_ARGS(ifp));
@@ -4339,6 +4447,7 @@ sppp_pap_input(struct sppp *sp, struct mbuf *m)
log(-1, "\n");
}
x = splimp();
+ SPPP_LOCK(sp);
sp->pp_flags &= ~PP_NEEDAUTH;
if (sp->myauth.proto == PPP_PAP &&
(sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) &&
@@ -4348,15 +4457,17 @@ sppp_pap_input(struct sppp *sp, struct mbuf *m)
* complete yet. Leave it to tlu to proceed
* to network phase.
*/
+ SPPP_UNLOCK(sp);
splx(x);
break;
}
+ SPPP_UNLOCK(sp);
splx(x);
sppp_phase_network(sp);
break;
case PAP_NAK:
- UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
+ callout_stop (&sp->pap_my_to_ch);
if (debug) {
log(LOG_INFO, SPP_FMT "pap failure",
SPP_ARGS(ifp));
@@ -4395,10 +4506,10 @@ sppp_pap_init(struct sppp *sp)
sp->fail_counter[IDX_PAP] = 0;
sp->pp_seq[IDX_PAP] = 0;
sp->pp_rseq[IDX_PAP] = 0;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- callout_handle_init(&sp->ch[IDX_PAP]);
- callout_handle_init(&sp->pap_my_to_ch);
-#endif
+ callout_init(&sp->ch[IDX_PAP],
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
+ callout_init(&sp->pap_my_to_ch,
+ (sp->pp_if.if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE);
}
static void
@@ -4413,8 +4524,8 @@ sppp_pap_open(struct sppp *sp)
if (sp->myauth.proto == PPP_PAP) {
/* we are peer, send a request, and start a timer */
pap.scr(sp);
- TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout,
- sp->pap_my_to_ch);
+ callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout,
+ sppp_pap_my_TO, (void *)sp);
}
}
@@ -4437,6 +4548,7 @@ sppp_pap_TO(void *cookie)
int s;
s = splimp();
+ SPPP_LOCK(sp);
if (debug)
log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n",
SPP_ARGS(ifp),
@@ -4460,6 +4572,7 @@ sppp_pap_TO(void *cookie)
break;
}
+ SPPP_UNLOCK(sp);
splx(s);
}
@@ -4478,7 +4591,9 @@ sppp_pap_my_TO(void *cookie)
log(LOG_DEBUG, SPP_FMT "pap peer TO\n",
SPP_ARGS(ifp));
+ SPPP_LOCK(sp);
pap.scr(sp);
+ SPPP_UNLOCK(sp);
}
static void
@@ -4494,6 +4609,7 @@ sppp_pap_tlu(struct sppp *sp)
SPP_ARGS(ifp), pap.name);
x = splimp();
+ SPPP_LOCK(sp);
/* indicate to LCP that we need to be closed down */
sp->lcp.protos |= (1 << IDX_PAP);
@@ -4503,9 +4619,11 @@ sppp_pap_tlu(struct sppp *sp)
* complete yet. Defer the transition to network
* phase.
*/
+ SPPP_UNLOCK(sp);
splx(x);
return;
}
+ SPPP_UNLOCK(sp);
splx(x);
sppp_phase_network(sp);
}
@@ -4517,8 +4635,8 @@ sppp_pap_tld(struct sppp *sp)
if (debug)
log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp));
- UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]);
- UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
+ callout_stop (&sp->ch[IDX_PAP]);
+ callout_stop (&sp->pap_my_to_ch);
sp->lcp.protos &= ~(1 << IDX_PAP);
lcp.Close(sp);
@@ -4642,50 +4760,51 @@ sppp_qflush(struct ifqueue *ifq)
static void
sppp_keepalive(void *dummy)
{
- struct sppp *sp;
+ struct sppp *sp = (struct sppp*)dummy;
+ struct ifnet *ifp = &sp->pp_if;
int s;
s = splimp();
- for (sp=spppq; sp; sp=sp->pp_next) {
- struct ifnet *ifp = &sp->pp_if;
-
- /* Keepalive mode disabled or channel down? */
- if (! (sp->pp_flags & PP_KEEPALIVE) ||
- ! (ifp->if_flags & IFF_RUNNING))
- continue;
-
- /* No keepalive in PPP mode if LCP not opened yet. */
- if (sp->pp_mode != IFF_CISCO &&
- sp->pp_phase < PHASE_AUTHENTICATE)
- continue;
-
- if (sp->pp_alivecnt == MAXALIVECNT) {
- /* No keepalive packets got. Stop the interface. */
- printf (SPP_FMT "down\n", SPP_ARGS(ifp));
- if_down (ifp);
- sppp_qflush (&sp->pp_cpq);
- if (sp->pp_mode != IFF_CISCO) {
- /* XXX */
- /* Shut down the PPP link. */
- lcp.Down(sp);
- /* Initiate negotiation. XXX */
- lcp.Up(sp);
- }
- }
- if (sp->pp_alivecnt <= MAXALIVECNT)
- ++sp->pp_alivecnt;
- if (sp->pp_mode == IFF_CISCO)
- sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ,
- ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]);
- else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
- long nmagic = htonl (sp->lcp.magic);
- sp->lcp.echoid = ++sp->pp_seq[IDX_LCP];
- sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
- sp->lcp.echoid, 4, &nmagic);
+ SPPP_LOCK(sp);
+ /* Keepalive mode disabled or channel down? */
+ if (! (sp->pp_flags & PP_KEEPALIVE) ||
+ ! (ifp->if_flags & IFF_RUNNING))
+ goto out;
+
+ /* No keepalive in PPP mode if LCP not opened yet. */
+ if (sp->pp_mode != IFF_CISCO &&
+ sp->pp_phase < PHASE_AUTHENTICATE)
+ goto out;
+
+ if (sp->pp_alivecnt == MAXALIVECNT) {
+ /* No keepalive packets got. Stop the interface. */
+ printf (SPP_FMT "down\n", SPP_ARGS(ifp));
+ if_down (ifp);
+ sppp_qflush (&sp->pp_cpq);
+ if (sp->pp_mode != IFF_CISCO) {
+ /* XXX */
+ /* Shut down the PPP link. */
+ lcp.Down(sp);
+ /* Initiate negotiation. XXX */
+ lcp.Up(sp);
}
}
+ if (sp->pp_alivecnt <= MAXALIVECNT)
+ ++sp->pp_alivecnt;
+ if (sp->pp_mode == IFF_CISCO)
+ sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ,
+ ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]);
+ else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
+ long nmagic = htonl (sp->lcp.magic);
+ sp->lcp.echoid = ++sp->pp_seq[IDX_LCP];
+ sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
+ sp->lcp.echoid, 4, &nmagic);
+ }
+out:
+ SPPP_UNLOCK(sp);
splx(s);
- TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch);
+ callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive,
+ (void *)sp);
}
/*
OpenPOWER on IntegriCloud