if_spppsubr.c revision 29024
14910Swollman/* 24910Swollman * Synchronous PPP/Cisco link level subroutines. 34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes. 44910Swollman * 54910Swollman * Copyright (C) 1994 Cronyx Ltd. 625944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru> 74910Swollman * 825944Sjoerg * Heavily revamped to conform to RFC 1661. 925944Sjoerg * Copyright (C) 1997, Joerg Wunsch. 1025944Sjoerg * 114910Swollman * This software is distributed with NO WARRANTIES, not even the implied 124910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 134910Swollman * 144910Swollman * Authors grant any other persons or organisations permission to use 154910Swollman * or modify this software as long as this message is kept with the software, 164910Swollman * all derivative works or modified versions. 174910Swollman * 1825944Sjoerg * From: Version 1.9, Wed Oct 4 18:58:15 MSK 1995 1916288Sgpalmer * 2029024Sbde * $Id: if_spppsubr.c,v 1.25 1997/08/12 05:22:54 kjc Exp $ 214910Swollman */ 224910Swollman 234910Swollman#include <sys/param.h> 244952Sbde#include <sys/systm.h> 254952Sbde#include <sys/kernel.h> 2624204Sbde#include <sys/sockio.h> 274910Swollman#include <sys/socket.h> 2825706Sjoerg#include <sys/syslog.h> 2929024Sbde#include <sys/malloc.h> 304910Swollman#include <sys/mbuf.h> 314910Swollman 324910Swollman#include <net/if.h> 334910Swollman#include <net/netisr.h> 344910Swollman#include <net/if_types.h> 354910Swollman 364910Swollman#ifdef INET 374910Swollman#include <netinet/in.h> 384910Swollman#include <netinet/in_systm.h> 394910Swollman#include <netinet/in_var.h> 404910Swollman#include <netinet/ip.h> 414910Swollman#include <netinet/tcp.h> 424910Swollman#include <netinet/if_ether.h> 434910Swollman#endif 444910Swollman 4511819Sjulian#ifdef IPX 4611819Sjulian#include <netipx/ipx.h> 4711819Sjulian#include <netipx/ipx_if.h> 4811819Sjulian#endif 4911819Sjulian 504910Swollman#ifdef NS 514910Swollman#include <netns/ns.h> 524910Swollman#include <netns/ns_if.h> 534910Swollman#endif 544910Swollman 554910Swollman#ifdef ISO 564910Swollman#include <netiso/argo_debug.h> 574910Swollman#include <netiso/iso.h> 584910Swollman#include <netiso/iso_var.h> 594910Swollman#include <netiso/iso_snpac.h> 604910Swollman#endif 614910Swollman 624910Swollman#include <net/if_sppp.h> 634910Swollman 644910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 654910Swollman 6625944Sjoerg/* 6725944Sjoerg * Interface flags that can be set in an ifconfig command. 6825944Sjoerg * 6925955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 7025944Sjoerg * as being administrative openable, but won't be opened to begin 7125944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 7225944Sjoerg * -link1 will cause the administrative open of the LCP layer. 7325955Sjoerg * 7425955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 7525955Sjoerg * arrive to be sent. 7625944Sjoerg */ 7725944Sjoerg 7825955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 7925955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 8025944Sjoerg 814910Swollman#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 824910Swollman#define PPP_UI 0x03 /* Unnumbered Information */ 834910Swollman#define PPP_IP 0x0021 /* Internet Protocol */ 844910Swollman#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 854910Swollman#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 8612495Speter#define PPP_IPX 0x002b /* Novell IPX Protocol */ 874910Swollman#define PPP_LCP 0xc021 /* Link Control Protocol */ 884910Swollman#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 894910Swollman 9025944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 9125944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 9225944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 9325944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 9425944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 9525944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 9625944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 9725944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 9825944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 9925944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 10025944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1014910Swollman 1024910Swollman#define LCP_OPT_MRU 1 /* maximum receive unit */ 1034910Swollman#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 1044910Swollman#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 1054910Swollman#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 1064910Swollman#define LCP_OPT_MAGIC 5 /* magic number */ 1074910Swollman#define LCP_OPT_RESERVED 6 /* reserved */ 1084910Swollman#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 1094910Swollman#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1104910Swollman 11125944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 11225944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 11325944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1144910Swollman 1154910Swollman#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 1164910Swollman#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 1174910Swollman#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 1184910Swollman#define CISCO_ADDR_REQ 0 /* Cisco address request */ 1194910Swollman#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 1204910Swollman#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 1214910Swollman 12225944Sjoerg/* states are named and numbered according to RFC 1661 */ 12325944Sjoerg#define STATE_INITIAL 0 12425944Sjoerg#define STATE_STARTING 1 12525944Sjoerg#define STATE_CLOSED 2 12625944Sjoerg#define STATE_STOPPED 3 12725944Sjoerg#define STATE_CLOSING 4 12825944Sjoerg#define STATE_STOPPING 5 12925944Sjoerg#define STATE_REQ_SENT 6 13025944Sjoerg#define STATE_ACK_RCVD 7 13125944Sjoerg#define STATE_ACK_SENT 8 13225944Sjoerg#define STATE_OPENED 9 13325944Sjoerg 1344910Swollmanstruct ppp_header { 13511189Sjkh u_char address; 13611189Sjkh u_char control; 13711189Sjkh u_short protocol; 1384910Swollman}; 1394910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1404910Swollman 1414910Swollmanstruct lcp_header { 14211189Sjkh u_char type; 14311189Sjkh u_char ident; 14411189Sjkh u_short len; 1454910Swollman}; 1464910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1474910Swollman 1484910Swollmanstruct cisco_packet { 14911189Sjkh u_long type; 15011189Sjkh u_long par1; 15111189Sjkh u_long par2; 15211189Sjkh u_short rel; 15311189Sjkh u_short time0; 15411189Sjkh u_short time1; 1554910Swollman}; 1564910Swollman#define CISCO_PACKET_LEN 18 1574910Swollman 15825944Sjoerg/* 15925944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 16025944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 16125944Sjoerg * case you can't make sense out of these abbreviation; it will also 16225944Sjoerg * explain the semantics related to the various events and actions. 16325944Sjoerg */ 16425944Sjoergstruct cp { 16525944Sjoerg u_short proto; /* PPP control protocol number */ 16625944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 16725944Sjoerg u_char flags; 16825944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 16925944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 17025944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 17125944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 17225944Sjoerg const char *name; /* name of this control protocol */ 17325944Sjoerg /* event handlers */ 17425944Sjoerg void (*Up)(struct sppp *sp); 17525944Sjoerg void (*Down)(struct sppp *sp); 17625944Sjoerg void (*Open)(struct sppp *sp); 17725944Sjoerg void (*Close)(struct sppp *sp); 17825944Sjoerg void (*TO)(void *sp); 17925944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 18025944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 18125944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 18225944Sjoerg /* actions */ 18325944Sjoerg void (*tlu)(struct sppp *sp); 18425944Sjoerg void (*tld)(struct sppp *sp); 18525944Sjoerg void (*tls)(struct sppp *sp); 18625944Sjoerg void (*tlf)(struct sppp *sp); 18725944Sjoerg void (*scr)(struct sppp *sp); 18825944Sjoerg}; 18925944Sjoerg 19012820Sphkstatic struct sppp *spppq; 1914910Swollman 1924910Swollman/* 1934910Swollman * The following disgusting hack gets around the problem that IP TOS 1944910Swollman * can't be set yet. We want to put "interactive" traffic on a high 1954910Swollman * priority queue. To decide if traffic is interactive, we check that 1964910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 1974910Swollman */ 19811189Sjkhstatic u_short interactive_ports[8] = { 1994910Swollman 0, 513, 0, 0, 2004910Swollman 0, 21, 0, 23, 2014910Swollman}; 2024910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2034910Swollman 20425944Sjoerg/* almost every function needs these */ 20525944Sjoerg#define STDDCL \ 20625944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 20725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 20811189Sjkh 20925944Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 21025944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2114910Swollman 21225944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 21325944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 21425944Sjoerg 21525944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 21625944Sjoerg struct mbuf *m); 21725944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 21825944Sjoerg u_char ident, u_short len, void *data); 21925944Sjoergstatic void sppp_cp_timeout(void *arg); 22025944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 22125944Sjoerg int newstate); 22225944Sjoerg 22325944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 22425944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 22525944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 22625944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 22725944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 22825944Sjoerg 22925944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 23025944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 23125944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 23225944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 23325944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 23425944Sjoergstatic void sppp_lcp_TO(void *sp); 23525944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 23625944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 23725944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 23825944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 23925944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 24025944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 24125944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 24225944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 24325944Sjoergstatic void sppp_lcp_check(struct sppp *sp); 24425944Sjoerg 24525944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 24625944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 24725944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 24825944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 24925944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 25025944Sjoergstatic void sppp_ipcp_TO(void *sp); 25125944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 25225944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 25325944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 25425944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 25525944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 25625944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 25725944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 25825944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 25925944Sjoerg 26025944Sjoergstatic const char *sppp_cp_type_name(u_char type); 26125944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 26225944Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 26325944Sjoergstatic const char *sppp_state_name(int state); 26425944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 26525944Sjoergstatic const char *sppp_proto_name(u_short proto); 26625944Sjoerg 26725944Sjoergstatic void sppp_keepalive(void *dummy); 26825944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 26925944Sjoerg 27025944Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst); 27125944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 27225944Sjoerg 27325944Sjoergstatic void sppp_print_bytes(u_char *p, u_short len); 27425944Sjoerg 27525944Sjoerg/* our control protocol descriptors */ 27625944Sjoergconst struct cp lcp = { 27725944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 27825944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 27925944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 28025944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 28125944Sjoerg sppp_lcp_scr 28225944Sjoerg}; 28325944Sjoerg 28425944Sjoergconst struct cp ipcp = { 28525944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 28625944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 28725944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 28825944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 28925944Sjoerg sppp_ipcp_scr 29025944Sjoerg}; 29125944Sjoerg 29225944Sjoergconst struct cp *cps[IDX_COUNT] = { 29325944Sjoerg &lcp, /* IDX_LCP */ 29425944Sjoerg &ipcp, /* IDX_IPCP */ 29525944Sjoerg}; 29625944Sjoerg 29725944Sjoerg 29825944Sjoerg/* 29925944Sjoerg * Exported functions, comprising our interface to the lower layer. 3004910Swollman */ 3014910Swollman 3024910Swollman/* 3034910Swollman * Process the received packet. 3044910Swollman */ 30525706Sjoergvoid 30625706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 3074910Swollman{ 3084910Swollman struct ppp_header *h; 3094910Swollman struct ifqueue *inq = 0; 31011189Sjkh int s; 31125944Sjoerg struct sppp *sp = (struct sppp *)ifp; 31225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 3134910Swollman 3144910Swollman if (ifp->if_flags & IFF_UP) 3154910Swollman /* Count received bytes, add FCS and one flag */ 3164910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 3174910Swollman 3184910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 3194910Swollman /* Too small packet, drop it. */ 32025944Sjoerg if (debug) 32125706Sjoerg log(LOG_DEBUG, 32225706Sjoerg "%s%d: input packet is too small, %d bytes\n", 32325706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 32425944Sjoerg drop: 32525944Sjoerg ++ifp->if_ierrors; 32625944Sjoerg ++ifp->if_iqdrops; 3274910Swollman m_freem (m); 3284910Swollman return; 3294910Swollman } 3304910Swollman 3314910Swollman /* Get PPP header. */ 3324910Swollman h = mtod (m, struct ppp_header*); 3334910Swollman m_adj (m, PPP_HEADER_LEN); 3344910Swollman 3354910Swollman switch (h->address) { 3364910Swollman case PPP_ALLSTATIONS: 3374910Swollman if (h->control != PPP_UI) 3384910Swollman goto invalid; 33911189Sjkh if (sp->pp_flags & PP_CISCO) { 34025944Sjoerg if (debug) 34125706Sjoerg log(LOG_DEBUG, 34225706Sjoerg "%s%d: PPP packet in Cisco mode " 34325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 34425706Sjoerg ifp->if_name, ifp->if_unit, 34525706Sjoerg h->address, h->control, ntohs(h->protocol)); 34611189Sjkh goto drop; 34711189Sjkh } 3484910Swollman switch (ntohs (h->protocol)) { 3494910Swollman default: 35025944Sjoerg if (sp->state[IDX_LCP] == STATE_OPENED) 35125944Sjoerg sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 35211189Sjkh ++sp->pp_seq, m->m_pkthdr.len + 2, 3534910Swollman &h->protocol); 35425944Sjoerg if (debug) 35525706Sjoerg log(LOG_DEBUG, 35625706Sjoerg "%s%d: invalid input protocol " 35725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 35825706Sjoerg ifp->if_name, ifp->if_unit, 35925706Sjoerg h->address, h->control, ntohs(h->protocol)); 3604910Swollman ++ifp->if_noproto; 3614910Swollman goto drop; 3624910Swollman case PPP_LCP: 36325944Sjoerg sppp_cp_input(&lcp, (struct sppp*)ifp, m); 3644910Swollman m_freem (m); 3654910Swollman return; 3664910Swollman#ifdef INET 3674910Swollman case PPP_IPCP: 36825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 36925944Sjoerg sppp_cp_input(&ipcp, (struct sppp*) ifp, m); 3704910Swollman m_freem (m); 3714910Swollman return; 3724910Swollman case PPP_IP: 37325944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 3744910Swollman schednetisr (NETISR_IP); 3754910Swollman inq = &ipintrq; 3764910Swollman } 3774910Swollman break; 3784910Swollman#endif 37912495Speter#ifdef IPX 38012495Speter case PPP_IPX: 38112495Speter /* IPX IPXCP not implemented yet */ 38225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 38312495Speter schednetisr (NETISR_IPX); 38412495Speter inq = &ipxintrq; 38512495Speter } 38612495Speter break; 38712495Speter#endif 3884910Swollman#ifdef NS 3894910Swollman case PPP_XNS: 3904910Swollman /* XNS IDPCP not implemented yet */ 39125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 3924910Swollman schednetisr (NETISR_NS); 3934910Swollman inq = &nsintrq; 3944910Swollman } 3954910Swollman break; 3964910Swollman#endif 3974910Swollman#ifdef ISO 3984910Swollman case PPP_ISO: 3994910Swollman /* OSI NLCP not implemented yet */ 40025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 4014910Swollman schednetisr (NETISR_ISO); 4024910Swollman inq = &clnlintrq; 4034910Swollman } 4044910Swollman break; 4054910Swollman#endif 4064910Swollman } 4074910Swollman break; 4084910Swollman case CISCO_MULTICAST: 4094910Swollman case CISCO_UNICAST: 4104910Swollman /* Don't check the control field here (RFC 1547). */ 41111189Sjkh if (! (sp->pp_flags & PP_CISCO)) { 41225944Sjoerg if (debug) 41325706Sjoerg log(LOG_DEBUG, 41425706Sjoerg "%s%d: Cisco packet in PPP mode " 41525706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 41625706Sjoerg ifp->if_name, ifp->if_unit, 41725706Sjoerg h->address, h->control, ntohs(h->protocol)); 41811189Sjkh goto drop; 41911189Sjkh } 4204910Swollman switch (ntohs (h->protocol)) { 4214910Swollman default: 4224910Swollman ++ifp->if_noproto; 4234910Swollman goto invalid; 4244910Swollman case CISCO_KEEPALIVE: 4254910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 4264910Swollman m_freem (m); 4274910Swollman return; 4284910Swollman#ifdef INET 4294910Swollman case ETHERTYPE_IP: 4304910Swollman schednetisr (NETISR_IP); 4314910Swollman inq = &ipintrq; 4324910Swollman break; 4334910Swollman#endif 43412495Speter#ifdef IPX 43512495Speter case ETHERTYPE_IPX: 43612495Speter schednetisr (NETISR_IPX); 43712495Speter inq = &ipxintrq; 43812495Speter break; 43912495Speter#endif 4404910Swollman#ifdef NS 4414910Swollman case ETHERTYPE_NS: 4424910Swollman schednetisr (NETISR_NS); 4434910Swollman inq = &nsintrq; 4444910Swollman break; 4454910Swollman#endif 4464910Swollman } 4474910Swollman break; 44825944Sjoerg default: /* Invalid PPP packet. */ 44925944Sjoerg invalid: 45025944Sjoerg if (debug) 45125944Sjoerg log(LOG_DEBUG, 45225944Sjoerg "%s%d: invalid input packet " 45325944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 45425944Sjoerg ifp->if_name, ifp->if_unit, 45525944Sjoerg h->address, h->control, ntohs(h->protocol)); 45625944Sjoerg goto drop; 4574910Swollman } 4584910Swollman 4594910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 4604910Swollman goto drop; 4614910Swollman 4624910Swollman /* Check queue. */ 46325944Sjoerg s = splimp(); 4644910Swollman if (IF_QFULL (inq)) { 4654910Swollman /* Queue overflow. */ 46625944Sjoerg IF_DROP(inq); 46725944Sjoerg splx(s); 46825944Sjoerg if (debug) 46925706Sjoerg log(LOG_DEBUG, "%s%d: protocol queue overflow\n", 4704910Swollman ifp->if_name, ifp->if_unit); 4714910Swollman goto drop; 4724910Swollman } 47325944Sjoerg IF_ENQUEUE(inq, m); 47425944Sjoerg splx(s); 4754910Swollman} 4764910Swollman 4774910Swollman/* 4784910Swollman * Enqueue transmit packet. 4794910Swollman */ 48012820Sphkstatic int 48125706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 48225706Sjoerg struct sockaddr *dst, struct rtentry *rt) 4834910Swollman{ 4844910Swollman struct sppp *sp = (struct sppp*) ifp; 4854910Swollman struct ppp_header *h; 4864910Swollman struct ifqueue *ifq; 48725955Sjoerg int s, rv = 0; 4884910Swollman 48925944Sjoerg s = splimp(); 49025944Sjoerg 49125944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 49225944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 4934910Swollman m_freem (m); 4944910Swollman splx (s); 4954910Swollman return (ENETDOWN); 4964910Swollman } 4974910Swollman 49825944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 49925944Sjoerg /* 50025944Sjoerg * Interface is not yet running, but auto-dial. Need 50125944Sjoerg * to start LCP for it. 50225944Sjoerg */ 50325944Sjoerg ifp->if_flags |= IFF_RUNNING; 50425944Sjoerg splx(s); 50525944Sjoerg lcp.Open(sp); 50625944Sjoerg s = splimp(); 50725944Sjoerg } 50825944Sjoerg 5094910Swollman ifq = &ifp->if_snd; 5104910Swollman#ifdef INET 5114910Swollman /* 5124910Swollman * Put low delay, telnet, rlogin and ftp control packets 5134910Swollman * in front of the queue. 5144910Swollman */ 51512436Speter if (dst->sa_family == AF_INET) { 51612436Speter struct ip *ip = mtod (m, struct ip*); 51712436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 5184910Swollman 51912436Speter if (! IF_QFULL (&sp->pp_fastq) && 52012436Speter ((ip->ip_tos & IPTOS_LOWDELAY) || 52112436Speter ip->ip_p == IPPROTO_TCP && 52212436Speter m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) && 52312436Speter (INTERACTIVE (ntohs (tcp->th_sport)) || 52412436Speter INTERACTIVE (ntohs (tcp->th_dport))))) 52512436Speter ifq = &sp->pp_fastq; 5264910Swollman } 5274910Swollman#endif 5284910Swollman 5294910Swollman /* 5304910Swollman * Prepend general data packet PPP header. For now, IP only. 5314910Swollman */ 5324910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 5334910Swollman if (! m) { 5344910Swollman if (ifp->if_flags & IFF_DEBUG) 53525706Sjoerg log(LOG_DEBUG, "%s%d: no memory for transmit header\n", 5364910Swollman ifp->if_name, ifp->if_unit); 53725944Sjoerg ++ifp->if_oerrors; 5384910Swollman splx (s); 5394910Swollman return (ENOBUFS); 5404910Swollman } 5414910Swollman h = mtod (m, struct ppp_header*); 5424910Swollman if (sp->pp_flags & PP_CISCO) { 54328088Skjc h->address = CISCO_UNICAST; /* unicast address */ 5444910Swollman h->control = 0; 5454910Swollman } else { 5464910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 5474910Swollman h->control = PPP_UI; /* Unnumbered Info */ 5484910Swollman } 5494910Swollman 5504910Swollman switch (dst->sa_family) { 5514910Swollman#ifdef INET 5524910Swollman case AF_INET: /* Internet Protocol */ 55311189Sjkh if (sp->pp_flags & PP_CISCO) 55411189Sjkh h->protocol = htons (ETHERTYPE_IP); 55511189Sjkh else { 55625955Sjoerg /* 55725955Sjoerg * Don't choke with an ENETDOWN early. It's 55825955Sjoerg * possible that we just started dialing out, 55925955Sjoerg * so don't drop the packet immediately. If 56025955Sjoerg * we notice that we run out of buffer space 56125955Sjoerg * below, we will however remember that we are 56225955Sjoerg * not ready to carry IP packets, and return 56325955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 56425955Sjoerg */ 56525955Sjoerg h->protocol = htons(PPP_IP); 56625955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 56725955Sjoerg rv = ENETDOWN; 56811189Sjkh } 5694910Swollman break; 5704910Swollman#endif 5714910Swollman#ifdef NS 5724910Swollman case AF_NS: /* Xerox NS Protocol */ 5734910Swollman h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 5744910Swollman ETHERTYPE_NS : PPP_XNS); 5754910Swollman break; 5764910Swollman#endif 57711819Sjulian#ifdef IPX 57812495Speter case AF_IPX: /* Novell IPX Protocol */ 57911819Sjulian h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 58012495Speter ETHERTYPE_IPX : PPP_IPX); 58111819Sjulian break; 58211819Sjulian#endif 5834910Swollman#ifdef ISO 5844910Swollman case AF_ISO: /* ISO OSI Protocol */ 5854910Swollman if (sp->pp_flags & PP_CISCO) 5864910Swollman goto nosupport; 5874910Swollman h->protocol = htons (PPP_ISO); 5884910Swollman break; 58912820Sphknosupport: 5904910Swollman#endif 5914910Swollman default: 5924910Swollman m_freem (m); 59325944Sjoerg ++ifp->if_oerrors; 5944910Swollman splx (s); 5954910Swollman return (EAFNOSUPPORT); 5964910Swollman } 5974910Swollman 5984910Swollman /* 5994910Swollman * Queue message on interface, and start output if interface 6004910Swollman * not yet active. 6014910Swollman */ 6024910Swollman if (IF_QFULL (ifq)) { 6034910Swollman IF_DROP (&ifp->if_snd); 6044910Swollman m_freem (m); 60525944Sjoerg ++ifp->if_oerrors; 6064910Swollman splx (s); 60725955Sjoerg return (rv? rv: ENOBUFS); 6084910Swollman } 6094910Swollman IF_ENQUEUE (ifq, m); 6104910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 6114910Swollman (*ifp->if_start) (ifp); 6124910Swollman 6134910Swollman /* 6144910Swollman * Count output packets and bytes. 6154910Swollman * The packet length includes header, FCS and 1 flag, 6164910Swollman * according to RFC 1333. 6174910Swollman */ 6184910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 6194910Swollman splx (s); 6204910Swollman return (0); 6214910Swollman} 6224910Swollman 62325706Sjoergvoid 62425706Sjoergsppp_attach(struct ifnet *ifp) 6254910Swollman{ 6264910Swollman struct sppp *sp = (struct sppp*) ifp; 6274910Swollman 6284910Swollman /* Initialize keepalive handler. */ 6294910Swollman if (! spppq) 63011189Sjkh timeout (sppp_keepalive, 0, hz * 10); 6314910Swollman 6324910Swollman /* Insert new entry into the keepalive list. */ 6334910Swollman sp->pp_next = spppq; 6344910Swollman spppq = sp; 6354910Swollman 6364910Swollman sp->pp_if.if_type = IFT_PPP; 6374910Swollman sp->pp_if.if_output = sppp_output; 6384910Swollman sp->pp_fastq.ifq_maxlen = 32; 63926018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 6404910Swollman sp->pp_loopcnt = 0; 6414910Swollman sp->pp_alivecnt = 0; 64211189Sjkh sp->pp_seq = 0; 6434910Swollman sp->pp_rseq = 0; 64425944Sjoerg sp->pp_phase = PHASE_DEAD; 64525944Sjoerg sp->pp_up = lcp.Up; 64625944Sjoerg sp->pp_down = lcp.Down; 64725944Sjoerg 64825944Sjoerg sppp_lcp_init(sp); 64925944Sjoerg sppp_ipcp_init(sp); 6504910Swollman} 6514910Swollman 65212820Sphkvoid 65325706Sjoergsppp_detach(struct ifnet *ifp) 6544910Swollman{ 6554910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 65625944Sjoerg int i; 6574910Swollman 6584910Swollman /* Remove the entry from the keepalive list. */ 6594910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 6604910Swollman if (p == sp) { 6614910Swollman *q = p->pp_next; 6624910Swollman break; 6634910Swollman } 6644910Swollman 6654910Swollman /* Stop keepalive handler. */ 6664910Swollman if (! spppq) 66711189Sjkh untimeout (sppp_keepalive, 0); 66825944Sjoerg 66925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 67025944Sjoerg untimeout((cps[i])->TO, (void *)sp); 6714910Swollman} 6724910Swollman 6734910Swollman/* 6744910Swollman * Flush the interface output queue. 6754910Swollman */ 67625706Sjoergvoid 67725706Sjoergsppp_flush(struct ifnet *ifp) 6784910Swollman{ 6794910Swollman struct sppp *sp = (struct sppp*) ifp; 6804910Swollman 68125944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 68225944Sjoerg sppp_qflush (&sp->pp_fastq); 68326018Sjoerg sppp_qflush (&sp->pp_cpq); 6844910Swollman} 6854910Swollman 6864910Swollman/* 68711189Sjkh * Check if the output queue is empty. 68811189Sjkh */ 68912820Sphkint 69025706Sjoergsppp_isempty(struct ifnet *ifp) 69111189Sjkh{ 69211189Sjkh struct sppp *sp = (struct sppp*) ifp; 69325944Sjoerg int empty, s; 69411189Sjkh 69525944Sjoerg s = splimp(); 69626018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 69726018Sjoerg !sp->pp_if.if_snd.ifq_head; 69825944Sjoerg splx(s); 69911189Sjkh return (empty); 70011189Sjkh} 70111189Sjkh 70211189Sjkh/* 7034910Swollman * Get next packet to send. 7044910Swollman */ 70525706Sjoergstruct mbuf * 70625706Sjoergsppp_dequeue(struct ifnet *ifp) 7074910Swollman{ 7084910Swollman struct sppp *sp = (struct sppp*) ifp; 7094910Swollman struct mbuf *m; 71025944Sjoerg int s; 7114910Swollman 71225944Sjoerg s = splimp(); 71326018Sjoerg /* 71426018Sjoerg * Process only the control protocol queue until we are in 71526018Sjoerg * network phase. 71626018Sjoerg * 71726018Sjoerg * XXX Network phase itself is still not a sufficient test, we 71826018Sjoerg * normally should keep a separate queue for each supported 71926018Sjoerg * protocol family, and only serve these queues as the 72026018Sjoerg * respective NCPs were opened. The simplistic logic used 72126018Sjoerg * here might cause some loss of network traffic while the 72226018Sjoerg * NCPs are being negotiated, in particular if the NCPs take a 72326018Sjoerg * long time to negotiate. 72426018Sjoerg * 72526018Sjoerg * Do always serve all three queues in Cisco mode. 72626018Sjoerg */ 72726018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 72826018Sjoerg if (m == NULL && 72926018Sjoerg (sp->pp_phase == PHASE_NETWORK || 73026018Sjoerg (sp->pp_flags & PP_CISCO) != 0)) { 73126018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 73226018Sjoerg if (m == NULL) 73326018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 73426018Sjoerg } 73526018Sjoerg splx(s); 73626018Sjoerg return m; 7374910Swollman} 7384910Swollman 7394910Swollman/* 74025944Sjoerg * Process an ioctl request. Called on low priority level. 7414910Swollman */ 74225944Sjoergint 74325944Sjoergsppp_ioctl(struct ifnet *ifp, int cmd, void *data) 7444910Swollman{ 74525944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 74625944Sjoerg struct sppp *sp = (struct sppp*) ifp; 74725944Sjoerg int s, going_up, going_down, newmode; 7484910Swollman 74925944Sjoerg s = splimp(); 75025944Sjoerg switch (cmd) { 75125944Sjoerg case SIOCAIFADDR: 75225944Sjoerg case SIOCSIFDSTADDR: 75325944Sjoerg break; 7544910Swollman 75525944Sjoerg case SIOCSIFADDR: 75625944Sjoerg if_up(ifp); 75725944Sjoerg /* fall through... */ 75811189Sjkh 75925944Sjoerg case SIOCSIFFLAGS: 76025944Sjoerg going_up = ifp->if_flags & IFF_UP && 76125944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 76225944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 76325944Sjoerg ifp->if_flags & IFF_RUNNING; 76425944Sjoerg newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); 76525944Sjoerg if (newmode == (IFF_AUTO | IFF_PASSIVE)) { 76625944Sjoerg /* sanity */ 76725944Sjoerg newmode = IFF_PASSIVE; 76825944Sjoerg ifp->if_flags &= ~IFF_AUTO; 7694910Swollman } 7704910Swollman 77125944Sjoerg if (going_up || going_down) 77225944Sjoerg lcp.Close(sp); 77325944Sjoerg if (going_up && newmode == 0) { 77425944Sjoerg /* neither auto-dial nor passive */ 77525944Sjoerg ifp->if_flags |= IFF_RUNNING; 77625944Sjoerg if (!(sp->pp_flags & PP_CISCO)) 77725944Sjoerg lcp.Open(sp); 77826018Sjoerg } else if (going_down) { 77926018Sjoerg sppp_flush(ifp); 78025944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 78126018Sjoerg } 7824910Swollman 7834910Swollman break; 78411189Sjkh 78525944Sjoerg#ifdef SIOCSIFMTU 78625944Sjoerg#ifndef ifr_mtu 78725944Sjoerg#define ifr_mtu ifr_metric 78825944Sjoerg#endif 78925944Sjoerg case SIOCSIFMTU: 79025944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 79125944Sjoerg return (EINVAL); 79225944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 7934910Swollman break; 79425944Sjoerg#endif 79525944Sjoerg#ifdef SLIOCSETMTU 79625944Sjoerg case SLIOCSETMTU: 79725944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 79825944Sjoerg return (EINVAL); 79925944Sjoerg ifp->if_mtu = *(short*)data; 8004910Swollman break; 80125944Sjoerg#endif 80225944Sjoerg#ifdef SIOCGIFMTU 80325944Sjoerg case SIOCGIFMTU: 80425944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 80511189Sjkh break; 80625944Sjoerg#endif 80725944Sjoerg#ifdef SLIOCGETMTU 80825944Sjoerg case SLIOCGETMTU: 80925944Sjoerg *(short*)data = ifp->if_mtu; 8104910Swollman break; 81125944Sjoerg#endif 81225944Sjoerg case SIOCADDMULTI: 81325944Sjoerg case SIOCDELMULTI: 8144910Swollman break; 81511189Sjkh 81625944Sjoerg default: 81725944Sjoerg splx(s); 81825944Sjoerg return (ENOTTY); 8194910Swollman } 82025944Sjoerg splx(s); 82125944Sjoerg return (0); 8224910Swollman} 8234910Swollman 82425944Sjoerg 82525944Sjoerg/* 82625944Sjoerg * Cisco framing implementation. 82725944Sjoerg */ 82825944Sjoerg 8294910Swollman/* 8304910Swollman * Handle incoming Cisco keepalive protocol packets. 8314910Swollman */ 83212820Sphkstatic void 83325706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 8344910Swollman{ 83525944Sjoerg STDDCL; 8364910Swollman struct cisco_packet *h; 8374910Swollman struct ifaddr *ifa; 8384910Swollman 83927929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 84025706Sjoerg if (debug) 84125706Sjoerg log(LOG_DEBUG, 84225706Sjoerg "%s%d: invalid cisco packet length: %d bytes\n", 84325706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 8444910Swollman return; 8454910Swollman } 8464910Swollman h = mtod (m, struct cisco_packet*); 84725706Sjoerg if (debug) 84825706Sjoerg log(LOG_DEBUG, 84925706Sjoerg "%s%d: cisco input: %d bytes " 85025706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 85125706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len, 85225706Sjoerg ntohl (h->type), h->par1, h->par2, h->rel, 85325706Sjoerg h->time0, h->time1); 8544910Swollman switch (ntohl (h->type)) { 8554910Swollman default: 85625706Sjoerg if (debug) 85725706Sjoerg addlog("%s%d: unknown cisco packet type: 0x%lx\n", 85825706Sjoerg ifp->if_name, ifp->if_unit, ntohl (h->type)); 8594910Swollman break; 8604910Swollman case CISCO_ADDR_REPLY: 8614910Swollman /* Reply on address request, ignore */ 8624910Swollman break; 8634910Swollman case CISCO_KEEPALIVE_REQ: 8644910Swollman sp->pp_alivecnt = 0; 8654910Swollman sp->pp_rseq = ntohl (h->par1); 8664910Swollman if (sp->pp_seq == sp->pp_rseq) { 8674910Swollman /* Local and remote sequence numbers are equal. 8684910Swollman * Probably, the line is in loopback mode. */ 86911189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 87011189Sjkh printf ("%s%d: loopback\n", 87111189Sjkh ifp->if_name, ifp->if_unit); 87211189Sjkh sp->pp_loopcnt = 0; 87311189Sjkh if (ifp->if_flags & IFF_UP) { 87411189Sjkh if_down (ifp); 87526018Sjoerg sppp_qflush (&sp->pp_cpq); 87611189Sjkh } 87711189Sjkh } 8784910Swollman ++sp->pp_loopcnt; 8794910Swollman 8804910Swollman /* Generate new local sequence number */ 8814910Swollman sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 88211189Sjkh break; 88311189Sjkh } 8844910Swollman sp->pp_loopcnt = 0; 88511189Sjkh if (! (ifp->if_flags & IFF_UP) && 88611189Sjkh (ifp->if_flags & IFF_RUNNING)) { 88711189Sjkh ifp->if_flags |= IFF_UP; 88811189Sjkh printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 88911189Sjkh } 8904910Swollman break; 8914910Swollman case CISCO_ADDR_REQ: 89220407Swollman for (ifa=ifp->if_addrhead.tqh_first; ifa; 89320407Swollman ifa=ifa->ifa_link.tqe_next) 8944910Swollman if (ifa->ifa_addr->sa_family == AF_INET) 8954910Swollman break; 8964910Swollman if (! ifa) { 89725706Sjoerg if (debug) 89825706Sjoerg addlog("%s%d: unknown address for cisco request\n", 89925706Sjoerg ifp->if_name, ifp->if_unit); 9004910Swollman return; 9014910Swollman } 9024910Swollman sppp_cisco_send (sp, CISCO_ADDR_REPLY, 9034910Swollman ntohl (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr), 9044910Swollman ntohl (((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr)); 9054910Swollman break; 9064910Swollman } 9074910Swollman} 9084910Swollman 9094910Swollman/* 91025944Sjoerg * Send Cisco keepalive packet. 9114910Swollman */ 91212820Sphkstatic void 91325944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 91425944Sjoerg{ 91525944Sjoerg STDDCL; 91625944Sjoerg struct ppp_header *h; 91725944Sjoerg struct cisco_packet *ch; 91825944Sjoerg struct mbuf *m; 91925944Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 92025944Sjoerg 92125944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 92225944Sjoerg if (! m) 92325944Sjoerg return; 92425944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 92525944Sjoerg m->m_pkthdr.rcvif = 0; 92625944Sjoerg 92725944Sjoerg h = mtod (m, struct ppp_header*); 92825944Sjoerg h->address = CISCO_MULTICAST; 92925944Sjoerg h->control = 0; 93025944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 93125944Sjoerg 93225944Sjoerg ch = (struct cisco_packet*) (h + 1); 93325944Sjoerg ch->type = htonl (type); 93425944Sjoerg ch->par1 = htonl (par1); 93525944Sjoerg ch->par2 = htonl (par2); 93625944Sjoerg ch->rel = -1; 93725944Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 93825944Sjoerg ch->time1 = htons ((u_short) t); 93925944Sjoerg 94025944Sjoerg if (debug) 94125944Sjoerg log(LOG_DEBUG, 94225944Sjoerg "%s%d: cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 94325944Sjoerg ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1, 94425944Sjoerg ch->par2, ch->rel, ch->time0, ch->time1); 94525944Sjoerg 94626018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 94726018Sjoerg IF_DROP (&sp->pp_fastq); 94825944Sjoerg IF_DROP (&ifp->if_snd); 94925944Sjoerg m_freem (m); 95025944Sjoerg } else 95126018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 95225944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 95325944Sjoerg (*ifp->if_start) (ifp); 95425944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 95525944Sjoerg} 95625944Sjoerg 95725944Sjoerg/* 95825944Sjoerg * PPP protocol implementation. 95925944Sjoerg */ 96025944Sjoerg 96125944Sjoerg/* 96225944Sjoerg * Send PPP control protocol packet. 96325944Sjoerg */ 96425944Sjoergstatic void 96525706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 96625706Sjoerg u_char ident, u_short len, void *data) 9674910Swollman{ 96825944Sjoerg STDDCL; 9694910Swollman struct ppp_header *h; 9704910Swollman struct lcp_header *lh; 9714910Swollman struct mbuf *m; 9724910Swollman 9734910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 9744910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 9754910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 9764910Swollman if (! m) 9774910Swollman return; 9784910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 9794910Swollman m->m_pkthdr.rcvif = 0; 9804910Swollman 9814910Swollman h = mtod (m, struct ppp_header*); 9824910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9834910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9844910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 9854910Swollman 9864910Swollman lh = (struct lcp_header*) (h + 1); 9874910Swollman lh->type = type; 9884910Swollman lh->ident = ident; 9894910Swollman lh->len = htons (LCP_HEADER_LEN + len); 9904910Swollman if (len) 9914910Swollman bcopy (data, lh+1, len); 9924910Swollman 99325706Sjoerg if (debug) { 99425944Sjoerg log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d", 99525944Sjoerg ifp->if_name, ifp->if_unit, 99625944Sjoerg sppp_proto_name(proto), 99725944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 99825944Sjoerg ntohs (lh->len)); 9994910Swollman if (len) 100011189Sjkh sppp_print_bytes ((u_char*) (lh+1), len); 100125706Sjoerg addlog(">\n"); 10024910Swollman } 100326018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 100426018Sjoerg IF_DROP (&sp->pp_fastq); 10054910Swollman IF_DROP (&ifp->if_snd); 10064910Swollman m_freem (m); 100725944Sjoerg ++ifp->if_oerrors; 10084910Swollman } else 100926018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 10104910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 10114910Swollman (*ifp->if_start) (ifp); 10124910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 10134910Swollman} 10144910Swollman 10154910Swollman/* 101625944Sjoerg * Handle incoming PPP control protocol packets. 10174910Swollman */ 101812820Sphkstatic void 101925944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 10204910Swollman{ 102125944Sjoerg STDDCL; 102225944Sjoerg struct lcp_header *h; 102325944Sjoerg int len = m->m_pkthdr.len; 102425944Sjoerg int rv; 102525944Sjoerg u_char *p; 10264910Swollman 102725944Sjoerg if (len < 4) { 102825944Sjoerg if (debug) 102925944Sjoerg log(LOG_DEBUG, 103025944Sjoerg "%s%d: %s invalid packet length: %d bytes\n", 103125944Sjoerg ifp->if_name, ifp->if_unit, cp->name, len); 10324910Swollman return; 103325944Sjoerg } 103425944Sjoerg h = mtod (m, struct lcp_header*); 103525944Sjoerg if (debug) { 103625944Sjoerg log(LOG_DEBUG, 103725944Sjoerg "%s%d: %s input(%s): <%s id=0x%x len=%d", 103825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 103925944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 104025944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 104125944Sjoerg if (len > 4) 104225944Sjoerg sppp_print_bytes ((u_char*) (h+1), len-4); 104325944Sjoerg addlog(">\n"); 104425944Sjoerg } 104525944Sjoerg if (len > ntohs (h->len)) 104625944Sjoerg len = ntohs (h->len); 104725944Sjoerg switch (h->type) { 104825944Sjoerg case CONF_REQ: 104925944Sjoerg if (len < 4) { 105025944Sjoerg if (debug) 105125944Sjoerg addlog("%s%d: %s invalid conf-req length %d\n", 105225944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 105325944Sjoerg len); 105425944Sjoerg ++ifp->if_ierrors; 105525944Sjoerg break; 105625944Sjoerg } 105725944Sjoerg rv = (cp->RCR)(sp, h, len); 105825944Sjoerg switch (sp->state[cp->protoidx]) { 105925944Sjoerg case STATE_OPENED: 106025944Sjoerg (cp->tld)(sp); 106125944Sjoerg (cp->scr)(sp); 106225944Sjoerg /* fall through... */ 106325944Sjoerg case STATE_ACK_SENT: 106425944Sjoerg case STATE_REQ_SENT: 106525944Sjoerg sppp_cp_change_state(cp, sp, rv? 106625944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 106725944Sjoerg break; 106825944Sjoerg case STATE_CLOSING: 106925944Sjoerg case STATE_STOPPING: 107025944Sjoerg break; 107125944Sjoerg case STATE_STOPPED: 107225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 107325944Sjoerg (cp->scr)(sp); 107425944Sjoerg sppp_cp_change_state(cp, sp, rv? 107525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 107625944Sjoerg break; 107725944Sjoerg case STATE_CLOSED: 107825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 107925944Sjoerg 0, 0); 108025944Sjoerg break; 108125944Sjoerg case STATE_ACK_RCVD: 108225944Sjoerg if (rv) { 108325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 108425944Sjoerg if (debug) 108526077Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 108626077Sjoerg ifp->if_name, ifp->if_unit, 108726077Sjoerg cp->name); 108825944Sjoerg (cp->tlu)(sp); 108925944Sjoerg } else 109025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 109125944Sjoerg break; 109225944Sjoerg default: 109325944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 109425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 109525944Sjoerg sppp_cp_type_name(h->type), 109625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 109725944Sjoerg ++ifp->if_ierrors; 109825944Sjoerg } 109925944Sjoerg break; 110025944Sjoerg case CONF_ACK: 110125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 110225944Sjoerg if (debug) 110325944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 110425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 110525944Sjoerg h->ident, sp->confid[cp->protoidx]); 110625944Sjoerg ++ifp->if_ierrors; 110725944Sjoerg break; 110825944Sjoerg } 110925944Sjoerg switch (sp->state[cp->protoidx]) { 111025944Sjoerg case STATE_CLOSED: 111125944Sjoerg case STATE_STOPPED: 111225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 111325944Sjoerg break; 111425944Sjoerg case STATE_CLOSING: 111525944Sjoerg case STATE_STOPPING: 111625944Sjoerg break; 111725944Sjoerg case STATE_REQ_SENT: 111825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 111925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 112025944Sjoerg break; 112125944Sjoerg case STATE_OPENED: 112225944Sjoerg (cp->tld)(sp); 112325944Sjoerg /* fall through */ 112425944Sjoerg case STATE_ACK_RCVD: 112525944Sjoerg (cp->scr)(sp); 112625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 112725944Sjoerg break; 112825944Sjoerg case STATE_ACK_SENT: 112925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 113025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 113125944Sjoerg if (debug) 113225944Sjoerg addlog("%s%d: %s tlu\n", 113325944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 113425944Sjoerg (cp->tlu)(sp); 113525944Sjoerg break; 113625944Sjoerg default: 113725944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 113825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 113925944Sjoerg sppp_cp_type_name(h->type), 114025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 114125944Sjoerg ++ifp->if_ierrors; 114225944Sjoerg } 114325944Sjoerg break; 114425944Sjoerg case CONF_NAK: 114525944Sjoerg case CONF_REJ: 114625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 114725944Sjoerg if (debug) 114825944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 114925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 115025944Sjoerg h->ident, sp->confid[cp->protoidx]); 115125944Sjoerg ++ifp->if_ierrors; 115225944Sjoerg break; 115325944Sjoerg } 115425944Sjoerg if (h->type == CONF_NAK) 115525944Sjoerg (cp->RCN_nak)(sp, h, len); 115625944Sjoerg else /* CONF_REJ */ 115725944Sjoerg (cp->RCN_rej)(sp, h, len); 11584910Swollman 115925944Sjoerg switch (sp->state[cp->protoidx]) { 116025944Sjoerg case STATE_CLOSED: 116125944Sjoerg case STATE_STOPPED: 116225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 116325944Sjoerg break; 116425944Sjoerg case STATE_REQ_SENT: 116525944Sjoerg case STATE_ACK_SENT: 116625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 116725944Sjoerg (cp->scr)(sp); 116825944Sjoerg break; 116925944Sjoerg case STATE_OPENED: 117025944Sjoerg (cp->tld)(sp); 117125944Sjoerg /* fall through */ 117225944Sjoerg case STATE_ACK_RCVD: 117325944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_SENT); 117425944Sjoerg (cp->scr)(sp); 117525944Sjoerg break; 117625944Sjoerg case STATE_CLOSING: 117725944Sjoerg case STATE_STOPPING: 117825944Sjoerg break; 117925944Sjoerg default: 118025944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 118125944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 118225944Sjoerg sppp_cp_type_name(h->type), 118325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 118425944Sjoerg ++ifp->if_ierrors; 118525944Sjoerg } 118625944Sjoerg break; 11874910Swollman 118825944Sjoerg case TERM_REQ: 118925944Sjoerg switch (sp->state[cp->protoidx]) { 119025944Sjoerg case STATE_ACK_RCVD: 119125944Sjoerg case STATE_ACK_SENT: 119225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 119325944Sjoerg /* fall through */ 119425944Sjoerg case STATE_CLOSED: 119525944Sjoerg case STATE_STOPPED: 119625944Sjoerg case STATE_CLOSING: 119725944Sjoerg case STATE_STOPPING: 119825944Sjoerg case STATE_REQ_SENT: 119925944Sjoerg sta: 120025944Sjoerg /* Send Terminate-Ack packet. */ 120125944Sjoerg if (debug) 120225944Sjoerg log(LOG_DEBUG, "%s%d: %s send terminate-ack\n", 120325944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 120425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 120525944Sjoerg break; 120625944Sjoerg case STATE_OPENED: 120725944Sjoerg (cp->tld)(sp); 120825944Sjoerg sp->rst_counter[cp->protoidx] = 0; 120925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 121025944Sjoerg goto sta; 121125944Sjoerg break; 121225944Sjoerg default: 121325944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 121425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 121525944Sjoerg sppp_cp_type_name(h->type), 121625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 121725944Sjoerg ++ifp->if_ierrors; 121825944Sjoerg } 121925944Sjoerg break; 122025944Sjoerg case TERM_ACK: 122125944Sjoerg switch (sp->state[cp->protoidx]) { 122225944Sjoerg case STATE_CLOSED: 122325944Sjoerg case STATE_STOPPED: 122425944Sjoerg case STATE_REQ_SENT: 122525944Sjoerg case STATE_ACK_SENT: 122625944Sjoerg break; 122725944Sjoerg case STATE_CLOSING: 122825944Sjoerg (cp->tlf)(sp); 122925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 123025944Sjoerg break; 123125944Sjoerg case STATE_STOPPING: 123225944Sjoerg (cp->tlf)(sp); 123325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 123425944Sjoerg break; 123525944Sjoerg case STATE_ACK_RCVD: 123625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 123725944Sjoerg break; 123825944Sjoerg case STATE_OPENED: 123925944Sjoerg (cp->tld)(sp); 124025944Sjoerg (cp->scr)(sp); 124125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 124225944Sjoerg break; 124325944Sjoerg default: 124425944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 124525944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 124625944Sjoerg sppp_cp_type_name(h->type), 124725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 124825944Sjoerg ++ifp->if_ierrors; 124925944Sjoerg } 125025944Sjoerg break; 125125944Sjoerg case CODE_REJ: 125225944Sjoerg case PROTO_REJ: 125325944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 125425944Sjoerg switch (sp->state[cp->protoidx]) { 125525944Sjoerg case STATE_CLOSED: 125625944Sjoerg case STATE_STOPPED: 125725944Sjoerg case STATE_REQ_SENT: 125825944Sjoerg case STATE_ACK_SENT: 125925944Sjoerg case STATE_CLOSING: 126025944Sjoerg case STATE_STOPPING: 126125944Sjoerg case STATE_OPENED: 126225944Sjoerg break; 126325944Sjoerg case STATE_ACK_RCVD: 126425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 126525944Sjoerg break; 126625944Sjoerg default: 126725944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 126825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 126925944Sjoerg sppp_cp_type_name(h->type), 127025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 127125944Sjoerg ++ifp->if_ierrors; 127225944Sjoerg } 127325944Sjoerg break; 127425944Sjoerg case DISC_REQ: 127525944Sjoerg if (cp->proto != PPP_LCP) 127625944Sjoerg goto illegal; 127725944Sjoerg /* Discard the packet. */ 127825944Sjoerg break; 127925944Sjoerg case ECHO_REQ: 128025944Sjoerg if (cp->proto != PPP_LCP) 128125944Sjoerg goto illegal; 128225944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 128325944Sjoerg if (debug) 128425944Sjoerg addlog("%s%d: lcp echo req but lcp closed\n", 128525944Sjoerg ifp->if_name, ifp->if_unit); 128625944Sjoerg ++ifp->if_ierrors; 128725944Sjoerg break; 128825944Sjoerg } 128925944Sjoerg if (len < 8) { 129025944Sjoerg if (debug) 129125944Sjoerg addlog("%s%d: invalid lcp echo request " 129225944Sjoerg "packet length: %d bytes\n", 129325944Sjoerg ifp->if_name, ifp->if_unit, len); 129425944Sjoerg break; 129525944Sjoerg } 129625944Sjoerg if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 129725944Sjoerg /* Line loopback mode detected. */ 129825944Sjoerg printf("%s%d: loopback\n", ifp->if_name, ifp->if_unit); 129925944Sjoerg if_down (ifp); 130026018Sjoerg sppp_qflush (&sp->pp_cpq); 13014910Swollman 130225944Sjoerg /* Shut down the PPP link. */ 130325944Sjoerg /* XXX */ 130425944Sjoerg lcp.Down(sp); 130525944Sjoerg lcp.Up(sp); 130625944Sjoerg break; 130725944Sjoerg } 130825944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 130925944Sjoerg if (debug) 131025944Sjoerg addlog("%s%d: got lcp echo req, sending echo rep\n", 131125944Sjoerg ifp->if_name, ifp->if_unit); 131225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 131325944Sjoerg break; 131425944Sjoerg case ECHO_REPLY: 131525944Sjoerg if (cp->proto != PPP_LCP) 131625944Sjoerg goto illegal; 131725944Sjoerg if (h->ident != sp->lcp.echoid) { 131825944Sjoerg ++ifp->if_ierrors; 131925944Sjoerg break; 132025944Sjoerg } 132125944Sjoerg if (len < 8) { 132225944Sjoerg if (debug) 132325944Sjoerg addlog("%s%d: lcp invalid echo reply " 132425944Sjoerg "packet length: %d bytes\n", 132525944Sjoerg ifp->if_name, ifp->if_unit, len); 132625944Sjoerg break; 132725944Sjoerg } 132825944Sjoerg if (debug) 132925944Sjoerg addlog("%s%d: lcp got echo rep\n", 133025944Sjoerg ifp->if_name, ifp->if_unit); 133125944Sjoerg if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 133225944Sjoerg sp->pp_alivecnt = 0; 133325944Sjoerg break; 133425944Sjoerg default: 133525944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 133625944Sjoerg illegal: 133725944Sjoerg if (debug) 133825944Sjoerg addlog("%s%d: %c send code-rej for 0x%x\n", 133925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, h->type); 134025944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 134125944Sjoerg m->m_pkthdr.len, h); 134225944Sjoerg ++ifp->if_ierrors; 134325944Sjoerg } 13444910Swollman} 13454910Swollman 134625944Sjoerg 13474910Swollman/* 134825944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 134925944Sjoerg * Basically, the state transition handling in the automaton. 13504910Swollman */ 135125944Sjoergstatic void 135225944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 13534910Swollman{ 135425944Sjoerg STDDCL; 13554910Swollman 135625944Sjoerg if (debug) 135725944Sjoerg log(LOG_DEBUG, "%s%d: %s up(%s)\n", 135825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 135925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 136025944Sjoerg 136125944Sjoerg switch (sp->state[cp->protoidx]) { 136225944Sjoerg case STATE_INITIAL: 136325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 136425944Sjoerg break; 136525944Sjoerg case STATE_STARTING: 136625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 136725944Sjoerg (cp->scr)(sp); 136825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 136925944Sjoerg break; 13704910Swollman default: 137125944Sjoerg printf("%s%d: %s illegal up in state %s\n", 137225944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 137325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 137425944Sjoerg } 137525944Sjoerg} 13764910Swollman 137725944Sjoergstatic void 137825944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 137925944Sjoerg{ 138025944Sjoerg STDDCL; 138125944Sjoerg 138225944Sjoerg if (debug) 138325944Sjoerg log(LOG_DEBUG, "%s%d: %s down(%s)\n", 138425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 138525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 138625944Sjoerg 138725944Sjoerg switch (sp->state[cp->protoidx]) { 138825944Sjoerg case STATE_CLOSED: 138925944Sjoerg case STATE_CLOSING: 139025944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 13914910Swollman break; 139225944Sjoerg case STATE_STOPPED: 139325944Sjoerg (cp->tls)(sp); 139425944Sjoerg /* fall through */ 139525944Sjoerg case STATE_STOPPING: 139625944Sjoerg case STATE_REQ_SENT: 139725944Sjoerg case STATE_ACK_RCVD: 139825944Sjoerg case STATE_ACK_SENT: 139925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 140025944Sjoerg break; 140125944Sjoerg case STATE_OPENED: 140225944Sjoerg (cp->tld)(sp); 140325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 140425944Sjoerg break; 140525944Sjoerg default: 140625944Sjoerg printf("%s%d: %s illegal down in state %s\n", 140725944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 140825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 140925944Sjoerg } 141025944Sjoerg} 14114910Swollman 141211189Sjkh 141325944Sjoergstatic void 141425944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 141525944Sjoerg{ 141625944Sjoerg STDDCL; 141725944Sjoerg 141825944Sjoerg if (debug) 141925944Sjoerg log(LOG_DEBUG, "%s%d: %s open(%s)\n", 142025944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 142125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 142225944Sjoerg 142325944Sjoerg switch (sp->state[cp->protoidx]) { 142425944Sjoerg case STATE_INITIAL: 142525944Sjoerg (cp->tls)(sp); 142625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 14274910Swollman break; 142825944Sjoerg case STATE_STARTING: 142925944Sjoerg break; 143025944Sjoerg case STATE_CLOSED: 143125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143225944Sjoerg (cp->scr)(sp); 143325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 143425944Sjoerg break; 143525944Sjoerg case STATE_STOPPED: 143625944Sjoerg case STATE_STOPPING: 143725944Sjoerg case STATE_REQ_SENT: 143825944Sjoerg case STATE_ACK_RCVD: 143925944Sjoerg case STATE_ACK_SENT: 144025944Sjoerg case STATE_OPENED: 144125944Sjoerg break; 144225944Sjoerg case STATE_CLOSING: 144325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 144425944Sjoerg break; 144525944Sjoerg } 144625944Sjoerg} 14474910Swollman 144825944Sjoerg 144925944Sjoergstatic void 145025944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 145125944Sjoerg{ 145225944Sjoerg STDDCL; 145325944Sjoerg 145425944Sjoerg if (debug) 145525944Sjoerg log(LOG_DEBUG, "%s%d: %s close(%s)\n", 145625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 145725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 145825944Sjoerg 145925944Sjoerg switch (sp->state[cp->protoidx]) { 146025944Sjoerg case STATE_INITIAL: 146125944Sjoerg case STATE_CLOSED: 146225944Sjoerg case STATE_CLOSING: 14634910Swollman break; 146425944Sjoerg case STATE_STARTING: 146525944Sjoerg (cp->tlf)(sp); 146625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 14674910Swollman break; 146825944Sjoerg case STATE_STOPPED: 146925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 14704910Swollman break; 147125944Sjoerg case STATE_STOPPING: 147225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 14734910Swollman break; 147425944Sjoerg case STATE_OPENED: 147525944Sjoerg (cp->tld)(sp); 147625944Sjoerg /* fall through */ 147725944Sjoerg case STATE_REQ_SENT: 147825944Sjoerg case STATE_ACK_RCVD: 147925944Sjoerg case STATE_ACK_SENT: 148025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 148125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 148225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 14834910Swollman break; 14844910Swollman } 14854910Swollman} 14864910Swollman 148725944Sjoergstatic void 148825944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 148925944Sjoerg{ 149025944Sjoerg STDDCL; 149125944Sjoerg int s; 149225944Sjoerg 149325944Sjoerg s = splimp(); 149425944Sjoerg if (debug) 149525944Sjoerg log(LOG_DEBUG, "%s%d: %s TO(%s) rst_counter = %d\n", 149625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 149725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 149825944Sjoerg sp->rst_counter[cp->protoidx]); 149925944Sjoerg 150025944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 150125944Sjoerg /* TO- event */ 150225944Sjoerg switch (sp->state[cp->protoidx]) { 150325944Sjoerg case STATE_CLOSING: 150425944Sjoerg (cp->tlf)(sp); 150525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 150625944Sjoerg break; 150725944Sjoerg case STATE_STOPPING: 150825944Sjoerg (cp->tlf)(sp); 150925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 151025944Sjoerg break; 151125944Sjoerg case STATE_REQ_SENT: 151225944Sjoerg case STATE_ACK_RCVD: 151325944Sjoerg case STATE_ACK_SENT: 151425944Sjoerg (cp->tlf)(sp); 151525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 151625944Sjoerg break; 151725944Sjoerg } 151825944Sjoerg else 151925944Sjoerg /* TO+ event */ 152025944Sjoerg switch (sp->state[cp->protoidx]) { 152125944Sjoerg case STATE_CLOSING: 152225944Sjoerg case STATE_STOPPING: 152325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 152425944Sjoerg 0, 0); 152525944Sjoerg timeout(cp->TO, (void *)sp, sp->lcp.timeout); 152625944Sjoerg break; 152725944Sjoerg case STATE_REQ_SENT: 152825944Sjoerg case STATE_ACK_RCVD: 152925944Sjoerg (cp->scr)(sp); 153025944Sjoerg /* sppp_cp_change_state() will restart the timer */ 153125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 153225944Sjoerg break; 153325944Sjoerg case STATE_ACK_SENT: 153425944Sjoerg (cp->scr)(sp); 153525944Sjoerg timeout(cp->TO, (void *)sp, sp->lcp.timeout); 153625944Sjoerg break; 153725944Sjoerg } 153825944Sjoerg 153925944Sjoerg splx(s); 154025944Sjoerg} 154125944Sjoerg 154211189Sjkh/* 154325944Sjoerg * Change the state of a control protocol in the state automaton. 154425944Sjoerg * Takes care of starting/stopping the restart timer. 154511189Sjkh */ 154625944Sjoergvoid 154725944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 154825944Sjoerg{ 154925944Sjoerg sp->state[cp->protoidx] = newstate; 155025944Sjoerg 155125944Sjoerg untimeout(cp->TO, (void *)sp); 155225944Sjoerg switch (newstate) { 155325944Sjoerg case STATE_INITIAL: 155425944Sjoerg case STATE_STARTING: 155525944Sjoerg case STATE_CLOSED: 155625944Sjoerg case STATE_STOPPED: 155725944Sjoerg case STATE_OPENED: 155825944Sjoerg break; 155925944Sjoerg case STATE_CLOSING: 156025944Sjoerg case STATE_STOPPING: 156125944Sjoerg case STATE_REQ_SENT: 156225944Sjoerg case STATE_ACK_RCVD: 156325944Sjoerg case STATE_ACK_SENT: 156425944Sjoerg timeout(cp->TO, (void *)sp, sp->lcp.timeout); 156525944Sjoerg break; 156625944Sjoerg } 156725944Sjoerg} 156825944Sjoerg/* 156925944Sjoerg *--------------------------------------------------------------------------* 157025944Sjoerg * * 157125944Sjoerg * The LCP implementation. * 157225944Sjoerg * * 157325944Sjoerg *--------------------------------------------------------------------------* 157425944Sjoerg */ 157525944Sjoergstatic void 157625944Sjoergsppp_lcp_init(struct sppp *sp) 157725944Sjoerg{ 157825944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 157925944Sjoerg sp->lcp.magic = 0; 158025944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 158125944Sjoerg sp->fail_counter[IDX_LCP] = 0; 158225944Sjoerg sp->lcp.protos = 0; 158325944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 158425944Sjoerg 158525944Sjoerg /* 158625944Sjoerg * Initialize counters and timeout values. Note that we don't 158725944Sjoerg * use the 3 seconds suggested in RFC 1661 since we are likely 158825944Sjoerg * running on a fast link. XXX We should probably implement 158925944Sjoerg * the exponential backoff option. Note that these values are 159025944Sjoerg * relevant for all control protocols, not just LCP only. 159125944Sjoerg */ 159225944Sjoerg sp->lcp.timeout = 1 * hz; 159325944Sjoerg sp->lcp.max_terminate = 2; 159425944Sjoerg sp->lcp.max_configure = 10; 159525944Sjoerg sp->lcp.max_failure = 10; 159625944Sjoerg} 159725944Sjoerg 159825944Sjoergstatic void 159925944Sjoergsppp_lcp_up(struct sppp *sp) 160025944Sjoerg{ 160125944Sjoerg STDDCL; 160225944Sjoerg 160325944Sjoerg /* 160425944Sjoerg * If this interface is passive or dial-on-demand, it means 160525944Sjoerg * we've got in incoming call. Activate the interface. 160625944Sjoerg */ 160725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 160825944Sjoerg if (debug) 160925944Sjoerg log(LOG_DEBUG, 161025944Sjoerg "%s%d: Up event (incoming call)\n", 161125944Sjoerg ifp->if_name, ifp->if_unit); 161225944Sjoerg ifp->if_flags |= IFF_RUNNING; 161325944Sjoerg lcp.Open(sp); 161425944Sjoerg } 161525944Sjoerg 161625944Sjoerg sppp_up_event(&lcp, sp); 161725944Sjoerg} 161825944Sjoerg 161925944Sjoergstatic void 162025944Sjoergsppp_lcp_down(struct sppp *sp) 162125944Sjoerg{ 162225944Sjoerg STDDCL; 162325944Sjoerg 162425944Sjoerg sppp_down_event(&lcp, sp); 162525944Sjoerg 162625944Sjoerg /* 162725944Sjoerg * If this is neither a dial-on-demand nor a passive 162825944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 162925944Sjoerg * administrator can force a redial by another ``ifconfig 163025944Sjoerg * up''. XXX For leased line operation, should we immediately 163125944Sjoerg * try to reopen the connection here? 163225944Sjoerg */ 163325944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 163425944Sjoerg log(LOG_INFO, 163525944Sjoerg "%s%d: Down event (carrier loss), taking interface down.\n", 163625944Sjoerg ifp->if_name, ifp->if_unit); 163725944Sjoerg if_down(ifp); 163825944Sjoerg } else { 163925944Sjoerg if (debug) 164025944Sjoerg log(LOG_DEBUG, 164125944Sjoerg "%s%d: Down event (carrier loss)\n", 164225944Sjoerg ifp->if_name, ifp->if_unit); 164325944Sjoerg } 164425944Sjoerg lcp.Close(sp); 164525944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 164625944Sjoerg} 164725944Sjoerg 164825944Sjoergstatic void 164925944Sjoergsppp_lcp_open(struct sppp *sp) 165025944Sjoerg{ 165125944Sjoerg sppp_open_event(&lcp, sp); 165225944Sjoerg} 165325944Sjoerg 165425944Sjoergstatic void 165525944Sjoergsppp_lcp_close(struct sppp *sp) 165625944Sjoerg{ 165725944Sjoerg sppp_close_event(&lcp, sp); 165825944Sjoerg} 165925944Sjoerg 166025944Sjoergstatic void 166125944Sjoergsppp_lcp_TO(void *cookie) 166225944Sjoerg{ 166325944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 166425944Sjoerg} 166525944Sjoerg 166625944Sjoerg/* 166725944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 166825944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 166925944Sjoerg * caused action scn. (The return value is used to make the state 167025944Sjoerg * transition decision in the state automaton.) 167125944Sjoerg */ 167212820Sphkstatic int 167325944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 16744910Swollman{ 167525944Sjoerg STDDCL; 167611189Sjkh u_char *buf, *r, *p; 167725944Sjoerg int origlen, rlen; 167825944Sjoerg u_long nmagic; 16794910Swollman 168011189Sjkh len -= 4; 168125944Sjoerg origlen = len; 168211189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 168311189Sjkh if (! buf) 168411189Sjkh return (0); 16854910Swollman 168625706Sjoerg if (debug) 168725944Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opts: ", 168825944Sjoerg ifp->if_name, ifp->if_unit); 168925706Sjoerg 169025944Sjoerg /* pass 1: check for things that need to be rejected */ 169111189Sjkh p = (void*) (h+1); 169211189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 169325944Sjoerg if (debug) 169425944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 169511189Sjkh switch (*p) { 169611189Sjkh case LCP_OPT_MAGIC: 169725944Sjoerg /* Magic number. */ 169825944Sjoerg /* fall through, both are same length */ 169925944Sjoerg case LCP_OPT_ASYNC_MAP: 170025944Sjoerg /* Async control character map. */ 170125944Sjoerg if (len >= 6 || p[1] == 6) 170225944Sjoerg continue; 170325944Sjoerg if (debug) 170425944Sjoerg addlog("[invalid] "); 170525944Sjoerg break; 170625944Sjoerg case LCP_OPT_MRU: 170725944Sjoerg /* Maximum receive unit. */ 170825944Sjoerg if (len >= 4 && p[1] == 4) 170925944Sjoerg continue; 171025944Sjoerg if (debug) 171125944Sjoerg addlog("[invalid] "); 171225944Sjoerg break; 171325944Sjoerg default: 171425944Sjoerg /* Others not supported. */ 171525944Sjoerg if (debug) 171625944Sjoerg addlog("[rej] "); 171725944Sjoerg break; 171825944Sjoerg } 171925944Sjoerg /* Add the option to rejected list. */ 172025944Sjoerg bcopy (p, r, p[1]); 172125944Sjoerg r += p[1]; 172225944Sjoerg rlen += p[1]; 172325944Sjoerg } 172425944Sjoerg if (rlen) { 172525944Sjoerg if (debug) 172625944Sjoerg addlog(" send conf-rej\n"); 172725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 172825944Sjoerg return 0; 172925944Sjoerg } else if (debug) 173025944Sjoerg addlog("\n"); 173125944Sjoerg 173225944Sjoerg /* 173325944Sjoerg * pass 2: check for option values that are unacceptable and 173425944Sjoerg * thus require to be nak'ed. 173525944Sjoerg */ 173625944Sjoerg if (debug) 173726077Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opt values: ", 173826077Sjoerg ifp->if_name, ifp->if_unit); 173925944Sjoerg 174025944Sjoerg p = (void*) (h+1); 174125944Sjoerg len = origlen; 174225944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 174325944Sjoerg if (debug) 174425944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 174525944Sjoerg switch (*p) { 174625944Sjoerg case LCP_OPT_MAGIC: 174711189Sjkh /* Magic number -- extract. */ 174825944Sjoerg nmagic = (u_long)p[2] << 24 | 174925944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 175025944Sjoerg if (nmagic != sp->lcp.magic) { 175125706Sjoerg if (debug) 175225944Sjoerg addlog("0x%x ", nmagic); 175311189Sjkh continue; 175411189Sjkh } 175525944Sjoerg /* 175625944Sjoerg * Local and remote magics equal -- loopback? 175725944Sjoerg */ 175825944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 175925944Sjoerg printf ("\n%s%d: loopback\n", 176025944Sjoerg ifp->if_name, ifp->if_unit); 176125944Sjoerg sp->pp_loopcnt = 0; 176225944Sjoerg if (ifp->if_flags & IFF_UP) { 176325944Sjoerg if_down(ifp); 176426018Sjoerg sppp_qflush(&sp->pp_cpq); 176525944Sjoerg /* XXX ? */ 176625944Sjoerg lcp.Down(sp); 176725944Sjoerg lcp.Up(sp); 176825944Sjoerg } 176925944Sjoerg } else if (debug) 177025944Sjoerg addlog("[glitch] "); 177125944Sjoerg ++sp->pp_loopcnt; 177225944Sjoerg /* 177325944Sjoerg * We negate our magic here, and NAK it. If 177425944Sjoerg * we see it later in an NAK packet, we 177525944Sjoerg * suggest a new one. 177625944Sjoerg */ 177725944Sjoerg nmagic = ~sp->lcp.magic; 177825944Sjoerg /* Gonna NAK it. */ 177925944Sjoerg p[2] = nmagic >> 24; 178025944Sjoerg p[3] = nmagic >> 16; 178125944Sjoerg p[4] = nmagic >> 8; 178225944Sjoerg p[5] = nmagic; 178311189Sjkh break; 178425944Sjoerg 178511189Sjkh case LCP_OPT_ASYNC_MAP: 178611189Sjkh /* Async control character map -- check to be zero. */ 178725944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 178825706Sjoerg if (debug) 178925944Sjoerg addlog("[empty] "); 179011189Sjkh continue; 179125706Sjoerg } 179225706Sjoerg if (debug) 179325944Sjoerg addlog("[non-empty] "); 179425944Sjoerg /* suggest a zero one */ 179525944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 179611189Sjkh break; 179725944Sjoerg 179811189Sjkh case LCP_OPT_MRU: 179925944Sjoerg /* 180025944Sjoerg * Maximum receive unit. Always agreeable, 180125944Sjoerg * but ignored by now. 180225944Sjoerg */ 180325944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 180425706Sjoerg if (debug) 180525944Sjoerg addlog("%d ", sp->lcp.their_mru); 180611189Sjkh continue; 180711189Sjkh } 180825944Sjoerg /* Add the option to nak'ed list. */ 180925706Sjoerg bcopy (p, r, p[1]); 181025706Sjoerg r += p[1]; 181111189Sjkh rlen += p[1]; 181212436Speter } 181325706Sjoerg if (rlen) { 181428036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 181528036Sjoerg if (debug) 181628036Sjoerg addlog(" max_failure (%d) exceeded, " 181728036Sjoerg "send conf-rej\n", 181828036Sjoerg sp->lcp.max_failure); 181928036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 182028036Sjoerg } else { 182128036Sjoerg if (debug) 182228036Sjoerg addlog(" send conf-nak\n"); 182328036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 182428036Sjoerg } 182525944Sjoerg return 0; 182625944Sjoerg } else { 182725944Sjoerg if (debug) 182825944Sjoerg addlog(" send conf-ack\n"); 182928036Sjoerg sp->fail_counter[IDX_LCP] = 0; 183025944Sjoerg sp->pp_loopcnt = 0; 183125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 183225944Sjoerg h->ident, origlen, h+1); 183325944Sjoerg } 183425944Sjoerg 183511189Sjkh free (buf, M_TEMP); 183611189Sjkh return (rlen == 0); 18374910Swollman} 18384910Swollman 183925944Sjoerg/* 184025944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 184125944Sjoerg * negotiation. 184225944Sjoerg */ 184312820Sphkstatic void 184425944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 18454910Swollman{ 184625944Sjoerg STDDCL; 184725944Sjoerg u_char *buf, *p; 18484910Swollman 184925944Sjoerg len -= 4; 185025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 185125944Sjoerg if (!buf) 18524910Swollman return; 185325944Sjoerg 185425944Sjoerg if (debug) 185525944Sjoerg log(LOG_DEBUG, "%s%d: lcp rej opts: ", 185625944Sjoerg ifp->if_name, ifp->if_unit); 185725944Sjoerg 185825944Sjoerg p = (void*) (h+1); 185925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 186025944Sjoerg if (debug) 186125944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 186225944Sjoerg switch (*p) { 186325944Sjoerg case LCP_OPT_MAGIC: 186425944Sjoerg /* Magic number -- can't use it, use 0 */ 186525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 186625944Sjoerg sp->lcp.magic = 0; 186725944Sjoerg break; 186825944Sjoerg case LCP_OPT_MRU: 186925944Sjoerg /* 187025944Sjoerg * Should not be rejected anyway, since we only 187125944Sjoerg * negotiate a MRU if explicitly requested by 187225944Sjoerg * peer. 187325944Sjoerg */ 187425944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 187525944Sjoerg break; 187625944Sjoerg } 18774910Swollman } 187825944Sjoerg if (debug) 187925944Sjoerg addlog("\n"); 188025944Sjoerg free (buf, M_TEMP); 188125944Sjoerg return; 188225944Sjoerg} 188325944Sjoerg 188425944Sjoerg/* 188525944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 188625944Sjoerg * negotiation. 188725944Sjoerg */ 188825944Sjoergstatic void 188925944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 189025944Sjoerg{ 189125944Sjoerg STDDCL; 189225944Sjoerg u_char *buf, *p; 189325944Sjoerg u_long magic; 189425944Sjoerg 189525944Sjoerg len -= 4; 189625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 189725944Sjoerg if (!buf) 189825944Sjoerg return; 189925944Sjoerg 190025944Sjoerg if (debug) 190125944Sjoerg log(LOG_DEBUG, "%s%d: lcp nak opts: ", 190225944Sjoerg ifp->if_name, ifp->if_unit); 190325944Sjoerg 190425944Sjoerg p = (void*) (h+1); 190525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 190625706Sjoerg if (debug) 190725944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 190825944Sjoerg switch (*p) { 190925944Sjoerg case LCP_OPT_MAGIC: 191025944Sjoerg /* Magic number -- renegotiate */ 191125944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 191225944Sjoerg len >= 6 && p[1] == 6) { 191325944Sjoerg magic = (u_long)p[2] << 24 | 191425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 191525944Sjoerg /* 191625944Sjoerg * If the remote magic is our negated one, 191725944Sjoerg * this looks like a loopback problem. 191825944Sjoerg * Suggest a new magic to make sure. 191925944Sjoerg */ 192025944Sjoerg if (magic == ~sp->lcp.magic) { 192125944Sjoerg if (debug) 192225944Sjoerg addlog("magic glitch "); 192325944Sjoerg sp->lcp.magic += time.tv_sec + time.tv_usec; 192425944Sjoerg } else { 192525944Sjoerg sp->lcp.magic = magic; 192625944Sjoerg if (debug) 192725944Sjoerg addlog("%d "); 192825944Sjoerg } 192925944Sjoerg } 193025944Sjoerg break; 193125944Sjoerg case LCP_OPT_MRU: 193225944Sjoerg /* 193325944Sjoerg * Peer wants to advise us to negotiate an MRU. 193425944Sjoerg * Agree on it if it's reasonable, or use 193525944Sjoerg * default otherwise. 193625944Sjoerg */ 193725944Sjoerg if (len >= 4 && p[1] == 4) { 193825944Sjoerg u_int mru = p[2] * 256 + p[3]; 193925944Sjoerg if (debug) 194025944Sjoerg addlog("%d ", mru); 194125944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 194225944Sjoerg mru = PP_MTU; 194325944Sjoerg sp->lcp.mru = mru; 194425944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 194525944Sjoerg } 194625944Sjoerg break; 19474910Swollman } 194825944Sjoerg } 194925944Sjoerg if (debug) 195025944Sjoerg addlog("\n"); 195125944Sjoerg free (buf, M_TEMP); 195225944Sjoerg return; 195325944Sjoerg} 195411189Sjkh 195525944Sjoergstatic void 195625944Sjoergsppp_lcp_tlu(struct sppp *sp) 195725944Sjoerg{ 195825944Sjoerg STDDCL; 195925944Sjoerg int i; 196025944Sjoerg u_long mask; 196125944Sjoerg 196225944Sjoerg /* XXX ? */ 196325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 196425944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 196525944Sjoerg /* Coming out of loopback mode. */ 196625944Sjoerg if_up(ifp); 196725944Sjoerg printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 196825944Sjoerg } 196925944Sjoerg 197025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 197125944Sjoerg if ((cps[i])->flags & CP_QUAL) 197225944Sjoerg (cps[i])->Open(sp); 197325944Sjoerg 197425944Sjoerg if (/* require authentication XXX */ 0) 197525944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 197625944Sjoerg else 197725944Sjoerg sp->pp_phase = PHASE_NETWORK; 197825944Sjoerg 197925944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 198025944Sjoerg sppp_phase_name(sp->pp_phase)); 198125944Sjoerg 198225944Sjoerg if (sp->pp_phase == PHASE_AUTHENTICATE) { 198325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 198425944Sjoerg if ((cps[i])->flags & CP_AUTH) 198525944Sjoerg (cps[i])->Open(sp); 198625944Sjoerg } else { 198725944Sjoerg /* Notify all NCPs. */ 198825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 198925944Sjoerg if ((cps[i])->flags & CP_NCP) 199025944Sjoerg (cps[i])->Open(sp); 199125944Sjoerg } 199225944Sjoerg 199325944Sjoerg /* Send Up events to all started protos. */ 199425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 199525944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 199625944Sjoerg (cps[i])->Up(sp); 199725944Sjoerg 199825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 199925944Sjoerg /* if no NCP is starting, close down */ 200025944Sjoerg sppp_lcp_check(sp); 200125944Sjoerg} 200225944Sjoerg 200325944Sjoergstatic void 200425944Sjoergsppp_lcp_tld(struct sppp *sp) 200525944Sjoerg{ 200625944Sjoerg STDDCL; 200725944Sjoerg int i; 200825944Sjoerg u_long mask; 200925944Sjoerg 201025944Sjoerg sp->pp_phase = PHASE_TERMINATE; 201125944Sjoerg 201225944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 201325944Sjoerg sppp_phase_name(sp->pp_phase)); 201425944Sjoerg 201525944Sjoerg /* 201625944Sjoerg * Take upper layers down. We send the Down event first and 201725944Sjoerg * the Close second to prevent the upper layers from sending 201825944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 201925944Sjoerg * describes it. 202025944Sjoerg */ 202125944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 202225944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 202325944Sjoerg (cps[i])->Down(sp); 202425944Sjoerg (cps[i])->Close(sp); 202525944Sjoerg } 202625944Sjoerg} 202725944Sjoerg 202825944Sjoergstatic void 202925944Sjoergsppp_lcp_tls(struct sppp *sp) 203025944Sjoerg{ 203125944Sjoerg STDDCL; 203225944Sjoerg 203325944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 203425944Sjoerg 203525944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 203625944Sjoerg sppp_phase_name(sp->pp_phase)); 203725944Sjoerg 203825944Sjoerg /* Notify lower layer if desired. */ 203925944Sjoerg if (sp->pp_tls) 204025944Sjoerg (sp->pp_tls)(sp); 204125944Sjoerg} 204225944Sjoerg 204325944Sjoergstatic void 204425944Sjoergsppp_lcp_tlf(struct sppp *sp) 204525944Sjoerg{ 204625944Sjoerg STDDCL; 204725944Sjoerg 204825944Sjoerg sp->pp_phase = PHASE_DEAD; 204925944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 205025944Sjoerg sppp_phase_name(sp->pp_phase)); 205125944Sjoerg 205225944Sjoerg /* Notify lower layer if desired. */ 205325944Sjoerg if (sp->pp_tlf) 205425944Sjoerg (sp->pp_tlf)(sp); 205525944Sjoerg} 205625944Sjoerg 205725944Sjoergstatic void 205825944Sjoergsppp_lcp_scr(struct sppp *sp) 205925944Sjoerg{ 206025944Sjoerg char opt[6 /* magicnum */ + 4 /* mru */]; 206125944Sjoerg int i = 0; 206225944Sjoerg 206325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 206425944Sjoerg if (! sp->lcp.magic) 206525944Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 206625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 206725944Sjoerg opt[i++] = 6; 206825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 206925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 207025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 207125944Sjoerg opt[i++] = sp->lcp.magic; 207225944Sjoerg } 207325944Sjoerg 207425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 207525944Sjoerg opt[i++] = LCP_OPT_MRU; 207625944Sjoerg opt[i++] = 4; 207725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 207825944Sjoerg opt[i++] = sp->lcp.mru; 207925944Sjoerg } 208025944Sjoerg 208125944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 208225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 208325944Sjoerg} 208425944Sjoerg 208525944Sjoerg/* 208625944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 208725944Sjoerg * Called by the NCPs during their tlf action handling. 208825944Sjoerg */ 208925944Sjoergstatic void 209025944Sjoergsppp_lcp_check(struct sppp *sp) 209125944Sjoerg{ 209225944Sjoerg int i, mask; 209325944Sjoerg 209425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 209525944Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 209625944Sjoerg return; 209725944Sjoerg lcp.Close(sp); 209825944Sjoerg} 209925944Sjoerg/* 210025944Sjoerg *--------------------------------------------------------------------------* 210125944Sjoerg * * 210225944Sjoerg * The IPCP implementation. * 210325944Sjoerg * * 210425944Sjoerg *--------------------------------------------------------------------------* 210525944Sjoerg */ 210625944Sjoerg 210725944Sjoergstatic void 210825944Sjoergsppp_ipcp_init(struct sppp *sp) 210925944Sjoerg{ 211025944Sjoerg sp->ipcp.opts = 0; 211125944Sjoerg sp->ipcp.flags = 0; 211225944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 211325944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 211425944Sjoerg} 211525944Sjoerg 211625944Sjoergstatic void 211725944Sjoergsppp_ipcp_up(struct sppp *sp) 211825944Sjoerg{ 211925944Sjoerg sppp_up_event(&ipcp, sp); 212025944Sjoerg} 212125944Sjoerg 212225944Sjoergstatic void 212325944Sjoergsppp_ipcp_down(struct sppp *sp) 212425944Sjoerg{ 212525944Sjoerg sppp_down_event(&ipcp, sp); 212625944Sjoerg} 212725944Sjoerg 212825944Sjoergstatic void 212925944Sjoergsppp_ipcp_open(struct sppp *sp) 213025944Sjoerg{ 213125944Sjoerg STDDCL; 213225944Sjoerg u_long myaddr, hisaddr; 213325944Sjoerg 213425944Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr); 213525944Sjoerg /* 213625944Sjoerg * If we don't have his address, this probably means our 213725944Sjoerg * interface doesn't want to talk IP at all. (This could 213825944Sjoerg * be the case if somebody wants to speak only IPX, for 213925944Sjoerg * example.) Don't open IPCP in this case. 214025944Sjoerg */ 214125944Sjoerg if (hisaddr == 0L) { 214225944Sjoerg /* XXX this message should go away */ 214325944Sjoerg if (debug) 214425944Sjoerg log(LOG_DEBUG, "%s%d: ipcp_open(): no IP interface\n", 214525944Sjoerg ifp->if_name, ifp->if_unit); 214625944Sjoerg return; 214725944Sjoerg } 214825944Sjoerg 214925944Sjoerg if (myaddr == 0L) { 215025944Sjoerg /* 215125944Sjoerg * I don't have an assigned address, so i need to 215225944Sjoerg * negotiate my address. 215325944Sjoerg */ 215425944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 215525944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 215625944Sjoerg } 215725944Sjoerg sppp_open_event(&ipcp, sp); 215825944Sjoerg} 215925944Sjoerg 216025944Sjoergstatic void 216125944Sjoergsppp_ipcp_close(struct sppp *sp) 216225944Sjoerg{ 216325944Sjoerg sppp_close_event(&ipcp, sp); 216425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 216525944Sjoerg /* 216625944Sjoerg * My address was dynamic, clear it again. 216725944Sjoerg */ 216825944Sjoerg sppp_set_ip_addr(sp, 0L); 216925944Sjoerg} 217025944Sjoerg 217125944Sjoergstatic void 217225944Sjoergsppp_ipcp_TO(void *cookie) 217325944Sjoerg{ 217425944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 217525944Sjoerg} 217625944Sjoerg 217725944Sjoerg/* 217825944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 217925944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 218025944Sjoerg * caused action scn. (The return value is used to make the state 218125944Sjoerg * transition decision in the state automaton.) 218225944Sjoerg */ 218325944Sjoergstatic int 218425944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 218525944Sjoerg{ 218625944Sjoerg u_char *buf, *r, *p; 218725944Sjoerg struct ifnet *ifp = &sp->pp_if; 218825944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 218925944Sjoerg u_long hisaddr, desiredaddr; 219025944Sjoerg 219125944Sjoerg len -= 4; 219225944Sjoerg origlen = len; 219325944Sjoerg /* 219425944Sjoerg * Make sure to allocate a buf that can at least hold a 219525944Sjoerg * conf-nak with an `address' option. We might need it below. 219625944Sjoerg */ 219725944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 219825944Sjoerg if (! buf) 219925944Sjoerg return (0); 220025944Sjoerg 220125944Sjoerg /* pass 1: see if we can recognize them */ 220225944Sjoerg if (debug) 220325944Sjoerg log(LOG_DEBUG, "%s%d: ipcp parse opts: ", 220425944Sjoerg ifp->if_name, ifp->if_unit); 220525944Sjoerg p = (void*) (h+1); 220625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 220725944Sjoerg if (debug) 220825944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 220925944Sjoerg switch (*p) { 221025944Sjoerg#ifdef notyet 221125944Sjoerg case IPCP_OPT_COMPRESSION: 221225944Sjoerg if (len >= 6 && p[1] >= 6) { 221325944Sjoerg /* correctly formed compress option */ 221425944Sjoerg continue; 221511189Sjkh } 221625706Sjoerg if (debug) 221725944Sjoerg addlog("[invalid] "); 221825944Sjoerg break; 221925944Sjoerg#endif 222025944Sjoerg case IPCP_OPT_ADDRESS: 222125944Sjoerg if (len >= 6 && p[1] == 6) { 222225944Sjoerg /* correctly formed address option */ 222325944Sjoerg continue; 222425944Sjoerg } 222525706Sjoerg if (debug) 222625944Sjoerg addlog("[invalid] "); 222711189Sjkh break; 222825944Sjoerg default: 222925944Sjoerg /* Others not supported. */ 223025944Sjoerg if (debug) 223125944Sjoerg addlog("[rej] "); 22324910Swollman break; 22334910Swollman } 223425944Sjoerg /* Add the option to rejected list. */ 223525944Sjoerg bcopy (p, r, p[1]); 223625944Sjoerg r += p[1]; 223725944Sjoerg rlen += p[1]; 223825944Sjoerg } 223925944Sjoerg if (rlen) { 224025944Sjoerg if (debug) 224125944Sjoerg addlog(" send conf-rej\n"); 224225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 224325944Sjoerg return 0; 224425944Sjoerg } else if (debug) 224525944Sjoerg addlog("\n"); 224625944Sjoerg 224725944Sjoerg /* pass 2: parse option values */ 224825944Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr); 224925944Sjoerg if (debug) 225025944Sjoerg addlog("%s%d: ipcp parse opt values: ", ifp->if_name, ifp->if_unit); 225125944Sjoerg p = (void*) (h+1); 225225944Sjoerg len = origlen; 225325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 225425944Sjoerg if (debug) 225525944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 225625944Sjoerg switch (*p) { 225725944Sjoerg#ifdef notyet 225825944Sjoerg case IPCP_OPT_COMPRESSION: 225925944Sjoerg continue; 226025944Sjoerg#endif 226125944Sjoerg case IPCP_OPT_ADDRESS: 226225944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 226325944Sjoerg p[4] << 8 | p[5]; 226425944Sjoerg if (desiredaddr == hisaddr) { 226525944Sjoerg /* 226625944Sjoerg * Peer's address is same as our value, 226725944Sjoerg * this is agreeable. Gonna conf-ack 226825944Sjoerg * it. 226925944Sjoerg */ 227025944Sjoerg if (debug) 227125944Sjoerg addlog("0x%x [ack] ", hisaddr); 227225944Sjoerg /* record that we've seen it already */ 227325944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 227425944Sjoerg continue; 227525944Sjoerg } 227625944Sjoerg /* 227725944Sjoerg * The address wasn't agreeable. This is either 227825944Sjoerg * he sent us 0.0.0.0, asking to assign him an 227925944Sjoerg * address, or he send us another address not 228025944Sjoerg * matching our value. Either case, we gonna 228125944Sjoerg * conf-nak it with our value. 228225944Sjoerg */ 228325944Sjoerg if (debug) { 228425944Sjoerg if (desiredaddr == 0) 228525944Sjoerg addlog("[addr requested] "); 228625944Sjoerg else 228725944Sjoerg addlog("0x%x [not agreed] ", 228825944Sjoerg desiredaddr); 228925944Sjoerg 229025944Sjoerg p[2] = hisaddr >> 24; 229125944Sjoerg p[3] = hisaddr >> 16; 229225944Sjoerg p[4] = hisaddr >> 8; 229325944Sjoerg p[5] = hisaddr; 229425944Sjoerg } 229511189Sjkh break; 229625706Sjoerg } 229725944Sjoerg /* Add the option to nak'ed list. */ 229825944Sjoerg bcopy (p, r, p[1]); 229925944Sjoerg r += p[1]; 230025944Sjoerg rlen += p[1]; 230125944Sjoerg } 230225944Sjoerg 230325944Sjoerg /* 230425944Sjoerg * If we are about to conf-ack the request, but haven't seen 230525944Sjoerg * his address so far, gonna conf-nak it instead, with the 230625944Sjoerg * `address' option present and our idea of his address being 230725944Sjoerg * filled in there, to request negotiation of both addresses. 230825944Sjoerg * 230925944Sjoerg * XXX This can result in an endless req - nak loop if peer 231025944Sjoerg * doesn't want to send us his address. Q: What should we do 231125944Sjoerg * about it? XXX A: implement the max-failure counter. 231225944Sjoerg */ 231325944Sjoerg if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { 231425944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 231525944Sjoerg buf[1] = 6; 231625944Sjoerg buf[2] = hisaddr >> 24; 231725944Sjoerg buf[3] = hisaddr >> 16; 231825944Sjoerg buf[4] = hisaddr >> 8; 231925944Sjoerg buf[5] = hisaddr; 232025944Sjoerg rlen = 6; 232125706Sjoerg if (debug) 232225944Sjoerg addlog("still need hisaddr "); 232325944Sjoerg } 232425944Sjoerg 232525944Sjoerg if (rlen) { 232625706Sjoerg if (debug) 232725944Sjoerg addlog(" send conf-nak\n"); 232825944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 232925944Sjoerg } else { 233025706Sjoerg if (debug) 233125944Sjoerg addlog(" send conf-ack\n"); 233225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 233325944Sjoerg h->ident, origlen, h+1); 233425944Sjoerg } 233525944Sjoerg 233625944Sjoerg free (buf, M_TEMP); 233725944Sjoerg return (rlen == 0); 233825944Sjoerg} 233925944Sjoerg 234025944Sjoerg/* 234125944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 234225944Sjoerg * negotiation. 234325944Sjoerg */ 234425944Sjoergstatic void 234525944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 234625944Sjoerg{ 234725944Sjoerg u_char *buf, *p; 234825944Sjoerg struct ifnet *ifp = &sp->pp_if; 234925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 235025944Sjoerg 235125944Sjoerg len -= 4; 235225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 235325944Sjoerg if (!buf) 235425944Sjoerg return; 235525944Sjoerg 235625944Sjoerg if (debug) 235725944Sjoerg log(LOG_DEBUG, "%s%d: ipcp rej opts: ", 235825944Sjoerg ifp->if_name, ifp->if_unit); 235925944Sjoerg 236025944Sjoerg p = (void*) (h+1); 236125944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 236225706Sjoerg if (debug) 236325944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 236425944Sjoerg switch (*p) { 236525944Sjoerg case IPCP_OPT_ADDRESS: 236625944Sjoerg /* 236725944Sjoerg * Peer doesn't grok address option. This is 236825944Sjoerg * bad. XXX Should we better give up here? 236925944Sjoerg */ 237025944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 237125944Sjoerg break; 237225944Sjoerg#ifdef notyet 237325944Sjoerg case IPCP_OPT_COMPRESS: 237425944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); 237525944Sjoerg break; 237625944Sjoerg#endif 237725944Sjoerg } 23784910Swollman } 237925944Sjoerg if (debug) 238025944Sjoerg addlog("\n"); 238125944Sjoerg free (buf, M_TEMP); 238225944Sjoerg return; 23834910Swollman} 23844910Swollman 238525944Sjoerg/* 238625944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 238725944Sjoerg * negotiation. 238825944Sjoerg */ 238912820Sphkstatic void 239025944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 23914910Swollman{ 239225944Sjoerg u_char *buf, *p; 239325944Sjoerg struct ifnet *ifp = &sp->pp_if; 239425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 239525944Sjoerg u_long wantaddr; 23964910Swollman 239725944Sjoerg len -= 4; 239825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 239925944Sjoerg if (!buf) 240025944Sjoerg return; 240125944Sjoerg 240225944Sjoerg if (debug) 240325944Sjoerg log(LOG_DEBUG, "%s%d: ipcp nak opts: ", 240425944Sjoerg ifp->if_name, ifp->if_unit); 240525944Sjoerg 240625944Sjoerg p = (void*) (h+1); 240725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 240825944Sjoerg if (debug) 240925944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 241025944Sjoerg switch (*p) { 241125944Sjoerg case IPCP_OPT_ADDRESS: 241225944Sjoerg /* 241325944Sjoerg * Peer doesn't like our local IP address. See 241425944Sjoerg * if we can do something for him. We'll drop 241525944Sjoerg * him our address then. 241625944Sjoerg */ 241725944Sjoerg if (len >= 6 && p[1] == 6) { 241825944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 241925944Sjoerg p[4] << 8 | p[5]; 242025944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 242125944Sjoerg if (debug) 242225944Sjoerg addlog("[wantaddr 0x%x] ", wantaddr); 242325944Sjoerg /* 242425944Sjoerg * When doing dynamic address assignment, 242525944Sjoerg * we accept his offer. Otherwise, we 242625944Sjoerg * ignore it and thus continue to negotiate 242725944Sjoerg * our already existing value. 242825944Sjoerg */ 242925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 243025944Sjoerg sppp_set_ip_addr(sp, wantaddr); 243125944Sjoerg if (debug) 243225944Sjoerg addlog("[agree] "); 243325944Sjoerg } 243425944Sjoerg } 243525944Sjoerg break; 243625944Sjoerg#ifdef notyet 243725944Sjoerg case IPCP_OPT_COMPRESS: 243825944Sjoerg /* 243925944Sjoerg * Peer wants different compression parameters. 244025944Sjoerg */ 244125944Sjoerg break; 244225944Sjoerg#endif 244325944Sjoerg } 244425944Sjoerg } 244525944Sjoerg if (debug) 244625944Sjoerg addlog("\n"); 244725944Sjoerg free (buf, M_TEMP); 244825944Sjoerg return; 24494910Swollman} 24504910Swollman 245112820Sphkstatic void 245225944Sjoergsppp_ipcp_tlu(struct sppp *sp) 24534910Swollman{ 24544910Swollman} 24554910Swollman 245625944Sjoergstatic void 245725944Sjoergsppp_ipcp_tld(struct sppp *sp) 245825944Sjoerg{ 245925944Sjoerg} 246025944Sjoerg 246125944Sjoergstatic void 246225944Sjoergsppp_ipcp_tls(struct sppp *sp) 246325944Sjoerg{ 246425944Sjoerg /* indicate to LCP that it must stay alive */ 246525944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 246625944Sjoerg} 246725944Sjoerg 246825944Sjoergstatic void 246925944Sjoergsppp_ipcp_tlf(struct sppp *sp) 247025944Sjoerg{ 247125944Sjoerg /* we no longer need LCP */ 247225944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 247325944Sjoerg sppp_lcp_check(sp); 247425944Sjoerg} 247525944Sjoerg 247625944Sjoergstatic void 247725944Sjoergsppp_ipcp_scr(struct sppp *sp) 247825944Sjoerg{ 247925944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 248025944Sjoerg u_long ouraddr; 248125944Sjoerg int i = 0; 248225944Sjoerg 248325944Sjoerg#ifdef notyet 248425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 248525944Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 248625944Sjoerg opt[i++] = 6; 248725944Sjoerg opt[i++] = 0; /* VJ header compression */ 248825944Sjoerg opt[i++] = 0x2d; /* VJ header compression */ 248925944Sjoerg opt[i++] = max_slot_id; 249025944Sjoerg opt[i++] = comp_slot_id; 249125944Sjoerg } 249225944Sjoerg#endif 249325944Sjoerg 249425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 249525944Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0); 249625944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 249725944Sjoerg opt[i++] = 6; 249825944Sjoerg opt[i++] = ouraddr >> 24; 249925944Sjoerg opt[i++] = ouraddr >> 16; 250025944Sjoerg opt[i++] = ouraddr >> 8; 250125944Sjoerg opt[i++] = ouraddr; 250225944Sjoerg } 250325944Sjoerg 250425944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 250525944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 250625944Sjoerg} 250725944Sjoerg 250825944Sjoerg 250925944Sjoerg/* 251025944Sjoerg * Random miscellaneous functions. 251125944Sjoerg */ 251225944Sjoerg 25134910Swollman/* 251425944Sjoerg * Flush interface queue. 25154910Swollman */ 251612820Sphkstatic void 251725944Sjoergsppp_qflush(struct ifqueue *ifq) 25184910Swollman{ 251925944Sjoerg struct mbuf *m, *n; 25204910Swollman 252125944Sjoerg n = ifq->ifq_head; 252225944Sjoerg while ((m = n)) { 252325944Sjoerg n = m->m_act; 252425944Sjoerg m_freem (m); 252511189Sjkh } 252625944Sjoerg ifq->ifq_head = 0; 252725944Sjoerg ifq->ifq_tail = 0; 252825944Sjoerg ifq->ifq_len = 0; 252925944Sjoerg} 253025944Sjoerg 253125944Sjoerg/* 253225944Sjoerg * Send keepalive packets, every 10 seconds. 253325944Sjoerg */ 253425944Sjoergstatic void 253525944Sjoergsppp_keepalive(void *dummy) 253625944Sjoerg{ 253725944Sjoerg struct sppp *sp; 253825944Sjoerg int s; 253925944Sjoerg 254025944Sjoerg s = splimp(); 254125944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 254225944Sjoerg struct ifnet *ifp = &sp->pp_if; 254325944Sjoerg 254425944Sjoerg /* Keepalive mode disabled or channel down? */ 254525944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 254625944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 254725944Sjoerg continue; 254825944Sjoerg 254925944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 255025944Sjoerg if (! (sp->pp_flags & PP_CISCO) && 255125944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 255225944Sjoerg continue; 255325944Sjoerg 255425944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 255525944Sjoerg /* No keepalive packets got. Stop the interface. */ 255625944Sjoerg printf ("%s%d: down\n", ifp->if_name, ifp->if_unit); 255725944Sjoerg if_down (ifp); 255826018Sjoerg sppp_qflush (&sp->pp_cpq); 255925944Sjoerg if (! (sp->pp_flags & PP_CISCO)) { 256025944Sjoerg /* XXX */ 256125944Sjoerg /* Shut down the PPP link. */ 256225944Sjoerg lcp.Down(sp); 256325944Sjoerg /* Initiate negotiation. XXX */ 256425944Sjoerg lcp.Up(sp); 256525944Sjoerg } 25664910Swollman } 256725944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 256825944Sjoerg ++sp->pp_alivecnt; 256925944Sjoerg if (sp->pp_flags & PP_CISCO) 257025944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 257125944Sjoerg sp->pp_rseq); 257225944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 257325944Sjoerg long nmagic = htonl (sp->lcp.magic); 257425944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 257525944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 257625944Sjoerg sp->lcp.echoid, 4, &nmagic); 257725944Sjoerg } 25784910Swollman } 257925944Sjoerg splx(s); 258025944Sjoerg timeout(sppp_keepalive, 0, hz * 10); 25814910Swollman} 25824910Swollman 258325944Sjoerg/* 258425944Sjoerg * Get both IP addresses. 258525944Sjoerg */ 258625944Sjoergstatic void 258725944Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst) 258825944Sjoerg{ 258925944Sjoerg struct ifnet *ifp = &sp->pp_if; 259025944Sjoerg struct ifaddr *ifa; 259125944Sjoerg struct sockaddr_in *si; 259225944Sjoerg u_long ssrc, ddst; 259325944Sjoerg 259425944Sjoerg ssrc = ddst = 0L; 259525944Sjoerg /* 259625944Sjoerg * Pick the first AF_INET address from the list, 259725944Sjoerg * aliases don't make any sense on a p2p link anyway. 259825944Sjoerg */ 259925944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 260025944Sjoerg ifa; 260125944Sjoerg ifa = ifa->ifa_link.tqe_next) 260225944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 260325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 260425944Sjoerg if (si) 260525944Sjoerg break; 260625944Sjoerg } 260725944Sjoerg if (ifa) { 260825944Sjoerg if (si && si->sin_addr.s_addr) 260925944Sjoerg ssrc = si->sin_addr.s_addr; 261025944Sjoerg 261125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 261225944Sjoerg if (si && si->sin_addr.s_addr) 261325944Sjoerg ddst = si->sin_addr.s_addr; 261425944Sjoerg } 261525944Sjoerg 261625944Sjoerg if (dst) *dst = ntohl(ddst); 261725944Sjoerg if (src) *src = ntohl(ssrc); 261825944Sjoerg} 261925944Sjoerg 262025944Sjoerg/* 262125944Sjoerg * Set my IP address. Must be called at splimp. 262225944Sjoerg */ 262325944Sjoergstatic void 262425944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 262525944Sjoerg{ 262625944Sjoerg struct ifnet *ifp = &sp->pp_if; 262725944Sjoerg struct ifaddr *ifa; 262825944Sjoerg struct sockaddr_in *si; 262925944Sjoerg u_long ssrc, ddst; 263025944Sjoerg 263125944Sjoerg /* 263225944Sjoerg * Pick the first AF_INET address from the list, 263325944Sjoerg * aliases don't make any sense on a p2p link anyway. 263425944Sjoerg */ 263525944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 263625944Sjoerg ifa; 263725944Sjoerg ifa = ifa->ifa_link.tqe_next) 263825944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 263925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 264025944Sjoerg if (si) 264125944Sjoerg break; 264225944Sjoerg } 264325944Sjoerg if (ifa && si) 264425944Sjoerg si->sin_addr.s_addr = htonl(src); 264525944Sjoerg} 264625944Sjoerg 264725706Sjoergstatic const char * 264825944Sjoergsppp_cp_type_name(u_char type) 26494910Swollman{ 265025706Sjoerg static char buf [12]; 26514910Swollman switch (type) { 265225944Sjoerg case CONF_REQ: return ("conf-req"); 265325944Sjoerg case CONF_ACK: return ("conf-ack"); 265425944Sjoerg case CONF_NAK: return ("conf-nak"); 265525944Sjoerg case CONF_REJ: return ("conf-rej"); 265625944Sjoerg case TERM_REQ: return ("term-req"); 265725944Sjoerg case TERM_ACK: return ("term-ack"); 265825944Sjoerg case CODE_REJ: return ("code-rej"); 265925944Sjoerg case PROTO_REJ: return ("proto-rej"); 266025944Sjoerg case ECHO_REQ: return ("echo-req"); 266125944Sjoerg case ECHO_REPLY: return ("echo-reply"); 266225944Sjoerg case DISC_REQ: return ("discard-req"); 26634910Swollman } 266425706Sjoerg sprintf (buf, "0x%x", type); 26654910Swollman return (buf); 26664910Swollman} 26674910Swollman 266825706Sjoergstatic const char * 266925944Sjoergsppp_lcp_opt_name(u_char opt) 26704910Swollman{ 267125706Sjoerg static char buf [12]; 267225944Sjoerg switch (opt) { 267325944Sjoerg case LCP_OPT_MRU: return ("mru"); 267425944Sjoerg case LCP_OPT_ASYNC_MAP: return ("async-map"); 267525944Sjoerg case LCP_OPT_AUTH_PROTO: return ("auth-proto"); 267625944Sjoerg case LCP_OPT_QUAL_PROTO: return ("qual-proto"); 267725944Sjoerg case LCP_OPT_MAGIC: return ("magic"); 267825944Sjoerg case LCP_OPT_PROTO_COMP: return ("proto-comp"); 267925944Sjoerg case LCP_OPT_ADDR_COMP: return ("addr-comp"); 26804910Swollman } 268125944Sjoerg sprintf (buf, "0x%x", opt); 26824910Swollman return (buf); 26834910Swollman} 26844910Swollman 268525944Sjoergstatic const char * 268625944Sjoergsppp_ipcp_opt_name(u_char opt) 268725944Sjoerg{ 268825944Sjoerg static char buf [12]; 268925944Sjoerg switch (opt) { 269025944Sjoerg case IPCP_OPT_ADDRESSES: return ("addresses"); 269125944Sjoerg case IPCP_OPT_COMPRESSION: return ("compression"); 269225944Sjoerg case IPCP_OPT_ADDRESS: return ("address"); 269325944Sjoerg } 269425944Sjoerg sprintf (buf, "0x%x", opt); 269525944Sjoerg return (buf); 269625944Sjoerg} 269725944Sjoerg 269825944Sjoergstatic const char * 269925944Sjoergsppp_state_name(int state) 270025944Sjoerg{ 270125944Sjoerg switch (state) { 270225944Sjoerg case STATE_INITIAL: return "initial"; 270325944Sjoerg case STATE_STARTING: return "starting"; 270425944Sjoerg case STATE_CLOSED: return "closed"; 270525944Sjoerg case STATE_STOPPED: return "stopped"; 270625944Sjoerg case STATE_CLOSING: return "closing"; 270725944Sjoerg case STATE_STOPPING: return "stopping"; 270825944Sjoerg case STATE_REQ_SENT: return "req-sent"; 270925944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 271025944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 271125944Sjoerg case STATE_OPENED: return "opened"; 271225944Sjoerg } 271325944Sjoerg return "illegal"; 271425944Sjoerg} 271525944Sjoerg 271625944Sjoergstatic const char * 271725944Sjoergsppp_phase_name(enum ppp_phase phase) 271825944Sjoerg{ 271925944Sjoerg switch (phase) { 272025944Sjoerg case PHASE_DEAD: return "dead"; 272125944Sjoerg case PHASE_ESTABLISH: return "establish"; 272225944Sjoerg case PHASE_TERMINATE: return "terminate"; 272325944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 272425944Sjoerg case PHASE_NETWORK: return "network"; 272525944Sjoerg } 272625944Sjoerg return "illegal"; 272725944Sjoerg} 272825944Sjoerg 272925944Sjoergstatic const char * 273025944Sjoergsppp_proto_name(u_short proto) 273125944Sjoerg{ 273225944Sjoerg static char buf[12]; 273325944Sjoerg switch (proto) { 273425944Sjoerg case PPP_LCP: return "lcp"; 273525944Sjoerg case PPP_IPCP: return "ipcp"; 273625944Sjoerg } 273725944Sjoerg sprintf(buf, "0x%x", (unsigned)proto); 273825944Sjoerg return buf; 273925944Sjoerg} 274025944Sjoerg 274112820Sphkstatic void 274225706Sjoergsppp_print_bytes(u_char *p, u_short len) 27434910Swollman{ 274425706Sjoerg addlog(" %x", *p++); 27454910Swollman while (--len > 0) 274625706Sjoerg addlog("-%x", *p++); 27474910Swollman} 274825944Sjoerg 274925944Sjoerg/* 275025944Sjoerg * This file is large. Tell emacs to highlight it nevertheless. 275125944Sjoerg * 275225944Sjoerg * Local Variables: 275325944Sjoerg * hilit-auto-highlight-maxout: 100000 275425944Sjoerg * End: 275525944Sjoerg */ 2756