summaryrefslogtreecommitdiffstats
path: root/sys/net/if_spppsubr.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-10-04 22:24:16 +0000
committerjkh <jkh@FreeBSD.org>1995-10-04 22:24:16 +0000
commit8a1fa70dc0da9908f692ff6de5fe8ca9cad9f310 (patch)
tree2fe87f819c9da98ccb878d0641f4b626f15c348d /sys/net/if_spppsubr.c
parent1c1ef85e1307f05f0ae122e54088a9f8e7425ef7 (diff)
downloadFreeBSD-src-8a1fa70dc0da9908f692ff6de5fe8ca9cad9f310.zip
FreeBSD-src-8a1fa70dc0da9908f692ff6de5fe8ca9cad9f310.tar.gz
This upgrades the driver for Cronyx-Sigma multiplexor boards
from version 1.2 to version 1.9. Submitted by: Serge Vakulenko, <vak@cronyx.ru>
Diffstat (limited to 'sys/net/if_spppsubr.c')
-rw-r--r--sys/net/if_spppsubr.c569
1 files changed, 337 insertions, 232 deletions
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 38b60ca..e8a9576 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -12,7 +12,7 @@
* or modify this software as long as this message is kept with the software,
* all derivative works or modified versions.
*
- * Version 1.1, Thu Oct 27 21:13:59 MSK 1994
+ * Version 1.9, Wed Oct 4 18:58:15 MSK 1995
*/
#undef DEBUG
@@ -53,7 +53,7 @@
#ifdef DEBUG
#define print(s) printf s
#else
-#define print(s) /*void*/
+#define print(s) {/*void*/}
#endif
#define MAXALIVECNT 3 /* max. alive packets */
@@ -103,26 +103,26 @@
#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */
struct ppp_header {
- unsigned char address;
- unsigned char control;
- unsigned short protocol;
+ u_char address;
+ u_char control;
+ u_short protocol;
};
#define PPP_HEADER_LEN sizeof (struct ppp_header)
struct lcp_header {
- unsigned char type;
- unsigned char ident;
- unsigned short len;
+ u_char type;
+ u_char ident;
+ u_short len;
};
#define LCP_HEADER_LEN sizeof (struct lcp_header)
struct cisco_packet {
- unsigned long type;
- unsigned long par1;
- unsigned long par2;
- unsigned short rel;
- unsigned short time0;
- unsigned short time1;
+ u_long type;
+ u_long par1;
+ u_long par2;
+ u_short rel;
+ u_short time0;
+ u_short time1;
};
#define CISCO_PACKET_LEN 18
@@ -134,27 +134,37 @@ struct sppp *spppq;
* priority queue. To decide if traffic is interactive, we check that
* a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
*/
-static unsigned short interactive_ports[8] = {
+static u_short interactive_ports[8] = {
0, 513, 0, 0,
0, 21, 0, 23,
};
#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
-void sppp_keepalive (void *dummy1);
-void sppp_cp_send (struct sppp *sp, unsigned short proto, unsigned char type,
- unsigned char ident, unsigned short len, void *data);
+/*
+ * Timeout routine activation macros.
+ */
+#define TIMO(p,s) if (! ((p)->pp_flags & PP_TIMO)) { \
+ timeout (sppp_cp_timeout, (void*) (p), (s)*hz); \
+ (p)->pp_flags |= PP_TIMO; }
+#define UNTIMO(p) if ((p)->pp_flags & PP_TIMO) { \
+ untimeout (sppp_cp_timeout, (void*) (p)); \
+ (p)->pp_flags &= ~PP_TIMO; }
+
+void sppp_keepalive (void *dummy);
+void sppp_cp_send (struct sppp *sp, u_short proto, u_char type,
+ u_char ident, u_short len, void *data);
void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2);
void sppp_lcp_input (struct sppp *sp, struct mbuf *m);
void sppp_cisco_input (struct sppp *sp, struct mbuf *m);
-void sppp_lcp_conf_rej (struct sppp *sp, struct lcp_header *h);
void sppp_ipcp_input (struct sppp *sp, struct mbuf *m);
void sppp_lcp_open (struct sppp *sp);
void sppp_ipcp_open (struct sppp *sp);
-int sppp_lcp_conf_unknown_options (int len, unsigned char *p);
+int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
+ int len, u_long *magic);
void sppp_cp_timeout (void *arg);
-char *sppp_lcp_type_name (unsigned char type);
-char *sppp_ipcp_type_name (unsigned char type);
-void sppp_print_bytes (unsigned char *p, unsigned short len);
+char *sppp_lcp_type_name (u_char type);
+char *sppp_ipcp_type_name (u_char type);
+void sppp_print_bytes (u_char *p, u_short len);
/*
* Flush interface queue.
@@ -179,8 +189,9 @@ static void qflush (struct ifqueue *ifq)
void sppp_input (struct ifnet *ifp, struct mbuf *m)
{
struct ppp_header *h;
- struct sppp *sp;
+ struct sppp *sp = (struct sppp*) ifp;
struct ifqueue *inq = 0;
+ int s;
ifp->if_lastchange = time;
if (ifp->if_flags & IFF_UP)
@@ -211,12 +222,18 @@ invalid: if (ifp->if_flags & IFF_DEBUG)
case PPP_ALLSTATIONS:
if (h->control != PPP_UI)
goto invalid;
- sp = (struct sppp*) ifp;
+ if (sp->pp_flags & PP_CISCO) {
+ if (ifp->if_flags & IFF_DEBUG)
+ printf ("%s%d: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n",
+ ifp->if_name, ifp->if_unit,
+ h->address, h->control, ntohs (h->protocol));
+ goto drop;
+ }
switch (ntohs (h->protocol)) {
default:
if (sp->lcp.state == LCP_STATE_OPENED)
sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ,
- ++sp->pp_seq, m->m_pkthdr.len - 2,
+ ++sp->pp_seq, m->m_pkthdr.len + 2,
&h->protocol);
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: invalid input protocol <0x%x 0x%x 0x%x>\n",
@@ -264,6 +281,13 @@ invalid: if (ifp->if_flags & IFF_DEBUG)
case CISCO_MULTICAST:
case CISCO_UNICAST:
/* Don't check the control field here (RFC 1547). */
+ if (! (sp->pp_flags & PP_CISCO)) {
+ if (ifp->if_flags & IFF_DEBUG)
+ printf ("%s%d: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n",
+ ifp->if_name, ifp->if_unit,
+ h->address, h->control, ntohs (h->protocol));
+ goto drop;
+ }
switch (ntohs (h->protocol)) {
default:
++ifp->if_noproto;
@@ -292,15 +316,18 @@ invalid: if (ifp->if_flags & IFF_DEBUG)
goto drop;
/* Check queue. */
+ s = splimp ();
if (IF_QFULL (inq)) {
/* Queue overflow. */
+ IF_DROP (inq);
+ splx (s);
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: protocol queue overflow\n",
ifp->if_name, ifp->if_unit);
- IF_DROP (inq);
goto drop;
}
IF_ENQUEUE (inq, m);
+ splx (s);
}
/*
@@ -361,8 +388,15 @@ int sppp_output (struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct
switch (dst->sa_family) {
#ifdef INET
case AF_INET: /* Internet Protocol */
- h->protocol = htons ((sp->pp_flags & PP_CISCO) ?
- ETHERTYPE_IP : PPP_IP);
+ if (sp->pp_flags & PP_CISCO)
+ h->protocol = htons (ETHERTYPE_IP);
+ else if (sp->ipcp.state == IPCP_STATE_OPENED)
+ h->protocol = htons (PPP_IP);
+ else {
+ m_freem (m);
+ splx (s);
+ return (ENETDOWN);
+ }
break;
#endif
#ifdef NS
@@ -416,7 +450,7 @@ void sppp_attach (struct ifnet *ifp)
/* Initialize keepalive handler. */
if (! spppq)
- timeout (sppp_keepalive, (void *)0, hz * 10);
+ timeout (sppp_keepalive, 0, hz * 10);
/* Insert new entry into the keepalive list. */
sp->pp_next = spppq;
@@ -427,10 +461,11 @@ void sppp_attach (struct ifnet *ifp)
sp->pp_fastq.ifq_maxlen = 32;
sp->pp_loopcnt = 0;
sp->pp_alivecnt = 0;
- sp->lcp.magic = time.tv_sec + time.tv_usec;
- sp->lcp.rmagic = 0;
- sp->pp_seq = sp->lcp.magic;
+ sp->pp_seq = 0;
sp->pp_rseq = 0;
+ sp->lcp.magic = 0;
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
}
void sppp_detach (struct ifnet *ifp)
@@ -446,8 +481,8 @@ void sppp_detach (struct ifnet *ifp)
/* Stop keepalive handler. */
if (! spppq)
- untimeout (sppp_keepalive, (void *)0);
- untimeout (sppp_cp_timeout, (void *)sp);
+ untimeout (sppp_keepalive, 0);
+ UNTIMO (sp);
}
/*
@@ -462,6 +497,19 @@ void sppp_flush (struct ifnet *ifp)
}
/*
+ * Check if the output queue is empty.
+ */
+int sppp_isempty (struct ifnet *ifp)
+{
+ struct sppp *sp = (struct sppp*) ifp;
+ int empty, s = splimp ();
+
+ empty = !sp->pp_fastq.ifq_head && !sp->pp_if.if_snd.ifq_head;
+ splx (s);
+ return (empty);
+}
+
+/*
* Get next packet to send.
*/
struct mbuf *sppp_dequeue (struct ifnet *ifp)
@@ -480,8 +528,7 @@ struct mbuf *sppp_dequeue (struct ifnet *ifp)
/*
* Send keepalive packets, every 10 seconds.
*/
-void
-sppp_keepalive (void *dummy1)
+void sppp_keepalive (void *dummy)
{
struct sppp *sp;
int s = splimp ();
@@ -489,8 +536,13 @@ sppp_keepalive (void *dummy1)
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) ||
+ ! (ifp->if_flags & IFF_RUNNING))
+ continue;
+
+ /* No keepalive in PPP mode if LCP not opened yet. */
+ if (! (sp->pp_flags & PP_CISCO) &&
sp->lcp.state != LCP_STATE_OPENED)
continue;
@@ -499,10 +551,15 @@ sppp_keepalive (void *dummy1)
printf ("%s%d: down\n", ifp->if_name, ifp->if_unit);
if_down (ifp);
qflush (&sp->pp_fastq);
+ if (! (sp->pp_flags & PP_CISCO)) {
+ /* Shut down the PPP link. */
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
+ UNTIMO (sp);
+ /* Initiate negotiation. */
+ sppp_lcp_open (sp);
+ }
}
- if (sp->pp_loopcnt >= MAXALIVECNT)
- printf ("%s%d: loopback\n", ifp->if_name, ifp->if_unit);
-
if (sp->pp_alivecnt <= MAXALIVECNT)
++sp->pp_alivecnt;
if (sp->pp_flags & PP_CISCO)
@@ -510,13 +567,13 @@ sppp_keepalive (void *dummy1)
sp->pp_rseq);
else if (sp->lcp.state == LCP_STATE_OPENED) {
long nmagic = htonl (sp->lcp.magic);
- sp->lcp.lastid = ++sp->pp_seq;
+ sp->lcp.echoid = ++sp->pp_seq;
sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ,
- sp->lcp.lastid, 4, &nmagic);
+ sp->lcp.echoid, 4, &nmagic);
}
}
splx (s);
- timeout (sppp_keepalive, (void *)0, hz * 10);
+ timeout (sppp_keepalive, 0, hz * 10);
}
/*
@@ -527,7 +584,8 @@ void sppp_lcp_input (struct sppp *sp, struct mbuf *m)
struct lcp_header *h;
struct ifnet *ifp = &sp->pp_if;
int len = m->m_pkthdr.len;
- unsigned char *p;
+ u_char *p, opt[6];
+ u_long rmagic;
if (len < 4) {
if (ifp->if_flags & IFF_DEBUG)
@@ -537,11 +595,18 @@ void sppp_lcp_input (struct sppp *sp, struct mbuf *m)
}
h = mtod (m, struct lcp_header*);
if (ifp->if_flags & IFF_DEBUG) {
- printf ("%s%d: lcp input: %d bytes <%s id=%xh len=%xh",
- ifp->if_name, ifp->if_unit, len,
+ char state = '?';
+ switch (sp->lcp.state) {
+ case LCP_STATE_CLOSED: state = 'C'; break;
+ case LCP_STATE_ACK_RCVD: state = 'R'; break;
+ case LCP_STATE_ACK_SENT: state = 'S'; break;
+ case LCP_STATE_OPENED: state = 'O'; break;
+ }
+ printf ("%s%d: lcp input(%c): %d bytes <%s id=%xh len=%xh",
+ ifp->if_name, ifp->if_unit, state, len,
sppp_lcp_type_name (h->type), h->ident, ntohs (h->len));
if (len > 4)
- sppp_print_bytes ((unsigned char*) (h+1), len-4);
+ sppp_print_bytes ((u_char*) (h+1), len-4);
printf (">\n");
}
if (len > ntohs (h->len))
@@ -549,107 +614,128 @@ void sppp_lcp_input (struct sppp *sp, struct mbuf *m)
switch (h->type) {
default:
/* Unknown packet type -- send Code-Reject packet. */
- sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, len, h);
+ sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq,
+ m->m_pkthdr.len, h);
break;
case LCP_CONF_REQ:
if (len < 4) {
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: invalid lcp configure request packet length: %d bytes\n",
ifp->if_name, ifp->if_unit, len);
- return;
+ break;
}
- if (len>4 && sppp_lcp_conf_unknown_options (len-4, (unsigned char*) (h+1))) {
- sppp_lcp_conf_rej (sp, h);
- if (sp->lcp.state == LCP_STATE_OPENED)
+ if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic))
+ goto badreq;
+ if (rmagic == sp->lcp.magic) {
+ /* Local and remote magics equal -- loopback? */
+ if (sp->pp_loopcnt >= MAXALIVECNT*5) {
+ printf ("%s%d: loopback\n",
+ ifp->if_name, ifp->if_unit);
+ sp->pp_loopcnt = 0;
+ if (ifp->if_flags & IFF_UP) {
+ if_down (ifp);
+ qflush (&sp->pp_fastq);
+ }
+ } else if (ifp->if_flags & IFF_DEBUG)
+ printf ("%s%d: conf req: magic glitch\n",
+ ifp->if_name, ifp->if_unit);
+ ++sp->pp_loopcnt;
+
+ /* MUST send Conf-Nack packet. */
+ rmagic = ~sp->lcp.magic;
+ opt[0] = LCP_OPT_MAGIC;
+ opt[1] = sizeof (opt);
+ opt[2] = rmagic >> 24;
+ opt[3] = rmagic >> 16;
+ opt[4] = rmagic >> 8;
+ opt[5] = rmagic;
+ sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK,
+ h->ident, sizeof (opt), &opt);
+badreq:
+ switch (sp->lcp.state) {
+ case LCP_STATE_OPENED:
/* Initiate renegotiation. */
sppp_lcp_open (sp);
- if (sp->lcp.state != LCP_STATE_ACK_RCVD) {
+ /* fall through... */
+ case LCP_STATE_ACK_SENT:
/* Go to closed state. */
sp->lcp.state = LCP_STATE_CLOSED;
sp->ipcp.state = IPCP_STATE_CLOSED;
}
- } else {
- /* Extract remote magic number. */
- p = (unsigned char*) (h+1);
- if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4)
- sp->lcp.rmagic = (unsigned long)p[2] << 24 |
- (unsigned long)p[3] << 16 |
- p[4] << 8 | p[5];
- if (sp->lcp.rmagic == sp->lcp.magic) {
- /* Local and remote magics are equal -- loop? */
- sp->lcp.rmagic = ~sp->lcp.magic;
- /* Send Configure-Nack packet. */
- p[2] = sp->lcp.rmagic >> 24;
- p[3] = sp->lcp.rmagic >> 16;
- p[4] = sp->lcp.rmagic >> 8;
- p[5] = sp->lcp.rmagic;
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK,
- h->ident, len-4, h+1);
- if (sp->lcp.state != LCP_STATE_ACK_RCVD) {
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
+ break;
}
- } else {
/* Send Configure-Ack packet. */
sp->pp_loopcnt = 0;
sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
h->ident, len-4, h+1);
- if (sp->lcp.state == LCP_STATE_OPENED)
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
/* Change the state. */
- if (sp->lcp.state == LCP_STATE_ACK_RCVD) {
+ switch (sp->lcp.state) {
+ case LCP_STATE_CLOSED:
+ sp->lcp.state = LCP_STATE_ACK_SENT;
+ break;
+ case LCP_STATE_ACK_RCVD:
sp->lcp.state = LCP_STATE_OPENED;
sppp_ipcp_open (sp);
- } else
- sp->lcp.state = LCP_STATE_ACK_SENT;
- }
+ break;
+ case LCP_STATE_OPENED:
+ /* Remote magic changed -- close session. */
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
+ /* Initiate renegotiation. */
+ sppp_lcp_open (sp);
+ break;
}
break;
case LCP_CONF_ACK:
- if (h->ident != sp->pp_seq)
- return;
- untimeout (sppp_cp_timeout, (void *)sp);
+ if (h->ident != sp->lcp.confid)
+ break;
+ UNTIMO (sp);
+ if (! (ifp->if_flags & IFF_UP) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ /* Coming out of loopback mode. */
+ ifp->if_flags |= IFF_UP;
+ printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
+ }
switch (sp->lcp.state) {
case LCP_STATE_CLOSED:
sp->lcp.state = LCP_STATE_ACK_RCVD;
+ TIMO (sp, 5);
break;
case LCP_STATE_ACK_SENT:
sp->lcp.state = LCP_STATE_OPENED;
sppp_ipcp_open (sp);
break;
- case LCP_STATE_ACK_RCVD:
- case LCP_STATE_OPENED:
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
}
break;
case LCP_CONF_NAK:
- if (h->ident != sp->pp_seq)
- return;
- p = (unsigned char*) (h+1);
+ if (h->ident != sp->lcp.confid)
+ break;
+ p = (u_char*) (h+1);
if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) {
- sp->lcp.rmagic = (unsigned long)p[2] << 24 |
- (unsigned long)p[3] << 16 |
- p[4] << 8 | p[5];
- if (sp->lcp.rmagic == ~sp->lcp.magic) {
+ rmagic = (u_long)p[2] << 24 |
+ (u_long)p[3] << 16 | p[4] << 8 | p[5];
+ if (rmagic == ~sp->lcp.magic) {
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: conf nak: magic glitch\n",
ifp->if_name, ifp->if_unit);
- ++sp->pp_loopcnt;
- sp->lcp.magic = time.tv_sec + time.tv_usec;
+ sp->lcp.magic += time.tv_sec + time.tv_usec;
+ } else
+ sp->lcp.magic = rmagic;
}
+ if (sp->lcp.state != LCP_STATE_ACK_SENT) {
+ /* Go to closed state. */
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
}
- /* Fall through. */
+ /* The link will be renegotiated after timeout,
+ * to avoid endless req-nack loop. */
+ UNTIMO (sp);
+ TIMO (sp, 2);
+ break;
case LCP_CONF_REJ:
- if (h->ident != sp->pp_seq)
- return;
- untimeout (sppp_cp_timeout, (void *)sp);
+ if (h->ident != sp->lcp.confid)
+ break;
+ UNTIMO (sp);
/* Initiate renegotiation. */
sppp_lcp_open (sp);
if (sp->lcp.state != LCP_STATE_ACK_SENT) {
@@ -659,27 +745,16 @@ void sppp_lcp_input (struct sppp *sp, struct mbuf *m)
}
break;
case LCP_TERM_REQ:
+ UNTIMO (sp);
/* Send Terminate-Ack packet. */
sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, 0);
- if (sp->lcp.state == LCP_STATE_OPENED)
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
/* Go to closed state. */
sp->lcp.state = LCP_STATE_CLOSED;
sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
- case LCP_TERM_ACK:
- if (h->ident != sp->pp_seq)
- return;
- if (sp->lcp.state == LCP_STATE_OPENED)
/* Initiate renegotiation. */
sppp_lcp_open (sp);
- if (sp->lcp.state != LCP_STATE_ACK_SENT) {
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- }
break;
+ case LCP_TERM_ACK:
case LCP_CODE_REJ:
case LCP_PROTO_REJ:
/* Ignore for now. */
@@ -692,33 +767,35 @@ void sppp_lcp_input (struct sppp *sp, struct mbuf *m)
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: invalid lcp echo request packet length: %d bytes\n",
ifp->if_name, ifp->if_unit, len);
- return;
+ break;
}
if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {
- if (ifp->if_flags & IFF_DEBUG)
- printf ("%s%d: echo reply: magic glitch\n",
- ifp->if_name, ifp->if_unit);
- ++sp->pp_loopcnt;
+ /* Line loopback mode detected. */
+ printf ("%s%d: loopback\n", ifp->if_name, ifp->if_unit);
+ if_down (ifp);
+ qflush (&sp->pp_fastq);
+
+ /* Shut down the PPP link. */
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
+ UNTIMO (sp);
+ /* Initiate negotiation. */
+ sppp_lcp_open (sp);
+ break;
}
*(long*)(h+1) = htonl (sp->lcp.magic);
sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1);
break;
case LCP_ECHO_REPLY:
- if (h->ident != sp->lcp.lastid)
- return;
+ if (h->ident != sp->lcp.echoid)
+ break;
if (len < 8) {
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: invalid lcp echo reply packet length: %d bytes\n",
ifp->if_name, ifp->if_unit, len);
- return;
- }
- if (ntohl (*(long*)(h+1)) == sp->lcp.magic)
- return;
- if (! (ifp->if_flags & IFF_UP) &&
- (ifp->if_flags & IFF_RUNNING)) {
- ifp->if_flags |= IFF_UP;
- printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
+ break;
}
+ if (ntohl (*(long*)(h+1)) != sp->lcp.magic)
sp->pp_alivecnt = 0;
break;
}
@@ -741,8 +818,7 @@ void sppp_cisco_input (struct sppp *sp, struct mbuf *m)
}
h = mtod (m, struct cisco_packet*);
if (ifp->if_flags & IFF_DEBUG)
- printf ("%s%d: cisco input: %d bytes "
- "<%lxh %lxh %lxh %xh %xh-%xh>\n",
+ printf ("%s%d: cisco input: %d bytes <%lxh %lxh %lxh %xh %xh-%xh>\n",
ifp->if_name, ifp->if_unit, m->m_pkthdr.len,
ntohl (h->type), h->par1, h->par2, h->rel,
h->time0, h->time1);
@@ -756,22 +832,32 @@ void sppp_cisco_input (struct sppp *sp, struct mbuf *m)
/* Reply on address request, ignore */
break;
case CISCO_KEEPALIVE_REQ:
- if (! (ifp->if_flags & IFF_UP) &&
- (ifp->if_flags & IFF_RUNNING)) {
- ifp->if_flags |= IFF_UP;
- printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
- }
sp->pp_alivecnt = 0;
sp->pp_rseq = ntohl (h->par1);
if (sp->pp_seq == sp->pp_rseq) {
/* Local and remote sequence numbers are equal.
* Probably, the line is in loopback mode. */
+ if (sp->pp_loopcnt >= MAXALIVECNT) {
+ printf ("%s%d: loopback\n",
+ ifp->if_name, ifp->if_unit);
+ sp->pp_loopcnt = 0;
+ if (ifp->if_flags & IFF_UP) {
+ if_down (ifp);
+ qflush (&sp->pp_fastq);
+ }
+ }
++sp->pp_loopcnt;
/* Generate new local sequence number */
sp->pp_seq ^= time.tv_sec ^ time.tv_usec;
- } else
+ break;
+ }
sp->pp_loopcnt = 0;
+ if (! (ifp->if_flags & IFF_UP) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ ifp->if_flags |= IFF_UP;
+ printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
+ }
break;
case CISCO_ADDR_REQ:
for (ifa=ifp->if_addrlist; ifa; ifa=ifa->ifa_next)
@@ -793,8 +879,8 @@ void sppp_cisco_input (struct sppp *sp, struct mbuf *m)
/*
* Send PPP LCP packet.
*/
-void sppp_cp_send (struct sppp *sp, unsigned short proto, unsigned char type,
- unsigned char ident, unsigned short len, void *data)
+void sppp_cp_send (struct sppp *sp, u_short proto, u_char type,
+ u_char ident, u_short len, void *data)
{
struct ppp_header *h;
struct lcp_header *lh;
@@ -829,7 +915,7 @@ void sppp_cp_send (struct sppp *sp, unsigned short proto, unsigned char type,
sppp_ipcp_type_name (lh->type), lh->ident,
ntohs (lh->len));
if (len)
- sppp_print_bytes ((unsigned char*) (lh+1), len);
+ sppp_print_bytes ((u_char*) (lh+1), len);
printf (">\n");
}
if (IF_QFULL (&sp->pp_fastq)) {
@@ -851,7 +937,7 @@ void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
struct cisco_packet *ch;
struct mbuf *m;
struct ifnet *ifp = &sp->pp_if;
- unsigned long t = (time.tv_sec - boottime.tv_sec) * 1000;
+ u_long t = (time.tv_sec - boottime.tv_sec) * 1000;
MGETHDR (m, M_DONTWAIT, MT_DATA);
if (! m)
@@ -869,8 +955,8 @@ void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
ch->par1 = htonl (par1);
ch->par2 = htonl (par2);
ch->rel = -1;
- ch->time0 = htons ((unsigned short) (t >> 16));
- ch->time1 = htons ((unsigned short) t);
+ ch->time0 = htons ((u_short) (t >> 16));
+ ch->time1 = htons ((u_short) t);
if (ifp->if_flags & IFF_DEBUG)
printf ("%s%d: cisco output: <%lxh %lxh %lxh %xh %xh-%xh>\n",
@@ -890,35 +976,42 @@ void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
/*
* Process an ioctl request. Called on low priority level.
*/
-int sppp_ioctl (struct ifnet *ifp, int cmd, caddr_t data)
+int sppp_ioctl (struct ifnet *ifp, int cmd, void *data)
{
struct ifreq *ifr = (struct ifreq*) data;
- struct sppp *sp;
- int s;
+ struct sppp *sp = (struct sppp*) ifp;
+ int s, going_up, going_down;
switch (cmd) {
default:
return (EINVAL);
- case SIOCSIFADDR:
case SIOCAIFADDR:
case SIOCSIFDSTADDR:
break;
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ /* fall through... */
+
case SIOCSIFFLAGS:
+ if (sp->pp_flags & PP_CISCO)
+ break;
s = splimp ();
- if (! (ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING)) {
- /* Interface is stopping. */
- sp = (struct sppp*) ifp;
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- sppp_cp_send (sp, PPP_LCP, LCP_TERM_REQ, ++sp->pp_seq,
- 0, 0);
- } else if ((ifp->if_flags & IFF_UP) && ! (ifp->if_flags & IFF_RUNNING)) {
- /* Interface is starting. */
- sp = (struct sppp*) ifp;
+ going_up = (ifp->if_flags & IFF_UP) &&
+ ! (ifp->if_flags & IFF_RUNNING);
+ going_down = ! (ifp->if_flags & IFF_UP) &&
+ (ifp->if_flags & IFF_RUNNING);
+ if (going_up || going_down) {
+ /* Shut down the PPP link. */
+ ifp->if_flags &= ~IFF_RUNNING;
sp->lcp.state = LCP_STATE_CLOSED;
sp->ipcp.state = IPCP_STATE_CLOSED;
+ UNTIMO (sp);
+ }
+ if (going_up) {
+ /* Interface is starting -- initiate negotiation. */
+ ifp->if_flags |= IFF_RUNNING;
sppp_lcp_open (sp);
}
splx (s);
@@ -960,35 +1053,56 @@ int sppp_ioctl (struct ifnet *ifp, int cmd, caddr_t data)
return (0);
}
-int sppp_lcp_conf_unknown_options (int len, unsigned char *p)
-{
- /* Analyze the LCP Configure-Request options list
- * for the presence of unknown options. */
- while (len > 0) {
- if (*p != LCP_OPT_MAGIC)
- return (1);
- len -= p[1];
- p += p[1];
- }
- return (0);
-}
-
-void sppp_lcp_conf_rej (struct sppp *sp, struct lcp_header *h)
+/*
+ * Analyze the LCP Configure-Request options list
+ * for the presence of unknown options.
+ * If the request contains unknown options, build and
+ * send Configure-reject packet, containing only unknown options.
+ */
+int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
+ int len, u_long *magic)
{
- /* The LCP Configure-Request contains unknown options.
- * Send Configure-reject packet, containing only unknown options. */
- unsigned char buf [PP_MTU], *r = buf, *p = (void*) (h+1);
- unsigned rlen = 0, len = h->len - 4;
-
- while (len > 0) {
- if (*p != LCP_OPT_MAGIC) {
+ u_char *buf, *r, *p;
+ int rlen;
+
+ len -= 4;
+ buf = r = malloc (len, M_TEMP, M_NOWAIT);
+ if (! buf)
+ return (0);
+
+ p = (void*) (h+1);
+ for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+ switch (*p) {
+ case LCP_OPT_MAGIC:
+ /* Magic number -- extract. */
+ if (len >= 6 && p[1] == 6) {
+ *magic = (u_long)p[2] << 24 |
+ (u_long)p[3] << 16 | p[4] << 8 | p[5];
+ continue;
+ }
+ break;
+ case LCP_OPT_ASYNC_MAP:
+ /* Async control character map -- check to be zero. */
+ if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] &&
+ ! p[4] && ! p[5])
+ continue;
+ break;
+ case LCP_OPT_MRU:
+ /* Maximum receive unit -- always OK. */
+ continue;
+ default:
+ /* Others not supported. */
+ break;
+ }
+ /* Add the option to rejected list. */
bcopy (p, r, p[1]);
r += p[1];
+ rlen += p[1];
}
- len -= p[1];
- p += p[1];
- }
+ if (rlen)
sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf);
+ free (buf, M_TEMP);
+ return (rlen == 0);
}
void sppp_ipcp_input (struct sppp *sp, struct mbuf *m)
@@ -1009,7 +1123,7 @@ void sppp_ipcp_input (struct sppp *sp, struct mbuf *m)
ifp->if_name, ifp->if_unit, len,
sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len));
if (len > 4)
- sppp_print_bytes ((unsigned char*) (h+1), len-4);
+ sppp_print_bytes ((u_char*) (h+1), len-4);
printf (">\n");
}
if (len > ntohs (h->len))
@@ -1029,51 +1143,46 @@ void sppp_ipcp_input (struct sppp *sp, struct mbuf *m)
if (len > 4) {
sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident,
len-4, h+1);
- if (sp->lcp.state == LCP_STATE_OPENED &&
- sp->ipcp.state == IPCP_STATE_OPENED)
+
+ switch (sp->ipcp.state) {
+ case IPCP_STATE_OPENED:
/* Initiate renegotiation. */
sppp_ipcp_open (sp);
- if (sp->ipcp.state != IPCP_STATE_ACK_RCVD)
+ /* fall through... */
+ case IPCP_STATE_ACK_SENT:
/* Go to closed state. */
sp->ipcp.state = IPCP_STATE_CLOSED;
+ }
} else {
/* Send Configure-Ack packet. */
sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident,
0, 0);
- if (sp->lcp.state == LCP_STATE_OPENED &&
- sp->ipcp.state == IPCP_STATE_OPENED)
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
/* Change the state. */
- sp->ipcp.state = (sp->ipcp.state == IPCP_STATE_ACK_RCVD) ?
- IPCP_STATE_OPENED : IPCP_STATE_ACK_SENT;
+ if (sp->ipcp.state == IPCP_STATE_ACK_RCVD)
+ sp->ipcp.state = IPCP_STATE_OPENED;
+ else
+ sp->ipcp.state = IPCP_STATE_ACK_SENT;
}
break;
case IPCP_CONF_ACK:
- untimeout (sppp_cp_timeout, (void *)sp);
+ if (h->ident != sp->ipcp.confid)
+ break;
+ UNTIMO (sp);
switch (sp->ipcp.state) {
case IPCP_STATE_CLOSED:
sp->ipcp.state = IPCP_STATE_ACK_RCVD;
+ TIMO (sp, 5);
break;
case IPCP_STATE_ACK_SENT:
sp->ipcp.state = IPCP_STATE_OPENED;
break;
- case IPCP_STATE_ACK_RCVD:
- case IPCP_STATE_OPENED:
- if (sp->lcp.state == LCP_STATE_OPENED)
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
- /* Go to closed state. */
- sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
}
break;
case IPCP_CONF_NAK:
case IPCP_CONF_REJ:
- untimeout (sppp_cp_timeout, (void *)sp);
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
- if (sp->lcp.state == LCP_STATE_OPENED)
+ if (h->ident != sp->ipcp.confid)
+ break;
+ UNTIMO (sp);
/* Initiate renegotiation. */
sppp_ipcp_open (sp);
if (sp->ipcp.state != IPCP_STATE_ACK_SENT)
@@ -1083,22 +1192,13 @@ void sppp_ipcp_input (struct sppp *sp, struct mbuf *m)
case IPCP_TERM_REQ:
/* Send Terminate-Ack packet. */
sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, 0);
- if (sp->lcp.state == LCP_STATE_OPENED &&
- sp->ipcp.state == IPCP_STATE_OPENED)
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
/* Go to closed state. */
sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
- case IPCP_TERM_ACK:
- if (sp->lcp.state == LCP_STATE_OPENED &&
- sp->ipcp.state == IPCP_STATE_OPENED)
/* Initiate renegotiation. */
sppp_ipcp_open (sp);
- if (sp->ipcp.state != IPCP_STATE_ACK_SENT)
- /* Go to closed state. */
- sp->ipcp.state = IPCP_STATE_CLOSED;
break;
+ case IPCP_TERM_ACK:
+ /* Ignore for now. */
case IPCP_CODE_REJ:
/* Ignore for now. */
break;
@@ -1109,7 +1209,7 @@ void sppp_lcp_open (struct sppp *sp)
{
char opt[6];
- /* Make new magic number. */
+ if (! sp->lcp.magic)
sp->lcp.magic = time.tv_sec + time.tv_usec;
opt[0] = LCP_OPT_MAGIC;
opt[1] = sizeof (opt);
@@ -1117,27 +1217,32 @@ void sppp_lcp_open (struct sppp *sp)
opt[3] = sp->lcp.magic >> 16;
opt[4] = sp->lcp.magic >> 8;
opt[5] = sp->lcp.magic;
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, ++sp->pp_seq,
+ sp->lcp.confid = ++sp->pp_seq;
+ sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid,
sizeof (opt), &opt);
- timeout (sppp_cp_timeout, (void *)sp, hz * 5);
+ TIMO (sp, 2);
}
void sppp_ipcp_open (struct sppp *sp)
{
- sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, ++sp->pp_seq, 0, 0);
- timeout (sppp_cp_timeout, (void *)sp, hz * 5);
+ sp->ipcp.confid = ++sp->pp_seq;
+ sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, 0);
+ TIMO (sp, 2);
}
/*
* Process PPP control protocol timeouts.
*/
-void
-sppp_cp_timeout (void * arg)
+void sppp_cp_timeout (void *arg)
{
struct sppp *sp = (struct sppp*) arg;
- struct ifnet *ifp = &sp->pp_if;
int s = splimp ();
+ sp->pp_flags &= ~PP_TIMO;
+ if (! (sp->pp_if.if_flags & IFF_RUNNING) || (sp->pp_flags & PP_CISCO)) {
+ splx (s);
+ return;
+ }
switch (sp->lcp.state) {
case LCP_STATE_CLOSED:
/* No ACK for Configure-Request, retry. */
@@ -1177,7 +1282,7 @@ sppp_cp_timeout (void * arg)
splx (s);
}
-char *sppp_lcp_type_name (unsigned char type)
+char *sppp_lcp_type_name (u_char type)
{
static char buf [8];
switch (type) {
@@ -1197,7 +1302,7 @@ char *sppp_lcp_type_name (unsigned char type)
return (buf);
}
-char *sppp_ipcp_type_name (unsigned char type)
+char *sppp_ipcp_type_name (u_char type)
{
static char buf [8];
switch (type) {
@@ -1213,7 +1318,7 @@ char *sppp_ipcp_type_name (unsigned char type)
return (buf);
}
-void sppp_print_bytes (unsigned char *p, unsigned short len)
+void sppp_print_bytes (u_char *p, u_short len)
{
printf (" %x", *p++);
while (--len > 0)
OpenPOWER on IntegriCloud