if_spppsubr.c revision 33181
14910Swollman/* 24910Swollman * Synchronous PPP/Cisco link level subroutines. 34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes. 44910Swollman * 530300Sjoerg * Copyright (C) 1994-1996 Cronyx Engineering 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 * 1830300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 1916288Sgpalmer * 2033181Seivind * $Id: if_spppsubr.c,v 1.31 1998/01/08 23:41:31 eivind Exp $ 214910Swollman */ 224910Swollman 2332350Seivind#include "opt_inet.h" 2431742Seivind#include "opt_ipx.h" 2531742Seivind 264910Swollman#include <sys/param.h> 274952Sbde#include <sys/systm.h> 284952Sbde#include <sys/kernel.h> 2924204Sbde#include <sys/sockio.h> 304910Swollman#include <sys/socket.h> 3125706Sjoerg#include <sys/syslog.h> 3229024Sbde#include <sys/malloc.h> 334910Swollman#include <sys/mbuf.h> 3430300Sjoerg#include <sys/md5.h> 354910Swollman 364910Swollman#include <net/if.h> 374910Swollman#include <net/netisr.h> 384910Swollman#include <net/if_types.h> 394910Swollman 4030300Sjoerg#include <machine/stdarg.h> 4130300Sjoerg 424910Swollman#ifdef INET 434910Swollman#include <netinet/in.h> 444910Swollman#include <netinet/in_systm.h> 454910Swollman#include <netinet/in_var.h> 464910Swollman#include <netinet/ip.h> 474910Swollman#include <netinet/tcp.h> 484910Swollman#include <netinet/if_ether.h> 4932350Seivind#else 5032350Seivind#error Huh? sppp without INET? 514910Swollman#endif 524910Swollman 5311819Sjulian#ifdef IPX 5411819Sjulian#include <netipx/ipx.h> 5511819Sjulian#include <netipx/ipx_if.h> 5611819Sjulian#endif 5711819Sjulian 584910Swollman#ifdef NS 594910Swollman#include <netns/ns.h> 604910Swollman#include <netns/ns_if.h> 614910Swollman#endif 624910Swollman 634910Swollman#ifdef ISO 644910Swollman#include <netiso/argo_debug.h> 654910Swollman#include <netiso/iso.h> 664910Swollman#include <netiso/iso_var.h> 674910Swollman#include <netiso/iso_snpac.h> 684910Swollman#endif 694910Swollman 704910Swollman#include <net/if_sppp.h> 714910Swollman 724910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 734910Swollman 7425944Sjoerg/* 7525944Sjoerg * Interface flags that can be set in an ifconfig command. 7625944Sjoerg * 7725955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 7825944Sjoerg * as being administrative openable, but won't be opened to begin 7925944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 8025944Sjoerg * -link1 will cause the administrative open of the LCP layer. 8125955Sjoerg * 8225955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 8325955Sjoerg * arrive to be sent. 8430300Sjoerg * 8530300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 8630300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 8730300Sjoerg * like 8830300Sjoerg * 8930300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 9030300Sjoerg * 9130300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 9230300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 9325944Sjoerg */ 9425944Sjoerg 9525955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 9625955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 9725944Sjoerg 9830300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 9930300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 10030300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 10130300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 10230300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 10330300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 10430300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 10530300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 10630300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 10730300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1084910Swollman 10925944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 11025944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 11125944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 11225944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 11325944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 11425944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 11525944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 11625944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 11725944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 11825944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 11925944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1204910Swollman 12130300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 12230300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 12330300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 12430300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 12530300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 12630300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 12730300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 12830300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1294910Swollman 13025944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 13125944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 13225944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1334910Swollman 13430300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 13530300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 13630300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1374910Swollman 13830300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 13930300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 14030300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 14130300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 14230300Sjoerg 14330300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 14430300Sjoerg 14530300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 14630300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 14730300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 14830300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 14930300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 15030300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 15130300Sjoerg 15225944Sjoerg/* states are named and numbered according to RFC 1661 */ 15325944Sjoerg#define STATE_INITIAL 0 15425944Sjoerg#define STATE_STARTING 1 15525944Sjoerg#define STATE_CLOSED 2 15625944Sjoerg#define STATE_STOPPED 3 15725944Sjoerg#define STATE_CLOSING 4 15825944Sjoerg#define STATE_STOPPING 5 15925944Sjoerg#define STATE_REQ_SENT 6 16025944Sjoerg#define STATE_ACK_RCVD 7 16125944Sjoerg#define STATE_ACK_SENT 8 16225944Sjoerg#define STATE_OPENED 9 16325944Sjoerg 1644910Swollmanstruct ppp_header { 16511189Sjkh u_char address; 16611189Sjkh u_char control; 16711189Sjkh u_short protocol; 1684910Swollman}; 1694910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1704910Swollman 1714910Swollmanstruct lcp_header { 17211189Sjkh u_char type; 17311189Sjkh u_char ident; 17411189Sjkh u_short len; 1754910Swollman}; 1764910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1774910Swollman 1784910Swollmanstruct cisco_packet { 17911189Sjkh u_long type; 18011189Sjkh u_long par1; 18111189Sjkh u_long par2; 18211189Sjkh u_short rel; 18311189Sjkh u_short time0; 18411189Sjkh u_short time1; 1854910Swollman}; 1864910Swollman#define CISCO_PACKET_LEN 18 1874910Swollman 18825944Sjoerg/* 18925944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 19025944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 19125944Sjoerg * case you can't make sense out of these abbreviation; it will also 19225944Sjoerg * explain the semantics related to the various events and actions. 19325944Sjoerg */ 19425944Sjoergstruct cp { 19525944Sjoerg u_short proto; /* PPP control protocol number */ 19625944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 19725944Sjoerg u_char flags; 19825944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 19925944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 20025944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 20125944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 20225944Sjoerg const char *name; /* name of this control protocol */ 20325944Sjoerg /* event handlers */ 20425944Sjoerg void (*Up)(struct sppp *sp); 20525944Sjoerg void (*Down)(struct sppp *sp); 20625944Sjoerg void (*Open)(struct sppp *sp); 20725944Sjoerg void (*Close)(struct sppp *sp); 20825944Sjoerg void (*TO)(void *sp); 20925944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 21025944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 21125944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 21225944Sjoerg /* actions */ 21325944Sjoerg void (*tlu)(struct sppp *sp); 21425944Sjoerg void (*tld)(struct sppp *sp); 21525944Sjoerg void (*tls)(struct sppp *sp); 21625944Sjoerg void (*tlf)(struct sppp *sp); 21725944Sjoerg void (*scr)(struct sppp *sp); 21825944Sjoerg}; 21925944Sjoerg 22012820Sphkstatic struct sppp *spppq; 22130300Sjoergstatic struct callout_handle keepalive_ch; 2224910Swollman 2234910Swollman/* 2244910Swollman * The following disgusting hack gets around the problem that IP TOS 2254910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2264910Swollman * priority queue. To decide if traffic is interactive, we check that 2274910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 22830300Sjoerg * 22930300Sjoerg * XXX is this really still necessary? - joerg - 2304910Swollman */ 23111189Sjkhstatic u_short interactive_ports[8] = { 2324910Swollman 0, 513, 0, 0, 2334910Swollman 0, 21, 0, 23, 2344910Swollman}; 2354910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2364910Swollman 23725944Sjoerg/* almost every function needs these */ 23825944Sjoerg#define STDDCL \ 23925944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 24025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 24111189Sjkh 24230300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 24325944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2444910Swollman 24525944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 24625944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 24725944Sjoerg 24825944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 24925944Sjoerg struct mbuf *m); 25025944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 25125944Sjoerg u_char ident, u_short len, void *data); 25225944Sjoergstatic void sppp_cp_timeout(void *arg); 25325944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 25425944Sjoerg int newstate); 25530300Sjoergstatic void sppp_auth_send(const struct cp *cp, 25630300Sjoerg struct sppp *sp, u_char type, u_char id, 25730300Sjoerg ...); 25825944Sjoerg 25925944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 26025944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 26125944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 26225944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 26325944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 26425944Sjoerg 26530300Sjoergstatic void sppp_null(struct sppp *sp); 26630300Sjoerg 26725944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 26825944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 26925944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 27025944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 27125944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 27225944Sjoergstatic void sppp_lcp_TO(void *sp); 27325944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 27425944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 27525944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 27625944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 27725944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 27825944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 27925944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 28025944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 28130300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 28230300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 28325944Sjoerg 28425944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 28525944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 28625944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 28725944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 28825944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 28925944Sjoergstatic void sppp_ipcp_TO(void *sp); 29025944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 29125944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 29225944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 29325944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 29425944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 29525944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 29625944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 29725944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 29825944Sjoerg 29930300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 30030300Sjoergstatic void sppp_pap_init(struct sppp *sp); 30130300Sjoergstatic void sppp_pap_open(struct sppp *sp); 30230300Sjoergstatic void sppp_pap_close(struct sppp *sp); 30330300Sjoergstatic void sppp_pap_TO(void *sp); 30430300Sjoergstatic void sppp_pap_my_TO(void *sp); 30530300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 30630300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 30730300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 30830300Sjoerg 30930300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 31030300Sjoergstatic void sppp_chap_init(struct sppp *sp); 31130300Sjoergstatic void sppp_chap_open(struct sppp *sp); 31230300Sjoergstatic void sppp_chap_close(struct sppp *sp); 31330300Sjoergstatic void sppp_chap_TO(void *sp); 31430300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 31530300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 31630300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 31730300Sjoerg 31830300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 31925944Sjoergstatic const char *sppp_cp_type_name(u_char type); 32030300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 32130300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 32225944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 32325944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 32425944Sjoergstatic const char *sppp_proto_name(u_short proto); 32530300Sjoergstatic const char *sppp_state_name(int state); 32630300Sjoergstatic int sppp_params(struct sppp *sp, int cmd, void *data); 32730300Sjoergstatic int sppp_strnlen(u_char *p, int max); 32830300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 32930300Sjoerg u_long *srcmask); 33025944Sjoergstatic void sppp_keepalive(void *dummy); 33130300Sjoergstatic void sppp_phase_network(struct sppp *sp); 33230300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 33330300Sjoergstatic void sppp_print_string(const char *p, u_short len); 33425944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 33525944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 33625944Sjoerg 33725944Sjoerg/* our control protocol descriptors */ 33833181Seivindstatic const struct cp lcp = { 33925944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 34025944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 34125944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 34225944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 34325944Sjoerg sppp_lcp_scr 34425944Sjoerg}; 34525944Sjoerg 34633181Seivindstatic const struct cp ipcp = { 34725944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 34825944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 34925944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 35025944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 35125944Sjoerg sppp_ipcp_scr 35225944Sjoerg}; 35325944Sjoerg 35433181Seivindstatic const struct cp pap = { 35530300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 35630300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 35730300Sjoerg sppp_pap_TO, 0, 0, 0, 35830300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 35930300Sjoerg sppp_pap_scr 36030300Sjoerg}; 36130300Sjoerg 36233181Seivindstatic const struct cp chap = { 36330300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 36430300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 36530300Sjoerg sppp_chap_TO, 0, 0, 0, 36630300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 36730300Sjoerg sppp_chap_scr 36830300Sjoerg}; 36930300Sjoerg 37033181Seivindstatic const struct cp *cps[IDX_COUNT] = { 37125944Sjoerg &lcp, /* IDX_LCP */ 37225944Sjoerg &ipcp, /* IDX_IPCP */ 37330300Sjoerg &pap, /* IDX_PAP */ 37430300Sjoerg &chap, /* IDX_CHAP */ 37525944Sjoerg}; 37625944Sjoerg 37725944Sjoerg 37825944Sjoerg/* 37925944Sjoerg * Exported functions, comprising our interface to the lower layer. 3804910Swollman */ 3814910Swollman 3824910Swollman/* 3834910Swollman * Process the received packet. 3844910Swollman */ 38525706Sjoergvoid 38625706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 3874910Swollman{ 3884910Swollman struct ppp_header *h; 3894910Swollman struct ifqueue *inq = 0; 39011189Sjkh int s; 39125944Sjoerg struct sppp *sp = (struct sppp *)ifp; 39225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 3934910Swollman 3944910Swollman if (ifp->if_flags & IFF_UP) 3954910Swollman /* Count received bytes, add FCS and one flag */ 3964910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 3974910Swollman 3984910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 3994910Swollman /* Too small packet, drop it. */ 40025944Sjoerg if (debug) 40125706Sjoerg log(LOG_DEBUG, 40225706Sjoerg "%s%d: input packet is too small, %d bytes\n", 40325706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 40425944Sjoerg drop: 40525944Sjoerg ++ifp->if_ierrors; 40625944Sjoerg ++ifp->if_iqdrops; 4074910Swollman m_freem (m); 4084910Swollman return; 4094910Swollman } 4104910Swollman 4114910Swollman /* Get PPP header. */ 4124910Swollman h = mtod (m, struct ppp_header*); 4134910Swollman m_adj (m, PPP_HEADER_LEN); 4144910Swollman 4154910Swollman switch (h->address) { 4164910Swollman case PPP_ALLSTATIONS: 4174910Swollman if (h->control != PPP_UI) 4184910Swollman goto invalid; 41911189Sjkh if (sp->pp_flags & PP_CISCO) { 42025944Sjoerg if (debug) 42125706Sjoerg log(LOG_DEBUG, 42225706Sjoerg "%s%d: PPP packet in Cisco mode " 42325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 42425706Sjoerg ifp->if_name, ifp->if_unit, 42525706Sjoerg h->address, h->control, ntohs(h->protocol)); 42611189Sjkh goto drop; 42711189Sjkh } 4284910Swollman switch (ntohs (h->protocol)) { 4294910Swollman default: 43025944Sjoerg if (sp->state[IDX_LCP] == STATE_OPENED) 43125944Sjoerg sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 43211189Sjkh ++sp->pp_seq, m->m_pkthdr.len + 2, 4334910Swollman &h->protocol); 43425944Sjoerg if (debug) 43525706Sjoerg log(LOG_DEBUG, 43625706Sjoerg "%s%d: invalid input protocol " 43725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 43825706Sjoerg ifp->if_name, ifp->if_unit, 43925706Sjoerg h->address, h->control, ntohs(h->protocol)); 4404910Swollman ++ifp->if_noproto; 4414910Swollman goto drop; 4424910Swollman case PPP_LCP: 44330300Sjoerg sppp_cp_input(&lcp, sp, m); 4444910Swollman m_freem (m); 4454910Swollman return; 44630300Sjoerg case PPP_PAP: 44730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 44830300Sjoerg sppp_pap_input(sp, m); 44930300Sjoerg m_freem (m); 45030300Sjoerg return; 45130300Sjoerg case PPP_CHAP: 45230300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 45330300Sjoerg sppp_chap_input(sp, m); 45430300Sjoerg m_freem (m); 45530300Sjoerg return; 4564910Swollman#ifdef INET 4574910Swollman case PPP_IPCP: 45825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 45930300Sjoerg sppp_cp_input(&ipcp, sp, m); 4604910Swollman m_freem (m); 4614910Swollman return; 4624910Swollman case PPP_IP: 46325944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 4644910Swollman schednetisr (NETISR_IP); 4654910Swollman inq = &ipintrq; 4664910Swollman } 4674910Swollman break; 4684910Swollman#endif 46912495Speter#ifdef IPX 47012495Speter case PPP_IPX: 47112495Speter /* IPX IPXCP not implemented yet */ 47225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 47312495Speter schednetisr (NETISR_IPX); 47412495Speter inq = &ipxintrq; 47512495Speter } 47612495Speter break; 47712495Speter#endif 4784910Swollman#ifdef NS 4794910Swollman case PPP_XNS: 4804910Swollman /* XNS IDPCP not implemented yet */ 48125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 4824910Swollman schednetisr (NETISR_NS); 4834910Swollman inq = &nsintrq; 4844910Swollman } 4854910Swollman break; 4864910Swollman#endif 4874910Swollman#ifdef ISO 4884910Swollman case PPP_ISO: 4894910Swollman /* OSI NLCP not implemented yet */ 49025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 4914910Swollman schednetisr (NETISR_ISO); 4924910Swollman inq = &clnlintrq; 4934910Swollman } 4944910Swollman break; 4954910Swollman#endif 4964910Swollman } 4974910Swollman break; 4984910Swollman case CISCO_MULTICAST: 4994910Swollman case CISCO_UNICAST: 5004910Swollman /* Don't check the control field here (RFC 1547). */ 50111189Sjkh if (! (sp->pp_flags & PP_CISCO)) { 50225944Sjoerg if (debug) 50325706Sjoerg log(LOG_DEBUG, 50425706Sjoerg "%s%d: Cisco packet in PPP mode " 50525706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 50625706Sjoerg ifp->if_name, ifp->if_unit, 50725706Sjoerg h->address, h->control, ntohs(h->protocol)); 50811189Sjkh goto drop; 50911189Sjkh } 5104910Swollman switch (ntohs (h->protocol)) { 5114910Swollman default: 5124910Swollman ++ifp->if_noproto; 5134910Swollman goto invalid; 5144910Swollman case CISCO_KEEPALIVE: 5154910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5164910Swollman m_freem (m); 5174910Swollman return; 5184910Swollman#ifdef INET 5194910Swollman case ETHERTYPE_IP: 5204910Swollman schednetisr (NETISR_IP); 5214910Swollman inq = &ipintrq; 5224910Swollman break; 5234910Swollman#endif 52412495Speter#ifdef IPX 52512495Speter case ETHERTYPE_IPX: 52612495Speter schednetisr (NETISR_IPX); 52712495Speter inq = &ipxintrq; 52812495Speter break; 52912495Speter#endif 5304910Swollman#ifdef NS 5314910Swollman case ETHERTYPE_NS: 5324910Swollman schednetisr (NETISR_NS); 5334910Swollman inq = &nsintrq; 5344910Swollman break; 5354910Swollman#endif 5364910Swollman } 5374910Swollman break; 53825944Sjoerg default: /* Invalid PPP packet. */ 53925944Sjoerg invalid: 54025944Sjoerg if (debug) 54125944Sjoerg log(LOG_DEBUG, 54225944Sjoerg "%s%d: invalid input packet " 54325944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54425944Sjoerg ifp->if_name, ifp->if_unit, 54525944Sjoerg h->address, h->control, ntohs(h->protocol)); 54625944Sjoerg goto drop; 5474910Swollman } 5484910Swollman 5494910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 5504910Swollman goto drop; 5514910Swollman 5524910Swollman /* Check queue. */ 55325944Sjoerg s = splimp(); 5544910Swollman if (IF_QFULL (inq)) { 5554910Swollman /* Queue overflow. */ 55625944Sjoerg IF_DROP(inq); 55725944Sjoerg splx(s); 55825944Sjoerg if (debug) 55925706Sjoerg log(LOG_DEBUG, "%s%d: protocol queue overflow\n", 5604910Swollman ifp->if_name, ifp->if_unit); 5614910Swollman goto drop; 5624910Swollman } 56325944Sjoerg IF_ENQUEUE(inq, m); 56425944Sjoerg splx(s); 5654910Swollman} 5664910Swollman 5674910Swollman/* 5684910Swollman * Enqueue transmit packet. 5694910Swollman */ 57012820Sphkstatic int 57125706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 57225706Sjoerg struct sockaddr *dst, struct rtentry *rt) 5734910Swollman{ 5744910Swollman struct sppp *sp = (struct sppp*) ifp; 5754910Swollman struct ppp_header *h; 5764910Swollman struct ifqueue *ifq; 57725955Sjoerg int s, rv = 0; 5784910Swollman 57925944Sjoerg s = splimp(); 58025944Sjoerg 58125944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 58225944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 5834910Swollman m_freem (m); 5844910Swollman splx (s); 5854910Swollman return (ENETDOWN); 5864910Swollman } 5874910Swollman 58825944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 58925944Sjoerg /* 59025944Sjoerg * Interface is not yet running, but auto-dial. Need 59125944Sjoerg * to start LCP for it. 59225944Sjoerg */ 59325944Sjoerg ifp->if_flags |= IFF_RUNNING; 59425944Sjoerg splx(s); 59525944Sjoerg lcp.Open(sp); 59625944Sjoerg s = splimp(); 59725944Sjoerg } 59825944Sjoerg 5994910Swollman ifq = &ifp->if_snd; 6004910Swollman#ifdef INET 6014910Swollman /* 6024910Swollman * Put low delay, telnet, rlogin and ftp control packets 6034910Swollman * in front of the queue. 6044910Swollman */ 60512436Speter if (dst->sa_family == AF_INET) { 60612436Speter struct ip *ip = mtod (m, struct ip*); 60712436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6084910Swollman 60912436Speter if (! IF_QFULL (&sp->pp_fastq) && 61012436Speter ((ip->ip_tos & IPTOS_LOWDELAY) || 61112436Speter ip->ip_p == IPPROTO_TCP && 61212436Speter m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) && 61312436Speter (INTERACTIVE (ntohs (tcp->th_sport)) || 61412436Speter INTERACTIVE (ntohs (tcp->th_dport))))) 61512436Speter ifq = &sp->pp_fastq; 6164910Swollman } 6174910Swollman#endif 6184910Swollman 6194910Swollman /* 6204910Swollman * Prepend general data packet PPP header. For now, IP only. 6214910Swollman */ 6224910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 6234910Swollman if (! m) { 6244910Swollman if (ifp->if_flags & IFF_DEBUG) 62525706Sjoerg log(LOG_DEBUG, "%s%d: no memory for transmit header\n", 6264910Swollman ifp->if_name, ifp->if_unit); 62725944Sjoerg ++ifp->if_oerrors; 6284910Swollman splx (s); 6294910Swollman return (ENOBUFS); 6304910Swollman } 6314910Swollman h = mtod (m, struct ppp_header*); 6324910Swollman if (sp->pp_flags & PP_CISCO) { 63328088Skjc h->address = CISCO_UNICAST; /* unicast address */ 6344910Swollman h->control = 0; 6354910Swollman } else { 6364910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 6374910Swollman h->control = PPP_UI; /* Unnumbered Info */ 6384910Swollman } 6394910Swollman 6404910Swollman switch (dst->sa_family) { 6414910Swollman#ifdef INET 6424910Swollman case AF_INET: /* Internet Protocol */ 64311189Sjkh if (sp->pp_flags & PP_CISCO) 64411189Sjkh h->protocol = htons (ETHERTYPE_IP); 64511189Sjkh else { 64625955Sjoerg /* 64725955Sjoerg * Don't choke with an ENETDOWN early. It's 64825955Sjoerg * possible that we just started dialing out, 64925955Sjoerg * so don't drop the packet immediately. If 65025955Sjoerg * we notice that we run out of buffer space 65125955Sjoerg * below, we will however remember that we are 65225955Sjoerg * not ready to carry IP packets, and return 65325955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 65425955Sjoerg */ 65525955Sjoerg h->protocol = htons(PPP_IP); 65625955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 65725955Sjoerg rv = ENETDOWN; 65811189Sjkh } 6594910Swollman break; 6604910Swollman#endif 6614910Swollman#ifdef NS 6624910Swollman case AF_NS: /* Xerox NS Protocol */ 6634910Swollman h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 6644910Swollman ETHERTYPE_NS : PPP_XNS); 6654910Swollman break; 6664910Swollman#endif 66711819Sjulian#ifdef IPX 66812495Speter case AF_IPX: /* Novell IPX Protocol */ 66911819Sjulian h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 67012495Speter ETHERTYPE_IPX : PPP_IPX); 67111819Sjulian break; 67211819Sjulian#endif 6734910Swollman#ifdef ISO 6744910Swollman case AF_ISO: /* ISO OSI Protocol */ 6754910Swollman if (sp->pp_flags & PP_CISCO) 6764910Swollman goto nosupport; 6774910Swollman h->protocol = htons (PPP_ISO); 6784910Swollman break; 67912820Sphknosupport: 6804910Swollman#endif 6814910Swollman default: 6824910Swollman m_freem (m); 68325944Sjoerg ++ifp->if_oerrors; 6844910Swollman splx (s); 6854910Swollman return (EAFNOSUPPORT); 6864910Swollman } 6874910Swollman 6884910Swollman /* 6894910Swollman * Queue message on interface, and start output if interface 6904910Swollman * not yet active. 6914910Swollman */ 6924910Swollman if (IF_QFULL (ifq)) { 6934910Swollman IF_DROP (&ifp->if_snd); 6944910Swollman m_freem (m); 69525944Sjoerg ++ifp->if_oerrors; 6964910Swollman splx (s); 69725955Sjoerg return (rv? rv: ENOBUFS); 6984910Swollman } 6994910Swollman IF_ENQUEUE (ifq, m); 7004910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 7014910Swollman (*ifp->if_start) (ifp); 7024910Swollman 7034910Swollman /* 7044910Swollman * Count output packets and bytes. 7054910Swollman * The packet length includes header, FCS and 1 flag, 7064910Swollman * according to RFC 1333. 7074910Swollman */ 7084910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 7094910Swollman splx (s); 7104910Swollman return (0); 7114910Swollman} 7124910Swollman 71325706Sjoergvoid 71425706Sjoergsppp_attach(struct ifnet *ifp) 7154910Swollman{ 7164910Swollman struct sppp *sp = (struct sppp*) ifp; 7174910Swollman 7184910Swollman /* Initialize keepalive handler. */ 7194910Swollman if (! spppq) 72030300Sjoerg keepalive_ch = timeout(sppp_keepalive, 0, hz * 10); 7214910Swollman 7224910Swollman /* Insert new entry into the keepalive list. */ 7234910Swollman sp->pp_next = spppq; 7244910Swollman spppq = sp; 7254910Swollman 7264910Swollman sp->pp_if.if_type = IFT_PPP; 7274910Swollman sp->pp_if.if_output = sppp_output; 7284910Swollman sp->pp_fastq.ifq_maxlen = 32; 72926018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 7304910Swollman sp->pp_loopcnt = 0; 7314910Swollman sp->pp_alivecnt = 0; 73211189Sjkh sp->pp_seq = 0; 7334910Swollman sp->pp_rseq = 0; 73425944Sjoerg sp->pp_phase = PHASE_DEAD; 73525944Sjoerg sp->pp_up = lcp.Up; 73625944Sjoerg sp->pp_down = lcp.Down; 73725944Sjoerg 73825944Sjoerg sppp_lcp_init(sp); 73925944Sjoerg sppp_ipcp_init(sp); 74030300Sjoerg sppp_pap_init(sp); 74130300Sjoerg sppp_chap_init(sp); 7424910Swollman} 7434910Swollman 74430300Sjoergvoid 74525706Sjoergsppp_detach(struct ifnet *ifp) 7464910Swollman{ 7474910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 74825944Sjoerg int i; 7494910Swollman 7504910Swollman /* Remove the entry from the keepalive list. */ 7514910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 7524910Swollman if (p == sp) { 7534910Swollman *q = p->pp_next; 7544910Swollman break; 7554910Swollman } 7564910Swollman 7574910Swollman /* Stop keepalive handler. */ 7584910Swollman if (! spppq) 75930300Sjoerg untimeout(sppp_keepalive, 0, keepalive_ch); 76025944Sjoerg 76125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 76229681Sgibbs untimeout((cps[i])->TO, (void *)sp, sp->ch[i]); 76330300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 7644910Swollman} 7654910Swollman 7664910Swollman/* 7674910Swollman * Flush the interface output queue. 7684910Swollman */ 76925706Sjoergvoid 77025706Sjoergsppp_flush(struct ifnet *ifp) 7714910Swollman{ 7724910Swollman struct sppp *sp = (struct sppp*) ifp; 7734910Swollman 77425944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 77525944Sjoerg sppp_qflush (&sp->pp_fastq); 77626018Sjoerg sppp_qflush (&sp->pp_cpq); 7774910Swollman} 7784910Swollman 7794910Swollman/* 78011189Sjkh * Check if the output queue is empty. 78111189Sjkh */ 78212820Sphkint 78325706Sjoergsppp_isempty(struct ifnet *ifp) 78411189Sjkh{ 78511189Sjkh struct sppp *sp = (struct sppp*) ifp; 78625944Sjoerg int empty, s; 78711189Sjkh 78825944Sjoerg s = splimp(); 78926018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 79026018Sjoerg !sp->pp_if.if_snd.ifq_head; 79125944Sjoerg splx(s); 79211189Sjkh return (empty); 79311189Sjkh} 79411189Sjkh 79511189Sjkh/* 7964910Swollman * Get next packet to send. 7974910Swollman */ 79825706Sjoergstruct mbuf * 79925706Sjoergsppp_dequeue(struct ifnet *ifp) 8004910Swollman{ 8014910Swollman struct sppp *sp = (struct sppp*) ifp; 8024910Swollman struct mbuf *m; 80325944Sjoerg int s; 8044910Swollman 80525944Sjoerg s = splimp(); 80626018Sjoerg /* 80730300Sjoerg * Process only the control protocol queue until we have at 80830300Sjoerg * least one NCP open. 80926018Sjoerg * 81026018Sjoerg * Do always serve all three queues in Cisco mode. 81126018Sjoerg */ 81226018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 81326018Sjoerg if (m == NULL && 81430300Sjoerg (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { 81526018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 81626018Sjoerg if (m == NULL) 81726018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 81826018Sjoerg } 81926018Sjoerg splx(s); 82026018Sjoerg return m; 8214910Swollman} 8224910Swollman 8234910Swollman/* 82430300Sjoerg * Pick the next packet, do not remove it from the queue. 82530300Sjoerg */ 82630300Sjoergstruct mbuf * 82730300Sjoergsppp_pick(struct ifnet *ifp) 82830300Sjoerg{ 82930300Sjoerg struct sppp *sp = (struct sppp*)ifp; 83030300Sjoerg struct mbuf *m; 83130300Sjoerg int s; 83230300Sjoerg 83330300Sjoerg s= splimp (); 83430300Sjoerg 83530300Sjoerg m = sp->pp_cpq.ifq_head; 83630300Sjoerg if (m == NULL && 83730300Sjoerg (sp->pp_phase == PHASE_NETWORK || 83830300Sjoerg (sp->pp_flags & PP_CISCO) != 0)) 83930300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 84030300Sjoerg m = sp->pp_if.if_snd.ifq_head; 84130300Sjoerg splx (s); 84230300Sjoerg return (m); 84330300Sjoerg} 84430300Sjoerg 84530300Sjoerg/* 84625944Sjoerg * Process an ioctl request. Called on low priority level. 8474910Swollman */ 84825944Sjoergint 84925944Sjoergsppp_ioctl(struct ifnet *ifp, int cmd, void *data) 8504910Swollman{ 85125944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 85225944Sjoerg struct sppp *sp = (struct sppp*) ifp; 85330300Sjoerg int s, rv, going_up, going_down, newmode; 8544910Swollman 85525944Sjoerg s = splimp(); 85630300Sjoerg rv = 0; 85725944Sjoerg switch (cmd) { 85825944Sjoerg case SIOCAIFADDR: 85925944Sjoerg case SIOCSIFDSTADDR: 86025944Sjoerg break; 8614910Swollman 86225944Sjoerg case SIOCSIFADDR: 86325944Sjoerg if_up(ifp); 86425944Sjoerg /* fall through... */ 86511189Sjkh 86625944Sjoerg case SIOCSIFFLAGS: 86725944Sjoerg going_up = ifp->if_flags & IFF_UP && 86825944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 86925944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 87025944Sjoerg ifp->if_flags & IFF_RUNNING; 87125944Sjoerg newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); 87225944Sjoerg if (newmode == (IFF_AUTO | IFF_PASSIVE)) { 87325944Sjoerg /* sanity */ 87425944Sjoerg newmode = IFF_PASSIVE; 87525944Sjoerg ifp->if_flags &= ~IFF_AUTO; 8764910Swollman } 8774910Swollman 87825944Sjoerg if (going_up || going_down) 87925944Sjoerg lcp.Close(sp); 88025944Sjoerg if (going_up && newmode == 0) { 88125944Sjoerg /* neither auto-dial nor passive */ 88225944Sjoerg ifp->if_flags |= IFF_RUNNING; 88325944Sjoerg if (!(sp->pp_flags & PP_CISCO)) 88425944Sjoerg lcp.Open(sp); 88526018Sjoerg } else if (going_down) { 88626018Sjoerg sppp_flush(ifp); 88725944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 88826018Sjoerg } 8894910Swollman 8904910Swollman break; 89111189Sjkh 89225944Sjoerg#ifdef SIOCSIFMTU 89325944Sjoerg#ifndef ifr_mtu 89425944Sjoerg#define ifr_mtu ifr_metric 89525944Sjoerg#endif 89625944Sjoerg case SIOCSIFMTU: 89725944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 89825944Sjoerg return (EINVAL); 89925944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 9004910Swollman break; 90125944Sjoerg#endif 90225944Sjoerg#ifdef SLIOCSETMTU 90325944Sjoerg case SLIOCSETMTU: 90425944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 90525944Sjoerg return (EINVAL); 90625944Sjoerg ifp->if_mtu = *(short*)data; 9074910Swollman break; 90825944Sjoerg#endif 90925944Sjoerg#ifdef SIOCGIFMTU 91025944Sjoerg case SIOCGIFMTU: 91125944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 91211189Sjkh break; 91325944Sjoerg#endif 91425944Sjoerg#ifdef SLIOCGETMTU 91525944Sjoerg case SLIOCGETMTU: 91625944Sjoerg *(short*)data = ifp->if_mtu; 9174910Swollman break; 91825944Sjoerg#endif 91925944Sjoerg case SIOCADDMULTI: 92025944Sjoerg case SIOCDELMULTI: 9214910Swollman break; 92211189Sjkh 92330300Sjoerg case SIOCGIFGENERIC: 92430300Sjoerg case SIOCSIFGENERIC: 92530300Sjoerg rv = sppp_params(sp, cmd, data); 92630300Sjoerg break; 92730300Sjoerg 92825944Sjoerg default: 92930300Sjoerg rv = ENOTTY; 9304910Swollman } 93125944Sjoerg splx(s); 93230300Sjoerg return rv; 9334910Swollman} 9344910Swollman 93525944Sjoerg 93625944Sjoerg/* 93725944Sjoerg * Cisco framing implementation. 93825944Sjoerg */ 93925944Sjoerg 9404910Swollman/* 9414910Swollman * Handle incoming Cisco keepalive protocol packets. 9424910Swollman */ 94330300Sjoergstatic void 94425706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 9454910Swollman{ 94625944Sjoerg STDDCL; 9474910Swollman struct cisco_packet *h; 94830300Sjoerg u_long me, mymask; 9494910Swollman 95027929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 95125706Sjoerg if (debug) 95225706Sjoerg log(LOG_DEBUG, 95330300Sjoerg "%s%d: cisco invalid packet length: %d bytes\n", 95425706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 9554910Swollman return; 9564910Swollman } 9574910Swollman h = mtod (m, struct cisco_packet*); 95825706Sjoerg if (debug) 95925706Sjoerg log(LOG_DEBUG, 96025706Sjoerg "%s%d: cisco input: %d bytes " 96125706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 96225706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len, 96325706Sjoerg ntohl (h->type), h->par1, h->par2, h->rel, 96425706Sjoerg h->time0, h->time1); 9654910Swollman switch (ntohl (h->type)) { 9664910Swollman default: 96725706Sjoerg if (debug) 96830300Sjoerg addlog("%s%d: cisco unknown packet type: 0x%lx\n", 96925706Sjoerg ifp->if_name, ifp->if_unit, ntohl (h->type)); 9704910Swollman break; 9714910Swollman case CISCO_ADDR_REPLY: 9724910Swollman /* Reply on address request, ignore */ 9734910Swollman break; 9744910Swollman case CISCO_KEEPALIVE_REQ: 9754910Swollman sp->pp_alivecnt = 0; 9764910Swollman sp->pp_rseq = ntohl (h->par1); 9774910Swollman if (sp->pp_seq == sp->pp_rseq) { 9784910Swollman /* Local and remote sequence numbers are equal. 9794910Swollman * Probably, the line is in loopback mode. */ 98011189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 98111189Sjkh printf ("%s%d: loopback\n", 98211189Sjkh ifp->if_name, ifp->if_unit); 98311189Sjkh sp->pp_loopcnt = 0; 98411189Sjkh if (ifp->if_flags & IFF_UP) { 98511189Sjkh if_down (ifp); 98626018Sjoerg sppp_qflush (&sp->pp_cpq); 98711189Sjkh } 98811189Sjkh } 9894910Swollman ++sp->pp_loopcnt; 9904910Swollman 9914910Swollman /* Generate new local sequence number */ 9924910Swollman sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 99311189Sjkh break; 99411189Sjkh } 99530300Sjoerg sp->pp_loopcnt = 0; 99611189Sjkh if (! (ifp->if_flags & IFF_UP) && 99711189Sjkh (ifp->if_flags & IFF_RUNNING)) { 99830300Sjoerg if_up(ifp); 99911189Sjkh printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 100011189Sjkh } 10014910Swollman break; 10024910Swollman case CISCO_ADDR_REQ: 100330300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 100430300Sjoerg if (me != 0L) 100530300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 10064910Swollman break; 10074910Swollman } 10084910Swollman} 10094910Swollman 10104910Swollman/* 101125944Sjoerg * Send Cisco keepalive packet. 10124910Swollman */ 101312820Sphkstatic void 101425944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 101525944Sjoerg{ 101625944Sjoerg STDDCL; 101725944Sjoerg struct ppp_header *h; 101825944Sjoerg struct cisco_packet *ch; 101925944Sjoerg struct mbuf *m; 102025944Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 102125944Sjoerg 102225944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 102325944Sjoerg if (! m) 102425944Sjoerg return; 102525944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 102625944Sjoerg m->m_pkthdr.rcvif = 0; 102725944Sjoerg 102825944Sjoerg h = mtod (m, struct ppp_header*); 102925944Sjoerg h->address = CISCO_MULTICAST; 103025944Sjoerg h->control = 0; 103125944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 103225944Sjoerg 103325944Sjoerg ch = (struct cisco_packet*) (h + 1); 103425944Sjoerg ch->type = htonl (type); 103525944Sjoerg ch->par1 = htonl (par1); 103625944Sjoerg ch->par2 = htonl (par2); 103725944Sjoerg ch->rel = -1; 103825944Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 103925944Sjoerg ch->time1 = htons ((u_short) t); 104025944Sjoerg 104125944Sjoerg if (debug) 104225944Sjoerg log(LOG_DEBUG, 104325944Sjoerg "%s%d: cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 104425944Sjoerg ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1, 104525944Sjoerg ch->par2, ch->rel, ch->time0, ch->time1); 104625944Sjoerg 104726018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 104826018Sjoerg IF_DROP (&sp->pp_fastq); 104925944Sjoerg IF_DROP (&ifp->if_snd); 105025944Sjoerg m_freem (m); 105125944Sjoerg } else 105226018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 105325944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 105425944Sjoerg (*ifp->if_start) (ifp); 105525944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 105625944Sjoerg} 105725944Sjoerg 105825944Sjoerg/* 105925944Sjoerg * PPP protocol implementation. 106025944Sjoerg */ 106125944Sjoerg 106225944Sjoerg/* 106325944Sjoerg * Send PPP control protocol packet. 106425944Sjoerg */ 106525944Sjoergstatic void 106625706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 106725706Sjoerg u_char ident, u_short len, void *data) 10684910Swollman{ 106925944Sjoerg STDDCL; 10704910Swollman struct ppp_header *h; 10714910Swollman struct lcp_header *lh; 10724910Swollman struct mbuf *m; 10734910Swollman 10744910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 10754910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 10764910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 10774910Swollman if (! m) 10784910Swollman return; 10794910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 10804910Swollman m->m_pkthdr.rcvif = 0; 10814910Swollman 10824910Swollman h = mtod (m, struct ppp_header*); 10834910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 10844910Swollman h->control = PPP_UI; /* Unnumbered Info */ 10854910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 10864910Swollman 10874910Swollman lh = (struct lcp_header*) (h + 1); 10884910Swollman lh->type = type; 10894910Swollman lh->ident = ident; 10904910Swollman lh->len = htons (LCP_HEADER_LEN + len); 10914910Swollman if (len) 10924910Swollman bcopy (data, lh+1, len); 10934910Swollman 109425706Sjoerg if (debug) { 109525944Sjoerg log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d", 109625944Sjoerg ifp->if_name, ifp->if_unit, 109725944Sjoerg sppp_proto_name(proto), 109825944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 109925944Sjoerg ntohs (lh->len)); 11004910Swollman if (len) 110111189Sjkh sppp_print_bytes ((u_char*) (lh+1), len); 110225706Sjoerg addlog(">\n"); 11034910Swollman } 110426018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 110526018Sjoerg IF_DROP (&sp->pp_fastq); 11064910Swollman IF_DROP (&ifp->if_snd); 11074910Swollman m_freem (m); 110825944Sjoerg ++ifp->if_oerrors; 11094910Swollman } else 111026018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 11114910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 11124910Swollman (*ifp->if_start) (ifp); 11134910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 11144910Swollman} 11154910Swollman 11164910Swollman/* 111725944Sjoerg * Handle incoming PPP control protocol packets. 11184910Swollman */ 111912820Sphkstatic void 112025944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 11214910Swollman{ 112225944Sjoerg STDDCL; 112325944Sjoerg struct lcp_header *h; 112425944Sjoerg int len = m->m_pkthdr.len; 112525944Sjoerg int rv; 112625944Sjoerg u_char *p; 11274910Swollman 112825944Sjoerg if (len < 4) { 112925944Sjoerg if (debug) 113025944Sjoerg log(LOG_DEBUG, 113125944Sjoerg "%s%d: %s invalid packet length: %d bytes\n", 113225944Sjoerg ifp->if_name, ifp->if_unit, cp->name, len); 11334910Swollman return; 113425944Sjoerg } 113525944Sjoerg h = mtod (m, struct lcp_header*); 113625944Sjoerg if (debug) { 113725944Sjoerg log(LOG_DEBUG, 113825944Sjoerg "%s%d: %s input(%s): <%s id=0x%x len=%d", 113925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 114025944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 114125944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 114225944Sjoerg if (len > 4) 114325944Sjoerg sppp_print_bytes ((u_char*) (h+1), len-4); 114425944Sjoerg addlog(">\n"); 114525944Sjoerg } 114625944Sjoerg if (len > ntohs (h->len)) 114725944Sjoerg len = ntohs (h->len); 114830300Sjoerg p = (u_char *)(h + 1); 114925944Sjoerg switch (h->type) { 115025944Sjoerg case CONF_REQ: 115125944Sjoerg if (len < 4) { 115225944Sjoerg if (debug) 115325944Sjoerg addlog("%s%d: %s invalid conf-req length %d\n", 115425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 115525944Sjoerg len); 115625944Sjoerg ++ifp->if_ierrors; 115725944Sjoerg break; 115825944Sjoerg } 115930300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 116030300Sjoerg switch (sp->state[cp->protoidx]) { 116130300Sjoerg case STATE_CLOSING: 116230300Sjoerg case STATE_STOPPING: 116330300Sjoerg return; 116430300Sjoerg case STATE_CLOSED: 116530300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 116630300Sjoerg 0, 0); 116730300Sjoerg return; 116830300Sjoerg } 116925944Sjoerg rv = (cp->RCR)(sp, h, len); 117025944Sjoerg switch (sp->state[cp->protoidx]) { 117125944Sjoerg case STATE_OPENED: 117225944Sjoerg (cp->tld)(sp); 117325944Sjoerg (cp->scr)(sp); 117425944Sjoerg /* fall through... */ 117525944Sjoerg case STATE_ACK_SENT: 117625944Sjoerg case STATE_REQ_SENT: 117725944Sjoerg sppp_cp_change_state(cp, sp, rv? 117825944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 117925944Sjoerg break; 118025944Sjoerg case STATE_STOPPED: 118125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 118225944Sjoerg (cp->scr)(sp); 118325944Sjoerg sppp_cp_change_state(cp, sp, rv? 118425944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 118525944Sjoerg break; 118625944Sjoerg case STATE_ACK_RCVD: 118725944Sjoerg if (rv) { 118825944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 118925944Sjoerg if (debug) 119026077Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 119126077Sjoerg ifp->if_name, ifp->if_unit, 119226077Sjoerg cp->name); 119325944Sjoerg (cp->tlu)(sp); 119425944Sjoerg } else 119525944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 119625944Sjoerg break; 119725944Sjoerg default: 119825944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 119925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 120025944Sjoerg sppp_cp_type_name(h->type), 120125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 120225944Sjoerg ++ifp->if_ierrors; 120325944Sjoerg } 120425944Sjoerg break; 120525944Sjoerg case CONF_ACK: 120625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 120725944Sjoerg if (debug) 120825944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 120925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 121025944Sjoerg h->ident, sp->confid[cp->protoidx]); 121125944Sjoerg ++ifp->if_ierrors; 121225944Sjoerg break; 121325944Sjoerg } 121425944Sjoerg switch (sp->state[cp->protoidx]) { 121525944Sjoerg case STATE_CLOSED: 121625944Sjoerg case STATE_STOPPED: 121725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 121825944Sjoerg break; 121925944Sjoerg case STATE_CLOSING: 122025944Sjoerg case STATE_STOPPING: 122125944Sjoerg break; 122225944Sjoerg case STATE_REQ_SENT: 122325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 122425944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 122525944Sjoerg break; 122625944Sjoerg case STATE_OPENED: 122725944Sjoerg (cp->tld)(sp); 122825944Sjoerg /* fall through */ 122925944Sjoerg case STATE_ACK_RCVD: 123025944Sjoerg (cp->scr)(sp); 123125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 123225944Sjoerg break; 123325944Sjoerg case STATE_ACK_SENT: 123425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 123525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 123625944Sjoerg if (debug) 123730300Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 123825944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 123925944Sjoerg (cp->tlu)(sp); 124025944Sjoerg break; 124125944Sjoerg default: 124225944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 124325944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 124425944Sjoerg sppp_cp_type_name(h->type), 124525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 124625944Sjoerg ++ifp->if_ierrors; 124725944Sjoerg } 124825944Sjoerg break; 124925944Sjoerg case CONF_NAK: 125025944Sjoerg case CONF_REJ: 125125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 125225944Sjoerg if (debug) 125325944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 125425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 125525944Sjoerg h->ident, sp->confid[cp->protoidx]); 125625944Sjoerg ++ifp->if_ierrors; 125725944Sjoerg break; 125825944Sjoerg } 125925944Sjoerg if (h->type == CONF_NAK) 126025944Sjoerg (cp->RCN_nak)(sp, h, len); 126125944Sjoerg else /* CONF_REJ */ 126225944Sjoerg (cp->RCN_rej)(sp, h, len); 12634910Swollman 126425944Sjoerg switch (sp->state[cp->protoidx]) { 126525944Sjoerg case STATE_CLOSED: 126625944Sjoerg case STATE_STOPPED: 126725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 126825944Sjoerg break; 126925944Sjoerg case STATE_REQ_SENT: 127025944Sjoerg case STATE_ACK_SENT: 127125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 127225944Sjoerg (cp->scr)(sp); 127325944Sjoerg break; 127425944Sjoerg case STATE_OPENED: 127525944Sjoerg (cp->tld)(sp); 127625944Sjoerg /* fall through */ 127725944Sjoerg case STATE_ACK_RCVD: 127825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_SENT); 127925944Sjoerg (cp->scr)(sp); 128025944Sjoerg break; 128125944Sjoerg case STATE_CLOSING: 128225944Sjoerg case STATE_STOPPING: 128325944Sjoerg break; 128425944Sjoerg default: 128525944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 128625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 128725944Sjoerg sppp_cp_type_name(h->type), 128825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 128925944Sjoerg ++ifp->if_ierrors; 129025944Sjoerg } 129125944Sjoerg break; 12924910Swollman 129325944Sjoerg case TERM_REQ: 129425944Sjoerg switch (sp->state[cp->protoidx]) { 129525944Sjoerg case STATE_ACK_RCVD: 129625944Sjoerg case STATE_ACK_SENT: 129725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 129825944Sjoerg /* fall through */ 129925944Sjoerg case STATE_CLOSED: 130025944Sjoerg case STATE_STOPPED: 130125944Sjoerg case STATE_CLOSING: 130225944Sjoerg case STATE_STOPPING: 130325944Sjoerg case STATE_REQ_SENT: 130425944Sjoerg sta: 130525944Sjoerg /* Send Terminate-Ack packet. */ 130625944Sjoerg if (debug) 130725944Sjoerg log(LOG_DEBUG, "%s%d: %s send terminate-ack\n", 130825944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 130925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 131025944Sjoerg break; 131125944Sjoerg case STATE_OPENED: 131225944Sjoerg (cp->tld)(sp); 131325944Sjoerg sp->rst_counter[cp->protoidx] = 0; 131425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 131525944Sjoerg goto sta; 131625944Sjoerg break; 131725944Sjoerg default: 131825944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 131925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 132025944Sjoerg sppp_cp_type_name(h->type), 132125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 132225944Sjoerg ++ifp->if_ierrors; 132325944Sjoerg } 132425944Sjoerg break; 132525944Sjoerg case TERM_ACK: 132625944Sjoerg switch (sp->state[cp->protoidx]) { 132725944Sjoerg case STATE_CLOSED: 132825944Sjoerg case STATE_STOPPED: 132925944Sjoerg case STATE_REQ_SENT: 133025944Sjoerg case STATE_ACK_SENT: 133125944Sjoerg break; 133225944Sjoerg case STATE_CLOSING: 133325944Sjoerg (cp->tlf)(sp); 133425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 133525944Sjoerg break; 133625944Sjoerg case STATE_STOPPING: 133725944Sjoerg (cp->tlf)(sp); 133825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 133925944Sjoerg break; 134025944Sjoerg case STATE_ACK_RCVD: 134125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 134225944Sjoerg break; 134325944Sjoerg case STATE_OPENED: 134425944Sjoerg (cp->tld)(sp); 134525944Sjoerg (cp->scr)(sp); 134625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 134725944Sjoerg break; 134825944Sjoerg default: 134925944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 135025944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 135125944Sjoerg sppp_cp_type_name(h->type), 135225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 135325944Sjoerg ++ifp->if_ierrors; 135425944Sjoerg } 135525944Sjoerg break; 135625944Sjoerg case CODE_REJ: 135725944Sjoerg case PROTO_REJ: 135825944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 135930300Sjoerg log(LOG_INFO, 136030300Sjoerg "%s%d: %s: ignoring RXJ (%s) for proto 0x%x, " 136130300Sjoerg "danger will robinson\n", 136230300Sjoerg ifp->if_name, ifp->if_unit, cp->name, 136330300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 136425944Sjoerg switch (sp->state[cp->protoidx]) { 136525944Sjoerg case STATE_CLOSED: 136625944Sjoerg case STATE_STOPPED: 136725944Sjoerg case STATE_REQ_SENT: 136825944Sjoerg case STATE_ACK_SENT: 136925944Sjoerg case STATE_CLOSING: 137025944Sjoerg case STATE_STOPPING: 137125944Sjoerg case STATE_OPENED: 137225944Sjoerg break; 137325944Sjoerg case STATE_ACK_RCVD: 137425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 137525944Sjoerg break; 137625944Sjoerg default: 137725944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 137825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 137925944Sjoerg sppp_cp_type_name(h->type), 138025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 138125944Sjoerg ++ifp->if_ierrors; 138225944Sjoerg } 138325944Sjoerg break; 138425944Sjoerg case DISC_REQ: 138525944Sjoerg if (cp->proto != PPP_LCP) 138625944Sjoerg goto illegal; 138725944Sjoerg /* Discard the packet. */ 138825944Sjoerg break; 138925944Sjoerg case ECHO_REQ: 139025944Sjoerg if (cp->proto != PPP_LCP) 139125944Sjoerg goto illegal; 139225944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 139325944Sjoerg if (debug) 139425944Sjoerg addlog("%s%d: lcp echo req but lcp closed\n", 139525944Sjoerg ifp->if_name, ifp->if_unit); 139625944Sjoerg ++ifp->if_ierrors; 139725944Sjoerg break; 139825944Sjoerg } 139925944Sjoerg if (len < 8) { 140025944Sjoerg if (debug) 140125944Sjoerg addlog("%s%d: invalid lcp echo request " 140225944Sjoerg "packet length: %d bytes\n", 140325944Sjoerg ifp->if_name, ifp->if_unit, len); 140425944Sjoerg break; 140525944Sjoerg } 140625944Sjoerg if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 140725944Sjoerg /* Line loopback mode detected. */ 140825944Sjoerg printf("%s%d: loopback\n", ifp->if_name, ifp->if_unit); 140925944Sjoerg if_down (ifp); 141026018Sjoerg sppp_qflush (&sp->pp_cpq); 14114910Swollman 141225944Sjoerg /* Shut down the PPP link. */ 141325944Sjoerg /* XXX */ 141425944Sjoerg lcp.Down(sp); 141525944Sjoerg lcp.Up(sp); 141625944Sjoerg break; 141725944Sjoerg } 141825944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 141925944Sjoerg if (debug) 142025944Sjoerg addlog("%s%d: got lcp echo req, sending echo rep\n", 142125944Sjoerg ifp->if_name, ifp->if_unit); 142225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 142325944Sjoerg break; 142425944Sjoerg case ECHO_REPLY: 142525944Sjoerg if (cp->proto != PPP_LCP) 142625944Sjoerg goto illegal; 142725944Sjoerg if (h->ident != sp->lcp.echoid) { 142825944Sjoerg ++ifp->if_ierrors; 142925944Sjoerg break; 143025944Sjoerg } 143125944Sjoerg if (len < 8) { 143225944Sjoerg if (debug) 143325944Sjoerg addlog("%s%d: lcp invalid echo reply " 143425944Sjoerg "packet length: %d bytes\n", 143525944Sjoerg ifp->if_name, ifp->if_unit, len); 143625944Sjoerg break; 143725944Sjoerg } 143825944Sjoerg if (debug) 143925944Sjoerg addlog("%s%d: lcp got echo rep\n", 144025944Sjoerg ifp->if_name, ifp->if_unit); 144125944Sjoerg if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 144225944Sjoerg sp->pp_alivecnt = 0; 144325944Sjoerg break; 144425944Sjoerg default: 144525944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 144625944Sjoerg illegal: 144725944Sjoerg if (debug) 144825944Sjoerg addlog("%s%d: %c send code-rej for 0x%x\n", 144925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, h->type); 145025944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 145125944Sjoerg m->m_pkthdr.len, h); 145225944Sjoerg ++ifp->if_ierrors; 145325944Sjoerg } 14544910Swollman} 14554910Swollman 145625944Sjoerg 14574910Swollman/* 145825944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 145925944Sjoerg * Basically, the state transition handling in the automaton. 14604910Swollman */ 146125944Sjoergstatic void 146225944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 14634910Swollman{ 146425944Sjoerg STDDCL; 14654910Swollman 146625944Sjoerg if (debug) 146725944Sjoerg log(LOG_DEBUG, "%s%d: %s up(%s)\n", 146825944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 146925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 147025944Sjoerg 147125944Sjoerg switch (sp->state[cp->protoidx]) { 147225944Sjoerg case STATE_INITIAL: 147325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 147425944Sjoerg break; 147525944Sjoerg case STATE_STARTING: 147625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 147725944Sjoerg (cp->scr)(sp); 147825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 147925944Sjoerg break; 14804910Swollman default: 148125944Sjoerg printf("%s%d: %s illegal up in state %s\n", 148225944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 148325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 148425944Sjoerg } 148525944Sjoerg} 14864910Swollman 148725944Sjoergstatic void 148825944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 148925944Sjoerg{ 149025944Sjoerg STDDCL; 149125944Sjoerg 149225944Sjoerg if (debug) 149325944Sjoerg log(LOG_DEBUG, "%s%d: %s down(%s)\n", 149425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 149525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149625944Sjoerg 149725944Sjoerg switch (sp->state[cp->protoidx]) { 149825944Sjoerg case STATE_CLOSED: 149925944Sjoerg case STATE_CLOSING: 150025944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 15014910Swollman break; 150225944Sjoerg case STATE_STOPPED: 150325944Sjoerg (cp->tls)(sp); 150425944Sjoerg /* fall through */ 150525944Sjoerg case STATE_STOPPING: 150625944Sjoerg case STATE_REQ_SENT: 150725944Sjoerg case STATE_ACK_RCVD: 150825944Sjoerg case STATE_ACK_SENT: 150925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 151025944Sjoerg break; 151125944Sjoerg case STATE_OPENED: 151225944Sjoerg (cp->tld)(sp); 151325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 151425944Sjoerg break; 151525944Sjoerg default: 151625944Sjoerg printf("%s%d: %s illegal down in state %s\n", 151725944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 151825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 151925944Sjoerg } 152025944Sjoerg} 15214910Swollman 152211189Sjkh 152325944Sjoergstatic void 152425944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 152525944Sjoerg{ 152625944Sjoerg STDDCL; 152725944Sjoerg 152825944Sjoerg if (debug) 152925944Sjoerg log(LOG_DEBUG, "%s%d: %s open(%s)\n", 153025944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 153125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 153225944Sjoerg 153325944Sjoerg switch (sp->state[cp->protoidx]) { 153425944Sjoerg case STATE_INITIAL: 153525944Sjoerg (cp->tls)(sp); 153625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 15374910Swollman break; 153825944Sjoerg case STATE_STARTING: 153925944Sjoerg break; 154025944Sjoerg case STATE_CLOSED: 154125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 154225944Sjoerg (cp->scr)(sp); 154325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154425944Sjoerg break; 154525944Sjoerg case STATE_STOPPED: 154625944Sjoerg case STATE_STOPPING: 154725944Sjoerg case STATE_REQ_SENT: 154825944Sjoerg case STATE_ACK_RCVD: 154925944Sjoerg case STATE_ACK_SENT: 155025944Sjoerg case STATE_OPENED: 155125944Sjoerg break; 155225944Sjoerg case STATE_CLOSING: 155325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 155425944Sjoerg break; 155525944Sjoerg } 155625944Sjoerg} 15574910Swollman 155825944Sjoerg 155925944Sjoergstatic void 156025944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 156125944Sjoerg{ 156225944Sjoerg STDDCL; 156325944Sjoerg 156425944Sjoerg if (debug) 156525944Sjoerg log(LOG_DEBUG, "%s%d: %s close(%s)\n", 156625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 156725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 156825944Sjoerg 156925944Sjoerg switch (sp->state[cp->protoidx]) { 157025944Sjoerg case STATE_INITIAL: 157125944Sjoerg case STATE_CLOSED: 157225944Sjoerg case STATE_CLOSING: 15734910Swollman break; 157425944Sjoerg case STATE_STARTING: 157525944Sjoerg (cp->tlf)(sp); 157625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 15774910Swollman break; 157825944Sjoerg case STATE_STOPPED: 157925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 15804910Swollman break; 158125944Sjoerg case STATE_STOPPING: 158225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 15834910Swollman break; 158425944Sjoerg case STATE_OPENED: 158525944Sjoerg (cp->tld)(sp); 158625944Sjoerg /* fall through */ 158725944Sjoerg case STATE_REQ_SENT: 158825944Sjoerg case STATE_ACK_RCVD: 158925944Sjoerg case STATE_ACK_SENT: 159025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 159125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 159225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 15934910Swollman break; 15944910Swollman } 15954910Swollman} 15964910Swollman 159725944Sjoergstatic void 159825944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 159925944Sjoerg{ 160025944Sjoerg STDDCL; 160125944Sjoerg int s; 160225944Sjoerg 160325944Sjoerg s = splimp(); 160425944Sjoerg if (debug) 160525944Sjoerg log(LOG_DEBUG, "%s%d: %s TO(%s) rst_counter = %d\n", 160625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 160725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 160825944Sjoerg sp->rst_counter[cp->protoidx]); 160925944Sjoerg 161025944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 161125944Sjoerg /* TO- event */ 161225944Sjoerg switch (sp->state[cp->protoidx]) { 161325944Sjoerg case STATE_CLOSING: 161425944Sjoerg (cp->tlf)(sp); 161525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 161625944Sjoerg break; 161725944Sjoerg case STATE_STOPPING: 161825944Sjoerg (cp->tlf)(sp); 161925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 162025944Sjoerg break; 162125944Sjoerg case STATE_REQ_SENT: 162225944Sjoerg case STATE_ACK_RCVD: 162325944Sjoerg case STATE_ACK_SENT: 162425944Sjoerg (cp->tlf)(sp); 162525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 162625944Sjoerg break; 162725944Sjoerg } 162825944Sjoerg else 162925944Sjoerg /* TO+ event */ 163025944Sjoerg switch (sp->state[cp->protoidx]) { 163125944Sjoerg case STATE_CLOSING: 163225944Sjoerg case STATE_STOPPING: 163325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 163425944Sjoerg 0, 0); 163529681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 163629681Sgibbs sp->lcp.timeout); 163725944Sjoerg break; 163825944Sjoerg case STATE_REQ_SENT: 163925944Sjoerg case STATE_ACK_RCVD: 164025944Sjoerg (cp->scr)(sp); 164125944Sjoerg /* sppp_cp_change_state() will restart the timer */ 164225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 164325944Sjoerg break; 164425944Sjoerg case STATE_ACK_SENT: 164525944Sjoerg (cp->scr)(sp); 164629681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 164729681Sgibbs sp->lcp.timeout); 164825944Sjoerg break; 164925944Sjoerg } 165025944Sjoerg 165125944Sjoerg splx(s); 165225944Sjoerg} 165325944Sjoerg 165411189Sjkh/* 165525944Sjoerg * Change the state of a control protocol in the state automaton. 165625944Sjoerg * Takes care of starting/stopping the restart timer. 165711189Sjkh */ 165825944Sjoergvoid 165925944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 166025944Sjoerg{ 166125944Sjoerg sp->state[cp->protoidx] = newstate; 166225944Sjoerg 166329681Sgibbs untimeout(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 166425944Sjoerg switch (newstate) { 166525944Sjoerg case STATE_INITIAL: 166625944Sjoerg case STATE_STARTING: 166725944Sjoerg case STATE_CLOSED: 166825944Sjoerg case STATE_STOPPED: 166925944Sjoerg case STATE_OPENED: 167025944Sjoerg break; 167125944Sjoerg case STATE_CLOSING: 167225944Sjoerg case STATE_STOPPING: 167325944Sjoerg case STATE_REQ_SENT: 167425944Sjoerg case STATE_ACK_RCVD: 167525944Sjoerg case STATE_ACK_SENT: 167629681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 167729681Sgibbs sp->lcp.timeout); 167825944Sjoerg break; 167925944Sjoerg } 168025944Sjoerg} 168125944Sjoerg/* 168225944Sjoerg *--------------------------------------------------------------------------* 168325944Sjoerg * * 168425944Sjoerg * The LCP implementation. * 168525944Sjoerg * * 168625944Sjoerg *--------------------------------------------------------------------------* 168725944Sjoerg */ 168825944Sjoergstatic void 168925944Sjoergsppp_lcp_init(struct sppp *sp) 169025944Sjoerg{ 169125944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 169225944Sjoerg sp->lcp.magic = 0; 169325944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 169425944Sjoerg sp->fail_counter[IDX_LCP] = 0; 169525944Sjoerg sp->lcp.protos = 0; 169625944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 169730300Sjoerg 169825944Sjoerg /* 169925944Sjoerg * Initialize counters and timeout values. Note that we don't 170025944Sjoerg * use the 3 seconds suggested in RFC 1661 since we are likely 170125944Sjoerg * running on a fast link. XXX We should probably implement 170225944Sjoerg * the exponential backoff option. Note that these values are 170325944Sjoerg * relevant for all control protocols, not just LCP only. 170425944Sjoerg */ 170525944Sjoerg sp->lcp.timeout = 1 * hz; 170625944Sjoerg sp->lcp.max_terminate = 2; 170725944Sjoerg sp->lcp.max_configure = 10; 170825944Sjoerg sp->lcp.max_failure = 10; 170930300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 171025944Sjoerg} 171125944Sjoerg 171225944Sjoergstatic void 171325944Sjoergsppp_lcp_up(struct sppp *sp) 171425944Sjoerg{ 171525944Sjoerg STDDCL; 171625944Sjoerg 171725944Sjoerg /* 171830300Sjoerg * If this interface is passive or dial-on-demand, and we are 171930300Sjoerg * still in Initial state, it means we've got an incoming 172030300Sjoerg * call. Activate the interface. 172125944Sjoerg */ 172225944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 172325944Sjoerg if (debug) 172425944Sjoerg log(LOG_DEBUG, 172530300Sjoerg "%s%d: Up event", ifp->if_name, ifp->if_unit); 172625944Sjoerg ifp->if_flags |= IFF_RUNNING; 172730300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 172830300Sjoerg if (debug) 172930300Sjoerg addlog("(incoming call)\n"); 173030300Sjoerg sp->pp_flags |= PP_CALLIN; 173130300Sjoerg lcp.Open(sp); 173230300Sjoerg } else if (debug) 173330300Sjoerg addlog("\n"); 173425944Sjoerg } 173525944Sjoerg 173625944Sjoerg sppp_up_event(&lcp, sp); 173725944Sjoerg} 173825944Sjoerg 173925944Sjoergstatic void 174025944Sjoergsppp_lcp_down(struct sppp *sp) 174125944Sjoerg{ 174225944Sjoerg STDDCL; 174325944Sjoerg 174425944Sjoerg sppp_down_event(&lcp, sp); 174525944Sjoerg 174625944Sjoerg /* 174725944Sjoerg * If this is neither a dial-on-demand nor a passive 174825944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 174925944Sjoerg * administrator can force a redial by another ``ifconfig 175025944Sjoerg * up''. XXX For leased line operation, should we immediately 175125944Sjoerg * try to reopen the connection here? 175225944Sjoerg */ 175325944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 175425944Sjoerg log(LOG_INFO, 175525944Sjoerg "%s%d: Down event (carrier loss), taking interface down.\n", 175625944Sjoerg ifp->if_name, ifp->if_unit); 175725944Sjoerg if_down(ifp); 175825944Sjoerg } else { 175925944Sjoerg if (debug) 176025944Sjoerg log(LOG_DEBUG, 176125944Sjoerg "%s%d: Down event (carrier loss)\n", 176225944Sjoerg ifp->if_name, ifp->if_unit); 176325944Sjoerg } 176430300Sjoerg sp->pp_flags &= ~PP_CALLIN; 176530300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 176630300Sjoerg lcp.Close(sp); 176725944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 176825944Sjoerg} 176925944Sjoerg 177025944Sjoergstatic void 177125944Sjoergsppp_lcp_open(struct sppp *sp) 177225944Sjoerg{ 177330300Sjoerg /* 177430300Sjoerg * If we are authenticator, negotiate LCP_AUTH 177530300Sjoerg */ 177630300Sjoerg if (sp->hisauth.proto != 0) 177730300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 177830300Sjoerg else 177930300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 178030300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 178125944Sjoerg sppp_open_event(&lcp, sp); 178225944Sjoerg} 178325944Sjoerg 178425944Sjoergstatic void 178525944Sjoergsppp_lcp_close(struct sppp *sp) 178625944Sjoerg{ 178725944Sjoerg sppp_close_event(&lcp, sp); 178825944Sjoerg} 178925944Sjoerg 179025944Sjoergstatic void 179125944Sjoergsppp_lcp_TO(void *cookie) 179225944Sjoerg{ 179325944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 179425944Sjoerg} 179525944Sjoerg 179625944Sjoerg/* 179725944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 179825944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 179925944Sjoerg * caused action scn. (The return value is used to make the state 180025944Sjoerg * transition decision in the state automaton.) 180125944Sjoerg */ 180212820Sphkstatic int 180325944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 18044910Swollman{ 180525944Sjoerg STDDCL; 180611189Sjkh u_char *buf, *r, *p; 180725944Sjoerg int origlen, rlen; 180825944Sjoerg u_long nmagic; 180930300Sjoerg u_short authproto; 18104910Swollman 181111189Sjkh len -= 4; 181225944Sjoerg origlen = len; 181311189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 181411189Sjkh if (! buf) 181511189Sjkh return (0); 18164910Swollman 181725706Sjoerg if (debug) 181825944Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opts: ", 181925944Sjoerg ifp->if_name, ifp->if_unit); 182025706Sjoerg 182125944Sjoerg /* pass 1: check for things that need to be rejected */ 182211189Sjkh p = (void*) (h+1); 182311189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 182425944Sjoerg if (debug) 182525944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 182611189Sjkh switch (*p) { 182711189Sjkh case LCP_OPT_MAGIC: 182825944Sjoerg /* Magic number. */ 182925944Sjoerg /* fall through, both are same length */ 183025944Sjoerg case LCP_OPT_ASYNC_MAP: 183125944Sjoerg /* Async control character map. */ 183225944Sjoerg if (len >= 6 || p[1] == 6) 183325944Sjoerg continue; 183425944Sjoerg if (debug) 183525944Sjoerg addlog("[invalid] "); 183625944Sjoerg break; 183725944Sjoerg case LCP_OPT_MRU: 183825944Sjoerg /* Maximum receive unit. */ 183925944Sjoerg if (len >= 4 && p[1] == 4) 184025944Sjoerg continue; 184125944Sjoerg if (debug) 184225944Sjoerg addlog("[invalid] "); 184325944Sjoerg break; 184430300Sjoerg case LCP_OPT_AUTH_PROTO: 184530300Sjoerg if (len < 4) { 184630300Sjoerg if (debug) 184730300Sjoerg addlog("[invalid] "); 184830300Sjoerg break; 184930300Sjoerg } 185030300Sjoerg authproto = (p[2] << 8) + p[3]; 185130300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 185230300Sjoerg if (debug) 185330300Sjoerg addlog("[invalid chap len] "); 185430300Sjoerg break; 185530300Sjoerg } 185630300Sjoerg if (sp->myauth.proto == 0) { 185730300Sjoerg /* we are not configured to do auth */ 185830300Sjoerg if (debug) 185930300Sjoerg addlog("[not configured] "); 186030300Sjoerg break; 186130300Sjoerg } 186230300Sjoerg /* 186330300Sjoerg * Remote want us to authenticate, remember this, 186430300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 186530300Sjoerg * up. 186630300Sjoerg */ 186730300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 186830300Sjoerg continue; 186925944Sjoerg default: 187025944Sjoerg /* Others not supported. */ 187125944Sjoerg if (debug) 187225944Sjoerg addlog("[rej] "); 187325944Sjoerg break; 187425944Sjoerg } 187525944Sjoerg /* Add the option to rejected list. */ 187625944Sjoerg bcopy (p, r, p[1]); 187725944Sjoerg r += p[1]; 187825944Sjoerg rlen += p[1]; 187925944Sjoerg } 188025944Sjoerg if (rlen) { 188125944Sjoerg if (debug) 188225944Sjoerg addlog(" send conf-rej\n"); 188325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 188425944Sjoerg return 0; 188525944Sjoerg } else if (debug) 188625944Sjoerg addlog("\n"); 188725944Sjoerg 188825944Sjoerg /* 188925944Sjoerg * pass 2: check for option values that are unacceptable and 189025944Sjoerg * thus require to be nak'ed. 189125944Sjoerg */ 189225944Sjoerg if (debug) 189326077Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opt values: ", 189426077Sjoerg ifp->if_name, ifp->if_unit); 189525944Sjoerg 189625944Sjoerg p = (void*) (h+1); 189725944Sjoerg len = origlen; 189825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 189925944Sjoerg if (debug) 190025944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 190125944Sjoerg switch (*p) { 190225944Sjoerg case LCP_OPT_MAGIC: 190311189Sjkh /* Magic number -- extract. */ 190425944Sjoerg nmagic = (u_long)p[2] << 24 | 190525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 190625944Sjoerg if (nmagic != sp->lcp.magic) { 190725706Sjoerg if (debug) 190825944Sjoerg addlog("0x%x ", nmagic); 190911189Sjkh continue; 191011189Sjkh } 191125944Sjoerg /* 191225944Sjoerg * Local and remote magics equal -- loopback? 191325944Sjoerg */ 191425944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 191530300Sjoerg printf ("%s%d: loopback\n", 191625944Sjoerg ifp->if_name, ifp->if_unit); 191725944Sjoerg sp->pp_loopcnt = 0; 191825944Sjoerg if (ifp->if_flags & IFF_UP) { 191925944Sjoerg if_down(ifp); 192026018Sjoerg sppp_qflush(&sp->pp_cpq); 192125944Sjoerg /* XXX ? */ 192225944Sjoerg lcp.Down(sp); 192325944Sjoerg lcp.Up(sp); 192425944Sjoerg } 192525944Sjoerg } else if (debug) 192625944Sjoerg addlog("[glitch] "); 192725944Sjoerg ++sp->pp_loopcnt; 192825944Sjoerg /* 192925944Sjoerg * We negate our magic here, and NAK it. If 193025944Sjoerg * we see it later in an NAK packet, we 193125944Sjoerg * suggest a new one. 193225944Sjoerg */ 193325944Sjoerg nmagic = ~sp->lcp.magic; 193425944Sjoerg /* Gonna NAK it. */ 193525944Sjoerg p[2] = nmagic >> 24; 193625944Sjoerg p[3] = nmagic >> 16; 193725944Sjoerg p[4] = nmagic >> 8; 193825944Sjoerg p[5] = nmagic; 193911189Sjkh break; 194025944Sjoerg 194111189Sjkh case LCP_OPT_ASYNC_MAP: 194211189Sjkh /* Async control character map -- check to be zero. */ 194325944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 194425706Sjoerg if (debug) 194525944Sjoerg addlog("[empty] "); 194611189Sjkh continue; 194725706Sjoerg } 194825706Sjoerg if (debug) 194925944Sjoerg addlog("[non-empty] "); 195025944Sjoerg /* suggest a zero one */ 195125944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 195211189Sjkh break; 195325944Sjoerg 195411189Sjkh case LCP_OPT_MRU: 195525944Sjoerg /* 195625944Sjoerg * Maximum receive unit. Always agreeable, 195725944Sjoerg * but ignored by now. 195825944Sjoerg */ 195925944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 196025706Sjoerg if (debug) 196125944Sjoerg addlog("%d ", sp->lcp.their_mru); 196211189Sjkh continue; 196330300Sjoerg 196430300Sjoerg case LCP_OPT_AUTH_PROTO: 196530300Sjoerg authproto = (p[2] << 8) + p[3]; 196630300Sjoerg if (sp->myauth.proto != authproto) { 196730300Sjoerg /* not agreed, nak */ 196830300Sjoerg if (debug) 196930300Sjoerg addlog("[mine %s != his %s] ", 197030300Sjoerg sppp_proto_name(sp->hisauth.proto), 197130300Sjoerg sppp_proto_name(authproto)); 197230300Sjoerg p[2] = sp->myauth.proto >> 8; 197330300Sjoerg p[3] = sp->myauth.proto; 197430300Sjoerg break; 197530300Sjoerg } 197630300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 197730300Sjoerg if (debug) 197830300Sjoerg addlog("[chap not MD5] "); 197930300Sjoerg p[4] == CHAP_MD5; 198030300Sjoerg break; 198130300Sjoerg } 198230300Sjoerg continue; 198311189Sjkh } 198425944Sjoerg /* Add the option to nak'ed list. */ 198525706Sjoerg bcopy (p, r, p[1]); 198625706Sjoerg r += p[1]; 198711189Sjkh rlen += p[1]; 198812436Speter } 198925706Sjoerg if (rlen) { 199028036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 199128036Sjoerg if (debug) 199228036Sjoerg addlog(" max_failure (%d) exceeded, " 199328036Sjoerg "send conf-rej\n", 199428036Sjoerg sp->lcp.max_failure); 199528036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 199628036Sjoerg } else { 199728036Sjoerg if (debug) 199828036Sjoerg addlog(" send conf-nak\n"); 199928036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 200028036Sjoerg } 200125944Sjoerg return 0; 200225944Sjoerg } else { 200325944Sjoerg if (debug) 200425944Sjoerg addlog(" send conf-ack\n"); 200528036Sjoerg sp->fail_counter[IDX_LCP] = 0; 200625944Sjoerg sp->pp_loopcnt = 0; 200725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 200825944Sjoerg h->ident, origlen, h+1); 200925944Sjoerg } 201025944Sjoerg 201111189Sjkh free (buf, M_TEMP); 201211189Sjkh return (rlen == 0); 20134910Swollman} 20144910Swollman 201525944Sjoerg/* 201625944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 201725944Sjoerg * negotiation. 201825944Sjoerg */ 201912820Sphkstatic void 202025944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 20214910Swollman{ 202225944Sjoerg STDDCL; 202325944Sjoerg u_char *buf, *p; 20244910Swollman 202525944Sjoerg len -= 4; 202625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 202725944Sjoerg if (!buf) 20284910Swollman return; 202925944Sjoerg 203025944Sjoerg if (debug) 203125944Sjoerg log(LOG_DEBUG, "%s%d: lcp rej opts: ", 203225944Sjoerg ifp->if_name, ifp->if_unit); 203325944Sjoerg 203425944Sjoerg p = (void*) (h+1); 203525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 203625944Sjoerg if (debug) 203725944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 203825944Sjoerg switch (*p) { 203925944Sjoerg case LCP_OPT_MAGIC: 204025944Sjoerg /* Magic number -- can't use it, use 0 */ 204125944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 204225944Sjoerg sp->lcp.magic = 0; 204325944Sjoerg break; 204425944Sjoerg case LCP_OPT_MRU: 204525944Sjoerg /* 204625944Sjoerg * Should not be rejected anyway, since we only 204725944Sjoerg * negotiate a MRU if explicitly requested by 204825944Sjoerg * peer. 204925944Sjoerg */ 205025944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 205125944Sjoerg break; 205230300Sjoerg case LCP_OPT_AUTH_PROTO: 205330300Sjoerg /* 205430300Sjoerg * Peer doesn't want to authenticate himself, 205530300Sjoerg * deny unless this is a dialout call, and 205630300Sjoerg * AUTHFLAG_NOCALLOUT is set. 205730300Sjoerg */ 205830300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 205930300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 206030300Sjoerg if (debug) 206130300Sjoerg addlog("[don't insist on auth " 206230300Sjoerg "for callout]"); 206330300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 206430300Sjoerg break; 206530300Sjoerg } 206630300Sjoerg if (debug) 206730300Sjoerg addlog("[access denied]\n"); 206830300Sjoerg lcp.Close(sp); 206930300Sjoerg break; 207025944Sjoerg } 20714910Swollman } 207225944Sjoerg if (debug) 207325944Sjoerg addlog("\n"); 207425944Sjoerg free (buf, M_TEMP); 207525944Sjoerg return; 207625944Sjoerg} 207725944Sjoerg 207825944Sjoerg/* 207925944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 208025944Sjoerg * negotiation. 208125944Sjoerg */ 208225944Sjoergstatic void 208325944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 208425944Sjoerg{ 208525944Sjoerg STDDCL; 208625944Sjoerg u_char *buf, *p; 208725944Sjoerg u_long magic; 208825944Sjoerg 208925944Sjoerg len -= 4; 209025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 209125944Sjoerg if (!buf) 209225944Sjoerg return; 209325944Sjoerg 209425944Sjoerg if (debug) 209525944Sjoerg log(LOG_DEBUG, "%s%d: lcp nak opts: ", 209625944Sjoerg ifp->if_name, ifp->if_unit); 209725944Sjoerg 209825944Sjoerg p = (void*) (h+1); 209925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 210025706Sjoerg if (debug) 210125944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 210225944Sjoerg switch (*p) { 210325944Sjoerg case LCP_OPT_MAGIC: 210425944Sjoerg /* Magic number -- renegotiate */ 210525944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 210625944Sjoerg len >= 6 && p[1] == 6) { 210725944Sjoerg magic = (u_long)p[2] << 24 | 210825944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 210925944Sjoerg /* 211025944Sjoerg * If the remote magic is our negated one, 211125944Sjoerg * this looks like a loopback problem. 211225944Sjoerg * Suggest a new magic to make sure. 211325944Sjoerg */ 211425944Sjoerg if (magic == ~sp->lcp.magic) { 211525944Sjoerg if (debug) 211625944Sjoerg addlog("magic glitch "); 211725944Sjoerg sp->lcp.magic += time.tv_sec + time.tv_usec; 211825944Sjoerg } else { 211925944Sjoerg sp->lcp.magic = magic; 212025944Sjoerg if (debug) 212125944Sjoerg addlog("%d "); 212225944Sjoerg } 212325944Sjoerg } 212425944Sjoerg break; 212525944Sjoerg case LCP_OPT_MRU: 212625944Sjoerg /* 212725944Sjoerg * Peer wants to advise us to negotiate an MRU. 212825944Sjoerg * Agree on it if it's reasonable, or use 212925944Sjoerg * default otherwise. 213025944Sjoerg */ 213125944Sjoerg if (len >= 4 && p[1] == 4) { 213225944Sjoerg u_int mru = p[2] * 256 + p[3]; 213325944Sjoerg if (debug) 213425944Sjoerg addlog("%d ", mru); 213525944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 213625944Sjoerg mru = PP_MTU; 213725944Sjoerg sp->lcp.mru = mru; 213825944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 213925944Sjoerg } 214025944Sjoerg break; 214130300Sjoerg case LCP_OPT_AUTH_PROTO: 214230300Sjoerg /* 214330300Sjoerg * Peer doesn't like our authentication method, 214430300Sjoerg * deny. 214530300Sjoerg */ 214630300Sjoerg if (debug) 214730300Sjoerg addlog("[access denied]\n"); 214830300Sjoerg lcp.Close(sp); 214930300Sjoerg break; 21504910Swollman } 215125944Sjoerg } 215225944Sjoerg if (debug) 215325944Sjoerg addlog("\n"); 215425944Sjoerg free (buf, M_TEMP); 215525944Sjoerg return; 215625944Sjoerg} 215711189Sjkh 215825944Sjoergstatic void 215925944Sjoergsppp_lcp_tlu(struct sppp *sp) 216025944Sjoerg{ 216125944Sjoerg STDDCL; 216225944Sjoerg int i; 216325944Sjoerg u_long mask; 216425944Sjoerg 216525944Sjoerg /* XXX ? */ 216625944Sjoerg if (! (ifp->if_flags & IFF_UP) && 216725944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 216825944Sjoerg /* Coming out of loopback mode. */ 216925944Sjoerg if_up(ifp); 217025944Sjoerg printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 217125944Sjoerg } 217225944Sjoerg 217325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 217425944Sjoerg if ((cps[i])->flags & CP_QUAL) 217525944Sjoerg (cps[i])->Open(sp); 217625944Sjoerg 217730300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 217830300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 217925944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 218025944Sjoerg else 218125944Sjoerg sp->pp_phase = PHASE_NETWORK; 218225944Sjoerg 218325944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 218425944Sjoerg sppp_phase_name(sp->pp_phase)); 218525944Sjoerg 218630300Sjoerg /* 218730300Sjoerg * Open all authentication protocols. This is even required 218830300Sjoerg * if we already proceeded to network phase, since it might be 218930300Sjoerg * that remote wants us to authenticate, so we might have to 219030300Sjoerg * send a PAP request. Undesired authentication protocols 219130300Sjoerg * don't do anything when they get an Open event. 219230300Sjoerg */ 219330300Sjoerg for (i = 0; i < IDX_COUNT; i++) 219430300Sjoerg if ((cps[i])->flags & CP_AUTH) 219530300Sjoerg (cps[i])->Open(sp); 219630300Sjoerg 219730300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 219825944Sjoerg /* Notify all NCPs. */ 219925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 220025944Sjoerg if ((cps[i])->flags & CP_NCP) 220125944Sjoerg (cps[i])->Open(sp); 220225944Sjoerg } 220325944Sjoerg 220425944Sjoerg /* Send Up events to all started protos. */ 220525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 220625944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 220725944Sjoerg (cps[i])->Up(sp); 220825944Sjoerg 220925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 221025944Sjoerg /* if no NCP is starting, close down */ 221130300Sjoerg sppp_lcp_check_and_close(sp); 221225944Sjoerg} 221325944Sjoerg 221425944Sjoergstatic void 221525944Sjoergsppp_lcp_tld(struct sppp *sp) 221625944Sjoerg{ 221725944Sjoerg STDDCL; 221825944Sjoerg int i; 221925944Sjoerg u_long mask; 222025944Sjoerg 222125944Sjoerg sp->pp_phase = PHASE_TERMINATE; 222225944Sjoerg 222325944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 222425944Sjoerg sppp_phase_name(sp->pp_phase)); 222525944Sjoerg 222625944Sjoerg /* 222725944Sjoerg * Take upper layers down. We send the Down event first and 222825944Sjoerg * the Close second to prevent the upper layers from sending 222925944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 223025944Sjoerg * describes it. 223125944Sjoerg */ 223225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 223325944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 223425944Sjoerg (cps[i])->Down(sp); 223525944Sjoerg (cps[i])->Close(sp); 223625944Sjoerg } 223725944Sjoerg} 223825944Sjoerg 223925944Sjoergstatic void 224025944Sjoergsppp_lcp_tls(struct sppp *sp) 224125944Sjoerg{ 224225944Sjoerg STDDCL; 224325944Sjoerg 224425944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 224525944Sjoerg 224625944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 224725944Sjoerg sppp_phase_name(sp->pp_phase)); 224825944Sjoerg 224925944Sjoerg /* Notify lower layer if desired. */ 225025944Sjoerg if (sp->pp_tls) 225125944Sjoerg (sp->pp_tls)(sp); 225225944Sjoerg} 225325944Sjoerg 225425944Sjoergstatic void 225525944Sjoergsppp_lcp_tlf(struct sppp *sp) 225625944Sjoerg{ 225725944Sjoerg STDDCL; 225825944Sjoerg 225925944Sjoerg sp->pp_phase = PHASE_DEAD; 226025944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 226125944Sjoerg sppp_phase_name(sp->pp_phase)); 226225944Sjoerg 226325944Sjoerg /* Notify lower layer if desired. */ 226425944Sjoerg if (sp->pp_tlf) 226525944Sjoerg (sp->pp_tlf)(sp); 226625944Sjoerg} 226725944Sjoerg 226825944Sjoergstatic void 226925944Sjoergsppp_lcp_scr(struct sppp *sp) 227025944Sjoerg{ 227130300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 227225944Sjoerg int i = 0; 227330300Sjoerg u_short authproto; 227425944Sjoerg 227525944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 227625944Sjoerg if (! sp->lcp.magic) 227725944Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 227825944Sjoerg opt[i++] = LCP_OPT_MAGIC; 227925944Sjoerg opt[i++] = 6; 228025944Sjoerg opt[i++] = sp->lcp.magic >> 24; 228125944Sjoerg opt[i++] = sp->lcp.magic >> 16; 228225944Sjoerg opt[i++] = sp->lcp.magic >> 8; 228325944Sjoerg opt[i++] = sp->lcp.magic; 228425944Sjoerg } 228525944Sjoerg 228625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 228725944Sjoerg opt[i++] = LCP_OPT_MRU; 228825944Sjoerg opt[i++] = 4; 228925944Sjoerg opt[i++] = sp->lcp.mru >> 8; 229025944Sjoerg opt[i++] = sp->lcp.mru; 229125944Sjoerg } 229225944Sjoerg 229330300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 229430300Sjoerg authproto = sp->hisauth.proto; 229530300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 229630300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 229730300Sjoerg opt[i++] = authproto >> 8; 229830300Sjoerg opt[i++] = authproto; 229930300Sjoerg if (authproto == PPP_CHAP) 230030300Sjoerg opt[i++] = CHAP_MD5; 230130300Sjoerg } 230230300Sjoerg 230325944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 230425944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 230525944Sjoerg} 230625944Sjoerg 230725944Sjoerg/* 230830300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 230930300Sjoerg */ 231030300Sjoergstatic int 231130300Sjoergsppp_ncp_check(struct sppp *sp) 231230300Sjoerg{ 231330300Sjoerg int i, mask; 231430300Sjoerg 231530300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 231630300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 231730300Sjoerg return 1; 231830300Sjoerg return 0; 231930300Sjoerg} 232030300Sjoerg 232130300Sjoerg/* 232225944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 232325944Sjoerg * Called by the NCPs during their tlf action handling. 232425944Sjoerg */ 232525944Sjoergstatic void 232630300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 232725944Sjoerg{ 232825944Sjoerg 232930300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 233030300Sjoerg /* don't bother, we are already going down */ 233130300Sjoerg return; 233230300Sjoerg 233330300Sjoerg if (sppp_ncp_check(sp)) 233430300Sjoerg return; 233530300Sjoerg 233625944Sjoerg lcp.Close(sp); 233725944Sjoerg} 233825944Sjoerg/* 233925944Sjoerg *--------------------------------------------------------------------------* 234025944Sjoerg * * 234125944Sjoerg * The IPCP implementation. * 234225944Sjoerg * * 234325944Sjoerg *--------------------------------------------------------------------------* 234425944Sjoerg */ 234525944Sjoerg 234625944Sjoergstatic void 234725944Sjoergsppp_ipcp_init(struct sppp *sp) 234825944Sjoerg{ 234925944Sjoerg sp->ipcp.opts = 0; 235025944Sjoerg sp->ipcp.flags = 0; 235125944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 235225944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 235329681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 235425944Sjoerg} 235525944Sjoerg 235625944Sjoergstatic void 235725944Sjoergsppp_ipcp_up(struct sppp *sp) 235825944Sjoerg{ 235925944Sjoerg sppp_up_event(&ipcp, sp); 236025944Sjoerg} 236125944Sjoerg 236225944Sjoergstatic void 236325944Sjoergsppp_ipcp_down(struct sppp *sp) 236425944Sjoerg{ 236525944Sjoerg sppp_down_event(&ipcp, sp); 236625944Sjoerg} 236725944Sjoerg 236825944Sjoergstatic void 236925944Sjoergsppp_ipcp_open(struct sppp *sp) 237025944Sjoerg{ 237125944Sjoerg STDDCL; 237225944Sjoerg u_long myaddr, hisaddr; 237325944Sjoerg 237430300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 237525944Sjoerg /* 237625944Sjoerg * If we don't have his address, this probably means our 237725944Sjoerg * interface doesn't want to talk IP at all. (This could 237825944Sjoerg * be the case if somebody wants to speak only IPX, for 237925944Sjoerg * example.) Don't open IPCP in this case. 238025944Sjoerg */ 238125944Sjoerg if (hisaddr == 0L) { 238225944Sjoerg /* XXX this message should go away */ 238325944Sjoerg if (debug) 238425944Sjoerg log(LOG_DEBUG, "%s%d: ipcp_open(): no IP interface\n", 238525944Sjoerg ifp->if_name, ifp->if_unit); 238625944Sjoerg return; 238725944Sjoerg } 238825944Sjoerg 238925944Sjoerg if (myaddr == 0L) { 239025944Sjoerg /* 239125944Sjoerg * I don't have an assigned address, so i need to 239225944Sjoerg * negotiate my address. 239325944Sjoerg */ 239425944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 239525944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 239625944Sjoerg } 239725944Sjoerg sppp_open_event(&ipcp, sp); 239825944Sjoerg} 239925944Sjoerg 240025944Sjoergstatic void 240125944Sjoergsppp_ipcp_close(struct sppp *sp) 240225944Sjoerg{ 240325944Sjoerg sppp_close_event(&ipcp, sp); 240425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 240525944Sjoerg /* 240625944Sjoerg * My address was dynamic, clear it again. 240725944Sjoerg */ 240825944Sjoerg sppp_set_ip_addr(sp, 0L); 240925944Sjoerg} 241025944Sjoerg 241125944Sjoergstatic void 241225944Sjoergsppp_ipcp_TO(void *cookie) 241325944Sjoerg{ 241425944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 241525944Sjoerg} 241625944Sjoerg 241725944Sjoerg/* 241825944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 241925944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 242025944Sjoerg * caused action scn. (The return value is used to make the state 242125944Sjoerg * transition decision in the state automaton.) 242225944Sjoerg */ 242325944Sjoergstatic int 242425944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 242525944Sjoerg{ 242625944Sjoerg u_char *buf, *r, *p; 242725944Sjoerg struct ifnet *ifp = &sp->pp_if; 242825944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 242925944Sjoerg u_long hisaddr, desiredaddr; 243025944Sjoerg 243125944Sjoerg len -= 4; 243225944Sjoerg origlen = len; 243325944Sjoerg /* 243425944Sjoerg * Make sure to allocate a buf that can at least hold a 243525944Sjoerg * conf-nak with an `address' option. We might need it below. 243625944Sjoerg */ 243725944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 243825944Sjoerg if (! buf) 243925944Sjoerg return (0); 244025944Sjoerg 244125944Sjoerg /* pass 1: see if we can recognize them */ 244225944Sjoerg if (debug) 244325944Sjoerg log(LOG_DEBUG, "%s%d: ipcp parse opts: ", 244425944Sjoerg ifp->if_name, ifp->if_unit); 244525944Sjoerg p = (void*) (h+1); 244625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 244725944Sjoerg if (debug) 244825944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 244925944Sjoerg switch (*p) { 245025944Sjoerg#ifdef notyet 245125944Sjoerg case IPCP_OPT_COMPRESSION: 245225944Sjoerg if (len >= 6 && p[1] >= 6) { 245325944Sjoerg /* correctly formed compress option */ 245425944Sjoerg continue; 245511189Sjkh } 245625706Sjoerg if (debug) 245725944Sjoerg addlog("[invalid] "); 245825944Sjoerg break; 245925944Sjoerg#endif 246025944Sjoerg case IPCP_OPT_ADDRESS: 246125944Sjoerg if (len >= 6 && p[1] == 6) { 246225944Sjoerg /* correctly formed address option */ 246325944Sjoerg continue; 246425944Sjoerg } 246525706Sjoerg if (debug) 246625944Sjoerg addlog("[invalid] "); 246711189Sjkh break; 246825944Sjoerg default: 246925944Sjoerg /* Others not supported. */ 247025944Sjoerg if (debug) 247125944Sjoerg addlog("[rej] "); 24724910Swollman break; 24734910Swollman } 247425944Sjoerg /* Add the option to rejected list. */ 247525944Sjoerg bcopy (p, r, p[1]); 247625944Sjoerg r += p[1]; 247725944Sjoerg rlen += p[1]; 247825944Sjoerg } 247925944Sjoerg if (rlen) { 248025944Sjoerg if (debug) 248125944Sjoerg addlog(" send conf-rej\n"); 248225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 248325944Sjoerg return 0; 248425944Sjoerg } else if (debug) 248525944Sjoerg addlog("\n"); 248625944Sjoerg 248725944Sjoerg /* pass 2: parse option values */ 248830300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 248925944Sjoerg if (debug) 249030300Sjoerg log(LOG_DEBUG, "%s%d: ipcp parse opt values: ", 249130300Sjoerg ifp->if_name, ifp->if_unit); 249225944Sjoerg p = (void*) (h+1); 249325944Sjoerg len = origlen; 249425944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 249525944Sjoerg if (debug) 249625944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 249725944Sjoerg switch (*p) { 249825944Sjoerg#ifdef notyet 249925944Sjoerg case IPCP_OPT_COMPRESSION: 250025944Sjoerg continue; 250125944Sjoerg#endif 250225944Sjoerg case IPCP_OPT_ADDRESS: 250325944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 250425944Sjoerg p[4] << 8 | p[5]; 250525944Sjoerg if (desiredaddr == hisaddr) { 250625944Sjoerg /* 250725944Sjoerg * Peer's address is same as our value, 250825944Sjoerg * this is agreeable. Gonna conf-ack 250925944Sjoerg * it. 251025944Sjoerg */ 251125944Sjoerg if (debug) 251230300Sjoerg addlog("%s [ack] ", 251330300Sjoerg sppp_dotted_quad(hisaddr)); 251425944Sjoerg /* record that we've seen it already */ 251525944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 251625944Sjoerg continue; 251725944Sjoerg } 251825944Sjoerg /* 251925944Sjoerg * The address wasn't agreeable. This is either 252025944Sjoerg * he sent us 0.0.0.0, asking to assign him an 252125944Sjoerg * address, or he send us another address not 252225944Sjoerg * matching our value. Either case, we gonna 252325944Sjoerg * conf-nak it with our value. 252425944Sjoerg */ 252525944Sjoerg if (debug) { 252625944Sjoerg if (desiredaddr == 0) 252725944Sjoerg addlog("[addr requested] "); 252825944Sjoerg else 252930300Sjoerg addlog("%s [not agreed] ", 253030300Sjoerg sppp_dotted_quad(desiredaddr)); 253125944Sjoerg 253225944Sjoerg p[2] = hisaddr >> 24; 253325944Sjoerg p[3] = hisaddr >> 16; 253425944Sjoerg p[4] = hisaddr >> 8; 253525944Sjoerg p[5] = hisaddr; 253625944Sjoerg } 253711189Sjkh break; 253825706Sjoerg } 253925944Sjoerg /* Add the option to nak'ed list. */ 254025944Sjoerg bcopy (p, r, p[1]); 254125944Sjoerg r += p[1]; 254225944Sjoerg rlen += p[1]; 254325944Sjoerg } 254425944Sjoerg 254525944Sjoerg /* 254625944Sjoerg * If we are about to conf-ack the request, but haven't seen 254725944Sjoerg * his address so far, gonna conf-nak it instead, with the 254825944Sjoerg * `address' option present and our idea of his address being 254925944Sjoerg * filled in there, to request negotiation of both addresses. 255025944Sjoerg * 255125944Sjoerg * XXX This can result in an endless req - nak loop if peer 255225944Sjoerg * doesn't want to send us his address. Q: What should we do 255325944Sjoerg * about it? XXX A: implement the max-failure counter. 255425944Sjoerg */ 255525944Sjoerg if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { 255625944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 255725944Sjoerg buf[1] = 6; 255825944Sjoerg buf[2] = hisaddr >> 24; 255925944Sjoerg buf[3] = hisaddr >> 16; 256025944Sjoerg buf[4] = hisaddr >> 8; 256125944Sjoerg buf[5] = hisaddr; 256225944Sjoerg rlen = 6; 256325706Sjoerg if (debug) 256425944Sjoerg addlog("still need hisaddr "); 256525944Sjoerg } 256625944Sjoerg 256725944Sjoerg if (rlen) { 256825706Sjoerg if (debug) 256925944Sjoerg addlog(" send conf-nak\n"); 257025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 257125944Sjoerg } else { 257225706Sjoerg if (debug) 257325944Sjoerg addlog(" send conf-ack\n"); 257425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 257525944Sjoerg h->ident, origlen, h+1); 257625944Sjoerg } 257725944Sjoerg 257825944Sjoerg free (buf, M_TEMP); 257925944Sjoerg return (rlen == 0); 258025944Sjoerg} 258125944Sjoerg 258225944Sjoerg/* 258325944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 258425944Sjoerg * negotiation. 258525944Sjoerg */ 258625944Sjoergstatic void 258725944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 258825944Sjoerg{ 258925944Sjoerg u_char *buf, *p; 259025944Sjoerg struct ifnet *ifp = &sp->pp_if; 259125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 259225944Sjoerg 259325944Sjoerg len -= 4; 259425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 259525944Sjoerg if (!buf) 259625944Sjoerg return; 259725944Sjoerg 259825944Sjoerg if (debug) 259925944Sjoerg log(LOG_DEBUG, "%s%d: ipcp rej opts: ", 260025944Sjoerg ifp->if_name, ifp->if_unit); 260125944Sjoerg 260225944Sjoerg p = (void*) (h+1); 260325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 260425706Sjoerg if (debug) 260525944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 260625944Sjoerg switch (*p) { 260725944Sjoerg case IPCP_OPT_ADDRESS: 260825944Sjoerg /* 260925944Sjoerg * Peer doesn't grok address option. This is 261025944Sjoerg * bad. XXX Should we better give up here? 261125944Sjoerg */ 261225944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 261325944Sjoerg break; 261425944Sjoerg#ifdef notyet 261525944Sjoerg case IPCP_OPT_COMPRESS: 261625944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); 261725944Sjoerg break; 261825944Sjoerg#endif 261925944Sjoerg } 26204910Swollman } 262125944Sjoerg if (debug) 262225944Sjoerg addlog("\n"); 262325944Sjoerg free (buf, M_TEMP); 262425944Sjoerg return; 26254910Swollman} 26264910Swollman 262725944Sjoerg/* 262825944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 262925944Sjoerg * negotiation. 263025944Sjoerg */ 263112820Sphkstatic void 263225944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 26334910Swollman{ 263425944Sjoerg u_char *buf, *p; 263525944Sjoerg struct ifnet *ifp = &sp->pp_if; 263625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 263725944Sjoerg u_long wantaddr; 26384910Swollman 263925944Sjoerg len -= 4; 264025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 264125944Sjoerg if (!buf) 264225944Sjoerg return; 264325944Sjoerg 264425944Sjoerg if (debug) 264525944Sjoerg log(LOG_DEBUG, "%s%d: ipcp nak opts: ", 264625944Sjoerg ifp->if_name, ifp->if_unit); 264725944Sjoerg 264825944Sjoerg p = (void*) (h+1); 264925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 265025944Sjoerg if (debug) 265125944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 265225944Sjoerg switch (*p) { 265325944Sjoerg case IPCP_OPT_ADDRESS: 265425944Sjoerg /* 265525944Sjoerg * Peer doesn't like our local IP address. See 265625944Sjoerg * if we can do something for him. We'll drop 265725944Sjoerg * him our address then. 265825944Sjoerg */ 265925944Sjoerg if (len >= 6 && p[1] == 6) { 266025944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 266125944Sjoerg p[4] << 8 | p[5]; 266225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 266325944Sjoerg if (debug) 266430300Sjoerg addlog("[wantaddr %s] ", 266530300Sjoerg sppp_dotted_quad(wantaddr)); 266625944Sjoerg /* 266725944Sjoerg * When doing dynamic address assignment, 266825944Sjoerg * we accept his offer. Otherwise, we 266925944Sjoerg * ignore it and thus continue to negotiate 267025944Sjoerg * our already existing value. 267125944Sjoerg */ 267225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 267325944Sjoerg sppp_set_ip_addr(sp, wantaddr); 267425944Sjoerg if (debug) 267525944Sjoerg addlog("[agree] "); 267625944Sjoerg } 267725944Sjoerg } 267825944Sjoerg break; 267925944Sjoerg#ifdef notyet 268025944Sjoerg case IPCP_OPT_COMPRESS: 268125944Sjoerg /* 268225944Sjoerg * Peer wants different compression parameters. 268325944Sjoerg */ 268425944Sjoerg break; 268525944Sjoerg#endif 268625944Sjoerg } 268725944Sjoerg } 268825944Sjoerg if (debug) 268925944Sjoerg addlog("\n"); 269025944Sjoerg free (buf, M_TEMP); 269125944Sjoerg return; 26924910Swollman} 26934910Swollman 269412820Sphkstatic void 269525944Sjoergsppp_ipcp_tlu(struct sppp *sp) 26964910Swollman{ 26974910Swollman} 26984910Swollman 269925944Sjoergstatic void 270025944Sjoergsppp_ipcp_tld(struct sppp *sp) 270125944Sjoerg{ 270225944Sjoerg} 270325944Sjoerg 270425944Sjoergstatic void 270525944Sjoergsppp_ipcp_tls(struct sppp *sp) 270625944Sjoerg{ 270725944Sjoerg /* indicate to LCP that it must stay alive */ 270825944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 270925944Sjoerg} 271025944Sjoerg 271125944Sjoergstatic void 271225944Sjoergsppp_ipcp_tlf(struct sppp *sp) 271325944Sjoerg{ 271425944Sjoerg /* we no longer need LCP */ 271525944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 271630300Sjoerg sppp_lcp_check_and_close(sp); 271725944Sjoerg} 271825944Sjoerg 271925944Sjoergstatic void 272025944Sjoergsppp_ipcp_scr(struct sppp *sp) 272125944Sjoerg{ 272225944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 272325944Sjoerg u_long ouraddr; 272425944Sjoerg int i = 0; 272525944Sjoerg 272625944Sjoerg#ifdef notyet 272725944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 272825944Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 272925944Sjoerg opt[i++] = 6; 273025944Sjoerg opt[i++] = 0; /* VJ header compression */ 273125944Sjoerg opt[i++] = 0x2d; /* VJ header compression */ 273225944Sjoerg opt[i++] = max_slot_id; 273325944Sjoerg opt[i++] = comp_slot_id; 273425944Sjoerg } 273525944Sjoerg#endif 273625944Sjoerg 273725944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 273830300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 273925944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 274025944Sjoerg opt[i++] = 6; 274125944Sjoerg opt[i++] = ouraddr >> 24; 274225944Sjoerg opt[i++] = ouraddr >> 16; 274325944Sjoerg opt[i++] = ouraddr >> 8; 274425944Sjoerg opt[i++] = ouraddr; 274525944Sjoerg } 274625944Sjoerg 274725944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 274825944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 274925944Sjoerg} 275025944Sjoerg 275125944Sjoerg 275225944Sjoerg/* 275330300Sjoerg *--------------------------------------------------------------------------* 275430300Sjoerg * * 275530300Sjoerg * The CHAP implementation. * 275630300Sjoerg * * 275730300Sjoerg *--------------------------------------------------------------------------* 275830300Sjoerg */ 275930300Sjoerg 276030300Sjoerg/* 276130300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 276230300Sjoerg * the control protocols do, since they do have Open and Close events, but 276330300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 276430300Sjoerg * authentication protocols may be different in both directions (this makes 276530300Sjoerg * sense, think of a machine that never accepts incoming calls but only 276630300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 276730300Sjoerg * 276830300Sjoerg * Our state machine for the local authentication protocol (we are requesting 276930300Sjoerg * the peer to authenticate) looks like: 277030300Sjoerg * 277130300Sjoerg * RCA- 277230300Sjoerg * +--------------------------------------------+ 277330300Sjoerg * V scn,tld| 277430300Sjoerg * +--------+ Close +---------+ RCA+ 277530300Sjoerg * | |<----------------------------------| |------+ 277630300Sjoerg * +--->| Closed | TO* | Opened | sca | 277730300Sjoerg * | | |-----+ +-------| |<-----+ 277830300Sjoerg * | +--------+ irc | | +---------+ 277930300Sjoerg * | ^ | | ^ 278030300Sjoerg * | | | | | 278130300Sjoerg * | | | | | 278230300Sjoerg * | TO-| | | | 278330300Sjoerg * | |tld TO+ V | | 278430300Sjoerg * | | +------->+ | | 278530300Sjoerg * | | | | | | 278630300Sjoerg * | +--------+ V | | 278730300Sjoerg * | | |<----+<--------------------+ | 278830300Sjoerg * | | Req- | scr | 278930300Sjoerg * | | Sent | | 279030300Sjoerg * | | | | 279130300Sjoerg * | +--------+ | 279230300Sjoerg * | RCA- | | RCA+ | 279330300Sjoerg * +------+ +------------------------------------------+ 279430300Sjoerg * scn,tld sca,irc,ict,tlu 279530300Sjoerg * 279630300Sjoerg * 279730300Sjoerg * with: 279830300Sjoerg * 279930300Sjoerg * Open: LCP reached authentication phase 280030300Sjoerg * Close: LCP reached terminate phase 280130300Sjoerg * 280230300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 280330300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 280430300Sjoerg * TO+: timeout with restart counter >= 0 280530300Sjoerg * TO-: timeout with restart counter < 0 280630300Sjoerg * TO*: reschedule timeout for CHAP 280730300Sjoerg * 280830300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 280930300Sjoerg * sca: send ack packet (pap-ack, chap-success) 281030300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 281130300Sjoerg * ict: initialize re-challenge timer (CHAP only) 281230300Sjoerg * 281330300Sjoerg * tlu: this-layer-up, LCP reaches network phase 281430300Sjoerg * tld: this-layer-down, LCP enters terminate phase 281530300Sjoerg * 281630300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 281730300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 281830300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 281930300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 282030300Sjoerg * causing LCP to enter terminate phase. 282130300Sjoerg * 282230300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 282330300Sjoerg * expected to send one based on the successful negotiation of PAP as 282430300Sjoerg * the authentication protocol during the LCP option negotiation. 282530300Sjoerg * 282630300Sjoerg * Incoming authentication protocol requests (remote requests 282730300Sjoerg * authentication, we are peer) don't employ a state machine at all, 282830300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 282930300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 283030300Sjoerg * still in authentication phase (thereby violating the standard that 283130300Sjoerg * demands that these NCP packets are to be discarded), so we keep 283230300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 283330300Sjoerg * phase network once we've seen a positive acknowledge for the 283430300Sjoerg * authentication. 283530300Sjoerg */ 283630300Sjoerg 283730300Sjoerg/* 283830300Sjoerg * Handle incoming CHAP packets. 283930300Sjoerg */ 284030300Sjoergvoid 284130300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 284230300Sjoerg{ 284330300Sjoerg STDDCL; 284430300Sjoerg struct lcp_header *h; 284530300Sjoerg int len, x; 284630300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 284730300Sjoerg int value_len, name_len; 284830300Sjoerg MD5_CTX ctx; 284930300Sjoerg 285030300Sjoerg len = m->m_pkthdr.len; 285130300Sjoerg if (len < 4) { 285230300Sjoerg if (debug) 285330300Sjoerg log(LOG_DEBUG, 285430300Sjoerg "%s%d: chap invalid packet length: %d bytes\n", 285530300Sjoerg ifp->if_name, ifp->if_unit, len); 285630300Sjoerg return; 285730300Sjoerg } 285830300Sjoerg h = mtod (m, struct lcp_header*); 285930300Sjoerg if (len > ntohs (h->len)) 286030300Sjoerg len = ntohs (h->len); 286130300Sjoerg 286230300Sjoerg switch (h->type) { 286330300Sjoerg /* challenge, failure and success are his authproto */ 286430300Sjoerg case CHAP_CHALLENGE: 286530300Sjoerg value = 1 + (u_char*)(h+1); 286630300Sjoerg value_len = value[-1]; 286730300Sjoerg name = value + value_len; 286830300Sjoerg name_len = len - value_len - 5; 286930300Sjoerg if (name_len < 0) { 287030300Sjoerg if (debug) { 287130300Sjoerg log(LOG_DEBUG, 287230300Sjoerg "%s%d: chap corrupted challenge " 287330300Sjoerg "<%s id=0x%x len=%d", 287430300Sjoerg ifp->if_name, ifp->if_unit, 287530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 287630300Sjoerg h->ident, ntohs(h->len)); 287730300Sjoerg if (len > 4) 287830300Sjoerg sppp_print_bytes((u_char*) (h+1), len-4); 287930300Sjoerg addlog(">\n"); 288030300Sjoerg } 288130300Sjoerg break; 288230300Sjoerg } 288330300Sjoerg 288430300Sjoerg if (debug) { 288530300Sjoerg log(LOG_DEBUG, 288630300Sjoerg "%s%d: chap input <%s id=0x%x len=%d name=", 288730300Sjoerg ifp->if_name, ifp->if_unit, 288830300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 288930300Sjoerg ntohs(h->len)); 289030300Sjoerg sppp_print_string((char*) name, name_len); 289130300Sjoerg addlog(" value-size=%d value=", value_len); 289230300Sjoerg sppp_print_bytes(value, value_len); 289330300Sjoerg addlog(">\n"); 289430300Sjoerg } 289530300Sjoerg 289630300Sjoerg /* Compute reply value. */ 289730300Sjoerg MD5Init(&ctx); 289830300Sjoerg MD5Update(&ctx, &h->ident, 1); 289930300Sjoerg MD5Update(&ctx, sp->myauth.secret, 290030300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 290130300Sjoerg MD5Update(&ctx, value, value_len); 290230300Sjoerg MD5Final(digest, &ctx); 290330300Sjoerg dsize = sizeof digest; 290430300Sjoerg 290530300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 290630300Sjoerg sizeof dsize, (const char *)&dsize, 290730300Sjoerg sizeof digest, digest, 290830300Sjoerg sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 290930300Sjoerg sp->myauth.name, 291030300Sjoerg 0); 291130300Sjoerg break; 291230300Sjoerg 291330300Sjoerg case CHAP_SUCCESS: 291430300Sjoerg if (debug) { 291530300Sjoerg log(LOG_DEBUG, "%s%d: chap success", 291630300Sjoerg ifp->if_name, ifp->if_unit); 291730300Sjoerg if (len > 4) { 291830300Sjoerg addlog(": "); 291930300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 292030300Sjoerg } 292130300Sjoerg addlog("\n"); 292230300Sjoerg } 292330300Sjoerg x = splimp(); 292430300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 292530300Sjoerg if (sp->myauth.proto == PPP_CHAP && 292632169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 292730300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 292830300Sjoerg /* 292930300Sjoerg * We are authenticator for CHAP but didn't 293030300Sjoerg * complete yet. Leave it to tlu to proceed 293130300Sjoerg * to network phase. 293230300Sjoerg */ 293330300Sjoerg splx(x); 293430300Sjoerg break; 293530300Sjoerg } 293630300Sjoerg splx(x); 293730300Sjoerg sppp_phase_network(sp); 293830300Sjoerg break; 293930300Sjoerg 294030300Sjoerg case CHAP_FAILURE: 294130300Sjoerg if (debug) { 294230300Sjoerg log(LOG_INFO, "%s%d: chap failure", 294330300Sjoerg ifp->if_name, ifp->if_unit); 294430300Sjoerg if (len > 4) { 294530300Sjoerg addlog(": "); 294630300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 294730300Sjoerg } 294830300Sjoerg addlog("\n"); 294930300Sjoerg } else 295030300Sjoerg log(LOG_INFO, "%s%d: chap failure\n", 295130300Sjoerg ifp->if_name, ifp->if_unit); 295230300Sjoerg /* await LCP shutdown by authenticator */ 295330300Sjoerg break; 295430300Sjoerg 295530300Sjoerg /* response is my authproto */ 295630300Sjoerg case CHAP_RESPONSE: 295730300Sjoerg value = 1 + (u_char*)(h+1); 295830300Sjoerg value_len = value[-1]; 295930300Sjoerg name = value + value_len; 296030300Sjoerg name_len = len - value_len - 5; 296130300Sjoerg if (name_len < 0) { 296230300Sjoerg if (debug) { 296330300Sjoerg log(LOG_DEBUG, 296430300Sjoerg "%s%d: chap corrupted response " 296530300Sjoerg "<%s id=0x%x len=%d", 296630300Sjoerg ifp->if_name, ifp->if_unit, 296730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 296830300Sjoerg h->ident, ntohs(h->len)); 296930300Sjoerg if (len > 4) 297030300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 297130300Sjoerg addlog(">\n"); 297230300Sjoerg } 297330300Sjoerg break; 297430300Sjoerg } 297530300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 297630300Sjoerg if (debug) 297730300Sjoerg log(LOG_DEBUG, 297830300Sjoerg "%s%d: chap dropping response for old ID " 297930300Sjoerg "(got %d, expected %d)\n", 298030300Sjoerg h->ident, sp->confid[IDX_CHAP]); 298130300Sjoerg break; 298230300Sjoerg } 298330300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 298430300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 298530300Sjoerg log(LOG_INFO, "%s%d: chap response, his name ", 298630300Sjoerg ifp->if_name, ifp->if_unit); 298730300Sjoerg sppp_print_string(name, name_len); 298830300Sjoerg addlog(" != expected "); 298930300Sjoerg sppp_print_string(sp->hisauth.name, 299030300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 299130300Sjoerg addlog("\n"); 299230300Sjoerg } 299330300Sjoerg if (debug) { 299430300Sjoerg log(LOG_DEBUG, "%s%d: chap input(%s) " 299530300Sjoerg "<%s id=0x%x len=%d name=", 299630300Sjoerg ifp->if_name, ifp->if_unit, 299730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 299830300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 299930300Sjoerg h->ident, ntohs (h->len)); 300030300Sjoerg sppp_print_string((char*)name, name_len); 300130300Sjoerg addlog(" value-size=%d value=", value_len); 300230300Sjoerg sppp_print_bytes(value, value_len); 300330300Sjoerg addlog(">\n"); 300430300Sjoerg } 300530300Sjoerg if (value_len != AUTHKEYLEN) { 300630300Sjoerg if (debug) 300730300Sjoerg log(LOG_DEBUG, 300830300Sjoerg "%s%d: chap bad hash value length: " 300930300Sjoerg "%d bytes, should be %d\n", 301030300Sjoerg ifp->if_name, ifp->if_unit, value_len, 301130300Sjoerg AUTHKEYLEN); 301230300Sjoerg break; 301330300Sjoerg } 301430300Sjoerg 301530300Sjoerg MD5Init(&ctx); 301630300Sjoerg MD5Update(&ctx, &h->ident, 1); 301730300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 301830300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 301930300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 302030300Sjoerg MD5Final(digest, &ctx); 302130300Sjoerg 302230300Sjoerg#define FAILMSG "Failed..." 302330300Sjoerg#define SUCCMSG "Welcome!" 302430300Sjoerg 302530300Sjoerg if (value_len != sizeof digest || 302630300Sjoerg bcmp(digest, value, value_len) != 0) { 302730300Sjoerg /* action scn, tld */ 302830300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 302930300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 303030300Sjoerg 0); 303130300Sjoerg chap.tld(sp); 303230300Sjoerg break; 303330300Sjoerg } 303430300Sjoerg /* action sca, perhaps tlu */ 303530300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 303630300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 303730300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 303830300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 303930300Sjoerg 0); 304030300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 304130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 304230300Sjoerg chap.tlu(sp); 304330300Sjoerg } 304430300Sjoerg break; 304530300Sjoerg 304630300Sjoerg default: 304730300Sjoerg /* Unknown CHAP packet type -- ignore. */ 304830300Sjoerg if (debug) { 304930300Sjoerg log(LOG_DEBUG, "%s%d: chap unknown input(%s) " 305030300Sjoerg "<0x%x id=0x%xh len=%d", 305130300Sjoerg ifp->if_name, ifp->if_unit, 305230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 305330300Sjoerg h->type, h->ident, ntohs(h->len)); 305430300Sjoerg if (len > 4) 305530300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 305630300Sjoerg addlog(">\n"); 305730300Sjoerg } 305830300Sjoerg break; 305930300Sjoerg 306030300Sjoerg } 306130300Sjoerg} 306230300Sjoerg 306330300Sjoergstatic void 306430300Sjoergsppp_chap_init(struct sppp *sp) 306530300Sjoerg{ 306630300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 306730300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 306830300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 306930300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 307030300Sjoerg} 307130300Sjoerg 307230300Sjoergstatic void 307330300Sjoergsppp_chap_open(struct sppp *sp) 307430300Sjoerg{ 307530300Sjoerg if (sp->myauth.proto == PPP_CHAP && 307630300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 307730300Sjoerg /* we are authenticator for CHAP, start it */ 307830300Sjoerg chap.scr(sp); 307930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 308030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 308130300Sjoerg } 308230300Sjoerg /* nothing to be done if we are peer, await a challenge */ 308330300Sjoerg} 308430300Sjoerg 308530300Sjoergstatic void 308630300Sjoergsppp_chap_close(struct sppp *sp) 308730300Sjoerg{ 308830300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 308930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 309030300Sjoerg} 309130300Sjoerg 309230300Sjoergstatic void 309330300Sjoergsppp_chap_TO(void *cookie) 309430300Sjoerg{ 309530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 309630300Sjoerg STDDCL; 309730300Sjoerg int s; 309830300Sjoerg 309930300Sjoerg s = splimp(); 310030300Sjoerg if (debug) 310130300Sjoerg log(LOG_DEBUG, "%s%d: chap TO(%s) rst_counter = %d\n", 310230300Sjoerg ifp->if_name, ifp->if_unit, 310330300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 310430300Sjoerg sp->rst_counter[IDX_CHAP]); 310530300Sjoerg 310630300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 310730300Sjoerg /* TO- event */ 310830300Sjoerg switch (sp->state[IDX_CHAP]) { 310930300Sjoerg case STATE_REQ_SENT: 311030300Sjoerg chap.tld(sp); 311130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 311230300Sjoerg break; 311330300Sjoerg } 311430300Sjoerg else 311530300Sjoerg /* TO+ (or TO*) event */ 311630300Sjoerg switch (sp->state[IDX_CHAP]) { 311730300Sjoerg case STATE_OPENED: 311830300Sjoerg /* TO* event */ 311930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 312030300Sjoerg /* fall through */ 312130300Sjoerg case STATE_REQ_SENT: 312230300Sjoerg chap.scr(sp); 312330300Sjoerg /* sppp_cp_change_state() will restart the timer */ 312430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 312530300Sjoerg break; 312630300Sjoerg } 312730300Sjoerg 312830300Sjoerg splx(s); 312930300Sjoerg} 313030300Sjoerg 313130300Sjoergstatic void 313230300Sjoergsppp_chap_tlu(struct sppp *sp) 313330300Sjoerg{ 313430300Sjoerg STDDCL; 313530300Sjoerg int i, x; 313630300Sjoerg 313730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 313830300Sjoerg 313930300Sjoerg /* 314030300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 314130300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 314230300Sjoerg * initial challenge-response exchange has taken place. 314330300Sjoerg * Provide for an option to avoid rechallenges. 314430300Sjoerg */ 314530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 314630300Sjoerg /* 314730300Sjoerg * Compute the re-challenge timeout. This will yield 314830300Sjoerg * a number between 300 and 810 seconds. 314930300Sjoerg */ 315030300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 315130300Sjoerg 315230300Sjoerg sp->ch[IDX_CHAP] = timeout(chap.TO, (void *)sp, i * hz); 315330300Sjoerg } 315430300Sjoerg 315530300Sjoerg if (debug) { 315630300Sjoerg log(LOG_DEBUG, 315730300Sjoerg "%s%d: chap %s, ", 315830300Sjoerg ifp->if_name, ifp->if_unit, 315930300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 316030300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 316130300Sjoerg addlog("next re-challenge in %d seconds\n", i); 316230300Sjoerg else 316330300Sjoerg addlog("re-challenging supressed\n"); 316430300Sjoerg } 316530300Sjoerg 316630300Sjoerg x = splimp(); 316730300Sjoerg /* indicate to LCP that we need to be closed down */ 316830300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 316930300Sjoerg 317030300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 317130300Sjoerg /* 317230300Sjoerg * Remote is authenticator, but his auth proto didn't 317330300Sjoerg * complete yet. Defer the transition to network 317430300Sjoerg * phase. 317530300Sjoerg */ 317630300Sjoerg splx(x); 317730300Sjoerg return; 317830300Sjoerg } 317930300Sjoerg splx(x); 318030300Sjoerg 318130300Sjoerg /* 318230300Sjoerg * If we are already in phase network, we are done here. This 318330300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 318430300Sjoerg */ 318530300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 318630300Sjoerg sppp_phase_network(sp); 318730300Sjoerg} 318830300Sjoerg 318930300Sjoergstatic void 319030300Sjoergsppp_chap_tld(struct sppp *sp) 319130300Sjoerg{ 319230300Sjoerg STDDCL; 319330300Sjoerg 319430300Sjoerg if (debug) 319530300Sjoerg log(LOG_DEBUG, "%s%d: chap tld\n", ifp->if_name, ifp->if_unit); 319630300Sjoerg untimeout(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 319730300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 319830300Sjoerg 319930300Sjoerg lcp.Close(sp); 320030300Sjoerg} 320130300Sjoerg 320230300Sjoergstatic void 320330300Sjoergsppp_chap_scr(struct sppp *sp) 320430300Sjoerg{ 320530300Sjoerg struct timeval tv; 320630300Sjoerg u_long *ch, seed; 320730300Sjoerg u_char clen; 320830300Sjoerg 320930300Sjoerg /* Compute random challenge. */ 321030300Sjoerg ch = (u_long *)sp->myauth.challenge; 321130300Sjoerg microtime(&tv); 321230300Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 321330300Sjoerg ch[0] = seed ^ random(); 321430300Sjoerg ch[1] = seed ^ random(); 321530300Sjoerg ch[2] = seed ^ random(); 321630300Sjoerg ch[3] = seed ^ random(); 321730300Sjoerg clen = AUTHKEYLEN; 321830300Sjoerg 321930300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 322030300Sjoerg 322130300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 322230300Sjoerg sizeof clen, (const char *)&clen, 322330300Sjoerg AUTHKEYLEN, sp->myauth.challenge, 322430300Sjoerg sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 322530300Sjoerg sp->myauth.name, 322630300Sjoerg 0); 322730300Sjoerg} 322830300Sjoerg/* 322930300Sjoerg *--------------------------------------------------------------------------* 323030300Sjoerg * * 323130300Sjoerg * The PAP implementation. * 323230300Sjoerg * * 323330300Sjoerg *--------------------------------------------------------------------------* 323430300Sjoerg */ 323530300Sjoerg/* 323630300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 323730300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 323830300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 323930300Sjoerg * retry counter is expired). 324030300Sjoerg */ 324130300Sjoerg 324230300Sjoerg/* 324330300Sjoerg * Handle incoming PAP packets. */ 324430300Sjoergstatic void 324530300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 324630300Sjoerg{ 324730300Sjoerg STDDCL; 324830300Sjoerg struct lcp_header *h; 324930300Sjoerg int len, x; 325030300Sjoerg u_char *name, *passwd, mlen; 325130300Sjoerg int name_len, passwd_len; 325230300Sjoerg 325330300Sjoerg len = m->m_pkthdr.len; 325430300Sjoerg if (len < 5) { 325530300Sjoerg if (debug) 325630300Sjoerg log(LOG_DEBUG, 325730300Sjoerg "%s%d: pap invalid packet length: %d bytes\n", 325830300Sjoerg ifp->if_name, ifp->if_unit, len); 325930300Sjoerg return; 326030300Sjoerg } 326130300Sjoerg h = mtod (m, struct lcp_header*); 326230300Sjoerg if (len > ntohs (h->len)) 326330300Sjoerg len = ntohs (h->len); 326430300Sjoerg switch (h->type) { 326530300Sjoerg /* PAP request is my authproto */ 326630300Sjoerg case PAP_REQ: 326730300Sjoerg name = 1 + (u_char*)(h+1); 326830300Sjoerg name_len = name[-1]; 326930300Sjoerg passwd = name + name_len + 1; 327030300Sjoerg if (name_len > len - 6 || 327130300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 327230300Sjoerg if (debug) { 327330300Sjoerg log(LOG_DEBUG, "%s%d: pap corrupted input " 327430300Sjoerg "<%s id=0x%x len=%d", 327530300Sjoerg ifp->if_name, ifp->if_unit, 327630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 327730300Sjoerg h->ident, ntohs(h->len)); 327830300Sjoerg if (len > 4) 327930300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 328030300Sjoerg addlog(">\n"); 328130300Sjoerg } 328230300Sjoerg break; 328330300Sjoerg } 328430300Sjoerg if (debug) { 328530300Sjoerg log(LOG_DEBUG, "%s%d: pap input(%s) " 328630300Sjoerg "<%s id=0x%x len=%d name=", 328730300Sjoerg ifp->if_name, ifp->if_unit, 328830300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 328930300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 329030300Sjoerg h->ident, ntohs(h->len)); 329130300Sjoerg sppp_print_string((char*)name, name_len); 329230300Sjoerg addlog(" passwd="); 329330300Sjoerg sppp_print_string((char*)passwd, passwd_len); 329430300Sjoerg addlog(">\n"); 329530300Sjoerg } 329630300Sjoerg if (name_len > AUTHNAMELEN || 329730300Sjoerg passwd_len > AUTHKEYLEN || 329830300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 329930300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 330030300Sjoerg /* action scn, tld */ 330130300Sjoerg mlen = sizeof(FAILMSG) - 1; 330230300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 330330300Sjoerg sizeof mlen, (const char *)&mlen, 330430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 330530300Sjoerg 0); 330630300Sjoerg pap.tld(sp); 330730300Sjoerg break; 330830300Sjoerg } 330930300Sjoerg /* action sca, perhaps tlu */ 331030300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 331130300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 331230300Sjoerg mlen = sizeof(SUCCMSG) - 1; 331330300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 331430300Sjoerg sizeof mlen, (const char *)&mlen, 331530300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 331630300Sjoerg 0); 331730300Sjoerg } 331830300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 331930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 332030300Sjoerg pap.tlu(sp); 332130300Sjoerg } 332230300Sjoerg break; 332330300Sjoerg 332430300Sjoerg /* ack and nak are his authproto */ 332530300Sjoerg case PAP_ACK: 332630300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 332730300Sjoerg if (debug) { 332830300Sjoerg log(LOG_DEBUG, "%s%d: pap success", 332930300Sjoerg ifp->if_name, ifp->if_unit); 333030300Sjoerg name_len = *((char *)h); 333130300Sjoerg if (len > 5 && name_len) { 333230300Sjoerg addlog(": "); 333330300Sjoerg sppp_print_string((char*)(h+1), name_len); 333430300Sjoerg } 333530300Sjoerg addlog("\n"); 333630300Sjoerg } 333730300Sjoerg x = splimp(); 333830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 333930300Sjoerg if (sp->myauth.proto == PPP_PAP && 334032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 334130300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 334230300Sjoerg /* 334330300Sjoerg * We are authenticator for PAP but didn't 334430300Sjoerg * complete yet. Leave it to tlu to proceed 334530300Sjoerg * to network phase. 334630300Sjoerg */ 334730300Sjoerg splx(x); 334830300Sjoerg break; 334930300Sjoerg } 335030300Sjoerg splx(x); 335130300Sjoerg sppp_phase_network(sp); 335230300Sjoerg break; 335330300Sjoerg 335430300Sjoerg case PAP_NAK: 335530300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 335630300Sjoerg if (debug) { 335730300Sjoerg log(LOG_INFO, "%s%d: pap failure", 335830300Sjoerg ifp->if_name, ifp->if_unit); 335930300Sjoerg name_len = *((char *)h); 336030300Sjoerg if (len > 5 && name_len) { 336130300Sjoerg addlog(": "); 336230300Sjoerg sppp_print_string((char*)(h+1), name_len); 336330300Sjoerg } 336430300Sjoerg addlog("\n"); 336530300Sjoerg } else 336630300Sjoerg log(LOG_INFO, "%s%d: pap failure\n", 336730300Sjoerg ifp->if_name, ifp->if_unit); 336830300Sjoerg /* await LCP shutdown by authenticator */ 336930300Sjoerg break; 337030300Sjoerg 337130300Sjoerg default: 337230300Sjoerg /* Unknown PAP packet type -- ignore. */ 337330300Sjoerg if (debug) { 337430300Sjoerg log(LOG_DEBUG, "%s%d: pap corrupted input " 337530300Sjoerg "<0x%x id=0x%x len=%d", 337630300Sjoerg ifp->if_name, ifp->if_unit, 337730300Sjoerg h->type, h->ident, ntohs(h->len)); 337830300Sjoerg if (len > 4) 337930300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 338030300Sjoerg addlog(">\n"); 338130300Sjoerg } 338230300Sjoerg break; 338330300Sjoerg 338430300Sjoerg } 338530300Sjoerg} 338630300Sjoerg 338730300Sjoergstatic void 338830300Sjoergsppp_pap_init(struct sppp *sp) 338930300Sjoerg{ 339030300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 339130300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 339230300Sjoerg sp->fail_counter[IDX_PAP] = 0; 339330300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 339430300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 339530300Sjoerg} 339630300Sjoerg 339730300Sjoergstatic void 339830300Sjoergsppp_pap_open(struct sppp *sp) 339930300Sjoerg{ 340030300Sjoerg if (sp->hisauth.proto == PPP_PAP && 340130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 340230300Sjoerg /* we are authenticator for PAP, start our timer */ 340330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 340430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 340530300Sjoerg } 340630300Sjoerg if (sp->myauth.proto == PPP_PAP) { 340730300Sjoerg /* we are peer, send a request, and start a timer */ 340830300Sjoerg pap.scr(sp); 340930300Sjoerg sp->pap_my_to_ch = timeout(sppp_pap_my_TO, (void *)sp, 341030300Sjoerg sp->lcp.timeout); 341130300Sjoerg } 341230300Sjoerg} 341330300Sjoerg 341430300Sjoergstatic void 341530300Sjoergsppp_pap_close(struct sppp *sp) 341630300Sjoerg{ 341730300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 341830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 341930300Sjoerg} 342030300Sjoerg 342130300Sjoerg/* 342230300Sjoerg * That's the timeout routine if we are authenticator. Since the 342330300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 342430300Sjoerg */ 342530300Sjoergstatic void 342630300Sjoergsppp_pap_TO(void *cookie) 342730300Sjoerg{ 342830300Sjoerg struct sppp *sp = (struct sppp *)cookie; 342930300Sjoerg STDDCL; 343030300Sjoerg int s; 343130300Sjoerg 343230300Sjoerg s = splimp(); 343330300Sjoerg if (debug) 343430300Sjoerg log(LOG_DEBUG, "%s%d: pap TO(%s) rst_counter = %d\n", 343530300Sjoerg ifp->if_name, ifp->if_unit, 343630300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 343730300Sjoerg sp->rst_counter[IDX_PAP]); 343830300Sjoerg 343930300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 344030300Sjoerg /* TO- event */ 344130300Sjoerg switch (sp->state[IDX_PAP]) { 344230300Sjoerg case STATE_REQ_SENT: 344330300Sjoerg pap.tld(sp); 344430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 344530300Sjoerg break; 344630300Sjoerg } 344730300Sjoerg else 344830300Sjoerg /* TO+ event, not very much we could do */ 344930300Sjoerg switch (sp->state[IDX_PAP]) { 345030300Sjoerg case STATE_REQ_SENT: 345130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 345230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 345330300Sjoerg break; 345430300Sjoerg } 345530300Sjoerg 345630300Sjoerg splx(s); 345730300Sjoerg} 345830300Sjoerg 345930300Sjoerg/* 346030300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 346130300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 346230300Sjoerg * XXX We should impose a max counter. 346330300Sjoerg */ 346430300Sjoergstatic void 346530300Sjoergsppp_pap_my_TO(void *cookie) 346630300Sjoerg{ 346730300Sjoerg struct sppp *sp = (struct sppp *)cookie; 346830300Sjoerg STDDCL; 346930300Sjoerg 347030300Sjoerg if (debug) 347130300Sjoerg log(LOG_DEBUG, "%s%d: pap peer TO\n", 347230300Sjoerg ifp->if_name, ifp->if_unit); 347330300Sjoerg 347430300Sjoerg pap.scr(sp); 347530300Sjoerg} 347630300Sjoerg 347730300Sjoergstatic void 347830300Sjoergsppp_pap_tlu(struct sppp *sp) 347930300Sjoerg{ 348030300Sjoerg STDDCL; 348130300Sjoerg int x; 348230300Sjoerg 348330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 348430300Sjoerg 348530300Sjoerg if (debug) 348630300Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 348730300Sjoerg ifp->if_name, ifp->if_unit, pap.name); 348830300Sjoerg 348930300Sjoerg x = splimp(); 349030300Sjoerg /* indicate to LCP that we need to be closed down */ 349130300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 349230300Sjoerg 349330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 349430300Sjoerg /* 349530300Sjoerg * Remote is authenticator, but his auth proto didn't 349630300Sjoerg * complete yet. Defer the transition to network 349730300Sjoerg * phase. 349830300Sjoerg */ 349930300Sjoerg splx(x); 350030300Sjoerg return; 350130300Sjoerg } 350230300Sjoerg splx(x); 350330300Sjoerg sppp_phase_network(sp); 350430300Sjoerg} 350530300Sjoerg 350630300Sjoergstatic void 350730300Sjoergsppp_pap_tld(struct sppp *sp) 350830300Sjoerg{ 350930300Sjoerg STDDCL; 351030300Sjoerg 351130300Sjoerg if (debug) 351230300Sjoerg log(LOG_DEBUG, "%s%d: pap tld\n", ifp->if_name, ifp->if_unit); 351330300Sjoerg untimeout(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 351430300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 351530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 351630300Sjoerg 351730300Sjoerg lcp.Close(sp); 351830300Sjoerg} 351930300Sjoerg 352030300Sjoergstatic void 352130300Sjoergsppp_pap_scr(struct sppp *sp) 352230300Sjoerg{ 352330300Sjoerg STDDCL; 352430300Sjoerg u_char idlen, pwdlen; 352530300Sjoerg 352630300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 352730300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 352830300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 352930300Sjoerg 353030300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 353130300Sjoerg sizeof idlen, (const char *)&idlen, 353230300Sjoerg (unsigned)idlen, sp->myauth.name, 353330300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 353430300Sjoerg (unsigned)pwdlen, sp->myauth.secret, 353530300Sjoerg 0); 353630300Sjoerg} 353730300Sjoerg/* 353825944Sjoerg * Random miscellaneous functions. 353925944Sjoerg */ 354025944Sjoerg 35414910Swollman/* 354230300Sjoerg * Send a PAP or CHAP proto packet. 354330300Sjoerg * 354430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 354530300Sjoerg * ``unsigned mlen, const u_char *msg''. Processing will stop iff 354630300Sjoerg * mlen == 0. 354730300Sjoerg */ 354830300Sjoerg 354930300Sjoergstatic void 355030300Sjoergsppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, 355130300Sjoerg ...) 355230300Sjoerg{ 355330300Sjoerg STDDCL; 355430300Sjoerg struct ppp_header *h; 355530300Sjoerg struct lcp_header *lh; 355630300Sjoerg struct mbuf *m; 355730300Sjoerg u_char *p; 355830300Sjoerg int len; 355930300Sjoerg unsigned mlen; 356030300Sjoerg const char *msg; 356130300Sjoerg va_list ap; 356230300Sjoerg 356330300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 356430300Sjoerg if (! m) 356530300Sjoerg return; 356630300Sjoerg m->m_pkthdr.rcvif = 0; 356730300Sjoerg 356830300Sjoerg h = mtod (m, struct ppp_header*); 356930300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 357030300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 357130300Sjoerg h->protocol = htons(cp->proto); 357230300Sjoerg 357330300Sjoerg lh = (struct lcp_header*)(h + 1); 357430300Sjoerg lh->type = type; 357530300Sjoerg lh->ident = id; 357630300Sjoerg p = (u_char*) (lh+1); 357730300Sjoerg 357830300Sjoerg va_start(ap, id); 357930300Sjoerg len = 0; 358030300Sjoerg 358130300Sjoerg while ((mlen = va_arg(ap, unsigned)) != 0) { 358230300Sjoerg msg = va_arg(ap, const char *); 358330300Sjoerg len += mlen; 358430300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 358530300Sjoerg va_end(ap); 358630300Sjoerg m_freem(m); 358730300Sjoerg return; 358830300Sjoerg } 358930300Sjoerg 359030300Sjoerg bcopy(msg, p, mlen); 359130300Sjoerg p += mlen; 359230300Sjoerg } 359330300Sjoerg va_end(ap); 359430300Sjoerg 359530300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 359630300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 359730300Sjoerg 359830300Sjoerg if (debug) { 359930300Sjoerg log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d", 360030300Sjoerg ifp->if_name, ifp->if_unit, cp->name, 360130300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 360230300Sjoerg lh->ident, ntohs(lh->len)); 360330300Sjoerg if (len) 360430300Sjoerg sppp_print_bytes((u_char*) (lh+1), len); 360530300Sjoerg addlog(">\n"); 360630300Sjoerg } 360730300Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 360830300Sjoerg IF_DROP (&sp->pp_fastq); 360930300Sjoerg IF_DROP (&ifp->if_snd); 361030300Sjoerg m_freem (m); 361130300Sjoerg ++ifp->if_oerrors; 361230300Sjoerg } else 361330300Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 361430300Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 361530300Sjoerg (*ifp->if_start) (ifp); 361630300Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 361730300Sjoerg} 361830300Sjoerg 361930300Sjoerg/* 362025944Sjoerg * Flush interface queue. 36214910Swollman */ 362212820Sphkstatic void 362325944Sjoergsppp_qflush(struct ifqueue *ifq) 36244910Swollman{ 362525944Sjoerg struct mbuf *m, *n; 36264910Swollman 362725944Sjoerg n = ifq->ifq_head; 362825944Sjoerg while ((m = n)) { 362925944Sjoerg n = m->m_act; 363025944Sjoerg m_freem (m); 363111189Sjkh } 363225944Sjoerg ifq->ifq_head = 0; 363325944Sjoerg ifq->ifq_tail = 0; 363425944Sjoerg ifq->ifq_len = 0; 363525944Sjoerg} 363625944Sjoerg 363725944Sjoerg/* 363825944Sjoerg * Send keepalive packets, every 10 seconds. 363925944Sjoerg */ 364025944Sjoergstatic void 364125944Sjoergsppp_keepalive(void *dummy) 364225944Sjoerg{ 364325944Sjoerg struct sppp *sp; 364425944Sjoerg int s; 364525944Sjoerg 364625944Sjoerg s = splimp(); 364725944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 364825944Sjoerg struct ifnet *ifp = &sp->pp_if; 364925944Sjoerg 365025944Sjoerg /* Keepalive mode disabled or channel down? */ 365125944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 365225944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 365325944Sjoerg continue; 365425944Sjoerg 365525944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 365625944Sjoerg if (! (sp->pp_flags & PP_CISCO) && 365725944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 365825944Sjoerg continue; 365925944Sjoerg 366025944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 366125944Sjoerg /* No keepalive packets got. Stop the interface. */ 366225944Sjoerg printf ("%s%d: down\n", ifp->if_name, ifp->if_unit); 366325944Sjoerg if_down (ifp); 366426018Sjoerg sppp_qflush (&sp->pp_cpq); 366525944Sjoerg if (! (sp->pp_flags & PP_CISCO)) { 366625944Sjoerg /* XXX */ 366725944Sjoerg /* Shut down the PPP link. */ 366825944Sjoerg lcp.Down(sp); 366925944Sjoerg /* Initiate negotiation. XXX */ 367025944Sjoerg lcp.Up(sp); 367125944Sjoerg } 36724910Swollman } 367325944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 367425944Sjoerg ++sp->pp_alivecnt; 367525944Sjoerg if (sp->pp_flags & PP_CISCO) 367625944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 367725944Sjoerg sp->pp_rseq); 367825944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 367925944Sjoerg long nmagic = htonl (sp->lcp.magic); 368025944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 368125944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 368225944Sjoerg sp->lcp.echoid, 4, &nmagic); 368325944Sjoerg } 36844910Swollman } 368525944Sjoerg splx(s); 368629681Sgibbs keepalive_ch = timeout(sppp_keepalive, 0, hz * 10); 36874910Swollman} 36884910Swollman 368925944Sjoerg/* 369025944Sjoerg * Get both IP addresses. 369125944Sjoerg */ 369225944Sjoergstatic void 369330300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 369425944Sjoerg{ 369525944Sjoerg struct ifnet *ifp = &sp->pp_if; 369625944Sjoerg struct ifaddr *ifa; 369730300Sjoerg struct sockaddr_in *si, *sm; 369825944Sjoerg u_long ssrc, ddst; 369925944Sjoerg 370025944Sjoerg ssrc = ddst = 0L; 370125944Sjoerg /* 370225944Sjoerg * Pick the first AF_INET address from the list, 370325944Sjoerg * aliases don't make any sense on a p2p link anyway. 370425944Sjoerg */ 370525944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 370630300Sjoerg ifa; 370725944Sjoerg ifa = ifa->ifa_link.tqe_next) 370825944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 370925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 371030300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 371125944Sjoerg if (si) 371225944Sjoerg break; 371325944Sjoerg } 371425944Sjoerg if (ifa) { 371530300Sjoerg if (si && si->sin_addr.s_addr) { 371625944Sjoerg ssrc = si->sin_addr.s_addr; 371730300Sjoerg if (srcmask) 371830300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 371930300Sjoerg } 372025944Sjoerg 372125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 372225944Sjoerg if (si && si->sin_addr.s_addr) 372325944Sjoerg ddst = si->sin_addr.s_addr; 372425944Sjoerg } 372525944Sjoerg 372625944Sjoerg if (dst) *dst = ntohl(ddst); 372725944Sjoerg if (src) *src = ntohl(ssrc); 372825944Sjoerg} 372925944Sjoerg 373025944Sjoerg/* 373125944Sjoerg * Set my IP address. Must be called at splimp. 373225944Sjoerg */ 373325944Sjoergstatic void 373425944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 373525944Sjoerg{ 373625944Sjoerg struct ifnet *ifp = &sp->pp_if; 373725944Sjoerg struct ifaddr *ifa; 373825944Sjoerg struct sockaddr_in *si; 373925944Sjoerg u_long ssrc, ddst; 374025944Sjoerg 374125944Sjoerg /* 374225944Sjoerg * Pick the first AF_INET address from the list, 374325944Sjoerg * aliases don't make any sense on a p2p link anyway. 374425944Sjoerg */ 374525944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 374630300Sjoerg ifa; 374725944Sjoerg ifa = ifa->ifa_link.tqe_next) 374825944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 374925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 375025944Sjoerg if (si) 375125944Sjoerg break; 375225944Sjoerg } 375325944Sjoerg if (ifa && si) 375425944Sjoerg si->sin_addr.s_addr = htonl(src); 375525944Sjoerg} 375625944Sjoerg 375730300Sjoergstatic int 375830300Sjoergsppp_params(struct sppp *sp, int cmd, void *data) 375930300Sjoerg{ 376030300Sjoerg int subcmd; 376130300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 376230300Sjoerg struct spppreq spr; 376330300Sjoerg 376430300Sjoerg /* 376530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 376630300Sjoerg * Check the cmd word first before attempting to fetch all the 376730300Sjoerg * data. 376830300Sjoerg */ 376930300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 377030300Sjoerg return EFAULT; 377130300Sjoerg 377230300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 377330300Sjoerg return EFAULT; 377430300Sjoerg 377530300Sjoerg switch (subcmd) { 377630300Sjoerg case SPPPIOGDEFS: 377730300Sjoerg if (cmd != SIOCGIFGENERIC) 377830300Sjoerg return EINVAL; 377930300Sjoerg /* 378030300Sjoerg * We copy over the entire current state, but clean 378130300Sjoerg * out some of the stuff we don't wanna pass up. 378230300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 378330300Sjoerg * called by any user. No need to ever get PAP or 378430300Sjoerg * CHAP secrets back to userland anyway. 378530300Sjoerg */ 378630300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 378730300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 378830300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 378930300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 379030300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 379130300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 379230300Sjoerg 379330300Sjoerg case SPPPIOSDEFS: 379430300Sjoerg if (cmd != SIOCSIFGENERIC) 379530300Sjoerg return EINVAL; 379630300Sjoerg /* 379730300Sjoerg * We have a very specific idea of which fields we allow 379830300Sjoerg * being passed back from userland, so to not clobber our 379930300Sjoerg * current state. For one, we only allow setting 380030300Sjoerg * anything if LCP is in dead phase. Once the LCP 380130300Sjoerg * negotiations started, the authentication settings must 380230300Sjoerg * not be changed again. (The administrator can force an 380330300Sjoerg * ifconfig down in order to get LCP back into dead 380430300Sjoerg * phase.) 380530300Sjoerg * 380630300Sjoerg * Also, we only allow for authentication parameters to be 380730300Sjoerg * specified. 380830300Sjoerg * 380930300Sjoerg * XXX Should allow to set or clear pp_flags. 381030300Sjoerg * 381130300Sjoerg * Finally, if the respective authentication protocol to 381230300Sjoerg * be used is set differently than 0, but the secret is 381330300Sjoerg * passed as all zeros, we don't trash the existing secret. 381430300Sjoerg * This allows an administrator to change the system name 381530300Sjoerg * only without clobbering the secret (which he didn't get 381630300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 381730300Sjoerg * secrets are cleared if the authentication protocol is 381830300Sjoerg * reset to 0. 381930300Sjoerg */ 382030300Sjoerg if (sp->pp_phase != PHASE_DEAD) 382130300Sjoerg return EBUSY; 382230300Sjoerg 382330300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 382430300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 382530300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 382630300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 382730300Sjoerg return EINVAL; 382830300Sjoerg 382930300Sjoerg if (spr.defs.myauth.proto == 0) 383030300Sjoerg /* resetting myauth */ 383130300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 383230300Sjoerg else { 383330300Sjoerg /* setting/changing myauth */ 383430300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 383530300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 383630300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 383730300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 383830300Sjoerg AUTHKEYLEN); 383930300Sjoerg } 384030300Sjoerg if (spr.defs.hisauth.proto == 0) 384130300Sjoerg /* resetting hisauth */ 384230300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 384330300Sjoerg else { 384430300Sjoerg /* setting/changing hisauth */ 384530300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 384630300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 384730300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 384830300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 384930300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 385030300Sjoerg AUTHKEYLEN); 385130300Sjoerg } 385230300Sjoerg break; 385330300Sjoerg 385430300Sjoerg default: 385530300Sjoerg return EINVAL; 385630300Sjoerg } 385730300Sjoerg 385830300Sjoerg return 0; 385930300Sjoerg} 386030300Sjoerg 386130300Sjoergstatic void 386230300Sjoergsppp_phase_network(struct sppp *sp) 386330300Sjoerg{ 386430300Sjoerg struct ifnet *ifp = &sp->pp_if; 386530300Sjoerg int i; 386630300Sjoerg u_long mask; 386730300Sjoerg 386830300Sjoerg sp->pp_phase = PHASE_NETWORK; 386930300Sjoerg 387030300Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 387130300Sjoerg sppp_phase_name(sp->pp_phase)); 387230300Sjoerg 387330300Sjoerg /* Notify NCPs now. */ 387430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 387530300Sjoerg if ((cps[i])->flags & CP_NCP) 387630300Sjoerg (cps[i])->Open(sp); 387730300Sjoerg 387830300Sjoerg /* Send Up events to all NCPs. */ 387930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 388030300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 388130300Sjoerg (cps[i])->Up(sp); 388230300Sjoerg 388330300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 388430300Sjoerg sppp_lcp_check_and_close(sp); 388530300Sjoerg} 388630300Sjoerg 388730300Sjoerg 388825706Sjoergstatic const char * 388925944Sjoergsppp_cp_type_name(u_char type) 38904910Swollman{ 389130300Sjoerg static char buf[12]; 38924910Swollman switch (type) { 389330300Sjoerg case CONF_REQ: return "conf-req"; 389430300Sjoerg case CONF_ACK: return "conf-ack"; 389530300Sjoerg case CONF_NAK: return "conf-nak"; 389630300Sjoerg case CONF_REJ: return "conf-rej"; 389730300Sjoerg case TERM_REQ: return "term-req"; 389830300Sjoerg case TERM_ACK: return "term-ack"; 389930300Sjoerg case CODE_REJ: return "code-rej"; 390030300Sjoerg case PROTO_REJ: return "proto-rej"; 390130300Sjoerg case ECHO_REQ: return "echo-req"; 390230300Sjoerg case ECHO_REPLY: return "echo-reply"; 390330300Sjoerg case DISC_REQ: return "discard-req"; 39044910Swollman } 390525706Sjoerg sprintf (buf, "0x%x", type); 390630300Sjoerg return buf; 39074910Swollman} 39084910Swollman 390925706Sjoergstatic const char * 391030300Sjoergsppp_auth_type_name(u_short proto, u_char type) 391130300Sjoerg{ 391230300Sjoerg static char buf[12]; 391330300Sjoerg switch (proto) { 391430300Sjoerg case PPP_CHAP: 391530300Sjoerg switch (type) { 391630300Sjoerg case CHAP_CHALLENGE: return "challenge"; 391730300Sjoerg case CHAP_RESPONSE: return "response"; 391830300Sjoerg case CHAP_SUCCESS: return "success"; 391930300Sjoerg case CHAP_FAILURE: return "failure"; 392030300Sjoerg } 392130300Sjoerg case PPP_PAP: 392230300Sjoerg switch (type) { 392330300Sjoerg case PAP_REQ: return "req"; 392430300Sjoerg case PAP_ACK: return "ack"; 392530300Sjoerg case PAP_NAK: return "nak"; 392630300Sjoerg } 392730300Sjoerg } 392830300Sjoerg sprintf (buf, "0x%x", type); 392930300Sjoerg return buf; 393030300Sjoerg} 393130300Sjoerg 393230300Sjoergstatic const char * 393325944Sjoergsppp_lcp_opt_name(u_char opt) 39344910Swollman{ 393530300Sjoerg static char buf[12]; 393625944Sjoerg switch (opt) { 393730300Sjoerg case LCP_OPT_MRU: return "mru"; 393830300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 393930300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 394030300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 394130300Sjoerg case LCP_OPT_MAGIC: return "magic"; 394230300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 394330300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 39444910Swollman } 394525944Sjoerg sprintf (buf, "0x%x", opt); 394630300Sjoerg return buf; 39474910Swollman} 39484910Swollman 394925944Sjoergstatic const char * 395025944Sjoergsppp_ipcp_opt_name(u_char opt) 395125944Sjoerg{ 395230300Sjoerg static char buf[12]; 395325944Sjoerg switch (opt) { 395430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 395530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 395630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 395725944Sjoerg } 395825944Sjoerg sprintf (buf, "0x%x", opt); 395930300Sjoerg return buf; 396025944Sjoerg} 396125944Sjoerg 396225944Sjoergstatic const char * 396325944Sjoergsppp_state_name(int state) 396425944Sjoerg{ 396525944Sjoerg switch (state) { 396625944Sjoerg case STATE_INITIAL: return "initial"; 396725944Sjoerg case STATE_STARTING: return "starting"; 396825944Sjoerg case STATE_CLOSED: return "closed"; 396925944Sjoerg case STATE_STOPPED: return "stopped"; 397025944Sjoerg case STATE_CLOSING: return "closing"; 397125944Sjoerg case STATE_STOPPING: return "stopping"; 397225944Sjoerg case STATE_REQ_SENT: return "req-sent"; 397325944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 397425944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 397525944Sjoerg case STATE_OPENED: return "opened"; 397625944Sjoerg } 397725944Sjoerg return "illegal"; 397825944Sjoerg} 397925944Sjoerg 398025944Sjoergstatic const char * 398125944Sjoergsppp_phase_name(enum ppp_phase phase) 398225944Sjoerg{ 398325944Sjoerg switch (phase) { 398425944Sjoerg case PHASE_DEAD: return "dead"; 398525944Sjoerg case PHASE_ESTABLISH: return "establish"; 398625944Sjoerg case PHASE_TERMINATE: return "terminate"; 398725944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 398825944Sjoerg case PHASE_NETWORK: return "network"; 398925944Sjoerg } 399025944Sjoerg return "illegal"; 399125944Sjoerg} 399225944Sjoerg 399325944Sjoergstatic const char * 399425944Sjoergsppp_proto_name(u_short proto) 399525944Sjoerg{ 399625944Sjoerg static char buf[12]; 399725944Sjoerg switch (proto) { 399825944Sjoerg case PPP_LCP: return "lcp"; 399925944Sjoerg case PPP_IPCP: return "ipcp"; 400030300Sjoerg case PPP_PAP: return "pap"; 400130300Sjoerg case PPP_CHAP: return "chap"; 400225944Sjoerg } 400325944Sjoerg sprintf(buf, "0x%x", (unsigned)proto); 400425944Sjoerg return buf; 400525944Sjoerg} 400625944Sjoerg 400712820Sphkstatic void 400830300Sjoergsppp_print_bytes(const u_char *p, u_short len) 40094910Swollman{ 401025706Sjoerg addlog(" %x", *p++); 40114910Swollman while (--len > 0) 401225706Sjoerg addlog("-%x", *p++); 40134910Swollman} 401425944Sjoerg 401530300Sjoergstatic void 401630300Sjoergsppp_print_string(const char *p, u_short len) 401730300Sjoerg{ 401830300Sjoerg u_char c; 401930300Sjoerg 402030300Sjoerg while (len-- > 0) { 402130300Sjoerg c = *p++; 402230300Sjoerg /* 402330300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 402430300Sjoerg * using only them, but we don't rely on it. */ 402530300Sjoerg if (c < ' ' || c > '~') 402630300Sjoerg addlog("\\x%x", c); 402730300Sjoerg else 402830300Sjoerg addlog("%c", c); 402930300Sjoerg } 403030300Sjoerg} 403130300Sjoerg 403230300Sjoergstatic const char * 403330300Sjoergsppp_dotted_quad(u_long addr) 403430300Sjoerg{ 403530300Sjoerg static char s[16]; 403630300Sjoerg sprintf(s, "%d.%d.%d.%d", 403730300Sjoerg (addr >> 24) & 0xff, 403830300Sjoerg (addr >> 16) & 0xff, 403930300Sjoerg (addr >> 8) & 0xff, 404030300Sjoerg addr & 0xff); 404130300Sjoerg return s; 404230300Sjoerg} 404330300Sjoerg 404430300Sjoergstatic int 404530300Sjoergsppp_strnlen(u_char *p, int max) 404630300Sjoerg{ 404730300Sjoerg int len; 404830300Sjoerg 404930300Sjoerg for (len = 0; len < max && *p; ++p) 405030300Sjoerg ++len; 405130300Sjoerg return len; 405230300Sjoerg} 405330300Sjoerg 405430300Sjoerg/* a dummy, used to drop uninteresting events */ 405530300Sjoergstatic void 405630300Sjoergsppp_null(struct sppp *unused) 405730300Sjoerg{ 405830300Sjoerg /* do just nothing */ 405930300Sjoerg} 406025944Sjoerg/* 406125944Sjoerg * This file is large. Tell emacs to highlight it nevertheless. 406225944Sjoerg * 406325944Sjoerg * Local Variables: 406430300Sjoerg * hilit-auto-highlight-maxout: 120000 406525944Sjoerg * End: 406625944Sjoerg */ 4067