if_spppsubr.c revision 31742
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 * 2031742Seivind * $Id: if_spppsubr.c,v 1.28 1997/10/11 11:25:28 joerg Exp $ 214910Swollman */ 224910Swollman 2331742Seivind#include "opt_ipx.h" 2431742Seivind 254910Swollman#include <sys/param.h> 264952Sbde#include <sys/systm.h> 274952Sbde#include <sys/kernel.h> 2824204Sbde#include <sys/sockio.h> 294910Swollman#include <sys/socket.h> 3025706Sjoerg#include <sys/syslog.h> 3129024Sbde#include <sys/malloc.h> 324910Swollman#include <sys/mbuf.h> 3330300Sjoerg#include <sys/md5.h> 344910Swollman 354910Swollman#include <net/if.h> 364910Swollman#include <net/netisr.h> 374910Swollman#include <net/if_types.h> 384910Swollman 3930300Sjoerg#include <machine/stdarg.h> 4030300Sjoerg 414910Swollman#ifdef INET 424910Swollman#include <netinet/in.h> 434910Swollman#include <netinet/in_systm.h> 444910Swollman#include <netinet/in_var.h> 454910Swollman#include <netinet/ip.h> 464910Swollman#include <netinet/tcp.h> 474910Swollman#include <netinet/if_ether.h> 484910Swollman#endif 494910Swollman 5011819Sjulian#ifdef IPX 5111819Sjulian#include <netipx/ipx.h> 5211819Sjulian#include <netipx/ipx_if.h> 5311819Sjulian#endif 5411819Sjulian 554910Swollman#ifdef NS 564910Swollman#include <netns/ns.h> 574910Swollman#include <netns/ns_if.h> 584910Swollman#endif 594910Swollman 604910Swollman#ifdef ISO 614910Swollman#include <netiso/argo_debug.h> 624910Swollman#include <netiso/iso.h> 634910Swollman#include <netiso/iso_var.h> 644910Swollman#include <netiso/iso_snpac.h> 654910Swollman#endif 664910Swollman 674910Swollman#include <net/if_sppp.h> 684910Swollman 694910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 704910Swollman 7125944Sjoerg/* 7225944Sjoerg * Interface flags that can be set in an ifconfig command. 7325944Sjoerg * 7425955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 7525944Sjoerg * as being administrative openable, but won't be opened to begin 7625944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 7725944Sjoerg * -link1 will cause the administrative open of the LCP layer. 7825955Sjoerg * 7925955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 8025955Sjoerg * arrive to be sent. 8130300Sjoerg * 8230300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 8330300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 8430300Sjoerg * like 8530300Sjoerg * 8630300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 8730300Sjoerg * 8830300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 8930300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 9025944Sjoerg */ 9125944Sjoerg 9225955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 9325955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 9425944Sjoerg 9530300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 9630300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 9730300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 9830300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 9930300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 10030300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 10130300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 10230300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 10330300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 10430300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1054910Swollman 10625944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 10725944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 10825944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 10925944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 11025944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 11125944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 11225944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 11325944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 11425944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 11525944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 11625944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1174910Swollman 11830300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 11930300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 12030300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 12130300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 12230300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 12330300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 12430300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 12530300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1264910Swollman 12725944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 12825944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 12925944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1304910Swollman 13130300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 13230300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 13330300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1344910Swollman 13530300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 13630300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 13730300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 13830300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 13930300Sjoerg 14030300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 14130300Sjoerg 14230300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 14330300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 14430300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 14530300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 14630300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 14730300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 14830300Sjoerg 14925944Sjoerg/* states are named and numbered according to RFC 1661 */ 15025944Sjoerg#define STATE_INITIAL 0 15125944Sjoerg#define STATE_STARTING 1 15225944Sjoerg#define STATE_CLOSED 2 15325944Sjoerg#define STATE_STOPPED 3 15425944Sjoerg#define STATE_CLOSING 4 15525944Sjoerg#define STATE_STOPPING 5 15625944Sjoerg#define STATE_REQ_SENT 6 15725944Sjoerg#define STATE_ACK_RCVD 7 15825944Sjoerg#define STATE_ACK_SENT 8 15925944Sjoerg#define STATE_OPENED 9 16025944Sjoerg 1614910Swollmanstruct ppp_header { 16211189Sjkh u_char address; 16311189Sjkh u_char control; 16411189Sjkh u_short protocol; 1654910Swollman}; 1664910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1674910Swollman 1684910Swollmanstruct lcp_header { 16911189Sjkh u_char type; 17011189Sjkh u_char ident; 17111189Sjkh u_short len; 1724910Swollman}; 1734910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1744910Swollman 1754910Swollmanstruct cisco_packet { 17611189Sjkh u_long type; 17711189Sjkh u_long par1; 17811189Sjkh u_long par2; 17911189Sjkh u_short rel; 18011189Sjkh u_short time0; 18111189Sjkh u_short time1; 1824910Swollman}; 1834910Swollman#define CISCO_PACKET_LEN 18 1844910Swollman 18525944Sjoerg/* 18625944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 18725944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 18825944Sjoerg * case you can't make sense out of these abbreviation; it will also 18925944Sjoerg * explain the semantics related to the various events and actions. 19025944Sjoerg */ 19125944Sjoergstruct cp { 19225944Sjoerg u_short proto; /* PPP control protocol number */ 19325944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 19425944Sjoerg u_char flags; 19525944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 19625944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 19725944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 19825944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 19925944Sjoerg const char *name; /* name of this control protocol */ 20025944Sjoerg /* event handlers */ 20125944Sjoerg void (*Up)(struct sppp *sp); 20225944Sjoerg void (*Down)(struct sppp *sp); 20325944Sjoerg void (*Open)(struct sppp *sp); 20425944Sjoerg void (*Close)(struct sppp *sp); 20525944Sjoerg void (*TO)(void *sp); 20625944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 20725944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 20825944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 20925944Sjoerg /* actions */ 21025944Sjoerg void (*tlu)(struct sppp *sp); 21125944Sjoerg void (*tld)(struct sppp *sp); 21225944Sjoerg void (*tls)(struct sppp *sp); 21325944Sjoerg void (*tlf)(struct sppp *sp); 21425944Sjoerg void (*scr)(struct sppp *sp); 21525944Sjoerg}; 21625944Sjoerg 21712820Sphkstatic struct sppp *spppq; 21830300Sjoergstatic struct callout_handle keepalive_ch; 2194910Swollman 2204910Swollman/* 2214910Swollman * The following disgusting hack gets around the problem that IP TOS 2224910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2234910Swollman * priority queue. To decide if traffic is interactive, we check that 2244910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 22530300Sjoerg * 22630300Sjoerg * XXX is this really still necessary? - joerg - 2274910Swollman */ 22811189Sjkhstatic u_short interactive_ports[8] = { 2294910Swollman 0, 513, 0, 0, 2304910Swollman 0, 21, 0, 23, 2314910Swollman}; 2324910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2334910Swollman 23425944Sjoerg/* almost every function needs these */ 23525944Sjoerg#define STDDCL \ 23625944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 23725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 23811189Sjkh 23930300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 24025944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2414910Swollman 24225944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 24325944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 24425944Sjoerg 24525944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 24625944Sjoerg struct mbuf *m); 24725944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 24825944Sjoerg u_char ident, u_short len, void *data); 24925944Sjoergstatic void sppp_cp_timeout(void *arg); 25025944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 25125944Sjoerg int newstate); 25230300Sjoergstatic void sppp_auth_send(const struct cp *cp, 25330300Sjoerg struct sppp *sp, u_char type, u_char id, 25430300Sjoerg ...); 25525944Sjoerg 25625944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 25725944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 25825944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 25925944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 26025944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 26125944Sjoerg 26230300Sjoergstatic void sppp_null(struct sppp *sp); 26330300Sjoerg 26425944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 26525944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 26625944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 26725944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 26825944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 26925944Sjoergstatic void sppp_lcp_TO(void *sp); 27025944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 27125944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 27225944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 27325944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 27425944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 27525944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 27625944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 27725944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 27830300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 27930300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 28025944Sjoerg 28125944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 28225944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 28325944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 28425944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 28525944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 28625944Sjoergstatic void sppp_ipcp_TO(void *sp); 28725944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 28825944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 28925944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 29025944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 29125944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 29225944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 29325944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 29425944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 29525944Sjoerg 29630300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 29730300Sjoergstatic void sppp_pap_init(struct sppp *sp); 29830300Sjoergstatic void sppp_pap_open(struct sppp *sp); 29930300Sjoergstatic void sppp_pap_close(struct sppp *sp); 30030300Sjoergstatic void sppp_pap_TO(void *sp); 30130300Sjoergstatic void sppp_pap_my_TO(void *sp); 30230300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 30330300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 30430300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 30530300Sjoerg 30630300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 30730300Sjoergstatic void sppp_chap_init(struct sppp *sp); 30830300Sjoergstatic void sppp_chap_open(struct sppp *sp); 30930300Sjoergstatic void sppp_chap_close(struct sppp *sp); 31030300Sjoergstatic void sppp_chap_TO(void *sp); 31130300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 31230300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 31330300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 31430300Sjoerg 31530300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 31625944Sjoergstatic const char *sppp_cp_type_name(u_char type); 31730300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 31830300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 31925944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 32025944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 32125944Sjoergstatic const char *sppp_proto_name(u_short proto); 32230300Sjoergstatic const char *sppp_state_name(int state); 32330300Sjoergstatic int sppp_params(struct sppp *sp, int cmd, void *data); 32430300Sjoergstatic int sppp_strnlen(u_char *p, int max); 32530300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 32630300Sjoerg u_long *srcmask); 32725944Sjoergstatic void sppp_keepalive(void *dummy); 32830300Sjoergstatic void sppp_phase_network(struct sppp *sp); 32930300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 33030300Sjoergstatic void sppp_print_string(const char *p, u_short len); 33125944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 33225944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 33325944Sjoerg 33425944Sjoerg/* our control protocol descriptors */ 33525944Sjoergconst struct cp lcp = { 33625944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 33725944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 33825944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 33925944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 34025944Sjoerg sppp_lcp_scr 34125944Sjoerg}; 34225944Sjoerg 34325944Sjoergconst struct cp ipcp = { 34425944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 34525944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 34625944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 34725944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 34825944Sjoerg sppp_ipcp_scr 34925944Sjoerg}; 35025944Sjoerg 35130300Sjoergconst struct cp pap = { 35230300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 35330300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 35430300Sjoerg sppp_pap_TO, 0, 0, 0, 35530300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 35630300Sjoerg sppp_pap_scr 35730300Sjoerg}; 35830300Sjoerg 35930300Sjoergconst struct cp chap = { 36030300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 36130300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 36230300Sjoerg sppp_chap_TO, 0, 0, 0, 36330300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 36430300Sjoerg sppp_chap_scr 36530300Sjoerg}; 36630300Sjoerg 36725944Sjoergconst struct cp *cps[IDX_COUNT] = { 36825944Sjoerg &lcp, /* IDX_LCP */ 36925944Sjoerg &ipcp, /* IDX_IPCP */ 37030300Sjoerg &pap, /* IDX_PAP */ 37130300Sjoerg &chap, /* IDX_CHAP */ 37225944Sjoerg}; 37325944Sjoerg 37425944Sjoerg 37525944Sjoerg/* 37625944Sjoerg * Exported functions, comprising our interface to the lower layer. 3774910Swollman */ 3784910Swollman 3794910Swollman/* 3804910Swollman * Process the received packet. 3814910Swollman */ 38225706Sjoergvoid 38325706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 3844910Swollman{ 3854910Swollman struct ppp_header *h; 3864910Swollman struct ifqueue *inq = 0; 38711189Sjkh int s; 38825944Sjoerg struct sppp *sp = (struct sppp *)ifp; 38925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 3904910Swollman 3914910Swollman if (ifp->if_flags & IFF_UP) 3924910Swollman /* Count received bytes, add FCS and one flag */ 3934910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 3944910Swollman 3954910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 3964910Swollman /* Too small packet, drop it. */ 39725944Sjoerg if (debug) 39825706Sjoerg log(LOG_DEBUG, 39925706Sjoerg "%s%d: input packet is too small, %d bytes\n", 40025706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 40125944Sjoerg drop: 40225944Sjoerg ++ifp->if_ierrors; 40325944Sjoerg ++ifp->if_iqdrops; 4044910Swollman m_freem (m); 4054910Swollman return; 4064910Swollman } 4074910Swollman 4084910Swollman /* Get PPP header. */ 4094910Swollman h = mtod (m, struct ppp_header*); 4104910Swollman m_adj (m, PPP_HEADER_LEN); 4114910Swollman 4124910Swollman switch (h->address) { 4134910Swollman case PPP_ALLSTATIONS: 4144910Swollman if (h->control != PPP_UI) 4154910Swollman goto invalid; 41611189Sjkh if (sp->pp_flags & PP_CISCO) { 41725944Sjoerg if (debug) 41825706Sjoerg log(LOG_DEBUG, 41925706Sjoerg "%s%d: PPP packet in Cisco mode " 42025706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 42125706Sjoerg ifp->if_name, ifp->if_unit, 42225706Sjoerg h->address, h->control, ntohs(h->protocol)); 42311189Sjkh goto drop; 42411189Sjkh } 4254910Swollman switch (ntohs (h->protocol)) { 4264910Swollman default: 42725944Sjoerg if (sp->state[IDX_LCP] == STATE_OPENED) 42825944Sjoerg sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 42911189Sjkh ++sp->pp_seq, m->m_pkthdr.len + 2, 4304910Swollman &h->protocol); 43125944Sjoerg if (debug) 43225706Sjoerg log(LOG_DEBUG, 43325706Sjoerg "%s%d: invalid input protocol " 43425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 43525706Sjoerg ifp->if_name, ifp->if_unit, 43625706Sjoerg h->address, h->control, ntohs(h->protocol)); 4374910Swollman ++ifp->if_noproto; 4384910Swollman goto drop; 4394910Swollman case PPP_LCP: 44030300Sjoerg sppp_cp_input(&lcp, sp, m); 4414910Swollman m_freem (m); 4424910Swollman return; 44330300Sjoerg case PPP_PAP: 44430300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 44530300Sjoerg sppp_pap_input(sp, m); 44630300Sjoerg m_freem (m); 44730300Sjoerg return; 44830300Sjoerg case PPP_CHAP: 44930300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 45030300Sjoerg sppp_chap_input(sp, m); 45130300Sjoerg m_freem (m); 45230300Sjoerg return; 4534910Swollman#ifdef INET 4544910Swollman case PPP_IPCP: 45525944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 45630300Sjoerg sppp_cp_input(&ipcp, sp, m); 4574910Swollman m_freem (m); 4584910Swollman return; 4594910Swollman case PPP_IP: 46025944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 4614910Swollman schednetisr (NETISR_IP); 4624910Swollman inq = &ipintrq; 4634910Swollman } 4644910Swollman break; 4654910Swollman#endif 46612495Speter#ifdef IPX 46712495Speter case PPP_IPX: 46812495Speter /* IPX IPXCP not implemented yet */ 46925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 47012495Speter schednetisr (NETISR_IPX); 47112495Speter inq = &ipxintrq; 47212495Speter } 47312495Speter break; 47412495Speter#endif 4754910Swollman#ifdef NS 4764910Swollman case PPP_XNS: 4774910Swollman /* XNS IDPCP not implemented yet */ 47825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 4794910Swollman schednetisr (NETISR_NS); 4804910Swollman inq = &nsintrq; 4814910Swollman } 4824910Swollman break; 4834910Swollman#endif 4844910Swollman#ifdef ISO 4854910Swollman case PPP_ISO: 4864910Swollman /* OSI NLCP not implemented yet */ 48725944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 4884910Swollman schednetisr (NETISR_ISO); 4894910Swollman inq = &clnlintrq; 4904910Swollman } 4914910Swollman break; 4924910Swollman#endif 4934910Swollman } 4944910Swollman break; 4954910Swollman case CISCO_MULTICAST: 4964910Swollman case CISCO_UNICAST: 4974910Swollman /* Don't check the control field here (RFC 1547). */ 49811189Sjkh if (! (sp->pp_flags & PP_CISCO)) { 49925944Sjoerg if (debug) 50025706Sjoerg log(LOG_DEBUG, 50125706Sjoerg "%s%d: Cisco packet in PPP mode " 50225706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 50325706Sjoerg ifp->if_name, ifp->if_unit, 50425706Sjoerg h->address, h->control, ntohs(h->protocol)); 50511189Sjkh goto drop; 50611189Sjkh } 5074910Swollman switch (ntohs (h->protocol)) { 5084910Swollman default: 5094910Swollman ++ifp->if_noproto; 5104910Swollman goto invalid; 5114910Swollman case CISCO_KEEPALIVE: 5124910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5134910Swollman m_freem (m); 5144910Swollman return; 5154910Swollman#ifdef INET 5164910Swollman case ETHERTYPE_IP: 5174910Swollman schednetisr (NETISR_IP); 5184910Swollman inq = &ipintrq; 5194910Swollman break; 5204910Swollman#endif 52112495Speter#ifdef IPX 52212495Speter case ETHERTYPE_IPX: 52312495Speter schednetisr (NETISR_IPX); 52412495Speter inq = &ipxintrq; 52512495Speter break; 52612495Speter#endif 5274910Swollman#ifdef NS 5284910Swollman case ETHERTYPE_NS: 5294910Swollman schednetisr (NETISR_NS); 5304910Swollman inq = &nsintrq; 5314910Swollman break; 5324910Swollman#endif 5334910Swollman } 5344910Swollman break; 53525944Sjoerg default: /* Invalid PPP packet. */ 53625944Sjoerg invalid: 53725944Sjoerg if (debug) 53825944Sjoerg log(LOG_DEBUG, 53925944Sjoerg "%s%d: invalid input packet " 54025944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54125944Sjoerg ifp->if_name, ifp->if_unit, 54225944Sjoerg h->address, h->control, ntohs(h->protocol)); 54325944Sjoerg goto drop; 5444910Swollman } 5454910Swollman 5464910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 5474910Swollman goto drop; 5484910Swollman 5494910Swollman /* Check queue. */ 55025944Sjoerg s = splimp(); 5514910Swollman if (IF_QFULL (inq)) { 5524910Swollman /* Queue overflow. */ 55325944Sjoerg IF_DROP(inq); 55425944Sjoerg splx(s); 55525944Sjoerg if (debug) 55625706Sjoerg log(LOG_DEBUG, "%s%d: protocol queue overflow\n", 5574910Swollman ifp->if_name, ifp->if_unit); 5584910Swollman goto drop; 5594910Swollman } 56025944Sjoerg IF_ENQUEUE(inq, m); 56125944Sjoerg splx(s); 5624910Swollman} 5634910Swollman 5644910Swollman/* 5654910Swollman * Enqueue transmit packet. 5664910Swollman */ 56712820Sphkstatic int 56825706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 56925706Sjoerg struct sockaddr *dst, struct rtentry *rt) 5704910Swollman{ 5714910Swollman struct sppp *sp = (struct sppp*) ifp; 5724910Swollman struct ppp_header *h; 5734910Swollman struct ifqueue *ifq; 57425955Sjoerg int s, rv = 0; 5754910Swollman 57625944Sjoerg s = splimp(); 57725944Sjoerg 57825944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 57925944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 5804910Swollman m_freem (m); 5814910Swollman splx (s); 5824910Swollman return (ENETDOWN); 5834910Swollman } 5844910Swollman 58525944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 58625944Sjoerg /* 58725944Sjoerg * Interface is not yet running, but auto-dial. Need 58825944Sjoerg * to start LCP for it. 58925944Sjoerg */ 59025944Sjoerg ifp->if_flags |= IFF_RUNNING; 59125944Sjoerg splx(s); 59225944Sjoerg lcp.Open(sp); 59325944Sjoerg s = splimp(); 59425944Sjoerg } 59525944Sjoerg 5964910Swollman ifq = &ifp->if_snd; 5974910Swollman#ifdef INET 5984910Swollman /* 5994910Swollman * Put low delay, telnet, rlogin and ftp control packets 6004910Swollman * in front of the queue. 6014910Swollman */ 60212436Speter if (dst->sa_family == AF_INET) { 60312436Speter struct ip *ip = mtod (m, struct ip*); 60412436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6054910Swollman 60612436Speter if (! IF_QFULL (&sp->pp_fastq) && 60712436Speter ((ip->ip_tos & IPTOS_LOWDELAY) || 60812436Speter ip->ip_p == IPPROTO_TCP && 60912436Speter m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) && 61012436Speter (INTERACTIVE (ntohs (tcp->th_sport)) || 61112436Speter INTERACTIVE (ntohs (tcp->th_dport))))) 61212436Speter ifq = &sp->pp_fastq; 6134910Swollman } 6144910Swollman#endif 6154910Swollman 6164910Swollman /* 6174910Swollman * Prepend general data packet PPP header. For now, IP only. 6184910Swollman */ 6194910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 6204910Swollman if (! m) { 6214910Swollman if (ifp->if_flags & IFF_DEBUG) 62225706Sjoerg log(LOG_DEBUG, "%s%d: no memory for transmit header\n", 6234910Swollman ifp->if_name, ifp->if_unit); 62425944Sjoerg ++ifp->if_oerrors; 6254910Swollman splx (s); 6264910Swollman return (ENOBUFS); 6274910Swollman } 6284910Swollman h = mtod (m, struct ppp_header*); 6294910Swollman if (sp->pp_flags & PP_CISCO) { 63028088Skjc h->address = CISCO_UNICAST; /* unicast address */ 6314910Swollman h->control = 0; 6324910Swollman } else { 6334910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 6344910Swollman h->control = PPP_UI; /* Unnumbered Info */ 6354910Swollman } 6364910Swollman 6374910Swollman switch (dst->sa_family) { 6384910Swollman#ifdef INET 6394910Swollman case AF_INET: /* Internet Protocol */ 64011189Sjkh if (sp->pp_flags & PP_CISCO) 64111189Sjkh h->protocol = htons (ETHERTYPE_IP); 64211189Sjkh else { 64325955Sjoerg /* 64425955Sjoerg * Don't choke with an ENETDOWN early. It's 64525955Sjoerg * possible that we just started dialing out, 64625955Sjoerg * so don't drop the packet immediately. If 64725955Sjoerg * we notice that we run out of buffer space 64825955Sjoerg * below, we will however remember that we are 64925955Sjoerg * not ready to carry IP packets, and return 65025955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 65125955Sjoerg */ 65225955Sjoerg h->protocol = htons(PPP_IP); 65325955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 65425955Sjoerg rv = ENETDOWN; 65511189Sjkh } 6564910Swollman break; 6574910Swollman#endif 6584910Swollman#ifdef NS 6594910Swollman case AF_NS: /* Xerox NS Protocol */ 6604910Swollman h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 6614910Swollman ETHERTYPE_NS : PPP_XNS); 6624910Swollman break; 6634910Swollman#endif 66411819Sjulian#ifdef IPX 66512495Speter case AF_IPX: /* Novell IPX Protocol */ 66611819Sjulian h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 66712495Speter ETHERTYPE_IPX : PPP_IPX); 66811819Sjulian break; 66911819Sjulian#endif 6704910Swollman#ifdef ISO 6714910Swollman case AF_ISO: /* ISO OSI Protocol */ 6724910Swollman if (sp->pp_flags & PP_CISCO) 6734910Swollman goto nosupport; 6744910Swollman h->protocol = htons (PPP_ISO); 6754910Swollman break; 67612820Sphknosupport: 6774910Swollman#endif 6784910Swollman default: 6794910Swollman m_freem (m); 68025944Sjoerg ++ifp->if_oerrors; 6814910Swollman splx (s); 6824910Swollman return (EAFNOSUPPORT); 6834910Swollman } 6844910Swollman 6854910Swollman /* 6864910Swollman * Queue message on interface, and start output if interface 6874910Swollman * not yet active. 6884910Swollman */ 6894910Swollman if (IF_QFULL (ifq)) { 6904910Swollman IF_DROP (&ifp->if_snd); 6914910Swollman m_freem (m); 69225944Sjoerg ++ifp->if_oerrors; 6934910Swollman splx (s); 69425955Sjoerg return (rv? rv: ENOBUFS); 6954910Swollman } 6964910Swollman IF_ENQUEUE (ifq, m); 6974910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 6984910Swollman (*ifp->if_start) (ifp); 6994910Swollman 7004910Swollman /* 7014910Swollman * Count output packets and bytes. 7024910Swollman * The packet length includes header, FCS and 1 flag, 7034910Swollman * according to RFC 1333. 7044910Swollman */ 7054910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 7064910Swollman splx (s); 7074910Swollman return (0); 7084910Swollman} 7094910Swollman 71025706Sjoergvoid 71125706Sjoergsppp_attach(struct ifnet *ifp) 7124910Swollman{ 7134910Swollman struct sppp *sp = (struct sppp*) ifp; 7144910Swollman 7154910Swollman /* Initialize keepalive handler. */ 7164910Swollman if (! spppq) 71730300Sjoerg keepalive_ch = timeout(sppp_keepalive, 0, hz * 10); 7184910Swollman 7194910Swollman /* Insert new entry into the keepalive list. */ 7204910Swollman sp->pp_next = spppq; 7214910Swollman spppq = sp; 7224910Swollman 7234910Swollman sp->pp_if.if_type = IFT_PPP; 7244910Swollman sp->pp_if.if_output = sppp_output; 7254910Swollman sp->pp_fastq.ifq_maxlen = 32; 72626018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 7274910Swollman sp->pp_loopcnt = 0; 7284910Swollman sp->pp_alivecnt = 0; 72911189Sjkh sp->pp_seq = 0; 7304910Swollman sp->pp_rseq = 0; 73125944Sjoerg sp->pp_phase = PHASE_DEAD; 73225944Sjoerg sp->pp_up = lcp.Up; 73325944Sjoerg sp->pp_down = lcp.Down; 73425944Sjoerg 73525944Sjoerg sppp_lcp_init(sp); 73625944Sjoerg sppp_ipcp_init(sp); 73730300Sjoerg sppp_pap_init(sp); 73830300Sjoerg sppp_chap_init(sp); 7394910Swollman} 7404910Swollman 74130300Sjoergvoid 74225706Sjoergsppp_detach(struct ifnet *ifp) 7434910Swollman{ 7444910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 74525944Sjoerg int i; 7464910Swollman 7474910Swollman /* Remove the entry from the keepalive list. */ 7484910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 7494910Swollman if (p == sp) { 7504910Swollman *q = p->pp_next; 7514910Swollman break; 7524910Swollman } 7534910Swollman 7544910Swollman /* Stop keepalive handler. */ 7554910Swollman if (! spppq) 75630300Sjoerg untimeout(sppp_keepalive, 0, keepalive_ch); 75725944Sjoerg 75825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 75929681Sgibbs untimeout((cps[i])->TO, (void *)sp, sp->ch[i]); 76030300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 7614910Swollman} 7624910Swollman 7634910Swollman/* 7644910Swollman * Flush the interface output queue. 7654910Swollman */ 76625706Sjoergvoid 76725706Sjoergsppp_flush(struct ifnet *ifp) 7684910Swollman{ 7694910Swollman struct sppp *sp = (struct sppp*) ifp; 7704910Swollman 77125944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 77225944Sjoerg sppp_qflush (&sp->pp_fastq); 77326018Sjoerg sppp_qflush (&sp->pp_cpq); 7744910Swollman} 7754910Swollman 7764910Swollman/* 77711189Sjkh * Check if the output queue is empty. 77811189Sjkh */ 77912820Sphkint 78025706Sjoergsppp_isempty(struct ifnet *ifp) 78111189Sjkh{ 78211189Sjkh struct sppp *sp = (struct sppp*) ifp; 78325944Sjoerg int empty, s; 78411189Sjkh 78525944Sjoerg s = splimp(); 78626018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 78726018Sjoerg !sp->pp_if.if_snd.ifq_head; 78825944Sjoerg splx(s); 78911189Sjkh return (empty); 79011189Sjkh} 79111189Sjkh 79211189Sjkh/* 7934910Swollman * Get next packet to send. 7944910Swollman */ 79525706Sjoergstruct mbuf * 79625706Sjoergsppp_dequeue(struct ifnet *ifp) 7974910Swollman{ 7984910Swollman struct sppp *sp = (struct sppp*) ifp; 7994910Swollman struct mbuf *m; 80025944Sjoerg int s; 8014910Swollman 80225944Sjoerg s = splimp(); 80326018Sjoerg /* 80430300Sjoerg * Process only the control protocol queue until we have at 80530300Sjoerg * least one NCP open. 80626018Sjoerg * 80726018Sjoerg * Do always serve all three queues in Cisco mode. 80826018Sjoerg */ 80926018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 81026018Sjoerg if (m == NULL && 81130300Sjoerg (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { 81226018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 81326018Sjoerg if (m == NULL) 81426018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 81526018Sjoerg } 81626018Sjoerg splx(s); 81726018Sjoerg return m; 8184910Swollman} 8194910Swollman 8204910Swollman/* 82130300Sjoerg * Pick the next packet, do not remove it from the queue. 82230300Sjoerg */ 82330300Sjoergstruct mbuf * 82430300Sjoergsppp_pick(struct ifnet *ifp) 82530300Sjoerg{ 82630300Sjoerg struct sppp *sp = (struct sppp*)ifp; 82730300Sjoerg struct mbuf *m; 82830300Sjoerg int s; 82930300Sjoerg 83030300Sjoerg s= splimp (); 83130300Sjoerg 83230300Sjoerg m = sp->pp_cpq.ifq_head; 83330300Sjoerg if (m == NULL && 83430300Sjoerg (sp->pp_phase == PHASE_NETWORK || 83530300Sjoerg (sp->pp_flags & PP_CISCO) != 0)) 83630300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 83730300Sjoerg m = sp->pp_if.if_snd.ifq_head; 83830300Sjoerg splx (s); 83930300Sjoerg return (m); 84030300Sjoerg} 84130300Sjoerg 84230300Sjoerg/* 84325944Sjoerg * Process an ioctl request. Called on low priority level. 8444910Swollman */ 84525944Sjoergint 84625944Sjoergsppp_ioctl(struct ifnet *ifp, int cmd, void *data) 8474910Swollman{ 84825944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 84925944Sjoerg struct sppp *sp = (struct sppp*) ifp; 85030300Sjoerg int s, rv, going_up, going_down, newmode; 8514910Swollman 85225944Sjoerg s = splimp(); 85330300Sjoerg rv = 0; 85425944Sjoerg switch (cmd) { 85525944Sjoerg case SIOCAIFADDR: 85625944Sjoerg case SIOCSIFDSTADDR: 85725944Sjoerg break; 8584910Swollman 85925944Sjoerg case SIOCSIFADDR: 86025944Sjoerg if_up(ifp); 86125944Sjoerg /* fall through... */ 86211189Sjkh 86325944Sjoerg case SIOCSIFFLAGS: 86425944Sjoerg going_up = ifp->if_flags & IFF_UP && 86525944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 86625944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 86725944Sjoerg ifp->if_flags & IFF_RUNNING; 86825944Sjoerg newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); 86925944Sjoerg if (newmode == (IFF_AUTO | IFF_PASSIVE)) { 87025944Sjoerg /* sanity */ 87125944Sjoerg newmode = IFF_PASSIVE; 87225944Sjoerg ifp->if_flags &= ~IFF_AUTO; 8734910Swollman } 8744910Swollman 87525944Sjoerg if (going_up || going_down) 87625944Sjoerg lcp.Close(sp); 87725944Sjoerg if (going_up && newmode == 0) { 87825944Sjoerg /* neither auto-dial nor passive */ 87925944Sjoerg ifp->if_flags |= IFF_RUNNING; 88025944Sjoerg if (!(sp->pp_flags & PP_CISCO)) 88125944Sjoerg lcp.Open(sp); 88226018Sjoerg } else if (going_down) { 88326018Sjoerg sppp_flush(ifp); 88425944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 88526018Sjoerg } 8864910Swollman 8874910Swollman break; 88811189Sjkh 88925944Sjoerg#ifdef SIOCSIFMTU 89025944Sjoerg#ifndef ifr_mtu 89125944Sjoerg#define ifr_mtu ifr_metric 89225944Sjoerg#endif 89325944Sjoerg case SIOCSIFMTU: 89425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 89525944Sjoerg return (EINVAL); 89625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 8974910Swollman break; 89825944Sjoerg#endif 89925944Sjoerg#ifdef SLIOCSETMTU 90025944Sjoerg case SLIOCSETMTU: 90125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 90225944Sjoerg return (EINVAL); 90325944Sjoerg ifp->if_mtu = *(short*)data; 9044910Swollman break; 90525944Sjoerg#endif 90625944Sjoerg#ifdef SIOCGIFMTU 90725944Sjoerg case SIOCGIFMTU: 90825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 90911189Sjkh break; 91025944Sjoerg#endif 91125944Sjoerg#ifdef SLIOCGETMTU 91225944Sjoerg case SLIOCGETMTU: 91325944Sjoerg *(short*)data = ifp->if_mtu; 9144910Swollman break; 91525944Sjoerg#endif 91625944Sjoerg case SIOCADDMULTI: 91725944Sjoerg case SIOCDELMULTI: 9184910Swollman break; 91911189Sjkh 92030300Sjoerg case SIOCGIFGENERIC: 92130300Sjoerg case SIOCSIFGENERIC: 92230300Sjoerg rv = sppp_params(sp, cmd, data); 92330300Sjoerg break; 92430300Sjoerg 92525944Sjoerg default: 92630300Sjoerg rv = ENOTTY; 9274910Swollman } 92825944Sjoerg splx(s); 92930300Sjoerg return rv; 9304910Swollman} 9314910Swollman 93225944Sjoerg 93325944Sjoerg/* 93425944Sjoerg * Cisco framing implementation. 93525944Sjoerg */ 93625944Sjoerg 9374910Swollman/* 9384910Swollman * Handle incoming Cisco keepalive protocol packets. 9394910Swollman */ 94030300Sjoergstatic void 94125706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 9424910Swollman{ 94325944Sjoerg STDDCL; 9444910Swollman struct cisco_packet *h; 94530300Sjoerg u_long me, mymask; 9464910Swollman 94727929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 94825706Sjoerg if (debug) 94925706Sjoerg log(LOG_DEBUG, 95030300Sjoerg "%s%d: cisco invalid packet length: %d bytes\n", 95125706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len); 9524910Swollman return; 9534910Swollman } 9544910Swollman h = mtod (m, struct cisco_packet*); 95525706Sjoerg if (debug) 95625706Sjoerg log(LOG_DEBUG, 95725706Sjoerg "%s%d: cisco input: %d bytes " 95825706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 95925706Sjoerg ifp->if_name, ifp->if_unit, m->m_pkthdr.len, 96025706Sjoerg ntohl (h->type), h->par1, h->par2, h->rel, 96125706Sjoerg h->time0, h->time1); 9624910Swollman switch (ntohl (h->type)) { 9634910Swollman default: 96425706Sjoerg if (debug) 96530300Sjoerg addlog("%s%d: cisco unknown packet type: 0x%lx\n", 96625706Sjoerg ifp->if_name, ifp->if_unit, ntohl (h->type)); 9674910Swollman break; 9684910Swollman case CISCO_ADDR_REPLY: 9694910Swollman /* Reply on address request, ignore */ 9704910Swollman break; 9714910Swollman case CISCO_KEEPALIVE_REQ: 9724910Swollman sp->pp_alivecnt = 0; 9734910Swollman sp->pp_rseq = ntohl (h->par1); 9744910Swollman if (sp->pp_seq == sp->pp_rseq) { 9754910Swollman /* Local and remote sequence numbers are equal. 9764910Swollman * Probably, the line is in loopback mode. */ 97711189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 97811189Sjkh printf ("%s%d: loopback\n", 97911189Sjkh ifp->if_name, ifp->if_unit); 98011189Sjkh sp->pp_loopcnt = 0; 98111189Sjkh if (ifp->if_flags & IFF_UP) { 98211189Sjkh if_down (ifp); 98326018Sjoerg sppp_qflush (&sp->pp_cpq); 98411189Sjkh } 98511189Sjkh } 9864910Swollman ++sp->pp_loopcnt; 9874910Swollman 9884910Swollman /* Generate new local sequence number */ 9894910Swollman sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 99011189Sjkh break; 99111189Sjkh } 99230300Sjoerg sp->pp_loopcnt = 0; 99311189Sjkh if (! (ifp->if_flags & IFF_UP) && 99411189Sjkh (ifp->if_flags & IFF_RUNNING)) { 99530300Sjoerg if_up(ifp); 99611189Sjkh printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 99711189Sjkh } 9984910Swollman break; 9994910Swollman case CISCO_ADDR_REQ: 100030300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 100130300Sjoerg if (me != 0L) 100230300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 10034910Swollman break; 10044910Swollman } 10054910Swollman} 10064910Swollman 10074910Swollman/* 100825944Sjoerg * Send Cisco keepalive packet. 10094910Swollman */ 101012820Sphkstatic void 101125944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 101225944Sjoerg{ 101325944Sjoerg STDDCL; 101425944Sjoerg struct ppp_header *h; 101525944Sjoerg struct cisco_packet *ch; 101625944Sjoerg struct mbuf *m; 101725944Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 101825944Sjoerg 101925944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 102025944Sjoerg if (! m) 102125944Sjoerg return; 102225944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 102325944Sjoerg m->m_pkthdr.rcvif = 0; 102425944Sjoerg 102525944Sjoerg h = mtod (m, struct ppp_header*); 102625944Sjoerg h->address = CISCO_MULTICAST; 102725944Sjoerg h->control = 0; 102825944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 102925944Sjoerg 103025944Sjoerg ch = (struct cisco_packet*) (h + 1); 103125944Sjoerg ch->type = htonl (type); 103225944Sjoerg ch->par1 = htonl (par1); 103325944Sjoerg ch->par2 = htonl (par2); 103425944Sjoerg ch->rel = -1; 103525944Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 103625944Sjoerg ch->time1 = htons ((u_short) t); 103725944Sjoerg 103825944Sjoerg if (debug) 103925944Sjoerg log(LOG_DEBUG, 104025944Sjoerg "%s%d: cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 104125944Sjoerg ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1, 104225944Sjoerg ch->par2, ch->rel, ch->time0, ch->time1); 104325944Sjoerg 104426018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 104526018Sjoerg IF_DROP (&sp->pp_fastq); 104625944Sjoerg IF_DROP (&ifp->if_snd); 104725944Sjoerg m_freem (m); 104825944Sjoerg } else 104926018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 105025944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 105125944Sjoerg (*ifp->if_start) (ifp); 105225944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 105325944Sjoerg} 105425944Sjoerg 105525944Sjoerg/* 105625944Sjoerg * PPP protocol implementation. 105725944Sjoerg */ 105825944Sjoerg 105925944Sjoerg/* 106025944Sjoerg * Send PPP control protocol packet. 106125944Sjoerg */ 106225944Sjoergstatic void 106325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 106425706Sjoerg u_char ident, u_short len, void *data) 10654910Swollman{ 106625944Sjoerg STDDCL; 10674910Swollman struct ppp_header *h; 10684910Swollman struct lcp_header *lh; 10694910Swollman struct mbuf *m; 10704910Swollman 10714910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 10724910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 10734910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 10744910Swollman if (! m) 10754910Swollman return; 10764910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 10774910Swollman m->m_pkthdr.rcvif = 0; 10784910Swollman 10794910Swollman h = mtod (m, struct ppp_header*); 10804910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 10814910Swollman h->control = PPP_UI; /* Unnumbered Info */ 10824910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 10834910Swollman 10844910Swollman lh = (struct lcp_header*) (h + 1); 10854910Swollman lh->type = type; 10864910Swollman lh->ident = ident; 10874910Swollman lh->len = htons (LCP_HEADER_LEN + len); 10884910Swollman if (len) 10894910Swollman bcopy (data, lh+1, len); 10904910Swollman 109125706Sjoerg if (debug) { 109225944Sjoerg log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d", 109325944Sjoerg ifp->if_name, ifp->if_unit, 109425944Sjoerg sppp_proto_name(proto), 109525944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 109625944Sjoerg ntohs (lh->len)); 10974910Swollman if (len) 109811189Sjkh sppp_print_bytes ((u_char*) (lh+1), len); 109925706Sjoerg addlog(">\n"); 11004910Swollman } 110126018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 110226018Sjoerg IF_DROP (&sp->pp_fastq); 11034910Swollman IF_DROP (&ifp->if_snd); 11044910Swollman m_freem (m); 110525944Sjoerg ++ifp->if_oerrors; 11064910Swollman } else 110726018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 11084910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 11094910Swollman (*ifp->if_start) (ifp); 11104910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 11114910Swollman} 11124910Swollman 11134910Swollman/* 111425944Sjoerg * Handle incoming PPP control protocol packets. 11154910Swollman */ 111612820Sphkstatic void 111725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 11184910Swollman{ 111925944Sjoerg STDDCL; 112025944Sjoerg struct lcp_header *h; 112125944Sjoerg int len = m->m_pkthdr.len; 112225944Sjoerg int rv; 112325944Sjoerg u_char *p; 11244910Swollman 112525944Sjoerg if (len < 4) { 112625944Sjoerg if (debug) 112725944Sjoerg log(LOG_DEBUG, 112825944Sjoerg "%s%d: %s invalid packet length: %d bytes\n", 112925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, len); 11304910Swollman return; 113125944Sjoerg } 113225944Sjoerg h = mtod (m, struct lcp_header*); 113325944Sjoerg if (debug) { 113425944Sjoerg log(LOG_DEBUG, 113525944Sjoerg "%s%d: %s input(%s): <%s id=0x%x len=%d", 113625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 113725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 113825944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 113925944Sjoerg if (len > 4) 114025944Sjoerg sppp_print_bytes ((u_char*) (h+1), len-4); 114125944Sjoerg addlog(">\n"); 114225944Sjoerg } 114325944Sjoerg if (len > ntohs (h->len)) 114425944Sjoerg len = ntohs (h->len); 114530300Sjoerg p = (u_char *)(h + 1); 114625944Sjoerg switch (h->type) { 114725944Sjoerg case CONF_REQ: 114825944Sjoerg if (len < 4) { 114925944Sjoerg if (debug) 115025944Sjoerg addlog("%s%d: %s invalid conf-req length %d\n", 115125944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 115225944Sjoerg len); 115325944Sjoerg ++ifp->if_ierrors; 115425944Sjoerg break; 115525944Sjoerg } 115630300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 115730300Sjoerg switch (sp->state[cp->protoidx]) { 115830300Sjoerg case STATE_CLOSING: 115930300Sjoerg case STATE_STOPPING: 116030300Sjoerg return; 116130300Sjoerg case STATE_CLOSED: 116230300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 116330300Sjoerg 0, 0); 116430300Sjoerg return; 116530300Sjoerg } 116625944Sjoerg rv = (cp->RCR)(sp, h, len); 116725944Sjoerg switch (sp->state[cp->protoidx]) { 116825944Sjoerg case STATE_OPENED: 116925944Sjoerg (cp->tld)(sp); 117025944Sjoerg (cp->scr)(sp); 117125944Sjoerg /* fall through... */ 117225944Sjoerg case STATE_ACK_SENT: 117325944Sjoerg case STATE_REQ_SENT: 117425944Sjoerg sppp_cp_change_state(cp, sp, rv? 117525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 117625944Sjoerg break; 117725944Sjoerg case STATE_STOPPED: 117825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 117925944Sjoerg (cp->scr)(sp); 118025944Sjoerg sppp_cp_change_state(cp, sp, rv? 118125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 118225944Sjoerg break; 118325944Sjoerg case STATE_ACK_RCVD: 118425944Sjoerg if (rv) { 118525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 118625944Sjoerg if (debug) 118726077Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 118826077Sjoerg ifp->if_name, ifp->if_unit, 118926077Sjoerg cp->name); 119025944Sjoerg (cp->tlu)(sp); 119125944Sjoerg } else 119225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 119325944Sjoerg break; 119425944Sjoerg default: 119525944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 119625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 119725944Sjoerg sppp_cp_type_name(h->type), 119825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 119925944Sjoerg ++ifp->if_ierrors; 120025944Sjoerg } 120125944Sjoerg break; 120225944Sjoerg case CONF_ACK: 120325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 120425944Sjoerg if (debug) 120525944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 120625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 120725944Sjoerg h->ident, sp->confid[cp->protoidx]); 120825944Sjoerg ++ifp->if_ierrors; 120925944Sjoerg break; 121025944Sjoerg } 121125944Sjoerg switch (sp->state[cp->protoidx]) { 121225944Sjoerg case STATE_CLOSED: 121325944Sjoerg case STATE_STOPPED: 121425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 121525944Sjoerg break; 121625944Sjoerg case STATE_CLOSING: 121725944Sjoerg case STATE_STOPPING: 121825944Sjoerg break; 121925944Sjoerg case STATE_REQ_SENT: 122025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 122125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 122225944Sjoerg break; 122325944Sjoerg case STATE_OPENED: 122425944Sjoerg (cp->tld)(sp); 122525944Sjoerg /* fall through */ 122625944Sjoerg case STATE_ACK_RCVD: 122725944Sjoerg (cp->scr)(sp); 122825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 122925944Sjoerg break; 123025944Sjoerg case STATE_ACK_SENT: 123125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 123225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 123325944Sjoerg if (debug) 123430300Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 123525944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 123625944Sjoerg (cp->tlu)(sp); 123725944Sjoerg break; 123825944Sjoerg default: 123925944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 124025944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 124125944Sjoerg sppp_cp_type_name(h->type), 124225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 124325944Sjoerg ++ifp->if_ierrors; 124425944Sjoerg } 124525944Sjoerg break; 124625944Sjoerg case CONF_NAK: 124725944Sjoerg case CONF_REJ: 124825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 124925944Sjoerg if (debug) 125025944Sjoerg addlog("%s%d: %s id mismatch 0x%x != 0x%x\n", 125125944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 125225944Sjoerg h->ident, sp->confid[cp->protoidx]); 125325944Sjoerg ++ifp->if_ierrors; 125425944Sjoerg break; 125525944Sjoerg } 125625944Sjoerg if (h->type == CONF_NAK) 125725944Sjoerg (cp->RCN_nak)(sp, h, len); 125825944Sjoerg else /* CONF_REJ */ 125925944Sjoerg (cp->RCN_rej)(sp, h, len); 12604910Swollman 126125944Sjoerg switch (sp->state[cp->protoidx]) { 126225944Sjoerg case STATE_CLOSED: 126325944Sjoerg case STATE_STOPPED: 126425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 126525944Sjoerg break; 126625944Sjoerg case STATE_REQ_SENT: 126725944Sjoerg case STATE_ACK_SENT: 126825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 126925944Sjoerg (cp->scr)(sp); 127025944Sjoerg break; 127125944Sjoerg case STATE_OPENED: 127225944Sjoerg (cp->tld)(sp); 127325944Sjoerg /* fall through */ 127425944Sjoerg case STATE_ACK_RCVD: 127525944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_SENT); 127625944Sjoerg (cp->scr)(sp); 127725944Sjoerg break; 127825944Sjoerg case STATE_CLOSING: 127925944Sjoerg case STATE_STOPPING: 128025944Sjoerg break; 128125944Sjoerg default: 128225944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 128325944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 128425944Sjoerg sppp_cp_type_name(h->type), 128525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 128625944Sjoerg ++ifp->if_ierrors; 128725944Sjoerg } 128825944Sjoerg break; 12894910Swollman 129025944Sjoerg case TERM_REQ: 129125944Sjoerg switch (sp->state[cp->protoidx]) { 129225944Sjoerg case STATE_ACK_RCVD: 129325944Sjoerg case STATE_ACK_SENT: 129425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 129525944Sjoerg /* fall through */ 129625944Sjoerg case STATE_CLOSED: 129725944Sjoerg case STATE_STOPPED: 129825944Sjoerg case STATE_CLOSING: 129925944Sjoerg case STATE_STOPPING: 130025944Sjoerg case STATE_REQ_SENT: 130125944Sjoerg sta: 130225944Sjoerg /* Send Terminate-Ack packet. */ 130325944Sjoerg if (debug) 130425944Sjoerg log(LOG_DEBUG, "%s%d: %s send terminate-ack\n", 130525944Sjoerg ifp->if_name, ifp->if_unit, cp->name); 130625944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 130725944Sjoerg break; 130825944Sjoerg case STATE_OPENED: 130925944Sjoerg (cp->tld)(sp); 131025944Sjoerg sp->rst_counter[cp->protoidx] = 0; 131125944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 131225944Sjoerg goto sta; 131325944Sjoerg break; 131425944Sjoerg default: 131525944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 131625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 131725944Sjoerg sppp_cp_type_name(h->type), 131825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 131925944Sjoerg ++ifp->if_ierrors; 132025944Sjoerg } 132125944Sjoerg break; 132225944Sjoerg case TERM_ACK: 132325944Sjoerg switch (sp->state[cp->protoidx]) { 132425944Sjoerg case STATE_CLOSED: 132525944Sjoerg case STATE_STOPPED: 132625944Sjoerg case STATE_REQ_SENT: 132725944Sjoerg case STATE_ACK_SENT: 132825944Sjoerg break; 132925944Sjoerg case STATE_CLOSING: 133025944Sjoerg (cp->tlf)(sp); 133125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 133225944Sjoerg break; 133325944Sjoerg case STATE_STOPPING: 133425944Sjoerg (cp->tlf)(sp); 133525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 133625944Sjoerg break; 133725944Sjoerg case STATE_ACK_RCVD: 133825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 133925944Sjoerg break; 134025944Sjoerg case STATE_OPENED: 134125944Sjoerg (cp->tld)(sp); 134225944Sjoerg (cp->scr)(sp); 134325944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 134425944Sjoerg break; 134525944Sjoerg default: 134625944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 134725944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 134825944Sjoerg sppp_cp_type_name(h->type), 134925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 135025944Sjoerg ++ifp->if_ierrors; 135125944Sjoerg } 135225944Sjoerg break; 135325944Sjoerg case CODE_REJ: 135425944Sjoerg case PROTO_REJ: 135525944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 135630300Sjoerg log(LOG_INFO, 135730300Sjoerg "%s%d: %s: ignoring RXJ (%s) for proto 0x%x, " 135830300Sjoerg "danger will robinson\n", 135930300Sjoerg ifp->if_name, ifp->if_unit, cp->name, 136030300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 136125944Sjoerg switch (sp->state[cp->protoidx]) { 136225944Sjoerg case STATE_CLOSED: 136325944Sjoerg case STATE_STOPPED: 136425944Sjoerg case STATE_REQ_SENT: 136525944Sjoerg case STATE_ACK_SENT: 136625944Sjoerg case STATE_CLOSING: 136725944Sjoerg case STATE_STOPPING: 136825944Sjoerg case STATE_OPENED: 136925944Sjoerg break; 137025944Sjoerg case STATE_ACK_RCVD: 137125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 137225944Sjoerg break; 137325944Sjoerg default: 137425944Sjoerg printf("%s%d: %s illegal %s in state %s\n", 137525944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 137625944Sjoerg sppp_cp_type_name(h->type), 137725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 137825944Sjoerg ++ifp->if_ierrors; 137925944Sjoerg } 138025944Sjoerg break; 138125944Sjoerg case DISC_REQ: 138225944Sjoerg if (cp->proto != PPP_LCP) 138325944Sjoerg goto illegal; 138425944Sjoerg /* Discard the packet. */ 138525944Sjoerg break; 138625944Sjoerg case ECHO_REQ: 138725944Sjoerg if (cp->proto != PPP_LCP) 138825944Sjoerg goto illegal; 138925944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 139025944Sjoerg if (debug) 139125944Sjoerg addlog("%s%d: lcp echo req but lcp closed\n", 139225944Sjoerg ifp->if_name, ifp->if_unit); 139325944Sjoerg ++ifp->if_ierrors; 139425944Sjoerg break; 139525944Sjoerg } 139625944Sjoerg if (len < 8) { 139725944Sjoerg if (debug) 139825944Sjoerg addlog("%s%d: invalid lcp echo request " 139925944Sjoerg "packet length: %d bytes\n", 140025944Sjoerg ifp->if_name, ifp->if_unit, len); 140125944Sjoerg break; 140225944Sjoerg } 140325944Sjoerg if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 140425944Sjoerg /* Line loopback mode detected. */ 140525944Sjoerg printf("%s%d: loopback\n", ifp->if_name, ifp->if_unit); 140625944Sjoerg if_down (ifp); 140726018Sjoerg sppp_qflush (&sp->pp_cpq); 14084910Swollman 140925944Sjoerg /* Shut down the PPP link. */ 141025944Sjoerg /* XXX */ 141125944Sjoerg lcp.Down(sp); 141225944Sjoerg lcp.Up(sp); 141325944Sjoerg break; 141425944Sjoerg } 141525944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 141625944Sjoerg if (debug) 141725944Sjoerg addlog("%s%d: got lcp echo req, sending echo rep\n", 141825944Sjoerg ifp->if_name, ifp->if_unit); 141925944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 142025944Sjoerg break; 142125944Sjoerg case ECHO_REPLY: 142225944Sjoerg if (cp->proto != PPP_LCP) 142325944Sjoerg goto illegal; 142425944Sjoerg if (h->ident != sp->lcp.echoid) { 142525944Sjoerg ++ifp->if_ierrors; 142625944Sjoerg break; 142725944Sjoerg } 142825944Sjoerg if (len < 8) { 142925944Sjoerg if (debug) 143025944Sjoerg addlog("%s%d: lcp invalid echo reply " 143125944Sjoerg "packet length: %d bytes\n", 143225944Sjoerg ifp->if_name, ifp->if_unit, len); 143325944Sjoerg break; 143425944Sjoerg } 143525944Sjoerg if (debug) 143625944Sjoerg addlog("%s%d: lcp got echo rep\n", 143725944Sjoerg ifp->if_name, ifp->if_unit); 143825944Sjoerg if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 143925944Sjoerg sp->pp_alivecnt = 0; 144025944Sjoerg break; 144125944Sjoerg default: 144225944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 144325944Sjoerg illegal: 144425944Sjoerg if (debug) 144525944Sjoerg addlog("%s%d: %c send code-rej for 0x%x\n", 144625944Sjoerg ifp->if_name, ifp->if_unit, cp->name, h->type); 144725944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 144825944Sjoerg m->m_pkthdr.len, h); 144925944Sjoerg ++ifp->if_ierrors; 145025944Sjoerg } 14514910Swollman} 14524910Swollman 145325944Sjoerg 14544910Swollman/* 145525944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 145625944Sjoerg * Basically, the state transition handling in the automaton. 14574910Swollman */ 145825944Sjoergstatic void 145925944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 14604910Swollman{ 146125944Sjoerg STDDCL; 14624910Swollman 146325944Sjoerg if (debug) 146425944Sjoerg log(LOG_DEBUG, "%s%d: %s up(%s)\n", 146525944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 146625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 146725944Sjoerg 146825944Sjoerg switch (sp->state[cp->protoidx]) { 146925944Sjoerg case STATE_INITIAL: 147025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 147125944Sjoerg break; 147225944Sjoerg case STATE_STARTING: 147325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 147425944Sjoerg (cp->scr)(sp); 147525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 147625944Sjoerg break; 14774910Swollman default: 147825944Sjoerg printf("%s%d: %s illegal up in state %s\n", 147925944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 148025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 148125944Sjoerg } 148225944Sjoerg} 14834910Swollman 148425944Sjoergstatic void 148525944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 148625944Sjoerg{ 148725944Sjoerg STDDCL; 148825944Sjoerg 148925944Sjoerg if (debug) 149025944Sjoerg log(LOG_DEBUG, "%s%d: %s down(%s)\n", 149125944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 149225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149325944Sjoerg 149425944Sjoerg switch (sp->state[cp->protoidx]) { 149525944Sjoerg case STATE_CLOSED: 149625944Sjoerg case STATE_CLOSING: 149725944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 14984910Swollman break; 149925944Sjoerg case STATE_STOPPED: 150025944Sjoerg (cp->tls)(sp); 150125944Sjoerg /* fall through */ 150225944Sjoerg case STATE_STOPPING: 150325944Sjoerg case STATE_REQ_SENT: 150425944Sjoerg case STATE_ACK_RCVD: 150525944Sjoerg case STATE_ACK_SENT: 150625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 150725944Sjoerg break; 150825944Sjoerg case STATE_OPENED: 150925944Sjoerg (cp->tld)(sp); 151025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 151125944Sjoerg break; 151225944Sjoerg default: 151325944Sjoerg printf("%s%d: %s illegal down in state %s\n", 151425944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 151525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 151625944Sjoerg } 151725944Sjoerg} 15184910Swollman 151911189Sjkh 152025944Sjoergstatic void 152125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 152225944Sjoerg{ 152325944Sjoerg STDDCL; 152425944Sjoerg 152525944Sjoerg if (debug) 152625944Sjoerg log(LOG_DEBUG, "%s%d: %s open(%s)\n", 152725944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 152825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152925944Sjoerg 153025944Sjoerg switch (sp->state[cp->protoidx]) { 153125944Sjoerg case STATE_INITIAL: 153225944Sjoerg (cp->tls)(sp); 153325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 15344910Swollman break; 153525944Sjoerg case STATE_STARTING: 153625944Sjoerg break; 153725944Sjoerg case STATE_CLOSED: 153825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 153925944Sjoerg (cp->scr)(sp); 154025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154125944Sjoerg break; 154225944Sjoerg case STATE_STOPPED: 154325944Sjoerg case STATE_STOPPING: 154425944Sjoerg case STATE_REQ_SENT: 154525944Sjoerg case STATE_ACK_RCVD: 154625944Sjoerg case STATE_ACK_SENT: 154725944Sjoerg case STATE_OPENED: 154825944Sjoerg break; 154925944Sjoerg case STATE_CLOSING: 155025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 155125944Sjoerg break; 155225944Sjoerg } 155325944Sjoerg} 15544910Swollman 155525944Sjoerg 155625944Sjoergstatic void 155725944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 155825944Sjoerg{ 155925944Sjoerg STDDCL; 156025944Sjoerg 156125944Sjoerg if (debug) 156225944Sjoerg log(LOG_DEBUG, "%s%d: %s close(%s)\n", 156325944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 156425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 156525944Sjoerg 156625944Sjoerg switch (sp->state[cp->protoidx]) { 156725944Sjoerg case STATE_INITIAL: 156825944Sjoerg case STATE_CLOSED: 156925944Sjoerg case STATE_CLOSING: 15704910Swollman break; 157125944Sjoerg case STATE_STARTING: 157225944Sjoerg (cp->tlf)(sp); 157325944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 15744910Swollman break; 157525944Sjoerg case STATE_STOPPED: 157625944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 15774910Swollman break; 157825944Sjoerg case STATE_STOPPING: 157925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 15804910Swollman break; 158125944Sjoerg case STATE_OPENED: 158225944Sjoerg (cp->tld)(sp); 158325944Sjoerg /* fall through */ 158425944Sjoerg case STATE_REQ_SENT: 158525944Sjoerg case STATE_ACK_RCVD: 158625944Sjoerg case STATE_ACK_SENT: 158725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 158825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 158925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 15904910Swollman break; 15914910Swollman } 15924910Swollman} 15934910Swollman 159425944Sjoergstatic void 159525944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 159625944Sjoerg{ 159725944Sjoerg STDDCL; 159825944Sjoerg int s; 159925944Sjoerg 160025944Sjoerg s = splimp(); 160125944Sjoerg if (debug) 160225944Sjoerg log(LOG_DEBUG, "%s%d: %s TO(%s) rst_counter = %d\n", 160325944Sjoerg ifp->if_name, ifp->if_unit, cp->name, 160425944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 160525944Sjoerg sp->rst_counter[cp->protoidx]); 160625944Sjoerg 160725944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 160825944Sjoerg /* TO- event */ 160925944Sjoerg switch (sp->state[cp->protoidx]) { 161025944Sjoerg case STATE_CLOSING: 161125944Sjoerg (cp->tlf)(sp); 161225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 161325944Sjoerg break; 161425944Sjoerg case STATE_STOPPING: 161525944Sjoerg (cp->tlf)(sp); 161625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 161725944Sjoerg break; 161825944Sjoerg case STATE_REQ_SENT: 161925944Sjoerg case STATE_ACK_RCVD: 162025944Sjoerg case STATE_ACK_SENT: 162125944Sjoerg (cp->tlf)(sp); 162225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPED); 162325944Sjoerg break; 162425944Sjoerg } 162525944Sjoerg else 162625944Sjoerg /* TO+ event */ 162725944Sjoerg switch (sp->state[cp->protoidx]) { 162825944Sjoerg case STATE_CLOSING: 162925944Sjoerg case STATE_STOPPING: 163025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 163125944Sjoerg 0, 0); 163229681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 163329681Sgibbs sp->lcp.timeout); 163425944Sjoerg break; 163525944Sjoerg case STATE_REQ_SENT: 163625944Sjoerg case STATE_ACK_RCVD: 163725944Sjoerg (cp->scr)(sp); 163825944Sjoerg /* sppp_cp_change_state() will restart the timer */ 163925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 164025944Sjoerg break; 164125944Sjoerg case STATE_ACK_SENT: 164225944Sjoerg (cp->scr)(sp); 164329681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 164429681Sgibbs sp->lcp.timeout); 164525944Sjoerg break; 164625944Sjoerg } 164725944Sjoerg 164825944Sjoerg splx(s); 164925944Sjoerg} 165025944Sjoerg 165111189Sjkh/* 165225944Sjoerg * Change the state of a control protocol in the state automaton. 165325944Sjoerg * Takes care of starting/stopping the restart timer. 165411189Sjkh */ 165525944Sjoergvoid 165625944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 165725944Sjoerg{ 165825944Sjoerg sp->state[cp->protoidx] = newstate; 165925944Sjoerg 166029681Sgibbs untimeout(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 166125944Sjoerg switch (newstate) { 166225944Sjoerg case STATE_INITIAL: 166325944Sjoerg case STATE_STARTING: 166425944Sjoerg case STATE_CLOSED: 166525944Sjoerg case STATE_STOPPED: 166625944Sjoerg case STATE_OPENED: 166725944Sjoerg break; 166825944Sjoerg case STATE_CLOSING: 166925944Sjoerg case STATE_STOPPING: 167025944Sjoerg case STATE_REQ_SENT: 167125944Sjoerg case STATE_ACK_RCVD: 167225944Sjoerg case STATE_ACK_SENT: 167329681Sgibbs sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp, 167429681Sgibbs sp->lcp.timeout); 167525944Sjoerg break; 167625944Sjoerg } 167725944Sjoerg} 167825944Sjoerg/* 167925944Sjoerg *--------------------------------------------------------------------------* 168025944Sjoerg * * 168125944Sjoerg * The LCP implementation. * 168225944Sjoerg * * 168325944Sjoerg *--------------------------------------------------------------------------* 168425944Sjoerg */ 168525944Sjoergstatic void 168625944Sjoergsppp_lcp_init(struct sppp *sp) 168725944Sjoerg{ 168825944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 168925944Sjoerg sp->lcp.magic = 0; 169025944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 169125944Sjoerg sp->fail_counter[IDX_LCP] = 0; 169225944Sjoerg sp->lcp.protos = 0; 169325944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 169430300Sjoerg 169525944Sjoerg /* 169625944Sjoerg * Initialize counters and timeout values. Note that we don't 169725944Sjoerg * use the 3 seconds suggested in RFC 1661 since we are likely 169825944Sjoerg * running on a fast link. XXX We should probably implement 169925944Sjoerg * the exponential backoff option. Note that these values are 170025944Sjoerg * relevant for all control protocols, not just LCP only. 170125944Sjoerg */ 170225944Sjoerg sp->lcp.timeout = 1 * hz; 170325944Sjoerg sp->lcp.max_terminate = 2; 170425944Sjoerg sp->lcp.max_configure = 10; 170525944Sjoerg sp->lcp.max_failure = 10; 170630300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 170725944Sjoerg} 170825944Sjoerg 170925944Sjoergstatic void 171025944Sjoergsppp_lcp_up(struct sppp *sp) 171125944Sjoerg{ 171225944Sjoerg STDDCL; 171325944Sjoerg 171425944Sjoerg /* 171530300Sjoerg * If this interface is passive or dial-on-demand, and we are 171630300Sjoerg * still in Initial state, it means we've got an incoming 171730300Sjoerg * call. Activate the interface. 171825944Sjoerg */ 171925944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 172025944Sjoerg if (debug) 172125944Sjoerg log(LOG_DEBUG, 172230300Sjoerg "%s%d: Up event", ifp->if_name, ifp->if_unit); 172325944Sjoerg ifp->if_flags |= IFF_RUNNING; 172430300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 172530300Sjoerg if (debug) 172630300Sjoerg addlog("(incoming call)\n"); 172730300Sjoerg sp->pp_flags |= PP_CALLIN; 172830300Sjoerg lcp.Open(sp); 172930300Sjoerg } else if (debug) 173030300Sjoerg addlog("\n"); 173125944Sjoerg } 173225944Sjoerg 173325944Sjoerg sppp_up_event(&lcp, sp); 173425944Sjoerg} 173525944Sjoerg 173625944Sjoergstatic void 173725944Sjoergsppp_lcp_down(struct sppp *sp) 173825944Sjoerg{ 173925944Sjoerg STDDCL; 174025944Sjoerg 174125944Sjoerg sppp_down_event(&lcp, sp); 174225944Sjoerg 174325944Sjoerg /* 174425944Sjoerg * If this is neither a dial-on-demand nor a passive 174525944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 174625944Sjoerg * administrator can force a redial by another ``ifconfig 174725944Sjoerg * up''. XXX For leased line operation, should we immediately 174825944Sjoerg * try to reopen the connection here? 174925944Sjoerg */ 175025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 175125944Sjoerg log(LOG_INFO, 175225944Sjoerg "%s%d: Down event (carrier loss), taking interface down.\n", 175325944Sjoerg ifp->if_name, ifp->if_unit); 175425944Sjoerg if_down(ifp); 175525944Sjoerg } else { 175625944Sjoerg if (debug) 175725944Sjoerg log(LOG_DEBUG, 175825944Sjoerg "%s%d: Down event (carrier loss)\n", 175925944Sjoerg ifp->if_name, ifp->if_unit); 176025944Sjoerg } 176130300Sjoerg sp->pp_flags &= ~PP_CALLIN; 176230300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 176330300Sjoerg lcp.Close(sp); 176425944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 176525944Sjoerg} 176625944Sjoerg 176725944Sjoergstatic void 176825944Sjoergsppp_lcp_open(struct sppp *sp) 176925944Sjoerg{ 177030300Sjoerg /* 177130300Sjoerg * If we are authenticator, negotiate LCP_AUTH 177230300Sjoerg */ 177330300Sjoerg if (sp->hisauth.proto != 0) 177430300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 177530300Sjoerg else 177630300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 177730300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 177825944Sjoerg sppp_open_event(&lcp, sp); 177925944Sjoerg} 178025944Sjoerg 178125944Sjoergstatic void 178225944Sjoergsppp_lcp_close(struct sppp *sp) 178325944Sjoerg{ 178425944Sjoerg sppp_close_event(&lcp, sp); 178525944Sjoerg} 178625944Sjoerg 178725944Sjoergstatic void 178825944Sjoergsppp_lcp_TO(void *cookie) 178925944Sjoerg{ 179025944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 179125944Sjoerg} 179225944Sjoerg 179325944Sjoerg/* 179425944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 179525944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 179625944Sjoerg * caused action scn. (The return value is used to make the state 179725944Sjoerg * transition decision in the state automaton.) 179825944Sjoerg */ 179912820Sphkstatic int 180025944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 18014910Swollman{ 180225944Sjoerg STDDCL; 180311189Sjkh u_char *buf, *r, *p; 180425944Sjoerg int origlen, rlen; 180525944Sjoerg u_long nmagic; 180630300Sjoerg u_short authproto; 18074910Swollman 180811189Sjkh len -= 4; 180925944Sjoerg origlen = len; 181011189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 181111189Sjkh if (! buf) 181211189Sjkh return (0); 18134910Swollman 181425706Sjoerg if (debug) 181525944Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opts: ", 181625944Sjoerg ifp->if_name, ifp->if_unit); 181725706Sjoerg 181825944Sjoerg /* pass 1: check for things that need to be rejected */ 181911189Sjkh p = (void*) (h+1); 182011189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 182125944Sjoerg if (debug) 182225944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 182311189Sjkh switch (*p) { 182411189Sjkh case LCP_OPT_MAGIC: 182525944Sjoerg /* Magic number. */ 182625944Sjoerg /* fall through, both are same length */ 182725944Sjoerg case LCP_OPT_ASYNC_MAP: 182825944Sjoerg /* Async control character map. */ 182925944Sjoerg if (len >= 6 || p[1] == 6) 183025944Sjoerg continue; 183125944Sjoerg if (debug) 183225944Sjoerg addlog("[invalid] "); 183325944Sjoerg break; 183425944Sjoerg case LCP_OPT_MRU: 183525944Sjoerg /* Maximum receive unit. */ 183625944Sjoerg if (len >= 4 && p[1] == 4) 183725944Sjoerg continue; 183825944Sjoerg if (debug) 183925944Sjoerg addlog("[invalid] "); 184025944Sjoerg break; 184130300Sjoerg case LCP_OPT_AUTH_PROTO: 184230300Sjoerg if (len < 4) { 184330300Sjoerg if (debug) 184430300Sjoerg addlog("[invalid] "); 184530300Sjoerg break; 184630300Sjoerg } 184730300Sjoerg authproto = (p[2] << 8) + p[3]; 184830300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 184930300Sjoerg if (debug) 185030300Sjoerg addlog("[invalid chap len] "); 185130300Sjoerg break; 185230300Sjoerg } 185330300Sjoerg if (sp->myauth.proto == 0) { 185430300Sjoerg /* we are not configured to do auth */ 185530300Sjoerg if (debug) 185630300Sjoerg addlog("[not configured] "); 185730300Sjoerg break; 185830300Sjoerg } 185930300Sjoerg /* 186030300Sjoerg * Remote want us to authenticate, remember this, 186130300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 186230300Sjoerg * up. 186330300Sjoerg */ 186430300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 186530300Sjoerg continue; 186625944Sjoerg default: 186725944Sjoerg /* Others not supported. */ 186825944Sjoerg if (debug) 186925944Sjoerg addlog("[rej] "); 187025944Sjoerg break; 187125944Sjoerg } 187225944Sjoerg /* Add the option to rejected list. */ 187325944Sjoerg bcopy (p, r, p[1]); 187425944Sjoerg r += p[1]; 187525944Sjoerg rlen += p[1]; 187625944Sjoerg } 187725944Sjoerg if (rlen) { 187825944Sjoerg if (debug) 187925944Sjoerg addlog(" send conf-rej\n"); 188025944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 188125944Sjoerg return 0; 188225944Sjoerg } else if (debug) 188325944Sjoerg addlog("\n"); 188425944Sjoerg 188525944Sjoerg /* 188625944Sjoerg * pass 2: check for option values that are unacceptable and 188725944Sjoerg * thus require to be nak'ed. 188825944Sjoerg */ 188925944Sjoerg if (debug) 189026077Sjoerg log(LOG_DEBUG, "%s%d: lcp parse opt values: ", 189126077Sjoerg ifp->if_name, ifp->if_unit); 189225944Sjoerg 189325944Sjoerg p = (void*) (h+1); 189425944Sjoerg len = origlen; 189525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 189625944Sjoerg if (debug) 189725944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 189825944Sjoerg switch (*p) { 189925944Sjoerg case LCP_OPT_MAGIC: 190011189Sjkh /* Magic number -- extract. */ 190125944Sjoerg nmagic = (u_long)p[2] << 24 | 190225944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 190325944Sjoerg if (nmagic != sp->lcp.magic) { 190425706Sjoerg if (debug) 190525944Sjoerg addlog("0x%x ", nmagic); 190611189Sjkh continue; 190711189Sjkh } 190825944Sjoerg /* 190925944Sjoerg * Local and remote magics equal -- loopback? 191025944Sjoerg */ 191125944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 191230300Sjoerg printf ("%s%d: loopback\n", 191325944Sjoerg ifp->if_name, ifp->if_unit); 191425944Sjoerg sp->pp_loopcnt = 0; 191525944Sjoerg if (ifp->if_flags & IFF_UP) { 191625944Sjoerg if_down(ifp); 191726018Sjoerg sppp_qflush(&sp->pp_cpq); 191825944Sjoerg /* XXX ? */ 191925944Sjoerg lcp.Down(sp); 192025944Sjoerg lcp.Up(sp); 192125944Sjoerg } 192225944Sjoerg } else if (debug) 192325944Sjoerg addlog("[glitch] "); 192425944Sjoerg ++sp->pp_loopcnt; 192525944Sjoerg /* 192625944Sjoerg * We negate our magic here, and NAK it. If 192725944Sjoerg * we see it later in an NAK packet, we 192825944Sjoerg * suggest a new one. 192925944Sjoerg */ 193025944Sjoerg nmagic = ~sp->lcp.magic; 193125944Sjoerg /* Gonna NAK it. */ 193225944Sjoerg p[2] = nmagic >> 24; 193325944Sjoerg p[3] = nmagic >> 16; 193425944Sjoerg p[4] = nmagic >> 8; 193525944Sjoerg p[5] = nmagic; 193611189Sjkh break; 193725944Sjoerg 193811189Sjkh case LCP_OPT_ASYNC_MAP: 193911189Sjkh /* Async control character map -- check to be zero. */ 194025944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 194125706Sjoerg if (debug) 194225944Sjoerg addlog("[empty] "); 194311189Sjkh continue; 194425706Sjoerg } 194525706Sjoerg if (debug) 194625944Sjoerg addlog("[non-empty] "); 194725944Sjoerg /* suggest a zero one */ 194825944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 194911189Sjkh break; 195025944Sjoerg 195111189Sjkh case LCP_OPT_MRU: 195225944Sjoerg /* 195325944Sjoerg * Maximum receive unit. Always agreeable, 195425944Sjoerg * but ignored by now. 195525944Sjoerg */ 195625944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 195725706Sjoerg if (debug) 195825944Sjoerg addlog("%d ", sp->lcp.their_mru); 195911189Sjkh continue; 196030300Sjoerg 196130300Sjoerg case LCP_OPT_AUTH_PROTO: 196230300Sjoerg authproto = (p[2] << 8) + p[3]; 196330300Sjoerg if (sp->myauth.proto != authproto) { 196430300Sjoerg /* not agreed, nak */ 196530300Sjoerg if (debug) 196630300Sjoerg addlog("[mine %s != his %s] ", 196730300Sjoerg sppp_proto_name(sp->hisauth.proto), 196830300Sjoerg sppp_proto_name(authproto)); 196930300Sjoerg p[2] = sp->myauth.proto >> 8; 197030300Sjoerg p[3] = sp->myauth.proto; 197130300Sjoerg break; 197230300Sjoerg } 197330300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 197430300Sjoerg if (debug) 197530300Sjoerg addlog("[chap not MD5] "); 197630300Sjoerg p[4] == CHAP_MD5; 197730300Sjoerg break; 197830300Sjoerg } 197930300Sjoerg continue; 198011189Sjkh } 198125944Sjoerg /* Add the option to nak'ed list. */ 198225706Sjoerg bcopy (p, r, p[1]); 198325706Sjoerg r += p[1]; 198411189Sjkh rlen += p[1]; 198512436Speter } 198625706Sjoerg if (rlen) { 198728036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 198828036Sjoerg if (debug) 198928036Sjoerg addlog(" max_failure (%d) exceeded, " 199028036Sjoerg "send conf-rej\n", 199128036Sjoerg sp->lcp.max_failure); 199228036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 199328036Sjoerg } else { 199428036Sjoerg if (debug) 199528036Sjoerg addlog(" send conf-nak\n"); 199628036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 199728036Sjoerg } 199825944Sjoerg return 0; 199925944Sjoerg } else { 200025944Sjoerg if (debug) 200125944Sjoerg addlog(" send conf-ack\n"); 200228036Sjoerg sp->fail_counter[IDX_LCP] = 0; 200325944Sjoerg sp->pp_loopcnt = 0; 200425944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 200525944Sjoerg h->ident, origlen, h+1); 200625944Sjoerg } 200725944Sjoerg 200811189Sjkh free (buf, M_TEMP); 200911189Sjkh return (rlen == 0); 20104910Swollman} 20114910Swollman 201225944Sjoerg/* 201325944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 201425944Sjoerg * negotiation. 201525944Sjoerg */ 201612820Sphkstatic void 201725944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 20184910Swollman{ 201925944Sjoerg STDDCL; 202025944Sjoerg u_char *buf, *p; 20214910Swollman 202225944Sjoerg len -= 4; 202325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 202425944Sjoerg if (!buf) 20254910Swollman return; 202625944Sjoerg 202725944Sjoerg if (debug) 202825944Sjoerg log(LOG_DEBUG, "%s%d: lcp rej opts: ", 202925944Sjoerg ifp->if_name, ifp->if_unit); 203025944Sjoerg 203125944Sjoerg p = (void*) (h+1); 203225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 203325944Sjoerg if (debug) 203425944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 203525944Sjoerg switch (*p) { 203625944Sjoerg case LCP_OPT_MAGIC: 203725944Sjoerg /* Magic number -- can't use it, use 0 */ 203825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 203925944Sjoerg sp->lcp.magic = 0; 204025944Sjoerg break; 204125944Sjoerg case LCP_OPT_MRU: 204225944Sjoerg /* 204325944Sjoerg * Should not be rejected anyway, since we only 204425944Sjoerg * negotiate a MRU if explicitly requested by 204525944Sjoerg * peer. 204625944Sjoerg */ 204725944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 204825944Sjoerg break; 204930300Sjoerg case LCP_OPT_AUTH_PROTO: 205030300Sjoerg /* 205130300Sjoerg * Peer doesn't want to authenticate himself, 205230300Sjoerg * deny unless this is a dialout call, and 205330300Sjoerg * AUTHFLAG_NOCALLOUT is set. 205430300Sjoerg */ 205530300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 205630300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 205730300Sjoerg if (debug) 205830300Sjoerg addlog("[don't insist on auth " 205930300Sjoerg "for callout]"); 206030300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 206130300Sjoerg break; 206230300Sjoerg } 206330300Sjoerg if (debug) 206430300Sjoerg addlog("[access denied]\n"); 206530300Sjoerg lcp.Close(sp); 206630300Sjoerg break; 206725944Sjoerg } 20684910Swollman } 206925944Sjoerg if (debug) 207025944Sjoerg addlog("\n"); 207125944Sjoerg free (buf, M_TEMP); 207225944Sjoerg return; 207325944Sjoerg} 207425944Sjoerg 207525944Sjoerg/* 207625944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 207725944Sjoerg * negotiation. 207825944Sjoerg */ 207925944Sjoergstatic void 208025944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 208125944Sjoerg{ 208225944Sjoerg STDDCL; 208325944Sjoerg u_char *buf, *p; 208425944Sjoerg u_long magic; 208525944Sjoerg 208625944Sjoerg len -= 4; 208725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 208825944Sjoerg if (!buf) 208925944Sjoerg return; 209025944Sjoerg 209125944Sjoerg if (debug) 209225944Sjoerg log(LOG_DEBUG, "%s%d: lcp nak opts: ", 209325944Sjoerg ifp->if_name, ifp->if_unit); 209425944Sjoerg 209525944Sjoerg p = (void*) (h+1); 209625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 209725706Sjoerg if (debug) 209825944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 209925944Sjoerg switch (*p) { 210025944Sjoerg case LCP_OPT_MAGIC: 210125944Sjoerg /* Magic number -- renegotiate */ 210225944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 210325944Sjoerg len >= 6 && p[1] == 6) { 210425944Sjoerg magic = (u_long)p[2] << 24 | 210525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 210625944Sjoerg /* 210725944Sjoerg * If the remote magic is our negated one, 210825944Sjoerg * this looks like a loopback problem. 210925944Sjoerg * Suggest a new magic to make sure. 211025944Sjoerg */ 211125944Sjoerg if (magic == ~sp->lcp.magic) { 211225944Sjoerg if (debug) 211325944Sjoerg addlog("magic glitch "); 211425944Sjoerg sp->lcp.magic += time.tv_sec + time.tv_usec; 211525944Sjoerg } else { 211625944Sjoerg sp->lcp.magic = magic; 211725944Sjoerg if (debug) 211825944Sjoerg addlog("%d "); 211925944Sjoerg } 212025944Sjoerg } 212125944Sjoerg break; 212225944Sjoerg case LCP_OPT_MRU: 212325944Sjoerg /* 212425944Sjoerg * Peer wants to advise us to negotiate an MRU. 212525944Sjoerg * Agree on it if it's reasonable, or use 212625944Sjoerg * default otherwise. 212725944Sjoerg */ 212825944Sjoerg if (len >= 4 && p[1] == 4) { 212925944Sjoerg u_int mru = p[2] * 256 + p[3]; 213025944Sjoerg if (debug) 213125944Sjoerg addlog("%d ", mru); 213225944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 213325944Sjoerg mru = PP_MTU; 213425944Sjoerg sp->lcp.mru = mru; 213525944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 213625944Sjoerg } 213725944Sjoerg break; 213830300Sjoerg case LCP_OPT_AUTH_PROTO: 213930300Sjoerg /* 214030300Sjoerg * Peer doesn't like our authentication method, 214130300Sjoerg * deny. 214230300Sjoerg */ 214330300Sjoerg if (debug) 214430300Sjoerg addlog("[access denied]\n"); 214530300Sjoerg lcp.Close(sp); 214630300Sjoerg break; 21474910Swollman } 214825944Sjoerg } 214925944Sjoerg if (debug) 215025944Sjoerg addlog("\n"); 215125944Sjoerg free (buf, M_TEMP); 215225944Sjoerg return; 215325944Sjoerg} 215411189Sjkh 215525944Sjoergstatic void 215625944Sjoergsppp_lcp_tlu(struct sppp *sp) 215725944Sjoerg{ 215825944Sjoerg STDDCL; 215925944Sjoerg int i; 216025944Sjoerg u_long mask; 216125944Sjoerg 216225944Sjoerg /* XXX ? */ 216325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 216425944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 216525944Sjoerg /* Coming out of loopback mode. */ 216625944Sjoerg if_up(ifp); 216725944Sjoerg printf ("%s%d: up\n", ifp->if_name, ifp->if_unit); 216825944Sjoerg } 216925944Sjoerg 217025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 217125944Sjoerg if ((cps[i])->flags & CP_QUAL) 217225944Sjoerg (cps[i])->Open(sp); 217325944Sjoerg 217430300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 217530300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 217625944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 217725944Sjoerg else 217825944Sjoerg sp->pp_phase = PHASE_NETWORK; 217925944Sjoerg 218025944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 218125944Sjoerg sppp_phase_name(sp->pp_phase)); 218225944Sjoerg 218330300Sjoerg /* 218430300Sjoerg * Open all authentication protocols. This is even required 218530300Sjoerg * if we already proceeded to network phase, since it might be 218630300Sjoerg * that remote wants us to authenticate, so we might have to 218730300Sjoerg * send a PAP request. Undesired authentication protocols 218830300Sjoerg * don't do anything when they get an Open event. 218930300Sjoerg */ 219030300Sjoerg for (i = 0; i < IDX_COUNT; i++) 219130300Sjoerg if ((cps[i])->flags & CP_AUTH) 219230300Sjoerg (cps[i])->Open(sp); 219330300Sjoerg 219430300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 219525944Sjoerg /* Notify all NCPs. */ 219625944Sjoerg for (i = 0; i < IDX_COUNT; i++) 219725944Sjoerg if ((cps[i])->flags & CP_NCP) 219825944Sjoerg (cps[i])->Open(sp); 219925944Sjoerg } 220025944Sjoerg 220125944Sjoerg /* Send Up events to all started protos. */ 220225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 220325944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 220425944Sjoerg (cps[i])->Up(sp); 220525944Sjoerg 220625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 220725944Sjoerg /* if no NCP is starting, close down */ 220830300Sjoerg sppp_lcp_check_and_close(sp); 220925944Sjoerg} 221025944Sjoerg 221125944Sjoergstatic void 221225944Sjoergsppp_lcp_tld(struct sppp *sp) 221325944Sjoerg{ 221425944Sjoerg STDDCL; 221525944Sjoerg int i; 221625944Sjoerg u_long mask; 221725944Sjoerg 221825944Sjoerg sp->pp_phase = PHASE_TERMINATE; 221925944Sjoerg 222025944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 222125944Sjoerg sppp_phase_name(sp->pp_phase)); 222225944Sjoerg 222325944Sjoerg /* 222425944Sjoerg * Take upper layers down. We send the Down event first and 222525944Sjoerg * the Close second to prevent the upper layers from sending 222625944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 222725944Sjoerg * describes it. 222825944Sjoerg */ 222925944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 223025944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 223125944Sjoerg (cps[i])->Down(sp); 223225944Sjoerg (cps[i])->Close(sp); 223325944Sjoerg } 223425944Sjoerg} 223525944Sjoerg 223625944Sjoergstatic void 223725944Sjoergsppp_lcp_tls(struct sppp *sp) 223825944Sjoerg{ 223925944Sjoerg STDDCL; 224025944Sjoerg 224125944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 224225944Sjoerg 224325944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 224425944Sjoerg sppp_phase_name(sp->pp_phase)); 224525944Sjoerg 224625944Sjoerg /* Notify lower layer if desired. */ 224725944Sjoerg if (sp->pp_tls) 224825944Sjoerg (sp->pp_tls)(sp); 224925944Sjoerg} 225025944Sjoerg 225125944Sjoergstatic void 225225944Sjoergsppp_lcp_tlf(struct sppp *sp) 225325944Sjoerg{ 225425944Sjoerg STDDCL; 225525944Sjoerg 225625944Sjoerg sp->pp_phase = PHASE_DEAD; 225725944Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 225825944Sjoerg sppp_phase_name(sp->pp_phase)); 225925944Sjoerg 226025944Sjoerg /* Notify lower layer if desired. */ 226125944Sjoerg if (sp->pp_tlf) 226225944Sjoerg (sp->pp_tlf)(sp); 226325944Sjoerg} 226425944Sjoerg 226525944Sjoergstatic void 226625944Sjoergsppp_lcp_scr(struct sppp *sp) 226725944Sjoerg{ 226830300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 226925944Sjoerg int i = 0; 227030300Sjoerg u_short authproto; 227125944Sjoerg 227225944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 227325944Sjoerg if (! sp->lcp.magic) 227425944Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 227525944Sjoerg opt[i++] = LCP_OPT_MAGIC; 227625944Sjoerg opt[i++] = 6; 227725944Sjoerg opt[i++] = sp->lcp.magic >> 24; 227825944Sjoerg opt[i++] = sp->lcp.magic >> 16; 227925944Sjoerg opt[i++] = sp->lcp.magic >> 8; 228025944Sjoerg opt[i++] = sp->lcp.magic; 228125944Sjoerg } 228225944Sjoerg 228325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 228425944Sjoerg opt[i++] = LCP_OPT_MRU; 228525944Sjoerg opt[i++] = 4; 228625944Sjoerg opt[i++] = sp->lcp.mru >> 8; 228725944Sjoerg opt[i++] = sp->lcp.mru; 228825944Sjoerg } 228925944Sjoerg 229030300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 229130300Sjoerg authproto = sp->hisauth.proto; 229230300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 229330300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 229430300Sjoerg opt[i++] = authproto >> 8; 229530300Sjoerg opt[i++] = authproto; 229630300Sjoerg if (authproto == PPP_CHAP) 229730300Sjoerg opt[i++] = CHAP_MD5; 229830300Sjoerg } 229930300Sjoerg 230025944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 230125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 230225944Sjoerg} 230325944Sjoerg 230425944Sjoerg/* 230530300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 230630300Sjoerg */ 230730300Sjoergstatic int 230830300Sjoergsppp_ncp_check(struct sppp *sp) 230930300Sjoerg{ 231030300Sjoerg int i, mask; 231130300Sjoerg 231230300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 231330300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 231430300Sjoerg return 1; 231530300Sjoerg return 0; 231630300Sjoerg} 231730300Sjoerg 231830300Sjoerg/* 231925944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 232025944Sjoerg * Called by the NCPs during their tlf action handling. 232125944Sjoerg */ 232225944Sjoergstatic void 232330300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 232425944Sjoerg{ 232525944Sjoerg 232630300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 232730300Sjoerg /* don't bother, we are already going down */ 232830300Sjoerg return; 232930300Sjoerg 233030300Sjoerg if (sppp_ncp_check(sp)) 233130300Sjoerg return; 233230300Sjoerg 233325944Sjoerg lcp.Close(sp); 233425944Sjoerg} 233525944Sjoerg/* 233625944Sjoerg *--------------------------------------------------------------------------* 233725944Sjoerg * * 233825944Sjoerg * The IPCP implementation. * 233925944Sjoerg * * 234025944Sjoerg *--------------------------------------------------------------------------* 234125944Sjoerg */ 234225944Sjoerg 234325944Sjoergstatic void 234425944Sjoergsppp_ipcp_init(struct sppp *sp) 234525944Sjoerg{ 234625944Sjoerg sp->ipcp.opts = 0; 234725944Sjoerg sp->ipcp.flags = 0; 234825944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 234925944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 235029681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 235125944Sjoerg} 235225944Sjoerg 235325944Sjoergstatic void 235425944Sjoergsppp_ipcp_up(struct sppp *sp) 235525944Sjoerg{ 235625944Sjoerg sppp_up_event(&ipcp, sp); 235725944Sjoerg} 235825944Sjoerg 235925944Sjoergstatic void 236025944Sjoergsppp_ipcp_down(struct sppp *sp) 236125944Sjoerg{ 236225944Sjoerg sppp_down_event(&ipcp, sp); 236325944Sjoerg} 236425944Sjoerg 236525944Sjoergstatic void 236625944Sjoergsppp_ipcp_open(struct sppp *sp) 236725944Sjoerg{ 236825944Sjoerg STDDCL; 236925944Sjoerg u_long myaddr, hisaddr; 237025944Sjoerg 237130300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 237225944Sjoerg /* 237325944Sjoerg * If we don't have his address, this probably means our 237425944Sjoerg * interface doesn't want to talk IP at all. (This could 237525944Sjoerg * be the case if somebody wants to speak only IPX, for 237625944Sjoerg * example.) Don't open IPCP in this case. 237725944Sjoerg */ 237825944Sjoerg if (hisaddr == 0L) { 237925944Sjoerg /* XXX this message should go away */ 238025944Sjoerg if (debug) 238125944Sjoerg log(LOG_DEBUG, "%s%d: ipcp_open(): no IP interface\n", 238225944Sjoerg ifp->if_name, ifp->if_unit); 238325944Sjoerg return; 238425944Sjoerg } 238525944Sjoerg 238625944Sjoerg if (myaddr == 0L) { 238725944Sjoerg /* 238825944Sjoerg * I don't have an assigned address, so i need to 238925944Sjoerg * negotiate my address. 239025944Sjoerg */ 239125944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 239225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 239325944Sjoerg } 239425944Sjoerg sppp_open_event(&ipcp, sp); 239525944Sjoerg} 239625944Sjoerg 239725944Sjoergstatic void 239825944Sjoergsppp_ipcp_close(struct sppp *sp) 239925944Sjoerg{ 240025944Sjoerg sppp_close_event(&ipcp, sp); 240125944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 240225944Sjoerg /* 240325944Sjoerg * My address was dynamic, clear it again. 240425944Sjoerg */ 240525944Sjoerg sppp_set_ip_addr(sp, 0L); 240625944Sjoerg} 240725944Sjoerg 240825944Sjoergstatic void 240925944Sjoergsppp_ipcp_TO(void *cookie) 241025944Sjoerg{ 241125944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 241225944Sjoerg} 241325944Sjoerg 241425944Sjoerg/* 241525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 241625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 241725944Sjoerg * caused action scn. (The return value is used to make the state 241825944Sjoerg * transition decision in the state automaton.) 241925944Sjoerg */ 242025944Sjoergstatic int 242125944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 242225944Sjoerg{ 242325944Sjoerg u_char *buf, *r, *p; 242425944Sjoerg struct ifnet *ifp = &sp->pp_if; 242525944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 242625944Sjoerg u_long hisaddr, desiredaddr; 242725944Sjoerg 242825944Sjoerg len -= 4; 242925944Sjoerg origlen = len; 243025944Sjoerg /* 243125944Sjoerg * Make sure to allocate a buf that can at least hold a 243225944Sjoerg * conf-nak with an `address' option. We might need it below. 243325944Sjoerg */ 243425944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 243525944Sjoerg if (! buf) 243625944Sjoerg return (0); 243725944Sjoerg 243825944Sjoerg /* pass 1: see if we can recognize them */ 243925944Sjoerg if (debug) 244025944Sjoerg log(LOG_DEBUG, "%s%d: ipcp parse opts: ", 244125944Sjoerg ifp->if_name, ifp->if_unit); 244225944Sjoerg p = (void*) (h+1); 244325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 244425944Sjoerg if (debug) 244525944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 244625944Sjoerg switch (*p) { 244725944Sjoerg#ifdef notyet 244825944Sjoerg case IPCP_OPT_COMPRESSION: 244925944Sjoerg if (len >= 6 && p[1] >= 6) { 245025944Sjoerg /* correctly formed compress option */ 245125944Sjoerg continue; 245211189Sjkh } 245325706Sjoerg if (debug) 245425944Sjoerg addlog("[invalid] "); 245525944Sjoerg break; 245625944Sjoerg#endif 245725944Sjoerg case IPCP_OPT_ADDRESS: 245825944Sjoerg if (len >= 6 && p[1] == 6) { 245925944Sjoerg /* correctly formed address option */ 246025944Sjoerg continue; 246125944Sjoerg } 246225706Sjoerg if (debug) 246325944Sjoerg addlog("[invalid] "); 246411189Sjkh break; 246525944Sjoerg default: 246625944Sjoerg /* Others not supported. */ 246725944Sjoerg if (debug) 246825944Sjoerg addlog("[rej] "); 24694910Swollman break; 24704910Swollman } 247125944Sjoerg /* Add the option to rejected list. */ 247225944Sjoerg bcopy (p, r, p[1]); 247325944Sjoerg r += p[1]; 247425944Sjoerg rlen += p[1]; 247525944Sjoerg } 247625944Sjoerg if (rlen) { 247725944Sjoerg if (debug) 247825944Sjoerg addlog(" send conf-rej\n"); 247925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 248025944Sjoerg return 0; 248125944Sjoerg } else if (debug) 248225944Sjoerg addlog("\n"); 248325944Sjoerg 248425944Sjoerg /* pass 2: parse option values */ 248530300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 248625944Sjoerg if (debug) 248730300Sjoerg log(LOG_DEBUG, "%s%d: ipcp parse opt values: ", 248830300Sjoerg ifp->if_name, ifp->if_unit); 248925944Sjoerg p = (void*) (h+1); 249025944Sjoerg len = origlen; 249125944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 249225944Sjoerg if (debug) 249325944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 249425944Sjoerg switch (*p) { 249525944Sjoerg#ifdef notyet 249625944Sjoerg case IPCP_OPT_COMPRESSION: 249725944Sjoerg continue; 249825944Sjoerg#endif 249925944Sjoerg case IPCP_OPT_ADDRESS: 250025944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 250125944Sjoerg p[4] << 8 | p[5]; 250225944Sjoerg if (desiredaddr == hisaddr) { 250325944Sjoerg /* 250425944Sjoerg * Peer's address is same as our value, 250525944Sjoerg * this is agreeable. Gonna conf-ack 250625944Sjoerg * it. 250725944Sjoerg */ 250825944Sjoerg if (debug) 250930300Sjoerg addlog("%s [ack] ", 251030300Sjoerg sppp_dotted_quad(hisaddr)); 251125944Sjoerg /* record that we've seen it already */ 251225944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 251325944Sjoerg continue; 251425944Sjoerg } 251525944Sjoerg /* 251625944Sjoerg * The address wasn't agreeable. This is either 251725944Sjoerg * he sent us 0.0.0.0, asking to assign him an 251825944Sjoerg * address, or he send us another address not 251925944Sjoerg * matching our value. Either case, we gonna 252025944Sjoerg * conf-nak it with our value. 252125944Sjoerg */ 252225944Sjoerg if (debug) { 252325944Sjoerg if (desiredaddr == 0) 252425944Sjoerg addlog("[addr requested] "); 252525944Sjoerg else 252630300Sjoerg addlog("%s [not agreed] ", 252730300Sjoerg sppp_dotted_quad(desiredaddr)); 252825944Sjoerg 252925944Sjoerg p[2] = hisaddr >> 24; 253025944Sjoerg p[3] = hisaddr >> 16; 253125944Sjoerg p[4] = hisaddr >> 8; 253225944Sjoerg p[5] = hisaddr; 253325944Sjoerg } 253411189Sjkh break; 253525706Sjoerg } 253625944Sjoerg /* Add the option to nak'ed list. */ 253725944Sjoerg bcopy (p, r, p[1]); 253825944Sjoerg r += p[1]; 253925944Sjoerg rlen += p[1]; 254025944Sjoerg } 254125944Sjoerg 254225944Sjoerg /* 254325944Sjoerg * If we are about to conf-ack the request, but haven't seen 254425944Sjoerg * his address so far, gonna conf-nak it instead, with the 254525944Sjoerg * `address' option present and our idea of his address being 254625944Sjoerg * filled in there, to request negotiation of both addresses. 254725944Sjoerg * 254825944Sjoerg * XXX This can result in an endless req - nak loop if peer 254925944Sjoerg * doesn't want to send us his address. Q: What should we do 255025944Sjoerg * about it? XXX A: implement the max-failure counter. 255125944Sjoerg */ 255225944Sjoerg if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { 255325944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 255425944Sjoerg buf[1] = 6; 255525944Sjoerg buf[2] = hisaddr >> 24; 255625944Sjoerg buf[3] = hisaddr >> 16; 255725944Sjoerg buf[4] = hisaddr >> 8; 255825944Sjoerg buf[5] = hisaddr; 255925944Sjoerg rlen = 6; 256025706Sjoerg if (debug) 256125944Sjoerg addlog("still need hisaddr "); 256225944Sjoerg } 256325944Sjoerg 256425944Sjoerg if (rlen) { 256525706Sjoerg if (debug) 256625944Sjoerg addlog(" send conf-nak\n"); 256725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 256825944Sjoerg } else { 256925706Sjoerg if (debug) 257025944Sjoerg addlog(" send conf-ack\n"); 257125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 257225944Sjoerg h->ident, origlen, h+1); 257325944Sjoerg } 257425944Sjoerg 257525944Sjoerg free (buf, M_TEMP); 257625944Sjoerg return (rlen == 0); 257725944Sjoerg} 257825944Sjoerg 257925944Sjoerg/* 258025944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 258125944Sjoerg * negotiation. 258225944Sjoerg */ 258325944Sjoergstatic void 258425944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 258525944Sjoerg{ 258625944Sjoerg u_char *buf, *p; 258725944Sjoerg struct ifnet *ifp = &sp->pp_if; 258825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 258925944Sjoerg 259025944Sjoerg len -= 4; 259125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 259225944Sjoerg if (!buf) 259325944Sjoerg return; 259425944Sjoerg 259525944Sjoerg if (debug) 259625944Sjoerg log(LOG_DEBUG, "%s%d: ipcp rej opts: ", 259725944Sjoerg ifp->if_name, ifp->if_unit); 259825944Sjoerg 259925944Sjoerg p = (void*) (h+1); 260025944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 260125706Sjoerg if (debug) 260225944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 260325944Sjoerg switch (*p) { 260425944Sjoerg case IPCP_OPT_ADDRESS: 260525944Sjoerg /* 260625944Sjoerg * Peer doesn't grok address option. This is 260725944Sjoerg * bad. XXX Should we better give up here? 260825944Sjoerg */ 260925944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 261025944Sjoerg break; 261125944Sjoerg#ifdef notyet 261225944Sjoerg case IPCP_OPT_COMPRESS: 261325944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); 261425944Sjoerg break; 261525944Sjoerg#endif 261625944Sjoerg } 26174910Swollman } 261825944Sjoerg if (debug) 261925944Sjoerg addlog("\n"); 262025944Sjoerg free (buf, M_TEMP); 262125944Sjoerg return; 26224910Swollman} 26234910Swollman 262425944Sjoerg/* 262525944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 262625944Sjoerg * negotiation. 262725944Sjoerg */ 262812820Sphkstatic void 262925944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 26304910Swollman{ 263125944Sjoerg u_char *buf, *p; 263225944Sjoerg struct ifnet *ifp = &sp->pp_if; 263325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 263425944Sjoerg u_long wantaddr; 26354910Swollman 263625944Sjoerg len -= 4; 263725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 263825944Sjoerg if (!buf) 263925944Sjoerg return; 264025944Sjoerg 264125944Sjoerg if (debug) 264225944Sjoerg log(LOG_DEBUG, "%s%d: ipcp nak opts: ", 264325944Sjoerg ifp->if_name, ifp->if_unit); 264425944Sjoerg 264525944Sjoerg p = (void*) (h+1); 264625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 264725944Sjoerg if (debug) 264825944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 264925944Sjoerg switch (*p) { 265025944Sjoerg case IPCP_OPT_ADDRESS: 265125944Sjoerg /* 265225944Sjoerg * Peer doesn't like our local IP address. See 265325944Sjoerg * if we can do something for him. We'll drop 265425944Sjoerg * him our address then. 265525944Sjoerg */ 265625944Sjoerg if (len >= 6 && p[1] == 6) { 265725944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 265825944Sjoerg p[4] << 8 | p[5]; 265925944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 266025944Sjoerg if (debug) 266130300Sjoerg addlog("[wantaddr %s] ", 266230300Sjoerg sppp_dotted_quad(wantaddr)); 266325944Sjoerg /* 266425944Sjoerg * When doing dynamic address assignment, 266525944Sjoerg * we accept his offer. Otherwise, we 266625944Sjoerg * ignore it and thus continue to negotiate 266725944Sjoerg * our already existing value. 266825944Sjoerg */ 266925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 267025944Sjoerg sppp_set_ip_addr(sp, wantaddr); 267125944Sjoerg if (debug) 267225944Sjoerg addlog("[agree] "); 267325944Sjoerg } 267425944Sjoerg } 267525944Sjoerg break; 267625944Sjoerg#ifdef notyet 267725944Sjoerg case IPCP_OPT_COMPRESS: 267825944Sjoerg /* 267925944Sjoerg * Peer wants different compression parameters. 268025944Sjoerg */ 268125944Sjoerg break; 268225944Sjoerg#endif 268325944Sjoerg } 268425944Sjoerg } 268525944Sjoerg if (debug) 268625944Sjoerg addlog("\n"); 268725944Sjoerg free (buf, M_TEMP); 268825944Sjoerg return; 26894910Swollman} 26904910Swollman 269112820Sphkstatic void 269225944Sjoergsppp_ipcp_tlu(struct sppp *sp) 26934910Swollman{ 26944910Swollman} 26954910Swollman 269625944Sjoergstatic void 269725944Sjoergsppp_ipcp_tld(struct sppp *sp) 269825944Sjoerg{ 269925944Sjoerg} 270025944Sjoerg 270125944Sjoergstatic void 270225944Sjoergsppp_ipcp_tls(struct sppp *sp) 270325944Sjoerg{ 270425944Sjoerg /* indicate to LCP that it must stay alive */ 270525944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 270625944Sjoerg} 270725944Sjoerg 270825944Sjoergstatic void 270925944Sjoergsppp_ipcp_tlf(struct sppp *sp) 271025944Sjoerg{ 271125944Sjoerg /* we no longer need LCP */ 271225944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 271330300Sjoerg sppp_lcp_check_and_close(sp); 271425944Sjoerg} 271525944Sjoerg 271625944Sjoergstatic void 271725944Sjoergsppp_ipcp_scr(struct sppp *sp) 271825944Sjoerg{ 271925944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 272025944Sjoerg u_long ouraddr; 272125944Sjoerg int i = 0; 272225944Sjoerg 272325944Sjoerg#ifdef notyet 272425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 272525944Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 272625944Sjoerg opt[i++] = 6; 272725944Sjoerg opt[i++] = 0; /* VJ header compression */ 272825944Sjoerg opt[i++] = 0x2d; /* VJ header compression */ 272925944Sjoerg opt[i++] = max_slot_id; 273025944Sjoerg opt[i++] = comp_slot_id; 273125944Sjoerg } 273225944Sjoerg#endif 273325944Sjoerg 273425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 273530300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 273625944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 273725944Sjoerg opt[i++] = 6; 273825944Sjoerg opt[i++] = ouraddr >> 24; 273925944Sjoerg opt[i++] = ouraddr >> 16; 274025944Sjoerg opt[i++] = ouraddr >> 8; 274125944Sjoerg opt[i++] = ouraddr; 274225944Sjoerg } 274325944Sjoerg 274425944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 274525944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 274625944Sjoerg} 274725944Sjoerg 274825944Sjoerg 274925944Sjoerg/* 275030300Sjoerg *--------------------------------------------------------------------------* 275130300Sjoerg * * 275230300Sjoerg * The CHAP implementation. * 275330300Sjoerg * * 275430300Sjoerg *--------------------------------------------------------------------------* 275530300Sjoerg */ 275630300Sjoerg 275730300Sjoerg/* 275830300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 275930300Sjoerg * the control protocols do, since they do have Open and Close events, but 276030300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 276130300Sjoerg * authentication protocols may be different in both directions (this makes 276230300Sjoerg * sense, think of a machine that never accepts incoming calls but only 276330300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 276430300Sjoerg * 276530300Sjoerg * Our state machine for the local authentication protocol (we are requesting 276630300Sjoerg * the peer to authenticate) looks like: 276730300Sjoerg * 276830300Sjoerg * RCA- 276930300Sjoerg * +--------------------------------------------+ 277030300Sjoerg * V scn,tld| 277130300Sjoerg * +--------+ Close +---------+ RCA+ 277230300Sjoerg * | |<----------------------------------| |------+ 277330300Sjoerg * +--->| Closed | TO* | Opened | sca | 277430300Sjoerg * | | |-----+ +-------| |<-----+ 277530300Sjoerg * | +--------+ irc | | +---------+ 277630300Sjoerg * | ^ | | ^ 277730300Sjoerg * | | | | | 277830300Sjoerg * | | | | | 277930300Sjoerg * | TO-| | | | 278030300Sjoerg * | |tld TO+ V | | 278130300Sjoerg * | | +------->+ | | 278230300Sjoerg * | | | | | | 278330300Sjoerg * | +--------+ V | | 278430300Sjoerg * | | |<----+<--------------------+ | 278530300Sjoerg * | | Req- | scr | 278630300Sjoerg * | | Sent | | 278730300Sjoerg * | | | | 278830300Sjoerg * | +--------+ | 278930300Sjoerg * | RCA- | | RCA+ | 279030300Sjoerg * +------+ +------------------------------------------+ 279130300Sjoerg * scn,tld sca,irc,ict,tlu 279230300Sjoerg * 279330300Sjoerg * 279430300Sjoerg * with: 279530300Sjoerg * 279630300Sjoerg * Open: LCP reached authentication phase 279730300Sjoerg * Close: LCP reached terminate phase 279830300Sjoerg * 279930300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 280030300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 280130300Sjoerg * TO+: timeout with restart counter >= 0 280230300Sjoerg * TO-: timeout with restart counter < 0 280330300Sjoerg * TO*: reschedule timeout for CHAP 280430300Sjoerg * 280530300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 280630300Sjoerg * sca: send ack packet (pap-ack, chap-success) 280730300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 280830300Sjoerg * ict: initialize re-challenge timer (CHAP only) 280930300Sjoerg * 281030300Sjoerg * tlu: this-layer-up, LCP reaches network phase 281130300Sjoerg * tld: this-layer-down, LCP enters terminate phase 281230300Sjoerg * 281330300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 281430300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 281530300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 281630300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 281730300Sjoerg * causing LCP to enter terminate phase. 281830300Sjoerg * 281930300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 282030300Sjoerg * expected to send one based on the successful negotiation of PAP as 282130300Sjoerg * the authentication protocol during the LCP option negotiation. 282230300Sjoerg * 282330300Sjoerg * Incoming authentication protocol requests (remote requests 282430300Sjoerg * authentication, we are peer) don't employ a state machine at all, 282530300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 282630300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 282730300Sjoerg * still in authentication phase (thereby violating the standard that 282830300Sjoerg * demands that these NCP packets are to be discarded), so we keep 282930300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 283030300Sjoerg * phase network once we've seen a positive acknowledge for the 283130300Sjoerg * authentication. 283230300Sjoerg */ 283330300Sjoerg 283430300Sjoerg/* 283530300Sjoerg * Handle incoming CHAP packets. 283630300Sjoerg */ 283730300Sjoergvoid 283830300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 283930300Sjoerg{ 284030300Sjoerg STDDCL; 284130300Sjoerg struct lcp_header *h; 284230300Sjoerg int len, x; 284330300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 284430300Sjoerg int value_len, name_len; 284530300Sjoerg MD5_CTX ctx; 284630300Sjoerg 284730300Sjoerg len = m->m_pkthdr.len; 284830300Sjoerg if (len < 4) { 284930300Sjoerg if (debug) 285030300Sjoerg log(LOG_DEBUG, 285130300Sjoerg "%s%d: chap invalid packet length: %d bytes\n", 285230300Sjoerg ifp->if_name, ifp->if_unit, len); 285330300Sjoerg return; 285430300Sjoerg } 285530300Sjoerg h = mtod (m, struct lcp_header*); 285630300Sjoerg if (len > ntohs (h->len)) 285730300Sjoerg len = ntohs (h->len); 285830300Sjoerg 285930300Sjoerg switch (h->type) { 286030300Sjoerg /* challenge, failure and success are his authproto */ 286130300Sjoerg case CHAP_CHALLENGE: 286230300Sjoerg value = 1 + (u_char*)(h+1); 286330300Sjoerg value_len = value[-1]; 286430300Sjoerg name = value + value_len; 286530300Sjoerg name_len = len - value_len - 5; 286630300Sjoerg if (name_len < 0) { 286730300Sjoerg if (debug) { 286830300Sjoerg log(LOG_DEBUG, 286930300Sjoerg "%s%d: chap corrupted challenge " 287030300Sjoerg "<%s id=0x%x len=%d", 287130300Sjoerg ifp->if_name, ifp->if_unit, 287230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 287330300Sjoerg h->ident, ntohs(h->len)); 287430300Sjoerg if (len > 4) 287530300Sjoerg sppp_print_bytes((u_char*) (h+1), len-4); 287630300Sjoerg addlog(">\n"); 287730300Sjoerg } 287830300Sjoerg break; 287930300Sjoerg } 288030300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 288130300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 288230300Sjoerg log(LOG_INFO, "%s%d: chap challenge, his name "); 288330300Sjoerg sppp_print_string(name, name_len); 288430300Sjoerg addlog(" != expected "); 288530300Sjoerg sppp_print_string(sp->hisauth.name, 288630300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 288730300Sjoerg addlog("\n"); 288830300Sjoerg } 288930300Sjoerg 289030300Sjoerg if (debug) { 289130300Sjoerg log(LOG_DEBUG, 289230300Sjoerg "%s%d: chap input <%s id=0x%x len=%d name=", 289330300Sjoerg ifp->if_name, ifp->if_unit, 289430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 289530300Sjoerg ntohs(h->len)); 289630300Sjoerg sppp_print_string((char*) name, name_len); 289730300Sjoerg addlog(" value-size=%d value=", value_len); 289830300Sjoerg sppp_print_bytes(value, value_len); 289930300Sjoerg addlog(">\n"); 290030300Sjoerg } 290130300Sjoerg 290230300Sjoerg /* Compute reply value. */ 290330300Sjoerg MD5Init(&ctx); 290430300Sjoerg MD5Update(&ctx, &h->ident, 1); 290530300Sjoerg MD5Update(&ctx, sp->myauth.secret, 290630300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 290730300Sjoerg MD5Update(&ctx, value, value_len); 290830300Sjoerg MD5Final(digest, &ctx); 290930300Sjoerg dsize = sizeof digest; 291030300Sjoerg 291130300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 291230300Sjoerg sizeof dsize, (const char *)&dsize, 291330300Sjoerg sizeof digest, digest, 291430300Sjoerg sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 291530300Sjoerg sp->myauth.name, 291630300Sjoerg 0); 291730300Sjoerg break; 291830300Sjoerg 291930300Sjoerg case CHAP_SUCCESS: 292030300Sjoerg if (debug) { 292130300Sjoerg log(LOG_DEBUG, "%s%d: chap success", 292230300Sjoerg ifp->if_name, ifp->if_unit); 292330300Sjoerg if (len > 4) { 292430300Sjoerg addlog(": "); 292530300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 292630300Sjoerg } 292730300Sjoerg addlog("\n"); 292830300Sjoerg } 292930300Sjoerg x = splimp(); 293030300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 293130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 293230300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 293330300Sjoerg /* 293430300Sjoerg * We are authenticator for CHAP but didn't 293530300Sjoerg * complete yet. Leave it to tlu to proceed 293630300Sjoerg * to network phase. 293730300Sjoerg */ 293830300Sjoerg splx(x); 293930300Sjoerg break; 294030300Sjoerg } 294130300Sjoerg splx(x); 294230300Sjoerg sppp_phase_network(sp); 294330300Sjoerg break; 294430300Sjoerg 294530300Sjoerg case CHAP_FAILURE: 294630300Sjoerg if (debug) { 294730300Sjoerg log(LOG_INFO, "%s%d: chap failure", 294830300Sjoerg ifp->if_name, ifp->if_unit); 294930300Sjoerg if (len > 4) { 295030300Sjoerg addlog(": "); 295130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 295230300Sjoerg } 295330300Sjoerg addlog("\n"); 295430300Sjoerg } else 295530300Sjoerg log(LOG_INFO, "%s%d: chap failure\n", 295630300Sjoerg ifp->if_name, ifp->if_unit); 295730300Sjoerg /* await LCP shutdown by authenticator */ 295830300Sjoerg break; 295930300Sjoerg 296030300Sjoerg /* response is my authproto */ 296130300Sjoerg case CHAP_RESPONSE: 296230300Sjoerg value = 1 + (u_char*)(h+1); 296330300Sjoerg value_len = value[-1]; 296430300Sjoerg name = value + value_len; 296530300Sjoerg name_len = len - value_len - 5; 296630300Sjoerg if (name_len < 0) { 296730300Sjoerg if (debug) { 296830300Sjoerg log(LOG_DEBUG, 296930300Sjoerg "%s%d: chap corrupted response " 297030300Sjoerg "<%s id=0x%x len=%d", 297130300Sjoerg ifp->if_name, ifp->if_unit, 297230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 297330300Sjoerg h->ident, ntohs(h->len)); 297430300Sjoerg if (len > 4) 297530300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 297630300Sjoerg addlog(">\n"); 297730300Sjoerg } 297830300Sjoerg break; 297930300Sjoerg } 298030300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 298130300Sjoerg if (debug) 298230300Sjoerg log(LOG_DEBUG, 298330300Sjoerg "%s%d: chap dropping response for old ID " 298430300Sjoerg "(got %d, expected %d)\n", 298530300Sjoerg h->ident, sp->confid[IDX_CHAP]); 298630300Sjoerg break; 298730300Sjoerg } 298830300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 298930300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 299030300Sjoerg log(LOG_INFO, "%s%d: chap response, his name ", 299130300Sjoerg ifp->if_name, ifp->if_unit); 299230300Sjoerg sppp_print_string(name, name_len); 299330300Sjoerg addlog(" != expected "); 299430300Sjoerg sppp_print_string(sp->hisauth.name, 299530300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 299630300Sjoerg addlog("\n"); 299730300Sjoerg } 299830300Sjoerg if (debug) { 299930300Sjoerg log(LOG_DEBUG, "%s%d: chap input(%s) " 300030300Sjoerg "<%s id=0x%x len=%d name=", 300130300Sjoerg ifp->if_name, ifp->if_unit, 300230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 300330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 300430300Sjoerg h->ident, ntohs (h->len)); 300530300Sjoerg sppp_print_string((char*)name, name_len); 300630300Sjoerg addlog(" value-size=%d value=", value_len); 300730300Sjoerg sppp_print_bytes(value, value_len); 300830300Sjoerg addlog(">\n"); 300930300Sjoerg } 301030300Sjoerg if (value_len != AUTHKEYLEN) { 301130300Sjoerg if (debug) 301230300Sjoerg log(LOG_DEBUG, 301330300Sjoerg "%s%d: chap bad hash value length: " 301430300Sjoerg "%d bytes, should be %d\n", 301530300Sjoerg ifp->if_name, ifp->if_unit, value_len, 301630300Sjoerg AUTHKEYLEN); 301730300Sjoerg break; 301830300Sjoerg } 301930300Sjoerg 302030300Sjoerg MD5Init(&ctx); 302130300Sjoerg MD5Update(&ctx, &h->ident, 1); 302230300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 302330300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 302430300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 302530300Sjoerg MD5Final(digest, &ctx); 302630300Sjoerg 302730300Sjoerg#define FAILMSG "Failed..." 302830300Sjoerg#define SUCCMSG "Welcome!" 302930300Sjoerg 303030300Sjoerg if (value_len != sizeof digest || 303130300Sjoerg bcmp(digest, value, value_len) != 0) { 303230300Sjoerg /* action scn, tld */ 303330300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 303430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 303530300Sjoerg 0); 303630300Sjoerg chap.tld(sp); 303730300Sjoerg break; 303830300Sjoerg } 303930300Sjoerg /* action sca, perhaps tlu */ 304030300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 304130300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 304230300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 304330300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 304430300Sjoerg 0); 304530300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 304630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 304730300Sjoerg chap.tlu(sp); 304830300Sjoerg } 304930300Sjoerg break; 305030300Sjoerg 305130300Sjoerg default: 305230300Sjoerg /* Unknown CHAP packet type -- ignore. */ 305330300Sjoerg if (debug) { 305430300Sjoerg log(LOG_DEBUG, "%s%d: chap unknown input(%s) " 305530300Sjoerg "<0x%x id=0x%xh len=%d", 305630300Sjoerg ifp->if_name, ifp->if_unit, 305730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 305830300Sjoerg h->type, h->ident, ntohs(h->len)); 305930300Sjoerg if (len > 4) 306030300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 306130300Sjoerg addlog(">\n"); 306230300Sjoerg } 306330300Sjoerg break; 306430300Sjoerg 306530300Sjoerg } 306630300Sjoerg} 306730300Sjoerg 306830300Sjoergstatic void 306930300Sjoergsppp_chap_init(struct sppp *sp) 307030300Sjoerg{ 307130300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 307230300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 307330300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 307430300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 307530300Sjoerg} 307630300Sjoerg 307730300Sjoergstatic void 307830300Sjoergsppp_chap_open(struct sppp *sp) 307930300Sjoerg{ 308030300Sjoerg if (sp->myauth.proto == PPP_CHAP && 308130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 308230300Sjoerg /* we are authenticator for CHAP, start it */ 308330300Sjoerg chap.scr(sp); 308430300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 308530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 308630300Sjoerg } 308730300Sjoerg /* nothing to be done if we are peer, await a challenge */ 308830300Sjoerg} 308930300Sjoerg 309030300Sjoergstatic void 309130300Sjoergsppp_chap_close(struct sppp *sp) 309230300Sjoerg{ 309330300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 309430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 309530300Sjoerg} 309630300Sjoerg 309730300Sjoergstatic void 309830300Sjoergsppp_chap_TO(void *cookie) 309930300Sjoerg{ 310030300Sjoerg struct sppp *sp = (struct sppp *)cookie; 310130300Sjoerg STDDCL; 310230300Sjoerg int s; 310330300Sjoerg 310430300Sjoerg s = splimp(); 310530300Sjoerg if (debug) 310630300Sjoerg log(LOG_DEBUG, "%s%d: chap TO(%s) rst_counter = %d\n", 310730300Sjoerg ifp->if_name, ifp->if_unit, 310830300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 310930300Sjoerg sp->rst_counter[IDX_CHAP]); 311030300Sjoerg 311130300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 311230300Sjoerg /* TO- event */ 311330300Sjoerg switch (sp->state[IDX_CHAP]) { 311430300Sjoerg case STATE_REQ_SENT: 311530300Sjoerg chap.tld(sp); 311630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 311730300Sjoerg break; 311830300Sjoerg } 311930300Sjoerg else 312030300Sjoerg /* TO+ (or TO*) event */ 312130300Sjoerg switch (sp->state[IDX_CHAP]) { 312230300Sjoerg case STATE_OPENED: 312330300Sjoerg /* TO* event */ 312430300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 312530300Sjoerg /* fall through */ 312630300Sjoerg case STATE_REQ_SENT: 312730300Sjoerg chap.scr(sp); 312830300Sjoerg /* sppp_cp_change_state() will restart the timer */ 312930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 313030300Sjoerg break; 313130300Sjoerg } 313230300Sjoerg 313330300Sjoerg splx(s); 313430300Sjoerg} 313530300Sjoerg 313630300Sjoergstatic void 313730300Sjoergsppp_chap_tlu(struct sppp *sp) 313830300Sjoerg{ 313930300Sjoerg STDDCL; 314030300Sjoerg int i, x; 314130300Sjoerg 314230300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 314330300Sjoerg 314430300Sjoerg /* 314530300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 314630300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 314730300Sjoerg * initial challenge-response exchange has taken place. 314830300Sjoerg * Provide for an option to avoid rechallenges. 314930300Sjoerg */ 315030300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 315130300Sjoerg /* 315230300Sjoerg * Compute the re-challenge timeout. This will yield 315330300Sjoerg * a number between 300 and 810 seconds. 315430300Sjoerg */ 315530300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 315630300Sjoerg 315730300Sjoerg sp->ch[IDX_CHAP] = timeout(chap.TO, (void *)sp, i * hz); 315830300Sjoerg } 315930300Sjoerg 316030300Sjoerg if (debug) { 316130300Sjoerg log(LOG_DEBUG, 316230300Sjoerg "%s%d: chap %s, ", 316330300Sjoerg ifp->if_name, ifp->if_unit, 316430300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 316530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 316630300Sjoerg addlog("next re-challenge in %d seconds\n", i); 316730300Sjoerg else 316830300Sjoerg addlog("re-challenging supressed\n"); 316930300Sjoerg } 317030300Sjoerg 317130300Sjoerg x = splimp(); 317230300Sjoerg /* indicate to LCP that we need to be closed down */ 317330300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 317430300Sjoerg 317530300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 317630300Sjoerg /* 317730300Sjoerg * Remote is authenticator, but his auth proto didn't 317830300Sjoerg * complete yet. Defer the transition to network 317930300Sjoerg * phase. 318030300Sjoerg */ 318130300Sjoerg splx(x); 318230300Sjoerg return; 318330300Sjoerg } 318430300Sjoerg splx(x); 318530300Sjoerg 318630300Sjoerg /* 318730300Sjoerg * If we are already in phase network, we are done here. This 318830300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 318930300Sjoerg */ 319030300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 319130300Sjoerg sppp_phase_network(sp); 319230300Sjoerg} 319330300Sjoerg 319430300Sjoergstatic void 319530300Sjoergsppp_chap_tld(struct sppp *sp) 319630300Sjoerg{ 319730300Sjoerg STDDCL; 319830300Sjoerg 319930300Sjoerg if (debug) 320030300Sjoerg log(LOG_DEBUG, "%s%d: chap tld\n", ifp->if_name, ifp->if_unit); 320130300Sjoerg untimeout(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 320230300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 320330300Sjoerg 320430300Sjoerg lcp.Close(sp); 320530300Sjoerg} 320630300Sjoerg 320730300Sjoergstatic void 320830300Sjoergsppp_chap_scr(struct sppp *sp) 320930300Sjoerg{ 321030300Sjoerg struct timeval tv; 321130300Sjoerg u_long *ch, seed; 321230300Sjoerg u_char clen; 321330300Sjoerg 321430300Sjoerg /* Compute random challenge. */ 321530300Sjoerg ch = (u_long *)sp->myauth.challenge; 321630300Sjoerg microtime(&tv); 321730300Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 321830300Sjoerg ch[0] = seed ^ random(); 321930300Sjoerg ch[1] = seed ^ random(); 322030300Sjoerg ch[2] = seed ^ random(); 322130300Sjoerg ch[3] = seed ^ random(); 322230300Sjoerg clen = AUTHKEYLEN; 322330300Sjoerg 322430300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 322530300Sjoerg 322630300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 322730300Sjoerg sizeof clen, (const char *)&clen, 322830300Sjoerg AUTHKEYLEN, sp->myauth.challenge, 322930300Sjoerg sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 323030300Sjoerg sp->myauth.name, 323130300Sjoerg 0); 323230300Sjoerg} 323330300Sjoerg/* 323430300Sjoerg *--------------------------------------------------------------------------* 323530300Sjoerg * * 323630300Sjoerg * The PAP implementation. * 323730300Sjoerg * * 323830300Sjoerg *--------------------------------------------------------------------------* 323930300Sjoerg */ 324030300Sjoerg/* 324130300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 324230300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 324330300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 324430300Sjoerg * retry counter is expired). 324530300Sjoerg */ 324630300Sjoerg 324730300Sjoerg/* 324830300Sjoerg * Handle incoming PAP packets. */ 324930300Sjoergstatic void 325030300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 325130300Sjoerg{ 325230300Sjoerg STDDCL; 325330300Sjoerg struct lcp_header *h; 325430300Sjoerg int len, x; 325530300Sjoerg u_char *name, *passwd, mlen; 325630300Sjoerg int name_len, passwd_len; 325730300Sjoerg 325830300Sjoerg len = m->m_pkthdr.len; 325930300Sjoerg if (len < 5) { 326030300Sjoerg if (debug) 326130300Sjoerg log(LOG_DEBUG, 326230300Sjoerg "%s%d: pap invalid packet length: %d bytes\n", 326330300Sjoerg ifp->if_name, ifp->if_unit, len); 326430300Sjoerg return; 326530300Sjoerg } 326630300Sjoerg h = mtod (m, struct lcp_header*); 326730300Sjoerg if (len > ntohs (h->len)) 326830300Sjoerg len = ntohs (h->len); 326930300Sjoerg switch (h->type) { 327030300Sjoerg /* PAP request is my authproto */ 327130300Sjoerg case PAP_REQ: 327230300Sjoerg name = 1 + (u_char*)(h+1); 327330300Sjoerg name_len = name[-1]; 327430300Sjoerg passwd = name + name_len + 1; 327530300Sjoerg if (name_len > len - 6 || 327630300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 327730300Sjoerg if (debug) { 327830300Sjoerg log(LOG_DEBUG, "%s%d: pap corrupted input " 327930300Sjoerg "<%s id=0x%x len=%d", 328030300Sjoerg ifp->if_name, ifp->if_unit, 328130300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 328230300Sjoerg h->ident, ntohs(h->len)); 328330300Sjoerg if (len > 4) 328430300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 328530300Sjoerg addlog(">\n"); 328630300Sjoerg } 328730300Sjoerg break; 328830300Sjoerg } 328930300Sjoerg if (debug) { 329030300Sjoerg log(LOG_DEBUG, "%s%d: pap input(%s) " 329130300Sjoerg "<%s id=0x%x len=%d name=", 329230300Sjoerg ifp->if_name, ifp->if_unit, 329330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 329430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 329530300Sjoerg h->ident, ntohs(h->len)); 329630300Sjoerg sppp_print_string((char*)name, name_len); 329730300Sjoerg addlog(" passwd="); 329830300Sjoerg sppp_print_string((char*)passwd, passwd_len); 329930300Sjoerg addlog(">\n"); 330030300Sjoerg } 330130300Sjoerg if (name_len > AUTHNAMELEN || 330230300Sjoerg passwd_len > AUTHKEYLEN || 330330300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 330430300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 330530300Sjoerg /* action scn, tld */ 330630300Sjoerg mlen = sizeof(FAILMSG) - 1; 330730300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 330830300Sjoerg sizeof mlen, (const char *)&mlen, 330930300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 331030300Sjoerg 0); 331130300Sjoerg pap.tld(sp); 331230300Sjoerg break; 331330300Sjoerg } 331430300Sjoerg /* action sca, perhaps tlu */ 331530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 331630300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 331730300Sjoerg mlen = sizeof(SUCCMSG) - 1; 331830300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 331930300Sjoerg sizeof mlen, (const char *)&mlen, 332030300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 332130300Sjoerg 0); 332230300Sjoerg } 332330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 332430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 332530300Sjoerg pap.tlu(sp); 332630300Sjoerg } 332730300Sjoerg break; 332830300Sjoerg 332930300Sjoerg /* ack and nak are his authproto */ 333030300Sjoerg case PAP_ACK: 333130300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 333230300Sjoerg if (debug) { 333330300Sjoerg log(LOG_DEBUG, "%s%d: pap success", 333430300Sjoerg ifp->if_name, ifp->if_unit); 333530300Sjoerg name_len = *((char *)h); 333630300Sjoerg if (len > 5 && name_len) { 333730300Sjoerg addlog(": "); 333830300Sjoerg sppp_print_string((char*)(h+1), name_len); 333930300Sjoerg } 334030300Sjoerg addlog("\n"); 334130300Sjoerg } 334230300Sjoerg x = splimp(); 334330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 334430300Sjoerg if (sp->myauth.proto == PPP_PAP && 334530300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 334630300Sjoerg /* 334730300Sjoerg * We are authenticator for PAP but didn't 334830300Sjoerg * complete yet. Leave it to tlu to proceed 334930300Sjoerg * to network phase. 335030300Sjoerg */ 335130300Sjoerg splx(x); 335230300Sjoerg break; 335330300Sjoerg } 335430300Sjoerg splx(x); 335530300Sjoerg sppp_phase_network(sp); 335630300Sjoerg break; 335730300Sjoerg 335830300Sjoerg case PAP_NAK: 335930300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 336030300Sjoerg if (debug) { 336130300Sjoerg log(LOG_INFO, "%s%d: pap failure", 336230300Sjoerg ifp->if_name, ifp->if_unit); 336330300Sjoerg name_len = *((char *)h); 336430300Sjoerg if (len > 5 && name_len) { 336530300Sjoerg addlog(": "); 336630300Sjoerg sppp_print_string((char*)(h+1), name_len); 336730300Sjoerg } 336830300Sjoerg addlog("\n"); 336930300Sjoerg } else 337030300Sjoerg log(LOG_INFO, "%s%d: pap failure\n", 337130300Sjoerg ifp->if_name, ifp->if_unit); 337230300Sjoerg /* await LCP shutdown by authenticator */ 337330300Sjoerg break; 337430300Sjoerg 337530300Sjoerg default: 337630300Sjoerg /* Unknown PAP packet type -- ignore. */ 337730300Sjoerg if (debug) { 337830300Sjoerg log(LOG_DEBUG, "%s%d: pap corrupted input " 337930300Sjoerg "<0x%x id=0x%x len=%d", 338030300Sjoerg ifp->if_name, ifp->if_unit, 338130300Sjoerg h->type, h->ident, ntohs(h->len)); 338230300Sjoerg if (len > 4) 338330300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 338430300Sjoerg addlog(">\n"); 338530300Sjoerg } 338630300Sjoerg break; 338730300Sjoerg 338830300Sjoerg } 338930300Sjoerg} 339030300Sjoerg 339130300Sjoergstatic void 339230300Sjoergsppp_pap_init(struct sppp *sp) 339330300Sjoerg{ 339430300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 339530300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 339630300Sjoerg sp->fail_counter[IDX_PAP] = 0; 339730300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 339830300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 339930300Sjoerg} 340030300Sjoerg 340130300Sjoergstatic void 340230300Sjoergsppp_pap_open(struct sppp *sp) 340330300Sjoerg{ 340430300Sjoerg if (sp->hisauth.proto == PPP_PAP && 340530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 340630300Sjoerg /* we are authenticator for PAP, start our timer */ 340730300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 340830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 340930300Sjoerg } 341030300Sjoerg if (sp->myauth.proto == PPP_PAP) { 341130300Sjoerg /* we are peer, send a request, and start a timer */ 341230300Sjoerg pap.scr(sp); 341330300Sjoerg sp->pap_my_to_ch = timeout(sppp_pap_my_TO, (void *)sp, 341430300Sjoerg sp->lcp.timeout); 341530300Sjoerg } 341630300Sjoerg} 341730300Sjoerg 341830300Sjoergstatic void 341930300Sjoergsppp_pap_close(struct sppp *sp) 342030300Sjoerg{ 342130300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 342230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 342330300Sjoerg} 342430300Sjoerg 342530300Sjoerg/* 342630300Sjoerg * That's the timeout routine if we are authenticator. Since the 342730300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 342830300Sjoerg */ 342930300Sjoergstatic void 343030300Sjoergsppp_pap_TO(void *cookie) 343130300Sjoerg{ 343230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 343330300Sjoerg STDDCL; 343430300Sjoerg int s; 343530300Sjoerg 343630300Sjoerg s = splimp(); 343730300Sjoerg if (debug) 343830300Sjoerg log(LOG_DEBUG, "%s%d: pap TO(%s) rst_counter = %d\n", 343930300Sjoerg ifp->if_name, ifp->if_unit, 344030300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 344130300Sjoerg sp->rst_counter[IDX_PAP]); 344230300Sjoerg 344330300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 344430300Sjoerg /* TO- event */ 344530300Sjoerg switch (sp->state[IDX_PAP]) { 344630300Sjoerg case STATE_REQ_SENT: 344730300Sjoerg pap.tld(sp); 344830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 344930300Sjoerg break; 345030300Sjoerg } 345130300Sjoerg else 345230300Sjoerg /* TO+ event, not very much we could do */ 345330300Sjoerg switch (sp->state[IDX_PAP]) { 345430300Sjoerg case STATE_REQ_SENT: 345530300Sjoerg /* sppp_cp_change_state() will restart the timer */ 345630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 345730300Sjoerg break; 345830300Sjoerg } 345930300Sjoerg 346030300Sjoerg splx(s); 346130300Sjoerg} 346230300Sjoerg 346330300Sjoerg/* 346430300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 346530300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 346630300Sjoerg * XXX We should impose a max counter. 346730300Sjoerg */ 346830300Sjoergstatic void 346930300Sjoergsppp_pap_my_TO(void *cookie) 347030300Sjoerg{ 347130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 347230300Sjoerg STDDCL; 347330300Sjoerg 347430300Sjoerg if (debug) 347530300Sjoerg log(LOG_DEBUG, "%s%d: pap peer TO\n", 347630300Sjoerg ifp->if_name, ifp->if_unit); 347730300Sjoerg 347830300Sjoerg pap.scr(sp); 347930300Sjoerg} 348030300Sjoerg 348130300Sjoergstatic void 348230300Sjoergsppp_pap_tlu(struct sppp *sp) 348330300Sjoerg{ 348430300Sjoerg STDDCL; 348530300Sjoerg int x; 348630300Sjoerg 348730300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 348830300Sjoerg 348930300Sjoerg if (debug) 349030300Sjoerg log(LOG_DEBUG, "%s%d: %s tlu\n", 349130300Sjoerg ifp->if_name, ifp->if_unit, pap.name); 349230300Sjoerg 349330300Sjoerg x = splimp(); 349430300Sjoerg /* indicate to LCP that we need to be closed down */ 349530300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 349630300Sjoerg 349730300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 349830300Sjoerg /* 349930300Sjoerg * Remote is authenticator, but his auth proto didn't 350030300Sjoerg * complete yet. Defer the transition to network 350130300Sjoerg * phase. 350230300Sjoerg */ 350330300Sjoerg splx(x); 350430300Sjoerg return; 350530300Sjoerg } 350630300Sjoerg splx(x); 350730300Sjoerg sppp_phase_network(sp); 350830300Sjoerg} 350930300Sjoerg 351030300Sjoergstatic void 351130300Sjoergsppp_pap_tld(struct sppp *sp) 351230300Sjoerg{ 351330300Sjoerg STDDCL; 351430300Sjoerg 351530300Sjoerg if (debug) 351630300Sjoerg log(LOG_DEBUG, "%s%d: pap tld\n", ifp->if_name, ifp->if_unit); 351730300Sjoerg untimeout(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 351830300Sjoerg untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 351930300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 352030300Sjoerg 352130300Sjoerg lcp.Close(sp); 352230300Sjoerg} 352330300Sjoerg 352430300Sjoergstatic void 352530300Sjoergsppp_pap_scr(struct sppp *sp) 352630300Sjoerg{ 352730300Sjoerg STDDCL; 352830300Sjoerg u_char idlen, pwdlen; 352930300Sjoerg 353030300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 353130300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 353230300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 353330300Sjoerg 353430300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 353530300Sjoerg sizeof idlen, (const char *)&idlen, 353630300Sjoerg (unsigned)idlen, sp->myauth.name, 353730300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 353830300Sjoerg (unsigned)pwdlen, sp->myauth.secret, 353930300Sjoerg 0); 354030300Sjoerg} 354130300Sjoerg/* 354225944Sjoerg * Random miscellaneous functions. 354325944Sjoerg */ 354425944Sjoerg 35454910Swollman/* 354630300Sjoerg * Send a PAP or CHAP proto packet. 354730300Sjoerg * 354830300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 354930300Sjoerg * ``unsigned mlen, const u_char *msg''. Processing will stop iff 355030300Sjoerg * mlen == 0. 355130300Sjoerg */ 355230300Sjoerg 355330300Sjoergstatic void 355430300Sjoergsppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, 355530300Sjoerg ...) 355630300Sjoerg{ 355730300Sjoerg STDDCL; 355830300Sjoerg struct ppp_header *h; 355930300Sjoerg struct lcp_header *lh; 356030300Sjoerg struct mbuf *m; 356130300Sjoerg u_char *p; 356230300Sjoerg int len; 356330300Sjoerg unsigned mlen; 356430300Sjoerg const char *msg; 356530300Sjoerg va_list ap; 356630300Sjoerg 356730300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 356830300Sjoerg if (! m) 356930300Sjoerg return; 357030300Sjoerg m->m_pkthdr.rcvif = 0; 357130300Sjoerg 357230300Sjoerg h = mtod (m, struct ppp_header*); 357330300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 357430300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 357530300Sjoerg h->protocol = htons(cp->proto); 357630300Sjoerg 357730300Sjoerg lh = (struct lcp_header*)(h + 1); 357830300Sjoerg lh->type = type; 357930300Sjoerg lh->ident = id; 358030300Sjoerg p = (u_char*) (lh+1); 358130300Sjoerg 358230300Sjoerg va_start(ap, id); 358330300Sjoerg len = 0; 358430300Sjoerg 358530300Sjoerg while ((mlen = va_arg(ap, unsigned)) != 0) { 358630300Sjoerg msg = va_arg(ap, const char *); 358730300Sjoerg len += mlen; 358830300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 358930300Sjoerg va_end(ap); 359030300Sjoerg m_freem(m); 359130300Sjoerg return; 359230300Sjoerg } 359330300Sjoerg 359430300Sjoerg bcopy(msg, p, mlen); 359530300Sjoerg p += mlen; 359630300Sjoerg } 359730300Sjoerg va_end(ap); 359830300Sjoerg 359930300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 360030300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 360130300Sjoerg 360230300Sjoerg if (debug) { 360330300Sjoerg log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d", 360430300Sjoerg ifp->if_name, ifp->if_unit, cp->name, 360530300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 360630300Sjoerg lh->ident, ntohs(lh->len)); 360730300Sjoerg if (len) 360830300Sjoerg sppp_print_bytes((u_char*) (lh+1), len); 360930300Sjoerg addlog(">\n"); 361030300Sjoerg } 361130300Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 361230300Sjoerg IF_DROP (&sp->pp_fastq); 361330300Sjoerg IF_DROP (&ifp->if_snd); 361430300Sjoerg m_freem (m); 361530300Sjoerg ++ifp->if_oerrors; 361630300Sjoerg } else 361730300Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 361830300Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 361930300Sjoerg (*ifp->if_start) (ifp); 362030300Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 362130300Sjoerg} 362230300Sjoerg 362330300Sjoerg/* 362425944Sjoerg * Flush interface queue. 36254910Swollman */ 362612820Sphkstatic void 362725944Sjoergsppp_qflush(struct ifqueue *ifq) 36284910Swollman{ 362925944Sjoerg struct mbuf *m, *n; 36304910Swollman 363125944Sjoerg n = ifq->ifq_head; 363225944Sjoerg while ((m = n)) { 363325944Sjoerg n = m->m_act; 363425944Sjoerg m_freem (m); 363511189Sjkh } 363625944Sjoerg ifq->ifq_head = 0; 363725944Sjoerg ifq->ifq_tail = 0; 363825944Sjoerg ifq->ifq_len = 0; 363925944Sjoerg} 364025944Sjoerg 364125944Sjoerg/* 364225944Sjoerg * Send keepalive packets, every 10 seconds. 364325944Sjoerg */ 364425944Sjoergstatic void 364525944Sjoergsppp_keepalive(void *dummy) 364625944Sjoerg{ 364725944Sjoerg struct sppp *sp; 364825944Sjoerg int s; 364925944Sjoerg 365025944Sjoerg s = splimp(); 365125944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 365225944Sjoerg struct ifnet *ifp = &sp->pp_if; 365325944Sjoerg 365425944Sjoerg /* Keepalive mode disabled or channel down? */ 365525944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 365625944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 365725944Sjoerg continue; 365825944Sjoerg 365925944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 366025944Sjoerg if (! (sp->pp_flags & PP_CISCO) && 366125944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 366225944Sjoerg continue; 366325944Sjoerg 366425944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 366525944Sjoerg /* No keepalive packets got. Stop the interface. */ 366625944Sjoerg printf ("%s%d: down\n", ifp->if_name, ifp->if_unit); 366725944Sjoerg if_down (ifp); 366826018Sjoerg sppp_qflush (&sp->pp_cpq); 366925944Sjoerg if (! (sp->pp_flags & PP_CISCO)) { 367025944Sjoerg /* XXX */ 367125944Sjoerg /* Shut down the PPP link. */ 367225944Sjoerg lcp.Down(sp); 367325944Sjoerg /* Initiate negotiation. XXX */ 367425944Sjoerg lcp.Up(sp); 367525944Sjoerg } 36764910Swollman } 367725944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 367825944Sjoerg ++sp->pp_alivecnt; 367925944Sjoerg if (sp->pp_flags & PP_CISCO) 368025944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 368125944Sjoerg sp->pp_rseq); 368225944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 368325944Sjoerg long nmagic = htonl (sp->lcp.magic); 368425944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 368525944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 368625944Sjoerg sp->lcp.echoid, 4, &nmagic); 368725944Sjoerg } 36884910Swollman } 368925944Sjoerg splx(s); 369029681Sgibbs keepalive_ch = timeout(sppp_keepalive, 0, hz * 10); 36914910Swollman} 36924910Swollman 369325944Sjoerg/* 369425944Sjoerg * Get both IP addresses. 369525944Sjoerg */ 369625944Sjoergstatic void 369730300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 369825944Sjoerg{ 369925944Sjoerg struct ifnet *ifp = &sp->pp_if; 370025944Sjoerg struct ifaddr *ifa; 370130300Sjoerg struct sockaddr_in *si, *sm; 370225944Sjoerg u_long ssrc, ddst; 370325944Sjoerg 370425944Sjoerg ssrc = ddst = 0L; 370525944Sjoerg /* 370625944Sjoerg * Pick the first AF_INET address from the list, 370725944Sjoerg * aliases don't make any sense on a p2p link anyway. 370825944Sjoerg */ 370925944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 371030300Sjoerg ifa; 371125944Sjoerg ifa = ifa->ifa_link.tqe_next) 371225944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 371325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 371430300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 371525944Sjoerg if (si) 371625944Sjoerg break; 371725944Sjoerg } 371825944Sjoerg if (ifa) { 371930300Sjoerg if (si && si->sin_addr.s_addr) { 372025944Sjoerg ssrc = si->sin_addr.s_addr; 372130300Sjoerg if (srcmask) 372230300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 372330300Sjoerg } 372425944Sjoerg 372525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 372625944Sjoerg if (si && si->sin_addr.s_addr) 372725944Sjoerg ddst = si->sin_addr.s_addr; 372825944Sjoerg } 372925944Sjoerg 373025944Sjoerg if (dst) *dst = ntohl(ddst); 373125944Sjoerg if (src) *src = ntohl(ssrc); 373225944Sjoerg} 373325944Sjoerg 373425944Sjoerg/* 373525944Sjoerg * Set my IP address. Must be called at splimp. 373625944Sjoerg */ 373725944Sjoergstatic void 373825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 373925944Sjoerg{ 374025944Sjoerg struct ifnet *ifp = &sp->pp_if; 374125944Sjoerg struct ifaddr *ifa; 374225944Sjoerg struct sockaddr_in *si; 374325944Sjoerg u_long ssrc, ddst; 374425944Sjoerg 374525944Sjoerg /* 374625944Sjoerg * Pick the first AF_INET address from the list, 374725944Sjoerg * aliases don't make any sense on a p2p link anyway. 374825944Sjoerg */ 374925944Sjoerg for (ifa = ifp->if_addrhead.tqh_first, si = 0; 375030300Sjoerg ifa; 375125944Sjoerg ifa = ifa->ifa_link.tqe_next) 375225944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 375325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 375425944Sjoerg if (si) 375525944Sjoerg break; 375625944Sjoerg } 375725944Sjoerg if (ifa && si) 375825944Sjoerg si->sin_addr.s_addr = htonl(src); 375925944Sjoerg} 376025944Sjoerg 376130300Sjoergstatic int 376230300Sjoergsppp_params(struct sppp *sp, int cmd, void *data) 376330300Sjoerg{ 376430300Sjoerg int subcmd; 376530300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 376630300Sjoerg struct spppreq spr; 376730300Sjoerg 376830300Sjoerg /* 376930300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 377030300Sjoerg * Check the cmd word first before attempting to fetch all the 377130300Sjoerg * data. 377230300Sjoerg */ 377330300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 377430300Sjoerg return EFAULT; 377530300Sjoerg 377630300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 377730300Sjoerg return EFAULT; 377830300Sjoerg 377930300Sjoerg switch (subcmd) { 378030300Sjoerg case SPPPIOGDEFS: 378130300Sjoerg if (cmd != SIOCGIFGENERIC) 378230300Sjoerg return EINVAL; 378330300Sjoerg /* 378430300Sjoerg * We copy over the entire current state, but clean 378530300Sjoerg * out some of the stuff we don't wanna pass up. 378630300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 378730300Sjoerg * called by any user. No need to ever get PAP or 378830300Sjoerg * CHAP secrets back to userland anyway. 378930300Sjoerg */ 379030300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 379130300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 379230300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 379330300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 379430300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 379530300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 379630300Sjoerg 379730300Sjoerg case SPPPIOSDEFS: 379830300Sjoerg if (cmd != SIOCSIFGENERIC) 379930300Sjoerg return EINVAL; 380030300Sjoerg /* 380130300Sjoerg * We have a very specific idea of which fields we allow 380230300Sjoerg * being passed back from userland, so to not clobber our 380330300Sjoerg * current state. For one, we only allow setting 380430300Sjoerg * anything if LCP is in dead phase. Once the LCP 380530300Sjoerg * negotiations started, the authentication settings must 380630300Sjoerg * not be changed again. (The administrator can force an 380730300Sjoerg * ifconfig down in order to get LCP back into dead 380830300Sjoerg * phase.) 380930300Sjoerg * 381030300Sjoerg * Also, we only allow for authentication parameters to be 381130300Sjoerg * specified. 381230300Sjoerg * 381330300Sjoerg * XXX Should allow to set or clear pp_flags. 381430300Sjoerg * 381530300Sjoerg * Finally, if the respective authentication protocol to 381630300Sjoerg * be used is set differently than 0, but the secret is 381730300Sjoerg * passed as all zeros, we don't trash the existing secret. 381830300Sjoerg * This allows an administrator to change the system name 381930300Sjoerg * only without clobbering the secret (which he didn't get 382030300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 382130300Sjoerg * secrets are cleared if the authentication protocol is 382230300Sjoerg * reset to 0. 382330300Sjoerg */ 382430300Sjoerg if (sp->pp_phase != PHASE_DEAD) 382530300Sjoerg return EBUSY; 382630300Sjoerg 382730300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 382830300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 382930300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 383030300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 383130300Sjoerg return EINVAL; 383230300Sjoerg 383330300Sjoerg if (spr.defs.myauth.proto == 0) 383430300Sjoerg /* resetting myauth */ 383530300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 383630300Sjoerg else { 383730300Sjoerg /* setting/changing myauth */ 383830300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 383930300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 384030300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 384130300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 384230300Sjoerg AUTHKEYLEN); 384330300Sjoerg } 384430300Sjoerg if (spr.defs.hisauth.proto == 0) 384530300Sjoerg /* resetting hisauth */ 384630300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 384730300Sjoerg else { 384830300Sjoerg /* setting/changing hisauth */ 384930300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 385030300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 385130300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 385230300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 385330300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 385430300Sjoerg AUTHKEYLEN); 385530300Sjoerg } 385630300Sjoerg break; 385730300Sjoerg 385830300Sjoerg default: 385930300Sjoerg return EINVAL; 386030300Sjoerg } 386130300Sjoerg 386230300Sjoerg return 0; 386330300Sjoerg} 386430300Sjoerg 386530300Sjoergstatic void 386630300Sjoergsppp_phase_network(struct sppp *sp) 386730300Sjoerg{ 386830300Sjoerg struct ifnet *ifp = &sp->pp_if; 386930300Sjoerg int i; 387030300Sjoerg u_long mask; 387130300Sjoerg 387230300Sjoerg sp->pp_phase = PHASE_NETWORK; 387330300Sjoerg 387430300Sjoerg log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit, 387530300Sjoerg sppp_phase_name(sp->pp_phase)); 387630300Sjoerg 387730300Sjoerg /* Notify NCPs now. */ 387830300Sjoerg for (i = 0; i < IDX_COUNT; i++) 387930300Sjoerg if ((cps[i])->flags & CP_NCP) 388030300Sjoerg (cps[i])->Open(sp); 388130300Sjoerg 388230300Sjoerg /* Send Up events to all NCPs. */ 388330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 388430300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 388530300Sjoerg (cps[i])->Up(sp); 388630300Sjoerg 388730300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 388830300Sjoerg sppp_lcp_check_and_close(sp); 388930300Sjoerg} 389030300Sjoerg 389130300Sjoerg 389225706Sjoergstatic const char * 389325944Sjoergsppp_cp_type_name(u_char type) 38944910Swollman{ 389530300Sjoerg static char buf[12]; 38964910Swollman switch (type) { 389730300Sjoerg case CONF_REQ: return "conf-req"; 389830300Sjoerg case CONF_ACK: return "conf-ack"; 389930300Sjoerg case CONF_NAK: return "conf-nak"; 390030300Sjoerg case CONF_REJ: return "conf-rej"; 390130300Sjoerg case TERM_REQ: return "term-req"; 390230300Sjoerg case TERM_ACK: return "term-ack"; 390330300Sjoerg case CODE_REJ: return "code-rej"; 390430300Sjoerg case PROTO_REJ: return "proto-rej"; 390530300Sjoerg case ECHO_REQ: return "echo-req"; 390630300Sjoerg case ECHO_REPLY: return "echo-reply"; 390730300Sjoerg case DISC_REQ: return "discard-req"; 39084910Swollman } 390925706Sjoerg sprintf (buf, "0x%x", type); 391030300Sjoerg return buf; 39114910Swollman} 39124910Swollman 391325706Sjoergstatic const char * 391430300Sjoergsppp_auth_type_name(u_short proto, u_char type) 391530300Sjoerg{ 391630300Sjoerg static char buf[12]; 391730300Sjoerg switch (proto) { 391830300Sjoerg case PPP_CHAP: 391930300Sjoerg switch (type) { 392030300Sjoerg case CHAP_CHALLENGE: return "challenge"; 392130300Sjoerg case CHAP_RESPONSE: return "response"; 392230300Sjoerg case CHAP_SUCCESS: return "success"; 392330300Sjoerg case CHAP_FAILURE: return "failure"; 392430300Sjoerg } 392530300Sjoerg case PPP_PAP: 392630300Sjoerg switch (type) { 392730300Sjoerg case PAP_REQ: return "req"; 392830300Sjoerg case PAP_ACK: return "ack"; 392930300Sjoerg case PAP_NAK: return "nak"; 393030300Sjoerg } 393130300Sjoerg } 393230300Sjoerg sprintf (buf, "0x%x", type); 393330300Sjoerg return buf; 393430300Sjoerg} 393530300Sjoerg 393630300Sjoergstatic const char * 393725944Sjoergsppp_lcp_opt_name(u_char opt) 39384910Swollman{ 393930300Sjoerg static char buf[12]; 394025944Sjoerg switch (opt) { 394130300Sjoerg case LCP_OPT_MRU: return "mru"; 394230300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 394330300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 394430300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 394530300Sjoerg case LCP_OPT_MAGIC: return "magic"; 394630300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 394730300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 39484910Swollman } 394925944Sjoerg sprintf (buf, "0x%x", opt); 395030300Sjoerg return buf; 39514910Swollman} 39524910Swollman 395325944Sjoergstatic const char * 395425944Sjoergsppp_ipcp_opt_name(u_char opt) 395525944Sjoerg{ 395630300Sjoerg static char buf[12]; 395725944Sjoerg switch (opt) { 395830300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 395930300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 396030300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 396125944Sjoerg } 396225944Sjoerg sprintf (buf, "0x%x", opt); 396330300Sjoerg return buf; 396425944Sjoerg} 396525944Sjoerg 396625944Sjoergstatic const char * 396725944Sjoergsppp_state_name(int state) 396825944Sjoerg{ 396925944Sjoerg switch (state) { 397025944Sjoerg case STATE_INITIAL: return "initial"; 397125944Sjoerg case STATE_STARTING: return "starting"; 397225944Sjoerg case STATE_CLOSED: return "closed"; 397325944Sjoerg case STATE_STOPPED: return "stopped"; 397425944Sjoerg case STATE_CLOSING: return "closing"; 397525944Sjoerg case STATE_STOPPING: return "stopping"; 397625944Sjoerg case STATE_REQ_SENT: return "req-sent"; 397725944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 397825944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 397925944Sjoerg case STATE_OPENED: return "opened"; 398025944Sjoerg } 398125944Sjoerg return "illegal"; 398225944Sjoerg} 398325944Sjoerg 398425944Sjoergstatic const char * 398525944Sjoergsppp_phase_name(enum ppp_phase phase) 398625944Sjoerg{ 398725944Sjoerg switch (phase) { 398825944Sjoerg case PHASE_DEAD: return "dead"; 398925944Sjoerg case PHASE_ESTABLISH: return "establish"; 399025944Sjoerg case PHASE_TERMINATE: return "terminate"; 399125944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 399225944Sjoerg case PHASE_NETWORK: return "network"; 399325944Sjoerg } 399425944Sjoerg return "illegal"; 399525944Sjoerg} 399625944Sjoerg 399725944Sjoergstatic const char * 399825944Sjoergsppp_proto_name(u_short proto) 399925944Sjoerg{ 400025944Sjoerg static char buf[12]; 400125944Sjoerg switch (proto) { 400225944Sjoerg case PPP_LCP: return "lcp"; 400325944Sjoerg case PPP_IPCP: return "ipcp"; 400430300Sjoerg case PPP_PAP: return "pap"; 400530300Sjoerg case PPP_CHAP: return "chap"; 400625944Sjoerg } 400725944Sjoerg sprintf(buf, "0x%x", (unsigned)proto); 400825944Sjoerg return buf; 400925944Sjoerg} 401025944Sjoerg 401112820Sphkstatic void 401230300Sjoergsppp_print_bytes(const u_char *p, u_short len) 40134910Swollman{ 401425706Sjoerg addlog(" %x", *p++); 40154910Swollman while (--len > 0) 401625706Sjoerg addlog("-%x", *p++); 40174910Swollman} 401825944Sjoerg 401930300Sjoergstatic void 402030300Sjoergsppp_print_string(const char *p, u_short len) 402130300Sjoerg{ 402230300Sjoerg u_char c; 402330300Sjoerg 402430300Sjoerg while (len-- > 0) { 402530300Sjoerg c = *p++; 402630300Sjoerg /* 402730300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 402830300Sjoerg * using only them, but we don't rely on it. */ 402930300Sjoerg if (c < ' ' || c > '~') 403030300Sjoerg addlog("\\x%x", c); 403130300Sjoerg else 403230300Sjoerg addlog("%c", c); 403330300Sjoerg } 403430300Sjoerg} 403530300Sjoerg 403630300Sjoergstatic const char * 403730300Sjoergsppp_dotted_quad(u_long addr) 403830300Sjoerg{ 403930300Sjoerg static char s[16]; 404030300Sjoerg sprintf(s, "%d.%d.%d.%d", 404130300Sjoerg (addr >> 24) & 0xff, 404230300Sjoerg (addr >> 16) & 0xff, 404330300Sjoerg (addr >> 8) & 0xff, 404430300Sjoerg addr & 0xff); 404530300Sjoerg return s; 404630300Sjoerg} 404730300Sjoerg 404830300Sjoergstatic int 404930300Sjoergsppp_strnlen(u_char *p, int max) 405030300Sjoerg{ 405130300Sjoerg int len; 405230300Sjoerg 405330300Sjoerg for (len = 0; len < max && *p; ++p) 405430300Sjoerg ++len; 405530300Sjoerg return len; 405630300Sjoerg} 405730300Sjoerg 405830300Sjoerg/* a dummy, used to drop uninteresting events */ 405930300Sjoergstatic void 406030300Sjoergsppp_null(struct sppp *unused) 406130300Sjoerg{ 406230300Sjoerg /* do just nothing */ 406330300Sjoerg} 406425944Sjoerg/* 406525944Sjoerg * This file is large. Tell emacs to highlight it nevertheless. 406625944Sjoerg * 406725944Sjoerg * Local Variables: 406830300Sjoerg * hilit-auto-highlight-maxout: 120000 406925944Sjoerg * End: 407025944Sjoerg */ 4071