Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 04 Feb 1999 00:18:46 +0100
From:      Poul-Henning Kamp <phk@FreeBSD.ORG>
To:        isdn@FreeBSD.ORG
Subject:   I4B PPP users, please test...
Message-ID:  <26029.918083926@critter.freebsd.dk>

next in thread | raw e-mail | index | archive | help

I'm trying to get the sppp code to behave less erratically in
various corner cases (loopbacks, leased lines and whatsnot).

This patch should hopefully not make things worse for ISDN
use of the sppp implementation, but to make sure before I
commit it, I'd like to hear back from a few people first.

Don't worry about the "b6" you will see in ifconfig, it means
that the isppp driver is "SMART" about the flags now, and a
minor patch to ifconfig will make it look smarter there too.

Poul-Henning


Index: i386/isa/if_ar.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/if_ar.c,v
retrieving revision 1.24
diff -u -r1.24 if_ar.c
--- if_ar.c	1998/12/16 18:42:38	1.24
+++ if_ar.c	1999/02/03 23:14:25
@@ -600,13 +600,6 @@
 
 	TRC(printf("ar%d: arioctl.\n", ifp->if_unit);)
 
-	if(cmd == SIOCSIFFLAGS) {
-		if(ifp->if_flags & IFF_LINK2)
-			sp->pp_flags |= PP_CISCO;
-		else
-			sp->pp_flags &= ~PP_CISCO;
-	}
-
 	was_up = ifp->if_flags & IFF_RUNNING;
 
 	error = sppp_ioctl(ifp, cmd, data);
Index: i386/isa/if_cx.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/if_cx.c,v
retrieving revision 1.26
diff -u -r1.26 if_cx.c
--- if_cx.c	1998/12/16 18:42:38	1.26
+++ if_cx.c	1999/02/03 23:15:21
@@ -827,10 +827,6 @@
 	if (! new.ext) {
 		struct sppp *sp = (struct sppp*) c->ifp;
 
-		if (new.cisco)
-			sp->pp_flags |= PP_CISCO;
-		else
-			sp->pp_flags &= ~PP_CISCO;
 		if (new.keepalive)
 			sp->pp_flags |= PP_KEEPALIVE;
 		else
Index: i386/isa/if_sr.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/if_sr.c,v
retrieving revision 1.21
diff -u -r1.21 if_sr.c
--- if_sr.c	1999/01/18 21:27:03	1.21
+++ if_sr.c	1999/02/03 23:15:32
@@ -1275,13 +1275,6 @@
 		ifp->if_flags &= ~IFF_LINK1;
 #endif
 
-		/*
-		 * Next we can handle minor protocol point(s)
-		 */
-		if (ifp->if_flags & IFF_LINK2)
-			sp->pp_flags |= PP_CISCO;
-		else
-			sp->pp_flags &= ~PP_CISCO;
 	}
 	/*
 	 * Next, we'll allow the network service layer we've called process
Index: net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.65
diff -u -r1.65 if.c
--- if.c	1999/02/01 20:03:27	1.65
+++ if.c	1999/02/03 21:01:39
@@ -604,6 +604,13 @@
 		error = suser(p->p_ucred, &p->p_acflag);
 		if (error)
 			return (error);
+		ifr->ifr_flags &= ~IFF_CANTCHANGE;
+		if (ifp->if_flags & IFF_SMART) {
+			if (ifp->if_ioctl)
+				(void) (*ifp->if_ioctl)(ifp, cmd, data);
+			getmicrotime(&ifp->if_lastchange);
+			break;
+		}
 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
 			int s = splimp();
 			if_down(ifp);
@@ -615,7 +622,7 @@
 			splx(s);
 		}
 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
-			(ifr->ifr_flags &~ IFF_CANTCHANGE);
+			ifr->ifr_flags;
 		if (ifp->if_ioctl)
 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
 		getmicrotime(&ifp->if_lastchange);
Index: net/if.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.49
diff -u -r1.49 if.h
--- if.h	1998/03/21 13:36:20	1.49
+++ if.h	1999/02/03 21:00:25
@@ -82,7 +82,7 @@
 #define	IFF_DEBUG	0x4		/* turn on debugging */
 #define	IFF_LOOPBACK	0x8		/* is a loopback net */
 #define	IFF_POINTOPOINT	0x10		/* interface is point-to-point link */
-/*#define IFF_NOTRAILERS 0x20		 * obsolete: avoid use of trailers */
+#define IFF_SMART	0x20		/* smart interface, don't muck with flags */
 #define	IFF_RUNNING	0x40		/* resources allocated */
 #define	IFF_NOARP	0x80		/* no address resolution protocol */
 #define	IFF_PROMISC	0x100		/* receive all packets */
@@ -97,7 +97,7 @@
 
 /* flags set internally only: */
 #define	IFF_CANTCHANGE \
-	(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
+	(IFF_BROADCAST|IFF_POINTOPOINT|IFF_SMART|IFF_RUNNING|IFF_OACTIVE|\
 	    IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
 
 #define	IFQ_MAXLEN	50
Index: net/if_sppp.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_sppp.h,v
retrieving revision 1.13
diff -u -r1.13 if_sppp.h
--- if_sppp.h	1998/12/27 21:30:44	1.13
+++ if_sppp.h	1999/02/03 21:42:25
@@ -83,7 +83,8 @@
 	struct  ifqueue pp_fastq; /* fast output queue */
 	struct	ifqueue pp_cpq;	/* PPP control protocol queue */
 	struct  sppp *pp_next;  /* next interface in keepalive list */
-	u_int   pp_flags;       /* use Cisco protocol instead of PPP */
+	u_short pp_mode;        /* operating mode */
+	u_short pp_flags;       /* various bits */
 	u_short pp_alivecnt;    /* keepalive packets counter */
 	u_short pp_loopcnt;     /* loopback detection counter */
 	u_long  pp_seq;         /* local sequence number */
@@ -132,11 +133,13 @@
 };
 
 #define PP_KEEPALIVE    0x01    /* use keepalive protocol */
-#define PP_CISCO        0x02    /* use Cisco protocol instead of PPP */
-				/* 0x04 was PP_TIMO */
 #define PP_CALLIN	0x08	/* we are being called */
 #define PP_NEEDAUTH	0x10	/* remote requested authentication */
 
+#define PPM_LEASED	0x00
+#define PPM_CISCO	0x01
+#define PPM_AUTO	0x02
+#define PPM_PASSIVE	0x03
 
 #define PP_MTU          1500    /* default/minimal MRU */
 #define PP_MAX_MRU	2048	/* maximal MRU we want to negotiate */
Index: net/if_spppsubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.52
diff -u -r1.52 if_spppsubr.c
--- if_spppsubr.c	1998/12/27 21:30:44	1.52
+++ if_spppsubr.c	1999/02/03 22:50:49
@@ -134,6 +134,7 @@
 
 #define IFF_PASSIVE	IFF_LINK0	/* wait passively for connection */
 #define IFF_AUTO	IFF_LINK1	/* auto-dial on output */
+#define IFF_CISCO	IFF_LINK2	/* cisco protocol */
 
 #define PPP_ALLSTATIONS 0xff		/* All-Stations broadcast address */
 #define PPP_UI		0x03		/* Unnumbered Information */
@@ -466,7 +467,7 @@
 	case PPP_ALLSTATIONS:
 		if (h->control != PPP_UI)
 			goto invalid;
-		if (sp->pp_flags & PP_CISCO) {
+		if (sp->pp_mode == PPM_CISCO) {
 			if (debug)
 				log(LOG_DEBUG,
 				    SPP_FMT "PPP packet in Cisco mode "
@@ -548,7 +549,7 @@
 	case CISCO_MULTICAST:
 	case CISCO_UNICAST:
 		/* Don't check the control field here (RFC 1547). */
-		if (! (sp->pp_flags & PP_CISCO)) {
+		if (sp->pp_mode != PPM_CISCO) {
 			if (debug)
 				log(LOG_DEBUG,
 				    SPP_FMT "Cisco packet in PPP mode "
@@ -711,7 +712,7 @@
 	 * (albeit due to the implementation it's always enough)
 	 */
 	h = mtod (m, struct ppp_header*);
-	if (sp->pp_flags & PP_CISCO) {
+	if (sp->pp_mode == PPM_CISCO) {
 		h->address = CISCO_UNICAST;        /* unicast address */
 		h->control = 0;
 	} else {
@@ -722,7 +723,7 @@
 	switch (dst->sa_family) {
 #ifdef INET
 	case AF_INET:   /* Internet Protocol */
-		if (sp->pp_flags & PP_CISCO)
+		if (sp->pp_mode == PPM_CISCO)
 			h->protocol = htons (ETHERTYPE_IP);
 		else {
 			/*
@@ -742,19 +743,19 @@
 #endif
 #ifdef NS
 	case AF_NS:     /* Xerox NS Protocol */
-		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?
+		h->protocol = htons ((sp->pp_mode == PPM_CISCO) ?
 			ETHERTYPE_NS : PPP_XNS);
 		break;
 #endif
 #ifdef IPX
 	case AF_IPX:     /* Novell IPX Protocol */
-		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?
+		h->protocol = htons ((sp->pp_mode == PPM_CISCO) ?
 			ETHERTYPE_IPX : PPP_IPX);
 		break;
 #endif
 #ifdef ISO
 	case AF_ISO:    /* ISO OSI Protocol */
-		if (sp->pp_flags & PP_CISCO)
+		if (sp->pp_mode == PPM_CISCO)
 			goto nosupport;
 		h->protocol = htons (PPP_ISO);
 		break;
@@ -806,7 +807,7 @@
 	spppq = sp;
 
 	sp->pp_if.if_mtu = PP_MTU;
-	sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+	sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_SMART;
 	sp->pp_if.if_type = IFT_PPP;
 	sp->pp_if.if_output = sppp_output;
 #if 0
@@ -898,7 +899,7 @@
 	 */
 	IF_DEQUEUE(&sp->pp_cpq, m);
 	if (m == NULL &&
-	    (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {
+	    (sppp_ncp_check(sp) || (sp->pp_mode == PPM_CISCO))) {
 		IF_DEQUEUE(&sp->pp_fastq, m);
 		if (m == NULL)
 			IF_DEQUEUE (&sp->pp_if.if_snd, m);
@@ -922,7 +923,7 @@
 	m = sp->pp_cpq.ifq_head;
 	if (m == NULL &&
 	    (sp->pp_phase == PHASE_NETWORK ||
-	     (sp->pp_flags & PP_CISCO) != 0))
+	     sp->pp_mode == PPM_CISCO))
 		if ((m = sp->pp_fastq.ifq_head) == NULL)
 			m = sp->pp_if.if_snd.ifq_head;
 	splx (s);
@@ -937,7 +938,7 @@
 {
 	struct ifreq *ifr = (struct ifreq*) data;
 	struct sppp *sp = (struct sppp*) ifp;
-	int s, rv, going_up, going_down, newmode;
+	int s, rv;
 
 	s = splimp();
 	rv = 0;
@@ -947,33 +948,56 @@
 		break;
 
 	case SIOCSIFADDR:
-		if_up(ifp);
-		/* fall through... */
+		break;
 
 	case SIOCSIFFLAGS:
-		going_up = ifp->if_flags & IFF_UP &&
-			(ifp->if_flags & IFF_RUNNING) == 0;
-		going_down = (ifp->if_flags & IFF_UP) == 0 &&
-			ifp->if_flags & IFF_RUNNING;
-		newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE);
-		if (newmode == (IFF_AUTO | IFF_PASSIVE)) {
-			/* sanity */
-			newmode = IFF_PASSIVE;
-			ifp->if_flags &= ~IFF_AUTO;
-		}
 
-		if (going_up || going_down)
+		printf("Flags %08x/%08x mode %d\n", 
+			ifp->if_flags, ifr->ifr_flags, sp->pp_mode);
+		if (sp->pp_mode != PPM_CISCO) 
 			lcp.Close(sp);
-		if (going_up && newmode == 0) {
-			/* neither auto-dial nor passive */
-			ifp->if_flags |= IFF_RUNNING;
-			if (!(sp->pp_flags & PP_CISCO))
-				lcp.Open(sp);
-		} else if (going_down) {
-			sppp_flush(ifp);
-			ifp->if_flags &= ~IFF_RUNNING;
+
+		ifp->if_flags &= ~(IFF_PASSIVE|IFF_AUTO|IFF_CISCO);
+		sp->pp_mode = PPM_LEASED;
+		if (ifr->ifr_flags & IFF_PASSIVE) {
+			sp->pp_mode = PPM_PASSIVE;
+			ifp->if_flags |= IFF_PASSIVE;
+		} else if (ifr->ifr_flags & IFF_AUTO) {
+			sp->pp_mode = PPM_AUTO;
+			ifp->if_flags |= IFF_AUTO;
+		} else if (ifr->ifr_flags & IFF_CISCO) {
+			sp->pp_mode = PPM_CISCO;
+			ifp->if_flags |= IFF_CISCO;
 		}
 
+		printf("Flags %08x/%08x mode %d\n", 
+			ifp->if_flags, ifr->ifr_flags, sp->pp_mode);
+
+		if ((ifr->ifr_flags & IFF_UP) && (ifp->if_flags & IFF_UP)) {
+			if (sp->pp_mode == PPM_LEASED)
+				lcp.Open(sp);
+		} else if ((ifr->ifr_flags & IFF_UP) != 
+		    (ifp->if_flags & IFF_UP)) {
+			s = splimp();
+			if (ifr->ifr_flags & IFF_UP)
+				if_route(ifp, IFF_UP, AF_UNSPEC);
+			else 
+				if_unroute(ifp, IFF_UP, AF_UNSPEC);
+			splx(s);
+			if (!(ifr->ifr_flags & IFF_UP)) {
+				sppp_flush(ifp);
+				ifp->if_flags &= ~IFF_RUNNING;
+			} else if (sp->pp_mode == PPM_LEASED) {
+				lcp.Open(sp);
+				ifp->if_flags |= IFF_RUNNING;
+			} else if (sp->pp_mode == PPM_CISCO) {
+				ifp->if_flags |= IFF_RUNNING;
+			}
+		}
+		ifp->if_flags &= ~(IFF_UP|IFF_DEBUG);
+		ifp->if_flags |= ifr->ifr_flags & (IFF_UP|IFF_DEBUG);
+		printf("Flags %08x/%08x mode %d\n", 
+			ifp->if_flags, ifr->ifr_flags, sp->pp_mode);
 		break;
 
 #ifdef SIOCSIFMTU
@@ -1511,13 +1535,12 @@
 		if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {
 			/* Line loopback mode detected. */
 			printf(SPP_FMT "loopback\n", SPP_ARGS(ifp));
-			if_down (ifp);
-			sppp_qflush (&sp->pp_cpq);
-
-			/* Shut down the PPP link. */
-			/* XXX */
-			lcp.Down(sp);
-			lcp.Up(sp);
+			if (sp->pp_mode == PPM_LEASED) {
+				lcp.Down(sp);
+				lcp.Up(sp);
+			} else if (sp->pp_mode != PPM_CISCO) {
+				lcp.Close(sp);
+			}
 			break;
 		}
 		*(long*)(h+1) = htonl (sp->lcp.magic);
@@ -1822,23 +1845,18 @@
 {
 	STDDCL;
 
+	log(LOG_INFO, SPP_FMT "Up event\n", SPP_ARGS(ifp));
 	/*
 	 * If this interface is passive or dial-on-demand, and we are
 	 * still in Initial state, it means we've got an incoming
 	 * call.  Activate the interface.
 	 */
-	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) {
-		if (debug)
-			log(LOG_DEBUG,
-			    SPP_FMT "Up event", SPP_ARGS(ifp));
+	if (sp->pp_mode == PPM_AUTO || sp->pp_mode == PPM_PASSIVE) {
 		ifp->if_flags |= IFF_RUNNING;
 		if (sp->state[IDX_LCP] == STATE_INITIAL) {
-			if (debug)
-				addlog("(incoming call)\n");
 			sp->pp_flags |= PP_CALLIN;
 			lcp.Open(sp);
-		} else if (debug)
-			addlog("\n");
+		} 
 	}
 
 	sppp_up_event(&lcp, sp);
@@ -1849,30 +1867,14 @@
 {
 	STDDCL;
 
+	log(LOG_INFO, SPP_FMT "Down event\n", SPP_ARGS(ifp));
+
 	sppp_down_event(&lcp, sp);
 
-	/*
-	 * If this is neither a dial-on-demand nor a passive
-	 * interface, simulate an ``ifconfig down'' action, so the
-	 * administrator can force a redial by another ``ifconfig
-	 * up''.  XXX For leased line operation, should we immediately
-	 * try to reopen the connection here?
-	 */
-	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) {
-		log(LOG_INFO,
-		    SPP_FMT "Down event, taking interface down.\n",
-		    SPP_ARGS(ifp));
-		if_down(ifp);
-	} else {
-		if (debug)
-			log(LOG_DEBUG,
-			    SPP_FMT "Down event (carrier loss)\n",
-			    SPP_ARGS(ifp));
-	}
-	sp->pp_flags &= ~PP_CALLIN;
-	if (sp->state[IDX_LCP] != STATE_INITIAL)
+	if (sp->pp_mode == PPM_AUTO || sp->pp_mode == PPM_PASSIVE) {
+		sp->pp_flags &= ~PP_CALLIN;
 		lcp.Close(sp);
-	ifp->if_flags &= ~IFF_RUNNING;
+	}
 }
 
 static void
@@ -1892,7 +1894,14 @@
 static void
 sppp_lcp_close(struct sppp *sp)
 {
+	STDDCL;
+
 	sppp_close_event(&lcp, sp);
+	if (sp->pp_mode == PPM_AUTO || sp->pp_mode == PPM_PASSIVE) {
+		if_down(ifp);
+		ifp->if_flags &= ~IFF_RUNNING;
+		sppp_qflush (&sp->pp_cpq);
+	}
 }
 
 static void
@@ -2018,32 +2027,17 @@
 			}
 			/*
 			 * Local and remote magics equal -- loopback?
-			 */
-			if (sp->pp_loopcnt >= MAXALIVECNT*5) {
-				printf (SPP_FMT "loopback\n",
-					SPP_ARGS(ifp));
-				sp->pp_loopcnt = 0;
-				if (ifp->if_flags & IFF_UP) {
-					if_down(ifp);
-					sppp_qflush(&sp->pp_cpq);
-					/* XXX ? */
-					lcp.Down(sp);
-					lcp.Up(sp);
-				}
-			} else if (debug)
-				addlog("[glitch] ");
-			++sp->pp_loopcnt;
-			/*
-			 * We negate our magic here, and NAK it.  If
-			 * we see it later in an NAK packet, we
-			 * suggest a new one.
+			 * Choose new magic and ignore this packet...
 			 */
-			nmagic = ~sp->lcp.magic;
-			/* Gonna NAK it. */
-			p[2] = nmagic >> 24;
-			p[3] = nmagic >> 16;
-			p[4] = nmagic >> 8;
-			p[5] = nmagic;
+			if (debug)
+				addlog("loopback ? \n");
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+			sp->lcp.magic = random();
+#else
+			sp->lcp.magic = time.tv_sec + time.tv_usec;
+#endif
+			free (buf, M_TEMP);
+			return (0);
 			break;
 
 		case LCP_OPT_ASYNC_MAP:
@@ -2221,7 +2215,7 @@
 				 */
 				if (magic == ~sp->lcp.magic) {
 					if (debug)
-						addlog("magic glitch ");
+						addlog("glitch ");
 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
 					sp->lcp.magic = random();
 #else
@@ -3813,26 +3807,23 @@
 			continue;
 
 		/* No keepalive in PPP mode if LCP not opened yet. */
-		if (! (sp->pp_flags & PP_CISCO) &&
+		if (sp->pp_mode != PPM_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_flags & PP_CISCO)) {
-				/* XXX */
-				/* Shut down the PPP link. */
+			printf (SPP_FMT "no keepalives\n", SPP_ARGS(ifp));
+			if (sp->pp_mode == PPM_LEASED) {
 				lcp.Down(sp);
-				/* Initiate negotiation. XXX */
 				lcp.Up(sp);
+			} else if (sp->pp_mode != PPM_CISCO) {
+				lcp.Close(sp);
 			}
 		}
 		if (sp->pp_alivecnt <= MAXALIVECNT)
 			++sp->pp_alivecnt;
-		if (sp->pp_flags & PP_CISCO)
+		if (sp->pp_mode == PPM_CISCO)
 			sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,
 				sp->pp_rseq);
 		else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
--
Poul-Henning Kamp             FreeBSD coreteam member
phk@FreeBSD.ORG               "Real hackers run -current on their laptop."
FreeBSD -- It will take a long time before progress goes too far!

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-isdn" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?26029.918083926>