if_spppsubr.c revision 42065
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 * 2042065Sphk * $Id: if_spppsubr.c,v 1.49 1998/12/26 12:14:31 phk Exp $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2731742Seivind#include "opt_ipx.h" 2840008Sjoerg#endif 2931742Seivind 3040008Sjoerg#ifdef NetBSD1_3 3140008Sjoerg# if NetBSD1_3 > 6 3240008Sjoerg# include "opt_inet.h" 3340008Sjoerg# include "opt_iso.h" 3440008Sjoerg# endif 3540008Sjoerg#endif 3640008Sjoerg 374952Sbde#include <sys/systm.h> 384952Sbde#include <sys/kernel.h> 3924204Sbde#include <sys/sockio.h> 404910Swollman#include <sys/socket.h> 4125706Sjoerg#include <sys/syslog.h> 4229024Sbde#include <sys/malloc.h> 434910Swollman#include <sys/mbuf.h> 4440008Sjoerg 4540008Sjoerg#if defined (__OpenBSD__) 4640008Sjoerg#include <sys/md5k.h> 4740008Sjoerg#else 4830300Sjoerg#include <sys/md5.h> 4940008Sjoerg#endif 504910Swollman 514910Swollman#include <net/if.h> 524910Swollman#include <net/netisr.h> 534910Swollman#include <net/if_types.h> 544910Swollman 5542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 5640008Sjoerg#include <machine/random.h> 5740008Sjoerg#endif 5840008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 5940008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6040008Sjoerg#endif 6130300Sjoerg#include <machine/stdarg.h> 6230300Sjoerg 634910Swollman#ifdef INET 644910Swollman#include <netinet/in.h> 654910Swollman#include <netinet/in_systm.h> 664910Swollman#include <netinet/in_var.h> 674910Swollman#include <netinet/ip.h> 684910Swollman#include <netinet/tcp.h> 6940008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7040008Sjoerg# include <netinet/if_ether.h> 7140008Sjoerg# else 7240008Sjoerg# include <net/ethertypes.h> 7340008Sjoerg# endif 7432350Seivind#else 7540008Sjoerg# error Huh? sppp without INET? 764910Swollman#endif 774910Swollman 7811819Sjulian#ifdef IPX 7911819Sjulian#include <netipx/ipx.h> 8011819Sjulian#include <netipx/ipx_if.h> 8111819Sjulian#endif 8211819Sjulian 834910Swollman#ifdef NS 844910Swollman#include <netns/ns.h> 854910Swollman#include <netns/ns_if.h> 864910Swollman#endif 874910Swollman 884910Swollman#ifdef ISO 894910Swollman#include <netiso/argo_debug.h> 904910Swollman#include <netiso/iso.h> 914910Swollman#include <netiso/iso_var.h> 924910Swollman#include <netiso/iso_snpac.h> 934910Swollman#endif 944910Swollman 954910Swollman#include <net/if_sppp.h> 964910Swollman 9742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9842064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9942064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 10040008Sjoerg#else 10142064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10242064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10340008Sjoerg#endif 1044910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1054910Swollman 10625944Sjoerg/* 10725944Sjoerg * Interface flags that can be set in an ifconfig command. 10825944Sjoerg * 10925955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11025944Sjoerg * as being administrative openable, but won't be opened to begin 11125944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11225944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11325955Sjoerg * 11425955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11525955Sjoerg * arrive to be sent. 11630300Sjoerg * 11730300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11830300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 11930300Sjoerg * like 12030300Sjoerg * 12130300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12230300Sjoerg * 12330300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12430300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12525944Sjoerg */ 12625944Sjoerg 12725955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12825955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 12925944Sjoerg 13030300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13130300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13230300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13330300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13430300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13530300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 13630300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 13730300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 13830300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 13930300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1404910Swollman 14125944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 14225944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 14325944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 14425944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 14525944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 14625944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 14725944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 14825944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 14925944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15025944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15125944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1524910Swollman 15330300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 15430300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 15530300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 15630300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 15730300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 15830300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 15930300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16030300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1614910Swollman 16225944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 16325944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 16425944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1654910Swollman 16630300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 16730300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 16830300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1694910Swollman 17030300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17130300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 17230300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 17330300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 17430300Sjoerg 17530300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 17630300Sjoerg 17730300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 17830300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 17930300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18030300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18130300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 18230300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 18330300Sjoerg 18425944Sjoerg/* states are named and numbered according to RFC 1661 */ 18525944Sjoerg#define STATE_INITIAL 0 18625944Sjoerg#define STATE_STARTING 1 18725944Sjoerg#define STATE_CLOSED 2 18825944Sjoerg#define STATE_STOPPED 3 18925944Sjoerg#define STATE_CLOSING 4 19025944Sjoerg#define STATE_STOPPING 5 19125944Sjoerg#define STATE_REQ_SENT 6 19225944Sjoerg#define STATE_ACK_RCVD 7 19325944Sjoerg#define STATE_ACK_SENT 8 19425944Sjoerg#define STATE_OPENED 9 19525944Sjoerg 1964910Swollmanstruct ppp_header { 19711189Sjkh u_char address; 19811189Sjkh u_char control; 19911189Sjkh u_short protocol; 2004910Swollman}; 2014910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2024910Swollman 2034910Swollmanstruct lcp_header { 20411189Sjkh u_char type; 20511189Sjkh u_char ident; 20611189Sjkh u_short len; 2074910Swollman}; 2084910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2094910Swollman 2104910Swollmanstruct cisco_packet { 21111189Sjkh u_long type; 21211189Sjkh u_long par1; 21311189Sjkh u_long par2; 21411189Sjkh u_short rel; 21511189Sjkh u_short time0; 21611189Sjkh u_short time1; 2174910Swollman}; 2184910Swollman#define CISCO_PACKET_LEN 18 2194910Swollman 22025944Sjoerg/* 22125944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 22225944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 22325944Sjoerg * case you can't make sense out of these abbreviation; it will also 22425944Sjoerg * explain the semantics related to the various events and actions. 22525944Sjoerg */ 22625944Sjoergstruct cp { 22725944Sjoerg u_short proto; /* PPP control protocol number */ 22825944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 22925944Sjoerg u_char flags; 23025944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23125944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 23225944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 23325944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 23425944Sjoerg const char *name; /* name of this control protocol */ 23525944Sjoerg /* event handlers */ 23625944Sjoerg void (*Up)(struct sppp *sp); 23725944Sjoerg void (*Down)(struct sppp *sp); 23825944Sjoerg void (*Open)(struct sppp *sp); 23925944Sjoerg void (*Close)(struct sppp *sp); 24025944Sjoerg void (*TO)(void *sp); 24125944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 24225944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 24325944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 24425944Sjoerg /* actions */ 24525944Sjoerg void (*tlu)(struct sppp *sp); 24625944Sjoerg void (*tld)(struct sppp *sp); 24725944Sjoerg void (*tls)(struct sppp *sp); 24825944Sjoerg void (*tlf)(struct sppp *sp); 24925944Sjoerg void (*scr)(struct sppp *sp); 25025944Sjoerg}; 25125944Sjoerg 25212820Sphkstatic struct sppp *spppq; 25342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 25430300Sjoergstatic struct callout_handle keepalive_ch; 25540008Sjoerg#endif 2564910Swollman 25742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 25840008Sjoerg#define SPP_FMT "%s%d: " 25940008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26040008Sjoerg#else 26140008Sjoerg#define SPP_FMT "%s: " 26240008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 26340008Sjoerg#endif 26440008Sjoerg 2654910Swollman/* 2664910Swollman * The following disgusting hack gets around the problem that IP TOS 2674910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2684910Swollman * priority queue. To decide if traffic is interactive, we check that 2694910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27030300Sjoerg * 27130300Sjoerg * XXX is this really still necessary? - joerg - 2724910Swollman */ 27311189Sjkhstatic u_short interactive_ports[8] = { 2744910Swollman 0, 513, 0, 0, 2754910Swollman 0, 21, 0, 23, 2764910Swollman}; 2774910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2784910Swollman 27925944Sjoerg/* almost every function needs these */ 28025944Sjoerg#define STDDCL \ 28125944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 28225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 28311189Sjkh 28430300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 28525944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2864910Swollman 28725944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 28825944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 28925944Sjoerg 29025944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29125944Sjoerg struct mbuf *m); 29225944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 29325944Sjoerg u_char ident, u_short len, void *data); 29440008Sjoerg#ifdef notyet 29525944Sjoergstatic void sppp_cp_timeout(void *arg); 29640008Sjoerg#endif 29725944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 29825944Sjoerg int newstate); 29930300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30030300Sjoerg struct sppp *sp, u_char type, u_char id, 30130300Sjoerg ...); 30225944Sjoerg 30325944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 30425944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 30525944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 30625944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 30725944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 30825944Sjoerg 30930300Sjoergstatic void sppp_null(struct sppp *sp); 31030300Sjoerg 31125944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31225944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31325944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31425944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 31525944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 31625944Sjoergstatic void sppp_lcp_TO(void *sp); 31725944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31825944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31925944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32025944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32225944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32325944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32425944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 32530300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 32630300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 32725944Sjoerg 32825944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 32925944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33025944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33125944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33225944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33325944Sjoergstatic void sppp_ipcp_TO(void *sp); 33425944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33525944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33625944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33725944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 33925944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34025944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34125944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34225944Sjoerg 34330300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 34430300Sjoergstatic void sppp_pap_init(struct sppp *sp); 34530300Sjoergstatic void sppp_pap_open(struct sppp *sp); 34630300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34730300Sjoergstatic void sppp_pap_TO(void *sp); 34830300Sjoergstatic void sppp_pap_my_TO(void *sp); 34930300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 35030300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 35130300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 35230300Sjoerg 35330300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 35430300Sjoergstatic void sppp_chap_init(struct sppp *sp); 35530300Sjoergstatic void sppp_chap_open(struct sppp *sp); 35630300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35730300Sjoergstatic void sppp_chap_TO(void *sp); 35830300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35930300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 36030300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 36130300Sjoerg 36230300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 36325944Sjoergstatic const char *sppp_cp_type_name(u_char type); 36430300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 36530300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 36625944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36725944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 36825944Sjoergstatic const char *sppp_proto_name(u_short proto); 36930300Sjoergstatic const char *sppp_state_name(int state); 37038343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37130300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37230300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 37330300Sjoerg u_long *srcmask); 37425944Sjoergstatic void sppp_keepalive(void *dummy); 37530300Sjoergstatic void sppp_phase_network(struct sppp *sp); 37630300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 37730300Sjoergstatic void sppp_print_string(const char *p, u_short len); 37825944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 37925944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 38025944Sjoerg 38125944Sjoerg/* our control protocol descriptors */ 38233181Seivindstatic const struct cp lcp = { 38325944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 38425944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 38525944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 38625944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 38725944Sjoerg sppp_lcp_scr 38825944Sjoerg}; 38925944Sjoerg 39033181Seivindstatic const struct cp ipcp = { 39125944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 39225944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 39325944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 39425944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 39525944Sjoerg sppp_ipcp_scr 39625944Sjoerg}; 39725944Sjoerg 39833181Seivindstatic const struct cp pap = { 39930300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 40030300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 40130300Sjoerg sppp_pap_TO, 0, 0, 0, 40230300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 40330300Sjoerg sppp_pap_scr 40430300Sjoerg}; 40530300Sjoerg 40633181Seivindstatic const struct cp chap = { 40730300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 40830300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 40930300Sjoerg sppp_chap_TO, 0, 0, 0, 41030300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 41130300Sjoerg sppp_chap_scr 41230300Sjoerg}; 41330300Sjoerg 41433181Seivindstatic const struct cp *cps[IDX_COUNT] = { 41525944Sjoerg &lcp, /* IDX_LCP */ 41625944Sjoerg &ipcp, /* IDX_IPCP */ 41730300Sjoerg &pap, /* IDX_PAP */ 41830300Sjoerg &chap, /* IDX_CHAP */ 41925944Sjoerg}; 42025944Sjoerg 42125944Sjoerg 42225944Sjoerg/* 42325944Sjoerg * Exported functions, comprising our interface to the lower layer. 4244910Swollman */ 4254910Swollman 4264910Swollman/* 4274910Swollman * Process the received packet. 4284910Swollman */ 42925706Sjoergvoid 43025706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4314910Swollman{ 4324910Swollman struct ppp_header *h; 4334910Swollman struct ifqueue *inq = 0; 43411189Sjkh int s; 43525944Sjoerg struct sppp *sp = (struct sppp *)ifp; 43625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 4374910Swollman 4384910Swollman if (ifp->if_flags & IFF_UP) 4394910Swollman /* Count received bytes, add FCS and one flag */ 4404910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 4414910Swollman 4424910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 4434910Swollman /* Too small packet, drop it. */ 44425944Sjoerg if (debug) 44525706Sjoerg log(LOG_DEBUG, 44640008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 44740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 44825944Sjoerg drop: 44925944Sjoerg ++ifp->if_ierrors; 45025944Sjoerg ++ifp->if_iqdrops; 4514910Swollman m_freem (m); 4524910Swollman return; 4534910Swollman } 4544910Swollman 4554910Swollman /* Get PPP header. */ 4564910Swollman h = mtod (m, struct ppp_header*); 4574910Swollman m_adj (m, PPP_HEADER_LEN); 4584910Swollman 4594910Swollman switch (h->address) { 4604910Swollman case PPP_ALLSTATIONS: 4614910Swollman if (h->control != PPP_UI) 4624910Swollman goto invalid; 46311189Sjkh if (sp->pp_flags & PP_CISCO) { 46425944Sjoerg if (debug) 46525706Sjoerg log(LOG_DEBUG, 46640008Sjoerg SPP_FMT "PPP packet in Cisco mode " 46725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 46840008Sjoerg SPP_ARGS(ifp), 46925706Sjoerg h->address, h->control, ntohs(h->protocol)); 47011189Sjkh goto drop; 47111189Sjkh } 4724910Swollman switch (ntohs (h->protocol)) { 4734910Swollman default: 47425944Sjoerg if (sp->state[IDX_LCP] == STATE_OPENED) 47525944Sjoerg sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 47611189Sjkh ++sp->pp_seq, m->m_pkthdr.len + 2, 4774910Swollman &h->protocol); 47825944Sjoerg if (debug) 47925706Sjoerg log(LOG_DEBUG, 48040008Sjoerg SPP_FMT "invalid input protocol " 48125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 48240008Sjoerg SPP_ARGS(ifp), 48325706Sjoerg h->address, h->control, ntohs(h->protocol)); 4844910Swollman ++ifp->if_noproto; 4854910Swollman goto drop; 4864910Swollman case PPP_LCP: 48730300Sjoerg sppp_cp_input(&lcp, sp, m); 4884910Swollman m_freem (m); 4894910Swollman return; 49030300Sjoerg case PPP_PAP: 49130300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49230300Sjoerg sppp_pap_input(sp, m); 49330300Sjoerg m_freem (m); 49430300Sjoerg return; 49530300Sjoerg case PPP_CHAP: 49630300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49730300Sjoerg sppp_chap_input(sp, m); 49830300Sjoerg m_freem (m); 49930300Sjoerg return; 5004910Swollman#ifdef INET 5014910Swollman case PPP_IPCP: 50225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 50330300Sjoerg sppp_cp_input(&ipcp, sp, m); 5044910Swollman m_freem (m); 5054910Swollman return; 5064910Swollman case PPP_IP: 50725944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5084910Swollman schednetisr (NETISR_IP); 5094910Swollman inq = &ipintrq; 5104910Swollman } 5114910Swollman break; 5124910Swollman#endif 51312495Speter#ifdef IPX 51412495Speter case PPP_IPX: 51512495Speter /* IPX IPXCP not implemented yet */ 51625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 51712495Speter schednetisr (NETISR_IPX); 51812495Speter inq = &ipxintrq; 51912495Speter } 52012495Speter break; 52112495Speter#endif 5224910Swollman#ifdef NS 5234910Swollman case PPP_XNS: 5244910Swollman /* XNS IDPCP not implemented yet */ 52525944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5264910Swollman schednetisr (NETISR_NS); 5274910Swollman inq = &nsintrq; 5284910Swollman } 5294910Swollman break; 5304910Swollman#endif 5314910Swollman#ifdef ISO 5324910Swollman case PPP_ISO: 5334910Swollman /* OSI NLCP not implemented yet */ 53425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5354910Swollman schednetisr (NETISR_ISO); 5364910Swollman inq = &clnlintrq; 5374910Swollman } 5384910Swollman break; 5394910Swollman#endif 5404910Swollman } 5414910Swollman break; 5424910Swollman case CISCO_MULTICAST: 5434910Swollman case CISCO_UNICAST: 5444910Swollman /* Don't check the control field here (RFC 1547). */ 54511189Sjkh if (! (sp->pp_flags & PP_CISCO)) { 54625944Sjoerg if (debug) 54725706Sjoerg log(LOG_DEBUG, 54840008Sjoerg SPP_FMT "Cisco packet in PPP mode " 54925706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55040008Sjoerg SPP_ARGS(ifp), 55125706Sjoerg h->address, h->control, ntohs(h->protocol)); 55211189Sjkh goto drop; 55311189Sjkh } 5544910Swollman switch (ntohs (h->protocol)) { 5554910Swollman default: 5564910Swollman ++ifp->if_noproto; 5574910Swollman goto invalid; 5584910Swollman case CISCO_KEEPALIVE: 5594910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5604910Swollman m_freem (m); 5614910Swollman return; 5624910Swollman#ifdef INET 5634910Swollman case ETHERTYPE_IP: 5644910Swollman schednetisr (NETISR_IP); 5654910Swollman inq = &ipintrq; 5664910Swollman break; 5674910Swollman#endif 56812495Speter#ifdef IPX 56912495Speter case ETHERTYPE_IPX: 57012495Speter schednetisr (NETISR_IPX); 57112495Speter inq = &ipxintrq; 57212495Speter break; 57312495Speter#endif 5744910Swollman#ifdef NS 5754910Swollman case ETHERTYPE_NS: 5764910Swollman schednetisr (NETISR_NS); 5774910Swollman inq = &nsintrq; 5784910Swollman break; 5794910Swollman#endif 5804910Swollman } 5814910Swollman break; 58225944Sjoerg default: /* Invalid PPP packet. */ 58325944Sjoerg invalid: 58425944Sjoerg if (debug) 58525944Sjoerg log(LOG_DEBUG, 58640008Sjoerg SPP_FMT "invalid input packet " 58725944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 58840008Sjoerg SPP_ARGS(ifp), 58925944Sjoerg h->address, h->control, ntohs(h->protocol)); 59025944Sjoerg goto drop; 5914910Swollman } 5924910Swollman 5934910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 5944910Swollman goto drop; 5954910Swollman 5964910Swollman /* Check queue. */ 59725944Sjoerg s = splimp(); 5984910Swollman if (IF_QFULL (inq)) { 5994910Swollman /* Queue overflow. */ 60025944Sjoerg IF_DROP(inq); 60125944Sjoerg splx(s); 60225944Sjoerg if (debug) 60340008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 60440008Sjoerg SPP_ARGS(ifp)); 6054910Swollman goto drop; 6064910Swollman } 60725944Sjoerg IF_ENQUEUE(inq, m); 60825944Sjoerg splx(s); 6094910Swollman} 6104910Swollman 6114910Swollman/* 6124910Swollman * Enqueue transmit packet. 6134910Swollman */ 61412820Sphkstatic int 61525706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 61625706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6174910Swollman{ 6184910Swollman struct sppp *sp = (struct sppp*) ifp; 6194910Swollman struct ppp_header *h; 6204910Swollman struct ifqueue *ifq; 62125955Sjoerg int s, rv = 0; 6224910Swollman 62325944Sjoerg s = splimp(); 62425944Sjoerg 62525944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 62625944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 6274910Swollman m_freem (m); 6284910Swollman splx (s); 6294910Swollman return (ENETDOWN); 6304910Swollman } 6314910Swollman 63225944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 63325944Sjoerg /* 63425944Sjoerg * Interface is not yet running, but auto-dial. Need 63525944Sjoerg * to start LCP for it. 63625944Sjoerg */ 63725944Sjoerg ifp->if_flags |= IFF_RUNNING; 63825944Sjoerg splx(s); 63925944Sjoerg lcp.Open(sp); 64025944Sjoerg s = splimp(); 64125944Sjoerg } 64225944Sjoerg 6434910Swollman ifq = &ifp->if_snd; 6444910Swollman#ifdef INET 6454910Swollman /* 6464910Swollman * Put low delay, telnet, rlogin and ftp control packets 6474910Swollman * in front of the queue. 6484910Swollman */ 64912436Speter if (dst->sa_family == AF_INET) { 65040008Sjoerg /* XXX Check mbuf length here? */ 65112436Speter struct ip *ip = mtod (m, struct ip*); 65212436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6534910Swollman 65441686Sphk if (IF_QFULL (&sp->pp_fastq)) 65541686Sphk ; 65641686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 65712436Speter ifq = &sp->pp_fastq; 65841686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 65941686Sphk ; 66041686Sphk else if (ip->ip_p != IPPROTO_TCP) 66141686Sphk ; 66241686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 66341686Sphk ifq = &sp->pp_fastq; 66441686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 66541686Sphk ifq = &sp->pp_fastq; 6664910Swollman } 6674910Swollman#endif 6684910Swollman 6694910Swollman /* 6704910Swollman * Prepend general data packet PPP header. For now, IP only. 6714910Swollman */ 6724910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 6734910Swollman if (! m) { 6744910Swollman if (ifp->if_flags & IFF_DEBUG) 67540008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 67640008Sjoerg SPP_ARGS(ifp)); 67725944Sjoerg ++ifp->if_oerrors; 6784910Swollman splx (s); 6794910Swollman return (ENOBUFS); 6804910Swollman } 68140008Sjoerg /* 68240008Sjoerg * May want to check size of packet 68340008Sjoerg * (albeit due to the implementation it's always enough) 68440008Sjoerg */ 6854910Swollman h = mtod (m, struct ppp_header*); 6864910Swollman if (sp->pp_flags & PP_CISCO) { 68728088Skjc h->address = CISCO_UNICAST; /* unicast address */ 6884910Swollman h->control = 0; 6894910Swollman } else { 6904910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 6914910Swollman h->control = PPP_UI; /* Unnumbered Info */ 6924910Swollman } 6934910Swollman 6944910Swollman switch (dst->sa_family) { 6954910Swollman#ifdef INET 6964910Swollman case AF_INET: /* Internet Protocol */ 69711189Sjkh if (sp->pp_flags & PP_CISCO) 69811189Sjkh h->protocol = htons (ETHERTYPE_IP); 69911189Sjkh else { 70025955Sjoerg /* 70125955Sjoerg * Don't choke with an ENETDOWN early. It's 70225955Sjoerg * possible that we just started dialing out, 70325955Sjoerg * so don't drop the packet immediately. If 70425955Sjoerg * we notice that we run out of buffer space 70525955Sjoerg * below, we will however remember that we are 70625955Sjoerg * not ready to carry IP packets, and return 70725955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 70825955Sjoerg */ 70925955Sjoerg h->protocol = htons(PPP_IP); 71025955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 71125955Sjoerg rv = ENETDOWN; 71211189Sjkh } 7134910Swollman break; 7144910Swollman#endif 7154910Swollman#ifdef NS 7164910Swollman case AF_NS: /* Xerox NS Protocol */ 7174910Swollman h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 7184910Swollman ETHERTYPE_NS : PPP_XNS); 7194910Swollman break; 7204910Swollman#endif 72111819Sjulian#ifdef IPX 72212495Speter case AF_IPX: /* Novell IPX Protocol */ 72311819Sjulian h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 72412495Speter ETHERTYPE_IPX : PPP_IPX); 72511819Sjulian break; 72611819Sjulian#endif 7274910Swollman#ifdef ISO 7284910Swollman case AF_ISO: /* ISO OSI Protocol */ 7294910Swollman if (sp->pp_flags & PP_CISCO) 7304910Swollman goto nosupport; 7314910Swollman h->protocol = htons (PPP_ISO); 7324910Swollman break; 73312820Sphknosupport: 7344910Swollman#endif 7354910Swollman default: 7364910Swollman m_freem (m); 73725944Sjoerg ++ifp->if_oerrors; 7384910Swollman splx (s); 7394910Swollman return (EAFNOSUPPORT); 7404910Swollman } 7414910Swollman 7424910Swollman /* 7434910Swollman * Queue message on interface, and start output if interface 7444910Swollman * not yet active. 7454910Swollman */ 7464910Swollman if (IF_QFULL (ifq)) { 7474910Swollman IF_DROP (&ifp->if_snd); 7484910Swollman m_freem (m); 74925944Sjoerg ++ifp->if_oerrors; 7504910Swollman splx (s); 75125955Sjoerg return (rv? rv: ENOBUFS); 7524910Swollman } 7534910Swollman IF_ENQUEUE (ifq, m); 7544910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 7554910Swollman (*ifp->if_start) (ifp); 7564910Swollman 7574910Swollman /* 7584910Swollman * Count output packets and bytes. 7594910Swollman * The packet length includes header, FCS and 1 flag, 7604910Swollman * according to RFC 1333. 7614910Swollman */ 7624910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 7634910Swollman splx (s); 7644910Swollman return (0); 7654910Swollman} 7664910Swollman 76725706Sjoergvoid 76825706Sjoergsppp_attach(struct ifnet *ifp) 7694910Swollman{ 7704910Swollman struct sppp *sp = (struct sppp*) ifp; 7714910Swollman 7724910Swollman /* Initialize keepalive handler. */ 7734910Swollman if (! spppq) 77442064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 7754910Swollman 7764910Swollman /* Insert new entry into the keepalive list. */ 7774910Swollman sp->pp_next = spppq; 7784910Swollman spppq = sp; 7794910Swollman 78042064Sphk sp->pp_if.if_mtu = PP_MTU; 78142064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 7824910Swollman sp->pp_if.if_type = IFT_PPP; 7834910Swollman sp->pp_if.if_output = sppp_output; 78442064Sphk sp->pp_flags = PP_KEEPALIVE; 7854910Swollman sp->pp_fastq.ifq_maxlen = 32; 78626018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 7874910Swollman sp->pp_loopcnt = 0; 7884910Swollman sp->pp_alivecnt = 0; 78911189Sjkh sp->pp_seq = 0; 7904910Swollman sp->pp_rseq = 0; 79125944Sjoerg sp->pp_phase = PHASE_DEAD; 79225944Sjoerg sp->pp_up = lcp.Up; 79325944Sjoerg sp->pp_down = lcp.Down; 79425944Sjoerg 79525944Sjoerg sppp_lcp_init(sp); 79625944Sjoerg sppp_ipcp_init(sp); 79730300Sjoerg sppp_pap_init(sp); 79830300Sjoerg sppp_chap_init(sp); 7994910Swollman} 8004910Swollman 80130300Sjoergvoid 80225706Sjoergsppp_detach(struct ifnet *ifp) 8034910Swollman{ 8044910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 80525944Sjoerg int i; 8064910Swollman 8074910Swollman /* Remove the entry from the keepalive list. */ 8084910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 8094910Swollman if (p == sp) { 8104910Swollman *q = p->pp_next; 8114910Swollman break; 8124910Swollman } 8134910Swollman 8144910Swollman /* Stop keepalive handler. */ 8154910Swollman if (! spppq) 81640008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 81725944Sjoerg 81825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 81940008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 82040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 8214910Swollman} 8224910Swollman 8234910Swollman/* 8244910Swollman * Flush the interface output queue. 8254910Swollman */ 82625706Sjoergvoid 82725706Sjoergsppp_flush(struct ifnet *ifp) 8284910Swollman{ 8294910Swollman struct sppp *sp = (struct sppp*) ifp; 8304910Swollman 83125944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 83225944Sjoerg sppp_qflush (&sp->pp_fastq); 83326018Sjoerg sppp_qflush (&sp->pp_cpq); 8344910Swollman} 8354910Swollman 8364910Swollman/* 83711189Sjkh * Check if the output queue is empty. 83811189Sjkh */ 83912820Sphkint 84025706Sjoergsppp_isempty(struct ifnet *ifp) 84111189Sjkh{ 84211189Sjkh struct sppp *sp = (struct sppp*) ifp; 84325944Sjoerg int empty, s; 84411189Sjkh 84525944Sjoerg s = splimp(); 84626018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 84726018Sjoerg !sp->pp_if.if_snd.ifq_head; 84825944Sjoerg splx(s); 84911189Sjkh return (empty); 85011189Sjkh} 85111189Sjkh 85211189Sjkh/* 8534910Swollman * Get next packet to send. 8544910Swollman */ 85525706Sjoergstruct mbuf * 85625706Sjoergsppp_dequeue(struct ifnet *ifp) 8574910Swollman{ 8584910Swollman struct sppp *sp = (struct sppp*) ifp; 8594910Swollman struct mbuf *m; 86025944Sjoerg int s; 8614910Swollman 86225944Sjoerg s = splimp(); 86326018Sjoerg /* 86430300Sjoerg * Process only the control protocol queue until we have at 86530300Sjoerg * least one NCP open. 86626018Sjoerg * 86726018Sjoerg * Do always serve all three queues in Cisco mode. 86826018Sjoerg */ 86926018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 87026018Sjoerg if (m == NULL && 87130300Sjoerg (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { 87226018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 87326018Sjoerg if (m == NULL) 87426018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 87526018Sjoerg } 87626018Sjoerg splx(s); 87726018Sjoerg return m; 8784910Swollman} 8794910Swollman 8804910Swollman/* 88130300Sjoerg * Pick the next packet, do not remove it from the queue. 88230300Sjoerg */ 88330300Sjoergstruct mbuf * 88430300Sjoergsppp_pick(struct ifnet *ifp) 88530300Sjoerg{ 88630300Sjoerg struct sppp *sp = (struct sppp*)ifp; 88730300Sjoerg struct mbuf *m; 88830300Sjoerg int s; 88930300Sjoerg 89030300Sjoerg s= splimp (); 89130300Sjoerg 89230300Sjoerg m = sp->pp_cpq.ifq_head; 89330300Sjoerg if (m == NULL && 89430300Sjoerg (sp->pp_phase == PHASE_NETWORK || 89530300Sjoerg (sp->pp_flags & PP_CISCO) != 0)) 89630300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 89730300Sjoerg m = sp->pp_if.if_snd.ifq_head; 89830300Sjoerg splx (s); 89930300Sjoerg return (m); 90030300Sjoerg} 90130300Sjoerg 90230300Sjoerg/* 90325944Sjoerg * Process an ioctl request. Called on low priority level. 9044910Swollman */ 90525944Sjoergint 90638343Sbdesppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) 9074910Swollman{ 90825944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 90925944Sjoerg struct sppp *sp = (struct sppp*) ifp; 91030300Sjoerg int s, rv, going_up, going_down, newmode; 9114910Swollman 91225944Sjoerg s = splimp(); 91330300Sjoerg rv = 0; 91425944Sjoerg switch (cmd) { 91525944Sjoerg case SIOCAIFADDR: 91625944Sjoerg case SIOCSIFDSTADDR: 91725944Sjoerg break; 9184910Swollman 91925944Sjoerg case SIOCSIFADDR: 92025944Sjoerg if_up(ifp); 92125944Sjoerg /* fall through... */ 92211189Sjkh 92325944Sjoerg case SIOCSIFFLAGS: 92425944Sjoerg going_up = ifp->if_flags & IFF_UP && 92525944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 92625944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 92725944Sjoerg ifp->if_flags & IFF_RUNNING; 92825944Sjoerg newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); 92925944Sjoerg if (newmode == (IFF_AUTO | IFF_PASSIVE)) { 93025944Sjoerg /* sanity */ 93125944Sjoerg newmode = IFF_PASSIVE; 93225944Sjoerg ifp->if_flags &= ~IFF_AUTO; 9334910Swollman } 9344910Swollman 93525944Sjoerg if (going_up || going_down) 93625944Sjoerg lcp.Close(sp); 93725944Sjoerg if (going_up && newmode == 0) { 93825944Sjoerg /* neither auto-dial nor passive */ 93925944Sjoerg ifp->if_flags |= IFF_RUNNING; 94025944Sjoerg if (!(sp->pp_flags & PP_CISCO)) 94125944Sjoerg lcp.Open(sp); 94226018Sjoerg } else if (going_down) { 94326018Sjoerg sppp_flush(ifp); 94425944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 94526018Sjoerg } 9464910Swollman 9474910Swollman break; 94811189Sjkh 94925944Sjoerg#ifdef SIOCSIFMTU 95025944Sjoerg#ifndef ifr_mtu 95125944Sjoerg#define ifr_mtu ifr_metric 95225944Sjoerg#endif 95325944Sjoerg case SIOCSIFMTU: 95425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 95525944Sjoerg return (EINVAL); 95625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 9574910Swollman break; 95825944Sjoerg#endif 95925944Sjoerg#ifdef SLIOCSETMTU 96025944Sjoerg case SLIOCSETMTU: 96125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 96225944Sjoerg return (EINVAL); 96325944Sjoerg ifp->if_mtu = *(short*)data; 9644910Swollman break; 96525944Sjoerg#endif 96625944Sjoerg#ifdef SIOCGIFMTU 96725944Sjoerg case SIOCGIFMTU: 96825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 96911189Sjkh break; 97025944Sjoerg#endif 97125944Sjoerg#ifdef SLIOCGETMTU 97225944Sjoerg case SLIOCGETMTU: 97325944Sjoerg *(short*)data = ifp->if_mtu; 9744910Swollman break; 97525944Sjoerg#endif 97625944Sjoerg case SIOCADDMULTI: 97725944Sjoerg case SIOCDELMULTI: 9784910Swollman break; 97911189Sjkh 98030300Sjoerg case SIOCGIFGENERIC: 98130300Sjoerg case SIOCSIFGENERIC: 98230300Sjoerg rv = sppp_params(sp, cmd, data); 98330300Sjoerg break; 98430300Sjoerg 98525944Sjoerg default: 98630300Sjoerg rv = ENOTTY; 9874910Swollman } 98825944Sjoerg splx(s); 98930300Sjoerg return rv; 9904910Swollman} 9914910Swollman 99225944Sjoerg 99325944Sjoerg/* 99425944Sjoerg * Cisco framing implementation. 99525944Sjoerg */ 99625944Sjoerg 9974910Swollman/* 9984910Swollman * Handle incoming Cisco keepalive protocol packets. 9994910Swollman */ 100030300Sjoergstatic void 100125706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 10024910Swollman{ 100325944Sjoerg STDDCL; 10044910Swollman struct cisco_packet *h; 100530300Sjoerg u_long me, mymask; 10064910Swollman 100727929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 100825706Sjoerg if (debug) 100925706Sjoerg log(LOG_DEBUG, 101040008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 101140008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 10124910Swollman return; 10134910Swollman } 10144910Swollman h = mtod (m, struct cisco_packet*); 101525706Sjoerg if (debug) 101625706Sjoerg log(LOG_DEBUG, 101740008Sjoerg SPP_FMT "cisco input: %d bytes " 101825706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 101940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 102040008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 102140008Sjoerg (u_int)h->time0, (u_int)h->time1); 10224910Swollman switch (ntohl (h->type)) { 10234910Swollman default: 102425706Sjoerg if (debug) 102540008Sjoerg addlog(SPP_FMT "cisco unknown packet type: 0x%lx\n", 102640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 10274910Swollman break; 10284910Swollman case CISCO_ADDR_REPLY: 10294910Swollman /* Reply on address request, ignore */ 10304910Swollman break; 10314910Swollman case CISCO_KEEPALIVE_REQ: 10324910Swollman sp->pp_alivecnt = 0; 10334910Swollman sp->pp_rseq = ntohl (h->par1); 10344910Swollman if (sp->pp_seq == sp->pp_rseq) { 10354910Swollman /* Local and remote sequence numbers are equal. 10364910Swollman * Probably, the line is in loopback mode. */ 103711189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 103840008Sjoerg printf (SPP_FMT "loopback\n", 103940008Sjoerg SPP_ARGS(ifp)); 104011189Sjkh sp->pp_loopcnt = 0; 104111189Sjkh if (ifp->if_flags & IFF_UP) { 104211189Sjkh if_down (ifp); 104326018Sjoerg sppp_qflush (&sp->pp_cpq); 104411189Sjkh } 104511189Sjkh } 10464910Swollman ++sp->pp_loopcnt; 10474910Swollman 10484910Swollman /* Generate new local sequence number */ 104942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 105035064Sphk sp->pp_seq = random(); 105140008Sjoerg#else 105240008Sjoerg sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 105340008Sjoerg#endif 105411189Sjkh break; 105511189Sjkh } 105630300Sjoerg sp->pp_loopcnt = 0; 105711189Sjkh if (! (ifp->if_flags & IFF_UP) && 105811189Sjkh (ifp->if_flags & IFF_RUNNING)) { 105930300Sjoerg if_up(ifp); 106040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 106111189Sjkh } 10624910Swollman break; 10634910Swollman case CISCO_ADDR_REQ: 106430300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 106530300Sjoerg if (me != 0L) 106630300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 10674910Swollman break; 10684910Swollman } 10694910Swollman} 10704910Swollman 10714910Swollman/* 107225944Sjoerg * Send Cisco keepalive packet. 10734910Swollman */ 107412820Sphkstatic void 107525944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 107625944Sjoerg{ 107725944Sjoerg STDDCL; 107825944Sjoerg struct ppp_header *h; 107925944Sjoerg struct cisco_packet *ch; 108025944Sjoerg struct mbuf *m; 108142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 108235029Sphk struct timeval tv; 108340008Sjoerg#else 108440008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 108540008Sjoerg#endif 108625944Sjoerg 108742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 108836119Sphk getmicrouptime(&tv); 108940008Sjoerg#endif 109035029Sphk 109125944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 109225944Sjoerg if (! m) 109325944Sjoerg return; 109425944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 109525944Sjoerg m->m_pkthdr.rcvif = 0; 109625944Sjoerg 109725944Sjoerg h = mtod (m, struct ppp_header*); 109825944Sjoerg h->address = CISCO_MULTICAST; 109925944Sjoerg h->control = 0; 110025944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 110125944Sjoerg 110225944Sjoerg ch = (struct cisco_packet*) (h + 1); 110325944Sjoerg ch->type = htonl (type); 110425944Sjoerg ch->par1 = htonl (par1); 110525944Sjoerg ch->par2 = htonl (par2); 110625944Sjoerg ch->rel = -1; 110740008Sjoerg 110842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 110935029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 111035029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 111140008Sjoerg#else 111240008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 111340008Sjoerg ch->time1 = htons ((u_short) t); 111440008Sjoerg#endif 111525944Sjoerg 111625944Sjoerg if (debug) 111725944Sjoerg log(LOG_DEBUG, 111840008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 111940008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 112040008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 112125944Sjoerg 112226018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 112326018Sjoerg IF_DROP (&sp->pp_fastq); 112425944Sjoerg IF_DROP (&ifp->if_snd); 112525944Sjoerg m_freem (m); 112625944Sjoerg } else 112726018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 112825944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 112925944Sjoerg (*ifp->if_start) (ifp); 113025944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 113125944Sjoerg} 113225944Sjoerg 113325944Sjoerg/* 113425944Sjoerg * PPP protocol implementation. 113525944Sjoerg */ 113625944Sjoerg 113725944Sjoerg/* 113825944Sjoerg * Send PPP control protocol packet. 113925944Sjoerg */ 114025944Sjoergstatic void 114125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 114225706Sjoerg u_char ident, u_short len, void *data) 11434910Swollman{ 114425944Sjoerg STDDCL; 11454910Swollman struct ppp_header *h; 11464910Swollman struct lcp_header *lh; 11474910Swollman struct mbuf *m; 11484910Swollman 11494910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 11504910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 11514910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 11524910Swollman if (! m) 11534910Swollman return; 11544910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 11554910Swollman m->m_pkthdr.rcvif = 0; 11564910Swollman 11574910Swollman h = mtod (m, struct ppp_header*); 11584910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 11594910Swollman h->control = PPP_UI; /* Unnumbered Info */ 11604910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 11614910Swollman 11624910Swollman lh = (struct lcp_header*) (h + 1); 11634910Swollman lh->type = type; 11644910Swollman lh->ident = ident; 11654910Swollman lh->len = htons (LCP_HEADER_LEN + len); 11664910Swollman if (len) 11674910Swollman bcopy (data, lh+1, len); 11684910Swollman 116925706Sjoerg if (debug) { 117040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 117140008Sjoerg SPP_ARGS(ifp), 117225944Sjoerg sppp_proto_name(proto), 117325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 117425944Sjoerg ntohs (lh->len)); 11754910Swollman if (len) 117611189Sjkh sppp_print_bytes ((u_char*) (lh+1), len); 117725706Sjoerg addlog(">\n"); 11784910Swollman } 117926018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 118026018Sjoerg IF_DROP (&sp->pp_fastq); 11814910Swollman IF_DROP (&ifp->if_snd); 11824910Swollman m_freem (m); 118325944Sjoerg ++ifp->if_oerrors; 11844910Swollman } else 118526018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 11864910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 11874910Swollman (*ifp->if_start) (ifp); 11884910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 11894910Swollman} 11904910Swollman 11914910Swollman/* 119225944Sjoerg * Handle incoming PPP control protocol packets. 11934910Swollman */ 119412820Sphkstatic void 119525944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 11964910Swollman{ 119725944Sjoerg STDDCL; 119825944Sjoerg struct lcp_header *h; 119925944Sjoerg int len = m->m_pkthdr.len; 120025944Sjoerg int rv; 120125944Sjoerg u_char *p; 12024910Swollman 120325944Sjoerg if (len < 4) { 120425944Sjoerg if (debug) 120525944Sjoerg log(LOG_DEBUG, 120640008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 120740008Sjoerg SPP_ARGS(ifp), cp->name, len); 12084910Swollman return; 120925944Sjoerg } 121025944Sjoerg h = mtod (m, struct lcp_header*); 121125944Sjoerg if (debug) { 121225944Sjoerg log(LOG_DEBUG, 121340008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 121440008Sjoerg SPP_ARGS(ifp), cp->name, 121525944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 121625944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 121725944Sjoerg if (len > 4) 121825944Sjoerg sppp_print_bytes ((u_char*) (h+1), len-4); 121925944Sjoerg addlog(">\n"); 122025944Sjoerg } 122125944Sjoerg if (len > ntohs (h->len)) 122225944Sjoerg len = ntohs (h->len); 122330300Sjoerg p = (u_char *)(h + 1); 122425944Sjoerg switch (h->type) { 122525944Sjoerg case CONF_REQ: 122625944Sjoerg if (len < 4) { 122725944Sjoerg if (debug) 122840008Sjoerg addlog(SPP_FMT "%s invalid conf-req length %d\n", 122940008Sjoerg SPP_ARGS(ifp), cp->name, 123025944Sjoerg len); 123125944Sjoerg ++ifp->if_ierrors; 123225944Sjoerg break; 123325944Sjoerg } 123430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 123530300Sjoerg switch (sp->state[cp->protoidx]) { 123630300Sjoerg case STATE_CLOSING: 123730300Sjoerg case STATE_STOPPING: 123830300Sjoerg return; 123930300Sjoerg case STATE_CLOSED: 124030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 124130300Sjoerg 0, 0); 124230300Sjoerg return; 124330300Sjoerg } 124425944Sjoerg rv = (cp->RCR)(sp, h, len); 124525944Sjoerg switch (sp->state[cp->protoidx]) { 124625944Sjoerg case STATE_OPENED: 124725944Sjoerg (cp->tld)(sp); 124825944Sjoerg (cp->scr)(sp); 124925944Sjoerg /* fall through... */ 125025944Sjoerg case STATE_ACK_SENT: 125125944Sjoerg case STATE_REQ_SENT: 125225944Sjoerg sppp_cp_change_state(cp, sp, rv? 125325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 125425944Sjoerg break; 125525944Sjoerg case STATE_STOPPED: 125625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 125725944Sjoerg (cp->scr)(sp); 125825944Sjoerg sppp_cp_change_state(cp, sp, rv? 125925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 126025944Sjoerg break; 126125944Sjoerg case STATE_ACK_RCVD: 126225944Sjoerg if (rv) { 126325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 126425944Sjoerg if (debug) 126540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 126640008Sjoerg SPP_ARGS(ifp), 126726077Sjoerg cp->name); 126825944Sjoerg (cp->tlu)(sp); 126925944Sjoerg } else 127025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 127125944Sjoerg break; 127225944Sjoerg default: 127340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 127440008Sjoerg SPP_ARGS(ifp), cp->name, 127525944Sjoerg sppp_cp_type_name(h->type), 127625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 127725944Sjoerg ++ifp->if_ierrors; 127825944Sjoerg } 127925944Sjoerg break; 128025944Sjoerg case CONF_ACK: 128125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 128225944Sjoerg if (debug) 128340008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 128440008Sjoerg SPP_ARGS(ifp), cp->name, 128525944Sjoerg h->ident, sp->confid[cp->protoidx]); 128625944Sjoerg ++ifp->if_ierrors; 128725944Sjoerg break; 128825944Sjoerg } 128925944Sjoerg switch (sp->state[cp->protoidx]) { 129025944Sjoerg case STATE_CLOSED: 129125944Sjoerg case STATE_STOPPED: 129225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 129325944Sjoerg break; 129425944Sjoerg case STATE_CLOSING: 129525944Sjoerg case STATE_STOPPING: 129625944Sjoerg break; 129725944Sjoerg case STATE_REQ_SENT: 129825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 129925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 130025944Sjoerg break; 130125944Sjoerg case STATE_OPENED: 130225944Sjoerg (cp->tld)(sp); 130325944Sjoerg /* fall through */ 130425944Sjoerg case STATE_ACK_RCVD: 130525944Sjoerg (cp->scr)(sp); 130625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 130725944Sjoerg break; 130825944Sjoerg case STATE_ACK_SENT: 130925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 131025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 131125944Sjoerg if (debug) 131240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 131340008Sjoerg SPP_ARGS(ifp), cp->name); 131425944Sjoerg (cp->tlu)(sp); 131525944Sjoerg break; 131625944Sjoerg default: 131740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 131840008Sjoerg SPP_ARGS(ifp), cp->name, 131925944Sjoerg sppp_cp_type_name(h->type), 132025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 132125944Sjoerg ++ifp->if_ierrors; 132225944Sjoerg } 132325944Sjoerg break; 132425944Sjoerg case CONF_NAK: 132525944Sjoerg case CONF_REJ: 132625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 132725944Sjoerg if (debug) 132840008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 132940008Sjoerg SPP_ARGS(ifp), cp->name, 133025944Sjoerg h->ident, sp->confid[cp->protoidx]); 133125944Sjoerg ++ifp->if_ierrors; 133225944Sjoerg break; 133325944Sjoerg } 133425944Sjoerg if (h->type == CONF_NAK) 133525944Sjoerg (cp->RCN_nak)(sp, h, len); 133625944Sjoerg else /* CONF_REJ */ 133725944Sjoerg (cp->RCN_rej)(sp, h, len); 13384910Swollman 133925944Sjoerg switch (sp->state[cp->protoidx]) { 134025944Sjoerg case STATE_CLOSED: 134125944Sjoerg case STATE_STOPPED: 134225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 134325944Sjoerg break; 134425944Sjoerg case STATE_REQ_SENT: 134525944Sjoerg case STATE_ACK_SENT: 134625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 134725944Sjoerg (cp->scr)(sp); 134825944Sjoerg break; 134925944Sjoerg case STATE_OPENED: 135025944Sjoerg (cp->tld)(sp); 135125944Sjoerg /* fall through */ 135225944Sjoerg case STATE_ACK_RCVD: 135325944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_SENT); 135425944Sjoerg (cp->scr)(sp); 135525944Sjoerg break; 135625944Sjoerg case STATE_CLOSING: 135725944Sjoerg case STATE_STOPPING: 135825944Sjoerg break; 135925944Sjoerg default: 136040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 136140008Sjoerg SPP_ARGS(ifp), cp->name, 136225944Sjoerg sppp_cp_type_name(h->type), 136325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 136425944Sjoerg ++ifp->if_ierrors; 136525944Sjoerg } 136625944Sjoerg break; 13674910Swollman 136825944Sjoerg case TERM_REQ: 136925944Sjoerg switch (sp->state[cp->protoidx]) { 137025944Sjoerg case STATE_ACK_RCVD: 137125944Sjoerg case STATE_ACK_SENT: 137225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 137325944Sjoerg /* fall through */ 137425944Sjoerg case STATE_CLOSED: 137525944Sjoerg case STATE_STOPPED: 137625944Sjoerg case STATE_CLOSING: 137725944Sjoerg case STATE_STOPPING: 137825944Sjoerg case STATE_REQ_SENT: 137925944Sjoerg sta: 138025944Sjoerg /* Send Terminate-Ack packet. */ 138125944Sjoerg if (debug) 138240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 138340008Sjoerg SPP_ARGS(ifp), cp->name); 138425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 138525944Sjoerg break; 138625944Sjoerg case STATE_OPENED: 138725944Sjoerg (cp->tld)(sp); 138825944Sjoerg sp->rst_counter[cp->protoidx] = 0; 138925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 139025944Sjoerg goto sta; 139125944Sjoerg break; 139225944Sjoerg default: 139340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139440008Sjoerg SPP_ARGS(ifp), cp->name, 139525944Sjoerg sppp_cp_type_name(h->type), 139625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139725944Sjoerg ++ifp->if_ierrors; 139825944Sjoerg } 139925944Sjoerg break; 140025944Sjoerg case TERM_ACK: 140125944Sjoerg switch (sp->state[cp->protoidx]) { 140225944Sjoerg case STATE_CLOSED: 140325944Sjoerg case STATE_STOPPED: 140425944Sjoerg case STATE_REQ_SENT: 140525944Sjoerg case STATE_ACK_SENT: 140625944Sjoerg break; 140725944Sjoerg case STATE_CLOSING: 140841881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 140925944Sjoerg (cp->tlf)(sp); 141025944Sjoerg break; 141125944Sjoerg case STATE_STOPPING: 141241881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 141325944Sjoerg (cp->tlf)(sp); 141425944Sjoerg break; 141525944Sjoerg case STATE_ACK_RCVD: 141625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 141725944Sjoerg break; 141825944Sjoerg case STATE_OPENED: 141925944Sjoerg (cp->tld)(sp); 142025944Sjoerg (cp->scr)(sp); 142125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 142225944Sjoerg break; 142325944Sjoerg default: 142440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 142540008Sjoerg SPP_ARGS(ifp), cp->name, 142625944Sjoerg sppp_cp_type_name(h->type), 142725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 142825944Sjoerg ++ifp->if_ierrors; 142925944Sjoerg } 143025944Sjoerg break; 143125944Sjoerg case CODE_REJ: 143225944Sjoerg case PROTO_REJ: 143325944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 143430300Sjoerg log(LOG_INFO, 143540008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 143630300Sjoerg "danger will robinson\n", 143740008Sjoerg SPP_ARGS(ifp), cp->name, 143830300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 143925944Sjoerg switch (sp->state[cp->protoidx]) { 144025944Sjoerg case STATE_CLOSED: 144125944Sjoerg case STATE_STOPPED: 144225944Sjoerg case STATE_REQ_SENT: 144325944Sjoerg case STATE_ACK_SENT: 144425944Sjoerg case STATE_CLOSING: 144525944Sjoerg case STATE_STOPPING: 144625944Sjoerg case STATE_OPENED: 144725944Sjoerg break; 144825944Sjoerg case STATE_ACK_RCVD: 144925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 145025944Sjoerg break; 145125944Sjoerg default: 145240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 145340008Sjoerg SPP_ARGS(ifp), cp->name, 145425944Sjoerg sppp_cp_type_name(h->type), 145525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 145625944Sjoerg ++ifp->if_ierrors; 145725944Sjoerg } 145825944Sjoerg break; 145925944Sjoerg case DISC_REQ: 146025944Sjoerg if (cp->proto != PPP_LCP) 146125944Sjoerg goto illegal; 146225944Sjoerg /* Discard the packet. */ 146325944Sjoerg break; 146425944Sjoerg case ECHO_REQ: 146525944Sjoerg if (cp->proto != PPP_LCP) 146625944Sjoerg goto illegal; 146725944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 146825944Sjoerg if (debug) 146940008Sjoerg addlog(SPP_FMT "lcp echo req but lcp closed\n", 147040008Sjoerg SPP_ARGS(ifp)); 147125944Sjoerg ++ifp->if_ierrors; 147225944Sjoerg break; 147325944Sjoerg } 147425944Sjoerg if (len < 8) { 147525944Sjoerg if (debug) 147640008Sjoerg addlog(SPP_FMT "invalid lcp echo request " 147725944Sjoerg "packet length: %d bytes\n", 147840008Sjoerg SPP_ARGS(ifp), len); 147925944Sjoerg break; 148025944Sjoerg } 148125944Sjoerg if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 148225944Sjoerg /* Line loopback mode detected. */ 148340008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 148425944Sjoerg if_down (ifp); 148526018Sjoerg sppp_qflush (&sp->pp_cpq); 14864910Swollman 148725944Sjoerg /* Shut down the PPP link. */ 148825944Sjoerg /* XXX */ 148925944Sjoerg lcp.Down(sp); 149025944Sjoerg lcp.Up(sp); 149125944Sjoerg break; 149225944Sjoerg } 149325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 149425944Sjoerg if (debug) 149540008Sjoerg addlog(SPP_FMT "got lcp echo req, sending echo rep\n", 149640008Sjoerg SPP_ARGS(ifp)); 149725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 149825944Sjoerg break; 149925944Sjoerg case ECHO_REPLY: 150025944Sjoerg if (cp->proto != PPP_LCP) 150125944Sjoerg goto illegal; 150225944Sjoerg if (h->ident != sp->lcp.echoid) { 150325944Sjoerg ++ifp->if_ierrors; 150425944Sjoerg break; 150525944Sjoerg } 150625944Sjoerg if (len < 8) { 150725944Sjoerg if (debug) 150840008Sjoerg addlog(SPP_FMT "lcp invalid echo reply " 150925944Sjoerg "packet length: %d bytes\n", 151040008Sjoerg SPP_ARGS(ifp), len); 151125944Sjoerg break; 151225944Sjoerg } 151325944Sjoerg if (debug) 151440008Sjoerg addlog(SPP_FMT "lcp got echo rep\n", 151540008Sjoerg SPP_ARGS(ifp)); 151625944Sjoerg if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 151725944Sjoerg sp->pp_alivecnt = 0; 151825944Sjoerg break; 151925944Sjoerg default: 152025944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 152125944Sjoerg illegal: 152225944Sjoerg if (debug) 152340008Sjoerg addlog(SPP_FMT "%s send code-rej for 0x%x\n", 152440008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 152525944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 152625944Sjoerg m->m_pkthdr.len, h); 152725944Sjoerg ++ifp->if_ierrors; 152825944Sjoerg } 15294910Swollman} 15304910Swollman 153125944Sjoerg 15324910Swollman/* 153325944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 153425944Sjoerg * Basically, the state transition handling in the automaton. 15354910Swollman */ 153625944Sjoergstatic void 153725944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 15384910Swollman{ 153925944Sjoerg STDDCL; 15404910Swollman 154125944Sjoerg if (debug) 154240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 154340008Sjoerg SPP_ARGS(ifp), cp->name, 154425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 154525944Sjoerg 154625944Sjoerg switch (sp->state[cp->protoidx]) { 154725944Sjoerg case STATE_INITIAL: 154825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 154925944Sjoerg break; 155025944Sjoerg case STATE_STARTING: 155125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 155225944Sjoerg (cp->scr)(sp); 155325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 155425944Sjoerg break; 15554910Swollman default: 155640008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 155740008Sjoerg SPP_ARGS(ifp), cp->name, 155825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155925944Sjoerg } 156025944Sjoerg} 15614910Swollman 156225944Sjoergstatic void 156325944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 156425944Sjoerg{ 156525944Sjoerg STDDCL; 156625944Sjoerg 156725944Sjoerg if (debug) 156840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 156940008Sjoerg SPP_ARGS(ifp), cp->name, 157025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 157125944Sjoerg 157225944Sjoerg switch (sp->state[cp->protoidx]) { 157325944Sjoerg case STATE_CLOSED: 157425944Sjoerg case STATE_CLOSING: 157525944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 15764910Swollman break; 157725944Sjoerg case STATE_STOPPED: 157841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 157925944Sjoerg (cp->tls)(sp); 158041881Sphk break; 158125944Sjoerg case STATE_STOPPING: 158225944Sjoerg case STATE_REQ_SENT: 158325944Sjoerg case STATE_ACK_RCVD: 158425944Sjoerg case STATE_ACK_SENT: 158525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 158625944Sjoerg break; 158725944Sjoerg case STATE_OPENED: 158825944Sjoerg (cp->tld)(sp); 158925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 159025944Sjoerg break; 159125944Sjoerg default: 159240008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 159340008Sjoerg SPP_ARGS(ifp), cp->name, 159425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 159525944Sjoerg } 159625944Sjoerg} 15974910Swollman 159811189Sjkh 159925944Sjoergstatic void 160025944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 160125944Sjoerg{ 160225944Sjoerg STDDCL; 160325944Sjoerg 160425944Sjoerg if (debug) 160540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 160640008Sjoerg SPP_ARGS(ifp), cp->name, 160725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160825944Sjoerg 160925944Sjoerg switch (sp->state[cp->protoidx]) { 161025944Sjoerg case STATE_INITIAL: 161141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 161225944Sjoerg (cp->tls)(sp); 16134910Swollman break; 161425944Sjoerg case STATE_STARTING: 161525944Sjoerg break; 161625944Sjoerg case STATE_CLOSED: 161725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 161825944Sjoerg (cp->scr)(sp); 161925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 162025944Sjoerg break; 162125944Sjoerg case STATE_STOPPED: 162225944Sjoerg case STATE_STOPPING: 162325944Sjoerg case STATE_REQ_SENT: 162425944Sjoerg case STATE_ACK_RCVD: 162525944Sjoerg case STATE_ACK_SENT: 162625944Sjoerg case STATE_OPENED: 162725944Sjoerg break; 162825944Sjoerg case STATE_CLOSING: 162925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 163025944Sjoerg break; 163125944Sjoerg } 163225944Sjoerg} 16334910Swollman 163425944Sjoerg 163525944Sjoergstatic void 163625944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 163725944Sjoerg{ 163825944Sjoerg STDDCL; 163925944Sjoerg 164025944Sjoerg if (debug) 164140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 164240008Sjoerg SPP_ARGS(ifp), cp->name, 164325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164425944Sjoerg 164525944Sjoerg switch (sp->state[cp->protoidx]) { 164625944Sjoerg case STATE_INITIAL: 164725944Sjoerg case STATE_CLOSED: 164825944Sjoerg case STATE_CLOSING: 16494910Swollman break; 165025944Sjoerg case STATE_STARTING: 165141881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 165225944Sjoerg (cp->tlf)(sp); 16534910Swollman break; 165425944Sjoerg case STATE_STOPPED: 165525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 16564910Swollman break; 165725944Sjoerg case STATE_STOPPING: 165825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16594910Swollman break; 166025944Sjoerg case STATE_OPENED: 166125944Sjoerg (cp->tld)(sp); 166225944Sjoerg /* fall through */ 166325944Sjoerg case STATE_REQ_SENT: 166425944Sjoerg case STATE_ACK_RCVD: 166525944Sjoerg case STATE_ACK_SENT: 166625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 166725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 166825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16694910Swollman break; 16704910Swollman } 16714910Swollman} 16724910Swollman 167325944Sjoergstatic void 167425944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 167525944Sjoerg{ 167625944Sjoerg STDDCL; 167725944Sjoerg int s; 167825944Sjoerg 167925944Sjoerg s = splimp(); 168025944Sjoerg if (debug) 168140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 168240008Sjoerg SPP_ARGS(ifp), cp->name, 168325944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 168425944Sjoerg sp->rst_counter[cp->protoidx]); 168525944Sjoerg 168625944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 168725944Sjoerg /* TO- event */ 168825944Sjoerg switch (sp->state[cp->protoidx]) { 168925944Sjoerg case STATE_CLOSING: 169041881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 169125944Sjoerg (cp->tlf)(sp); 169225944Sjoerg break; 169325944Sjoerg case STATE_STOPPING: 169441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 169525944Sjoerg (cp->tlf)(sp); 169625944Sjoerg break; 169725944Sjoerg case STATE_REQ_SENT: 169825944Sjoerg case STATE_ACK_RCVD: 169925944Sjoerg case STATE_ACK_SENT: 170041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 170125944Sjoerg (cp->tlf)(sp); 170225944Sjoerg break; 170325944Sjoerg } 170425944Sjoerg else 170525944Sjoerg /* TO+ event */ 170625944Sjoerg switch (sp->state[cp->protoidx]) { 170725944Sjoerg case STATE_CLOSING: 170825944Sjoerg case STATE_STOPPING: 170925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 171025944Sjoerg 0, 0); 171142064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 171242064Sphk sp->ch[cp->protoidx]); 171325944Sjoerg break; 171425944Sjoerg case STATE_REQ_SENT: 171525944Sjoerg case STATE_ACK_RCVD: 171625944Sjoerg (cp->scr)(sp); 171725944Sjoerg /* sppp_cp_change_state() will restart the timer */ 171825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171925944Sjoerg break; 172025944Sjoerg case STATE_ACK_SENT: 172125944Sjoerg (cp->scr)(sp); 172242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 172342064Sphk sp->ch[cp->protoidx]); 172425944Sjoerg break; 172525944Sjoerg } 172625944Sjoerg 172725944Sjoerg splx(s); 172825944Sjoerg} 172925944Sjoerg 173011189Sjkh/* 173125944Sjoerg * Change the state of a control protocol in the state automaton. 173225944Sjoerg * Takes care of starting/stopping the restart timer. 173311189Sjkh */ 173425944Sjoergvoid 173525944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 173625944Sjoerg{ 173725944Sjoerg sp->state[cp->protoidx] = newstate; 173825944Sjoerg 173940008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 174025944Sjoerg switch (newstate) { 174125944Sjoerg case STATE_INITIAL: 174225944Sjoerg case STATE_STARTING: 174325944Sjoerg case STATE_CLOSED: 174425944Sjoerg case STATE_STOPPED: 174525944Sjoerg case STATE_OPENED: 174625944Sjoerg break; 174725944Sjoerg case STATE_CLOSING: 174825944Sjoerg case STATE_STOPPING: 174925944Sjoerg case STATE_REQ_SENT: 175025944Sjoerg case STATE_ACK_RCVD: 175125944Sjoerg case STATE_ACK_SENT: 175242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 175342064Sphk sp->ch[cp->protoidx]); 175425944Sjoerg break; 175525944Sjoerg } 175625944Sjoerg} 175725944Sjoerg/* 175825944Sjoerg *--------------------------------------------------------------------------* 175925944Sjoerg * * 176025944Sjoerg * The LCP implementation. * 176125944Sjoerg * * 176225944Sjoerg *--------------------------------------------------------------------------* 176325944Sjoerg */ 176425944Sjoergstatic void 176525944Sjoergsppp_lcp_init(struct sppp *sp) 176625944Sjoerg{ 176725944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 176825944Sjoerg sp->lcp.magic = 0; 176925944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 177025944Sjoerg sp->fail_counter[IDX_LCP] = 0; 177125944Sjoerg sp->lcp.protos = 0; 177225944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 177330300Sjoerg 177425944Sjoerg /* 177525944Sjoerg * Initialize counters and timeout values. Note that we don't 177625944Sjoerg * use the 3 seconds suggested in RFC 1661 since we are likely 177725944Sjoerg * running on a fast link. XXX We should probably implement 177825944Sjoerg * the exponential backoff option. Note that these values are 177925944Sjoerg * relevant for all control protocols, not just LCP only. 178025944Sjoerg */ 178125944Sjoerg sp->lcp.timeout = 1 * hz; 178225944Sjoerg sp->lcp.max_terminate = 2; 178325944Sjoerg sp->lcp.max_configure = 10; 178425944Sjoerg sp->lcp.max_failure = 10; 178542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 178630300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 178740008Sjoerg#endif 178825944Sjoerg} 178925944Sjoerg 179025944Sjoergstatic void 179125944Sjoergsppp_lcp_up(struct sppp *sp) 179225944Sjoerg{ 179325944Sjoerg STDDCL; 179425944Sjoerg 179525944Sjoerg /* 179630300Sjoerg * If this interface is passive or dial-on-demand, and we are 179730300Sjoerg * still in Initial state, it means we've got an incoming 179830300Sjoerg * call. Activate the interface. 179925944Sjoerg */ 180025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 180125944Sjoerg if (debug) 180225944Sjoerg log(LOG_DEBUG, 180340008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 180425944Sjoerg ifp->if_flags |= IFF_RUNNING; 180530300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 180630300Sjoerg if (debug) 180730300Sjoerg addlog("(incoming call)\n"); 180830300Sjoerg sp->pp_flags |= PP_CALLIN; 180930300Sjoerg lcp.Open(sp); 181030300Sjoerg } else if (debug) 181130300Sjoerg addlog("\n"); 181225944Sjoerg } 181325944Sjoerg 181425944Sjoerg sppp_up_event(&lcp, sp); 181525944Sjoerg} 181625944Sjoerg 181725944Sjoergstatic void 181825944Sjoergsppp_lcp_down(struct sppp *sp) 181925944Sjoerg{ 182025944Sjoerg STDDCL; 182125944Sjoerg 182225944Sjoerg sppp_down_event(&lcp, sp); 182325944Sjoerg 182425944Sjoerg /* 182525944Sjoerg * If this is neither a dial-on-demand nor a passive 182625944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 182725944Sjoerg * administrator can force a redial by another ``ifconfig 182825944Sjoerg * up''. XXX For leased line operation, should we immediately 182925944Sjoerg * try to reopen the connection here? 183025944Sjoerg */ 183125944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 183225944Sjoerg log(LOG_INFO, 183340008Sjoerg SPP_FMT "Down event (carrier loss), taking interface down.\n", 183440008Sjoerg SPP_ARGS(ifp)); 183525944Sjoerg if_down(ifp); 183625944Sjoerg } else { 183725944Sjoerg if (debug) 183825944Sjoerg log(LOG_DEBUG, 183940008Sjoerg SPP_FMT "Down event (carrier loss)\n", 184040008Sjoerg SPP_ARGS(ifp)); 184125944Sjoerg } 184230300Sjoerg sp->pp_flags &= ~PP_CALLIN; 184330300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 184430300Sjoerg lcp.Close(sp); 184525944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 184625944Sjoerg} 184725944Sjoerg 184825944Sjoergstatic void 184925944Sjoergsppp_lcp_open(struct sppp *sp) 185025944Sjoerg{ 185130300Sjoerg /* 185230300Sjoerg * If we are authenticator, negotiate LCP_AUTH 185330300Sjoerg */ 185430300Sjoerg if (sp->hisauth.proto != 0) 185530300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 185630300Sjoerg else 185730300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 185830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 185925944Sjoerg sppp_open_event(&lcp, sp); 186025944Sjoerg} 186125944Sjoerg 186225944Sjoergstatic void 186325944Sjoergsppp_lcp_close(struct sppp *sp) 186425944Sjoerg{ 186525944Sjoerg sppp_close_event(&lcp, sp); 186625944Sjoerg} 186725944Sjoerg 186825944Sjoergstatic void 186925944Sjoergsppp_lcp_TO(void *cookie) 187025944Sjoerg{ 187125944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 187225944Sjoerg} 187325944Sjoerg 187425944Sjoerg/* 187525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 187625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 187725944Sjoerg * caused action scn. (The return value is used to make the state 187825944Sjoerg * transition decision in the state automaton.) 187925944Sjoerg */ 188012820Sphkstatic int 188125944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 18824910Swollman{ 188325944Sjoerg STDDCL; 188411189Sjkh u_char *buf, *r, *p; 188525944Sjoerg int origlen, rlen; 188625944Sjoerg u_long nmagic; 188730300Sjoerg u_short authproto; 18884910Swollman 188911189Sjkh len -= 4; 189025944Sjoerg origlen = len; 189111189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 189211189Sjkh if (! buf) 189311189Sjkh return (0); 18944910Swollman 189525706Sjoerg if (debug) 189640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 189740008Sjoerg SPP_ARGS(ifp)); 189825706Sjoerg 189925944Sjoerg /* pass 1: check for things that need to be rejected */ 190011189Sjkh p = (void*) (h+1); 190111189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 190225944Sjoerg if (debug) 190325944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 190411189Sjkh switch (*p) { 190511189Sjkh case LCP_OPT_MAGIC: 190625944Sjoerg /* Magic number. */ 190725944Sjoerg /* fall through, both are same length */ 190825944Sjoerg case LCP_OPT_ASYNC_MAP: 190925944Sjoerg /* Async control character map. */ 191025944Sjoerg if (len >= 6 || p[1] == 6) 191125944Sjoerg continue; 191225944Sjoerg if (debug) 191325944Sjoerg addlog("[invalid] "); 191425944Sjoerg break; 191525944Sjoerg case LCP_OPT_MRU: 191625944Sjoerg /* Maximum receive unit. */ 191725944Sjoerg if (len >= 4 && p[1] == 4) 191825944Sjoerg continue; 191925944Sjoerg if (debug) 192025944Sjoerg addlog("[invalid] "); 192125944Sjoerg break; 192230300Sjoerg case LCP_OPT_AUTH_PROTO: 192330300Sjoerg if (len < 4) { 192430300Sjoerg if (debug) 192530300Sjoerg addlog("[invalid] "); 192630300Sjoerg break; 192730300Sjoerg } 192830300Sjoerg authproto = (p[2] << 8) + p[3]; 192930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 193030300Sjoerg if (debug) 193130300Sjoerg addlog("[invalid chap len] "); 193230300Sjoerg break; 193330300Sjoerg } 193430300Sjoerg if (sp->myauth.proto == 0) { 193530300Sjoerg /* we are not configured to do auth */ 193630300Sjoerg if (debug) 193730300Sjoerg addlog("[not configured] "); 193830300Sjoerg break; 193930300Sjoerg } 194030300Sjoerg /* 194130300Sjoerg * Remote want us to authenticate, remember this, 194230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 194330300Sjoerg * up. 194430300Sjoerg */ 194530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 194630300Sjoerg continue; 194725944Sjoerg default: 194825944Sjoerg /* Others not supported. */ 194925944Sjoerg if (debug) 195025944Sjoerg addlog("[rej] "); 195125944Sjoerg break; 195225944Sjoerg } 195325944Sjoerg /* Add the option to rejected list. */ 195425944Sjoerg bcopy (p, r, p[1]); 195525944Sjoerg r += p[1]; 195625944Sjoerg rlen += p[1]; 195725944Sjoerg } 195825944Sjoerg if (rlen) { 195925944Sjoerg if (debug) 196025944Sjoerg addlog(" send conf-rej\n"); 196125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 196225944Sjoerg return 0; 196325944Sjoerg } else if (debug) 196425944Sjoerg addlog("\n"); 196525944Sjoerg 196625944Sjoerg /* 196725944Sjoerg * pass 2: check for option values that are unacceptable and 196825944Sjoerg * thus require to be nak'ed. 196925944Sjoerg */ 197025944Sjoerg if (debug) 197140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 197240008Sjoerg SPP_ARGS(ifp)); 197325944Sjoerg 197425944Sjoerg p = (void*) (h+1); 197525944Sjoerg len = origlen; 197625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 197725944Sjoerg if (debug) 197825944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 197925944Sjoerg switch (*p) { 198025944Sjoerg case LCP_OPT_MAGIC: 198111189Sjkh /* Magic number -- extract. */ 198225944Sjoerg nmagic = (u_long)p[2] << 24 | 198325944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 198425944Sjoerg if (nmagic != sp->lcp.magic) { 198525706Sjoerg if (debug) 198638372Sbde addlog("0x%lx ", nmagic); 198711189Sjkh continue; 198811189Sjkh } 198925944Sjoerg /* 199025944Sjoerg * Local and remote magics equal -- loopback? 199125944Sjoerg */ 199225944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 199340008Sjoerg printf (SPP_FMT "loopback\n", 199440008Sjoerg SPP_ARGS(ifp)); 199525944Sjoerg sp->pp_loopcnt = 0; 199625944Sjoerg if (ifp->if_flags & IFF_UP) { 199725944Sjoerg if_down(ifp); 199826018Sjoerg sppp_qflush(&sp->pp_cpq); 199925944Sjoerg /* XXX ? */ 200025944Sjoerg lcp.Down(sp); 200125944Sjoerg lcp.Up(sp); 200225944Sjoerg } 200325944Sjoerg } else if (debug) 200425944Sjoerg addlog("[glitch] "); 200525944Sjoerg ++sp->pp_loopcnt; 200625944Sjoerg /* 200725944Sjoerg * We negate our magic here, and NAK it. If 200825944Sjoerg * we see it later in an NAK packet, we 200925944Sjoerg * suggest a new one. 201025944Sjoerg */ 201125944Sjoerg nmagic = ~sp->lcp.magic; 201225944Sjoerg /* Gonna NAK it. */ 201325944Sjoerg p[2] = nmagic >> 24; 201425944Sjoerg p[3] = nmagic >> 16; 201525944Sjoerg p[4] = nmagic >> 8; 201625944Sjoerg p[5] = nmagic; 201711189Sjkh break; 201825944Sjoerg 201911189Sjkh case LCP_OPT_ASYNC_MAP: 202011189Sjkh /* Async control character map -- check to be zero. */ 202125944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 202225706Sjoerg if (debug) 202325944Sjoerg addlog("[empty] "); 202411189Sjkh continue; 202525706Sjoerg } 202625706Sjoerg if (debug) 202725944Sjoerg addlog("[non-empty] "); 202825944Sjoerg /* suggest a zero one */ 202925944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 203011189Sjkh break; 203125944Sjoerg 203211189Sjkh case LCP_OPT_MRU: 203325944Sjoerg /* 203425944Sjoerg * Maximum receive unit. Always agreeable, 203525944Sjoerg * but ignored by now. 203625944Sjoerg */ 203725944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 203825706Sjoerg if (debug) 203938372Sbde addlog("%lu ", sp->lcp.their_mru); 204011189Sjkh continue; 204130300Sjoerg 204230300Sjoerg case LCP_OPT_AUTH_PROTO: 204330300Sjoerg authproto = (p[2] << 8) + p[3]; 204430300Sjoerg if (sp->myauth.proto != authproto) { 204530300Sjoerg /* not agreed, nak */ 204630300Sjoerg if (debug) 204730300Sjoerg addlog("[mine %s != his %s] ", 204830300Sjoerg sppp_proto_name(sp->hisauth.proto), 204930300Sjoerg sppp_proto_name(authproto)); 205030300Sjoerg p[2] = sp->myauth.proto >> 8; 205130300Sjoerg p[3] = sp->myauth.proto; 205230300Sjoerg break; 205330300Sjoerg } 205430300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 205530300Sjoerg if (debug) 205630300Sjoerg addlog("[chap not MD5] "); 205739981Sjoerg p[4] = CHAP_MD5; 205830300Sjoerg break; 205930300Sjoerg } 206030300Sjoerg continue; 206111189Sjkh } 206225944Sjoerg /* Add the option to nak'ed list. */ 206325706Sjoerg bcopy (p, r, p[1]); 206425706Sjoerg r += p[1]; 206511189Sjkh rlen += p[1]; 206612436Speter } 206725706Sjoerg if (rlen) { 206828036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 206928036Sjoerg if (debug) 207028036Sjoerg addlog(" max_failure (%d) exceeded, " 207128036Sjoerg "send conf-rej\n", 207228036Sjoerg sp->lcp.max_failure); 207328036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 207428036Sjoerg } else { 207528036Sjoerg if (debug) 207628036Sjoerg addlog(" send conf-nak\n"); 207728036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 207828036Sjoerg } 207925944Sjoerg return 0; 208025944Sjoerg } else { 208125944Sjoerg if (debug) 208225944Sjoerg addlog(" send conf-ack\n"); 208328036Sjoerg sp->fail_counter[IDX_LCP] = 0; 208425944Sjoerg sp->pp_loopcnt = 0; 208525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 208625944Sjoerg h->ident, origlen, h+1); 208725944Sjoerg } 208825944Sjoerg 208911189Sjkh free (buf, M_TEMP); 209011189Sjkh return (rlen == 0); 20914910Swollman} 20924910Swollman 209325944Sjoerg/* 209425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 209525944Sjoerg * negotiation. 209625944Sjoerg */ 209712820Sphkstatic void 209825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 20994910Swollman{ 210025944Sjoerg STDDCL; 210125944Sjoerg u_char *buf, *p; 21024910Swollman 210325944Sjoerg len -= 4; 210425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 210525944Sjoerg if (!buf) 21064910Swollman return; 210725944Sjoerg 210825944Sjoerg if (debug) 210940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 211040008Sjoerg SPP_ARGS(ifp)); 211125944Sjoerg 211225944Sjoerg p = (void*) (h+1); 211325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 211425944Sjoerg if (debug) 211525944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 211625944Sjoerg switch (*p) { 211725944Sjoerg case LCP_OPT_MAGIC: 211825944Sjoerg /* Magic number -- can't use it, use 0 */ 211925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 212025944Sjoerg sp->lcp.magic = 0; 212125944Sjoerg break; 212225944Sjoerg case LCP_OPT_MRU: 212325944Sjoerg /* 212425944Sjoerg * Should not be rejected anyway, since we only 212525944Sjoerg * negotiate a MRU if explicitly requested by 212625944Sjoerg * peer. 212725944Sjoerg */ 212825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 212925944Sjoerg break; 213030300Sjoerg case LCP_OPT_AUTH_PROTO: 213130300Sjoerg /* 213230300Sjoerg * Peer doesn't want to authenticate himself, 213330300Sjoerg * deny unless this is a dialout call, and 213430300Sjoerg * AUTHFLAG_NOCALLOUT is set. 213530300Sjoerg */ 213630300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 213730300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 213830300Sjoerg if (debug) 213930300Sjoerg addlog("[don't insist on auth " 214030300Sjoerg "for callout]"); 214130300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 214230300Sjoerg break; 214330300Sjoerg } 214430300Sjoerg if (debug) 214530300Sjoerg addlog("[access denied]\n"); 214630300Sjoerg lcp.Close(sp); 214730300Sjoerg break; 214825944Sjoerg } 21494910Swollman } 215025944Sjoerg if (debug) 215125944Sjoerg addlog("\n"); 215225944Sjoerg free (buf, M_TEMP); 215325944Sjoerg return; 215425944Sjoerg} 215525944Sjoerg 215625944Sjoerg/* 215725944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 215825944Sjoerg * negotiation. 215925944Sjoerg */ 216025944Sjoergstatic void 216125944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 216225944Sjoerg{ 216325944Sjoerg STDDCL; 216425944Sjoerg u_char *buf, *p; 216525944Sjoerg u_long magic; 216625944Sjoerg 216725944Sjoerg len -= 4; 216825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 216925944Sjoerg if (!buf) 217025944Sjoerg return; 217125944Sjoerg 217225944Sjoerg if (debug) 217340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 217440008Sjoerg SPP_ARGS(ifp)); 217525944Sjoerg 217625944Sjoerg p = (void*) (h+1); 217725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 217825706Sjoerg if (debug) 217925944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 218025944Sjoerg switch (*p) { 218125944Sjoerg case LCP_OPT_MAGIC: 218225944Sjoerg /* Magic number -- renegotiate */ 218325944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 218425944Sjoerg len >= 6 && p[1] == 6) { 218525944Sjoerg magic = (u_long)p[2] << 24 | 218625944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 218725944Sjoerg /* 218825944Sjoerg * If the remote magic is our negated one, 218925944Sjoerg * this looks like a loopback problem. 219025944Sjoerg * Suggest a new magic to make sure. 219125944Sjoerg */ 219225944Sjoerg if (magic == ~sp->lcp.magic) { 219325944Sjoerg if (debug) 219425944Sjoerg addlog("magic glitch "); 219542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 219635064Sphk sp->lcp.magic = random(); 219740008Sjoerg#else 219840008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 219940008Sjoerg#endif 220025944Sjoerg } else { 220125944Sjoerg sp->lcp.magic = magic; 220225944Sjoerg if (debug) 220340008Sjoerg addlog("%lu ", magic); 220425944Sjoerg } 220525944Sjoerg } 220625944Sjoerg break; 220725944Sjoerg case LCP_OPT_MRU: 220825944Sjoerg /* 220925944Sjoerg * Peer wants to advise us to negotiate an MRU. 221025944Sjoerg * Agree on it if it's reasonable, or use 221125944Sjoerg * default otherwise. 221225944Sjoerg */ 221325944Sjoerg if (len >= 4 && p[1] == 4) { 221425944Sjoerg u_int mru = p[2] * 256 + p[3]; 221525944Sjoerg if (debug) 221625944Sjoerg addlog("%d ", mru); 221725944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 221825944Sjoerg mru = PP_MTU; 221925944Sjoerg sp->lcp.mru = mru; 222025944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 222125944Sjoerg } 222225944Sjoerg break; 222330300Sjoerg case LCP_OPT_AUTH_PROTO: 222430300Sjoerg /* 222530300Sjoerg * Peer doesn't like our authentication method, 222630300Sjoerg * deny. 222730300Sjoerg */ 222830300Sjoerg if (debug) 222930300Sjoerg addlog("[access denied]\n"); 223030300Sjoerg lcp.Close(sp); 223130300Sjoerg break; 22324910Swollman } 223325944Sjoerg } 223425944Sjoerg if (debug) 223525944Sjoerg addlog("\n"); 223625944Sjoerg free (buf, M_TEMP); 223725944Sjoerg return; 223825944Sjoerg} 223911189Sjkh 224025944Sjoergstatic void 224125944Sjoergsppp_lcp_tlu(struct sppp *sp) 224225944Sjoerg{ 224340008Sjoerg struct ifnet *ifp = &sp->pp_if; 224425944Sjoerg int i; 224525944Sjoerg u_long mask; 224625944Sjoerg 224725944Sjoerg /* XXX ? */ 224825944Sjoerg if (! (ifp->if_flags & IFF_UP) && 224925944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 225025944Sjoerg /* Coming out of loopback mode. */ 225125944Sjoerg if_up(ifp); 225240008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 225325944Sjoerg } 225425944Sjoerg 225525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 225625944Sjoerg if ((cps[i])->flags & CP_QUAL) 225725944Sjoerg (cps[i])->Open(sp); 225825944Sjoerg 225930300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 226030300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 226125944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 226225944Sjoerg else 226325944Sjoerg sp->pp_phase = PHASE_NETWORK; 226425944Sjoerg 226540008Sjoerg log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 226625944Sjoerg sppp_phase_name(sp->pp_phase)); 226725944Sjoerg 226830300Sjoerg /* 226930300Sjoerg * Open all authentication protocols. This is even required 227030300Sjoerg * if we already proceeded to network phase, since it might be 227130300Sjoerg * that remote wants us to authenticate, so we might have to 227230300Sjoerg * send a PAP request. Undesired authentication protocols 227330300Sjoerg * don't do anything when they get an Open event. 227430300Sjoerg */ 227530300Sjoerg for (i = 0; i < IDX_COUNT; i++) 227630300Sjoerg if ((cps[i])->flags & CP_AUTH) 227730300Sjoerg (cps[i])->Open(sp); 227830300Sjoerg 227930300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 228025944Sjoerg /* Notify all NCPs. */ 228125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 228225944Sjoerg if ((cps[i])->flags & CP_NCP) 228325944Sjoerg (cps[i])->Open(sp); 228425944Sjoerg } 228525944Sjoerg 228625944Sjoerg /* Send Up events to all started protos. */ 228725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 228825944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 228925944Sjoerg (cps[i])->Up(sp); 229025944Sjoerg 229125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 229225944Sjoerg /* if no NCP is starting, close down */ 229330300Sjoerg sppp_lcp_check_and_close(sp); 229425944Sjoerg} 229525944Sjoerg 229625944Sjoergstatic void 229725944Sjoergsppp_lcp_tld(struct sppp *sp) 229825944Sjoerg{ 229940008Sjoerg struct ifnet *ifp = &sp->pp_if; 230025944Sjoerg int i; 230125944Sjoerg u_long mask; 230225944Sjoerg 230325944Sjoerg sp->pp_phase = PHASE_TERMINATE; 230425944Sjoerg 230540008Sjoerg log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 230625944Sjoerg sppp_phase_name(sp->pp_phase)); 230725944Sjoerg 230825944Sjoerg /* 230925944Sjoerg * Take upper layers down. We send the Down event first and 231025944Sjoerg * the Close second to prevent the upper layers from sending 231125944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 231225944Sjoerg * describes it. 231325944Sjoerg */ 231425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 231525944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 231625944Sjoerg (cps[i])->Down(sp); 231725944Sjoerg (cps[i])->Close(sp); 231825944Sjoerg } 231925944Sjoerg} 232025944Sjoerg 232125944Sjoergstatic void 232225944Sjoergsppp_lcp_tls(struct sppp *sp) 232325944Sjoerg{ 232440008Sjoerg struct ifnet *ifp = &sp->pp_if; 232525944Sjoerg 232625944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 232725944Sjoerg 232840008Sjoerg log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 232925944Sjoerg sppp_phase_name(sp->pp_phase)); 233025944Sjoerg 233125944Sjoerg /* Notify lower layer if desired. */ 233225944Sjoerg if (sp->pp_tls) 233325944Sjoerg (sp->pp_tls)(sp); 233441881Sphk else 233541881Sphk (sp->pp_up)(sp); 233625944Sjoerg} 233725944Sjoerg 233825944Sjoergstatic void 233925944Sjoergsppp_lcp_tlf(struct sppp *sp) 234025944Sjoerg{ 234140008Sjoerg struct ifnet *ifp = &sp->pp_if; 234225944Sjoerg 234325944Sjoerg sp->pp_phase = PHASE_DEAD; 234440008Sjoerg log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 234525944Sjoerg sppp_phase_name(sp->pp_phase)); 234625944Sjoerg 234725944Sjoerg /* Notify lower layer if desired. */ 234825944Sjoerg if (sp->pp_tlf) 234925944Sjoerg (sp->pp_tlf)(sp); 235041881Sphk else 235141881Sphk (sp->pp_down)(sp); 235225944Sjoerg} 235325944Sjoerg 235425944Sjoergstatic void 235525944Sjoergsppp_lcp_scr(struct sppp *sp) 235625944Sjoerg{ 235730300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 235825944Sjoerg int i = 0; 235930300Sjoerg u_short authproto; 236025944Sjoerg 236125944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 236225944Sjoerg if (! sp->lcp.magic) 236342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 236435064Sphk sp->lcp.magic = random(); 236540008Sjoerg#else 236640008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 236740008Sjoerg#endif 236825944Sjoerg opt[i++] = LCP_OPT_MAGIC; 236925944Sjoerg opt[i++] = 6; 237025944Sjoerg opt[i++] = sp->lcp.magic >> 24; 237125944Sjoerg opt[i++] = sp->lcp.magic >> 16; 237225944Sjoerg opt[i++] = sp->lcp.magic >> 8; 237325944Sjoerg opt[i++] = sp->lcp.magic; 237425944Sjoerg } 237525944Sjoerg 237625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 237725944Sjoerg opt[i++] = LCP_OPT_MRU; 237825944Sjoerg opt[i++] = 4; 237925944Sjoerg opt[i++] = sp->lcp.mru >> 8; 238025944Sjoerg opt[i++] = sp->lcp.mru; 238125944Sjoerg } 238225944Sjoerg 238330300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 238430300Sjoerg authproto = sp->hisauth.proto; 238530300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 238630300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 238730300Sjoerg opt[i++] = authproto >> 8; 238830300Sjoerg opt[i++] = authproto; 238930300Sjoerg if (authproto == PPP_CHAP) 239030300Sjoerg opt[i++] = CHAP_MD5; 239130300Sjoerg } 239230300Sjoerg 239325944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 239425944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 239525944Sjoerg} 239625944Sjoerg 239725944Sjoerg/* 239830300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 239930300Sjoerg */ 240030300Sjoergstatic int 240130300Sjoergsppp_ncp_check(struct sppp *sp) 240230300Sjoerg{ 240330300Sjoerg int i, mask; 240430300Sjoerg 240530300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 240630300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 240730300Sjoerg return 1; 240830300Sjoerg return 0; 240930300Sjoerg} 241030300Sjoerg 241130300Sjoerg/* 241225944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 241325944Sjoerg * Called by the NCPs during their tlf action handling. 241425944Sjoerg */ 241525944Sjoergstatic void 241630300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 241725944Sjoerg{ 241825944Sjoerg 241930300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 242030300Sjoerg /* don't bother, we are already going down */ 242130300Sjoerg return; 242230300Sjoerg 242330300Sjoerg if (sppp_ncp_check(sp)) 242430300Sjoerg return; 242530300Sjoerg 242625944Sjoerg lcp.Close(sp); 242725944Sjoerg} 242825944Sjoerg/* 242925944Sjoerg *--------------------------------------------------------------------------* 243025944Sjoerg * * 243125944Sjoerg * The IPCP implementation. * 243225944Sjoerg * * 243325944Sjoerg *--------------------------------------------------------------------------* 243425944Sjoerg */ 243525944Sjoerg 243625944Sjoergstatic void 243725944Sjoergsppp_ipcp_init(struct sppp *sp) 243825944Sjoerg{ 243925944Sjoerg sp->ipcp.opts = 0; 244025944Sjoerg sp->ipcp.flags = 0; 244125944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 244225944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 244342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 244429681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 244540008Sjoerg#endif 244625944Sjoerg} 244725944Sjoerg 244825944Sjoergstatic void 244925944Sjoergsppp_ipcp_up(struct sppp *sp) 245025944Sjoerg{ 245125944Sjoerg sppp_up_event(&ipcp, sp); 245225944Sjoerg} 245325944Sjoerg 245425944Sjoergstatic void 245525944Sjoergsppp_ipcp_down(struct sppp *sp) 245625944Sjoerg{ 245725944Sjoerg sppp_down_event(&ipcp, sp); 245825944Sjoerg} 245925944Sjoerg 246025944Sjoergstatic void 246125944Sjoergsppp_ipcp_open(struct sppp *sp) 246225944Sjoerg{ 246325944Sjoerg STDDCL; 246425944Sjoerg u_long myaddr, hisaddr; 246525944Sjoerg 246630300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 246725944Sjoerg /* 246825944Sjoerg * If we don't have his address, this probably means our 246925944Sjoerg * interface doesn't want to talk IP at all. (This could 247025944Sjoerg * be the case if somebody wants to speak only IPX, for 247125944Sjoerg * example.) Don't open IPCP in this case. 247225944Sjoerg */ 247325944Sjoerg if (hisaddr == 0L) { 247425944Sjoerg /* XXX this message should go away */ 247525944Sjoerg if (debug) 247640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 247740008Sjoerg SPP_ARGS(ifp)); 247825944Sjoerg return; 247925944Sjoerg } 248025944Sjoerg 248125944Sjoerg if (myaddr == 0L) { 248225944Sjoerg /* 248325944Sjoerg * I don't have an assigned address, so i need to 248425944Sjoerg * negotiate my address. 248525944Sjoerg */ 248625944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 248725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 248825944Sjoerg } 248925944Sjoerg sppp_open_event(&ipcp, sp); 249025944Sjoerg} 249125944Sjoerg 249225944Sjoergstatic void 249325944Sjoergsppp_ipcp_close(struct sppp *sp) 249425944Sjoerg{ 249525944Sjoerg sppp_close_event(&ipcp, sp); 249625944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 249725944Sjoerg /* 249825944Sjoerg * My address was dynamic, clear it again. 249925944Sjoerg */ 250025944Sjoerg sppp_set_ip_addr(sp, 0L); 250125944Sjoerg} 250225944Sjoerg 250325944Sjoergstatic void 250425944Sjoergsppp_ipcp_TO(void *cookie) 250525944Sjoerg{ 250625944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 250725944Sjoerg} 250825944Sjoerg 250925944Sjoerg/* 251025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 251125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 251225944Sjoerg * caused action scn. (The return value is used to make the state 251325944Sjoerg * transition decision in the state automaton.) 251425944Sjoerg */ 251525944Sjoergstatic int 251625944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 251725944Sjoerg{ 251825944Sjoerg u_char *buf, *r, *p; 251925944Sjoerg struct ifnet *ifp = &sp->pp_if; 252025944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 252125944Sjoerg u_long hisaddr, desiredaddr; 252225944Sjoerg 252325944Sjoerg len -= 4; 252425944Sjoerg origlen = len; 252525944Sjoerg /* 252625944Sjoerg * Make sure to allocate a buf that can at least hold a 252725944Sjoerg * conf-nak with an `address' option. We might need it below. 252825944Sjoerg */ 252925944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 253025944Sjoerg if (! buf) 253125944Sjoerg return (0); 253225944Sjoerg 253325944Sjoerg /* pass 1: see if we can recognize them */ 253425944Sjoerg if (debug) 253540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 253640008Sjoerg SPP_ARGS(ifp)); 253725944Sjoerg p = (void*) (h+1); 253825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 253925944Sjoerg if (debug) 254025944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 254125944Sjoerg switch (*p) { 254225944Sjoerg#ifdef notyet 254325944Sjoerg case IPCP_OPT_COMPRESSION: 254425944Sjoerg if (len >= 6 && p[1] >= 6) { 254525944Sjoerg /* correctly formed compress option */ 254625944Sjoerg continue; 254711189Sjkh } 254825706Sjoerg if (debug) 254925944Sjoerg addlog("[invalid] "); 255025944Sjoerg break; 255125944Sjoerg#endif 255225944Sjoerg case IPCP_OPT_ADDRESS: 255325944Sjoerg if (len >= 6 && p[1] == 6) { 255425944Sjoerg /* correctly formed address option */ 255525944Sjoerg continue; 255625944Sjoerg } 255725706Sjoerg if (debug) 255825944Sjoerg addlog("[invalid] "); 255911189Sjkh break; 256025944Sjoerg default: 256125944Sjoerg /* Others not supported. */ 256225944Sjoerg if (debug) 256325944Sjoerg addlog("[rej] "); 25644910Swollman break; 25654910Swollman } 256625944Sjoerg /* Add the option to rejected list. */ 256725944Sjoerg bcopy (p, r, p[1]); 256825944Sjoerg r += p[1]; 256925944Sjoerg rlen += p[1]; 257025944Sjoerg } 257125944Sjoerg if (rlen) { 257225944Sjoerg if (debug) 257325944Sjoerg addlog(" send conf-rej\n"); 257425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 257525944Sjoerg return 0; 257625944Sjoerg } else if (debug) 257725944Sjoerg addlog("\n"); 257825944Sjoerg 257925944Sjoerg /* pass 2: parse option values */ 258030300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 258125944Sjoerg if (debug) 258240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 258340008Sjoerg SPP_ARGS(ifp)); 258425944Sjoerg p = (void*) (h+1); 258525944Sjoerg len = origlen; 258625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 258725944Sjoerg if (debug) 258825944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 258925944Sjoerg switch (*p) { 259025944Sjoerg#ifdef notyet 259125944Sjoerg case IPCP_OPT_COMPRESSION: 259225944Sjoerg continue; 259325944Sjoerg#endif 259425944Sjoerg case IPCP_OPT_ADDRESS: 259525944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 259625944Sjoerg p[4] << 8 | p[5]; 259733928Sphk if (desiredaddr == hisaddr || 259833939Sbde hisaddr == 1 && desiredaddr != 0) { 259925944Sjoerg /* 260025944Sjoerg * Peer's address is same as our value, 260133928Sphk * or we have set it to 0.0.0.1 to 260233928Sphk * indicate that we do not really care, 260325944Sjoerg * this is agreeable. Gonna conf-ack 260425944Sjoerg * it. 260525944Sjoerg */ 260625944Sjoerg if (debug) 260730300Sjoerg addlog("%s [ack] ", 260833928Sphk sppp_dotted_quad(desiredaddr)); 260925944Sjoerg /* record that we've seen it already */ 261025944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 261125944Sjoerg continue; 261225944Sjoerg } 261325944Sjoerg /* 261425944Sjoerg * The address wasn't agreeable. This is either 261525944Sjoerg * he sent us 0.0.0.0, asking to assign him an 261625944Sjoerg * address, or he send us another address not 261725944Sjoerg * matching our value. Either case, we gonna 261825944Sjoerg * conf-nak it with our value. 261925944Sjoerg */ 262025944Sjoerg if (debug) { 262125944Sjoerg if (desiredaddr == 0) 262225944Sjoerg addlog("[addr requested] "); 262325944Sjoerg else 262430300Sjoerg addlog("%s [not agreed] ", 262530300Sjoerg sppp_dotted_quad(desiredaddr)); 262625944Sjoerg 262725944Sjoerg p[2] = hisaddr >> 24; 262825944Sjoerg p[3] = hisaddr >> 16; 262925944Sjoerg p[4] = hisaddr >> 8; 263025944Sjoerg p[5] = hisaddr; 263125944Sjoerg } 263211189Sjkh break; 263325706Sjoerg } 263425944Sjoerg /* Add the option to nak'ed list. */ 263525944Sjoerg bcopy (p, r, p[1]); 263625944Sjoerg r += p[1]; 263725944Sjoerg rlen += p[1]; 263825944Sjoerg } 263925944Sjoerg 264025944Sjoerg /* 264125944Sjoerg * If we are about to conf-ack the request, but haven't seen 264225944Sjoerg * his address so far, gonna conf-nak it instead, with the 264325944Sjoerg * `address' option present and our idea of his address being 264425944Sjoerg * filled in there, to request negotiation of both addresses. 264525944Sjoerg * 264625944Sjoerg * XXX This can result in an endless req - nak loop if peer 264725944Sjoerg * doesn't want to send us his address. Q: What should we do 264825944Sjoerg * about it? XXX A: implement the max-failure counter. 264925944Sjoerg */ 265025944Sjoerg if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { 265125944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 265225944Sjoerg buf[1] = 6; 265325944Sjoerg buf[2] = hisaddr >> 24; 265425944Sjoerg buf[3] = hisaddr >> 16; 265525944Sjoerg buf[4] = hisaddr >> 8; 265625944Sjoerg buf[5] = hisaddr; 265725944Sjoerg rlen = 6; 265825706Sjoerg if (debug) 265925944Sjoerg addlog("still need hisaddr "); 266025944Sjoerg } 266125944Sjoerg 266225944Sjoerg if (rlen) { 266325706Sjoerg if (debug) 266425944Sjoerg addlog(" send conf-nak\n"); 266525944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 266625944Sjoerg } else { 266725706Sjoerg if (debug) 266825944Sjoerg addlog(" send conf-ack\n"); 266925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 267025944Sjoerg h->ident, origlen, h+1); 267125944Sjoerg } 267225944Sjoerg 267325944Sjoerg free (buf, M_TEMP); 267425944Sjoerg return (rlen == 0); 267525944Sjoerg} 267625944Sjoerg 267725944Sjoerg/* 267825944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 267925944Sjoerg * negotiation. 268025944Sjoerg */ 268125944Sjoergstatic void 268225944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 268325944Sjoerg{ 268425944Sjoerg u_char *buf, *p; 268525944Sjoerg struct ifnet *ifp = &sp->pp_if; 268625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 268725944Sjoerg 268825944Sjoerg len -= 4; 268925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 269025944Sjoerg if (!buf) 269125944Sjoerg return; 269225944Sjoerg 269325944Sjoerg if (debug) 269440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 269540008Sjoerg SPP_ARGS(ifp)); 269625944Sjoerg 269725944Sjoerg p = (void*) (h+1); 269825944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 269925706Sjoerg if (debug) 270025944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 270125944Sjoerg switch (*p) { 270225944Sjoerg case IPCP_OPT_ADDRESS: 270325944Sjoerg /* 270425944Sjoerg * Peer doesn't grok address option. This is 270525944Sjoerg * bad. XXX Should we better give up here? 270625944Sjoerg */ 270725944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 270825944Sjoerg break; 270925944Sjoerg#ifdef notyet 271025944Sjoerg case IPCP_OPT_COMPRESS: 271125944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); 271225944Sjoerg break; 271325944Sjoerg#endif 271425944Sjoerg } 27154910Swollman } 271625944Sjoerg if (debug) 271725944Sjoerg addlog("\n"); 271825944Sjoerg free (buf, M_TEMP); 271925944Sjoerg return; 27204910Swollman} 27214910Swollman 272225944Sjoerg/* 272325944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 272425944Sjoerg * negotiation. 272525944Sjoerg */ 272612820Sphkstatic void 272725944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 27284910Swollman{ 272925944Sjoerg u_char *buf, *p; 273025944Sjoerg struct ifnet *ifp = &sp->pp_if; 273125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 273225944Sjoerg u_long wantaddr; 27334910Swollman 273425944Sjoerg len -= 4; 273525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 273625944Sjoerg if (!buf) 273725944Sjoerg return; 273825944Sjoerg 273925944Sjoerg if (debug) 274040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 274140008Sjoerg SPP_ARGS(ifp)); 274225944Sjoerg 274325944Sjoerg p = (void*) (h+1); 274425944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 274525944Sjoerg if (debug) 274625944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 274725944Sjoerg switch (*p) { 274825944Sjoerg case IPCP_OPT_ADDRESS: 274925944Sjoerg /* 275025944Sjoerg * Peer doesn't like our local IP address. See 275125944Sjoerg * if we can do something for him. We'll drop 275225944Sjoerg * him our address then. 275325944Sjoerg */ 275425944Sjoerg if (len >= 6 && p[1] == 6) { 275525944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 275625944Sjoerg p[4] << 8 | p[5]; 275725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 275825944Sjoerg if (debug) 275930300Sjoerg addlog("[wantaddr %s] ", 276030300Sjoerg sppp_dotted_quad(wantaddr)); 276125944Sjoerg /* 276225944Sjoerg * When doing dynamic address assignment, 276325944Sjoerg * we accept his offer. Otherwise, we 276425944Sjoerg * ignore it and thus continue to negotiate 276525944Sjoerg * our already existing value. 276625944Sjoerg */ 276725944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 276825944Sjoerg sppp_set_ip_addr(sp, wantaddr); 276925944Sjoerg if (debug) 277025944Sjoerg addlog("[agree] "); 277125944Sjoerg } 277225944Sjoerg } 277325944Sjoerg break; 277425944Sjoerg#ifdef notyet 277525944Sjoerg case IPCP_OPT_COMPRESS: 277625944Sjoerg /* 277725944Sjoerg * Peer wants different compression parameters. 277825944Sjoerg */ 277925944Sjoerg break; 278025944Sjoerg#endif 278125944Sjoerg } 278225944Sjoerg } 278325944Sjoerg if (debug) 278425944Sjoerg addlog("\n"); 278525944Sjoerg free (buf, M_TEMP); 278625944Sjoerg return; 27874910Swollman} 27884910Swollman 278912820Sphkstatic void 279025944Sjoergsppp_ipcp_tlu(struct sppp *sp) 27914910Swollman{ 27924910Swollman} 27934910Swollman 279425944Sjoergstatic void 279525944Sjoergsppp_ipcp_tld(struct sppp *sp) 279625944Sjoerg{ 279725944Sjoerg} 279825944Sjoerg 279925944Sjoergstatic void 280025944Sjoergsppp_ipcp_tls(struct sppp *sp) 280125944Sjoerg{ 280225944Sjoerg /* indicate to LCP that it must stay alive */ 280325944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 280425944Sjoerg} 280525944Sjoerg 280625944Sjoergstatic void 280725944Sjoergsppp_ipcp_tlf(struct sppp *sp) 280825944Sjoerg{ 280925944Sjoerg /* we no longer need LCP */ 281025944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 281130300Sjoerg sppp_lcp_check_and_close(sp); 281225944Sjoerg} 281325944Sjoerg 281425944Sjoergstatic void 281525944Sjoergsppp_ipcp_scr(struct sppp *sp) 281625944Sjoerg{ 281725944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 281825944Sjoerg u_long ouraddr; 281925944Sjoerg int i = 0; 282025944Sjoerg 282125944Sjoerg#ifdef notyet 282225944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 282325944Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 282425944Sjoerg opt[i++] = 6; 282525944Sjoerg opt[i++] = 0; /* VJ header compression */ 282625944Sjoerg opt[i++] = 0x2d; /* VJ header compression */ 282725944Sjoerg opt[i++] = max_slot_id; 282825944Sjoerg opt[i++] = comp_slot_id; 282925944Sjoerg } 283025944Sjoerg#endif 283125944Sjoerg 283225944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 283330300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 283425944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 283525944Sjoerg opt[i++] = 6; 283625944Sjoerg opt[i++] = ouraddr >> 24; 283725944Sjoerg opt[i++] = ouraddr >> 16; 283825944Sjoerg opt[i++] = ouraddr >> 8; 283925944Sjoerg opt[i++] = ouraddr; 284025944Sjoerg } 284125944Sjoerg 284225944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 284325944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 284425944Sjoerg} 284525944Sjoerg 284625944Sjoerg 284725944Sjoerg/* 284830300Sjoerg *--------------------------------------------------------------------------* 284930300Sjoerg * * 285030300Sjoerg * The CHAP implementation. * 285130300Sjoerg * * 285230300Sjoerg *--------------------------------------------------------------------------* 285330300Sjoerg */ 285430300Sjoerg 285530300Sjoerg/* 285630300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 285730300Sjoerg * the control protocols do, since they do have Open and Close events, but 285830300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 285930300Sjoerg * authentication protocols may be different in both directions (this makes 286030300Sjoerg * sense, think of a machine that never accepts incoming calls but only 286130300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 286230300Sjoerg * 286330300Sjoerg * Our state machine for the local authentication protocol (we are requesting 286430300Sjoerg * the peer to authenticate) looks like: 286530300Sjoerg * 286630300Sjoerg * RCA- 286730300Sjoerg * +--------------------------------------------+ 286830300Sjoerg * V scn,tld| 286930300Sjoerg * +--------+ Close +---------+ RCA+ 287030300Sjoerg * | |<----------------------------------| |------+ 287130300Sjoerg * +--->| Closed | TO* | Opened | sca | 287230300Sjoerg * | | |-----+ +-------| |<-----+ 287330300Sjoerg * | +--------+ irc | | +---------+ 287430300Sjoerg * | ^ | | ^ 287530300Sjoerg * | | | | | 287630300Sjoerg * | | | | | 287730300Sjoerg * | TO-| | | | 287830300Sjoerg * | |tld TO+ V | | 287930300Sjoerg * | | +------->+ | | 288030300Sjoerg * | | | | | | 288130300Sjoerg * | +--------+ V | | 288230300Sjoerg * | | |<----+<--------------------+ | 288330300Sjoerg * | | Req- | scr | 288430300Sjoerg * | | Sent | | 288530300Sjoerg * | | | | 288630300Sjoerg * | +--------+ | 288730300Sjoerg * | RCA- | | RCA+ | 288830300Sjoerg * +------+ +------------------------------------------+ 288930300Sjoerg * scn,tld sca,irc,ict,tlu 289030300Sjoerg * 289130300Sjoerg * 289230300Sjoerg * with: 289330300Sjoerg * 289430300Sjoerg * Open: LCP reached authentication phase 289530300Sjoerg * Close: LCP reached terminate phase 289630300Sjoerg * 289730300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 289830300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 289930300Sjoerg * TO+: timeout with restart counter >= 0 290030300Sjoerg * TO-: timeout with restart counter < 0 290130300Sjoerg * TO*: reschedule timeout for CHAP 290230300Sjoerg * 290330300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 290430300Sjoerg * sca: send ack packet (pap-ack, chap-success) 290530300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 290630300Sjoerg * ict: initialize re-challenge timer (CHAP only) 290730300Sjoerg * 290830300Sjoerg * tlu: this-layer-up, LCP reaches network phase 290930300Sjoerg * tld: this-layer-down, LCP enters terminate phase 291030300Sjoerg * 291130300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 291230300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 291330300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 291430300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 291530300Sjoerg * causing LCP to enter terminate phase. 291630300Sjoerg * 291730300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 291830300Sjoerg * expected to send one based on the successful negotiation of PAP as 291930300Sjoerg * the authentication protocol during the LCP option negotiation. 292030300Sjoerg * 292130300Sjoerg * Incoming authentication protocol requests (remote requests 292230300Sjoerg * authentication, we are peer) don't employ a state machine at all, 292330300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 292430300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 292530300Sjoerg * still in authentication phase (thereby violating the standard that 292630300Sjoerg * demands that these NCP packets are to be discarded), so we keep 292730300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 292830300Sjoerg * phase network once we've seen a positive acknowledge for the 292930300Sjoerg * authentication. 293030300Sjoerg */ 293130300Sjoerg 293230300Sjoerg/* 293330300Sjoerg * Handle incoming CHAP packets. 293430300Sjoerg */ 293530300Sjoergvoid 293630300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 293730300Sjoerg{ 293830300Sjoerg STDDCL; 293930300Sjoerg struct lcp_header *h; 294030300Sjoerg int len, x; 294130300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 294230300Sjoerg int value_len, name_len; 294330300Sjoerg MD5_CTX ctx; 294430300Sjoerg 294530300Sjoerg len = m->m_pkthdr.len; 294630300Sjoerg if (len < 4) { 294730300Sjoerg if (debug) 294830300Sjoerg log(LOG_DEBUG, 294940008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 295040008Sjoerg SPP_ARGS(ifp), len); 295130300Sjoerg return; 295230300Sjoerg } 295330300Sjoerg h = mtod (m, struct lcp_header*); 295430300Sjoerg if (len > ntohs (h->len)) 295530300Sjoerg len = ntohs (h->len); 295630300Sjoerg 295730300Sjoerg switch (h->type) { 295830300Sjoerg /* challenge, failure and success are his authproto */ 295930300Sjoerg case CHAP_CHALLENGE: 296030300Sjoerg value = 1 + (u_char*)(h+1); 296130300Sjoerg value_len = value[-1]; 296230300Sjoerg name = value + value_len; 296330300Sjoerg name_len = len - value_len - 5; 296430300Sjoerg if (name_len < 0) { 296530300Sjoerg if (debug) { 296630300Sjoerg log(LOG_DEBUG, 296740008Sjoerg SPP_FMT "chap corrupted challenge " 296830300Sjoerg "<%s id=0x%x len=%d", 296940008Sjoerg SPP_ARGS(ifp), 297030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 297130300Sjoerg h->ident, ntohs(h->len)); 297230300Sjoerg if (len > 4) 297330300Sjoerg sppp_print_bytes((u_char*) (h+1), len-4); 297430300Sjoerg addlog(">\n"); 297530300Sjoerg } 297630300Sjoerg break; 297730300Sjoerg } 297830300Sjoerg 297930300Sjoerg if (debug) { 298030300Sjoerg log(LOG_DEBUG, 298140008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 298240008Sjoerg SPP_ARGS(ifp), 298330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 298430300Sjoerg ntohs(h->len)); 298530300Sjoerg sppp_print_string((char*) name, name_len); 298630300Sjoerg addlog(" value-size=%d value=", value_len); 298730300Sjoerg sppp_print_bytes(value, value_len); 298830300Sjoerg addlog(">\n"); 298930300Sjoerg } 299030300Sjoerg 299130300Sjoerg /* Compute reply value. */ 299230300Sjoerg MD5Init(&ctx); 299330300Sjoerg MD5Update(&ctx, &h->ident, 1); 299430300Sjoerg MD5Update(&ctx, sp->myauth.secret, 299530300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 299630300Sjoerg MD5Update(&ctx, value, value_len); 299730300Sjoerg MD5Final(digest, &ctx); 299830300Sjoerg dsize = sizeof digest; 299930300Sjoerg 300030300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 300130300Sjoerg sizeof dsize, (const char *)&dsize, 300230300Sjoerg sizeof digest, digest, 300340008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 300430300Sjoerg sp->myauth.name, 300530300Sjoerg 0); 300630300Sjoerg break; 300730300Sjoerg 300830300Sjoerg case CHAP_SUCCESS: 300930300Sjoerg if (debug) { 301040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 301140008Sjoerg SPP_ARGS(ifp)); 301230300Sjoerg if (len > 4) { 301330300Sjoerg addlog(": "); 301430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 301530300Sjoerg } 301630300Sjoerg addlog("\n"); 301730300Sjoerg } 301830300Sjoerg x = splimp(); 301930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 302030300Sjoerg if (sp->myauth.proto == PPP_CHAP && 302132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 302230300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 302330300Sjoerg /* 302430300Sjoerg * We are authenticator for CHAP but didn't 302530300Sjoerg * complete yet. Leave it to tlu to proceed 302630300Sjoerg * to network phase. 302730300Sjoerg */ 302830300Sjoerg splx(x); 302930300Sjoerg break; 303030300Sjoerg } 303130300Sjoerg splx(x); 303230300Sjoerg sppp_phase_network(sp); 303330300Sjoerg break; 303430300Sjoerg 303530300Sjoerg case CHAP_FAILURE: 303630300Sjoerg if (debug) { 303740008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 303840008Sjoerg SPP_ARGS(ifp)); 303930300Sjoerg if (len > 4) { 304030300Sjoerg addlog(": "); 304130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 304230300Sjoerg } 304330300Sjoerg addlog("\n"); 304430300Sjoerg } else 304540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 304640008Sjoerg SPP_ARGS(ifp)); 304730300Sjoerg /* await LCP shutdown by authenticator */ 304830300Sjoerg break; 304930300Sjoerg 305030300Sjoerg /* response is my authproto */ 305130300Sjoerg case CHAP_RESPONSE: 305230300Sjoerg value = 1 + (u_char*)(h+1); 305330300Sjoerg value_len = value[-1]; 305430300Sjoerg name = value + value_len; 305530300Sjoerg name_len = len - value_len - 5; 305630300Sjoerg if (name_len < 0) { 305730300Sjoerg if (debug) { 305830300Sjoerg log(LOG_DEBUG, 305940008Sjoerg SPP_FMT "chap corrupted response " 306030300Sjoerg "<%s id=0x%x len=%d", 306140008Sjoerg SPP_ARGS(ifp), 306230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 306330300Sjoerg h->ident, ntohs(h->len)); 306430300Sjoerg if (len > 4) 306530300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 306630300Sjoerg addlog(">\n"); 306730300Sjoerg } 306830300Sjoerg break; 306930300Sjoerg } 307030300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 307130300Sjoerg if (debug) 307230300Sjoerg log(LOG_DEBUG, 307340008Sjoerg SPP_FMT "chap dropping response for old ID " 307430300Sjoerg "(got %d, expected %d)\n", 307540008Sjoerg SPP_ARGS(ifp), 307630300Sjoerg h->ident, sp->confid[IDX_CHAP]); 307730300Sjoerg break; 307830300Sjoerg } 307930300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 308030300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 308140008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 308240008Sjoerg SPP_ARGS(ifp)); 308330300Sjoerg sppp_print_string(name, name_len); 308430300Sjoerg addlog(" != expected "); 308530300Sjoerg sppp_print_string(sp->hisauth.name, 308630300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 308730300Sjoerg addlog("\n"); 308830300Sjoerg } 308930300Sjoerg if (debug) { 309040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 309130300Sjoerg "<%s id=0x%x len=%d name=", 309240008Sjoerg SPP_ARGS(ifp), 309330300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 309430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 309530300Sjoerg h->ident, ntohs (h->len)); 309630300Sjoerg sppp_print_string((char*)name, name_len); 309730300Sjoerg addlog(" value-size=%d value=", value_len); 309830300Sjoerg sppp_print_bytes(value, value_len); 309930300Sjoerg addlog(">\n"); 310030300Sjoerg } 310130300Sjoerg if (value_len != AUTHKEYLEN) { 310230300Sjoerg if (debug) 310330300Sjoerg log(LOG_DEBUG, 310440008Sjoerg SPP_FMT "chap bad hash value length: " 310530300Sjoerg "%d bytes, should be %d\n", 310640008Sjoerg SPP_ARGS(ifp), value_len, 310730300Sjoerg AUTHKEYLEN); 310830300Sjoerg break; 310930300Sjoerg } 311030300Sjoerg 311130300Sjoerg MD5Init(&ctx); 311230300Sjoerg MD5Update(&ctx, &h->ident, 1); 311330300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 311430300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 311530300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 311630300Sjoerg MD5Final(digest, &ctx); 311730300Sjoerg 311830300Sjoerg#define FAILMSG "Failed..." 311930300Sjoerg#define SUCCMSG "Welcome!" 312030300Sjoerg 312130300Sjoerg if (value_len != sizeof digest || 312230300Sjoerg bcmp(digest, value, value_len) != 0) { 312330300Sjoerg /* action scn, tld */ 312430300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 312530300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 312630300Sjoerg 0); 312730300Sjoerg chap.tld(sp); 312830300Sjoerg break; 312930300Sjoerg } 313030300Sjoerg /* action sca, perhaps tlu */ 313130300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 313230300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 313330300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 313430300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 313530300Sjoerg 0); 313630300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 313730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 313830300Sjoerg chap.tlu(sp); 313930300Sjoerg } 314030300Sjoerg break; 314130300Sjoerg 314230300Sjoerg default: 314330300Sjoerg /* Unknown CHAP packet type -- ignore. */ 314430300Sjoerg if (debug) { 314540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 314630300Sjoerg "<0x%x id=0x%xh len=%d", 314740008Sjoerg SPP_ARGS(ifp), 314830300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 314930300Sjoerg h->type, h->ident, ntohs(h->len)); 315030300Sjoerg if (len > 4) 315130300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 315230300Sjoerg addlog(">\n"); 315330300Sjoerg } 315430300Sjoerg break; 315530300Sjoerg 315630300Sjoerg } 315730300Sjoerg} 315830300Sjoerg 315930300Sjoergstatic void 316030300Sjoergsppp_chap_init(struct sppp *sp) 316130300Sjoerg{ 316230300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 316330300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 316430300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 316542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 316630300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 316740008Sjoerg#endif 316830300Sjoerg} 316930300Sjoerg 317030300Sjoergstatic void 317130300Sjoergsppp_chap_open(struct sppp *sp) 317230300Sjoerg{ 317330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 317430300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 317530300Sjoerg /* we are authenticator for CHAP, start it */ 317630300Sjoerg chap.scr(sp); 317730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 317830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 317930300Sjoerg } 318030300Sjoerg /* nothing to be done if we are peer, await a challenge */ 318130300Sjoerg} 318230300Sjoerg 318330300Sjoergstatic void 318430300Sjoergsppp_chap_close(struct sppp *sp) 318530300Sjoerg{ 318630300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 318730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 318830300Sjoerg} 318930300Sjoerg 319030300Sjoergstatic void 319130300Sjoergsppp_chap_TO(void *cookie) 319230300Sjoerg{ 319330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 319430300Sjoerg STDDCL; 319530300Sjoerg int s; 319630300Sjoerg 319730300Sjoerg s = splimp(); 319830300Sjoerg if (debug) 319940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 320040008Sjoerg SPP_ARGS(ifp), 320130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 320230300Sjoerg sp->rst_counter[IDX_CHAP]); 320330300Sjoerg 320430300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 320530300Sjoerg /* TO- event */ 320630300Sjoerg switch (sp->state[IDX_CHAP]) { 320730300Sjoerg case STATE_REQ_SENT: 320830300Sjoerg chap.tld(sp); 320930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 321030300Sjoerg break; 321130300Sjoerg } 321230300Sjoerg else 321330300Sjoerg /* TO+ (or TO*) event */ 321430300Sjoerg switch (sp->state[IDX_CHAP]) { 321530300Sjoerg case STATE_OPENED: 321630300Sjoerg /* TO* event */ 321730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 321830300Sjoerg /* fall through */ 321930300Sjoerg case STATE_REQ_SENT: 322030300Sjoerg chap.scr(sp); 322130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 322230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 322330300Sjoerg break; 322430300Sjoerg } 322530300Sjoerg 322630300Sjoerg splx(s); 322730300Sjoerg} 322830300Sjoerg 322930300Sjoergstatic void 323030300Sjoergsppp_chap_tlu(struct sppp *sp) 323130300Sjoerg{ 323230300Sjoerg STDDCL; 323330300Sjoerg int i, x; 323430300Sjoerg 323540010Sjoerg i = 0; 323630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 323730300Sjoerg 323830300Sjoerg /* 323930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 324030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 324130300Sjoerg * initial challenge-response exchange has taken place. 324230300Sjoerg * Provide for an option to avoid rechallenges. 324330300Sjoerg */ 324430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 324530300Sjoerg /* 324630300Sjoerg * Compute the re-challenge timeout. This will yield 324730300Sjoerg * a number between 300 and 810 seconds. 324830300Sjoerg */ 324930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 325042064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 325130300Sjoerg } 325230300Sjoerg 325330300Sjoerg if (debug) { 325430300Sjoerg log(LOG_DEBUG, 325540008Sjoerg SPP_FMT "chap %s, ", 325640008Sjoerg SPP_ARGS(ifp), 325730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 325830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 325930300Sjoerg addlog("next re-challenge in %d seconds\n", i); 326030300Sjoerg else 326130300Sjoerg addlog("re-challenging supressed\n"); 326230300Sjoerg } 326330300Sjoerg 326430300Sjoerg x = splimp(); 326530300Sjoerg /* indicate to LCP that we need to be closed down */ 326630300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 326730300Sjoerg 326830300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 326930300Sjoerg /* 327030300Sjoerg * Remote is authenticator, but his auth proto didn't 327130300Sjoerg * complete yet. Defer the transition to network 327230300Sjoerg * phase. 327330300Sjoerg */ 327430300Sjoerg splx(x); 327530300Sjoerg return; 327630300Sjoerg } 327730300Sjoerg splx(x); 327830300Sjoerg 327930300Sjoerg /* 328030300Sjoerg * If we are already in phase network, we are done here. This 328130300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 328230300Sjoerg */ 328330300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 328430300Sjoerg sppp_phase_network(sp); 328530300Sjoerg} 328630300Sjoerg 328730300Sjoergstatic void 328830300Sjoergsppp_chap_tld(struct sppp *sp) 328930300Sjoerg{ 329030300Sjoerg STDDCL; 329130300Sjoerg 329230300Sjoerg if (debug) 329340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 329440008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 329530300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 329630300Sjoerg 329730300Sjoerg lcp.Close(sp); 329830300Sjoerg} 329930300Sjoerg 330030300Sjoergstatic void 330130300Sjoergsppp_chap_scr(struct sppp *sp) 330230300Sjoerg{ 330330300Sjoerg u_long *ch, seed; 330430300Sjoerg u_char clen; 330540010Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 330640010Sjoerg struct timeval tv; 330740010Sjoerg#endif 330830300Sjoerg 330930300Sjoerg /* Compute random challenge. */ 331030300Sjoerg ch = (u_long *)sp->myauth.challenge; 331142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 331235064Sphk read_random(&seed, sizeof seed); 331340008Sjoerg#else 331440008Sjoerg microtime(&tv); 331540008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 331640008Sjoerg#endif 331730300Sjoerg ch[0] = seed ^ random(); 331830300Sjoerg ch[1] = seed ^ random(); 331930300Sjoerg ch[2] = seed ^ random(); 332030300Sjoerg ch[3] = seed ^ random(); 332130300Sjoerg clen = AUTHKEYLEN; 332230300Sjoerg 332330300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 332430300Sjoerg 332530300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 332630300Sjoerg sizeof clen, (const char *)&clen, 332740008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 332840008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 332930300Sjoerg sp->myauth.name, 333030300Sjoerg 0); 333130300Sjoerg} 333230300Sjoerg/* 333330300Sjoerg *--------------------------------------------------------------------------* 333430300Sjoerg * * 333530300Sjoerg * The PAP implementation. * 333630300Sjoerg * * 333730300Sjoerg *--------------------------------------------------------------------------* 333830300Sjoerg */ 333930300Sjoerg/* 334030300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 334130300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 334230300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 334330300Sjoerg * retry counter is expired). 334430300Sjoerg */ 334530300Sjoerg 334630300Sjoerg/* 334730300Sjoerg * Handle incoming PAP packets. */ 334830300Sjoergstatic void 334930300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 335030300Sjoerg{ 335130300Sjoerg STDDCL; 335230300Sjoerg struct lcp_header *h; 335330300Sjoerg int len, x; 335430300Sjoerg u_char *name, *passwd, mlen; 335530300Sjoerg int name_len, passwd_len; 335630300Sjoerg 335730300Sjoerg len = m->m_pkthdr.len; 335830300Sjoerg if (len < 5) { 335930300Sjoerg if (debug) 336030300Sjoerg log(LOG_DEBUG, 336140008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 336240008Sjoerg SPP_ARGS(ifp), len); 336330300Sjoerg return; 336430300Sjoerg } 336530300Sjoerg h = mtod (m, struct lcp_header*); 336630300Sjoerg if (len > ntohs (h->len)) 336730300Sjoerg len = ntohs (h->len); 336830300Sjoerg switch (h->type) { 336930300Sjoerg /* PAP request is my authproto */ 337030300Sjoerg case PAP_REQ: 337130300Sjoerg name = 1 + (u_char*)(h+1); 337230300Sjoerg name_len = name[-1]; 337330300Sjoerg passwd = name + name_len + 1; 337430300Sjoerg if (name_len > len - 6 || 337530300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 337630300Sjoerg if (debug) { 337740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 337830300Sjoerg "<%s id=0x%x len=%d", 337940008Sjoerg SPP_ARGS(ifp), 338030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 338130300Sjoerg 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 if (debug) { 338940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 339030300Sjoerg "<%s id=0x%x len=%d name=", 339140008Sjoerg SPP_ARGS(ifp), 339230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 339330300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 339430300Sjoerg h->ident, ntohs(h->len)); 339530300Sjoerg sppp_print_string((char*)name, name_len); 339630300Sjoerg addlog(" passwd="); 339730300Sjoerg sppp_print_string((char*)passwd, passwd_len); 339830300Sjoerg addlog(">\n"); 339930300Sjoerg } 340030300Sjoerg if (name_len > AUTHNAMELEN || 340130300Sjoerg passwd_len > AUTHKEYLEN || 340230300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 340330300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 340430300Sjoerg /* action scn, tld */ 340530300Sjoerg mlen = sizeof(FAILMSG) - 1; 340630300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 340730300Sjoerg sizeof mlen, (const char *)&mlen, 340830300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 340930300Sjoerg 0); 341030300Sjoerg pap.tld(sp); 341130300Sjoerg break; 341230300Sjoerg } 341330300Sjoerg /* action sca, perhaps tlu */ 341430300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 341530300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 341630300Sjoerg mlen = sizeof(SUCCMSG) - 1; 341730300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 341830300Sjoerg sizeof mlen, (const char *)&mlen, 341930300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 342030300Sjoerg 0); 342130300Sjoerg } 342230300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 342330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 342430300Sjoerg pap.tlu(sp); 342530300Sjoerg } 342630300Sjoerg break; 342730300Sjoerg 342830300Sjoerg /* ack and nak are his authproto */ 342930300Sjoerg case PAP_ACK: 343040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 343130300Sjoerg if (debug) { 343240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 343340008Sjoerg SPP_ARGS(ifp)); 343430300Sjoerg name_len = *((char *)h); 343530300Sjoerg if (len > 5 && name_len) { 343630300Sjoerg addlog(": "); 343730300Sjoerg sppp_print_string((char*)(h+1), name_len); 343830300Sjoerg } 343930300Sjoerg addlog("\n"); 344030300Sjoerg } 344130300Sjoerg x = splimp(); 344230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 344330300Sjoerg if (sp->myauth.proto == PPP_PAP && 344432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 344530300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 344630300Sjoerg /* 344730300Sjoerg * We are authenticator for PAP but didn't 344830300Sjoerg * complete yet. Leave it to tlu to proceed 344930300Sjoerg * to network phase. 345030300Sjoerg */ 345130300Sjoerg splx(x); 345230300Sjoerg break; 345330300Sjoerg } 345430300Sjoerg splx(x); 345530300Sjoerg sppp_phase_network(sp); 345630300Sjoerg break; 345730300Sjoerg 345830300Sjoerg case PAP_NAK: 345940008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 346030300Sjoerg if (debug) { 346140008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 346240008Sjoerg SPP_ARGS(ifp)); 346330300Sjoerg name_len = *((char *)h); 346430300Sjoerg if (len > 5 && name_len) { 346530300Sjoerg addlog(": "); 346630300Sjoerg sppp_print_string((char*)(h+1), name_len); 346730300Sjoerg } 346830300Sjoerg addlog("\n"); 346930300Sjoerg } else 347040008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 347140008Sjoerg SPP_ARGS(ifp)); 347230300Sjoerg /* await LCP shutdown by authenticator */ 347330300Sjoerg break; 347430300Sjoerg 347530300Sjoerg default: 347630300Sjoerg /* Unknown PAP packet type -- ignore. */ 347730300Sjoerg if (debug) { 347840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 347930300Sjoerg "<0x%x id=0x%x len=%d", 348040008Sjoerg SPP_ARGS(ifp), 348130300Sjoerg h->type, h->ident, ntohs(h->len)); 348230300Sjoerg if (len > 4) 348330300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 348430300Sjoerg addlog(">\n"); 348530300Sjoerg } 348630300Sjoerg break; 348730300Sjoerg 348830300Sjoerg } 348930300Sjoerg} 349030300Sjoerg 349130300Sjoergstatic void 349230300Sjoergsppp_pap_init(struct sppp *sp) 349330300Sjoerg{ 349430300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 349530300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 349630300Sjoerg sp->fail_counter[IDX_PAP] = 0; 349742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 349830300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 349930300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 350040008Sjoerg#endif 350130300Sjoerg} 350230300Sjoerg 350330300Sjoergstatic void 350430300Sjoergsppp_pap_open(struct sppp *sp) 350530300Sjoerg{ 350630300Sjoerg if (sp->hisauth.proto == PPP_PAP && 350730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 350830300Sjoerg /* we are authenticator for PAP, start our timer */ 350930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 351030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 351130300Sjoerg } 351230300Sjoerg if (sp->myauth.proto == PPP_PAP) { 351330300Sjoerg /* we are peer, send a request, and start a timer */ 351430300Sjoerg pap.scr(sp); 351542064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 351642064Sphk sp->pap_my_to_ch); 351730300Sjoerg } 351830300Sjoerg} 351930300Sjoerg 352030300Sjoergstatic void 352130300Sjoergsppp_pap_close(struct sppp *sp) 352230300Sjoerg{ 352330300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 352430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 352530300Sjoerg} 352630300Sjoerg 352730300Sjoerg/* 352830300Sjoerg * That's the timeout routine if we are authenticator. Since the 352930300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 353030300Sjoerg */ 353130300Sjoergstatic void 353230300Sjoergsppp_pap_TO(void *cookie) 353330300Sjoerg{ 353430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 353530300Sjoerg STDDCL; 353630300Sjoerg int s; 353730300Sjoerg 353830300Sjoerg s = splimp(); 353930300Sjoerg if (debug) 354040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 354140008Sjoerg SPP_ARGS(ifp), 354230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 354330300Sjoerg sp->rst_counter[IDX_PAP]); 354430300Sjoerg 354530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 354630300Sjoerg /* TO- event */ 354730300Sjoerg switch (sp->state[IDX_PAP]) { 354830300Sjoerg case STATE_REQ_SENT: 354930300Sjoerg pap.tld(sp); 355030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 355130300Sjoerg break; 355230300Sjoerg } 355330300Sjoerg else 355430300Sjoerg /* TO+ event, not very much we could do */ 355530300Sjoerg switch (sp->state[IDX_PAP]) { 355630300Sjoerg case STATE_REQ_SENT: 355730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 355830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 355930300Sjoerg break; 356030300Sjoerg } 356130300Sjoerg 356230300Sjoerg splx(s); 356330300Sjoerg} 356430300Sjoerg 356530300Sjoerg/* 356630300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 356730300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 356830300Sjoerg * XXX We should impose a max counter. 356930300Sjoerg */ 357030300Sjoergstatic void 357130300Sjoergsppp_pap_my_TO(void *cookie) 357230300Sjoerg{ 357330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 357430300Sjoerg STDDCL; 357530300Sjoerg 357630300Sjoerg if (debug) 357740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 357840008Sjoerg SPP_ARGS(ifp)); 357930300Sjoerg 358030300Sjoerg pap.scr(sp); 358130300Sjoerg} 358230300Sjoerg 358330300Sjoergstatic void 358430300Sjoergsppp_pap_tlu(struct sppp *sp) 358530300Sjoerg{ 358630300Sjoerg STDDCL; 358730300Sjoerg int x; 358830300Sjoerg 358930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 359030300Sjoerg 359130300Sjoerg if (debug) 359240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 359340008Sjoerg SPP_ARGS(ifp), pap.name); 359430300Sjoerg 359530300Sjoerg x = splimp(); 359630300Sjoerg /* indicate to LCP that we need to be closed down */ 359730300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 359830300Sjoerg 359930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 360030300Sjoerg /* 360130300Sjoerg * Remote is authenticator, but his auth proto didn't 360230300Sjoerg * complete yet. Defer the transition to network 360330300Sjoerg * phase. 360430300Sjoerg */ 360530300Sjoerg splx(x); 360630300Sjoerg return; 360730300Sjoerg } 360830300Sjoerg splx(x); 360930300Sjoerg sppp_phase_network(sp); 361030300Sjoerg} 361130300Sjoerg 361230300Sjoergstatic void 361330300Sjoergsppp_pap_tld(struct sppp *sp) 361430300Sjoerg{ 361530300Sjoerg STDDCL; 361630300Sjoerg 361730300Sjoerg if (debug) 361840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 361940008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 362040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 362130300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 362230300Sjoerg 362330300Sjoerg lcp.Close(sp); 362430300Sjoerg} 362530300Sjoerg 362630300Sjoergstatic void 362730300Sjoergsppp_pap_scr(struct sppp *sp) 362830300Sjoerg{ 362930300Sjoerg u_char idlen, pwdlen; 363030300Sjoerg 363130300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 363230300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 363330300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 363430300Sjoerg 363530300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 363630300Sjoerg sizeof idlen, (const char *)&idlen, 363740008Sjoerg (size_t)idlen, sp->myauth.name, 363830300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 363940008Sjoerg (size_t)pwdlen, sp->myauth.secret, 364030300Sjoerg 0); 364130300Sjoerg} 364230300Sjoerg/* 364325944Sjoerg * Random miscellaneous functions. 364425944Sjoerg */ 364525944Sjoerg 36464910Swollman/* 364730300Sjoerg * Send a PAP or CHAP proto packet. 364830300Sjoerg * 364930300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 365040008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 365130300Sjoerg * mlen == 0. 365230300Sjoerg */ 365330300Sjoerg 365430300Sjoergstatic void 365530300Sjoergsppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, 365630300Sjoerg ...) 365730300Sjoerg{ 365830300Sjoerg STDDCL; 365930300Sjoerg struct ppp_header *h; 366030300Sjoerg struct lcp_header *lh; 366130300Sjoerg struct mbuf *m; 366230300Sjoerg u_char *p; 366330300Sjoerg int len; 366440008Sjoerg size_t mlen; 366530300Sjoerg const char *msg; 366630300Sjoerg va_list ap; 366730300Sjoerg 366830300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 366930300Sjoerg if (! m) 367030300Sjoerg return; 367130300Sjoerg m->m_pkthdr.rcvif = 0; 367230300Sjoerg 367330300Sjoerg h = mtod (m, struct ppp_header*); 367430300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 367530300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 367630300Sjoerg h->protocol = htons(cp->proto); 367730300Sjoerg 367830300Sjoerg lh = (struct lcp_header*)(h + 1); 367930300Sjoerg lh->type = type; 368030300Sjoerg lh->ident = id; 368130300Sjoerg p = (u_char*) (lh+1); 368230300Sjoerg 368330300Sjoerg va_start(ap, id); 368430300Sjoerg len = 0; 368530300Sjoerg 368640008Sjoerg while ((mlen = va_arg(ap, size_t)) != 0) { 368730300Sjoerg msg = va_arg(ap, const char *); 368830300Sjoerg len += mlen; 368930300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 369030300Sjoerg va_end(ap); 369130300Sjoerg m_freem(m); 369230300Sjoerg return; 369330300Sjoerg } 369430300Sjoerg 369530300Sjoerg bcopy(msg, p, mlen); 369630300Sjoerg p += mlen; 369730300Sjoerg } 369830300Sjoerg va_end(ap); 369930300Sjoerg 370030300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 370130300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 370230300Sjoerg 370330300Sjoerg if (debug) { 370440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 370540008Sjoerg SPP_ARGS(ifp), cp->name, 370630300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 370730300Sjoerg lh->ident, ntohs(lh->len)); 370830300Sjoerg if (len) 370930300Sjoerg sppp_print_bytes((u_char*) (lh+1), len); 371030300Sjoerg addlog(">\n"); 371130300Sjoerg } 371230300Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 371330300Sjoerg IF_DROP (&sp->pp_fastq); 371430300Sjoerg IF_DROP (&ifp->if_snd); 371530300Sjoerg m_freem (m); 371630300Sjoerg ++ifp->if_oerrors; 371730300Sjoerg } else 371830300Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 371930300Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 372030300Sjoerg (*ifp->if_start) (ifp); 372130300Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 372230300Sjoerg} 372330300Sjoerg 372430300Sjoerg/* 372525944Sjoerg * Flush interface queue. 37264910Swollman */ 372712820Sphkstatic void 372825944Sjoergsppp_qflush(struct ifqueue *ifq) 37294910Swollman{ 373025944Sjoerg struct mbuf *m, *n; 37314910Swollman 373225944Sjoerg n = ifq->ifq_head; 373325944Sjoerg while ((m = n)) { 373425944Sjoerg n = m->m_act; 373525944Sjoerg m_freem (m); 373611189Sjkh } 373725944Sjoerg ifq->ifq_head = 0; 373825944Sjoerg ifq->ifq_tail = 0; 373925944Sjoerg ifq->ifq_len = 0; 374025944Sjoerg} 374125944Sjoerg 374225944Sjoerg/* 374325944Sjoerg * Send keepalive packets, every 10 seconds. 374425944Sjoerg */ 374525944Sjoergstatic void 374625944Sjoergsppp_keepalive(void *dummy) 374725944Sjoerg{ 374825944Sjoerg struct sppp *sp; 374925944Sjoerg int s; 375025944Sjoerg 375125944Sjoerg s = splimp(); 375225944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 375325944Sjoerg struct ifnet *ifp = &sp->pp_if; 375425944Sjoerg 375525944Sjoerg /* Keepalive mode disabled or channel down? */ 375625944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 375725944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 375825944Sjoerg continue; 375925944Sjoerg 376025944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 376125944Sjoerg if (! (sp->pp_flags & PP_CISCO) && 376225944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 376325944Sjoerg continue; 376425944Sjoerg 376525944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 376625944Sjoerg /* No keepalive packets got. Stop the interface. */ 376740008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 376825944Sjoerg if_down (ifp); 376926018Sjoerg sppp_qflush (&sp->pp_cpq); 377025944Sjoerg if (! (sp->pp_flags & PP_CISCO)) { 377125944Sjoerg /* XXX */ 377225944Sjoerg /* Shut down the PPP link. */ 377325944Sjoerg lcp.Down(sp); 377425944Sjoerg /* Initiate negotiation. XXX */ 377525944Sjoerg lcp.Up(sp); 377625944Sjoerg } 37774910Swollman } 377825944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 377925944Sjoerg ++sp->pp_alivecnt; 378025944Sjoerg if (sp->pp_flags & PP_CISCO) 378125944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 378225944Sjoerg sp->pp_rseq); 378325944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 378425944Sjoerg long nmagic = htonl (sp->lcp.magic); 378525944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 378625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 378725944Sjoerg sp->lcp.echoid, 4, &nmagic); 378825944Sjoerg } 37894910Swollman } 379025944Sjoerg splx(s); 379142064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 37924910Swollman} 37934910Swollman 379425944Sjoerg/* 379525944Sjoerg * Get both IP addresses. 379625944Sjoerg */ 379725944Sjoergstatic void 379830300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 379925944Sjoerg{ 380025944Sjoerg struct ifnet *ifp = &sp->pp_if; 380125944Sjoerg struct ifaddr *ifa; 380230300Sjoerg struct sockaddr_in *si, *sm; 380325944Sjoerg u_long ssrc, ddst; 380425944Sjoerg 380540010Sjoerg sm = NULL; 380625944Sjoerg ssrc = ddst = 0L; 380725944Sjoerg /* 380825944Sjoerg * Pick the first AF_INET address from the list, 380925944Sjoerg * aliases don't make any sense on a p2p link anyway. 381025944Sjoerg */ 381142065Sphk si = 0; 381242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 381342065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 381440008Sjoerg#else 381542065Sphk for (ifa = ifp->if_addrlist.tqh_first; 381640008Sjoerg ifa; 381740008Sjoerg ifa = ifa->ifa_list.tqe_next) 381840008Sjoerg#endif 381925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 382025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 382130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 382225944Sjoerg if (si) 382325944Sjoerg break; 382425944Sjoerg } 382525944Sjoerg if (ifa) { 382630300Sjoerg if (si && si->sin_addr.s_addr) { 382725944Sjoerg ssrc = si->sin_addr.s_addr; 382830300Sjoerg if (srcmask) 382930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 383030300Sjoerg } 383125944Sjoerg 383225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 383325944Sjoerg if (si && si->sin_addr.s_addr) 383425944Sjoerg ddst = si->sin_addr.s_addr; 383525944Sjoerg } 383625944Sjoerg 383725944Sjoerg if (dst) *dst = ntohl(ddst); 383825944Sjoerg if (src) *src = ntohl(ssrc); 383925944Sjoerg} 384025944Sjoerg 384125944Sjoerg/* 384225944Sjoerg * Set my IP address. Must be called at splimp. 384325944Sjoerg */ 384425944Sjoergstatic void 384525944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 384625944Sjoerg{ 384740010Sjoerg struct ifnet *ifp = &sp->pp_if; 384825944Sjoerg struct ifaddr *ifa; 384925944Sjoerg struct sockaddr_in *si; 385025944Sjoerg 385125944Sjoerg /* 385225944Sjoerg * Pick the first AF_INET address from the list, 385325944Sjoerg * aliases don't make any sense on a p2p link anyway. 385425944Sjoerg */ 385540008Sjoerg 385642065Sphk si = 0; 385742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 385842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 385940008Sjoerg#else 386042065Sphk for (ifa = ifp->if_addrlist.tqh_first; 386140008Sjoerg ifa; 386240008Sjoerg ifa = ifa->ifa_list.tqe_next) 386340008Sjoerg#endif 386440008Sjoerg { 386540008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 386640008Sjoerg { 386725944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 386825944Sjoerg if (si) 386925944Sjoerg break; 387025944Sjoerg } 387140008Sjoerg } 387240008Sjoerg 387325944Sjoerg if (ifa && si) 387425944Sjoerg si->sin_addr.s_addr = htonl(src); 387525944Sjoerg} 387625944Sjoerg 387730300Sjoergstatic int 387838343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 387930300Sjoerg{ 388038343Sbde u_long subcmd; 388130300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 388230300Sjoerg struct spppreq spr; 388330300Sjoerg 388430300Sjoerg /* 388530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 388630300Sjoerg * Check the cmd word first before attempting to fetch all the 388730300Sjoerg * data. 388830300Sjoerg */ 388930300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 389030300Sjoerg return EFAULT; 389130300Sjoerg 389230300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 389330300Sjoerg return EFAULT; 389430300Sjoerg 389530300Sjoerg switch (subcmd) { 389630300Sjoerg case SPPPIOGDEFS: 389730300Sjoerg if (cmd != SIOCGIFGENERIC) 389830300Sjoerg return EINVAL; 389930300Sjoerg /* 390030300Sjoerg * We copy over the entire current state, but clean 390130300Sjoerg * out some of the stuff we don't wanna pass up. 390230300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 390330300Sjoerg * called by any user. No need to ever get PAP or 390430300Sjoerg * CHAP secrets back to userland anyway. 390530300Sjoerg */ 390630300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 390730300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 390830300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 390930300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 391030300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 391130300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 391230300Sjoerg 391330300Sjoerg case SPPPIOSDEFS: 391430300Sjoerg if (cmd != SIOCSIFGENERIC) 391530300Sjoerg return EINVAL; 391630300Sjoerg /* 391730300Sjoerg * We have a very specific idea of which fields we allow 391830300Sjoerg * being passed back from userland, so to not clobber our 391930300Sjoerg * current state. For one, we only allow setting 392030300Sjoerg * anything if LCP is in dead phase. Once the LCP 392130300Sjoerg * negotiations started, the authentication settings must 392230300Sjoerg * not be changed again. (The administrator can force an 392330300Sjoerg * ifconfig down in order to get LCP back into dead 392430300Sjoerg * phase.) 392530300Sjoerg * 392630300Sjoerg * Also, we only allow for authentication parameters to be 392730300Sjoerg * specified. 392830300Sjoerg * 392930300Sjoerg * XXX Should allow to set or clear pp_flags. 393030300Sjoerg * 393130300Sjoerg * Finally, if the respective authentication protocol to 393230300Sjoerg * be used is set differently than 0, but the secret is 393330300Sjoerg * passed as all zeros, we don't trash the existing secret. 393430300Sjoerg * This allows an administrator to change the system name 393530300Sjoerg * only without clobbering the secret (which he didn't get 393630300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 393730300Sjoerg * secrets are cleared if the authentication protocol is 393830300Sjoerg * reset to 0. 393930300Sjoerg */ 394030300Sjoerg if (sp->pp_phase != PHASE_DEAD) 394130300Sjoerg return EBUSY; 394230300Sjoerg 394330300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 394430300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 394530300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 394630300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 394730300Sjoerg return EINVAL; 394830300Sjoerg 394930300Sjoerg if (spr.defs.myauth.proto == 0) 395030300Sjoerg /* resetting myauth */ 395130300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 395230300Sjoerg else { 395330300Sjoerg /* setting/changing myauth */ 395430300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 395530300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 395630300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 395730300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 395830300Sjoerg AUTHKEYLEN); 395930300Sjoerg } 396030300Sjoerg if (spr.defs.hisauth.proto == 0) 396130300Sjoerg /* resetting hisauth */ 396230300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 396330300Sjoerg else { 396430300Sjoerg /* setting/changing hisauth */ 396530300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 396630300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 396730300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 396830300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 396930300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 397030300Sjoerg AUTHKEYLEN); 397130300Sjoerg } 397230300Sjoerg break; 397330300Sjoerg 397430300Sjoerg default: 397530300Sjoerg return EINVAL; 397630300Sjoerg } 397730300Sjoerg 397830300Sjoerg return 0; 397930300Sjoerg} 398030300Sjoerg 398130300Sjoergstatic void 398230300Sjoergsppp_phase_network(struct sppp *sp) 398330300Sjoerg{ 398430300Sjoerg struct ifnet *ifp = &sp->pp_if; 398530300Sjoerg int i; 398630300Sjoerg u_long mask; 398730300Sjoerg 398830300Sjoerg sp->pp_phase = PHASE_NETWORK; 398930300Sjoerg 399040008Sjoerg log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 399130300Sjoerg sppp_phase_name(sp->pp_phase)); 399230300Sjoerg 399330300Sjoerg /* Notify NCPs now. */ 399430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 399530300Sjoerg if ((cps[i])->flags & CP_NCP) 399630300Sjoerg (cps[i])->Open(sp); 399730300Sjoerg 399830300Sjoerg /* Send Up events to all NCPs. */ 399930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 400030300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 400130300Sjoerg (cps[i])->Up(sp); 400230300Sjoerg 400330300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 400430300Sjoerg sppp_lcp_check_and_close(sp); 400530300Sjoerg} 400630300Sjoerg 400730300Sjoerg 400825706Sjoergstatic const char * 400925944Sjoergsppp_cp_type_name(u_char type) 40104910Swollman{ 401130300Sjoerg static char buf[12]; 40124910Swollman switch (type) { 401330300Sjoerg case CONF_REQ: return "conf-req"; 401430300Sjoerg case CONF_ACK: return "conf-ack"; 401530300Sjoerg case CONF_NAK: return "conf-nak"; 401630300Sjoerg case CONF_REJ: return "conf-rej"; 401730300Sjoerg case TERM_REQ: return "term-req"; 401830300Sjoerg case TERM_ACK: return "term-ack"; 401930300Sjoerg case CODE_REJ: return "code-rej"; 402030300Sjoerg case PROTO_REJ: return "proto-rej"; 402130300Sjoerg case ECHO_REQ: return "echo-req"; 402230300Sjoerg case ECHO_REPLY: return "echo-reply"; 402330300Sjoerg case DISC_REQ: return "discard-req"; 40244910Swollman } 402541514Sarchie snprintf (buf, sizeof(buf), "0x%x", type); 402630300Sjoerg return buf; 40274910Swollman} 40284910Swollman 402925706Sjoergstatic const char * 403030300Sjoergsppp_auth_type_name(u_short proto, u_char type) 403130300Sjoerg{ 403230300Sjoerg static char buf[12]; 403330300Sjoerg switch (proto) { 403430300Sjoerg case PPP_CHAP: 403530300Sjoerg switch (type) { 403630300Sjoerg case CHAP_CHALLENGE: return "challenge"; 403730300Sjoerg case CHAP_RESPONSE: return "response"; 403830300Sjoerg case CHAP_SUCCESS: return "success"; 403930300Sjoerg case CHAP_FAILURE: return "failure"; 404030300Sjoerg } 404130300Sjoerg case PPP_PAP: 404230300Sjoerg switch (type) { 404330300Sjoerg case PAP_REQ: return "req"; 404430300Sjoerg case PAP_ACK: return "ack"; 404530300Sjoerg case PAP_NAK: return "nak"; 404630300Sjoerg } 404730300Sjoerg } 404841514Sarchie snprintf (buf, sizeof(buf), "0x%x", type); 404930300Sjoerg return buf; 405030300Sjoerg} 405130300Sjoerg 405230300Sjoergstatic const char * 405325944Sjoergsppp_lcp_opt_name(u_char opt) 40544910Swollman{ 405530300Sjoerg static char buf[12]; 405625944Sjoerg switch (opt) { 405730300Sjoerg case LCP_OPT_MRU: return "mru"; 405830300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 405930300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 406030300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 406130300Sjoerg case LCP_OPT_MAGIC: return "magic"; 406230300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 406330300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 40644910Swollman } 406541514Sarchie snprintf (buf, sizeof(buf), "0x%x", opt); 406630300Sjoerg return buf; 40674910Swollman} 40684910Swollman 406925944Sjoergstatic const char * 407025944Sjoergsppp_ipcp_opt_name(u_char opt) 407125944Sjoerg{ 407230300Sjoerg static char buf[12]; 407325944Sjoerg switch (opt) { 407430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 407530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 407630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 407725944Sjoerg } 407841514Sarchie snprintf (buf, sizeof(buf), "0x%x", opt); 407930300Sjoerg return buf; 408025944Sjoerg} 408125944Sjoerg 408225944Sjoergstatic const char * 408325944Sjoergsppp_state_name(int state) 408425944Sjoerg{ 408525944Sjoerg switch (state) { 408625944Sjoerg case STATE_INITIAL: return "initial"; 408725944Sjoerg case STATE_STARTING: return "starting"; 408825944Sjoerg case STATE_CLOSED: return "closed"; 408925944Sjoerg case STATE_STOPPED: return "stopped"; 409025944Sjoerg case STATE_CLOSING: return "closing"; 409125944Sjoerg case STATE_STOPPING: return "stopping"; 409225944Sjoerg case STATE_REQ_SENT: return "req-sent"; 409325944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 409425944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 409525944Sjoerg case STATE_OPENED: return "opened"; 409625944Sjoerg } 409725944Sjoerg return "illegal"; 409825944Sjoerg} 409925944Sjoerg 410025944Sjoergstatic const char * 410125944Sjoergsppp_phase_name(enum ppp_phase phase) 410225944Sjoerg{ 410325944Sjoerg switch (phase) { 410425944Sjoerg case PHASE_DEAD: return "dead"; 410525944Sjoerg case PHASE_ESTABLISH: return "establish"; 410625944Sjoerg case PHASE_TERMINATE: return "terminate"; 410725944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 410825944Sjoerg case PHASE_NETWORK: return "network"; 410925944Sjoerg } 411025944Sjoerg return "illegal"; 411125944Sjoerg} 411225944Sjoerg 411325944Sjoergstatic const char * 411425944Sjoergsppp_proto_name(u_short proto) 411525944Sjoerg{ 411625944Sjoerg static char buf[12]; 411725944Sjoerg switch (proto) { 411825944Sjoerg case PPP_LCP: return "lcp"; 411925944Sjoerg case PPP_IPCP: return "ipcp"; 412030300Sjoerg case PPP_PAP: return "pap"; 412130300Sjoerg case PPP_CHAP: return "chap"; 412225944Sjoerg } 412341514Sarchie snprintf(buf, sizeof(buf), "0x%x", (unsigned)proto); 412425944Sjoerg return buf; 412525944Sjoerg} 412625944Sjoerg 412712820Sphkstatic void 412830300Sjoergsppp_print_bytes(const u_char *p, u_short len) 41294910Swollman{ 413040008Sjoerg addlog(" %02x", *p++); 41314910Swollman while (--len > 0) 413240008Sjoerg addlog("-%02x", *p++); 41334910Swollman} 413425944Sjoerg 413530300Sjoergstatic void 413630300Sjoergsppp_print_string(const char *p, u_short len) 413730300Sjoerg{ 413830300Sjoerg u_char c; 413930300Sjoerg 414030300Sjoerg while (len-- > 0) { 414130300Sjoerg c = *p++; 414230300Sjoerg /* 414330300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 414430300Sjoerg * using only them, but we don't rely on it. */ 414530300Sjoerg if (c < ' ' || c > '~') 414630300Sjoerg addlog("\\x%x", c); 414730300Sjoerg else 414830300Sjoerg addlog("%c", c); 414930300Sjoerg } 415030300Sjoerg} 415130300Sjoerg 415230300Sjoergstatic const char * 415330300Sjoergsppp_dotted_quad(u_long addr) 415430300Sjoerg{ 415530300Sjoerg static char s[16]; 415630300Sjoerg sprintf(s, "%d.%d.%d.%d", 415740008Sjoerg (int)((addr >> 24) & 0xff), 415840008Sjoerg (int)((addr >> 16) & 0xff), 415940008Sjoerg (int)((addr >> 8) & 0xff), 416038372Sbde (int)(addr & 0xff)); 416130300Sjoerg return s; 416230300Sjoerg} 416330300Sjoerg 416430300Sjoergstatic int 416530300Sjoergsppp_strnlen(u_char *p, int max) 416630300Sjoerg{ 416730300Sjoerg int len; 416830300Sjoerg 416930300Sjoerg for (len = 0; len < max && *p; ++p) 417030300Sjoerg ++len; 417130300Sjoerg return len; 417230300Sjoerg} 417330300Sjoerg 417430300Sjoerg/* a dummy, used to drop uninteresting events */ 417530300Sjoergstatic void 417630300Sjoergsppp_null(struct sppp *unused) 417730300Sjoerg{ 417830300Sjoerg /* do just nothing */ 417930300Sjoerg} 418025944Sjoerg/* 418125944Sjoerg * This file is large. Tell emacs to highlight it nevertheless. 418225944Sjoerg * 418325944Sjoerg * Local Variables: 418430300Sjoerg * hilit-auto-highlight-maxout: 120000 418525944Sjoerg * End: 418625944Sjoerg */ 4187