if_spppsubr.c revision 25706
1141104Sharti/* 294589Sobrien * Synchronous PPP/Cisco link level subroutines. 394589Sobrien * Keepalive protocol implemented in both Cisco and PPP modes. 45814Sjkh * 51590Srgrimes * Copyright (C) 1994 Cronyx Ltd. 61590Srgrimes * Author: Serge Vakulenko, <vak@zebub.msk.su> 71590Srgrimes * 81590Srgrimes * This software is distributed with NO WARRANTIES, not even the implied 91590Srgrimes * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 101590Srgrimes * 111590Srgrimes * Authors grant any other persons or organisations permission to use 121590Srgrimes * or modify this software as long as this message is kept with the software, 131590Srgrimes * all derivative works or modified versions. 141590Srgrimes * 151590Srgrimes * Version 1.9, Wed Oct 4 18:58:15 MSK 1995 161590Srgrimes * 171590Srgrimes * $Id: if_spppsubr.c,v 1.17 1997/03/24 11:33:16 bde Exp $ 181590Srgrimes */ 191590Srgrimes 201590Srgrimes#include <sys/param.h> 211590Srgrimes#include <sys/systm.h> 221590Srgrimes#include <sys/kernel.h> 231590Srgrimes#include <sys/sockio.h> 241590Srgrimes#include <sys/socket.h> 251590Srgrimes#include <sys/syslog.h> 261590Srgrimes#include <sys/mbuf.h> 271590Srgrimes 281590Srgrimes#include <net/if.h> 291590Srgrimes#include <net/netisr.h> 301590Srgrimes#include <net/if_types.h> 311590Srgrimes 321590Srgrimes#ifdef INET 331590Srgrimes#include <netinet/in.h> 341590Srgrimes#include <netinet/in_systm.h> 351590Srgrimes#include <netinet/in_var.h> 361590Srgrimes#include <netinet/ip.h> 371590Srgrimes#include <netinet/tcp.h> 3862833Swsanchez#include <netinet/if_ether.h> 3962833Swsanchez#endif 401590Srgrimes 411590Srgrimes#ifdef IPX 4262833Swsanchez#include <netipx/ipx.h> 4394587Sobrien#include <netipx/ipx_if.h> 441590Srgrimes#endif 4535483Simp 46103503Sjmallett#ifdef NS 4735483Simp#include <netns/ns.h> 4835483Simp#include <netns/ns_if.h> 491590Srgrimes#endif 501590Srgrimes 511590Srgrimes#ifdef ISO 521590Srgrimes#include <netiso/argo_debug.h> 531590Srgrimes#include <netiso/iso.h> 54144467Sharti#include <netiso/iso_var.h> 551590Srgrimes#include <netiso/iso_snpac.h> 56144467Sharti#endif 57144467Sharti 58144467Sharti#include <net/if_sppp.h> 59144467Sharti 60144467Sharti#define MAXALIVECNT 3 /* max. alive packets */ 61144467Sharti 62144467Sharti#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 631590Srgrimes#define PPP_UI 0x03 /* Unnumbered Information */ 64144467Sharti#define PPP_IP 0x0021 /* Internet Protocol */ 65144467Sharti#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 66144467Sharti#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 67144467Sharti#define PPP_IPX 0x002b /* Novell IPX Protocol */ 68144467Sharti#define PPP_LCP 0xc021 /* Link Control Protocol */ 691590Srgrimes#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 70144467Sharti 71144467Sharti#define LCP_CONF_REQ 1 /* PPP LCP configure request */ 72144467Sharti#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */ 73144467Sharti#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */ 741590Srgrimes#define LCP_CONF_REJ 4 /* PPP LCP configure reject */ 75144467Sharti#define LCP_TERM_REQ 5 /* PPP LCP terminate request */ 761590Srgrimes#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */ 77144467Sharti#define LCP_CODE_REJ 7 /* PPP LCP code reject */ 781590Srgrimes#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */ 79144467Sharti#define LCP_ECHO_REQ 9 /* PPP LCP echo request */ 80144467Sharti#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */ 81144467Sharti#define LCP_DISC_REQ 11 /* PPP LCP discard request */ 821590Srgrimes 83144467Sharti#define LCP_OPT_MRU 1 /* maximum receive unit */ 84144467Sharti#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 85144467Sharti#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 86144467Sharti#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 871590Srgrimes#define LCP_OPT_MAGIC 5 /* magic number */ 88144467Sharti#define LCP_OPT_RESERVED 6 /* reserved */ 89144467Sharti#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 90144467Sharti#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 911590Srgrimes 92144467Sharti#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */ 93144467Sharti#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */ 94144467Sharti#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */ 951590Srgrimes#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */ 96144467Sharti#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */ 971590Srgrimes#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */ 98144467Sharti#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */ 991590Srgrimes 1001590Srgrimes#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 101144494Sharti#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 1021590Srgrimes#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 103141104Sharti#define CISCO_ADDR_REQ 0 /* Cisco address request */ 1041590Srgrimes#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 105107447Sru#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 106104475Sphk 107107447Srustruct ppp_header { 1081590Srgrimes u_char address; 109141104Sharti u_char control; 11094506Scharnier u_short protocol; 1115814Sjkh}; 112144665Sharti#define PPP_HEADER_LEN sizeof (struct ppp_header) 1131590Srgrimes 1145814Sjkhstruct lcp_header { 115141104Sharti u_char type; 11680381Ssheldonh u_char ident; 11794506Scharnier u_short len; 118141104Sharti}; 119141104Sharti#define LCP_HEADER_LEN sizeof (struct lcp_header) 120142457Sharti 121146056Shartistruct cisco_packet { 1221590Srgrimes u_long type; 123141104Sharti u_long par1; 124141104Sharti u_long par2; 1251590Srgrimes u_short rel; 126141104Sharti u_short time0; 127141104Sharti u_short time1; 1281590Srgrimes}; 129141104Sharti#define CISCO_PACKET_LEN 18 130146056Sharti 131141104Shartistatic struct sppp *spppq; 132141104Sharti 133141104Sharti/* 1341590Srgrimes * The following disgusting hack gets around the problem that IP TOS 135146057Sharti * can't be set yet. We want to put "interactive" traffic on a high 136146057Sharti * priority queue. To decide if traffic is interactive, we check that 137146057Sharti * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 1381590Srgrimes */ 139146057Shartistatic u_short interactive_ports[8] = { 140146057Sharti 0, 513, 0, 0, 141146057Sharti 0, 21, 0, 23, 142146057Sharti}; 143146057Sharti#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 144146057Sharti 145146057Sharti/* 146146057Sharti * Timeout routine activation macros. 147146057Sharti */ 148144483Sharti#define TIMO(p,s) if (! ((p)->pp_flags & PP_TIMO)) { \ 149144483Sharti timeout (sppp_cp_timeout, (void*) (p), (s)*hz); \ 150144483Sharti (p)->pp_flags |= PP_TIMO; } 151144483Sharti#define UNTIMO(p) if ((p)->pp_flags & PP_TIMO) { \ 152144483Sharti untimeout (sppp_cp_timeout, (void*) (p)); \ 153144483Sharti (p)->pp_flags &= ~PP_TIMO; } 154144483Sharti 155144483Shartistatic void sppp_keepalive (void *dummy); 156144483Shartistatic void sppp_cp_send (struct sppp *sp, u_short proto, u_char type, 157144483Sharti u_char ident, u_short len, void *data); 158144483Shartistatic void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); 159144483Shartistatic void sppp_lcp_input (struct sppp *sp, struct mbuf *m); 160144665Shartistatic void sppp_cisco_input (struct sppp *sp, struct mbuf *m); 161144483Shartistatic void sppp_ipcp_input (struct sppp *sp, struct mbuf *m); 162144483Shartistatic void sppp_lcp_open (struct sppp *sp); 163144483Shartistatic void sppp_ipcp_open (struct sppp *sp); 164144483Shartistatic int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, 165144483Sharti int len, u_long *magic); 166144483Shartistatic void sppp_cp_timeout (void *arg); 167144483Shartistatic const char *sppp_lcp_type_name (u_char type); 168144483Shartistatic const char *sppp_ipcp_type_name (u_char type); 169144483Shartistatic void sppp_print_bytes (u_char *p, u_short len); 170144483Shartistatic int sppp_output (struct ifnet *ifp, struct mbuf *m, 171144483Sharti struct sockaddr *dst, struct rtentry *rt); 172144483Sharti 173144483Sharti/* 174144483Sharti * Flush interface queue. 175144483Sharti */ 176144483Shartistatic void 177144483Shartiqflush(struct ifqueue *ifq) 178144483Sharti{ 179144483Sharti struct mbuf *m, *n; 180144483Sharti 181144483Sharti n = ifq->ifq_head; 182144483Sharti while ((m = n)) { 183144483Sharti n = m->m_act; 184144483Sharti m_freem (m); 185146061Sharti } 186144483Sharti ifq->ifq_head = 0; 187144483Sharti ifq->ifq_tail = 0; 188144483Sharti ifq->ifq_len = 0; 189144483Sharti} 190144483Sharti 191144483Sharti/* 192144483Sharti * Process the received packet. 193144483Sharti */ 194144483Shartivoid 195144483Shartisppp_input(struct ifnet *ifp, struct mbuf *m) 196144483Sharti{ 197144483Sharti struct ppp_header *h; 198144483Sharti struct sppp *sp = (struct sppp*) ifp; 199146061Sharti struct ifqueue *inq = 0; 200144483Sharti int s; 201144483Sharti 202144483Sharti if (ifp->if_flags & IFF_UP) 203144483Sharti /* Count received bytes, add FCS and one flag */ 204144483Sharti ifp->if_ibytes += m->m_pkthdr.len + 3; 205144483Sharti 206144483Sharti if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 207144483Sharti /* Too small packet, drop it. */ 208144483Sharti if (ifp->if_flags & IFF_DEBUG) 209144483Sharti log(LOG_DEBUG, 210144483Sharti "%s%d: input packet is too small, %d bytes\n", 211144483Sharti ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 212144483Shartidrop: ++ifp->if_iqdrops; 213144483Sharti m_freem (m); 214144483Sharti return; 215144483Sharti } 216144483Sharti 217144483Sharti /* Get PPP header. */ 218144483Sharti h = mtod (m, struct ppp_header*); 219144483Sharti m_adj (m, PPP_HEADER_LEN); 220144483Sharti 221144483Sharti switch (h->address) { 222144483Sharti default: /* Invalid PPP packet. */ 223144483Shartiinvalid: if (ifp->if_flags & IFF_DEBUG) 224144483Sharti log(LOG_DEBUG, 225144483Sharti "%s%d: invalid input packet " 226144483Sharti "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 227144483Sharti ifp->if_name, ifp->if_unit, 228144483Sharti h->address, h->control, ntohs(h->protocol)); 229144483Sharti goto drop; 230144483Sharti case PPP_ALLSTATIONS: 231144483Sharti if (h->control != PPP_UI) 232144483Sharti goto invalid; 233144483Sharti if (sp->pp_flags & PP_CISCO) { 234144483Sharti if (ifp->if_flags & IFF_DEBUG) 235144483Sharti log(LOG_DEBUG, 236144483Sharti "%s%d: PPP packet in Cisco mode " 237144483Sharti "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 238144483Sharti ifp->if_name, ifp->if_unit, 239144483Sharti h->address, h->control, ntohs(h->protocol)); 240144483Sharti goto drop; 241144483Sharti } 242144483Sharti switch (ntohs (h->protocol)) { 243144483Sharti default: 244144483Sharti if (sp->lcp.state == LCP_STATE_OPENED) 245144494Sharti sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ, 246144494Sharti ++sp->pp_seq, m->m_pkthdr.len + 2, 247144483Sharti &h->protocol); 248144483Sharti if (ifp->if_flags & IFF_DEBUG) 249146061Sharti log(LOG_DEBUG, 250146061Sharti "%s%d: invalid input protocol " 251144483Sharti "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 252144483Sharti ifp->if_name, ifp->if_unit, 253144483Sharti h->address, h->control, ntohs(h->protocol)); 254146061Sharti ++ifp->if_noproto; 255144483Sharti goto drop; 256144494Sharti case PPP_LCP: 257144494Sharti sppp_lcp_input ((struct sppp*) ifp, m); 258144483Sharti m_freem (m); 259144483Sharti return; 260144483Sharti#ifdef INET 261144483Sharti case PPP_IPCP: 262144483Sharti if (sp->lcp.state == LCP_STATE_OPENED) 263144483Sharti sppp_ipcp_input ((struct sppp*) ifp, m); 264144483Sharti m_freem (m); 265144483Sharti return; 266144483Sharti case PPP_IP: 267144483Sharti if (sp->ipcp.state == IPCP_STATE_OPENED) { 268144483Sharti schednetisr (NETISR_IP); 269144483Sharti inq = &ipintrq; 270144483Sharti } 271144483Sharti break; 272144483Sharti#endif 273144483Sharti#ifdef IPX 274144483Sharti case PPP_IPX: 275144483Sharti /* IPX IPXCP not implemented yet */ 276144483Sharti if (sp->lcp.state == LCP_STATE_OPENED) { 277144483Sharti schednetisr (NETISR_IPX); 278144483Sharti inq = &ipxintrq; 279144483Sharti } 280144483Sharti break; 281144483Sharti#endif 282144483Sharti#ifdef NS 283144483Sharti case PPP_XNS: 284144483Sharti /* XNS IDPCP not implemented yet */ 285144483Sharti if (sp->lcp.state == LCP_STATE_OPENED) { 286144483Sharti schednetisr (NETISR_NS); 287144483Sharti inq = &nsintrq; 288144483Sharti } 289144483Sharti break; 290144483Sharti#endif 291144483Sharti#ifdef ISO 292144483Sharti case PPP_ISO: 293144483Sharti /* OSI NLCP not implemented yet */ 294144483Sharti if (sp->lcp.state == LCP_STATE_OPENED) { 295144483Sharti schednetisr (NETISR_ISO); 296144483Sharti inq = &clnlintrq; 297144483Sharti } 298144483Sharti break; 299144483Sharti#endif 300144483Sharti } 301144483Sharti break; 302144483Sharti case CISCO_MULTICAST: 303144483Sharti case CISCO_UNICAST: 304144483Sharti /* Don't check the control field here (RFC 1547). */ 305144483Sharti if (! (sp->pp_flags & PP_CISCO)) { 306144483Sharti if (ifp->if_flags & IFF_DEBUG) 307144483Sharti log(LOG_DEBUG, 308144483Sharti "%s%d: Cisco packet in PPP mode " 3098874Srgrimes "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 3101590Srgrimes ifp->if_name, ifp->if_unit, 311144467Sharti h->address, h->control, ntohs(h->protocol)); 312144467Sharti goto drop; 313144467Sharti } 314144467Sharti switch (ntohs (h->protocol)) { 315144467Sharti default: 3161590Srgrimes ++ifp->if_noproto; 31718730Ssteve goto invalid; 31818730Ssteve case CISCO_KEEPALIVE: 31918730Ssteve sppp_cisco_input ((struct sppp*) ifp, m); 32018730Ssteve m_freem (m); 321138232Sharti return; 3221590Srgrimes#ifdef INET 3231590Srgrimes case ETHERTYPE_IP: 3241590Srgrimes schednetisr (NETISR_IP); 3251590Srgrimes inq = &ipintrq; 3261590Srgrimes break; 3271590Srgrimes#endif 328144467Sharti#ifdef IPX 3291590Srgrimes case ETHERTYPE_IPX: 3301590Srgrimes schednetisr (NETISR_IPX); 331144467Sharti inq = &ipxintrq; 332144467Sharti break; 333144467Sharti#endif 334144467Sharti#ifdef NS 335144467Sharti case ETHERTYPE_NS: 336144467Sharti schednetisr (NETISR_NS); 3371590Srgrimes inq = &nsintrq; 3381590Srgrimes break; 339144467Sharti#endif 340146061Sharti } 341144467Sharti break; 342144467Sharti } 3431590Srgrimes 3441590Srgrimes if (! (ifp->if_flags & IFF_UP) || ! inq) 3451590Srgrimes goto drop; 3461590Srgrimes 347144483Sharti /* Check queue. */ 348144467Sharti s = splimp (); 349144467Sharti if (IF_QFULL (inq)) { 350144467Sharti /* Queue overflow. */ 351144467Sharti IF_DROP (inq); 352144467Sharti splx (s); 353144467Sharti if (ifp->if_flags & IFF_DEBUG) 354144467Sharti log(LOG_DEBUG, "%s%d: protocol queue overflow\n", 355144741Sharti ifp->if_name, ifp->if_unit); 356144467Sharti goto drop; 357144467Sharti } 358144467Sharti IF_ENQUEUE (inq, m); 359144467Sharti splx (s); 360144467Sharti} 361144467Sharti 362144467Sharti/* 363144467Sharti * Enqueue transmit packet. 364144467Sharti */ 365144741Shartistatic int 366144467Shartisppp_output(struct ifnet *ifp, struct mbuf *m, 36718730Ssteve struct sockaddr *dst, struct rtentry *rt) 368144467Sharti{ 36918730Ssteve struct sppp *sp = (struct sppp*) ifp; 370144467Sharti struct ppp_header *h; 371144467Sharti struct ifqueue *ifq; 372144467Sharti int s = splimp (); 373144467Sharti 374144467Sharti if (! (ifp->if_flags & IFF_UP) || ! (ifp->if_flags & IFF_RUNNING)) { 375144467Sharti m_freem (m); 376144467Sharti splx (s); 377144467Sharti return (ENETDOWN); 378144741Sharti } 379144467Sharti 380144467Sharti ifq = &ifp->if_snd; 381144467Sharti#ifdef INET 3821590Srgrimes /* 3831590Srgrimes * Put low delay, telnet, rlogin and ftp control packets 384144467Sharti * in front of the queue. 385144467Sharti */ 386144467Sharti if (dst->sa_family == AF_INET) { 387144467Sharti struct ip *ip = mtod (m, struct ip*); 388144483Sharti struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 389146059Sharti 390146059Sharti if (! IF_QFULL (&sp->pp_fastq) && 3911590Srgrimes ((ip->ip_tos & IPTOS_LOWDELAY) || 392144467Sharti ip->ip_p == IPPROTO_TCP && 393144656Sharti m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) && 394138916Sharti (INTERACTIVE (ntohs (tcp->th_sport)) || 395138916Sharti INTERACTIVE (ntohs (tcp->th_dport))))) 396144494Sharti ifq = &sp->pp_fastq; 397138916Sharti } 398146061Sharti#endif 3991590Srgrimes 400137572Sphk /* 401104475Sphk * Prepend general data packet PPP header. For now, IP only. 402104475Sphk */ 403104475Sphk M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 404146061Sharti if (! m) { 4051590Srgrimes if (ifp->if_flags & IFF_DEBUG) 4061590Srgrimes log(LOG_DEBUG, "%s%d: no memory for transmit header\n", 4071590Srgrimes ifp->if_name, ifp->if_unit); 408146061Sharti splx (s); 4091590Srgrimes return (ENOBUFS); 410146061Sharti } 4111590Srgrimes h = mtod (m, struct ppp_header*); 4121590Srgrimes if (sp->pp_flags & PP_CISCO) { 4131590Srgrimes h->address = CISCO_MULTICAST; /* broadcast address */ 414137202Sharti h->control = 0; 415137202Sharti } else { 416138232Sharti h->address = PPP_ALLSTATIONS; /* broadcast address */ 41718730Ssteve h->control = PPP_UI; /* Unnumbered Info */ 4181590Srgrimes } 419137252Sharti 420137252Sharti switch (dst->sa_family) { 421137252Sharti#ifdef INET 4228874Srgrimes case AF_INET: /* Internet Protocol */ 423138916Sharti if (sp->pp_flags & PP_CISCO) 424138916Sharti h->protocol = htons (ETHERTYPE_IP); 425138916Sharti else if (sp->ipcp.state == IPCP_STATE_OPENED) 4261590Srgrimes h->protocol = htons (PPP_IP); 427144494Sharti else { 4281590Srgrimes m_freem (m); 429144656Sharti splx (s); 430144656Sharti return (ENETDOWN); 431144656Sharti } 4321590Srgrimes break; 433137605Sharti#endif 434137605Sharti#ifdef NS 435137605Sharti case AF_NS: /* Xerox NS Protocol */ 4361590Srgrimes h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 43718730Ssteve ETHERTYPE_NS : PPP_XNS); 4381590Srgrimes break; 4391590Srgrimes#endif 44018730Ssteve#ifdef IPX 4411590Srgrimes case AF_IPX: /* Novell IPX Protocol */ 44218730Ssteve h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 4431590Srgrimes ETHERTYPE_IPX : PPP_IPX); 4441590Srgrimes break; 4451590Srgrimes#endif 44618730Ssteve#ifdef ISO 44718730Ssteve case AF_ISO: /* ISO OSI Protocol */ 44818730Ssteve if (sp->pp_flags & PP_CISCO) 44918730Ssteve goto nosupport; 45018730Ssteve h->protocol = htons (PPP_ISO); 45118730Ssteve break; 452103503Sjmallettnosupport: 45318730Ssteve#endif 454138232Sharti default: 45518730Ssteve m_freem (m); 45618730Ssteve splx (s); 45718730Ssteve return (EAFNOSUPPORT); 45818730Ssteve } 45918730Ssteve 46018730Ssteve /* 46118730Ssteve * Queue message on interface, and start output if interface 462103503Sjmallett * not yet active. 463103503Sjmallett */ 46418730Ssteve if (IF_QFULL (ifq)) { 465146129Sharti IF_DROP (&ifp->if_snd); 466146129Sharti m_freem (m); 467146129Sharti splx (s); 468146129Sharti return (ENOBUFS); 469146129Sharti } 470146129Sharti IF_ENQUEUE (ifq, m); 471146129Sharti if (! (ifp->if_flags & IFF_OACTIVE)) 472146129Sharti (*ifp->if_start) (ifp); 473146129Sharti 474146129Sharti /* 475146129Sharti * Count output packets and bytes. 476146129Sharti * The packet length includes header, FCS and 1 flag, 477146129Sharti * according to RFC 1333. 478146129Sharti */ 479146129Sharti ifp->if_obytes += m->m_pkthdr.len + 3; 48092921Simp splx (s); 48192921Simp return (0); 48292921Simp} 483144483Sharti 48492921Simpvoid 48592921Simpsppp_attach(struct ifnet *ifp) 486146129Sharti{ 4871590Srgrimes struct sppp *sp = (struct sppp*) ifp; 488144467Sharti 489146129Sharti /* Initialize keepalive handler. */ 490146129Sharti if (! spppq) 491146129Sharti timeout (sppp_keepalive, 0, hz * 10); 492146129Sharti 493146129Sharti /* Insert new entry into the keepalive list. */ 494146129Sharti sp->pp_next = spppq; 495146129Sharti spppq = sp; 496146129Sharti 497146129Sharti sp->pp_if.if_type = IFT_PPP; 498146129Sharti sp->pp_if.if_output = sppp_output; 499146129Sharti sp->pp_fastq.ifq_maxlen = 32; 500146129Sharti sp->pp_loopcnt = 0; 501146129Sharti sp->pp_alivecnt = 0; 502146129Sharti sp->pp_seq = 0; 503146129Sharti sp->pp_rseq = 0; 504146129Sharti sp->lcp.magic = 0; 505146129Sharti sp->lcp.state = LCP_STATE_CLOSED; 506146129Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 507146129Sharti} 508146129Sharti 509146129Shartivoid 510146129Shartisppp_detach(struct ifnet *ifp) 511146129Sharti{ 512146129Sharti struct sppp **q, *p, *sp = (struct sppp*) ifp; 513146129Sharti 514146129Sharti /* Remove the entry from the keepalive list. */ 515146129Sharti for (q = &spppq; (p = *q); q = &p->pp_next) 516146129Sharti if (p == sp) { 517146129Sharti *q = p->pp_next; 518146129Sharti break; 519146129Sharti } 520146129Sharti 521146129Sharti /* Stop keepalive handler. */ 522146129Sharti if (! spppq) 523146129Sharti untimeout (sppp_keepalive, 0); 524146129Sharti UNTIMO (sp); 525146129Sharti} 526146129Sharti 527146129Sharti/* 528146129Sharti * Flush the interface output queue. 529146129Sharti */ 530146129Shartivoid 531146129Shartisppp_flush(struct ifnet *ifp) 532146129Sharti{ 533146129Sharti struct sppp *sp = (struct sppp*) ifp; 534146129Sharti 535146129Sharti qflush (&sp->pp_if.if_snd); 536146129Sharti qflush (&sp->pp_fastq); 537146129Sharti} 538146129Sharti 539146129Sharti/* 540146129Sharti * Check if the output queue is empty. 541146129Sharti */ 542146129Shartiint 543146129Shartisppp_isempty(struct ifnet *ifp) 544146129Sharti{ 545146129Sharti struct sppp *sp = (struct sppp*) ifp; 546146129Sharti int empty, s = splimp (); 547146129Sharti 548146129Sharti empty = !sp->pp_fastq.ifq_head && !sp->pp_if.if_snd.ifq_head; 549146129Sharti splx (s); 550146129Sharti return (empty); 551146129Sharti} 552146129Sharti 553146129Sharti/* 554146129Sharti * Get next packet to send. 555146129Sharti */ 556146129Shartistruct mbuf * 557146129Shartisppp_dequeue(struct ifnet *ifp) 558146129Sharti{ 559146129Sharti struct sppp *sp = (struct sppp*) ifp; 560146129Sharti struct mbuf *m; 561146129Sharti int s = splimp (); 562146129Sharti 563146129Sharti IF_DEQUEUE (&sp->pp_fastq, m); 564146129Sharti if (! m) 565146129Sharti IF_DEQUEUE (&sp->pp_if.if_snd, m); 566146129Sharti splx (s); 567146129Sharti return (m); 568146129Sharti} 569146129Sharti 570146129Sharti/* 571146129Sharti * Send keepalive packets, every 10 seconds. 572146129Sharti */ 573146129Shartistatic void 574146129Shartisppp_keepalive(void *dummy) 575146129Sharti{ 576146129Sharti struct sppp *sp; 577146129Sharti int s = splimp (); 578146129Sharti 579146129Sharti for (sp=spppq; sp; sp=sp->pp_next) { 580146129Sharti struct ifnet *ifp = &sp->pp_if; 581137605Sharti 582144467Sharti /* Keepalive mode disabled or channel down? */ 583144467Sharti if (! (sp->pp_flags & PP_KEEPALIVE) || 584137605Sharti ! (ifp->if_flags & IFF_RUNNING)) 585137605Sharti continue; 586137605Sharti 587137605Sharti /* No keepalive in PPP mode if LCP not opened yet. */ 588137605Sharti if (! (sp->pp_flags & PP_CISCO) && 589137605Sharti sp->lcp.state != LCP_STATE_OPENED) 590137605Sharti continue; 591137605Sharti 592144467Sharti if (sp->pp_alivecnt == MAXALIVECNT) { 5931590Srgrimes /* No keepalive packets got. Stop the interface. */ 594137252Sharti printf ("%s%d: down\n", ifp->if_name, ifp->if_unit); 5951590Srgrimes if_down (ifp); 5961590Srgrimes qflush (&sp->pp_fastq); 5971590Srgrimes if (! (sp->pp_flags & PP_CISCO)) { 5981590Srgrimes /* Shut down the PPP link. */ 5991590Srgrimes sp->lcp.state = LCP_STATE_CLOSED; 6001590Srgrimes sp->ipcp.state = IPCP_STATE_CLOSED; 601104696Sjmallett UNTIMO (sp); 6021590Srgrimes /* Initiate negotiation. */ 603144741Sharti sppp_lcp_open (sp); 604144467Sharti } 605144467Sharti } 6068874Srgrimes if (sp->pp_alivecnt <= MAXALIVECNT) 607144467Sharti ++sp->pp_alivecnt; 608144467Sharti if (sp->pp_flags & PP_CISCO) 609144467Sharti sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 610137605Sharti sp->pp_rseq); 611144467Sharti else if (sp->lcp.state == LCP_STATE_OPENED) { 612144741Sharti long nmagic = htonl (sp->lcp.magic); 613144741Sharti sp->lcp.echoid = ++sp->pp_seq; 614144741Sharti sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, 615144741Sharti sp->lcp.echoid, 4, &nmagic); 616144741Sharti } 6171590Srgrimes } 618144467Sharti splx (s); 619144467Sharti timeout (sppp_keepalive, 0, hz * 10); 620144467Sharti} 621144467Sharti 622144467Sharti/* 623144467Sharti * Handle incoming PPP Link Control Protocol packets. 624144467Sharti */ 625144467Shartistatic void 626144657Shartisppp_lcp_input(struct sppp *sp, struct mbuf *m) 627144467Sharti{ 628144467Sharti struct lcp_header *h; 6298874Srgrimes struct ifnet *ifp = &sp->pp_if; 630144467Sharti int len = m->m_pkthdr.len, debug = ifp->if_flags & IFF_DEBUG; 631144467Sharti u_char *p, opt[6]; 632144467Sharti u_long rmagic; 633144467Sharti 634144467Sharti if (len < 4) { 635144467Sharti if (debug) 6368874Srgrimes log(LOG_DEBUG, 637144467Sharti "%s%d: invalid lcp packet length: %d bytes\n", 638144467Sharti ifp->if_name, ifp->if_unit, len); 639144467Sharti return; 640144467Sharti } 641144467Sharti h = mtod (m, struct lcp_header*); 642144467Sharti if (debug) { 643144467Sharti const char *state = "unknown"; 644144467Sharti switch (sp->lcp.state) { 645144467Sharti case LCP_STATE_CLOSED: state = "closed"; break; 646144467Sharti case LCP_STATE_ACK_RCVD: state = "ack-rcvd"; break; 647144467Sharti case LCP_STATE_ACK_SENT: state = "ack-sent"; break; 6481590Srgrimes case LCP_STATE_OPENED: state = "opened"; break; 649144467Sharti } 650144467Sharti log(LOG_DEBUG, 651144467Sharti "%s%d: lcp input(%s): %d bytes <%s id=0x%x len=0x%x", 6521590Srgrimes ifp->if_name, ifp->if_unit, state, len, 653144467Sharti sppp_lcp_type_name (h->type), h->ident, ntohs (h->len)); 65418730Ssteve if (len > 4) 655144467Sharti sppp_print_bytes ((u_char*) (h+1), len-4); 656144741Sharti addlog(">\n"); 657144741Sharti } 658144741Sharti if (len > ntohs (h->len)) 659144741Sharti len = ntohs (h->len); 660144741Sharti switch (h->type) { 6611590Srgrimes default: 662144467Sharti /* Unknown packet type -- send Code-Reject packet. */ 663144467Sharti if (debug) 664144467Sharti addlog("%s%d: sending lcp code rej\n", 665144467Sharti ifp->if_name, ifp->if_unit); 6661590Srgrimes sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, 6671590Srgrimes m->m_pkthdr.len, h); 668144467Sharti break; 6691590Srgrimes case LCP_CONF_REQ: 6701590Srgrimes if (len < 4) { 6711590Srgrimes if (debug) 6721590Srgrimes addlog("%s%d: invalid lcp configure request " 6731590Srgrimes "packet length: %d bytes\n", 6741590Srgrimes ifp->if_name, ifp->if_unit, len); 6751590Srgrimes break; 6761590Srgrimes } 6771590Srgrimes rmagic = 0xd00ddeed; /* in case LCP fails */ 6781590Srgrimes if (len > 4 && 6791590Srgrimes !sppp_lcp_conf_parse_options (sp, h, len, &rmagic)) 68094594Sobrien goto badreq; 681142993Sharti if (rmagic == sp->lcp.magic) { 6821590Srgrimes /* Local and remote magics equal -- loopback? */ 6831590Srgrimes if (sp->pp_loopcnt >= MAXALIVECNT*5) { 6841590Srgrimes printf ("%s%d: loopback\n", 6851590Srgrimes ifp->if_name, ifp->if_unit); 6861590Srgrimes sp->pp_loopcnt = 0; 6871590Srgrimes if (ifp->if_flags & IFF_UP) { 6881590Srgrimes if_down (ifp); 6891590Srgrimes qflush (&sp->pp_fastq); 6901590Srgrimes } 6911590Srgrimes } else if (debug) { 6921590Srgrimes addlog("%s%d: conf req: magic glitch, " 6931590Srgrimes "sending config nak\n", 694144741Sharti ifp->if_name, ifp->if_unit); 6951590Srgrimes } 696144467Sharti ++sp->pp_loopcnt; 697141258Sharti 698141258Sharti /* MUST send Conf-Nack packet. */ 699144467Sharti rmagic = ~sp->lcp.magic; 700141258Sharti opt[0] = LCP_OPT_MAGIC; 701144467Sharti opt[1] = sizeof (opt); 702141258Sharti opt[2] = rmagic >> 24; 703141258Sharti opt[3] = rmagic >> 16; 704144467Sharti opt[4] = rmagic >> 8; 705144467Sharti opt[5] = rmagic; 706144467Sharti sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, 7071590Srgrimes h->ident, sizeof (opt), &opt); 708144467Sharti badreq: 7091590Srgrimes switch (sp->lcp.state) { 710144467Sharti case LCP_STATE_OPENED: 711144467Sharti /* Initiate renegotiation. */ 712144467Sharti sppp_lcp_open (sp); 713144467Sharti /* fall through... */ 714144467Sharti case LCP_STATE_ACK_SENT: 715144467Sharti /* Go to closed state. */ 716144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 717144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 7181590Srgrimes } 7191590Srgrimes break; 720144467Sharti } 721144467Sharti /* Send Configure-Ack packet. */ 722144467Sharti if (debug) 723144467Sharti addlog("%s%d: sending configure ack\n", 7241590Srgrimes ifp->if_name, ifp->if_unit); 725144467Sharti sp->pp_loopcnt = 0; 7261590Srgrimes sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, 727144467Sharti h->ident, len-4, h+1); 728144467Sharti /* Change the state. */ 729144467Sharti switch (sp->lcp.state) { 730144467Sharti case LCP_STATE_CLOSED: 731144467Sharti sp->lcp.state = LCP_STATE_ACK_SENT; 732142457Sharti break; 733146027Sharti case LCP_STATE_ACK_RCVD: 734144467Sharti sp->lcp.state = LCP_STATE_OPENED; 735142457Sharti sppp_ipcp_open (sp); 736144467Sharti break; 7371590Srgrimes case LCP_STATE_OPENED: 738144467Sharti /* Remote magic changed -- close session. */ 7391590Srgrimes sp->lcp.state = LCP_STATE_CLOSED; 740144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 741144467Sharti /* Initiate renegotiation. */ 742144467Sharti sppp_lcp_open (sp); 743144467Sharti /* An ACK has already been sent. */ 744144467Sharti sp->lcp.state = LCP_STATE_ACK_SENT; 745144467Sharti break; 746132839Sharti } 747144467Sharti break; 748144467Sharti case LCP_CONF_ACK: 749144467Sharti if (h->ident != sp->lcp.confid) { 750132839Sharti if (debug) 751144467Sharti addlog("%s%d: lcp id mismatch 0x%x != 0x%x\n", 752144467Sharti ifp->if_name, ifp->if_unit, 753144467Sharti h->ident, sp->lcp.confid); 754132839Sharti break; 755144467Sharti } 756144467Sharti UNTIMO (sp); 757144467Sharti if (! (ifp->if_flags & IFF_UP) && 758144467Sharti (ifp->if_flags & IFF_RUNNING)) { 759144467Sharti /* Coming out of loopback mode. */ 760144467Sharti ifp->if_flags |= IFF_UP; 761144467Sharti printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 762144741Sharti } 763144467Sharti switch (sp->lcp.state) { 764144467Sharti case LCP_STATE_CLOSED: 765144467Sharti sp->lcp.state = LCP_STATE_ACK_RCVD; 766144467Sharti TIMO (sp, 5); 767144467Sharti break; 7681590Srgrimes case LCP_STATE_ACK_SENT: 7691590Srgrimes sp->lcp.state = LCP_STATE_OPENED; 770144467Sharti sppp_ipcp_open (sp); 771144467Sharti break; 7721590Srgrimes } 773144467Sharti break; 774144467Sharti case LCP_CONF_NAK: 7751590Srgrimes if (h->ident != sp->lcp.confid) { 77618730Ssteve if (debug) 7771590Srgrimes addlog("%s%d: lcp id mismatch 0x%x != 0x%x\n", 778144467Sharti ifp->if_name, ifp->if_unit, 7791590Srgrimes h->ident, sp->lcp.confid); 780144467Sharti break; 781144467Sharti } 782144467Sharti p = (u_char*) (h+1); 783144467Sharti if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) { 784144467Sharti rmagic = (u_long)p[2] << 24 | 785144467Sharti (u_long)p[3] << 16 | p[4] << 8 | p[5]; 786144467Sharti if (rmagic == ~sp->lcp.magic) { 787144467Sharti if (debug) 788144467Sharti addlog("%s%d: conf nak: magic glitch\n", 789144467Sharti ifp->if_name, ifp->if_unit); 790144467Sharti sp->lcp.magic += time.tv_sec + time.tv_usec; 791144467Sharti } else 792144467Sharti sp->lcp.magic = rmagic; 793144467Sharti } 794144467Sharti if (sp->lcp.state != LCP_STATE_ACK_SENT) { 795144467Sharti /* Go to closed state. */ 796144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 797144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 798144467Sharti } 799144467Sharti /* The link will be renegotiated after timeout, 800144467Sharti * to avoid endless req-nack loop. */ 801144467Sharti if (debug) 802144467Sharti addlog("%s%d: sleeping due to nak\n", 803144657Sharti ifp->if_name, ifp->if_unit); 804144467Sharti UNTIMO (sp); 805144467Sharti TIMO (sp, 2); 806144467Sharti break; 807144467Sharti case LCP_CONF_REJ: 808144467Sharti if (h->ident != sp->lcp.confid) { 809144467Sharti if (debug) 810144467Sharti addlog("%s%d: lcp id mismatch 0x%x != 0x%x\n", 811144467Sharti ifp->if_name, ifp->if_unit, 812144467Sharti h->ident, sp->lcp.confid); 813144467Sharti break; 814144467Sharti } 815144467Sharti UNTIMO (sp); 816144467Sharti /* Initiate renegotiation. */ 817144467Sharti if (debug) 818144467Sharti addlog("%s%d: reopening lcp\n", 819144467Sharti ifp->if_name, ifp->if_unit); 820144467Sharti sppp_lcp_open (sp); 821144467Sharti if (sp->lcp.state != LCP_STATE_ACK_SENT) { 822144467Sharti /* Go to closed state. */ 823144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 824144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 825144467Sharti } 826144467Sharti break; 827144467Sharti case LCP_TERM_REQ: 828144467Sharti UNTIMO (sp); 829144467Sharti /* Send Terminate-Ack packet. */ 830144467Sharti if (debug) 831144467Sharti addlog("%s%d: sending terminate-ack\n", 832144467Sharti ifp->if_name, ifp->if_unit); 833144467Sharti sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, 0); 834144467Sharti /* Go to closed state. */ 835144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 836144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 837144467Sharti /* Initiate renegotiation. */ 838144467Sharti sppp_lcp_open (sp); 8391590Srgrimes break; 840144467Sharti case LCP_TERM_ACK: 841144467Sharti case LCP_CODE_REJ: 842144467Sharti case LCP_PROTO_REJ: 8431590Srgrimes if (debug) 844144467Sharti addlog("%s%d: ignoring lcp code 0x%x\n", 8451590Srgrimes ifp->if_name, ifp->if_unit, h->type); 84618730Ssteve /* Ignore for now. */ 8471590Srgrimes break; 8481590Srgrimes case LCP_DISC_REQ: 849144467Sharti /* Discard the packet. */ 8501590Srgrimes break; 851144467Sharti case LCP_ECHO_REQ: 852144467Sharti if (sp->lcp.state != LCP_STATE_OPENED) { 8531590Srgrimes if (debug) 854144467Sharti addlog("%s%d: lcp echo req but lcp close\n", 8551590Srgrimes ifp->if_name, ifp->if_unit); 8561590Srgrimes break; 857144467Sharti } 85818730Ssteve if (len < 8) { 85918730Ssteve if (debug) 86018730Ssteve addlog("%s%d: invalid lcp echo request " 86118730Ssteve "packet length: %d bytes\n", 86218730Ssteve ifp->if_name, ifp->if_unit, len); 86318730Ssteve break; 86418730Ssteve } 865104696Sjmallett if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 86618730Ssteve /* Line loopback mode detected. */ 867138232Sharti printf ("%s%d: loopback\n", ifp->if_name, ifp->if_unit); 868144467Sharti if_down (ifp); 869137202Sharti qflush (&sp->pp_fastq); 870144467Sharti 87118730Ssteve /* Shut down the PPP link. */ 872144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 873144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 874144467Sharti UNTIMO (sp); 875144467Sharti /* Initiate negotiation. */ 876144467Sharti sppp_lcp_open (sp); 877144467Sharti break; 878144467Sharti } 879144467Sharti *(long*)(h+1) = htonl (sp->lcp.magic); 88018730Ssteve if (debug) 88118730Ssteve addlog("%s%d: got lcp echo req, sending echo rep\n", 88218730Ssteve ifp->if_name, ifp->if_unit); 883144467Sharti sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); 8841590Srgrimes break; 8851590Srgrimes case LCP_ECHO_REPLY: 8861590Srgrimes if (h->ident != sp->lcp.echoid) 8871590Srgrimes break; 8881590Srgrimes if (len < 8) { 8891590Srgrimes if (debug) 8901590Srgrimes addlog("%s%d: invalid lcp echo reply " 8911590Srgrimes "packet length: %d bytes\n", 8921590Srgrimes ifp->if_name, ifp->if_unit, len); 8931590Srgrimes break; 8941590Srgrimes } 8951590Srgrimes if (debug) 8961590Srgrimes addlog("%s%d: got lcp echo rep\n", 8971590Srgrimes ifp->if_name, ifp->if_unit); 8981590Srgrimes if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 8991590Srgrimes sp->pp_alivecnt = 0; 9001590Srgrimes break; 9011590Srgrimes } 902104696Sjmallett} 9031590Srgrimes 904144467Sharti/* 905144467Sharti * Handle incoming Cisco keepalive protocol packets. 9061590Srgrimes */ 907144657Shartistatic void 908144657Shartisppp_cisco_input(struct sppp *sp, struct mbuf *m) 909144657Sharti{ 910144467Sharti struct cisco_packet *h; 911144467Sharti struct ifaddr *ifa; 912144467Sharti struct ifnet *ifp = &sp->pp_if; 913144467Sharti int debug = ifp->if_flags & IFF_DEBUG; 914144467Sharti 915144467Sharti if (m->m_pkthdr.len != CISCO_PACKET_LEN) { 916144467Sharti if (debug) 917144467Sharti log(LOG_DEBUG, 918144467Sharti "%s%d: invalid cisco packet length: %d bytes\n", 919144467Sharti ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 920144467Sharti return; 921144467Sharti } 9228874Srgrimes h = mtod (m, struct cisco_packet*); 923144467Sharti if (debug) 924144467Sharti log(LOG_DEBUG, 925144467Sharti "%s%d: cisco input: %d bytes " 926144467Sharti "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 927144467Sharti ifp->if_name, ifp->if_unit, m->m_pkthdr.len, 928144467Sharti ntohl (h->type), h->par1, h->par2, h->rel, 929144467Sharti h->time0, h->time1); 930144467Sharti switch (ntohl (h->type)) { 931144467Sharti default: 9328874Srgrimes if (debug) 933144467Sharti addlog("%s%d: unknown cisco packet type: 0x%lx\n", 934144467Sharti ifp->if_name, ifp->if_unit, ntohl (h->type)); 935144467Sharti break; 936144467Sharti case CISCO_ADDR_REPLY: 937144467Sharti /* Reply on address request, ignore */ 938144467Sharti break; 9391590Srgrimes case CISCO_KEEPALIVE_REQ: 940144467Sharti sp->pp_alivecnt = 0; 941144467Sharti sp->pp_rseq = ntohl (h->par1); 942144467Sharti if (sp->pp_seq == sp->pp_rseq) { 943144467Sharti /* Local and remote sequence numbers are equal. 9441590Srgrimes * Probably, the line is in loopback mode. */ 9451590Srgrimes if (sp->pp_loopcnt >= MAXALIVECNT) { 946144467Sharti printf ("%s%d: loopback\n", 947144657Sharti ifp->if_name, ifp->if_unit); 948144467Sharti sp->pp_loopcnt = 0; 949144467Sharti if (ifp->if_flags & IFF_UP) { 950144467Sharti if_down (ifp); 951144467Sharti qflush (&sp->pp_fastq); 952144467Sharti } 953144467Sharti } 954144467Sharti ++sp->pp_loopcnt; 955144467Sharti 956144467Sharti /* Generate new local sequence number */ 957144467Sharti sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 958144467Sharti break; 959144467Sharti } 960144467Sharti sp->pp_loopcnt = 0; 961144467Sharti if (! (ifp->if_flags & IFF_UP) && 9621590Srgrimes (ifp->if_flags & IFF_RUNNING)) { 9631590Srgrimes ifp->if_flags |= IFF_UP; 964144467Sharti printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 965144665Sharti } 966144665Sharti break; 967144467Sharti case CISCO_ADDR_REQ: 968144467Sharti for (ifa=ifp->if_addrhead.tqh_first; ifa; 969144467Sharti ifa=ifa->ifa_link.tqe_next) 970144467Sharti if (ifa->ifa_addr->sa_family == AF_INET) 971144467Sharti break; 972144467Sharti if (! ifa) { 973144467Sharti if (debug) 974144467Sharti addlog("%s%d: unknown address for cisco request\n", 975144467Sharti ifp->if_name, ifp->if_unit); 976144467Sharti return; 977144467Sharti } 978144467Sharti sppp_cisco_send (sp, CISCO_ADDR_REPLY, 979144467Sharti ntohl (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr), 980144467Sharti ntohl (((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr)); 981144467Sharti break; 982144467Sharti } 983144467Sharti} 984144467Sharti 985144467Sharti/* 986144467Sharti * Send PPP LCP packet. 987144467Sharti */ 988144467Shartistatic void 989144665Shartisppp_cp_send(struct sppp *sp, u_short proto, u_char type, 990144665Sharti u_char ident, u_short len, void *data) 991144467Sharti{ 992144467Sharti struct ppp_header *h; 993144467Sharti struct lcp_header *lh; 994144467Sharti struct mbuf *m; 995144467Sharti struct ifnet *ifp = &sp->pp_if; 996144467Sharti int debug = ifp->if_flags & IFF_DEBUG; 997144467Sharti 998144494Sharti if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 999144467Sharti len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1000144467Sharti MGETHDR (m, M_DONTWAIT, MT_DATA); 1001144467Sharti if (! m) 1002144467Sharti return; 1003144467Sharti m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 1004144467Sharti m->m_pkthdr.rcvif = 0; 1005144467Sharti 1006144467Sharti h = mtod (m, struct ppp_header*); 1007144467Sharti h->address = PPP_ALLSTATIONS; /* broadcast address */ 1008144467Sharti h->control = PPP_UI; /* Unnumbered Info */ 1009144657Sharti h->protocol = htons (proto); /* Link Control Protocol */ 1010144467Sharti 1011144467Sharti lh = (struct lcp_header*) (h + 1); 1012144467Sharti lh->type = type; 1013144467Sharti lh->ident = ident; 1014144467Sharti lh->len = htons (LCP_HEADER_LEN + len); 1015144467Sharti if (len) 1016144467Sharti bcopy (data, lh+1, len); 1017144665Sharti 1018144665Sharti if (debug) { 101918730Ssteve log(LOG_DEBUG, "%s%d: %s output <%s id=%xh len=%xh", 1020144467Sharti ifp->if_name, ifp->if_unit, 1021144467Sharti proto==PPP_LCP ? "lcp" : "ipcp", 1022144467Sharti proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : 1023144467Sharti sppp_ipcp_type_name (lh->type), lh->ident, 1024144467Sharti ntohs (lh->len)); 1025144467Sharti if (len) 1026144467Sharti sppp_print_bytes ((u_char*) (lh+1), len); 1027144467Sharti addlog(">\n"); 102818730Ssteve } 1029144467Sharti if (IF_QFULL (&sp->pp_fastq)) { 1030144467Sharti IF_DROP (&ifp->if_snd); 1031144494Sharti m_freem (m); 1032144467Sharti } else 1033144665Sharti IF_ENQUEUE (&sp->pp_fastq, m); 1034144665Sharti if (! (ifp->if_flags & IFF_OACTIVE)) 1035144467Sharti (*ifp->if_start) (ifp); 1036144467Sharti ifp->if_obytes += m->m_pkthdr.len + 3; 1037144467Sharti} 1038144467Sharti 1039144467Sharti/* 1040144467Sharti * Send Cisco keepalive packet. 10411590Srgrimes */ 1042144467Shartistatic void 1043144467Shartisppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 1044144467Sharti{ 1045144467Sharti struct ppp_header *h; 1046144467Sharti struct cisco_packet *ch; 1047144467Sharti struct mbuf *m; 1048144467Sharti struct ifnet *ifp = &sp->pp_if; 10491590Srgrimes u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 1050144467Sharti int debug = ifp->if_flags & IFF_DEBUG; 10511590Srgrimes 10521590Srgrimes MGETHDR (m, M_DONTWAIT, MT_DATA); 10531590Srgrimes if (! m) 1054144467Sharti return; 1055144467Sharti m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 1056144467Sharti m->m_pkthdr.rcvif = 0; 10571590Srgrimes 1058144467Sharti h = mtod (m, struct ppp_header*); 1059144467Sharti h->address = CISCO_MULTICAST; 1060144467Sharti h->control = 0; 1061144467Sharti h->protocol = htons (CISCO_KEEPALIVE); 1062144467Sharti 1063144467Sharti ch = (struct cisco_packet*) (h + 1); 1064144467Sharti ch->type = htonl (type); 1065144467Sharti ch->par1 = htonl (par1); 1066144467Sharti ch->par2 = htonl (par2); 1067144467Sharti ch->rel = -1; 1068144467Sharti ch->time0 = htons ((u_short) (t >> 16)); 1069144467Sharti ch->time1 = htons ((u_short) t); 1070144467Sharti 1071144467Sharti if (debug) 1072144467Sharti log(LOG_DEBUG, 1073144467Sharti "%s%d: cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 1074144467Sharti ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1, 1075144467Sharti ch->par2, ch->rel, ch->time0, ch->time1); 1076144467Sharti 1077144467Sharti if (IF_QFULL (&sp->pp_fastq)) { 1078144467Sharti IF_DROP (&ifp->if_snd); 1079144467Sharti m_freem (m); 1080144467Sharti } else 1081144467Sharti IF_ENQUEUE (&sp->pp_fastq, m); 1082144467Sharti if (! (ifp->if_flags & IFF_OACTIVE)) 1083144467Sharti (*ifp->if_start) (ifp); 10841590Srgrimes ifp->if_obytes += m->m_pkthdr.len + 3; 1085143703Sharti} 1086144657Sharti 1087144657Sharti/* 1088144467Sharti * Process an ioctl request. Called on low priority level. 1089144467Sharti */ 1090144467Shartiint 1091144467Shartisppp_ioctl(struct ifnet *ifp, int cmd, void *data) 1092144467Sharti{ 1093144467Sharti struct ifreq *ifr = (struct ifreq*) data; 1094144467Sharti struct sppp *sp = (struct sppp*) ifp; 1095144467Sharti int s, going_up, going_down; 1096146027Sharti 1097146027Sharti switch (cmd) { 1098144467Sharti default: 10991590Srgrimes return (ENOTTY); 1100144467Sharti 1101144467Sharti case SIOCAIFADDR: 1102144467Sharti case SIOCSIFDSTADDR: 11031590Srgrimes break; 1104144467Sharti 1105144467Sharti case SIOCSIFADDR: 1106144467Sharti ifp->if_flags |= IFF_UP; 1107144467Sharti /* fall through... */ 1108144467Sharti 1109144467Sharti case SIOCSIFFLAGS: 1110144467Sharti s = splimp (); 11111590Srgrimes going_up = (ifp->if_flags & IFF_UP) && 1112144467Sharti ! (ifp->if_flags & IFF_RUNNING); 11131590Srgrimes going_down = ! (ifp->if_flags & IFF_UP) && 1114144657Sharti (ifp->if_flags & IFF_RUNNING); 1115144467Sharti if (going_up || going_down) { 1116144467Sharti /* Shut down the PPP link. */ 1117144467Sharti ifp->if_flags &= ~IFF_RUNNING; 1118144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 1119144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 1120144467Sharti UNTIMO (sp); 1121144467Sharti } 11228874Srgrimes if (going_up) { 1123144657Sharti /* Interface is starting -- initiate negotiation. */ 1124144467Sharti ifp->if_flags |= IFF_RUNNING; 1125144467Sharti if (!(sp->pp_flags & PP_CISCO)) 1126144467Sharti sppp_lcp_open (sp); 1127144467Sharti } 1128144467Sharti splx (s); 11291590Srgrimes break; 11301590Srgrimes 1131144467Sharti#ifdef SIOCSIFMTU 1132144467Sharti#ifndef ifr_mtu 11331590Srgrimes#define ifr_mtu ifr_metric 1134104696Sjmallett#endif 11351590Srgrimes case SIOCSIFMTU: 11361590Srgrimes if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > PP_MTU) 11371590Srgrimes return (EINVAL); 11381590Srgrimes ifp->if_mtu = ifr->ifr_mtu; 11391590Srgrimes break; 11401590Srgrimes#endif 1141104696Sjmallett#ifdef SLIOCSETMTU 11421590Srgrimes case SLIOCSETMTU: 1143144467Sharti if (*(short*)data < 128 || *(short*)data > PP_MTU) 1144144467Sharti return (EINVAL); 11451590Srgrimes ifp->if_mtu = *(short*)data; 1146144467Sharti break; 1147144467Sharti#endif 1148144467Sharti#ifdef SIOCGIFMTU 1149144467Sharti case SIOCGIFMTU: 1150144467Sharti ifr->ifr_mtu = ifp->if_mtu; 1151144467Sharti break; 1152144467Sharti#endif 11538874Srgrimes#ifdef SLIOCGETMTU 1154144467Sharti case SLIOCGETMTU: 1155144467Sharti *(short*)data = ifp->if_mtu; 1156144467Sharti break; 1157144467Sharti#endif 11581590Srgrimes case SIOCADDMULTI: 1159144467Sharti case SIOCDELMULTI: 1160144467Sharti break; 1161144467Sharti } 11621590Srgrimes return (0); 1163144467Sharti} 1164144467Sharti 1165144467Sharti/* 1166144467Sharti * Analyze the LCP Configure-Request options list 1167144467Sharti * for the presence of unknown options. 1168144467Sharti * If the request contains unknown options, build and 11691590Srgrimes * send Configure-reject packet, containing only unknown options. 1170144467Sharti */ 1171144467Shartistatic int 1172144467Shartisppp_lcp_conf_parse_options(struct sppp *sp, struct lcp_header *h, 11731590Srgrimes int len, u_long *magic) 1174144467Sharti{ 1175144467Sharti u_char *buf, *r, *p; 11761590Srgrimes struct ifnet *ifp = &sp->pp_if; 1177144467Sharti int rlen, debug = ifp->if_flags & IFF_DEBUG; 1178144467Sharti 1179144467Sharti len -= 4; 1180144467Sharti buf = r = malloc (len, M_TEMP, M_NOWAIT); 1181144467Sharti if (! buf) 1182144467Sharti return (0); 1183144467Sharti 1184144467Sharti if (debug) 1185144467Sharti addlog("%s%d: lcp parse opts: ", ifp->if_name, ifp->if_unit); 1186144467Sharti 1187144467Sharti p = (void*) (h+1); 1188144467Sharti for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 1189144467Sharti switch (*p) { 1190144467Sharti case LCP_OPT_MAGIC: 1191144467Sharti /* Magic number -- extract. */ 11921590Srgrimes if (debug) 11931590Srgrimes addlog(" magicnum: "); 11941590Srgrimes if (len >= 6 && p[1] == 6) { 11951590Srgrimes *magic = (u_long)p[2] << 24 | 1196144467Sharti (u_long)p[3] << 16 | p[4] << 8 | p[5]; 1197144467Sharti if (debug) 11988874Srgrimes addlog("0x%x", *magic); 11991590Srgrimes continue; 12001590Srgrimes } 12011590Srgrimes if (debug) 12021590Srgrimes addlog("invalid"); 12031590Srgrimes break; 12041590Srgrimes case LCP_OPT_ASYNC_MAP: 12051590Srgrimes /* Async control character map -- check to be zero. */ 12061590Srgrimes if (debug) 12071590Srgrimes addlog(" asyncmap: "); 1208104696Sjmallett if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && 12091590Srgrimes ! p[4] && ! p[5]) { 1210138232Sharti if (debug) 1211144467Sharti addlog("empty (ack)"); 1212144467Sharti continue; 1213144467Sharti } 1214144467Sharti if (debug) 1215144467Sharti addlog("non-empty (rej)"); 1216144467Sharti break; 1217144657Sharti case LCP_OPT_MRU: 1218144467Sharti /* Maximum receive unit -- always OK. */ 1219144467Sharti if (debug) 1220144467Sharti addlog(" mru (ignored)"); 1221144467Sharti continue; 1222144467Sharti default: 1223144467Sharti /* Others not supported. */ 1224144467Sharti if (debug) 1225144467Sharti addlog(" unknown 0x%x", *p); 1226144467Sharti break; 1227144467Sharti } 1228144467Sharti /* Add the option to rejected list. */ 1229144467Sharti bcopy (p, r, p[1]); 1230144467Sharti r += p[1]; 1231144467Sharti rlen += p[1]; 123218730Ssteve } 1233144467Sharti if (rlen) { 1234144467Sharti if (debug) 1235144467Sharti addlog(", send lcp configure nak\n"); 1236144467Sharti sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, h->ident, rlen, buf); 1237144467Sharti } else if (debug) 1238144467Sharti addlog("\n"); 1239144467Sharti free (buf, M_TEMP); 1240144467Sharti return (rlen == 0); 1241144467Sharti} 1242144467Sharti 1243144467Shartistatic void 1244144467Shartisppp_ipcp_input(struct sppp *sp, struct mbuf *m) 1245144467Sharti{ 1246144467Sharti struct lcp_header *h; 1247144467Sharti struct ifnet *ifp = &sp->pp_if; 1248144467Sharti int len = m->m_pkthdr.len, debug = ifp->if_flags & IFF_DEBUG;; 1249144467Sharti 1250144467Sharti if (len < 4) { 1251144467Sharti printf ("%s%d: invalid ipcp packet length: %d bytes\n", 1252144467Sharti ifp->if_name, ifp->if_unit, len); 1253144467Sharti return; 1254144467Sharti } 125535483Simp h = mtod (m, struct lcp_header*); 1256144467Sharti if (debug) { 1257144467Sharti log(LOG_DEBUG, 1258144467Sharti "%s%d: ipcp input: %d bytes <%s id=0x%x len=0x%x", 125935483Simp ifp->if_name, ifp->if_unit, len, 1260144467Sharti sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); 1261144467Sharti if (len > 4) 1262144467Sharti sppp_print_bytes ((u_char*) (h+1), len-4); 1263144467Sharti addlog(">\n"); 1264144467Sharti } 12651590Srgrimes if (len > ntohs (h->len)) 1266144467Sharti len = ntohs (h->len); 12671590Srgrimes switch (h->type) { 12681590Srgrimes default: 1269144467Sharti /* Unknown packet type -- send Code-Reject packet. */ 1270144467Sharti if (debug) 12711590Srgrimes addlog("%s%d: ipcp unknown type 0x%x, sending code rej\n", 12721590Srgrimes ifp->if_name, ifp->if_unit, h->type); 12731590Srgrimes sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); 12741590Srgrimes break; 12751590Srgrimes case IPCP_CONF_REQ: 12761590Srgrimes if (len < 4) { 12771590Srgrimes if (debug) 12781590Srgrimes addlog("%s%d: invalid ipcp configure " 1279104696Sjmallett "request packet length: %d bytes\n", 12801590Srgrimes ifp->if_name, ifp->if_unit, len); 1281146129Sharti return; 1282146129Sharti } 12838874Srgrimes if (len > 4) { 1284144467Sharti if (debug) 1285146061Sharti addlog("%s%d: rejecting ipcp conf req len=%d\n", 12868874Srgrimes ifp->if_name, ifp->if_unit, len); 1287144467Sharti sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, 1288144467Sharti len-4, h+1); 1289144467Sharti 1290144467Sharti switch (sp->ipcp.state) { 1291144467Sharti case IPCP_STATE_OPENED: 1292144467Sharti /* Initiate renegotiation. */ 12931590Srgrimes sppp_ipcp_open (sp); 12948874Srgrimes /* fall through... */ 12951590Srgrimes case IPCP_STATE_ACK_SENT: 1296144467Sharti /* Go to closed state. */ 1297144467Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 1298144467Sharti } 1299144467Sharti } else { 13001590Srgrimes if (debug) 1301144657Sharti addlog("%s%d: sending ipcp conf ack\n", 1302144467Sharti ifp->if_name, ifp->if_unit); 1303144467Sharti /* Send Configure-Ack packet. */ 1304144467Sharti sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, 13051590Srgrimes 0, 0); 13061590Srgrimes /* Change the state. */ 1307146129Sharti if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) 1308146129Sharti sp->ipcp.state = IPCP_STATE_OPENED; 1309146129Sharti else 1310146129Sharti sp->ipcp.state = IPCP_STATE_ACK_SENT; 1311146129Sharti } 1312146129Sharti break; 1313146129Sharti case IPCP_CONF_ACK: 1314146129Sharti if (h->ident != sp->ipcp.confid) { 1315146129Sharti if (debug) 1316146129Sharti addlog("%s%d: ipcp id mismatch 0x%x != 0x%x\n", 1317146129Sharti ifp->if_name, ifp->if_unit, 1318146129Sharti h->ident, sp->ipcp.confid); 1319146129Sharti break; 1320146129Sharti } 1321146129Sharti UNTIMO (sp); 1322146129Sharti switch (sp->ipcp.state) { 1323146129Sharti case IPCP_STATE_CLOSED: 1324146129Sharti sp->ipcp.state = IPCP_STATE_ACK_RCVD; 1325146129Sharti TIMO (sp, 5); 1326146129Sharti break; 1327146129Sharti case IPCP_STATE_ACK_SENT: 1328146129Sharti sp->ipcp.state = IPCP_STATE_OPENED; 1329146129Sharti break; 1330146129Sharti } 1331146129Sharti break; 1332146129Sharti case IPCP_CONF_NAK: 1333146129Sharti case IPCP_CONF_REJ: 1334146058Sharti if (h->ident != sp->ipcp.confid) { 1335144467Sharti if (debug) 1336146058Sharti addlog("%s%d: ipcp id mismatch 0x%x != 0x%x\n", 1337144467Sharti ifp->if_name, ifp->if_unit, 1338144665Sharti h->ident, sp->ipcp.confid); 1339144665Sharti break; 1340144665Sharti } 1341144665Sharti if (debug) 1342144467Sharti addlog("%s%d: got ipcp conf %s, reopening ipcp\n", 1343144467Sharti ifp->if_name, ifp->if_unit, 1344144467Sharti (h->type == IPCP_CONF_NAK? "nak": "rej")); 1345146129Sharti UNTIMO (sp); 1346146129Sharti /* Initiate renegotiation. */ 1347144665Sharti sppp_ipcp_open (sp); 1348144665Sharti if (sp->ipcp.state != IPCP_STATE_ACK_SENT) 1349144665Sharti /* Go to closed state. */ 1350144665Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 1351144665Sharti break; 1352144467Sharti case IPCP_TERM_REQ: 1353144665Sharti /* Send Terminate-Ack packet. */ 1354144665Sharti if (debug) 1355144665Sharti addlog("%s%d: got ipcp term req\n", 1356144665Sharti ifp->if_name, ifp->if_unit); 1357144665Sharti sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, 0); 1358144665Sharti /* Go to closed state. */ 1359104475Sphk sp->ipcp.state = IPCP_STATE_CLOSED; 1360144665Sharti /* Initiate renegotiation. */ 1361104475Sphk sppp_ipcp_open (sp); 1362144665Sharti break; 13638874Srgrimes case IPCP_TERM_ACK: 1364137202Sharti /* Ignore for now. */ 1365144665Sharti if (debug) 1366144665Sharti addlog("%s%d: ignoring ipcp term ack\n", 1367144665Sharti ifp->if_name, ifp->if_unit); 1368144665Sharti case IPCP_CODE_REJ: 1369144665Sharti /* Ignore for now. */ 1370144665Sharti if (debug) 1371144665Sharti addlog("%s%d: ignoring ipcp code rej\n", 1372144665Sharti ifp->if_name, ifp->if_unit); 1373144665Sharti break; 1374144665Sharti } 1375144665Sharti} 13761590Srgrimes 1377144665Shartistatic void 1378137202Shartisppp_lcp_open(struct sppp *sp) 1379144665Sharti{ 1380144467Sharti char opt[6]; 1381144665Sharti 1382144665Sharti if (! sp->lcp.magic) 1383144665Sharti sp->lcp.magic = time.tv_sec + time.tv_usec; 13841590Srgrimes opt[0] = LCP_OPT_MAGIC; 13851590Srgrimes opt[1] = sizeof (opt); 1386144467Sharti opt[2] = sp->lcp.magic >> 24; 1387144467Sharti opt[3] = sp->lcp.magic >> 16; 1388144467Sharti opt[4] = sp->lcp.magic >> 8; 1389144467Sharti opt[5] = sp->lcp.magic; 1390144494Sharti sp->lcp.confid = ++sp->pp_seq; 1391144467Sharti sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, 1392144467Sharti sizeof (opt), &opt); 13931590Srgrimes TIMO (sp, 2); 13941590Srgrimes} 13951590Srgrimes 1396144467Shartistatic void 1397144467Shartisppp_ipcp_open(struct sppp *sp) 13981590Srgrimes{ 13991590Srgrimes sp->ipcp.confid = ++sp->pp_seq; 14001590Srgrimes sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, 0); 1401104696Sjmallett TIMO (sp, 2); 14021590Srgrimes} 1403144467Sharti 1404144467Sharti/* 14058874Srgrimes * Process PPP control protocol timeouts. 1406144467Sharti */ 1407144467Shartistatic void 14081590Srgrimessppp_cp_timeout(void *arg) 1409144657Sharti{ 1410144657Sharti struct sppp *sp = (struct sppp*) arg; 1411144467Sharti int s = splimp (); 1412144467Sharti 1413144467Sharti sp->pp_flags &= ~PP_TIMO; 1414144467Sharti if (! (sp->pp_if.if_flags & IFF_RUNNING) || (sp->pp_flags & PP_CISCO)) { 1415144467Sharti splx (s); 1416144467Sharti return; 1417144467Sharti } 1418144657Sharti switch (sp->lcp.state) { 1419144657Sharti case LCP_STATE_CLOSED: 1420144657Sharti /* No ACK for Configure-Request, retry. */ 1421144657Sharti sppp_lcp_open (sp); 14221590Srgrimes break; 1423144467Sharti case LCP_STATE_ACK_RCVD: 1424144467Sharti /* ACK got, but no Configure-Request for peer, retry. */ 1425144467Sharti sppp_lcp_open (sp); 1426144467Sharti sp->lcp.state = LCP_STATE_CLOSED; 1427144467Sharti break; 1428144467Sharti case LCP_STATE_ACK_SENT: 1429144467Sharti /* ACK sent but no ACK for Configure-Request, retry. */ 1430144467Sharti sppp_lcp_open (sp); 1431144467Sharti break; 1432144467Sharti case LCP_STATE_OPENED: 1433144467Sharti /* LCP is already OK, try IPCP. */ 1434144467Sharti switch (sp->ipcp.state) { 1435144467Sharti case IPCP_STATE_CLOSED: 14361590Srgrimes /* No ACK for Configure-Request, retry. */ 1437144467Sharti sppp_ipcp_open (sp); 14381590Srgrimes break; 14391590Srgrimes case IPCP_STATE_ACK_RCVD: 1440144467Sharti /* ACK got, but no Configure-Request for peer, retry. */ 1441144467Sharti sppp_ipcp_open (sp); 1442144494Sharti sp->ipcp.state = IPCP_STATE_CLOSED; 1443144494Sharti break; 14441590Srgrimes case IPCP_STATE_ACK_SENT: 14451590Srgrimes /* ACK sent but no ACK for Configure-Request, retry. */ 14461590Srgrimes sppp_ipcp_open (sp); 14471590Srgrimes break; 14481590Srgrimes case IPCP_STATE_OPENED: 1449104696Sjmallett /* IPCP is OK. */ 14501590Srgrimes break; 145118730Ssteve } 1452144467Sharti break; 1453144467Sharti } 1454144467Sharti splx (s); 1455144467Sharti} 1456144467Sharti 1457144467Shartistatic const char * 1458144467Shartisppp_lcp_type_name(u_char type) 1459144467Sharti{ 1460144467Sharti static char buf [12]; 1461144467Sharti switch (type) { 1462144467Sharti case LCP_CONF_REQ: return ("conf-req"); 14638874Srgrimes case LCP_CONF_ACK: return ("conf-ack"); 1464144467Sharti case LCP_CONF_NAK: return ("conf-nack"); 14658874Srgrimes case LCP_CONF_REJ: return ("conf-rej"); 1466144467Sharti case LCP_TERM_REQ: return ("term-req"); 1467144657Sharti case LCP_TERM_ACK: return ("term-ack"); 1468144467Sharti case LCP_CODE_REJ: return ("code-rej"); 1469144657Sharti case LCP_PROTO_REJ: return ("proto-rej"); 1470144657Sharti case LCP_ECHO_REQ: return ("echo-req"); 1471144467Sharti case LCP_ECHO_REPLY: return ("echo-reply"); 1472144467Sharti case LCP_DISC_REQ: return ("discard-req"); 1473144494Sharti } 1474144467Sharti sprintf (buf, "0x%x", type); 1475144467Sharti return (buf); 1476144467Sharti} 1477144467Sharti 1478144467Shartistatic const char * 1479144467Shartisppp_ipcp_type_name(u_char type) 1480144467Sharti{ 1481144467Sharti static char buf [12]; 1482144467Sharti switch (type) { 1483144467Sharti case IPCP_CONF_REQ: return ("conf-req"); 1484144467Sharti case IPCP_CONF_ACK: return ("conf-ack"); 1485137202Sharti case IPCP_CONF_NAK: return ("conf-nack"); 14861590Srgrimes case IPCP_CONF_REJ: return ("conf-rej"); 1487144467Sharti case IPCP_TERM_REQ: return ("term-req"); 1488144467Sharti case IPCP_TERM_ACK: return ("term-ack"); 14891590Srgrimes case IPCP_CODE_REJ: return ("code-rej"); 1490144467Sharti } 1491144657Sharti sprintf (buf, "0x%x", type); 1492144657Sharti return (buf); 1493144467Sharti} 1494144467Sharti 1495144467Shartistatic void 1496144467Shartisppp_print_bytes(u_char *p, u_short len) 1497144467Sharti{ 1498144467Sharti addlog(" %x", *p++); 1499144467Sharti while (--len > 0) 15008874Srgrimes addlog("-%x", *p++); 1501144467Sharti} 1502144467Sharti