if_spppsubr.c revision 194951
14910Swollman/* 2139365Srik * Synchronous PPP/Cisco/Frame Relay link level subroutines. 34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes. 4139823Simp */ 5139823Simp/*- 6139365Srik * Copyright (C) 1994-2000 Cronyx Engineering. 725944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru> 84910Swollman * 925944Sjoerg * Heavily revamped to conform to RFC 1661. 1088534Sjoerg * Copyright (C) 1997, 2001 Joerg Wunsch. 1125944Sjoerg * 124910Swollman * This software is distributed with NO WARRANTIES, not even the implied 134910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 144910Swollman * 154910Swollman * Authors grant any other persons or organisations permission to use 164910Swollman * or modify this software as long as this message is kept with the software, 174910Swollman * all derivative works or modified versions. 184910Swollman * 1930300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 2016288Sgpalmer * 2150477Speter * $FreeBSD: head/sys/net/if_spppsubr.c 194951 2009-06-25 11:52:33Z rwatson $ 224910Swollman */ 234910Swollman 2440008Sjoerg#include <sys/param.h> 2540008Sjoerg 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2931742Seivind 304952Sbde#include <sys/systm.h> 314952Sbde#include <sys/kernel.h> 3270199Sjhay#include <sys/module.h> 3324204Sbde#include <sys/sockio.h> 344910Swollman#include <sys/socket.h> 3525706Sjoerg#include <sys/syslog.h> 3659604Sobrien#include <sys/random.h> 3729024Sbde#include <sys/malloc.h> 384910Swollman#include <sys/mbuf.h> 39181803Sbz#include <sys/vimage.h> 4040008Sjoerg 4130300Sjoerg#include <sys/md5.h> 424910Swollman 434910Swollman#include <net/if.h> 444910Swollman#include <net/netisr.h> 454910Swollman#include <net/if_types.h> 4642104Sphk#include <net/route.h> 4788534Sjoerg#include <netinet/in.h> 4888534Sjoerg#include <netinet/in_systm.h> 4988534Sjoerg#include <netinet/ip.h> 5088534Sjoerg#include <net/slcompress.h> 514910Swollman 5230300Sjoerg#include <machine/stdarg.h> 5330300Sjoerg 544910Swollman#include <netinet/in_var.h> 5588705Sjoerg 5688705Sjoerg#ifdef INET 574910Swollman#include <netinet/ip.h> 584910Swollman#include <netinet/tcp.h> 59185571Sbz#include <netinet/vinet.h> 604910Swollman#endif 614910Swollman 62148385Sume#ifdef INET6 63148385Sume#include <netinet6/scope6_var.h> 64148385Sume#endif 65148385Sume 66182121Simp#include <netinet/if_ether.h> 6788705Sjoerg 6811819Sjulian#ifdef IPX 6911819Sjulian#include <netipx/ipx.h> 7011819Sjulian#include <netipx/ipx_if.h> 7111819Sjulian#endif 7211819Sjulian 734910Swollman#include <net/if_sppp.h> 744910Swollman 75182121Simp#define IOCTL_CMD_T u_long 764910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 774910Swollman 7825944Sjoerg/* 7925944Sjoerg * Interface flags that can be set in an ifconfig command. 8025944Sjoerg * 8125955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 8225944Sjoerg * as being administrative openable, but won't be opened to begin 8325944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 8425944Sjoerg * -link1 will cause the administrative open of the LCP layer. 8525955Sjoerg * 8625955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 8725955Sjoerg * arrive to be sent. 8830300Sjoerg * 8930300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 9030300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 9130300Sjoerg * like 9230300Sjoerg * 9330300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 9430300Sjoerg * 9530300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 9630300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 9725944Sjoerg */ 9825944Sjoerg 9925955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 10025955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 10145152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 10225944Sjoerg 10330300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 10430300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 10530300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 10630300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 10730300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 10830300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 10988534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 11088534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 11178064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 11230300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 11330300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 11430300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 11530300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 11678064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1174910Swollman 11825944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 11925944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 12025944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 12125944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 12225944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 12325944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 12425944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 12525944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 12625944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 12725944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 12825944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1294910Swollman 13030300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 13130300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 13230300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 13330300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 13430300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 13530300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 13630300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 13730300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1384910Swollman 13925944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 14025944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 14125944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1424910Swollman 14378064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 14478064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 14578064Sume 14688534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 14788534Sjoerg 14830300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 14930300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 15030300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1514910Swollman 15230300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 15330300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 15430300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 15530300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 15630300Sjoerg 15730300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 15830300Sjoerg 15930300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 16030300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 16130300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 16230300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 16330300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 16430300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 16530300Sjoerg 16625944Sjoerg/* states are named and numbered according to RFC 1661 */ 16725944Sjoerg#define STATE_INITIAL 0 16825944Sjoerg#define STATE_STARTING 1 16925944Sjoerg#define STATE_CLOSED 2 17025944Sjoerg#define STATE_STOPPED 3 17125944Sjoerg#define STATE_CLOSING 4 17225944Sjoerg#define STATE_STOPPING 5 17325944Sjoerg#define STATE_REQ_SENT 6 17425944Sjoerg#define STATE_ACK_RCVD 7 17525944Sjoerg#define STATE_ACK_SENT 8 17625944Sjoerg#define STATE_OPENED 9 17725944Sjoerg 178147256SbrooksMALLOC_DEFINE(M_SPPP, "sppp", "synchronous PPP interface internals"); 179147256Sbrooks 1804910Swollmanstruct ppp_header { 18111189Sjkh u_char address; 18211189Sjkh u_char control; 18311189Sjkh u_short protocol; 184103842Salfred} __packed; 1854910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1864910Swollman 1874910Swollmanstruct lcp_header { 18811189Sjkh u_char type; 18911189Sjkh u_char ident; 19011189Sjkh u_short len; 191103842Salfred} __packed; 1924910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1934910Swollman 1944910Swollmanstruct cisco_packet { 19511189Sjkh u_long type; 19611189Sjkh u_long par1; 19711189Sjkh u_long par2; 19811189Sjkh u_short rel; 19911189Sjkh u_short time0; 20011189Sjkh u_short time1; 201103842Salfred} __packed; 20288704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 2034910Swollman 20425944Sjoerg/* 20525944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 20625944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 20725944Sjoerg * case you can't make sense out of these abbreviation; it will also 20825944Sjoerg * explain the semantics related to the various events and actions. 20925944Sjoerg */ 21025944Sjoergstruct cp { 21125944Sjoerg u_short proto; /* PPP control protocol number */ 21225944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 21325944Sjoerg u_char flags; 21425944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 21525944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 21625944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 21725944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 21825944Sjoerg const char *name; /* name of this control protocol */ 21925944Sjoerg /* event handlers */ 22025944Sjoerg void (*Up)(struct sppp *sp); 22125944Sjoerg void (*Down)(struct sppp *sp); 22225944Sjoerg void (*Open)(struct sppp *sp); 22325944Sjoerg void (*Close)(struct sppp *sp); 22425944Sjoerg void (*TO)(void *sp); 22525944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 22625944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 22725944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 22825944Sjoerg /* actions */ 22925944Sjoerg void (*tlu)(struct sppp *sp); 23025944Sjoerg void (*tld)(struct sppp *sp); 23125944Sjoerg void (*tls)(struct sppp *sp); 23225944Sjoerg void (*tlf)(struct sppp *sp); 23325944Sjoerg void (*scr)(struct sppp *sp); 23425944Sjoerg}; 23525944Sjoerg 23640008Sjoerg#define SPP_FMT "%s: " 23740008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 23840008Sjoerg 239188668Srwatson#define SPPP_LOCK(sp) mtx_lock (&(sp)->mtx) 240188668Srwatson#define SPPP_UNLOCK(sp) mtx_unlock (&(sp)->mtx) 241188668Srwatson#define SPPP_LOCK_ASSERT(sp) mtx_assert (&(sp)->mtx, MA_OWNED) 242190818Sed#define SPPP_LOCK_OWNED(sp) mtx_owned (&(sp)->mtx) 243138745Srik 24488705Sjoerg#ifdef INET 2454910Swollman/* 2464910Swollman * The following disgusting hack gets around the problem that IP TOS 2474910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2484910Swollman * priority queue. To decide if traffic is interactive, we check that 2494910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 25030300Sjoerg * 25130300Sjoerg * XXX is this really still necessary? - joerg - 2524910Swollman */ 253126910Srwatsonstatic const u_short interactive_ports[8] = { 2544910Swollman 0, 513, 0, 0, 2554910Swollman 0, 21, 0, 23, 2564910Swollman}; 2574910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 25888705Sjoerg#endif 2594910Swollman 26025944Sjoerg/* almost every function needs these */ 26125944Sjoerg#define STDDCL \ 262147256Sbrooks struct ifnet *ifp = SP2IFP(sp); \ 26325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 26411189Sjkh 26530300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 266191148Skmacy struct sockaddr *dst, struct route *ro); 2674910Swollman 26825944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 26925944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 27025944Sjoerg 27125944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 27225944Sjoerg struct mbuf *m); 27325944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 27425944Sjoerg u_char ident, u_short len, void *data); 27542104Sphk/* static void sppp_cp_timeout(void *arg); */ 27625944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 27725944Sjoerg int newstate); 27830300Sjoergstatic void sppp_auth_send(const struct cp *cp, 27942104Sphk struct sppp *sp, unsigned int type, unsigned int id, 28030300Sjoerg ...); 28125944Sjoerg 28225944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 28325944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 28425944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 28525944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 28625944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 28725944Sjoerg 28830300Sjoergstatic void sppp_null(struct sppp *sp); 28930300Sjoerg 290138745Srikstatic void sppp_pp_up(struct sppp *sp); 291138745Srikstatic void sppp_pp_down(struct sppp *sp); 292138745Srik 29325944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 29425944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 29525944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 29625944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 29725944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 29825944Sjoergstatic void sppp_lcp_TO(void *sp); 29925944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 30025944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 30125944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 30225944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 30325944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 30425944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 30525944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 30625944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 30730300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 30830300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 30925944Sjoerg 31025944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 31125944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 31225944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 31325944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 31425944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 31525944Sjoergstatic void sppp_ipcp_TO(void *sp); 31625944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31725944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31825944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 31925944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 32025944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 32125944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 32225944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 32325944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 32425944Sjoerg 32578064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 32678064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 32778064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 32878064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 32978064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 33078064Sumestatic void sppp_ipv6cp_TO(void *sp); 33178064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33278064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33378064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33478064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 33578064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 33678064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 33778064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 33878064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 33978064Sume 34030300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 34130300Sjoergstatic void sppp_pap_init(struct sppp *sp); 34230300Sjoergstatic void sppp_pap_open(struct sppp *sp); 34330300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34430300Sjoergstatic void sppp_pap_TO(void *sp); 34530300Sjoergstatic void sppp_pap_my_TO(void *sp); 34630300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 34730300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 34830300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 34930300Sjoerg 35030300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 35130300Sjoergstatic void sppp_chap_init(struct sppp *sp); 35230300Sjoergstatic void sppp_chap_open(struct sppp *sp); 35330300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35430300Sjoergstatic void sppp_chap_TO(void *sp); 35530300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35630300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 35730300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 35830300Sjoerg 35930300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 36025944Sjoergstatic const char *sppp_cp_type_name(u_char type); 361184682Sbz#ifdef INET 36230300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 36330300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 364184682Sbz#endif 36578064Sume#ifdef INET6 36678064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 36778064Sume#endif 36825944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36925944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 37025944Sjoergstatic const char *sppp_proto_name(u_short proto); 37130300Sjoergstatic const char *sppp_state_name(int state); 37238343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37330300Sjoergstatic int sppp_strnlen(u_char *p, int max); 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); 379184682Sbz#ifdef INET 38025944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 381184682Sbz#endif 38278064Sume#ifdef INET6 38378064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 38478064Sume struct in6_addr *dst, struct in6_addr *srcmask); 38578064Sume#ifdef IPV6CP_MYIFID_DYN 38678064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38778064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38878064Sume#endif 38978064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 39078064Sume#endif 39125944Sjoerg 392138745Srik/* if_start () wrapper */ 393138745Srikstatic void sppp_ifstart (struct ifnet *ifp); 394138745Srik 39525944Sjoerg/* our control protocol descriptors */ 39633181Seivindstatic const struct cp lcp = { 39725944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 39825944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 39925944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 40025944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 40125944Sjoerg sppp_lcp_scr 40225944Sjoerg}; 40325944Sjoerg 40433181Seivindstatic const struct cp ipcp = { 40588709Sjoerg PPP_IPCP, IDX_IPCP, 40688709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 40788709Sjoerg CP_NCP, 40888709Sjoerg#else 40988709Sjoerg 0, 41088709Sjoerg#endif 41188709Sjoerg "ipcp", 41225944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 41325944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 41425944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 41525944Sjoerg sppp_ipcp_scr 41625944Sjoerg}; 41725944Sjoerg 41878064Sumestatic const struct cp ipv6cp = { 41978064Sume PPP_IPV6CP, IDX_IPV6CP, 42078064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 42178064Sume CP_NCP, 42278064Sume#else 42378064Sume 0, 42478064Sume#endif 42578064Sume "ipv6cp", 42678064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 42778064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 42878064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 42978064Sume sppp_ipv6cp_scr 43078064Sume}; 43178064Sume 43233181Seivindstatic const struct cp pap = { 43330300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 43430300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 43530300Sjoerg sppp_pap_TO, 0, 0, 0, 43630300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 43730300Sjoerg sppp_pap_scr 43830300Sjoerg}; 43930300Sjoerg 44033181Seivindstatic const struct cp chap = { 44130300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 44230300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 44330300Sjoerg sppp_chap_TO, 0, 0, 0, 44430300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 44530300Sjoerg sppp_chap_scr 44630300Sjoerg}; 44730300Sjoerg 44833181Seivindstatic const struct cp *cps[IDX_COUNT] = { 44925944Sjoerg &lcp, /* IDX_LCP */ 45025944Sjoerg &ipcp, /* IDX_IPCP */ 45178064Sume &ipv6cp, /* IDX_IPV6CP */ 45230300Sjoerg &pap, /* IDX_PAP */ 45330300Sjoerg &chap, /* IDX_CHAP */ 45425944Sjoerg}; 45525944Sjoerg 456147256Sbrooksstatic void* 457147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp) 458147256Sbrooks{ 459147256Sbrooks struct sppp *sp; 460147256Sbrooks 461147256Sbrooks sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO); 462147256Sbrooks sp->pp_ifp = ifp; 463147256Sbrooks 464147256Sbrooks return (sp); 465147256Sbrooks} 466147256Sbrooks 467147256Sbrooksstatic void 468147256Sbrookssppp_free(void *com, u_char type) 469147256Sbrooks{ 470147256Sbrooks 471147256Sbrooks free(com, M_SPPP); 472147256Sbrooks} 473147256Sbrooks 47470199Sjhaystatic int 47570199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47670199Sjhay{ 47770199Sjhay switch (type) { 47870199Sjhay case MOD_LOAD: 479147256Sbrooks /* 480147256Sbrooks * XXX: should probably be IFT_SPPP, but it's fairly 481147256Sbrooks * harmless to allocate struct sppp's for non-sppp 482147256Sbrooks * interfaces. 483147256Sbrooks */ 484147256Sbrooks 485147256Sbrooks if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free); 48670199Sjhay break; 48770199Sjhay case MOD_UNLOAD: 488147256Sbrooks /* if_deregister_com_alloc(IFT_PPP); */ 48970199Sjhay return EACCES; 49070199Sjhay default: 491132199Sphk return EOPNOTSUPP; 49270199Sjhay } 49370199Sjhay return 0; 49470199Sjhay} 49570199Sjhaystatic moduledata_t spppmod = { 49670199Sjhay "sppp", 49770199Sjhay sppp_modevent, 49870199Sjhay 0 49970199Sjhay}; 50070199SjhayMODULE_VERSION(sppp, 1); 50170199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 50225944Sjoerg 50370199Sjhay/* 50425944Sjoerg * Exported functions, comprising our interface to the lower layer. 5054910Swollman */ 5064910Swollman 5074910Swollman/* 5084910Swollman * Process the received packet. 5094910Swollman */ 51025706Sjoergvoid 51125706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5124910Swollman{ 5134910Swollman struct ppp_header *h; 514111888Sjlemon int isr = -1; 515147256Sbrooks struct sppp *sp = IFP2SP(ifp); 516184682Sbz int debug, do_account = 0; 517184682Sbz#ifdef INET 518184682Sbz int hlen, vjlen; 51988700Sjoerg u_char *iphdr; 520184682Sbz#endif 5214910Swollman 522138745Srik SPPP_LOCK(sp); 523138745Srik debug = ifp->if_flags & IFF_DEBUG; 524138745Srik 5254910Swollman if (ifp->if_flags & IFF_UP) 5264910Swollman /* Count received bytes, add FCS and one flag */ 5274910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5284910Swollman 5294910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5304910Swollman /* Too small packet, drop it. */ 53125944Sjoerg if (debug) 53225706Sjoerg log(LOG_DEBUG, 53340008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 53440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 53525944Sjoerg drop: 53688700Sjoerg m_freem (m); 537138745Srik SPPP_UNLOCK(sp); 53888700Sjoerg drop2: 53925944Sjoerg ++ifp->if_ierrors; 54025944Sjoerg ++ifp->if_iqdrops; 5414910Swollman return; 5424910Swollman } 5434910Swollman 544139365Srik if (sp->pp_mode == PP_FR) { 545139365Srik sppp_fr_input (sp, m); 546139365Srik SPPP_UNLOCK(sp); 547139365Srik return; 548139365Srik } 549139365Srik 5504910Swollman /* Get PPP header. */ 5514910Swollman h = mtod (m, struct ppp_header*); 5524910Swollman m_adj (m, PPP_HEADER_LEN); 5534910Swollman 5544910Swollman switch (h->address) { 5554910Swollman case PPP_ALLSTATIONS: 5564910Swollman if (h->control != PPP_UI) 5574910Swollman goto invalid; 55845152Sphk if (sp->pp_mode == IFF_CISCO) { 55925944Sjoerg if (debug) 56025706Sjoerg log(LOG_DEBUG, 56140008Sjoerg SPP_FMT "PPP packet in Cisco mode " 56225706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 56340008Sjoerg SPP_ARGS(ifp), 56425706Sjoerg h->address, h->control, ntohs(h->protocol)); 56511189Sjkh goto drop; 56611189Sjkh } 5674910Swollman switch (ntohs (h->protocol)) { 5684910Swollman default: 56925944Sjoerg if (debug) 57025706Sjoerg log(LOG_DEBUG, 57144145Sphk SPP_FMT "rejecting protocol " 57225706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 57340008Sjoerg SPP_ARGS(ifp), 57425706Sjoerg h->address, h->control, ntohs(h->protocol)); 57544145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 57644145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 57778064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 57844145Sphk &h->protocol); 5794910Swollman ++ifp->if_noproto; 5804910Swollman goto drop; 5814910Swollman case PPP_LCP: 58230300Sjoerg sppp_cp_input(&lcp, sp, m); 5834910Swollman m_freem (m); 584138745Srik SPPP_UNLOCK(sp); 5854910Swollman return; 58630300Sjoerg case PPP_PAP: 58730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 58830300Sjoerg sppp_pap_input(sp, m); 58930300Sjoerg m_freem (m); 590138745Srik SPPP_UNLOCK(sp); 59130300Sjoerg return; 59230300Sjoerg case PPP_CHAP: 59330300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 59430300Sjoerg sppp_chap_input(sp, m); 59530300Sjoerg m_freem (m); 596138745Srik SPPP_UNLOCK(sp); 59730300Sjoerg return; 5984910Swollman#ifdef INET 5994910Swollman case PPP_IPCP: 60025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 60130300Sjoerg sppp_cp_input(&ipcp, sp, m); 6024910Swollman m_freem (m); 603138745Srik SPPP_UNLOCK(sp); 6044910Swollman return; 6054910Swollman case PPP_IP: 60625944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 607111888Sjlemon isr = NETISR_IP; 6084910Swollman } 60988577Sjoerg do_account++; 6104910Swollman break; 61188534Sjoerg case PPP_VJ_COMP: 61288534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 61388700Sjoerg if ((vjlen = 61488700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 61588700Sjoerg m->m_len, m->m_len, 61688700Sjoerg TYPE_COMPRESSED_TCP, 61788700Sjoerg sp->pp_comp, 61888700Sjoerg &iphdr, &hlen)) <= 0) { 61988700Sjoerg if (debug) 62088700Sjoerg log(LOG_INFO, 62188700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 62288700Sjoerg SPP_ARGS(ifp)); 62388534Sjoerg goto drop; 62488700Sjoerg } 62588700Sjoerg 62688700Sjoerg /* 62788700Sjoerg * Trim the VJ header off the packet, and prepend 62888700Sjoerg * the uncompressed IP header (which will usually 62988700Sjoerg * end up in two chained mbufs since there's not 63088700Sjoerg * enough leading space in the existing mbuf). 63188700Sjoerg */ 63288700Sjoerg m_adj(m, vjlen); 633111119Simp M_PREPEND(m, hlen, M_DONTWAIT); 634138745Srik if (m == NULL) { 635138745Srik SPPP_UNLOCK(sp); 63688700Sjoerg goto drop2; 637138745Srik } 63888700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 639111888Sjlemon isr = NETISR_IP; 64088534Sjoerg } 64188599Sjoerg do_account++; 64288534Sjoerg break; 64388534Sjoerg case PPP_VJ_UCOMP: 64488534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 64588700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 64688700Sjoerg m->m_len, m->m_len, 64788700Sjoerg TYPE_UNCOMPRESSED_TCP, 64888700Sjoerg sp->pp_comp, 64988700Sjoerg &iphdr, &hlen) != 0) { 65088700Sjoerg if (debug) 65188700Sjoerg log(LOG_INFO, 65288700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 65388700Sjoerg SPP_ARGS(ifp)); 65488534Sjoerg goto drop; 65588700Sjoerg } 656111888Sjlemon isr = NETISR_IP; 65788534Sjoerg } 65888599Sjoerg do_account++; 65988534Sjoerg break; 66078064Sume#endif 66188599Sjoerg#ifdef INET6 66288599Sjoerg case PPP_IPV6CP: 66388599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 66488599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 66588599Sjoerg m_freem (m); 666138745Srik SPPP_UNLOCK(sp); 66788599Sjoerg return; 66888599Sjoerg 66988599Sjoerg case PPP_IPV6: 670111888Sjlemon if (sp->state[IDX_IPV6CP] == STATE_OPENED) 671111888Sjlemon isr = NETISR_IPV6; 67288599Sjoerg do_account++; 67388599Sjoerg break; 67488599Sjoerg#endif 67512495Speter#ifdef IPX 67612495Speter case PPP_IPX: 67712495Speter /* IPX IPXCP not implemented yet */ 678111888Sjlemon if (sp->pp_phase == PHASE_NETWORK) 679111888Sjlemon isr = NETISR_IPX; 68088577Sjoerg do_account++; 68112495Speter break; 68212495Speter#endif 6834910Swollman } 6844910Swollman break; 6854910Swollman case CISCO_MULTICAST: 6864910Swollman case CISCO_UNICAST: 6874910Swollman /* Don't check the control field here (RFC 1547). */ 68845152Sphk if (sp->pp_mode != IFF_CISCO) { 68925944Sjoerg if (debug) 69025706Sjoerg log(LOG_DEBUG, 69140008Sjoerg SPP_FMT "Cisco packet in PPP mode " 69225706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 69340008Sjoerg SPP_ARGS(ifp), 69425706Sjoerg h->address, h->control, ntohs(h->protocol)); 69511189Sjkh goto drop; 69611189Sjkh } 6974910Swollman switch (ntohs (h->protocol)) { 6984910Swollman default: 6994910Swollman ++ifp->if_noproto; 7004910Swollman goto invalid; 7014910Swollman case CISCO_KEEPALIVE: 702147256Sbrooks sppp_cisco_input (sp, m); 7034910Swollman m_freem (m); 704138745Srik SPPP_UNLOCK(sp); 7054910Swollman return; 7064910Swollman#ifdef INET 7074910Swollman case ETHERTYPE_IP: 708111888Sjlemon isr = NETISR_IP; 70988577Sjoerg do_account++; 7104910Swollman break; 7114910Swollman#endif 71254263Sshin#ifdef INET6 71354263Sshin case ETHERTYPE_IPV6: 714111888Sjlemon isr = NETISR_IPV6; 71588577Sjoerg do_account++; 71654263Sshin break; 71754263Sshin#endif 71812495Speter#ifdef IPX 71912495Speter case ETHERTYPE_IPX: 720111888Sjlemon isr = NETISR_IPX; 72188577Sjoerg do_account++; 72212495Speter break; 72312495Speter#endif 7244910Swollman } 7254910Swollman break; 72625944Sjoerg default: /* Invalid PPP packet. */ 72725944Sjoerg invalid: 72825944Sjoerg if (debug) 72925944Sjoerg log(LOG_DEBUG, 73040008Sjoerg SPP_FMT "invalid input packet " 73125944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 73240008Sjoerg SPP_ARGS(ifp), 73325944Sjoerg h->address, h->control, ntohs(h->protocol)); 73425944Sjoerg goto drop; 7354910Swollman } 7364910Swollman 737111888Sjlemon if (! (ifp->if_flags & IFF_UP) || isr == -1) 7384910Swollman goto drop; 7394910Swollman 740138745Srik SPPP_UNLOCK(sp); 7414910Swollman /* Check queue. */ 742134391Sandre if (netisr_queue(isr, m)) { /* (0) on success. */ 74325944Sjoerg if (debug) 74440008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 74540008Sjoerg SPP_ARGS(ifp)); 746131241Srik goto drop2; 7474910Swollman } 748138745Srik 74988577Sjoerg if (do_account) 75088577Sjoerg /* 75188577Sjoerg * Do only account for network packets, not for control 75288577Sjoerg * packets. This is used by some subsystems to detect 75388577Sjoerg * idle lines. 75488577Sjoerg */ 755150349Sandre sp->pp_last_recv = time_uptime; 7564910Swollman} 7574910Swollman 758138745Srikstatic void 759138745Sriksppp_ifstart_sched(void *dummy) 760138745Srik{ 761138745Srik struct sppp *sp = dummy; 762138745Srik 763147256Sbrooks sp->if_start(SP2IFP(sp)); 764138745Srik} 765138745Srik 766138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for 767138745Srik * execution. We can't call it directly 768138745Srik */ 769138745Srikstatic void 770138745Sriksppp_ifstart(struct ifnet *ifp) 771138745Srik{ 772147256Sbrooks struct sppp *sp = IFP2SP(ifp); 773138745Srik 774138745Srik if (SPPP_LOCK_OWNED(sp)) { 775138745Srik if (callout_pending(&sp->ifstart_callout)) 776138745Srik return; 777138745Srik callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched, 778138745Srik (void *)sp); 779138745Srik } else { 780138745Srik sp->if_start(ifp); 781138745Srik } 782138745Srik} 783138745Srik 7844910Swollman/* 7854910Swollman * Enqueue transmit packet. 7864910Swollman */ 78712820Sphkstatic int 78825706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 789191148Skmacy struct sockaddr *dst, struct route *ro) 7904910Swollman{ 791147256Sbrooks struct sppp *sp = IFP2SP(ifp); 7924910Swollman struct ppp_header *h; 79378064Sume struct ifqueue *ifq = NULL; 794130549Smlaier int s, error, rv = 0; 795184682Sbz#ifdef INET 79688534Sjoerg int ipproto = PPP_IP; 797184682Sbz#endif 79842066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7994910Swollman 80025944Sjoerg s = splimp(); 801138745Srik SPPP_LOCK(sp); 80225944Sjoerg 803148887Srwatson if (!(ifp->if_flags & IFF_UP) || 804148887Srwatson (!(ifp->if_flags & IFF_AUTO) && 805148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING))) { 80688723Sjoerg#ifdef INET6 80788723Sjoerg drop: 80888723Sjoerg#endif 8094910Swollman m_freem (m); 810138745Srik SPPP_UNLOCK(sp); 8114910Swollman splx (s); 8124910Swollman return (ENETDOWN); 8134910Swollman } 8144910Swollman 815148887Srwatson if ((ifp->if_flags & IFF_AUTO) && 816148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 81788723Sjoerg#ifdef INET6 81825944Sjoerg /* 81988723Sjoerg * XXX 82088723Sjoerg * 82188723Sjoerg * Hack to prevent the initialization-time generated 82288723Sjoerg * IPv6 multicast packet to erroneously cause a 82388723Sjoerg * dialout event in case IPv6 has been 82488723Sjoerg * administratively disabled on that interface. 82588723Sjoerg */ 82688723Sjoerg if (dst->sa_family == AF_INET6 && 82788723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 82888723Sjoerg goto drop; 82988723Sjoerg#endif 83088723Sjoerg /* 83125944Sjoerg * Interface is not yet running, but auto-dial. Need 83225944Sjoerg * to start LCP for it. 83325944Sjoerg */ 834148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 83525944Sjoerg splx(s); 83625944Sjoerg lcp.Open(sp); 83725944Sjoerg s = splimp(); 83825944Sjoerg } 83925944Sjoerg 8404910Swollman#ifdef INET 84112436Speter if (dst->sa_family == AF_INET) { 84240008Sjoerg /* XXX Check mbuf length here? */ 84312436Speter struct ip *ip = mtod (m, struct ip*); 84412436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8454910Swollman 84642104Sphk /* 84742104Sphk * When using dynamic local IP address assignment by using 84842104Sphk * 0.0.0.0 as a local address, the first TCP session will 84942104Sphk * not connect because the local TCP checksum is computed 85042104Sphk * using 0.0.0.0 which will later become our real IP address 85142104Sphk * so the TCP checksum computed at the remote end will 85242104Sphk * become invalid. So we 85342104Sphk * - don't let packets with src ip addr 0 thru 85442104Sphk * - we flag TCP packets with src ip 0 as an error 85570199Sjhay */ 85642104Sphk 85742104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 85842104Sphk { 85942104Sphk m_freem(m); 860138745Srik SPPP_UNLOCK(sp); 86142104Sphk splx(s); 86242104Sphk if(ip->ip_p == IPPROTO_TCP) 86342104Sphk return(EADDRNOTAVAIL); 86442104Sphk else 86542104Sphk return(0); 86642104Sphk } 86770199Sjhay 86842104Sphk /* 86942104Sphk * Put low delay, telnet, rlogin and ftp control packets 870130549Smlaier * in front of the queue or let ALTQ take care. 87142104Sphk */ 872130549Smlaier if (ALTQ_IS_ENABLED(&ifp->if_snd)) 87341686Sphk ; 874130549Smlaier else if (_IF_QFULL(&sp->pp_fastq)) 875130549Smlaier ; 87641686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 87712436Speter ifq = &sp->pp_fastq; 87841686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 87941686Sphk ; 88041686Sphk else if (ip->ip_p != IPPROTO_TCP) 88141686Sphk ; 88241686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 88341686Sphk ifq = &sp->pp_fastq; 88441686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 88541686Sphk ifq = &sp->pp_fastq; 88688534Sjoerg 88788534Sjoerg /* 88888534Sjoerg * Do IP Header compression 88988534Sjoerg */ 890139365Srik if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR && 891138745Srik (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP) 89288599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 89388534Sjoerg sp->ipcp.compress_cid)) { 89488534Sjoerg case TYPE_COMPRESSED_TCP: 89588534Sjoerg ipproto = PPP_VJ_COMP; 89688534Sjoerg break; 89788534Sjoerg case TYPE_UNCOMPRESSED_TCP: 89888534Sjoerg ipproto = PPP_VJ_UCOMP; 89988534Sjoerg break; 90088534Sjoerg case TYPE_IP: 90188534Sjoerg ipproto = PPP_IP; 90288534Sjoerg break; 90388534Sjoerg default: 90488534Sjoerg m_freem(m); 905138745Srik SPPP_UNLOCK(sp); 90688534Sjoerg splx(s); 90788534Sjoerg return (EINVAL); 90888534Sjoerg } 9094910Swollman } 9104910Swollman#endif 9114910Swollman 91278064Sume#ifdef INET6 91378064Sume if (dst->sa_family == AF_INET6) { 91478064Sume /* XXX do something tricky here? */ 91578064Sume } 91678064Sume#endif 91778064Sume 918139365Srik if (sp->pp_mode == PP_FR) { 919139365Srik /* Add frame relay header. */ 920139365Srik m = sppp_fr_header (sp, m, dst->sa_family); 921139365Srik if (! m) 922139365Srik goto nobufs; 923139365Srik goto out; 924139365Srik } 925139365Srik 9264910Swollman /* 9274910Swollman * Prepend general data packet PPP header. For now, IP only. 9284910Swollman */ 929111119Simp M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 9304910Swollman if (! m) { 931139365Sriknobufs: if (debug) 93240008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 93340008Sjoerg SPP_ARGS(ifp)); 93425944Sjoerg ++ifp->if_oerrors; 935138745Srik SPPP_UNLOCK(sp); 9364910Swollman splx (s); 9374910Swollman return (ENOBUFS); 9384910Swollman } 93940008Sjoerg /* 94040008Sjoerg * May want to check size of packet 94140008Sjoerg * (albeit due to the implementation it's always enough) 94240008Sjoerg */ 9434910Swollman h = mtod (m, struct ppp_header*); 94445152Sphk if (sp->pp_mode == IFF_CISCO) { 94528088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9464910Swollman h->control = 0; 9474910Swollman } else { 9484910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9494910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9504910Swollman } 9514910Swollman 9524910Swollman switch (dst->sa_family) { 9534910Swollman#ifdef INET 9544910Swollman case AF_INET: /* Internet Protocol */ 95545152Sphk if (sp->pp_mode == IFF_CISCO) 95611189Sjkh h->protocol = htons (ETHERTYPE_IP); 95711189Sjkh else { 95825955Sjoerg /* 95925955Sjoerg * Don't choke with an ENETDOWN early. It's 96025955Sjoerg * possible that we just started dialing out, 96125955Sjoerg * so don't drop the packet immediately. If 96225955Sjoerg * we notice that we run out of buffer space 96325955Sjoerg * below, we will however remember that we are 96425955Sjoerg * not ready to carry IP packets, and return 96525955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 96625955Sjoerg */ 96788534Sjoerg h->protocol = htons(ipproto); 96825955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 96925955Sjoerg rv = ENETDOWN; 97011189Sjkh } 9714910Swollman break; 9724910Swollman#endif 97354263Sshin#ifdef INET6 97454263Sshin case AF_INET6: /* Internet Protocol */ 97554263Sshin if (sp->pp_mode == IFF_CISCO) 97654263Sshin h->protocol = htons (ETHERTYPE_IPV6); 97754263Sshin else { 97878064Sume /* 97978064Sume * Don't choke with an ENETDOWN early. It's 98078064Sume * possible that we just started dialing out, 98178064Sume * so don't drop the packet immediately. If 98278064Sume * we notice that we run out of buffer space 98378064Sume * below, we will however remember that we are 98478064Sume * not ready to carry IP packets, and return 98578064Sume * ENETDOWN, as opposed to ENOBUFS. 98678064Sume */ 98778064Sume h->protocol = htons(PPP_IPV6); 98878064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 98978064Sume rv = ENETDOWN; 99054263Sshin } 99154263Sshin break; 99254263Sshin#endif 99311819Sjulian#ifdef IPX 99412495Speter case AF_IPX: /* Novell IPX Protocol */ 99545152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 99612495Speter ETHERTYPE_IPX : PPP_IPX); 99711819Sjulian break; 99811819Sjulian#endif 9994910Swollman default: 10004910Swollman m_freem (m); 100125944Sjoerg ++ifp->if_oerrors; 1002138745Srik SPPP_UNLOCK(sp); 10034910Swollman splx (s); 10044910Swollman return (EAFNOSUPPORT); 10054910Swollman } 10064910Swollman 10074910Swollman /* 10084910Swollman * Queue message on interface, and start output if interface 100988577Sjoerg * not yet active. 10104910Swollman */ 1011139365Srikout: 1012130549Smlaier if (ifq != NULL) 1013130549Smlaier error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 1014130549Smlaier else 1015130549Smlaier IFQ_HANDOFF_ADJ(ifp, m, 3, error); 1016130549Smlaier if (error) { 101725944Sjoerg ++ifp->if_oerrors; 1018138745Srik SPPP_UNLOCK(sp); 1019111038Smaxim splx (s); 102025955Sjoerg return (rv? rv: ENOBUFS); 10214910Swollman } 1022138745Srik SPPP_UNLOCK(sp); 1023111038Smaxim splx (s); 102488577Sjoerg /* 102588577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 102688577Sjoerg * here since sppp_output() is only called on behalf of 102788577Sjoerg * network-layer traffic; control-layer traffic is handled 102888577Sjoerg * by sppp_cp_send(). 102988577Sjoerg */ 1030150349Sandre sp->pp_last_sent = time_uptime; 10314910Swollman return (0); 10324910Swollman} 10334910Swollman 103425706Sjoergvoid 103525706Sjoergsppp_attach(struct ifnet *ifp) 10364910Swollman{ 1037147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10384910Swollman 1039138745Srik /* Initialize mtx lock */ 1040138745Srik mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); 1041138745Srik 10424910Swollman /* Initialize keepalive handler. */ 1043188668Srwatson callout_init(&sp->keepalive_callout, CALLOUT_MPSAFE); 1044138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 1045138745Srik (void *)sp); 10464910Swollman 1047147256Sbrooks ifp->if_mtu = PP_MTU; 1048147256Sbrooks ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1049147256Sbrooks ifp->if_output = sppp_output; 105042104Sphk#if 0 105142064Sphk sp->pp_flags = PP_KEEPALIVE; 105242104Sphk#endif 1053147256Sbrooks ifp->if_snd.ifq_maxlen = 32; 105470199Sjhay sp->pp_fastq.ifq_maxlen = 32; 105570199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10564910Swollman sp->pp_loopcnt = 0; 10574910Swollman sp->pp_alivecnt = 0; 105878064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 105978064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 106025944Sjoerg sp->pp_phase = PHASE_DEAD; 1061138745Srik sp->pp_up = sppp_pp_up; 1062138745Srik sp->pp_down = sppp_pp_down; 106388716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 106493818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 106588716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 106693818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 1067150349Sandre sp->pp_last_recv = sp->pp_last_sent = time_uptime; 106888723Sjoerg sp->confflags = 0; 106988723Sjoerg#ifdef INET 107088723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 107188723Sjoerg#endif 107288723Sjoerg#ifdef INET6 107388723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 107488723Sjoerg#endif 1075188668Srwatson callout_init(&sp->ifstart_callout, CALLOUT_MPSAFE); 1076138745Srik sp->if_start = ifp->if_start; 1077138745Srik ifp->if_start = sppp_ifstart; 1078118072Sgj sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 107988599Sjoerg sl_compress_init(sp->pp_comp, -1); 108025944Sjoerg sppp_lcp_init(sp); 108125944Sjoerg sppp_ipcp_init(sp); 108278064Sume sppp_ipv6cp_init(sp); 108330300Sjoerg sppp_pap_init(sp); 108430300Sjoerg sppp_chap_init(sp); 10854910Swollman} 10864910Swollman 108730300Sjoergvoid 108825706Sjoergsppp_detach(struct ifnet *ifp) 10894910Swollman{ 1090147256Sbrooks struct sppp *sp = IFP2SP(ifp); 109125944Sjoerg int i; 10924910Swollman 1093138745Srik KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized")); 10944910Swollman 10954910Swollman /* Stop keepalive handler. */ 1096138745Srik if (!callout_drain(&sp->keepalive_callout)) 1097138745Srik callout_stop(&sp->keepalive_callout); 109825944Sjoerg 1099138745Srik for (i = 0; i < IDX_COUNT; i++) { 1100138745Srik if (!callout_drain(&sp->ch[i])) 1101138745Srik callout_stop(&sp->ch[i]); 1102138745Srik } 1103138745Srik if (!callout_drain(&sp->pap_my_to_ch)) 1104138745Srik callout_stop(&sp->pap_my_to_ch); 110569152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 110669152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 1107138745Srik mtx_destroy(&sp->mtx); 11084910Swollman} 11094910Swollman 11104910Swollman/* 11114910Swollman * Flush the interface output queue. 11124910Swollman */ 1113138745Srikstatic void 1114138745Sriksppp_flush_unlocked(struct ifnet *ifp) 11154910Swollman{ 1116147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11174910Swollman 1118147256Sbrooks sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd); 111925944Sjoerg sppp_qflush (&sp->pp_fastq); 112026018Sjoerg sppp_qflush (&sp->pp_cpq); 11214910Swollman} 11224910Swollman 1123138745Srikvoid 1124138745Sriksppp_flush(struct ifnet *ifp) 1125138745Srik{ 1126147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1127138745Srik 1128138745Srik SPPP_LOCK(sp); 1129138745Srik sppp_flush_unlocked (ifp); 1130138745Srik SPPP_UNLOCK(sp); 1131138745Srik} 1132138745Srik 11334910Swollman/* 113411189Sjkh * Check if the output queue is empty. 113511189Sjkh */ 113612820Sphkint 113725706Sjoergsppp_isempty(struct ifnet *ifp) 113811189Sjkh{ 1139147256Sbrooks struct sppp *sp = IFP2SP(ifp); 114025944Sjoerg int empty, s; 114111189Sjkh 114225944Sjoerg s = splimp(); 1143138745Srik SPPP_LOCK(sp); 114426018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1145147256Sbrooks !SP2IFP(sp)->if_snd.ifq_head; 1146138745Srik SPPP_UNLOCK(sp); 114725944Sjoerg splx(s); 114811189Sjkh return (empty); 114911189Sjkh} 115011189Sjkh 115111189Sjkh/* 11524910Swollman * Get next packet to send. 11534910Swollman */ 115425706Sjoergstruct mbuf * 115525706Sjoergsppp_dequeue(struct ifnet *ifp) 11564910Swollman{ 1157147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11584910Swollman struct mbuf *m; 115925944Sjoerg int s; 11604910Swollman 116125944Sjoerg s = splimp(); 1162138745Srik SPPP_LOCK(sp); 116326018Sjoerg /* 116430300Sjoerg * Process only the control protocol queue until we have at 116530300Sjoerg * least one NCP open. 116626018Sjoerg * 116726018Sjoerg * Do always serve all three queues in Cisco mode. 116826018Sjoerg */ 116926018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 117026018Sjoerg if (m == NULL && 1171139365Srik (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO || 1172139365Srik sp->pp_mode == PP_FR)) { 117326018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 117426018Sjoerg if (m == NULL) 1175147256Sbrooks IF_DEQUEUE (&SP2IFP(sp)->if_snd, m); 117626018Sjoerg } 1177138745Srik SPPP_UNLOCK(sp); 117826018Sjoerg splx(s); 117926018Sjoerg return m; 11804910Swollman} 11814910Swollman 11824910Swollman/* 118330300Sjoerg * Pick the next packet, do not remove it from the queue. 118430300Sjoerg */ 118530300Sjoergstruct mbuf * 118630300Sjoergsppp_pick(struct ifnet *ifp) 118730300Sjoerg{ 1188147256Sbrooks struct sppp *sp = IFP2SP(ifp); 118930300Sjoerg struct mbuf *m; 119030300Sjoerg int s; 119130300Sjoerg 1192138745Srik s = splimp (); 1193138745Srik SPPP_LOCK(sp); 119430300Sjoerg 119530300Sjoerg m = sp->pp_cpq.ifq_head; 119630300Sjoerg if (m == NULL && 1197138745Srik (sp->pp_phase == PHASE_NETWORK || 1198139365Srik sp->pp_mode == IFF_CISCO || 1199139365Srik sp->pp_mode == PP_FR)) 120030300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 1201147256Sbrooks m = SP2IFP(sp)->if_snd.ifq_head; 1202138745Srik SPPP_UNLOCK(sp); 120330300Sjoerg splx (s); 120430300Sjoerg return (m); 120530300Sjoerg} 120630300Sjoerg 120730300Sjoerg/* 120825944Sjoerg * Process an ioctl request. Called on low priority level. 12094910Swollman */ 121025944Sjoergint 121142104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 12124910Swollman{ 121325944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 1214147256Sbrooks struct sppp *sp = IFP2SP(ifp); 121530300Sjoerg int s, rv, going_up, going_down, newmode; 12164910Swollman 121725944Sjoerg s = splimp(); 1218138745Srik SPPP_LOCK(sp); 121930300Sjoerg rv = 0; 122025944Sjoerg switch (cmd) { 122125944Sjoerg case SIOCAIFADDR: 122225944Sjoerg case SIOCSIFDSTADDR: 122325944Sjoerg break; 12244910Swollman 122525944Sjoerg case SIOCSIFADDR: 122688503Sjoerg /* set the interface "up" when assigning an IP address */ 122788503Sjoerg ifp->if_flags |= IFF_UP; 1228102412Scharnier /* FALLTHROUGH */ 122911189Sjkh 123025944Sjoerg case SIOCSIFFLAGS: 123125944Sjoerg going_up = ifp->if_flags & IFF_UP && 1232148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 123325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1234148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 123545152Sphk 123645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 123745152Sphk if (!newmode) 123845152Sphk newmode = ifp->if_flags & IFF_AUTO; 123945152Sphk if (!newmode) 124045152Sphk newmode = ifp->if_flags & IFF_CISCO; 124145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 124245152Sphk ifp->if_flags |= newmode; 124345152Sphk 1244139365Srik if (!newmode) 1245139365Srik newmode = sp->pp_flags & PP_FR; 1246139365Srik 124745152Sphk if (newmode != sp->pp_mode) { 124845152Sphk going_down = 1; 124945152Sphk if (!going_up) 1250148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12514910Swollman } 12524910Swollman 125345152Sphk if (going_down) { 1254139365Srik if (sp->pp_mode != IFF_CISCO && 1255139365Srik sp->pp_mode != PP_FR) 125645152Sphk lcp.Close(sp); 125745152Sphk else if (sp->pp_tlf) 125845152Sphk (sp->pp_tlf)(sp); 1259138745Srik sppp_flush_unlocked(ifp); 1260148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 126145152Sphk sp->pp_mode = newmode; 126226018Sjoerg } 12634910Swollman 126445152Sphk if (going_up) { 1265139365Srik if (sp->pp_mode != IFF_CISCO && 1266139365Srik sp->pp_mode != PP_FR) 126745152Sphk lcp.Close(sp); 126845152Sphk sp->pp_mode = newmode; 126945152Sphk if (sp->pp_mode == 0) { 1270148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 127145152Sphk lcp.Open(sp); 127245152Sphk } 1273139365Srik if ((sp->pp_mode == IFF_CISCO) || 1274139365Srik (sp->pp_mode == PP_FR)) { 127545152Sphk if (sp->pp_tls) 127645152Sphk (sp->pp_tls)(sp); 1277148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 127845152Sphk } 127945152Sphk } 128045152Sphk 12814910Swollman break; 128211189Sjkh 128325944Sjoerg#ifdef SIOCSIFMTU 128425944Sjoerg#ifndef ifr_mtu 128525944Sjoerg#define ifr_mtu ifr_metric 128625944Sjoerg#endif 128725944Sjoerg case SIOCSIFMTU: 128825944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 128925944Sjoerg return (EINVAL); 129025944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12914910Swollman break; 129225944Sjoerg#endif 129325944Sjoerg#ifdef SLIOCSETMTU 129425944Sjoerg case SLIOCSETMTU: 129525944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 129625944Sjoerg return (EINVAL); 129725944Sjoerg ifp->if_mtu = *(short*)data; 12984910Swollman break; 129925944Sjoerg#endif 130025944Sjoerg#ifdef SIOCGIFMTU 130125944Sjoerg case SIOCGIFMTU: 130225944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 130311189Sjkh break; 130425944Sjoerg#endif 130525944Sjoerg#ifdef SLIOCGETMTU 130625944Sjoerg case SLIOCGETMTU: 130725944Sjoerg *(short*)data = ifp->if_mtu; 13084910Swollman break; 130925944Sjoerg#endif 131025944Sjoerg case SIOCADDMULTI: 131125944Sjoerg case SIOCDELMULTI: 13124910Swollman break; 131311189Sjkh 131430300Sjoerg case SIOCGIFGENERIC: 131530300Sjoerg case SIOCSIFGENERIC: 131630300Sjoerg rv = sppp_params(sp, cmd, data); 131730300Sjoerg break; 131830300Sjoerg 131925944Sjoerg default: 132030300Sjoerg rv = ENOTTY; 13214910Swollman } 1322138745Srik SPPP_UNLOCK(sp); 132325944Sjoerg splx(s); 132430300Sjoerg return rv; 13254910Swollman} 13264910Swollman 132770199Sjhay/* 132825944Sjoerg * Cisco framing implementation. 132925944Sjoerg */ 133025944Sjoerg 13314910Swollman/* 13324910Swollman * Handle incoming Cisco keepalive protocol packets. 13334910Swollman */ 133430300Sjoergstatic void 133525706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 13364910Swollman{ 133725944Sjoerg STDDCL; 13384910Swollman struct cisco_packet *h; 133930300Sjoerg u_long me, mymask; 13404910Swollman 134127929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 134225706Sjoerg if (debug) 134325706Sjoerg log(LOG_DEBUG, 134440008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 134540008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13464910Swollman return; 13474910Swollman } 13484910Swollman h = mtod (m, struct cisco_packet*); 134925706Sjoerg if (debug) 135025706Sjoerg log(LOG_DEBUG, 135140008Sjoerg SPP_FMT "cisco input: %d bytes " 135225706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 135340008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 135440008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 135540008Sjoerg (u_int)h->time0, (u_int)h->time1); 13564910Swollman switch (ntohl (h->type)) { 13574910Swollman default: 135825706Sjoerg if (debug) 135969211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 136040008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 13614910Swollman break; 13624910Swollman case CISCO_ADDR_REPLY: 13634910Swollman /* Reply on address request, ignore */ 13644910Swollman break; 13654910Swollman case CISCO_KEEPALIVE_REQ: 13664910Swollman sp->pp_alivecnt = 0; 136778064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 136878064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13694910Swollman /* Local and remote sequence numbers are equal. 13704910Swollman * Probably, the line is in loopback mode. */ 137111189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 137240008Sjoerg printf (SPP_FMT "loopback\n", 137340008Sjoerg SPP_ARGS(ifp)); 137411189Sjkh sp->pp_loopcnt = 0; 137511189Sjkh if (ifp->if_flags & IFF_UP) { 137611189Sjkh if_down (ifp); 137726018Sjoerg sppp_qflush (&sp->pp_cpq); 137811189Sjkh } 137911189Sjkh } 13804910Swollman ++sp->pp_loopcnt; 13814910Swollman 13824910Swollman /* Generate new local sequence number */ 138378064Sume sp->pp_seq[IDX_LCP] = random(); 138411189Sjkh break; 138511189Sjkh } 138630300Sjoerg sp->pp_loopcnt = 0; 138711189Sjkh if (! (ifp->if_flags & IFF_UP) && 1388148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 138930300Sjoerg if_up(ifp); 139040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 139111189Sjkh } 13924910Swollman break; 13934910Swollman case CISCO_ADDR_REQ: 139430300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 139530300Sjoerg if (me != 0L) 139630300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13974910Swollman break; 13984910Swollman } 13994910Swollman} 14004910Swollman 14014910Swollman/* 140225944Sjoerg * Send Cisco keepalive packet. 14034910Swollman */ 140412820Sphkstatic void 140525944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 140625944Sjoerg{ 140725944Sjoerg STDDCL; 140825944Sjoerg struct ppp_header *h; 140925944Sjoerg struct cisco_packet *ch; 141025944Sjoerg struct mbuf *m; 141135029Sphk struct timeval tv; 141225944Sjoerg 141336119Sphk getmicrouptime(&tv); 141470199Sjhay 1415111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 141625944Sjoerg if (! m) 141725944Sjoerg return; 141825944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 141925944Sjoerg m->m_pkthdr.rcvif = 0; 142025944Sjoerg 142125944Sjoerg h = mtod (m, struct ppp_header*); 142225944Sjoerg h->address = CISCO_MULTICAST; 142325944Sjoerg h->control = 0; 142425944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 142525944Sjoerg 142625944Sjoerg ch = (struct cisco_packet*) (h + 1); 142725944Sjoerg ch->type = htonl (type); 142825944Sjoerg ch->par1 = htonl (par1); 142925944Sjoerg ch->par2 = htonl (par2); 143025944Sjoerg ch->rel = -1; 143140008Sjoerg 143235029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 143335029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 143425944Sjoerg 143525944Sjoerg if (debug) 143625944Sjoerg log(LOG_DEBUG, 143740008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 143840008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 143940008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 144025944Sjoerg 144169152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 144269152Sjlemon ifp->if_oerrors++; 144325944Sjoerg} 144425944Sjoerg 144570199Sjhay/* 144625944Sjoerg * PPP protocol implementation. 144725944Sjoerg */ 144825944Sjoerg 144925944Sjoerg/* 145025944Sjoerg * Send PPP control protocol packet. 145125944Sjoerg */ 145225944Sjoergstatic void 145325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 145425706Sjoerg u_char ident, u_short len, void *data) 14554910Swollman{ 145625944Sjoerg STDDCL; 14574910Swollman struct ppp_header *h; 14584910Swollman struct lcp_header *lh; 14594910Swollman struct mbuf *m; 14604910Swollman 14614910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14624910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1463111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 14644910Swollman if (! m) 14654910Swollman return; 14664910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14674910Swollman m->m_pkthdr.rcvif = 0; 14684910Swollman 14694910Swollman h = mtod (m, struct ppp_header*); 14704910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14714910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14724910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14734910Swollman 14744910Swollman lh = (struct lcp_header*) (h + 1); 14754910Swollman lh->type = type; 14764910Swollman lh->ident = ident; 14774910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14784910Swollman if (len) 14794910Swollman bcopy (data, lh+1, len); 14804910Swollman 148125706Sjoerg if (debug) { 148240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 148340008Sjoerg SPP_ARGS(ifp), 148425944Sjoerg sppp_proto_name(proto), 148525944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 148625944Sjoerg ntohs (lh->len)); 148744145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 148869211Sphk log(-1, ">\n"); 14894910Swollman } 149069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 149169152Sjlemon ifp->if_oerrors++; 14924910Swollman} 14934910Swollman 14944910Swollman/* 149525944Sjoerg * Handle incoming PPP control protocol packets. 14964910Swollman */ 149712820Sphkstatic void 149825944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14994910Swollman{ 150025944Sjoerg STDDCL; 150125944Sjoerg struct lcp_header *h; 150225944Sjoerg int len = m->m_pkthdr.len; 150325944Sjoerg int rv; 150425944Sjoerg u_char *p; 15054910Swollman 150625944Sjoerg if (len < 4) { 150725944Sjoerg if (debug) 150825944Sjoerg log(LOG_DEBUG, 150940008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 151040008Sjoerg SPP_ARGS(ifp), cp->name, len); 15114910Swollman return; 151225944Sjoerg } 151325944Sjoerg h = mtod (m, struct lcp_header*); 151425944Sjoerg if (debug) { 151525944Sjoerg log(LOG_DEBUG, 151640008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 151740008Sjoerg SPP_ARGS(ifp), cp->name, 151825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 151925944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 152044145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 152169211Sphk log(-1, ">\n"); 152225944Sjoerg } 152325944Sjoerg if (len > ntohs (h->len)) 152425944Sjoerg len = ntohs (h->len); 152530300Sjoerg p = (u_char *)(h + 1); 152625944Sjoerg switch (h->type) { 152725944Sjoerg case CONF_REQ: 152825944Sjoerg if (len < 4) { 152925944Sjoerg if (debug) 153069211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 153140008Sjoerg SPP_ARGS(ifp), cp->name, 153225944Sjoerg len); 153325944Sjoerg ++ifp->if_ierrors; 153425944Sjoerg break; 153525944Sjoerg } 153630300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 153730300Sjoerg switch (sp->state[cp->protoidx]) { 153830300Sjoerg case STATE_CLOSING: 153930300Sjoerg case STATE_STOPPING: 154030300Sjoerg return; 154130300Sjoerg case STATE_CLOSED: 154230300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 154330300Sjoerg 0, 0); 154430300Sjoerg return; 154530300Sjoerg } 154625944Sjoerg rv = (cp->RCR)(sp, h, len); 154725944Sjoerg switch (sp->state[cp->protoidx]) { 154825944Sjoerg case STATE_OPENED: 154925944Sjoerg (cp->tld)(sp); 155025944Sjoerg (cp->scr)(sp); 1551102412Scharnier /* FALLTHROUGH */ 155225944Sjoerg case STATE_ACK_SENT: 155325944Sjoerg case STATE_REQ_SENT: 155470199Sjhay /* 155570199Sjhay * sppp_cp_change_state() have the side effect of 155670199Sjhay * restarting the timeouts. We want to avoid that 155770199Sjhay * if the state don't change, otherwise we won't 155870199Sjhay * ever timeout and resend a configuration request 155970199Sjhay * that got lost. 156070199Sjhay */ 156170199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 156270199Sjhay STATE_REQ_SENT)) 156370199Sjhay break; 156425944Sjoerg sppp_cp_change_state(cp, sp, rv? 156525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 156625944Sjoerg break; 156725944Sjoerg case STATE_STOPPED: 156825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 156925944Sjoerg (cp->scr)(sp); 157025944Sjoerg sppp_cp_change_state(cp, sp, rv? 157125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 157225944Sjoerg break; 157325944Sjoerg case STATE_ACK_RCVD: 157425944Sjoerg if (rv) { 157525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 157625944Sjoerg if (debug) 157740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 157840008Sjoerg SPP_ARGS(ifp), 157926077Sjoerg cp->name); 158025944Sjoerg (cp->tlu)(sp); 158125944Sjoerg } else 158225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 158325944Sjoerg break; 158425944Sjoerg default: 158540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 158640008Sjoerg SPP_ARGS(ifp), cp->name, 158725944Sjoerg sppp_cp_type_name(h->type), 158825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158925944Sjoerg ++ifp->if_ierrors; 159025944Sjoerg } 159125944Sjoerg break; 159225944Sjoerg case CONF_ACK: 159325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 159425944Sjoerg if (debug) 159569211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 159640008Sjoerg SPP_ARGS(ifp), cp->name, 159725944Sjoerg h->ident, sp->confid[cp->protoidx]); 159825944Sjoerg ++ifp->if_ierrors; 159925944Sjoerg break; 160025944Sjoerg } 160125944Sjoerg switch (sp->state[cp->protoidx]) { 160225944Sjoerg case STATE_CLOSED: 160325944Sjoerg case STATE_STOPPED: 160425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 160525944Sjoerg break; 160625944Sjoerg case STATE_CLOSING: 160725944Sjoerg case STATE_STOPPING: 160825944Sjoerg break; 160925944Sjoerg case STATE_REQ_SENT: 161025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 161125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 161225944Sjoerg break; 161325944Sjoerg case STATE_OPENED: 161425944Sjoerg (cp->tld)(sp); 1615102412Scharnier /* FALLTHROUGH */ 161625944Sjoerg case STATE_ACK_RCVD: 161725944Sjoerg (cp->scr)(sp); 161825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 161925944Sjoerg break; 162025944Sjoerg case STATE_ACK_SENT: 162125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 162225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 162325944Sjoerg if (debug) 162440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 162540008Sjoerg SPP_ARGS(ifp), cp->name); 162625944Sjoerg (cp->tlu)(sp); 162725944Sjoerg break; 162825944Sjoerg default: 162940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163040008Sjoerg SPP_ARGS(ifp), cp->name, 163125944Sjoerg sppp_cp_type_name(h->type), 163225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163325944Sjoerg ++ifp->if_ierrors; 163425944Sjoerg } 163525944Sjoerg break; 163625944Sjoerg case CONF_NAK: 163725944Sjoerg case CONF_REJ: 163825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 163925944Sjoerg if (debug) 164069211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 164140008Sjoerg SPP_ARGS(ifp), cp->name, 164225944Sjoerg h->ident, sp->confid[cp->protoidx]); 164325944Sjoerg ++ifp->if_ierrors; 164425944Sjoerg break; 164525944Sjoerg } 164625944Sjoerg if (h->type == CONF_NAK) 164725944Sjoerg (cp->RCN_nak)(sp, h, len); 164825944Sjoerg else /* CONF_REJ */ 164925944Sjoerg (cp->RCN_rej)(sp, h, len); 16504910Swollman 165125944Sjoerg switch (sp->state[cp->protoidx]) { 165225944Sjoerg case STATE_CLOSED: 165325944Sjoerg case STATE_STOPPED: 165425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 165525944Sjoerg break; 165625944Sjoerg case STATE_REQ_SENT: 165725944Sjoerg case STATE_ACK_SENT: 165825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 165970199Sjhay /* 166070199Sjhay * Slow things down a bit if we think we might be 166170199Sjhay * in loopback. Depend on the timeout to send the 166270199Sjhay * next configuration request. 166370199Sjhay */ 166470199Sjhay if (sp->pp_loopcnt) 166570199Sjhay break; 166625944Sjoerg (cp->scr)(sp); 166725944Sjoerg break; 166825944Sjoerg case STATE_OPENED: 166925944Sjoerg (cp->tld)(sp); 1670102412Scharnier /* FALLTHROUGH */ 167125944Sjoerg case STATE_ACK_RCVD: 167252633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 167325944Sjoerg (cp->scr)(sp); 167425944Sjoerg break; 167525944Sjoerg case STATE_CLOSING: 167625944Sjoerg case STATE_STOPPING: 167725944Sjoerg break; 167825944Sjoerg default: 167940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 168040008Sjoerg SPP_ARGS(ifp), cp->name, 168125944Sjoerg sppp_cp_type_name(h->type), 168225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 168325944Sjoerg ++ifp->if_ierrors; 168425944Sjoerg } 168525944Sjoerg break; 16864910Swollman 168725944Sjoerg case TERM_REQ: 168825944Sjoerg switch (sp->state[cp->protoidx]) { 168925944Sjoerg case STATE_ACK_RCVD: 169025944Sjoerg case STATE_ACK_SENT: 169125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1692102412Scharnier /* FALLTHROUGH */ 169325944Sjoerg case STATE_CLOSED: 169425944Sjoerg case STATE_STOPPED: 169525944Sjoerg case STATE_CLOSING: 169625944Sjoerg case STATE_STOPPING: 169725944Sjoerg case STATE_REQ_SENT: 169825944Sjoerg sta: 169925944Sjoerg /* Send Terminate-Ack packet. */ 170025944Sjoerg if (debug) 170140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 170240008Sjoerg SPP_ARGS(ifp), cp->name); 170325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 170425944Sjoerg break; 170525944Sjoerg case STATE_OPENED: 170625944Sjoerg (cp->tld)(sp); 170725944Sjoerg sp->rst_counter[cp->protoidx] = 0; 170825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 170925944Sjoerg goto sta; 171025944Sjoerg break; 171125944Sjoerg default: 171240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 171340008Sjoerg SPP_ARGS(ifp), cp->name, 171425944Sjoerg sppp_cp_type_name(h->type), 171525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 171625944Sjoerg ++ifp->if_ierrors; 171725944Sjoerg } 171825944Sjoerg break; 171925944Sjoerg case TERM_ACK: 172025944Sjoerg switch (sp->state[cp->protoidx]) { 172125944Sjoerg case STATE_CLOSED: 172225944Sjoerg case STATE_STOPPED: 172325944Sjoerg case STATE_REQ_SENT: 172425944Sjoerg case STATE_ACK_SENT: 172525944Sjoerg break; 172625944Sjoerg case STATE_CLOSING: 172741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 172825944Sjoerg (cp->tlf)(sp); 172925944Sjoerg break; 173025944Sjoerg case STATE_STOPPING: 173141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 173225944Sjoerg (cp->tlf)(sp); 173325944Sjoerg break; 173425944Sjoerg case STATE_ACK_RCVD: 173525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 173625944Sjoerg break; 173725944Sjoerg case STATE_OPENED: 173825944Sjoerg (cp->tld)(sp); 173925944Sjoerg (cp->scr)(sp); 174025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 174125944Sjoerg break; 174225944Sjoerg default: 174340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 174440008Sjoerg SPP_ARGS(ifp), cp->name, 174525944Sjoerg sppp_cp_type_name(h->type), 174625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 174725944Sjoerg ++ifp->if_ierrors; 174825944Sjoerg } 174925944Sjoerg break; 175025944Sjoerg case CODE_REJ: 175125944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 175230300Sjoerg log(LOG_INFO, 175340008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 175430300Sjoerg "danger will robinson\n", 175540008Sjoerg SPP_ARGS(ifp), cp->name, 175630300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 175725944Sjoerg switch (sp->state[cp->protoidx]) { 175825944Sjoerg case STATE_CLOSED: 175925944Sjoerg case STATE_STOPPED: 176025944Sjoerg case STATE_REQ_SENT: 176125944Sjoerg case STATE_ACK_SENT: 176225944Sjoerg case STATE_CLOSING: 176325944Sjoerg case STATE_STOPPING: 176425944Sjoerg case STATE_OPENED: 176525944Sjoerg break; 176625944Sjoerg case STATE_ACK_RCVD: 176725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 176825944Sjoerg break; 176925944Sjoerg default: 177040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 177140008Sjoerg SPP_ARGS(ifp), cp->name, 177225944Sjoerg sppp_cp_type_name(h->type), 177325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 177425944Sjoerg ++ifp->if_ierrors; 177525944Sjoerg } 177625944Sjoerg break; 177780715Sume case PROTO_REJ: 177880715Sume { 177980715Sume int catastrophic; 178080715Sume const struct cp *upper; 178180715Sume int i; 178280715Sume u_int16_t proto; 178380715Sume 178480715Sume catastrophic = 0; 178580715Sume upper = NULL; 178680715Sume proto = ntohs(*((u_int16_t *)p)); 178780715Sume for (i = 0; i < IDX_COUNT; i++) { 178880715Sume if (cps[i]->proto == proto) { 178980715Sume upper = cps[i]; 179080715Sume break; 179180715Sume } 179280715Sume } 179380715Sume if (upper == NULL) 179480715Sume catastrophic++; 179580715Sume 179688508Sjoerg if (catastrophic || debug) 179788508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 179888508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 179988508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 180088508Sjoerg sppp_cp_type_name(h->type), proto, 180188508Sjoerg upper ? upper->name : "unknown", 180288508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 180380715Sume 180480715Sume /* 180580715Sume * if we got RXJ+ against conf-req, the peer does not implement 180680715Sume * this particular protocol type. terminate the protocol. 180780715Sume */ 180880715Sume if (upper && !catastrophic) { 180980715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 181080715Sume upper->Close(sp); 181180715Sume break; 181280715Sume } 181380715Sume } 181480715Sume 181580715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 181680715Sume switch (sp->state[cp->protoidx]) { 181780715Sume case STATE_CLOSED: 181880715Sume case STATE_STOPPED: 181980715Sume case STATE_REQ_SENT: 182080715Sume case STATE_ACK_SENT: 182180715Sume case STATE_CLOSING: 182280715Sume case STATE_STOPPING: 182380715Sume case STATE_OPENED: 182480715Sume break; 182580715Sume case STATE_ACK_RCVD: 182680715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 182780715Sume break; 182880715Sume default: 182980715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 183080715Sume SPP_ARGS(ifp), cp->name, 183180715Sume sppp_cp_type_name(h->type), 183280715Sume sppp_state_name(sp->state[cp->protoidx])); 183380715Sume ++ifp->if_ierrors; 183480715Sume } 183580715Sume break; 183680715Sume } 183725944Sjoerg case DISC_REQ: 183825944Sjoerg if (cp->proto != PPP_LCP) 183925944Sjoerg goto illegal; 184025944Sjoerg /* Discard the packet. */ 184125944Sjoerg break; 184225944Sjoerg case ECHO_REQ: 184325944Sjoerg if (cp->proto != PPP_LCP) 184425944Sjoerg goto illegal; 184525944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 184625944Sjoerg if (debug) 184769211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 184840008Sjoerg SPP_ARGS(ifp)); 184925944Sjoerg ++ifp->if_ierrors; 185025944Sjoerg break; 185125944Sjoerg } 185225944Sjoerg if (len < 8) { 185325944Sjoerg if (debug) 185469211Sphk log(-1, SPP_FMT "invalid lcp echo request " 185525944Sjoerg "packet length: %d bytes\n", 185640008Sjoerg SPP_ARGS(ifp), len); 185725944Sjoerg break; 185825944Sjoerg } 185944145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 186044145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 186125944Sjoerg /* Line loopback mode detected. */ 186240008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 186370199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 186425944Sjoerg if_down (ifp); 186526018Sjoerg sppp_qflush (&sp->pp_cpq); 18664910Swollman 186725944Sjoerg /* Shut down the PPP link. */ 186825944Sjoerg /* XXX */ 186925944Sjoerg lcp.Down(sp); 187025944Sjoerg lcp.Up(sp); 187125944Sjoerg break; 187225944Sjoerg } 187325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 187425944Sjoerg if (debug) 187569211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 187640008Sjoerg SPP_ARGS(ifp)); 187725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 187825944Sjoerg break; 187925944Sjoerg case ECHO_REPLY: 188025944Sjoerg if (cp->proto != PPP_LCP) 188125944Sjoerg goto illegal; 188225944Sjoerg if (h->ident != sp->lcp.echoid) { 188325944Sjoerg ++ifp->if_ierrors; 188425944Sjoerg break; 188525944Sjoerg } 188625944Sjoerg if (len < 8) { 188725944Sjoerg if (debug) 188869211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 188925944Sjoerg "packet length: %d bytes\n", 189040008Sjoerg SPP_ARGS(ifp), len); 189125944Sjoerg break; 189225944Sjoerg } 189325944Sjoerg if (debug) 189469211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 189540008Sjoerg SPP_ARGS(ifp)); 189644145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 189744145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 189825944Sjoerg sp->pp_alivecnt = 0; 189925944Sjoerg break; 190025944Sjoerg default: 190125944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 190225944Sjoerg illegal: 190325944Sjoerg if (debug) 190469211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 190540008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 190678064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 190778064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 190825944Sjoerg ++ifp->if_ierrors; 190925944Sjoerg } 19104910Swollman} 19114910Swollman 191225944Sjoerg 19134910Swollman/* 191425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 191525944Sjoerg * Basically, the state transition handling in the automaton. 19164910Swollman */ 191725944Sjoergstatic void 191825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 19194910Swollman{ 192025944Sjoerg STDDCL; 19214910Swollman 192225944Sjoerg if (debug) 192340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 192440008Sjoerg SPP_ARGS(ifp), cp->name, 192525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 192625944Sjoerg 192725944Sjoerg switch (sp->state[cp->protoidx]) { 192825944Sjoerg case STATE_INITIAL: 192925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 193025944Sjoerg break; 193125944Sjoerg case STATE_STARTING: 193225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 193325944Sjoerg (cp->scr)(sp); 193425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 193525944Sjoerg break; 19364910Swollman default: 193740008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 193840008Sjoerg SPP_ARGS(ifp), cp->name, 193925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 194025944Sjoerg } 194125944Sjoerg} 19424910Swollman 194325944Sjoergstatic void 194425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 194525944Sjoerg{ 194625944Sjoerg STDDCL; 194725944Sjoerg 194825944Sjoerg if (debug) 194940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 195040008Sjoerg SPP_ARGS(ifp), cp->name, 195125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 195225944Sjoerg 195325944Sjoerg switch (sp->state[cp->protoidx]) { 195425944Sjoerg case STATE_CLOSED: 195525944Sjoerg case STATE_CLOSING: 195625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19574910Swollman break; 195825944Sjoerg case STATE_STOPPED: 195941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 196025944Sjoerg (cp->tls)(sp); 196141881Sphk break; 196225944Sjoerg case STATE_STOPPING: 196325944Sjoerg case STATE_REQ_SENT: 196425944Sjoerg case STATE_ACK_RCVD: 196525944Sjoerg case STATE_ACK_SENT: 196625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 196725944Sjoerg break; 196825944Sjoerg case STATE_OPENED: 196925944Sjoerg (cp->tld)(sp); 197025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 197125944Sjoerg break; 197225944Sjoerg default: 197340008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 197440008Sjoerg SPP_ARGS(ifp), cp->name, 197525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 197625944Sjoerg } 197725944Sjoerg} 19784910Swollman 197911189Sjkh 198025944Sjoergstatic void 198125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 198225944Sjoerg{ 198325944Sjoerg STDDCL; 198425944Sjoerg 198525944Sjoerg if (debug) 198640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 198740008Sjoerg SPP_ARGS(ifp), cp->name, 198825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 198925944Sjoerg 199025944Sjoerg switch (sp->state[cp->protoidx]) { 199125944Sjoerg case STATE_INITIAL: 199241881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 199325944Sjoerg (cp->tls)(sp); 19944910Swollman break; 199525944Sjoerg case STATE_STARTING: 199625944Sjoerg break; 199725944Sjoerg case STATE_CLOSED: 199825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 199925944Sjoerg (cp->scr)(sp); 200025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 200125944Sjoerg break; 200225944Sjoerg case STATE_STOPPED: 200374703Sjoerg /* 200474703Sjoerg * Try escaping stopped state. This seems to bite 200574703Sjoerg * people occasionally, in particular for IPCP, 200674703Sjoerg * presumably following previous IPCP negotiation 200774703Sjoerg * aborts. Somehow, we must have missed a Down event 200874703Sjoerg * which would have caused a transition into starting 200974703Sjoerg * state, so as a bandaid we force the Down event now. 201074703Sjoerg * This effectively implements (something like the) 201174703Sjoerg * `restart' option mentioned in the state transition 201274703Sjoerg * table of RFC 1661. 201374703Sjoerg */ 201474703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 201574703Sjoerg (cp->tls)(sp); 201674703Sjoerg break; 201725944Sjoerg case STATE_STOPPING: 201825944Sjoerg case STATE_REQ_SENT: 201925944Sjoerg case STATE_ACK_RCVD: 202025944Sjoerg case STATE_ACK_SENT: 202125944Sjoerg case STATE_OPENED: 202225944Sjoerg break; 202325944Sjoerg case STATE_CLOSING: 202425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 202525944Sjoerg break; 202625944Sjoerg } 202725944Sjoerg} 20284910Swollman 202925944Sjoerg 203025944Sjoergstatic void 203125944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 203225944Sjoerg{ 203325944Sjoerg STDDCL; 203425944Sjoerg 203525944Sjoerg if (debug) 203640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 203740008Sjoerg SPP_ARGS(ifp), cp->name, 203825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 203925944Sjoerg 204025944Sjoerg switch (sp->state[cp->protoidx]) { 204125944Sjoerg case STATE_INITIAL: 204225944Sjoerg case STATE_CLOSED: 204325944Sjoerg case STATE_CLOSING: 20444910Swollman break; 204525944Sjoerg case STATE_STARTING: 204641881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 204725944Sjoerg (cp->tlf)(sp); 20484910Swollman break; 204925944Sjoerg case STATE_STOPPED: 205025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20514910Swollman break; 205225944Sjoerg case STATE_STOPPING: 205325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20544910Swollman break; 205525944Sjoerg case STATE_OPENED: 205625944Sjoerg (cp->tld)(sp); 2057102412Scharnier /* FALLTHROUGH */ 205825944Sjoerg case STATE_REQ_SENT: 205925944Sjoerg case STATE_ACK_RCVD: 206025944Sjoerg case STATE_ACK_SENT: 206125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 206278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 206378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 206425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20654910Swollman break; 20664910Swollman } 20674910Swollman} 20684910Swollman 206925944Sjoergstatic void 207025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 207125944Sjoerg{ 207225944Sjoerg STDDCL; 207325944Sjoerg int s; 207425944Sjoerg 207525944Sjoerg s = splimp(); 2076138745Srik SPPP_LOCK(sp); 207725944Sjoerg if (debug) 207840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 207940008Sjoerg SPP_ARGS(ifp), cp->name, 208025944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 208125944Sjoerg sp->rst_counter[cp->protoidx]); 208225944Sjoerg 208325944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 208425944Sjoerg /* TO- event */ 208525944Sjoerg switch (sp->state[cp->protoidx]) { 208625944Sjoerg case STATE_CLOSING: 208741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 208825944Sjoerg (cp->tlf)(sp); 208925944Sjoerg break; 209025944Sjoerg case STATE_STOPPING: 209141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 209225944Sjoerg (cp->tlf)(sp); 209325944Sjoerg break; 209425944Sjoerg case STATE_REQ_SENT: 209525944Sjoerg case STATE_ACK_RCVD: 209625944Sjoerg case STATE_ACK_SENT: 209741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 209825944Sjoerg (cp->tlf)(sp); 209925944Sjoerg break; 210025944Sjoerg } 210125944Sjoerg else 210225944Sjoerg /* TO+ event */ 210325944Sjoerg switch (sp->state[cp->protoidx]) { 210425944Sjoerg case STATE_CLOSING: 210525944Sjoerg case STATE_STOPPING: 210678064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 210778064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2108138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2109138745Srik cp->TO, (void *)sp); 211025944Sjoerg break; 211125944Sjoerg case STATE_REQ_SENT: 211225944Sjoerg case STATE_ACK_RCVD: 211325944Sjoerg (cp->scr)(sp); 211425944Sjoerg /* sppp_cp_change_state() will restart the timer */ 211525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 211625944Sjoerg break; 211725944Sjoerg case STATE_ACK_SENT: 211825944Sjoerg (cp->scr)(sp); 2119138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2120138745Srik cp->TO, (void *)sp); 212125944Sjoerg break; 212225944Sjoerg } 212325944Sjoerg 2124138745Srik SPPP_UNLOCK(sp); 212525944Sjoerg splx(s); 212625944Sjoerg} 212725944Sjoerg 212811189Sjkh/* 212925944Sjoerg * Change the state of a control protocol in the state automaton. 213025944Sjoerg * Takes care of starting/stopping the restart timer. 213111189Sjkh */ 2132105228Sphkstatic void 213325944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 213425944Sjoerg{ 213525944Sjoerg sp->state[cp->protoidx] = newstate; 213625944Sjoerg 2137138745Srik callout_stop (&sp->ch[cp->protoidx]); 2138138745Srik 213925944Sjoerg switch (newstate) { 214025944Sjoerg case STATE_INITIAL: 214125944Sjoerg case STATE_STARTING: 214225944Sjoerg case STATE_CLOSED: 214325944Sjoerg case STATE_STOPPED: 214425944Sjoerg case STATE_OPENED: 214525944Sjoerg break; 214625944Sjoerg case STATE_CLOSING: 214725944Sjoerg case STATE_STOPPING: 214825944Sjoerg case STATE_REQ_SENT: 214925944Sjoerg case STATE_ACK_RCVD: 215025944Sjoerg case STATE_ACK_SENT: 2151138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2152138745Srik cp->TO, (void *)sp); 215325944Sjoerg break; 215425944Sjoerg } 215525944Sjoerg} 215670199Sjhay 215770199Sjhay/* 215825944Sjoerg *--------------------------------------------------------------------------* 215925944Sjoerg * * 216025944Sjoerg * The LCP implementation. * 216125944Sjoerg * * 216225944Sjoerg *--------------------------------------------------------------------------* 216325944Sjoerg */ 216425944Sjoergstatic void 2165138745Sriksppp_pp_up(struct sppp *sp) 2166138745Srik{ 2167138745Srik SPPP_LOCK(sp); 2168138745Srik lcp.Up(sp); 2169138745Srik SPPP_UNLOCK(sp); 2170138745Srik} 2171138745Srik 2172138745Srikstatic void 2173138745Sriksppp_pp_down(struct sppp *sp) 2174138745Srik{ 2175138745Srik SPPP_LOCK(sp); 2176138745Srik lcp.Down(sp); 2177138745Srik SPPP_UNLOCK(sp); 2178138745Srik} 2179138745Srik 2180138745Srikstatic void 218125944Sjoergsppp_lcp_init(struct sppp *sp) 218225944Sjoerg{ 218325944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 218425944Sjoerg sp->lcp.magic = 0; 218525944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 218625944Sjoerg sp->fail_counter[IDX_LCP] = 0; 218778064Sume sp->pp_seq[IDX_LCP] = 0; 218878064Sume sp->pp_rseq[IDX_LCP] = 0; 218925944Sjoerg sp->lcp.protos = 0; 219025944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 219130300Sjoerg 219244145Sphk /* Note that these values are relevant for all control protocols */ 219344145Sphk sp->lcp.timeout = 3 * hz; 219425944Sjoerg sp->lcp.max_terminate = 2; 219525944Sjoerg sp->lcp.max_configure = 10; 219625944Sjoerg sp->lcp.max_failure = 10; 2197188668Srwatson callout_init(&sp->ch[IDX_LCP], CALLOUT_MPSAFE); 219825944Sjoerg} 219925944Sjoerg 220025944Sjoergstatic void 220125944Sjoergsppp_lcp_up(struct sppp *sp) 220225944Sjoerg{ 220325944Sjoerg STDDCL; 220425944Sjoerg 220570199Sjhay sp->pp_alivecnt = 0; 220670199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 220770199Sjhay sp->lcp.magic = 0; 220870199Sjhay sp->lcp.protos = 0; 220970199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 221025944Sjoerg /* 221175321Sjoerg * If we are authenticator, negotiate LCP_AUTH 221275321Sjoerg */ 221375321Sjoerg if (sp->hisauth.proto != 0) 221475321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 221575321Sjoerg else 221675321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 221775321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 221875321Sjoerg /* 221930300Sjoerg * If this interface is passive or dial-on-demand, and we are 222030300Sjoerg * still in Initial state, it means we've got an incoming 222130300Sjoerg * call. Activate the interface. 222225944Sjoerg */ 222325944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 222425944Sjoerg if (debug) 222525944Sjoerg log(LOG_DEBUG, 222640008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2227148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 222830300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 222930300Sjoerg if (debug) 223069211Sphk log(-1, "(incoming call)\n"); 223130300Sjoerg sp->pp_flags |= PP_CALLIN; 223230300Sjoerg lcp.Open(sp); 223330300Sjoerg } else if (debug) 223469211Sphk log(-1, "\n"); 223588710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 223688710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2237148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 223888710Sjoerg lcp.Open(sp); 223925944Sjoerg } 224025944Sjoerg 224125944Sjoerg sppp_up_event(&lcp, sp); 224225944Sjoerg} 224325944Sjoerg 224425944Sjoergstatic void 224525944Sjoergsppp_lcp_down(struct sppp *sp) 224625944Sjoerg{ 224725944Sjoerg STDDCL; 224825944Sjoerg 224925944Sjoerg sppp_down_event(&lcp, sp); 225025944Sjoerg 225125944Sjoerg /* 225225944Sjoerg * If this is neither a dial-on-demand nor a passive 225325944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 225425944Sjoerg * administrator can force a redial by another ``ifconfig 225525944Sjoerg * up''. XXX For leased line operation, should we immediately 225625944Sjoerg * try to reopen the connection here? 225725944Sjoerg */ 225825944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 225925944Sjoerg log(LOG_INFO, 226042066Sphk SPP_FMT "Down event, taking interface down.\n", 226140008Sjoerg SPP_ARGS(ifp)); 226225944Sjoerg if_down(ifp); 226325944Sjoerg } else { 226425944Sjoerg if (debug) 226525944Sjoerg log(LOG_DEBUG, 226640008Sjoerg SPP_FMT "Down event (carrier loss)\n", 226740008Sjoerg SPP_ARGS(ifp)); 226870199Sjhay sp->pp_flags &= ~PP_CALLIN; 226970199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 227070199Sjhay lcp.Close(sp); 2271148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 227225944Sjoerg } 227325944Sjoerg} 227425944Sjoerg 227525944Sjoergstatic void 227625944Sjoergsppp_lcp_open(struct sppp *sp) 227725944Sjoerg{ 227825944Sjoerg sppp_open_event(&lcp, sp); 227925944Sjoerg} 228025944Sjoerg 228125944Sjoergstatic void 228225944Sjoergsppp_lcp_close(struct sppp *sp) 228325944Sjoerg{ 228425944Sjoerg sppp_close_event(&lcp, sp); 228525944Sjoerg} 228625944Sjoerg 228725944Sjoergstatic void 228825944Sjoergsppp_lcp_TO(void *cookie) 228925944Sjoerg{ 229025944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 229125944Sjoerg} 229225944Sjoerg 229325944Sjoerg/* 229425944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 229525944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 229625944Sjoerg * caused action scn. (The return value is used to make the state 229725944Sjoerg * transition decision in the state automaton.) 229825944Sjoerg */ 229912820Sphkstatic int 230025944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 23014910Swollman{ 230225944Sjoerg STDDCL; 230311189Sjkh u_char *buf, *r, *p; 230425944Sjoerg int origlen, rlen; 230525944Sjoerg u_long nmagic; 230630300Sjoerg u_short authproto; 23074910Swollman 230811189Sjkh len -= 4; 230925944Sjoerg origlen = len; 231011189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 231111189Sjkh if (! buf) 231211189Sjkh return (0); 23134910Swollman 231425706Sjoerg if (debug) 231540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 231640008Sjoerg SPP_ARGS(ifp)); 231725706Sjoerg 231825944Sjoerg /* pass 1: check for things that need to be rejected */ 231911189Sjkh p = (void*) (h+1); 2320161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2321161556Scperciva len-=p[1], p+=p[1]) { 232225944Sjoerg if (debug) 232369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 232411189Sjkh switch (*p) { 232511189Sjkh case LCP_OPT_MAGIC: 232625944Sjoerg /* Magic number. */ 232770199Sjhay if (len >= 6 && p[1] == 6) 232870199Sjhay continue; 232970199Sjhay if (debug) 233070199Sjhay log(-1, "[invalid] "); 233170199Sjhay break; 233225944Sjoerg case LCP_OPT_ASYNC_MAP: 233325944Sjoerg /* Async control character map. */ 233470199Sjhay if (len >= 6 && p[1] == 6) 233525944Sjoerg continue; 233625944Sjoerg if (debug) 233769211Sphk log(-1, "[invalid] "); 233825944Sjoerg break; 233925944Sjoerg case LCP_OPT_MRU: 234025944Sjoerg /* Maximum receive unit. */ 234125944Sjoerg if (len >= 4 && p[1] == 4) 234225944Sjoerg continue; 234325944Sjoerg if (debug) 234469211Sphk log(-1, "[invalid] "); 234525944Sjoerg break; 234630300Sjoerg case LCP_OPT_AUTH_PROTO: 234730300Sjoerg if (len < 4) { 234830300Sjoerg if (debug) 234969211Sphk log(-1, "[invalid] "); 235030300Sjoerg break; 235130300Sjoerg } 235230300Sjoerg authproto = (p[2] << 8) + p[3]; 235330300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 235430300Sjoerg if (debug) 235569211Sphk log(-1, "[invalid chap len] "); 235630300Sjoerg break; 235730300Sjoerg } 235830300Sjoerg if (sp->myauth.proto == 0) { 235930300Sjoerg /* we are not configured to do auth */ 236030300Sjoerg if (debug) 236169211Sphk log(-1, "[not configured] "); 236230300Sjoerg break; 236330300Sjoerg } 236430300Sjoerg /* 236530300Sjoerg * Remote want us to authenticate, remember this, 236630300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 236730300Sjoerg * up. 236830300Sjoerg */ 236930300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 237030300Sjoerg continue; 237125944Sjoerg default: 237225944Sjoerg /* Others not supported. */ 237325944Sjoerg if (debug) 237469211Sphk log(-1, "[rej] "); 237525944Sjoerg break; 237625944Sjoerg } 237725944Sjoerg /* Add the option to rejected list. */ 237825944Sjoerg bcopy (p, r, p[1]); 237925944Sjoerg r += p[1]; 238025944Sjoerg rlen += p[1]; 238125944Sjoerg } 238225944Sjoerg if (rlen) { 238325944Sjoerg if (debug) 238469211Sphk log(-1, " send conf-rej\n"); 238525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 238625944Sjoerg return 0; 238725944Sjoerg } else if (debug) 238869211Sphk log(-1, "\n"); 238925944Sjoerg 239025944Sjoerg /* 239125944Sjoerg * pass 2: check for option values that are unacceptable and 239225944Sjoerg * thus require to be nak'ed. 239325944Sjoerg */ 239425944Sjoerg if (debug) 239540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 239640008Sjoerg SPP_ARGS(ifp)); 239725944Sjoerg 239825944Sjoerg p = (void*) (h+1); 239925944Sjoerg len = origlen; 2400161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2401161556Scperciva len-=p[1], p+=p[1]) { 240225944Sjoerg if (debug) 240369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 240425944Sjoerg switch (*p) { 240525944Sjoerg case LCP_OPT_MAGIC: 240611189Sjkh /* Magic number -- extract. */ 240725944Sjoerg nmagic = (u_long)p[2] << 24 | 240825944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 240925944Sjoerg if (nmagic != sp->lcp.magic) { 241070199Sjhay sp->pp_loopcnt = 0; 241125706Sjoerg if (debug) 241269211Sphk log(-1, "0x%lx ", nmagic); 241311189Sjkh continue; 241411189Sjkh } 241570199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 241669211Sphk log(-1, "[glitch] "); 241725944Sjoerg ++sp->pp_loopcnt; 241825944Sjoerg /* 241925944Sjoerg * We negate our magic here, and NAK it. If 242025944Sjoerg * we see it later in an NAK packet, we 242125944Sjoerg * suggest a new one. 242225944Sjoerg */ 242325944Sjoerg nmagic = ~sp->lcp.magic; 242425944Sjoerg /* Gonna NAK it. */ 242525944Sjoerg p[2] = nmagic >> 24; 242625944Sjoerg p[3] = nmagic >> 16; 242725944Sjoerg p[4] = nmagic >> 8; 242825944Sjoerg p[5] = nmagic; 242911189Sjkh break; 243025944Sjoerg 243111189Sjkh case LCP_OPT_ASYNC_MAP: 243288506Sjoerg /* 243388506Sjoerg * Async control character map -- just ignore it. 243488506Sjoerg * 243588506Sjoerg * Quote from RFC 1662, chapter 6: 243688506Sjoerg * To enable this functionality, synchronous PPP 243788506Sjoerg * implementations MUST always respond to the 243888506Sjoerg * Async-Control-Character-Map Configuration 243988506Sjoerg * Option with the LCP Configure-Ack. However, 244088506Sjoerg * acceptance of the Configuration Option does 244188506Sjoerg * not imply that the synchronous implementation 244288506Sjoerg * will do any ACCM mapping. Instead, all such 244388506Sjoerg * octet mapping will be performed by the 244488506Sjoerg * asynchronous-to-synchronous converter. 244588506Sjoerg */ 244688506Sjoerg continue; 244725944Sjoerg 244811189Sjkh case LCP_OPT_MRU: 244925944Sjoerg /* 245025944Sjoerg * Maximum receive unit. Always agreeable, 245125944Sjoerg * but ignored by now. 245225944Sjoerg */ 245325944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 245425706Sjoerg if (debug) 245569211Sphk log(-1, "%lu ", sp->lcp.their_mru); 245611189Sjkh continue; 245730300Sjoerg 245830300Sjoerg case LCP_OPT_AUTH_PROTO: 245930300Sjoerg authproto = (p[2] << 8) + p[3]; 246030300Sjoerg if (sp->myauth.proto != authproto) { 246130300Sjoerg /* not agreed, nak */ 246230300Sjoerg if (debug) 246369211Sphk log(-1, "[mine %s != his %s] ", 246430300Sjoerg sppp_proto_name(sp->hisauth.proto), 246530300Sjoerg sppp_proto_name(authproto)); 246630300Sjoerg p[2] = sp->myauth.proto >> 8; 246730300Sjoerg p[3] = sp->myauth.proto; 246830300Sjoerg break; 246930300Sjoerg } 247030300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 247130300Sjoerg if (debug) 247269211Sphk log(-1, "[chap not MD5] "); 247339981Sjoerg p[4] = CHAP_MD5; 247430300Sjoerg break; 247530300Sjoerg } 247630300Sjoerg continue; 247711189Sjkh } 247825944Sjoerg /* Add the option to nak'ed list. */ 247925706Sjoerg bcopy (p, r, p[1]); 248025706Sjoerg r += p[1]; 248111189Sjkh rlen += p[1]; 248212436Speter } 248325706Sjoerg if (rlen) { 248470199Sjhay /* 248570199Sjhay * Local and remote magics equal -- loopback? 248670199Sjhay */ 248770199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 248870199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 248970199Sjhay printf (SPP_FMT "loopback\n", 249070199Sjhay SPP_ARGS(ifp)); 249170199Sjhay if (ifp->if_flags & IFF_UP) { 249270199Sjhay if_down(ifp); 249370199Sjhay sppp_qflush(&sp->pp_cpq); 249470199Sjhay /* XXX ? */ 249570199Sjhay lcp.Down(sp); 249670199Sjhay lcp.Up(sp); 249770199Sjhay } 2498131093Srik } else if (!sp->pp_loopcnt && 2499131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 250028036Sjoerg if (debug) 250169211Sphk log(-1, " max_failure (%d) exceeded, " 250228036Sjoerg "send conf-rej\n", 250328036Sjoerg sp->lcp.max_failure); 250428036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 250528036Sjoerg } else { 250628036Sjoerg if (debug) 250769211Sphk log(-1, " send conf-nak\n"); 250828036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 250928036Sjoerg } 251025944Sjoerg } else { 251125944Sjoerg if (debug) 251269211Sphk log(-1, " send conf-ack\n"); 251328036Sjoerg sp->fail_counter[IDX_LCP] = 0; 251425944Sjoerg sp->pp_loopcnt = 0; 251525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 251625944Sjoerg h->ident, origlen, h+1); 251725944Sjoerg } 251825944Sjoerg 251911189Sjkh free (buf, M_TEMP); 252011189Sjkh return (rlen == 0); 25214910Swollman} 25224910Swollman 252325944Sjoerg/* 252425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 252525944Sjoerg * negotiation. 252625944Sjoerg */ 252712820Sphkstatic void 252825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 25294910Swollman{ 253025944Sjoerg STDDCL; 253125944Sjoerg u_char *buf, *p; 25324910Swollman 253325944Sjoerg len -= 4; 253425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 253525944Sjoerg if (!buf) 25364910Swollman return; 253725944Sjoerg 253825944Sjoerg if (debug) 253940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 254040008Sjoerg SPP_ARGS(ifp)); 254125944Sjoerg 254225944Sjoerg p = (void*) (h+1); 2543161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2544161556Scperciva len -= p[1], p += p[1]) { 254525944Sjoerg if (debug) 254669211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 254725944Sjoerg switch (*p) { 254825944Sjoerg case LCP_OPT_MAGIC: 254925944Sjoerg /* Magic number -- can't use it, use 0 */ 255025944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 255125944Sjoerg sp->lcp.magic = 0; 255225944Sjoerg break; 255325944Sjoerg case LCP_OPT_MRU: 255425944Sjoerg /* 255525944Sjoerg * Should not be rejected anyway, since we only 255625944Sjoerg * negotiate a MRU if explicitly requested by 255725944Sjoerg * peer. 255825944Sjoerg */ 255925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 256025944Sjoerg break; 256130300Sjoerg case LCP_OPT_AUTH_PROTO: 256230300Sjoerg /* 256330300Sjoerg * Peer doesn't want to authenticate himself, 256430300Sjoerg * deny unless this is a dialout call, and 256530300Sjoerg * AUTHFLAG_NOCALLOUT is set. 256630300Sjoerg */ 256730300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 256830300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 256930300Sjoerg if (debug) 257069211Sphk log(-1, "[don't insist on auth " 257130300Sjoerg "for callout]"); 257230300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 257330300Sjoerg break; 257430300Sjoerg } 257530300Sjoerg if (debug) 257669211Sphk log(-1, "[access denied]\n"); 257730300Sjoerg lcp.Close(sp); 257830300Sjoerg break; 257925944Sjoerg } 25804910Swollman } 258125944Sjoerg if (debug) 258269211Sphk log(-1, "\n"); 258325944Sjoerg free (buf, M_TEMP); 258425944Sjoerg return; 258525944Sjoerg} 258625944Sjoerg 258725944Sjoerg/* 258825944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 258925944Sjoerg * negotiation. 259025944Sjoerg */ 259125944Sjoergstatic void 259225944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 259325944Sjoerg{ 259425944Sjoerg STDDCL; 259525944Sjoerg u_char *buf, *p; 259625944Sjoerg u_long magic; 259725944Sjoerg 259825944Sjoerg len -= 4; 259925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 260025944Sjoerg if (!buf) 260125944Sjoerg return; 260225944Sjoerg 260325944Sjoerg if (debug) 260440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 260540008Sjoerg SPP_ARGS(ifp)); 260625944Sjoerg 260725944Sjoerg p = (void*) (h+1); 2608161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2609161556Scperciva len -= p[1], p += p[1]) { 261025706Sjoerg if (debug) 261169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 261225944Sjoerg switch (*p) { 261325944Sjoerg case LCP_OPT_MAGIC: 261425944Sjoerg /* Magic number -- renegotiate */ 261525944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 261625944Sjoerg len >= 6 && p[1] == 6) { 261725944Sjoerg magic = (u_long)p[2] << 24 | 261825944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 261925944Sjoerg /* 262025944Sjoerg * If the remote magic is our negated one, 262125944Sjoerg * this looks like a loopback problem. 262225944Sjoerg * Suggest a new magic to make sure. 262325944Sjoerg */ 262425944Sjoerg if (magic == ~sp->lcp.magic) { 262525944Sjoerg if (debug) 262669211Sphk log(-1, "magic glitch "); 262735064Sphk sp->lcp.magic = random(); 262825944Sjoerg } else { 262925944Sjoerg sp->lcp.magic = magic; 263025944Sjoerg if (debug) 263169211Sphk log(-1, "%lu ", magic); 263225944Sjoerg } 263325944Sjoerg } 263425944Sjoerg break; 263525944Sjoerg case LCP_OPT_MRU: 263625944Sjoerg /* 263725944Sjoerg * Peer wants to advise us to negotiate an MRU. 263825944Sjoerg * Agree on it if it's reasonable, or use 263925944Sjoerg * default otherwise. 264025944Sjoerg */ 264125944Sjoerg if (len >= 4 && p[1] == 4) { 264225944Sjoerg u_int mru = p[2] * 256 + p[3]; 264325944Sjoerg if (debug) 264469211Sphk log(-1, "%d ", mru); 264525944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 264625944Sjoerg mru = PP_MTU; 264725944Sjoerg sp->lcp.mru = mru; 264825944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 264925944Sjoerg } 265025944Sjoerg break; 265130300Sjoerg case LCP_OPT_AUTH_PROTO: 265230300Sjoerg /* 265330300Sjoerg * Peer doesn't like our authentication method, 265430300Sjoerg * deny. 265530300Sjoerg */ 265630300Sjoerg if (debug) 265769211Sphk log(-1, "[access denied]\n"); 265830300Sjoerg lcp.Close(sp); 265930300Sjoerg break; 26604910Swollman } 266125944Sjoerg } 266225944Sjoerg if (debug) 266369211Sphk log(-1, "\n"); 266425944Sjoerg free (buf, M_TEMP); 266525944Sjoerg return; 266625944Sjoerg} 266711189Sjkh 266825944Sjoergstatic void 266925944Sjoergsppp_lcp_tlu(struct sppp *sp) 267025944Sjoerg{ 267142066Sphk STDDCL; 267225944Sjoerg int i; 267325944Sjoerg u_long mask; 267425944Sjoerg 267525944Sjoerg /* XXX ? */ 267625944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2677148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 267825944Sjoerg /* Coming out of loopback mode. */ 267925944Sjoerg if_up(ifp); 268040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 268125944Sjoerg } 268225944Sjoerg 268325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 268425944Sjoerg if ((cps[i])->flags & CP_QUAL) 268525944Sjoerg (cps[i])->Open(sp); 268625944Sjoerg 268730300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 268830300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 268925944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 269025944Sjoerg else 269125944Sjoerg sp->pp_phase = PHASE_NETWORK; 269225944Sjoerg 269342066Sphk if (debug) 269442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 269542066Sphk sppp_phase_name(sp->pp_phase)); 269625944Sjoerg 269730300Sjoerg /* 269830300Sjoerg * Open all authentication protocols. This is even required 269930300Sjoerg * if we already proceeded to network phase, since it might be 270030300Sjoerg * that remote wants us to authenticate, so we might have to 270130300Sjoerg * send a PAP request. Undesired authentication protocols 270230300Sjoerg * don't do anything when they get an Open event. 270330300Sjoerg */ 270430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 270530300Sjoerg if ((cps[i])->flags & CP_AUTH) 270630300Sjoerg (cps[i])->Open(sp); 270730300Sjoerg 270830300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 270925944Sjoerg /* Notify all NCPs. */ 271025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 271188723Sjoerg if (((cps[i])->flags & CP_NCP) && 271288723Sjoerg /* 271388723Sjoerg * XXX 271488723Sjoerg * Hack to administratively disable IPv6 if 271588723Sjoerg * not desired. Perhaps we should have another 271688723Sjoerg * flag for this, but right now, we can make 271788723Sjoerg * all struct cp's read/only. 271888723Sjoerg */ 271988723Sjoerg (cps[i] != &ipv6cp || 272088723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 272125944Sjoerg (cps[i])->Open(sp); 272225944Sjoerg } 272325944Sjoerg 272425944Sjoerg /* Send Up events to all started protos. */ 272525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 272688706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 272725944Sjoerg (cps[i])->Up(sp); 272825944Sjoerg 272942104Sphk /* notify low-level driver of state change */ 273042104Sphk if (sp->pp_chg) 273142104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 273242104Sphk 273325944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 273425944Sjoerg /* if no NCP is starting, close down */ 273530300Sjoerg sppp_lcp_check_and_close(sp); 273625944Sjoerg} 273725944Sjoerg 273825944Sjoergstatic void 273925944Sjoergsppp_lcp_tld(struct sppp *sp) 274025944Sjoerg{ 274142066Sphk STDDCL; 274225944Sjoerg int i; 274325944Sjoerg u_long mask; 274425944Sjoerg 274525944Sjoerg sp->pp_phase = PHASE_TERMINATE; 274625944Sjoerg 274742066Sphk if (debug) 274842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 274942066Sphk sppp_phase_name(sp->pp_phase)); 275025944Sjoerg 275125944Sjoerg /* 275225944Sjoerg * Take upper layers down. We send the Down event first and 275325944Sjoerg * the Close second to prevent the upper layers from sending 275425944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 275525944Sjoerg * describes it. 275625944Sjoerg */ 275725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 275888706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 275925944Sjoerg (cps[i])->Down(sp); 276025944Sjoerg (cps[i])->Close(sp); 276125944Sjoerg } 276225944Sjoerg} 276325944Sjoerg 276425944Sjoergstatic void 276525944Sjoergsppp_lcp_tls(struct sppp *sp) 276625944Sjoerg{ 276742066Sphk STDDCL; 276825944Sjoerg 276925944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 277025944Sjoerg 277142066Sphk if (debug) 277242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 277342066Sphk sppp_phase_name(sp->pp_phase)); 277425944Sjoerg 277525944Sjoerg /* Notify lower layer if desired. */ 277625944Sjoerg if (sp->pp_tls) 277725944Sjoerg (sp->pp_tls)(sp); 277841881Sphk else 277941881Sphk (sp->pp_up)(sp); 278025944Sjoerg} 278125944Sjoerg 278225944Sjoergstatic void 278325944Sjoergsppp_lcp_tlf(struct sppp *sp) 278425944Sjoerg{ 278542066Sphk STDDCL; 278625944Sjoerg 278725944Sjoerg sp->pp_phase = PHASE_DEAD; 278842066Sphk if (debug) 278942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 279042066Sphk sppp_phase_name(sp->pp_phase)); 279125944Sjoerg 279225944Sjoerg /* Notify lower layer if desired. */ 279325944Sjoerg if (sp->pp_tlf) 279425944Sjoerg (sp->pp_tlf)(sp); 279541881Sphk else 279641881Sphk (sp->pp_down)(sp); 279725944Sjoerg} 279825944Sjoerg 279925944Sjoergstatic void 280025944Sjoergsppp_lcp_scr(struct sppp *sp) 280125944Sjoerg{ 280230300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 280325944Sjoerg int i = 0; 280430300Sjoerg u_short authproto; 280525944Sjoerg 280625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 280725944Sjoerg if (! sp->lcp.magic) 280835064Sphk sp->lcp.magic = random(); 280925944Sjoerg opt[i++] = LCP_OPT_MAGIC; 281025944Sjoerg opt[i++] = 6; 281125944Sjoerg opt[i++] = sp->lcp.magic >> 24; 281225944Sjoerg opt[i++] = sp->lcp.magic >> 16; 281325944Sjoerg opt[i++] = sp->lcp.magic >> 8; 281425944Sjoerg opt[i++] = sp->lcp.magic; 281525944Sjoerg } 281625944Sjoerg 281725944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 281825944Sjoerg opt[i++] = LCP_OPT_MRU; 281925944Sjoerg opt[i++] = 4; 282025944Sjoerg opt[i++] = sp->lcp.mru >> 8; 282125944Sjoerg opt[i++] = sp->lcp.mru; 282225944Sjoerg } 282325944Sjoerg 282430300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 282530300Sjoerg authproto = sp->hisauth.proto; 282630300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 282730300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 282830300Sjoerg opt[i++] = authproto >> 8; 282930300Sjoerg opt[i++] = authproto; 283030300Sjoerg if (authproto == PPP_CHAP) 283130300Sjoerg opt[i++] = CHAP_MD5; 283230300Sjoerg } 283330300Sjoerg 283478064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 283525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 283625944Sjoerg} 283725944Sjoerg 283825944Sjoerg/* 283930300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 284030300Sjoerg */ 284130300Sjoergstatic int 284230300Sjoergsppp_ncp_check(struct sppp *sp) 284330300Sjoerg{ 284430300Sjoerg int i, mask; 284530300Sjoerg 284630300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 284788706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 284830300Sjoerg return 1; 284930300Sjoerg return 0; 285030300Sjoerg} 285130300Sjoerg 285230300Sjoerg/* 285325944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 285425944Sjoerg * Called by the NCPs during their tlf action handling. 285525944Sjoerg */ 285625944Sjoergstatic void 285730300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 285825944Sjoerg{ 285925944Sjoerg 286030300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 286130300Sjoerg /* don't bother, we are already going down */ 286230300Sjoerg return; 286330300Sjoerg 286430300Sjoerg if (sppp_ncp_check(sp)) 286530300Sjoerg return; 286630300Sjoerg 286725944Sjoerg lcp.Close(sp); 286825944Sjoerg} 286970199Sjhay 287070199Sjhay/* 287125944Sjoerg *--------------------------------------------------------------------------* 287225944Sjoerg * * 287325944Sjoerg * The IPCP implementation. * 287425944Sjoerg * * 287525944Sjoerg *--------------------------------------------------------------------------* 287625944Sjoerg */ 287725944Sjoerg 2878184682Sbz#ifdef INET 287925944Sjoergstatic void 288025944Sjoergsppp_ipcp_init(struct sppp *sp) 288125944Sjoerg{ 288225944Sjoerg sp->ipcp.opts = 0; 288325944Sjoerg sp->ipcp.flags = 0; 288425944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 288525944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 288678064Sume sp->pp_seq[IDX_IPCP] = 0; 288778064Sume sp->pp_rseq[IDX_IPCP] = 0; 2888188668Srwatson callout_init(&sp->ch[IDX_IPCP], CALLOUT_MPSAFE); 288925944Sjoerg} 289025944Sjoerg 289125944Sjoergstatic void 289225944Sjoergsppp_ipcp_up(struct sppp *sp) 289325944Sjoerg{ 289425944Sjoerg sppp_up_event(&ipcp, sp); 289525944Sjoerg} 289625944Sjoerg 289725944Sjoergstatic void 289825944Sjoergsppp_ipcp_down(struct sppp *sp) 289925944Sjoerg{ 290025944Sjoerg sppp_down_event(&ipcp, sp); 290125944Sjoerg} 290225944Sjoerg 290325944Sjoergstatic void 290425944Sjoergsppp_ipcp_open(struct sppp *sp) 290525944Sjoerg{ 290625944Sjoerg STDDCL; 290725944Sjoerg u_long myaddr, hisaddr; 290825944Sjoerg 290988534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 291088534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 291188700Sjoerg sp->ipcp.opts = 0; 291242104Sphk 291330300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 291425944Sjoerg /* 291525944Sjoerg * If we don't have his address, this probably means our 291625944Sjoerg * interface doesn't want to talk IP at all. (This could 291725944Sjoerg * be the case if somebody wants to speak only IPX, for 291825944Sjoerg * example.) Don't open IPCP in this case. 291925944Sjoerg */ 292025944Sjoerg if (hisaddr == 0L) { 292125944Sjoerg /* XXX this message should go away */ 292225944Sjoerg if (debug) 292340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 292440008Sjoerg SPP_ARGS(ifp)); 292525944Sjoerg return; 292625944Sjoerg } 292725944Sjoerg if (myaddr == 0L) { 292825944Sjoerg /* 292925944Sjoerg * I don't have an assigned address, so i need to 293025944Sjoerg * negotiate my address. 293125944Sjoerg */ 293225944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 293325944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 293442104Sphk } else 293542104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 293688723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 293788534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 293888534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 293988534Sjoerg sp->ipcp.compress_cid = 1; 294088534Sjoerg } 294125944Sjoerg sppp_open_event(&ipcp, sp); 294225944Sjoerg} 294325944Sjoerg 294425944Sjoergstatic void 294525944Sjoergsppp_ipcp_close(struct sppp *sp) 294625944Sjoerg{ 294725944Sjoerg sppp_close_event(&ipcp, sp); 294825944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 294925944Sjoerg /* 295025944Sjoerg * My address was dynamic, clear it again. 295125944Sjoerg */ 295225944Sjoerg sppp_set_ip_addr(sp, 0L); 295325944Sjoerg} 295425944Sjoerg 295525944Sjoergstatic void 295625944Sjoergsppp_ipcp_TO(void *cookie) 295725944Sjoerg{ 295825944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 295925944Sjoerg} 296025944Sjoerg 296125944Sjoerg/* 296225944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 296325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 296425944Sjoerg * caused action scn. (The return value is used to make the state 296525944Sjoerg * transition decision in the state automaton.) 296625944Sjoerg */ 296725944Sjoergstatic int 296825944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 296925944Sjoerg{ 297025944Sjoerg u_char *buf, *r, *p; 2971147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 297225944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 297325944Sjoerg u_long hisaddr, desiredaddr; 297442104Sphk int gotmyaddr = 0; 297588534Sjoerg int desiredcomp; 297625944Sjoerg 297725944Sjoerg len -= 4; 297825944Sjoerg origlen = len; 297925944Sjoerg /* 298025944Sjoerg * Make sure to allocate a buf that can at least hold a 298125944Sjoerg * conf-nak with an `address' option. We might need it below. 298225944Sjoerg */ 298325944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 298425944Sjoerg if (! buf) 298525944Sjoerg return (0); 298625944Sjoerg 298725944Sjoerg /* pass 1: see if we can recognize them */ 298825944Sjoerg if (debug) 298940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 299040008Sjoerg SPP_ARGS(ifp)); 299125944Sjoerg p = (void*) (h+1); 2992161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2993161556Scperciva len-=p[1], p+=p[1]) { 299425944Sjoerg if (debug) 299569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 299625944Sjoerg switch (*p) { 299788534Sjoerg case IPCP_OPT_COMPRESSION: 299888723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 299988534Sjoerg /* VJ compression administratively disabled */ 300088534Sjoerg if (debug) 300188534Sjoerg log(-1, "[locally disabled] "); 300288534Sjoerg break; 300388534Sjoerg } 300488534Sjoerg /* 300588534Sjoerg * In theory, we should only conf-rej an 300688534Sjoerg * option that is shorter than RFC 1618 300788534Sjoerg * requires (i.e. < 4), and should conf-nak 300888534Sjoerg * anything else that is not VJ. However, 300988534Sjoerg * since our algorithm always uses the 301088534Sjoerg * original option to NAK it with new values, 301188534Sjoerg * things would become more complicated. In 301288534Sjoerg * pratice, the only commonly implemented IP 301388534Sjoerg * compression option is VJ anyway, so the 301488534Sjoerg * difference is negligible. 301588534Sjoerg */ 301688534Sjoerg if (len >= 6 && p[1] == 6) { 301788534Sjoerg /* 301888534Sjoerg * correctly formed compression option 301988534Sjoerg * that could be VJ compression 302088534Sjoerg */ 302188534Sjoerg continue; 302288534Sjoerg } 302388534Sjoerg if (debug) 302488534Sjoerg log(-1, 302588534Sjoerg "optlen %d [invalid/unsupported] ", 302688534Sjoerg p[1]); 302788534Sjoerg break; 302825944Sjoerg case IPCP_OPT_ADDRESS: 302925944Sjoerg if (len >= 6 && p[1] == 6) { 303025944Sjoerg /* correctly formed address option */ 303125944Sjoerg continue; 303225944Sjoerg } 303325706Sjoerg if (debug) 303469211Sphk log(-1, "[invalid] "); 303511189Sjkh break; 303625944Sjoerg default: 303725944Sjoerg /* Others not supported. */ 303825944Sjoerg if (debug) 303969211Sphk log(-1, "[rej] "); 30404910Swollman break; 30414910Swollman } 304225944Sjoerg /* Add the option to rejected list. */ 304325944Sjoerg bcopy (p, r, p[1]); 304425944Sjoerg r += p[1]; 304525944Sjoerg rlen += p[1]; 304625944Sjoerg } 304725944Sjoerg if (rlen) { 304825944Sjoerg if (debug) 304969211Sphk log(-1, " send conf-rej\n"); 305025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 305125944Sjoerg return 0; 305225944Sjoerg } else if (debug) 305369211Sphk log(-1, "\n"); 305425944Sjoerg 305525944Sjoerg /* pass 2: parse option values */ 305630300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 305725944Sjoerg if (debug) 305840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 305940008Sjoerg SPP_ARGS(ifp)); 306025944Sjoerg p = (void*) (h+1); 306125944Sjoerg len = origlen; 3062161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3063161556Scperciva len-=p[1], p+=p[1]) { 306425944Sjoerg if (debug) 306569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 306625944Sjoerg switch (*p) { 306788534Sjoerg case IPCP_OPT_COMPRESSION: 306888534Sjoerg desiredcomp = p[2] << 8 | p[3]; 306988534Sjoerg /* We only support VJ */ 307088534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 307188534Sjoerg if (debug) 307288534Sjoerg log(-1, "VJ [ack] "); 307388534Sjoerg sp->ipcp.flags |= IPCP_VJ; 307488599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 307588534Sjoerg sp->ipcp.max_state = p[4]; 307688534Sjoerg sp->ipcp.compress_cid = p[5]; 307788534Sjoerg continue; 307888534Sjoerg } 307988534Sjoerg if (debug) 308088534Sjoerg log(-1, 308188534Sjoerg "compproto %#04x [not supported] ", 308288534Sjoerg desiredcomp); 308388534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 308488534Sjoerg p[3] = IPCP_COMP_VJ; 308588534Sjoerg p[4] = sp->ipcp.max_state; 308688534Sjoerg p[5] = sp->ipcp.compress_cid; 308788534Sjoerg break; 308825944Sjoerg case IPCP_OPT_ADDRESS: 308942104Sphk /* This is the address he wants in his end */ 309025944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 309125944Sjoerg p[4] << 8 | p[5]; 309233928Sphk if (desiredaddr == hisaddr || 309388702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 309425944Sjoerg /* 309525944Sjoerg * Peer's address is same as our value, 309688702Sjoerg * or we have set it to 0.0.0.* to 309733928Sphk * indicate that we do not really care, 309825944Sjoerg * this is agreeable. Gonna conf-ack 309925944Sjoerg * it. 310025944Sjoerg */ 310125944Sjoerg if (debug) 310269211Sphk log(-1, "%s [ack] ", 310342104Sphk sppp_dotted_quad(hisaddr)); 310425944Sjoerg /* record that we've seen it already */ 310525944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 310625944Sjoerg continue; 310725944Sjoerg } 310825944Sjoerg /* 310925944Sjoerg * The address wasn't agreeable. This is either 311025944Sjoerg * he sent us 0.0.0.0, asking to assign him an 311125944Sjoerg * address, or he send us another address not 311225944Sjoerg * matching our value. Either case, we gonna 311325944Sjoerg * conf-nak it with our value. 311442104Sphk * XXX: we should "rej" if hisaddr == 0 311525944Sjoerg */ 311625944Sjoerg if (debug) { 311725944Sjoerg if (desiredaddr == 0) 311869211Sphk log(-1, "[addr requested] "); 311925944Sjoerg else 312069211Sphk log(-1, "%s [not agreed] ", 312142104Sphk sppp_dotted_quad(desiredaddr)); 312225944Sjoerg 312325944Sjoerg } 312444235Sphk p[2] = hisaddr >> 24; 312544235Sphk p[3] = hisaddr >> 16; 312644235Sphk p[4] = hisaddr >> 8; 312744235Sphk p[5] = hisaddr; 312811189Sjkh break; 312925706Sjoerg } 313025944Sjoerg /* Add the option to nak'ed list. */ 313125944Sjoerg bcopy (p, r, p[1]); 313225944Sjoerg r += p[1]; 313325944Sjoerg rlen += p[1]; 313425944Sjoerg } 313525944Sjoerg 313625944Sjoerg /* 313725944Sjoerg * If we are about to conf-ack the request, but haven't seen 313825944Sjoerg * his address so far, gonna conf-nak it instead, with the 313925944Sjoerg * `address' option present and our idea of his address being 314025944Sjoerg * filled in there, to request negotiation of both addresses. 314125944Sjoerg * 314225944Sjoerg * XXX This can result in an endless req - nak loop if peer 314325944Sjoerg * doesn't want to send us his address. Q: What should we do 314425944Sjoerg * about it? XXX A: implement the max-failure counter. 314525944Sjoerg */ 314642104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 314725944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 314825944Sjoerg buf[1] = 6; 314925944Sjoerg buf[2] = hisaddr >> 24; 315025944Sjoerg buf[3] = hisaddr >> 16; 315125944Sjoerg buf[4] = hisaddr >> 8; 315225944Sjoerg buf[5] = hisaddr; 315325944Sjoerg rlen = 6; 315425706Sjoerg if (debug) 315569211Sphk log(-1, "still need hisaddr "); 315625944Sjoerg } 315725944Sjoerg 315825944Sjoerg if (rlen) { 315925706Sjoerg if (debug) 316069211Sphk log(-1, " send conf-nak\n"); 316125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 316225944Sjoerg } else { 316325706Sjoerg if (debug) 316469211Sphk log(-1, " send conf-ack\n"); 316525944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 316625944Sjoerg h->ident, origlen, h+1); 316725944Sjoerg } 316825944Sjoerg 316925944Sjoerg free (buf, M_TEMP); 317025944Sjoerg return (rlen == 0); 317125944Sjoerg} 317225944Sjoerg 317325944Sjoerg/* 317425944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 317525944Sjoerg * negotiation. 317625944Sjoerg */ 317725944Sjoergstatic void 317825944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 317925944Sjoerg{ 318025944Sjoerg u_char *buf, *p; 3181147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 318225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 318325944Sjoerg 318425944Sjoerg len -= 4; 318525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 318625944Sjoerg if (!buf) 318725944Sjoerg return; 318825944Sjoerg 318925944Sjoerg if (debug) 319040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 319140008Sjoerg SPP_ARGS(ifp)); 319225944Sjoerg 319325944Sjoerg p = (void*) (h+1); 3194161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3195161556Scperciva len -= p[1], p += p[1]) { 319625706Sjoerg if (debug) 319769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 319825944Sjoerg switch (*p) { 319988534Sjoerg case IPCP_OPT_COMPRESSION: 320088534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 320188534Sjoerg break; 320225944Sjoerg case IPCP_OPT_ADDRESS: 320325944Sjoerg /* 320425944Sjoerg * Peer doesn't grok address option. This is 320525944Sjoerg * bad. XXX Should we better give up here? 320642104Sphk * XXX We could try old "addresses" option... 320725944Sjoerg */ 320825944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 320925944Sjoerg break; 321025944Sjoerg } 32114910Swollman } 321225944Sjoerg if (debug) 321369211Sphk log(-1, "\n"); 321425944Sjoerg free (buf, M_TEMP); 321525944Sjoerg return; 32164910Swollman} 32174910Swollman 321825944Sjoerg/* 321925944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 322025944Sjoerg * negotiation. 322125944Sjoerg */ 322212820Sphkstatic void 322325944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 32244910Swollman{ 322525944Sjoerg u_char *buf, *p; 3226147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 322725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 322888534Sjoerg int desiredcomp; 322925944Sjoerg u_long wantaddr; 32304910Swollman 323125944Sjoerg len -= 4; 323225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 323325944Sjoerg if (!buf) 323425944Sjoerg return; 323525944Sjoerg 323625944Sjoerg if (debug) 323740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 323840008Sjoerg SPP_ARGS(ifp)); 323925944Sjoerg 324025944Sjoerg p = (void*) (h+1); 3241161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3242161556Scperciva len -= p[1], p += p[1]) { 324325944Sjoerg if (debug) 324469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 324525944Sjoerg switch (*p) { 324688534Sjoerg case IPCP_OPT_COMPRESSION: 324788534Sjoerg if (len >= 6 && p[1] == 6) { 324888534Sjoerg desiredcomp = p[2] << 8 | p[3]; 324988534Sjoerg if (debug) 325088534Sjoerg log(-1, "[wantcomp %#04x] ", 325188534Sjoerg desiredcomp); 325288534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 325388599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 325488534Sjoerg sp->ipcp.max_state = p[4]; 325588534Sjoerg sp->ipcp.compress_cid = p[5]; 325688534Sjoerg if (debug) 325788534Sjoerg log(-1, "[agree] "); 325888534Sjoerg } else 325988534Sjoerg sp->ipcp.opts &= 326088534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 326188534Sjoerg } 326288534Sjoerg break; 326325944Sjoerg case IPCP_OPT_ADDRESS: 326425944Sjoerg /* 326525944Sjoerg * Peer doesn't like our local IP address. See 326625944Sjoerg * if we can do something for him. We'll drop 326725944Sjoerg * him our address then. 326825944Sjoerg */ 326925944Sjoerg if (len >= 6 && p[1] == 6) { 327025944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 327125944Sjoerg p[4] << 8 | p[5]; 327225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 327325944Sjoerg if (debug) 327469211Sphk log(-1, "[wantaddr %s] ", 327530300Sjoerg sppp_dotted_quad(wantaddr)); 327625944Sjoerg /* 327725944Sjoerg * When doing dynamic address assignment, 327825944Sjoerg * we accept his offer. Otherwise, we 327925944Sjoerg * ignore it and thus continue to negotiate 328025944Sjoerg * our already existing value. 328142104Sphk * XXX: Bogus, if he said no once, he'll 328242104Sphk * just say no again, might as well die. 328325944Sjoerg */ 328425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 328525944Sjoerg sppp_set_ip_addr(sp, wantaddr); 328625944Sjoerg if (debug) 328769211Sphk log(-1, "[agree] "); 328842104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 328925944Sjoerg } 329025944Sjoerg } 329125944Sjoerg break; 329225944Sjoerg } 329325944Sjoerg } 329425944Sjoerg if (debug) 329569211Sphk log(-1, "\n"); 329625944Sjoerg free (buf, M_TEMP); 329725944Sjoerg return; 32984910Swollman} 32994910Swollman 330012820Sphkstatic void 330125944Sjoergsppp_ipcp_tlu(struct sppp *sp) 33024910Swollman{ 330342104Sphk /* we are up - notify isdn daemon */ 330442104Sphk if (sp->pp_con) 330542104Sphk sp->pp_con(sp); 33064910Swollman} 33074910Swollman 330825944Sjoergstatic void 330925944Sjoergsppp_ipcp_tld(struct sppp *sp) 331025944Sjoerg{ 331125944Sjoerg} 331225944Sjoerg 331325944Sjoergstatic void 331425944Sjoergsppp_ipcp_tls(struct sppp *sp) 331525944Sjoerg{ 331625944Sjoerg /* indicate to LCP that it must stay alive */ 331725944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 331825944Sjoerg} 331925944Sjoerg 332025944Sjoergstatic void 332125944Sjoergsppp_ipcp_tlf(struct sppp *sp) 332225944Sjoerg{ 332325944Sjoerg /* we no longer need LCP */ 332425944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 332530300Sjoerg sppp_lcp_check_and_close(sp); 332625944Sjoerg} 332725944Sjoerg 332825944Sjoergstatic void 332925944Sjoergsppp_ipcp_scr(struct sppp *sp) 333025944Sjoerg{ 333125944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 333225944Sjoerg u_long ouraddr; 333325944Sjoerg int i = 0; 333425944Sjoerg 333588534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 333688534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 333788534Sjoerg opt[i++] = 6; 333888534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 333988534Sjoerg opt[i++] = IPCP_COMP_VJ; 334088534Sjoerg opt[i++] = sp->ipcp.max_state; 334188534Sjoerg opt[i++] = sp->ipcp.compress_cid; 334288534Sjoerg } 334325944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 334430300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 334525944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 334625944Sjoerg opt[i++] = 6; 334725944Sjoerg opt[i++] = ouraddr >> 24; 334825944Sjoerg opt[i++] = ouraddr >> 16; 334925944Sjoerg opt[i++] = ouraddr >> 8; 335025944Sjoerg opt[i++] = ouraddr; 335125944Sjoerg } 335225944Sjoerg 335378064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 335425944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 335525944Sjoerg} 3356184682Sbz#else /* !INET */ 3357184682Sbzstatic void 3358184682Sbzsppp_ipcp_init(struct sppp *sp) 3359184682Sbz{ 3360184682Sbz} 336125944Sjoerg 3362184682Sbzstatic void 3363184682Sbzsppp_ipcp_up(struct sppp *sp) 3364184682Sbz{ 3365184682Sbz} 3366184682Sbz 3367184682Sbzstatic void 3368184682Sbzsppp_ipcp_down(struct sppp *sp) 3369184682Sbz{ 3370184682Sbz} 3371184682Sbz 3372184682Sbzstatic void 3373184682Sbzsppp_ipcp_open(struct sppp *sp) 3374184682Sbz{ 3375184682Sbz} 3376184682Sbz 3377184682Sbzstatic void 3378184682Sbzsppp_ipcp_close(struct sppp *sp) 3379184682Sbz{ 3380184682Sbz} 3381184682Sbz 3382184682Sbzstatic void 3383184682Sbzsppp_ipcp_TO(void *cookie) 3384184682Sbz{ 3385184682Sbz} 3386184682Sbz 3387184682Sbzstatic int 3388184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3389184682Sbz{ 3390184682Sbz return (0); 3391184682Sbz} 3392184682Sbz 3393184682Sbzstatic void 3394184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3395184682Sbz{ 3396184682Sbz} 3397184682Sbz 3398184682Sbzstatic void 3399184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3400184682Sbz{ 3401184682Sbz} 3402184682Sbz 3403184682Sbzstatic void 3404184682Sbzsppp_ipcp_tlu(struct sppp *sp) 3405184682Sbz{ 3406184682Sbz} 3407184682Sbz 3408184682Sbzstatic void 3409184682Sbzsppp_ipcp_tld(struct sppp *sp) 3410184682Sbz{ 3411184682Sbz} 3412184682Sbz 3413184682Sbzstatic void 3414184682Sbzsppp_ipcp_tls(struct sppp *sp) 3415184682Sbz{ 3416184682Sbz} 3417184682Sbz 3418184682Sbzstatic void 3419184682Sbzsppp_ipcp_tlf(struct sppp *sp) 3420184682Sbz{ 3421184682Sbz} 3422184682Sbz 3423184682Sbzstatic void 3424184682Sbzsppp_ipcp_scr(struct sppp *sp) 3425184682Sbz{ 3426184682Sbz} 3427184682Sbz#endif 3428184682Sbz 342970199Sjhay/* 343030300Sjoerg *--------------------------------------------------------------------------* 343130300Sjoerg * * 343278064Sume * The IPv6CP implementation. * 343378064Sume * * 343478064Sume *--------------------------------------------------------------------------* 343578064Sume */ 343678064Sume 343778064Sume#ifdef INET6 343878064Sumestatic void 343978064Sumesppp_ipv6cp_init(struct sppp *sp) 344078064Sume{ 344178064Sume sp->ipv6cp.opts = 0; 344278064Sume sp->ipv6cp.flags = 0; 344378064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 344478064Sume sp->fail_counter[IDX_IPV6CP] = 0; 344578064Sume sp->pp_seq[IDX_IPV6CP] = 0; 344678064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3447188668Srwatson callout_init(&sp->ch[IDX_IPV6CP], CALLOUT_MPSAFE); 344878064Sume} 344978064Sume 345078064Sumestatic void 345178064Sumesppp_ipv6cp_up(struct sppp *sp) 345278064Sume{ 345378064Sume sppp_up_event(&ipv6cp, sp); 345478064Sume} 345578064Sume 345678064Sumestatic void 345778064Sumesppp_ipv6cp_down(struct sppp *sp) 345878064Sume{ 345978064Sume sppp_down_event(&ipv6cp, sp); 346078064Sume} 346178064Sume 346278064Sumestatic void 346378064Sumesppp_ipv6cp_open(struct sppp *sp) 346478064Sume{ 346578064Sume STDDCL; 346678064Sume struct in6_addr myaddr, hisaddr; 346778064Sume 346878064Sume#ifdef IPV6CP_MYIFID_DYN 346978064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 347078064Sume#else 347178064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 347278064Sume#endif 347378064Sume 347478064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 347578064Sume /* 347678064Sume * If we don't have our address, this probably means our 347778064Sume * interface doesn't want to talk IPv6 at all. (This could 347878064Sume * be the case if somebody wants to speak only IPX, for 347978064Sume * example.) Don't open IPv6CP in this case. 348078064Sume */ 348178064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 348278064Sume /* XXX this message should go away */ 348378064Sume if (debug) 348478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 348578064Sume SPP_ARGS(ifp)); 348678064Sume return; 348778064Sume } 348878064Sume 348978064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 349078064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 349178064Sume sppp_open_event(&ipv6cp, sp); 349278064Sume} 349378064Sume 349478064Sumestatic void 349578064Sumesppp_ipv6cp_close(struct sppp *sp) 349678064Sume{ 349778064Sume sppp_close_event(&ipv6cp, sp); 349878064Sume} 349978064Sume 350078064Sumestatic void 350178064Sumesppp_ipv6cp_TO(void *cookie) 350278064Sume{ 350378064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 350478064Sume} 350578064Sume 350678064Sume/* 350778064Sume * Analyze a configure request. Return true if it was agreeable, and 350878064Sume * caused action sca, false if it has been rejected or nak'ed, and 350978064Sume * caused action scn. (The return value is used to make the state 351078064Sume * transition decision in the state automaton.) 351178064Sume */ 351278064Sumestatic int 351378064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 351478064Sume{ 351578064Sume u_char *buf, *r, *p; 3516147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 351778064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 351878064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 351978064Sume int ifidcount; 352078064Sume int type; 352178064Sume int collision, nohisaddr; 3522165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 352378064Sume 352478064Sume len -= 4; 352578064Sume origlen = len; 352678064Sume /* 352778064Sume * Make sure to allocate a buf that can at least hold a 352878064Sume * conf-nak with an `address' option. We might need it below. 352978064Sume */ 353078064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 353178064Sume if (! buf) 353278064Sume return (0); 353378064Sume 353478064Sume /* pass 1: see if we can recognize them */ 353578064Sume if (debug) 353678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 353778064Sume SPP_ARGS(ifp)); 353878064Sume p = (void*) (h+1); 353978064Sume ifidcount = 0; 3540161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3541161556Scperciva len-=p[1], p+=p[1]) { 354278064Sume if (debug) 354378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 354478064Sume switch (*p) { 354578064Sume case IPV6CP_OPT_IFID: 354678064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 354778064Sume /* correctly formed address option */ 354878064Sume ifidcount++; 354978064Sume continue; 355078064Sume } 355178064Sume if (debug) 355278176Sume log(-1, " [invalid]"); 355378064Sume break; 355478064Sume#ifdef notyet 355578064Sume case IPV6CP_OPT_COMPRESSION: 355678064Sume if (len >= 4 && p[1] >= 4) { 355778064Sume /* correctly formed compress option */ 355878064Sume continue; 355978064Sume } 356078064Sume if (debug) 356178176Sume log(-1, " [invalid]"); 356278064Sume break; 356378064Sume#endif 356478064Sume default: 356578064Sume /* Others not supported. */ 356678064Sume if (debug) 356778176Sume log(-1, " [rej]"); 356878064Sume break; 356978064Sume } 357078064Sume /* Add the option to rejected list. */ 357178064Sume bcopy (p, r, p[1]); 357278064Sume r += p[1]; 357378064Sume rlen += p[1]; 357478064Sume } 357578064Sume if (rlen) { 357678064Sume if (debug) 357778176Sume log(-1, " send conf-rej\n"); 357878064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 357978064Sume goto end; 358078064Sume } else if (debug) 358178176Sume log(-1, "\n"); 358278064Sume 358378064Sume /* pass 2: parse option values */ 358478064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 358578064Sume if (debug) 358678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 358778064Sume SPP_ARGS(ifp)); 358878064Sume p = (void*) (h+1); 358978064Sume len = origlen; 359078064Sume type = CONF_ACK; 3591161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3592161556Scperciva len-=p[1], p+=p[1]) { 359378064Sume if (debug) 359478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 359578064Sume switch (*p) { 359678064Sume#ifdef notyet 359778064Sume case IPV6CP_OPT_COMPRESSION: 359878064Sume continue; 359978064Sume#endif 360078064Sume case IPV6CP_OPT_IFID: 360178064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 360278064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 360378064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 360478064Sume &myaddr.s6_addr[8], 8) == 0); 360578064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 360678064Sume 360778064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3608148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 360978064Sume 361078064Sume if (!collision && !nohisaddr) { 361178064Sume /* no collision, hisaddr known - Conf-Ack */ 361278064Sume type = CONF_ACK; 361378064Sume 361478064Sume if (debug) { 361578176Sume log(-1, " %s [%s]", 3616165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3617165118Sbz sppp_cp_type_name(type)); 361878064Sume } 361978064Sume continue; 362078064Sume } 362178064Sume 362278064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 362378064Sume if (collision && nohisaddr) { 362478064Sume /* collision, hisaddr unknown - Conf-Rej */ 362578064Sume type = CONF_REJ; 362678064Sume bzero(&p[2], 8); 362778064Sume } else { 362878064Sume /* 362978064Sume * - no collision, hisaddr unknown, or 363078064Sume * - collision, hisaddr known 363178064Sume * Conf-Nak, suggest hisaddr 363278064Sume */ 363378064Sume type = CONF_NAK; 363478064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 363578064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 363678064Sume } 363778064Sume if (debug) 3638165118Sbz log(-1, " %s [%s]", 3639165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3640165118Sbz sppp_cp_type_name(type)); 364178064Sume break; 364278064Sume } 364378064Sume /* Add the option to nak'ed list. */ 364478064Sume bcopy (p, r, p[1]); 364578064Sume r += p[1]; 364678064Sume rlen += p[1]; 364778064Sume } 364878064Sume 364978064Sume if (rlen == 0 && type == CONF_ACK) { 365078064Sume if (debug) 365178176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 365278064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 365378064Sume } else { 365478064Sume#ifdef DIAGNOSTIC 365578064Sume if (type == CONF_ACK) 365678064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 365778064Sume#endif 365878064Sume 365978064Sume if (debug) { 366078176Sume log(-1, " send %s suggest %s\n", 3661165118Sbz sppp_cp_type_name(type), 3662165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 366378064Sume } 366478064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 366578064Sume } 366678064Sume 366778064Sume end: 366878064Sume free (buf, M_TEMP); 366978064Sume return (rlen == 0); 367078064Sume} 367178064Sume 367278064Sume/* 367378064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 367478064Sume * negotiation. 367578064Sume */ 367678064Sumestatic void 367778064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 367878064Sume{ 367978064Sume u_char *buf, *p; 3680147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 368178064Sume int debug = ifp->if_flags & IFF_DEBUG; 368278064Sume 368378064Sume len -= 4; 368478064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 368578064Sume if (!buf) 368678064Sume return; 368778064Sume 368878064Sume if (debug) 368978064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 369078064Sume SPP_ARGS(ifp)); 369178064Sume 369278064Sume p = (void*) (h+1); 3693161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3694161556Scperciva len -= p[1], p += p[1]) { 369578064Sume if (debug) 369678176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 369778064Sume switch (*p) { 369878064Sume case IPV6CP_OPT_IFID: 369978064Sume /* 370078064Sume * Peer doesn't grok address option. This is 370178064Sume * bad. XXX Should we better give up here? 370278064Sume */ 370378064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 370478064Sume break; 370578064Sume#ifdef notyet 370678064Sume case IPV6CP_OPT_COMPRESS: 370778064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 370878064Sume break; 370978064Sume#endif 371078064Sume } 371178064Sume } 371278064Sume if (debug) 371378176Sume log(-1, "\n"); 371478064Sume free (buf, M_TEMP); 371578064Sume return; 371678064Sume} 371778064Sume 371878064Sume/* 371978064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 372078064Sume * negotiation. 372178064Sume */ 372278064Sumestatic void 372378064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 372478064Sume{ 372578064Sume u_char *buf, *p; 3726147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 372778064Sume int debug = ifp->if_flags & IFF_DEBUG; 372878064Sume struct in6_addr suggestaddr; 3729165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 373078064Sume 373178064Sume len -= 4; 373278064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 373378064Sume if (!buf) 373478064Sume return; 373578064Sume 373678064Sume if (debug) 373778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 373878064Sume SPP_ARGS(ifp)); 373978064Sume 374078064Sume p = (void*) (h+1); 3741161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3742161556Scperciva len -= p[1], p += p[1]) { 374378064Sume if (debug) 374478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 374578064Sume switch (*p) { 374678064Sume case IPV6CP_OPT_IFID: 374778064Sume /* 374878064Sume * Peer doesn't like our local ifid. See 374978064Sume * if we can do something for him. We'll drop 375078064Sume * him our address then. 375178064Sume */ 375278064Sume if (len < 10 || p[1] != 10) 375378064Sume break; 375478064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 375578064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3756148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 375778064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 375878064Sume 375978064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 376078064Sume if (debug) 376178176Sume log(-1, " [suggestaddr %s]", 3762165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 376378064Sume#ifdef IPV6CP_MYIFID_DYN 376478064Sume /* 376578064Sume * When doing dynamic address assignment, 376678064Sume * we accept his offer. 376778064Sume */ 376878064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 376978064Sume struct in6_addr lastsuggest; 377078064Sume /* 377178064Sume * If <suggested myaddr from peer> equals to 377278064Sume * <hisaddr we have suggested last time>, 377378064Sume * we have a collision. generate new random 377478064Sume * ifid. 377578064Sume */ 377678064Sume sppp_suggest_ip6_addr(&lastsuggest); 377778064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 377878064Sume lastsuggest)) { 377978064Sume if (debug) 378078176Sume log(-1, " [random]"); 378178064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 378278064Sume } 378378064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 378478064Sume if (debug) 378578176Sume log(-1, " [agree]"); 378678064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 378778064Sume } 378878064Sume#else 378978064Sume /* 379078064Sume * Since we do not do dynamic address assignment, 379178064Sume * we ignore it and thus continue to negotiate 379278064Sume * our already existing value. This can possibly 379378064Sume * go into infinite request-reject loop. 379478064Sume * 379578064Sume * This is not likely because we normally use 379678064Sume * ifid based on MAC-address. 379778064Sume * If you have no ethernet card on the node, too bad. 379878064Sume * XXX should we use fail_counter? 379978064Sume */ 380078064Sume#endif 380178064Sume break; 380278064Sume#ifdef notyet 380378064Sume case IPV6CP_OPT_COMPRESS: 380478064Sume /* 380578064Sume * Peer wants different compression parameters. 380678064Sume */ 380778064Sume break; 380878064Sume#endif 380978064Sume } 381078064Sume } 381178064Sume if (debug) 381278176Sume log(-1, "\n"); 381378064Sume free (buf, M_TEMP); 381478064Sume return; 381578064Sume} 381678064Sumestatic void 381778064Sumesppp_ipv6cp_tlu(struct sppp *sp) 381878064Sume{ 381978064Sume /* we are up - notify isdn daemon */ 382078064Sume if (sp->pp_con) 382178064Sume sp->pp_con(sp); 382278064Sume} 382378064Sume 382478064Sumestatic void 382578064Sumesppp_ipv6cp_tld(struct sppp *sp) 382678064Sume{ 382778064Sume} 382878064Sume 382978064Sumestatic void 383078064Sumesppp_ipv6cp_tls(struct sppp *sp) 383178064Sume{ 383278064Sume /* indicate to LCP that it must stay alive */ 383378064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 383478064Sume} 383578064Sume 383678064Sumestatic void 383778064Sumesppp_ipv6cp_tlf(struct sppp *sp) 383878064Sume{ 383978064Sume 384078064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 384178064Sume /* we no longer need LCP */ 384278064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 384378064Sume sppp_lcp_check_and_close(sp); 384478064Sume#endif 384578064Sume} 384678064Sume 384778064Sumestatic void 384878064Sumesppp_ipv6cp_scr(struct sppp *sp) 384978064Sume{ 385078064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 385178064Sume struct in6_addr ouraddr; 385278064Sume int i = 0; 385378064Sume 385478064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 385578064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 385678064Sume opt[i++] = IPV6CP_OPT_IFID; 385778064Sume opt[i++] = 10; 385878064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 385978064Sume i += 8; 386078064Sume } 386178064Sume 386278064Sume#ifdef notyet 386378064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 386478064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 386578064Sume opt[i++] = 4; 386678064Sume opt[i++] = 0; /* TBD */ 386778064Sume opt[i++] = 0; /* TBD */ 386878064Sume /* variable length data may follow */ 386978064Sume } 387078064Sume#endif 387178064Sume 387278064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 387378064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 387478064Sume} 387578064Sume#else /*INET6*/ 387678064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 387778064Sume{ 387878064Sume} 387978064Sume 388078064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 388178064Sume{ 388278064Sume} 388378064Sume 388478064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 388578064Sume{ 388678064Sume} 388778064Sume 388878064Sume 388978064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 389078064Sume{ 389178064Sume} 389278064Sume 389378064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 389478064Sume{ 389578064Sume} 389678064Sume 389778064Sumestatic void sppp_ipv6cp_TO(void *sp) 389878064Sume{ 389978064Sume} 390078064Sume 390178064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 390278064Sume{ 390378064Sume return 0; 390478064Sume} 390578064Sume 390678064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 390778064Sume{ 390878064Sume} 390978064Sume 391078064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 391178064Sume{ 391278064Sume} 391378064Sume 391478064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 391578064Sume{ 391678064Sume} 391778064Sume 391878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 391978064Sume{ 392078064Sume} 392178064Sume 392278064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 392378064Sume{ 392478064Sume} 392578064Sume 392678064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 392778064Sume{ 392878064Sume} 392978064Sume 393078064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 393178064Sume{ 393278064Sume} 393378064Sume#endif /*INET6*/ 393478064Sume 393578064Sume/* 393678064Sume *--------------------------------------------------------------------------* 393778064Sume * * 393830300Sjoerg * The CHAP implementation. * 393930300Sjoerg * * 394030300Sjoerg *--------------------------------------------------------------------------* 394130300Sjoerg */ 394230300Sjoerg 394330300Sjoerg/* 394430300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 394530300Sjoerg * the control protocols do, since they do have Open and Close events, but 394630300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 394730300Sjoerg * authentication protocols may be different in both directions (this makes 394830300Sjoerg * sense, think of a machine that never accepts incoming calls but only 394930300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 395030300Sjoerg * 395130300Sjoerg * Our state machine for the local authentication protocol (we are requesting 395230300Sjoerg * the peer to authenticate) looks like: 395330300Sjoerg * 395430300Sjoerg * RCA- 395530300Sjoerg * +--------------------------------------------+ 395630300Sjoerg * V scn,tld| 395730300Sjoerg * +--------+ Close +---------+ RCA+ 395830300Sjoerg * | |<----------------------------------| |------+ 395930300Sjoerg * +--->| Closed | TO* | Opened | sca | 396030300Sjoerg * | | |-----+ +-------| |<-----+ 396130300Sjoerg * | +--------+ irc | | +---------+ 396230300Sjoerg * | ^ | | ^ 396330300Sjoerg * | | | | | 396430300Sjoerg * | | | | | 396530300Sjoerg * | TO-| | | | 396630300Sjoerg * | |tld TO+ V | | 396730300Sjoerg * | | +------->+ | | 396830300Sjoerg * | | | | | | 396930300Sjoerg * | +--------+ V | | 397030300Sjoerg * | | |<----+<--------------------+ | 397130300Sjoerg * | | Req- | scr | 397230300Sjoerg * | | Sent | | 397330300Sjoerg * | | | | 397430300Sjoerg * | +--------+ | 397530300Sjoerg * | RCA- | | RCA+ | 397630300Sjoerg * +------+ +------------------------------------------+ 397730300Sjoerg * scn,tld sca,irc,ict,tlu 397830300Sjoerg * 397930300Sjoerg * 398030300Sjoerg * with: 398130300Sjoerg * 398230300Sjoerg * Open: LCP reached authentication phase 398330300Sjoerg * Close: LCP reached terminate phase 398430300Sjoerg * 398530300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 398630300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 398730300Sjoerg * TO+: timeout with restart counter >= 0 398830300Sjoerg * TO-: timeout with restart counter < 0 398930300Sjoerg * TO*: reschedule timeout for CHAP 399030300Sjoerg * 399130300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 399230300Sjoerg * sca: send ack packet (pap-ack, chap-success) 399330300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 399430300Sjoerg * ict: initialize re-challenge timer (CHAP only) 399530300Sjoerg * 399630300Sjoerg * tlu: this-layer-up, LCP reaches network phase 399730300Sjoerg * tld: this-layer-down, LCP enters terminate phase 399830300Sjoerg * 399930300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 400030300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 400130300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 400230300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 400330300Sjoerg * causing LCP to enter terminate phase. 400430300Sjoerg * 400530300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 400630300Sjoerg * expected to send one based on the successful negotiation of PAP as 400730300Sjoerg * the authentication protocol during the LCP option negotiation. 400830300Sjoerg * 400930300Sjoerg * Incoming authentication protocol requests (remote requests 401030300Sjoerg * authentication, we are peer) don't employ a state machine at all, 401130300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 401230300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 401330300Sjoerg * still in authentication phase (thereby violating the standard that 401430300Sjoerg * demands that these NCP packets are to be discarded), so we keep 401530300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 401630300Sjoerg * phase network once we've seen a positive acknowledge for the 401730300Sjoerg * authentication. 401830300Sjoerg */ 401930300Sjoerg 402030300Sjoerg/* 402130300Sjoerg * Handle incoming CHAP packets. 402230300Sjoerg */ 4023105228Sphkstatic void 402430300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 402530300Sjoerg{ 402630300Sjoerg STDDCL; 402730300Sjoerg struct lcp_header *h; 402830300Sjoerg int len, x; 402930300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 403030300Sjoerg int value_len, name_len; 403130300Sjoerg MD5_CTX ctx; 403230300Sjoerg 403330300Sjoerg len = m->m_pkthdr.len; 403430300Sjoerg if (len < 4) { 403530300Sjoerg if (debug) 403630300Sjoerg log(LOG_DEBUG, 403740008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 403840008Sjoerg SPP_ARGS(ifp), len); 403930300Sjoerg return; 404030300Sjoerg } 404130300Sjoerg h = mtod (m, struct lcp_header*); 404230300Sjoerg if (len > ntohs (h->len)) 404330300Sjoerg len = ntohs (h->len); 404430300Sjoerg 404530300Sjoerg switch (h->type) { 404630300Sjoerg /* challenge, failure and success are his authproto */ 404730300Sjoerg case CHAP_CHALLENGE: 404830300Sjoerg value = 1 + (u_char*)(h+1); 404930300Sjoerg value_len = value[-1]; 405030300Sjoerg name = value + value_len; 405130300Sjoerg name_len = len - value_len - 5; 405230300Sjoerg if (name_len < 0) { 405330300Sjoerg if (debug) { 405430300Sjoerg log(LOG_DEBUG, 405540008Sjoerg SPP_FMT "chap corrupted challenge " 405630300Sjoerg "<%s id=0x%x len=%d", 405740008Sjoerg SPP_ARGS(ifp), 405830300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 405930300Sjoerg h->ident, ntohs(h->len)); 406044145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 406169211Sphk log(-1, ">\n"); 406230300Sjoerg } 406330300Sjoerg break; 406430300Sjoerg } 406570199Sjhay 406630300Sjoerg if (debug) { 406730300Sjoerg log(LOG_DEBUG, 406840008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 406940008Sjoerg SPP_ARGS(ifp), 407030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 407130300Sjoerg ntohs(h->len)); 407230300Sjoerg sppp_print_string((char*) name, name_len); 407369211Sphk log(-1, " value-size=%d value=", value_len); 407430300Sjoerg sppp_print_bytes(value, value_len); 407569211Sphk log(-1, ">\n"); 407630300Sjoerg } 407730300Sjoerg 407830300Sjoerg /* Compute reply value. */ 407930300Sjoerg MD5Init(&ctx); 408030300Sjoerg MD5Update(&ctx, &h->ident, 1); 408130300Sjoerg MD5Update(&ctx, sp->myauth.secret, 408230300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 408330300Sjoerg MD5Update(&ctx, value, value_len); 408430300Sjoerg MD5Final(digest, &ctx); 408530300Sjoerg dsize = sizeof digest; 408630300Sjoerg 408730300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 408830300Sjoerg sizeof dsize, (const char *)&dsize, 408930300Sjoerg sizeof digest, digest, 409040008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 409130300Sjoerg sp->myauth.name, 409230300Sjoerg 0); 409330300Sjoerg break; 409430300Sjoerg 409530300Sjoerg case CHAP_SUCCESS: 409630300Sjoerg if (debug) { 409740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 409840008Sjoerg SPP_ARGS(ifp)); 409930300Sjoerg if (len > 4) { 410069211Sphk log(-1, ": "); 410130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 410230300Sjoerg } 410369211Sphk log(-1, "\n"); 410430300Sjoerg } 410530300Sjoerg x = splimp(); 4106138745Srik SPPP_LOCK(sp); 410730300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 410830300Sjoerg if (sp->myauth.proto == PPP_CHAP && 410932169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 411030300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 411130300Sjoerg /* 411230300Sjoerg * We are authenticator for CHAP but didn't 411330300Sjoerg * complete yet. Leave it to tlu to proceed 411430300Sjoerg * to network phase. 411530300Sjoerg */ 4116138745Srik SPPP_UNLOCK(sp); 411730300Sjoerg splx(x); 411830300Sjoerg break; 411930300Sjoerg } 4120138745Srik SPPP_UNLOCK(sp); 412130300Sjoerg splx(x); 412230300Sjoerg sppp_phase_network(sp); 412330300Sjoerg break; 412430300Sjoerg 412530300Sjoerg case CHAP_FAILURE: 412630300Sjoerg if (debug) { 412740008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 412840008Sjoerg SPP_ARGS(ifp)); 412930300Sjoerg if (len > 4) { 413069211Sphk log(-1, ": "); 413130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 413230300Sjoerg } 413369211Sphk log(-1, "\n"); 413430300Sjoerg } else 413540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 413640008Sjoerg SPP_ARGS(ifp)); 413730300Sjoerg /* await LCP shutdown by authenticator */ 413830300Sjoerg break; 413930300Sjoerg 414030300Sjoerg /* response is my authproto */ 414130300Sjoerg case CHAP_RESPONSE: 414230300Sjoerg value = 1 + (u_char*)(h+1); 414330300Sjoerg value_len = value[-1]; 414430300Sjoerg name = value + value_len; 414530300Sjoerg name_len = len - value_len - 5; 414630300Sjoerg if (name_len < 0) { 414730300Sjoerg if (debug) { 414830300Sjoerg log(LOG_DEBUG, 414940008Sjoerg SPP_FMT "chap corrupted response " 415030300Sjoerg "<%s id=0x%x len=%d", 415140008Sjoerg SPP_ARGS(ifp), 415230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 415330300Sjoerg h->ident, ntohs(h->len)); 415444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 415569211Sphk log(-1, ">\n"); 415630300Sjoerg } 415730300Sjoerg break; 415830300Sjoerg } 415930300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 416030300Sjoerg if (debug) 416130300Sjoerg log(LOG_DEBUG, 416240008Sjoerg SPP_FMT "chap dropping response for old ID " 416330300Sjoerg "(got %d, expected %d)\n", 416440008Sjoerg SPP_ARGS(ifp), 416530300Sjoerg h->ident, sp->confid[IDX_CHAP]); 416630300Sjoerg break; 416730300Sjoerg } 416830300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 416930300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 417040008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 417140008Sjoerg SPP_ARGS(ifp)); 417230300Sjoerg sppp_print_string(name, name_len); 417369211Sphk log(-1, " != expected "); 417430300Sjoerg sppp_print_string(sp->hisauth.name, 417530300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 417669211Sphk log(-1, "\n"); 417770199Sjhay } 417830300Sjoerg if (debug) { 417940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 418030300Sjoerg "<%s id=0x%x len=%d name=", 418140008Sjoerg SPP_ARGS(ifp), 418230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 418330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 418430300Sjoerg h->ident, ntohs (h->len)); 418530300Sjoerg sppp_print_string((char*)name, name_len); 418669211Sphk log(-1, " value-size=%d value=", value_len); 418730300Sjoerg sppp_print_bytes(value, value_len); 418869211Sphk log(-1, ">\n"); 418930300Sjoerg } 419030300Sjoerg if (value_len != AUTHKEYLEN) { 419130300Sjoerg if (debug) 419230300Sjoerg log(LOG_DEBUG, 419340008Sjoerg SPP_FMT "chap bad hash value length: " 419430300Sjoerg "%d bytes, should be %d\n", 419540008Sjoerg SPP_ARGS(ifp), value_len, 419630300Sjoerg AUTHKEYLEN); 419730300Sjoerg break; 419830300Sjoerg } 419930300Sjoerg 420030300Sjoerg MD5Init(&ctx); 420130300Sjoerg MD5Update(&ctx, &h->ident, 1); 420230300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 420330300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 420430300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 420530300Sjoerg MD5Final(digest, &ctx); 420630300Sjoerg 420730300Sjoerg#define FAILMSG "Failed..." 420830300Sjoerg#define SUCCMSG "Welcome!" 420930300Sjoerg 421030300Sjoerg if (value_len != sizeof digest || 421130300Sjoerg bcmp(digest, value, value_len) != 0) { 421230300Sjoerg /* action scn, tld */ 421330300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 421430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 421530300Sjoerg 0); 421630300Sjoerg chap.tld(sp); 421730300Sjoerg break; 421830300Sjoerg } 421930300Sjoerg /* action sca, perhaps tlu */ 422030300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 422130300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 422230300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 422330300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 422430300Sjoerg 0); 422530300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 422630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 422730300Sjoerg chap.tlu(sp); 422830300Sjoerg } 422930300Sjoerg break; 423030300Sjoerg 423130300Sjoerg default: 423230300Sjoerg /* Unknown CHAP packet type -- ignore. */ 423330300Sjoerg if (debug) { 423440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 423530300Sjoerg "<0x%x id=0x%xh len=%d", 423640008Sjoerg SPP_ARGS(ifp), 423730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 423830300Sjoerg h->type, h->ident, ntohs(h->len)); 423944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 424069211Sphk log(-1, ">\n"); 424130300Sjoerg } 424230300Sjoerg break; 424330300Sjoerg 424430300Sjoerg } 424530300Sjoerg} 424630300Sjoerg 424730300Sjoergstatic void 424830300Sjoergsppp_chap_init(struct sppp *sp) 424930300Sjoerg{ 425030300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 425130300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 425230300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 425378064Sume sp->pp_seq[IDX_CHAP] = 0; 425478064Sume sp->pp_rseq[IDX_CHAP] = 0; 4255188668Srwatson callout_init(&sp->ch[IDX_CHAP], CALLOUT_MPSAFE); 425630300Sjoerg} 425730300Sjoerg 425830300Sjoergstatic void 425930300Sjoergsppp_chap_open(struct sppp *sp) 426030300Sjoerg{ 426130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 426230300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 426330300Sjoerg /* we are authenticator for CHAP, start it */ 426430300Sjoerg chap.scr(sp); 426530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 426630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 426730300Sjoerg } 426830300Sjoerg /* nothing to be done if we are peer, await a challenge */ 426930300Sjoerg} 427030300Sjoerg 427130300Sjoergstatic void 427230300Sjoergsppp_chap_close(struct sppp *sp) 427330300Sjoerg{ 427430300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 427530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 427630300Sjoerg} 427730300Sjoerg 427830300Sjoergstatic void 427930300Sjoergsppp_chap_TO(void *cookie) 428030300Sjoerg{ 428130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 428230300Sjoerg STDDCL; 428330300Sjoerg int s; 428430300Sjoerg 428530300Sjoerg s = splimp(); 4286138745Srik SPPP_LOCK(sp); 428730300Sjoerg if (debug) 428840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 428940008Sjoerg SPP_ARGS(ifp), 429030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 429130300Sjoerg sp->rst_counter[IDX_CHAP]); 429230300Sjoerg 429330300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 429430300Sjoerg /* TO- event */ 429530300Sjoerg switch (sp->state[IDX_CHAP]) { 429630300Sjoerg case STATE_REQ_SENT: 429730300Sjoerg chap.tld(sp); 429830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 429930300Sjoerg break; 430030300Sjoerg } 430130300Sjoerg else 430230300Sjoerg /* TO+ (or TO*) event */ 430330300Sjoerg switch (sp->state[IDX_CHAP]) { 430430300Sjoerg case STATE_OPENED: 430530300Sjoerg /* TO* event */ 430630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4307102412Scharnier /* FALLTHROUGH */ 430830300Sjoerg case STATE_REQ_SENT: 430930300Sjoerg chap.scr(sp); 431030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 431130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 431230300Sjoerg break; 431330300Sjoerg } 431430300Sjoerg 4315138745Srik SPPP_UNLOCK(sp); 431630300Sjoerg splx(s); 431730300Sjoerg} 431830300Sjoerg 431930300Sjoergstatic void 432030300Sjoergsppp_chap_tlu(struct sppp *sp) 432130300Sjoerg{ 432230300Sjoerg STDDCL; 432330300Sjoerg int i, x; 432430300Sjoerg 432540010Sjoerg i = 0; 432630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 432730300Sjoerg 432830300Sjoerg /* 432930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 433030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 433130300Sjoerg * initial challenge-response exchange has taken place. 433230300Sjoerg * Provide for an option to avoid rechallenges. 433330300Sjoerg */ 433430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 433530300Sjoerg /* 433630300Sjoerg * Compute the re-challenge timeout. This will yield 433730300Sjoerg * a number between 300 and 810 seconds. 433830300Sjoerg */ 433930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4340138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 434130300Sjoerg } 434230300Sjoerg 434330300Sjoerg if (debug) { 434430300Sjoerg log(LOG_DEBUG, 434540008Sjoerg SPP_FMT "chap %s, ", 434640008Sjoerg SPP_ARGS(ifp), 434730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 434830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 434969211Sphk log(-1, "next re-challenge in %d seconds\n", i); 435030300Sjoerg else 435169211Sphk log(-1, "re-challenging supressed\n"); 435230300Sjoerg } 435330300Sjoerg 435430300Sjoerg x = splimp(); 4355138745Srik SPPP_LOCK(sp); 435630300Sjoerg /* indicate to LCP that we need to be closed down */ 435730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 435830300Sjoerg 435930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 436030300Sjoerg /* 436130300Sjoerg * Remote is authenticator, but his auth proto didn't 436230300Sjoerg * complete yet. Defer the transition to network 436330300Sjoerg * phase. 436430300Sjoerg */ 4365138745Srik SPPP_UNLOCK(sp); 436630300Sjoerg splx(x); 436730300Sjoerg return; 436830300Sjoerg } 4369138745Srik SPPP_UNLOCK(sp); 437030300Sjoerg splx(x); 437130300Sjoerg 437230300Sjoerg /* 437330300Sjoerg * If we are already in phase network, we are done here. This 437430300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 437530300Sjoerg */ 437630300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 437730300Sjoerg sppp_phase_network(sp); 437830300Sjoerg} 437930300Sjoerg 438030300Sjoergstatic void 438130300Sjoergsppp_chap_tld(struct sppp *sp) 438230300Sjoerg{ 438330300Sjoerg STDDCL; 438430300Sjoerg 438530300Sjoerg if (debug) 438640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4387138745Srik callout_stop(&sp->ch[IDX_CHAP]); 438830300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 438930300Sjoerg 439030300Sjoerg lcp.Close(sp); 439130300Sjoerg} 439230300Sjoerg 439330300Sjoergstatic void 439430300Sjoergsppp_chap_scr(struct sppp *sp) 439530300Sjoerg{ 439630300Sjoerg u_long *ch, seed; 439730300Sjoerg u_char clen; 439830300Sjoerg 439930300Sjoerg /* Compute random challenge. */ 440030300Sjoerg ch = (u_long *)sp->myauth.challenge; 440135064Sphk read_random(&seed, sizeof seed); 440230300Sjoerg ch[0] = seed ^ random(); 440330300Sjoerg ch[1] = seed ^ random(); 440430300Sjoerg ch[2] = seed ^ random(); 440530300Sjoerg ch[3] = seed ^ random(); 440630300Sjoerg clen = AUTHKEYLEN; 440730300Sjoerg 440878064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 440930300Sjoerg 441030300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 441130300Sjoerg sizeof clen, (const char *)&clen, 441240008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 441340008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 441430300Sjoerg sp->myauth.name, 441530300Sjoerg 0); 441630300Sjoerg} 441770199Sjhay 441870199Sjhay/* 441930300Sjoerg *--------------------------------------------------------------------------* 442030300Sjoerg * * 442130300Sjoerg * The PAP implementation. * 442230300Sjoerg * * 442330300Sjoerg *--------------------------------------------------------------------------* 442430300Sjoerg */ 442530300Sjoerg/* 442630300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 442730300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 442830300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 442930300Sjoerg * retry counter is expired). 443030300Sjoerg */ 443130300Sjoerg 443230300Sjoerg/* 443330300Sjoerg * Handle incoming PAP packets. */ 443430300Sjoergstatic void 443530300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 443630300Sjoerg{ 443730300Sjoerg STDDCL; 443830300Sjoerg struct lcp_header *h; 443930300Sjoerg int len, x; 444030300Sjoerg u_char *name, *passwd, mlen; 444130300Sjoerg int name_len, passwd_len; 444230300Sjoerg 444330300Sjoerg len = m->m_pkthdr.len; 444430300Sjoerg if (len < 5) { 444530300Sjoerg if (debug) 444630300Sjoerg log(LOG_DEBUG, 444740008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 444840008Sjoerg SPP_ARGS(ifp), len); 444930300Sjoerg return; 445030300Sjoerg } 445130300Sjoerg h = mtod (m, struct lcp_header*); 445230300Sjoerg if (len > ntohs (h->len)) 445330300Sjoerg len = ntohs (h->len); 445430300Sjoerg switch (h->type) { 445530300Sjoerg /* PAP request is my authproto */ 445630300Sjoerg case PAP_REQ: 445730300Sjoerg name = 1 + (u_char*)(h+1); 445830300Sjoerg name_len = name[-1]; 445930300Sjoerg passwd = name + name_len + 1; 446030300Sjoerg if (name_len > len - 6 || 446130300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 446230300Sjoerg if (debug) { 446340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 446430300Sjoerg "<%s id=0x%x len=%d", 446540008Sjoerg SPP_ARGS(ifp), 446630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 446730300Sjoerg h->ident, ntohs(h->len)); 446844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 446969211Sphk log(-1, ">\n"); 447030300Sjoerg } 447130300Sjoerg break; 447230300Sjoerg } 447330300Sjoerg if (debug) { 447440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 447530300Sjoerg "<%s id=0x%x len=%d name=", 447640008Sjoerg SPP_ARGS(ifp), 447730300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 447830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 447930300Sjoerg h->ident, ntohs(h->len)); 448030300Sjoerg sppp_print_string((char*)name, name_len); 448169211Sphk log(-1, " passwd="); 448230300Sjoerg sppp_print_string((char*)passwd, passwd_len); 448369211Sphk log(-1, ">\n"); 448430300Sjoerg } 448574774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 448674774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 448730300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 448830300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 448930300Sjoerg /* action scn, tld */ 449030300Sjoerg mlen = sizeof(FAILMSG) - 1; 449130300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 449230300Sjoerg sizeof mlen, (const char *)&mlen, 449330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 449430300Sjoerg 0); 449530300Sjoerg pap.tld(sp); 449630300Sjoerg break; 449730300Sjoerg } 449830300Sjoerg /* action sca, perhaps tlu */ 449930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 450030300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 450130300Sjoerg mlen = sizeof(SUCCMSG) - 1; 450230300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 450330300Sjoerg sizeof mlen, (const char *)&mlen, 450430300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 450530300Sjoerg 0); 450630300Sjoerg } 450730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 450830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 450930300Sjoerg pap.tlu(sp); 451030300Sjoerg } 451130300Sjoerg break; 451230300Sjoerg 451330300Sjoerg /* ack and nak are his authproto */ 451430300Sjoerg case PAP_ACK: 4515138745Srik callout_stop(&sp->pap_my_to_ch); 451630300Sjoerg if (debug) { 451740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 451840008Sjoerg SPP_ARGS(ifp)); 451930300Sjoerg name_len = *((char *)h); 452030300Sjoerg if (len > 5 && name_len) { 452169211Sphk log(-1, ": "); 452230300Sjoerg sppp_print_string((char*)(h+1), name_len); 452330300Sjoerg } 452469211Sphk log(-1, "\n"); 452530300Sjoerg } 452630300Sjoerg x = splimp(); 4527138745Srik SPPP_LOCK(sp); 452830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 452930300Sjoerg if (sp->myauth.proto == PPP_PAP && 453032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 453130300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 453230300Sjoerg /* 453330300Sjoerg * We are authenticator for PAP but didn't 453430300Sjoerg * complete yet. Leave it to tlu to proceed 453530300Sjoerg * to network phase. 453630300Sjoerg */ 4537138745Srik SPPP_UNLOCK(sp); 453830300Sjoerg splx(x); 453930300Sjoerg break; 454030300Sjoerg } 4541138745Srik SPPP_UNLOCK(sp); 454230300Sjoerg splx(x); 454330300Sjoerg sppp_phase_network(sp); 454430300Sjoerg break; 454530300Sjoerg 454630300Sjoerg case PAP_NAK: 4547138745Srik callout_stop (&sp->pap_my_to_ch); 454830300Sjoerg if (debug) { 454940008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 455040008Sjoerg SPP_ARGS(ifp)); 455130300Sjoerg name_len = *((char *)h); 455230300Sjoerg if (len > 5 && name_len) { 455369211Sphk log(-1, ": "); 455430300Sjoerg sppp_print_string((char*)(h+1), name_len); 455530300Sjoerg } 455669211Sphk log(-1, "\n"); 455730300Sjoerg } else 455840008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 455940008Sjoerg SPP_ARGS(ifp)); 456030300Sjoerg /* await LCP shutdown by authenticator */ 456130300Sjoerg break; 456230300Sjoerg 456330300Sjoerg default: 456430300Sjoerg /* Unknown PAP packet type -- ignore. */ 456530300Sjoerg if (debug) { 456640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 456730300Sjoerg "<0x%x id=0x%x len=%d", 456840008Sjoerg SPP_ARGS(ifp), 456930300Sjoerg h->type, h->ident, ntohs(h->len)); 457044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 457169211Sphk log(-1, ">\n"); 457230300Sjoerg } 457330300Sjoerg break; 457430300Sjoerg 457530300Sjoerg } 457630300Sjoerg} 457730300Sjoerg 457830300Sjoergstatic void 457930300Sjoergsppp_pap_init(struct sppp *sp) 458030300Sjoerg{ 458130300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 458230300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 458330300Sjoerg sp->fail_counter[IDX_PAP] = 0; 458478064Sume sp->pp_seq[IDX_PAP] = 0; 458578064Sume sp->pp_rseq[IDX_PAP] = 0; 4586188668Srwatson callout_init(&sp->ch[IDX_PAP], CALLOUT_MPSAFE); 4587188668Srwatson callout_init(&sp->pap_my_to_ch, CALLOUT_MPSAFE); 458830300Sjoerg} 458930300Sjoerg 459030300Sjoergstatic void 459130300Sjoergsppp_pap_open(struct sppp *sp) 459230300Sjoerg{ 459330300Sjoerg if (sp->hisauth.proto == PPP_PAP && 459430300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 459530300Sjoerg /* we are authenticator for PAP, start our timer */ 459630300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 459730300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 459830300Sjoerg } 459930300Sjoerg if (sp->myauth.proto == PPP_PAP) { 460030300Sjoerg /* we are peer, send a request, and start a timer */ 460130300Sjoerg pap.scr(sp); 4602138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4603138745Srik sppp_pap_my_TO, (void *)sp); 460430300Sjoerg } 460530300Sjoerg} 460630300Sjoerg 460730300Sjoergstatic void 460830300Sjoergsppp_pap_close(struct sppp *sp) 460930300Sjoerg{ 461030300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 461130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 461230300Sjoerg} 461330300Sjoerg 461430300Sjoerg/* 461530300Sjoerg * That's the timeout routine if we are authenticator. Since the 461630300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 461730300Sjoerg */ 461830300Sjoergstatic void 461930300Sjoergsppp_pap_TO(void *cookie) 462030300Sjoerg{ 462130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 462230300Sjoerg STDDCL; 462330300Sjoerg int s; 462430300Sjoerg 462530300Sjoerg s = splimp(); 4626138745Srik SPPP_LOCK(sp); 462730300Sjoerg if (debug) 462840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 462940008Sjoerg SPP_ARGS(ifp), 463030300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 463130300Sjoerg sp->rst_counter[IDX_PAP]); 463230300Sjoerg 463330300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 463430300Sjoerg /* TO- event */ 463530300Sjoerg switch (sp->state[IDX_PAP]) { 463630300Sjoerg case STATE_REQ_SENT: 463730300Sjoerg pap.tld(sp); 463830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 463930300Sjoerg break; 464030300Sjoerg } 464130300Sjoerg else 464230300Sjoerg /* TO+ event, not very much we could do */ 464330300Sjoerg switch (sp->state[IDX_PAP]) { 464430300Sjoerg case STATE_REQ_SENT: 464530300Sjoerg /* sppp_cp_change_state() will restart the timer */ 464630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 464730300Sjoerg break; 464830300Sjoerg } 464930300Sjoerg 4650138745Srik SPPP_UNLOCK(sp); 465130300Sjoerg splx(s); 465230300Sjoerg} 465330300Sjoerg 465430300Sjoerg/* 465530300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 465630300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 465730300Sjoerg * XXX We should impose a max counter. 465830300Sjoerg */ 465930300Sjoergstatic void 466030300Sjoergsppp_pap_my_TO(void *cookie) 466130300Sjoerg{ 466230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 466330300Sjoerg STDDCL; 466430300Sjoerg 466530300Sjoerg if (debug) 466640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 466740008Sjoerg SPP_ARGS(ifp)); 466830300Sjoerg 4669138745Srik SPPP_LOCK(sp); 467030300Sjoerg pap.scr(sp); 4671138745Srik SPPP_UNLOCK(sp); 467230300Sjoerg} 467330300Sjoerg 467430300Sjoergstatic void 467530300Sjoergsppp_pap_tlu(struct sppp *sp) 467630300Sjoerg{ 467730300Sjoerg STDDCL; 467830300Sjoerg int x; 467930300Sjoerg 468030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 468130300Sjoerg 468230300Sjoerg if (debug) 468340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 468440008Sjoerg SPP_ARGS(ifp), pap.name); 468530300Sjoerg 468630300Sjoerg x = splimp(); 4687138745Srik SPPP_LOCK(sp); 468830300Sjoerg /* indicate to LCP that we need to be closed down */ 468930300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 469030300Sjoerg 469130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 469230300Sjoerg /* 469330300Sjoerg * Remote is authenticator, but his auth proto didn't 469430300Sjoerg * complete yet. Defer the transition to network 469530300Sjoerg * phase. 469630300Sjoerg */ 4697138745Srik SPPP_UNLOCK(sp); 469830300Sjoerg splx(x); 469930300Sjoerg return; 470030300Sjoerg } 4701138745Srik SPPP_UNLOCK(sp); 470230300Sjoerg splx(x); 470330300Sjoerg sppp_phase_network(sp); 470430300Sjoerg} 470530300Sjoerg 470630300Sjoergstatic void 470730300Sjoergsppp_pap_tld(struct sppp *sp) 470830300Sjoerg{ 470930300Sjoerg STDDCL; 471030300Sjoerg 471130300Sjoerg if (debug) 471240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4713138745Srik callout_stop (&sp->ch[IDX_PAP]); 4714138745Srik callout_stop (&sp->pap_my_to_ch); 471530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 471630300Sjoerg 471730300Sjoerg lcp.Close(sp); 471830300Sjoerg} 471930300Sjoerg 472030300Sjoergstatic void 472130300Sjoergsppp_pap_scr(struct sppp *sp) 472230300Sjoerg{ 472330300Sjoerg u_char idlen, pwdlen; 472430300Sjoerg 472578064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 472630300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 472730300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 472830300Sjoerg 472930300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 473030300Sjoerg sizeof idlen, (const char *)&idlen, 473140008Sjoerg (size_t)idlen, sp->myauth.name, 473230300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 473340008Sjoerg (size_t)pwdlen, sp->myauth.secret, 473430300Sjoerg 0); 473530300Sjoerg} 473670199Sjhay 473770199Sjhay/* 473825944Sjoerg * Random miscellaneous functions. 473925944Sjoerg */ 474025944Sjoerg 47414910Swollman/* 474230300Sjoerg * Send a PAP or CHAP proto packet. 474330300Sjoerg * 474430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 474540008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 474630300Sjoerg * mlen == 0. 474742104Sphk * NOTE: never declare variadic functions with types subject to type 474842104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 474942104Sphk * on the architecture you are on... 475030300Sjoerg */ 475130300Sjoerg 475230300Sjoergstatic void 475342104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 475442104Sphk unsigned int type, unsigned int id, 475530300Sjoerg ...) 475630300Sjoerg{ 475730300Sjoerg STDDCL; 475830300Sjoerg struct ppp_header *h; 475930300Sjoerg struct lcp_header *lh; 476030300Sjoerg struct mbuf *m; 476130300Sjoerg u_char *p; 476230300Sjoerg int len; 476342104Sphk unsigned int mlen; 476430300Sjoerg const char *msg; 476530300Sjoerg va_list ap; 476630300Sjoerg 4767111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 476830300Sjoerg if (! m) 476930300Sjoerg return; 477030300Sjoerg m->m_pkthdr.rcvif = 0; 477130300Sjoerg 477230300Sjoerg h = mtod (m, struct ppp_header*); 477330300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 477430300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 477530300Sjoerg h->protocol = htons(cp->proto); 477630300Sjoerg 477730300Sjoerg lh = (struct lcp_header*)(h + 1); 477830300Sjoerg lh->type = type; 477930300Sjoerg lh->ident = id; 478030300Sjoerg p = (u_char*) (lh+1); 478130300Sjoerg 478230300Sjoerg va_start(ap, id); 478330300Sjoerg len = 0; 478430300Sjoerg 478542104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 478630300Sjoerg msg = va_arg(ap, const char *); 478730300Sjoerg len += mlen; 478830300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 478930300Sjoerg va_end(ap); 479030300Sjoerg m_freem(m); 479130300Sjoerg return; 479230300Sjoerg } 479330300Sjoerg 479430300Sjoerg bcopy(msg, p, mlen); 479530300Sjoerg p += mlen; 479630300Sjoerg } 479730300Sjoerg va_end(ap); 479830300Sjoerg 479930300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 480030300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 480130300Sjoerg 480230300Sjoerg if (debug) { 480340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 480440008Sjoerg SPP_ARGS(ifp), cp->name, 480530300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 480630300Sjoerg lh->ident, ntohs(lh->len)); 480744145Sphk sppp_print_bytes((u_char*) (lh+1), len); 480869211Sphk log(-1, ">\n"); 480930300Sjoerg } 481069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 481169152Sjlemon ifp->if_oerrors++; 481230300Sjoerg} 481330300Sjoerg 481430300Sjoerg/* 481525944Sjoerg * Flush interface queue. 48164910Swollman */ 481712820Sphkstatic void 481825944Sjoergsppp_qflush(struct ifqueue *ifq) 48194910Swollman{ 482025944Sjoerg struct mbuf *m, *n; 48214910Swollman 482225944Sjoerg n = ifq->ifq_head; 482325944Sjoerg while ((m = n)) { 482425944Sjoerg n = m->m_act; 482525944Sjoerg m_freem (m); 482611189Sjkh } 482725944Sjoerg ifq->ifq_head = 0; 482825944Sjoerg ifq->ifq_tail = 0; 482925944Sjoerg ifq->ifq_len = 0; 483025944Sjoerg} 483125944Sjoerg 483225944Sjoerg/* 483325944Sjoerg * Send keepalive packets, every 10 seconds. 483425944Sjoerg */ 483525944Sjoergstatic void 483625944Sjoergsppp_keepalive(void *dummy) 483725944Sjoerg{ 4838138745Srik struct sppp *sp = (struct sppp*)dummy; 4839147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 484025944Sjoerg int s; 484125944Sjoerg 484225944Sjoerg s = splimp(); 4843138745Srik SPPP_LOCK(sp); 4844138745Srik /* Keepalive mode disabled or channel down? */ 4845138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4846148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4847138745Srik goto out; 484825944Sjoerg 4849139365Srik if (sp->pp_mode == PP_FR) { 4850139365Srik sppp_fr_keepalive (sp); 4851139365Srik goto out; 4852139365Srik } 4853139365Srik 4854138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4855138745Srik if (sp->pp_mode != IFF_CISCO && 4856138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4857138745Srik goto out; 485825944Sjoerg 4859138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4860138745Srik /* No keepalive packets got. Stop the interface. */ 4861138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4862138745Srik if_down (ifp); 4863138745Srik sppp_qflush (&sp->pp_cpq); 4864138745Srik if (sp->pp_mode != IFF_CISCO) { 4865138745Srik /* XXX */ 4866138745Srik /* Shut down the PPP link. */ 4867138745Srik lcp.Down(sp); 4868138745Srik /* Initiate negotiation. XXX */ 4869138745Srik lcp.Up(sp); 48704910Swollman } 48714910Swollman } 4872138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4873138745Srik ++sp->pp_alivecnt; 4874138745Srik if (sp->pp_mode == IFF_CISCO) 4875138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4876138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4877138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4878138745Srik long nmagic = htonl (sp->lcp.magic); 4879138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4880138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4881138745Srik sp->lcp.echoid, 4, &nmagic); 4882138745Srik } 4883138745Srikout: 4884138745Srik SPPP_UNLOCK(sp); 488525944Sjoerg splx(s); 4886138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4887138745Srik (void *)sp); 48884910Swollman} 48894910Swollman 489025944Sjoerg/* 489125944Sjoerg * Get both IP addresses. 489225944Sjoerg */ 4893139365Srikvoid 489430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 489525944Sjoerg{ 4896147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 489725944Sjoerg struct ifaddr *ifa; 489830300Sjoerg struct sockaddr_in *si, *sm; 489925944Sjoerg u_long ssrc, ddst; 490025944Sjoerg 490140010Sjoerg sm = NULL; 490225944Sjoerg ssrc = ddst = 0L; 490325944Sjoerg /* 490425944Sjoerg * Pick the first AF_INET address from the list, 490525944Sjoerg * aliases don't make any sense on a p2p link anyway. 490625944Sjoerg */ 490742065Sphk si = 0; 4908194813Srwatson IF_ADDR_LOCK(ifp); 490942065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 491025944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 491125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 491230300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 491325944Sjoerg if (si) 491425944Sjoerg break; 491525944Sjoerg } 491625944Sjoerg if (ifa) { 491730300Sjoerg if (si && si->sin_addr.s_addr) { 491825944Sjoerg ssrc = si->sin_addr.s_addr; 491930300Sjoerg if (srcmask) 492030300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 492130300Sjoerg } 492225944Sjoerg 492325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 492425944Sjoerg if (si && si->sin_addr.s_addr) 492525944Sjoerg ddst = si->sin_addr.s_addr; 492625944Sjoerg } 4927194813Srwatson IF_ADDR_UNLOCK(ifp); 492825944Sjoerg 492925944Sjoerg if (dst) *dst = ntohl(ddst); 493025944Sjoerg if (src) *src = ntohl(ssrc); 493125944Sjoerg} 493225944Sjoerg 4933184682Sbz#ifdef INET 493425944Sjoerg/* 493525944Sjoerg * Set my IP address. Must be called at splimp. 493625944Sjoerg */ 493725944Sjoergstatic void 493825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 493925944Sjoerg{ 4940183550Szec INIT_VNET_INET(curvnet); 494142104Sphk STDDCL; 494225944Sjoerg struct ifaddr *ifa; 494325944Sjoerg struct sockaddr_in *si; 494484318Sjlemon struct in_ifaddr *ia; 494525944Sjoerg 494625944Sjoerg /* 494725944Sjoerg * Pick the first AF_INET address from the list, 494825944Sjoerg * aliases don't make any sense on a p2p link anyway. 494925944Sjoerg */ 495042065Sphk si = 0; 4951194813Srwatson IF_ADDR_LOCK(ifp); 4952194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 4953194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET) { 495425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 4955194813Srwatson if (si != NULL) { 4956194813Srwatson ifa_ref(ifa); 495725944Sjoerg break; 4958194813Srwatson } 495925944Sjoerg } 496040008Sjoerg } 4961194813Srwatson IF_ADDR_UNLOCK(ifp); 496240008Sjoerg 4963194813Srwatson if (ifa != NULL) { 496442104Sphk int error; 4965194813Srwatson 496642104Sphk /* delete old route */ 496742104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 4968194813Srwatson if (debug && error) { 496942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 497042104Sphk SPP_ARGS(ifp), error); 497142104Sphk } 497242104Sphk 497342104Sphk /* set new address */ 497425944Sjoerg si->sin_addr.s_addr = htonl(src); 497584318Sjlemon ia = ifatoia(ifa); 4976194951Srwatson IN_IFADDR_WLOCK(); 497784318Sjlemon LIST_REMOVE(ia, ia_hash); 497884318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 4979194951Srwatson IN_IFADDR_WUNLOCK(); 498025944Sjoerg 498142104Sphk /* add new route */ 498270199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 4983194813Srwatson if (debug && error) { 498442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 498542104Sphk SPP_ARGS(ifp), error); 498642104Sphk } 4987194813Srwatson ifa_free(ifa); 498842104Sphk } 498988599Sjoerg} 4990184682Sbz#endif 499178064Sume 499278064Sume#ifdef INET6 499378064Sume/* 499478064Sume * Get both IPv6 addresses. 499578064Sume */ 499678064Sumestatic void 499778064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 499878064Sume struct in6_addr *srcmask) 499978064Sume{ 5000147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 500178064Sume struct ifaddr *ifa; 500278064Sume struct sockaddr_in6 *si, *sm; 500378064Sume struct in6_addr ssrc, ddst; 500478064Sume 500578064Sume sm = NULL; 500678064Sume bzero(&ssrc, sizeof(ssrc)); 500778064Sume bzero(&ddst, sizeof(ddst)); 500878064Sume /* 500978064Sume * Pick the first link-local AF_INET6 address from the list, 501078064Sume * aliases don't make any sense on a p2p link anyway. 501178064Sume */ 5012194813Srwatson si = NULL; 5013194813Srwatson IF_ADDR_LOCK(ifp); 5014160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 501578064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 501678064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 501778064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 501878064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 501978064Sume break; 502078064Sume } 502178064Sume if (ifa) { 502278064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 502378064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 502478064Sume if (srcmask) { 502578064Sume bcopy(&sm->sin6_addr, srcmask, 502678064Sume sizeof(*srcmask)); 502778064Sume } 502878064Sume } 502978064Sume 503078064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 503178064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 503278064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 503378064Sume } 503478064Sume 503578064Sume if (dst) 503678064Sume bcopy(&ddst, dst, sizeof(*dst)); 503778064Sume if (src) 503878064Sume bcopy(&ssrc, src, sizeof(*src)); 5039194813Srwatson IF_ADDR_UNLOCK(ifp); 504070199Sjhay} 504142104Sphk 504278064Sume#ifdef IPV6CP_MYIFID_DYN 504378064Sume/* 504478064Sume * Generate random ifid. 504578064Sume */ 504678064Sumestatic void 504778064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 504878064Sume{ 504978064Sume /* TBD */ 505078064Sume} 505178064Sume 505278064Sume/* 505378064Sume * Set my IPv6 address. Must be called at splimp. 505478064Sume */ 505578064Sumestatic void 505678064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 505778064Sume{ 505878064Sume STDDCL; 505978064Sume struct ifaddr *ifa; 506078064Sume struct sockaddr_in6 *sin6; 506178064Sume 506278064Sume /* 506378064Sume * Pick the first link-local AF_INET6 address from the list, 506478064Sume * aliases don't make any sense on a p2p link anyway. 506578064Sume */ 506678064Sume 506778064Sume sin6 = NULL; 5068194813Srwatson IF_ADDR_LOCK(ifp); 5069194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 5070194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET6) { 507178064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 5072194813Srwatson if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5073194813Srwatson ifa_ref(ifa); 507478064Sume break; 5075194813Srwatson } 507678064Sume } 507778064Sume } 5078194813Srwatson IF_ADDR_UNLOCK(ifp); 507978064Sume 5080194813Srwatson if (ifa != NULL) { 508178064Sume int error; 508278064Sume struct sockaddr_in6 new_sin6 = *sin6; 508378064Sume 508478064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 508578064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 5086194813Srwatson if (debug && error) { 508778064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 508878064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 508978064Sume } 5090194813Srwatson ifa_free(ifa); 509178064Sume } 509278064Sume} 509378064Sume#endif 509478064Sume 509578064Sume/* 509678064Sume * Suggest a candidate address to be used by peer. 509778064Sume */ 509878064Sumestatic void 509978064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 510078064Sume{ 510178064Sume struct in6_addr myaddr; 510278064Sume struct timeval tv; 510378064Sume 510478064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 510578064Sume 510678064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 510778064Sume microtime(&tv); 510878064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 510978064Sume myaddr.s6_addr[14] ^= 0xff; 511078064Sume myaddr.s6_addr[15] ^= 0xff; 511178064Sume } else { 511278064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 511378064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 511478064Sume } 511578064Sume if (suggest) 511678064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 511778064Sume} 511878064Sume#endif /*INET6*/ 511978064Sume 512030300Sjoergstatic int 512138343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 512230300Sjoerg{ 512338343Sbde u_long subcmd; 512430300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 512588600Sjoerg struct spppreq *spr; 512688600Sjoerg int rv = 0; 512730300Sjoerg 512888600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 512988600Sjoerg return (EAGAIN); 513030300Sjoerg /* 513130300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 513230300Sjoerg * Check the cmd word first before attempting to fetch all the 513330300Sjoerg * data. 513430300Sjoerg */ 513588600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 513688600Sjoerg rv = EFAULT; 513788600Sjoerg goto quit; 513888600Sjoerg } 513930300Sjoerg 514088600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 514188600Sjoerg rv = EFAULT; 514288600Sjoerg goto quit; 514388600Sjoerg } 514430300Sjoerg 514530300Sjoerg switch (subcmd) { 5146170490Smjacob case (u_long)SPPPIOGDEFS: 514788600Sjoerg if (cmd != SIOCGIFGENERIC) { 514888600Sjoerg rv = EINVAL; 514988600Sjoerg break; 515088600Sjoerg } 515130300Sjoerg /* 515230300Sjoerg * We copy over the entire current state, but clean 515330300Sjoerg * out some of the stuff we don't wanna pass up. 515430300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 515530300Sjoerg * called by any user. No need to ever get PAP or 515630300Sjoerg * CHAP secrets back to userland anyway. 515730300Sjoerg */ 515888600Sjoerg spr->defs.pp_phase = sp->pp_phase; 515988723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 516088723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 516188600Sjoerg spr->defs.lcp = sp->lcp; 516288600Sjoerg spr->defs.ipcp = sp->ipcp; 516388600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 516488600Sjoerg spr->defs.myauth = sp->myauth; 516588600Sjoerg spr->defs.hisauth = sp->hisauth; 516688600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 516788600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 516888600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 516988600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 517088550Sjoerg /* 517188550Sjoerg * Fixup the LCP timeout value to milliseconds so 517288550Sjoerg * spppcontrol doesn't need to bother about the value 517388550Sjoerg * of "hz". We do the reverse calculation below when 517488550Sjoerg * setting it. 517588550Sjoerg */ 517688600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 517788600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 517888600Sjoerg sizeof(struct spppreq)); 517988600Sjoerg break; 518030300Sjoerg 5181170490Smjacob case (u_long)SPPPIOSDEFS: 518288600Sjoerg if (cmd != SIOCSIFGENERIC) { 518388600Sjoerg rv = EINVAL; 518488600Sjoerg break; 518588600Sjoerg } 518630300Sjoerg /* 518788550Sjoerg * We have a very specific idea of which fields we 518888550Sjoerg * allow being passed back from userland, so to not 518988550Sjoerg * clobber our current state. For one, we only allow 519088550Sjoerg * setting anything if LCP is in dead or establish 519188550Sjoerg * phase. Once the authentication negotiations 519288550Sjoerg * started, the authentication settings must not be 519388550Sjoerg * changed again. (The administrator can force an 519430300Sjoerg * ifconfig down in order to get LCP back into dead 519530300Sjoerg * phase.) 519630300Sjoerg * 519730300Sjoerg * Also, we only allow for authentication parameters to be 519830300Sjoerg * specified. 519930300Sjoerg * 520030300Sjoerg * XXX Should allow to set or clear pp_flags. 520130300Sjoerg * 520230300Sjoerg * Finally, if the respective authentication protocol to 520330300Sjoerg * be used is set differently than 0, but the secret is 520430300Sjoerg * passed as all zeros, we don't trash the existing secret. 520530300Sjoerg * This allows an administrator to change the system name 520630300Sjoerg * only without clobbering the secret (which he didn't get 520730300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 520830300Sjoerg * secrets are cleared if the authentication protocol is 520988550Sjoerg * reset to 0. */ 521088550Sjoerg if (sp->pp_phase != PHASE_DEAD && 521188600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 521288600Sjoerg rv = EBUSY; 521388600Sjoerg break; 521488600Sjoerg } 521530300Sjoerg 521688600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 521788600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 521888600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 521988600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 522088600Sjoerg rv = EINVAL; 522188600Sjoerg break; 522288600Sjoerg } 522330300Sjoerg 522488600Sjoerg if (spr->defs.myauth.proto == 0) 522530300Sjoerg /* resetting myauth */ 522630300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 522730300Sjoerg else { 522830300Sjoerg /* setting/changing myauth */ 522988600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 523088600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 523188600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 523288600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 523330300Sjoerg AUTHKEYLEN); 523430300Sjoerg } 523588600Sjoerg if (spr->defs.hisauth.proto == 0) 523630300Sjoerg /* resetting hisauth */ 523730300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 523830300Sjoerg else { 523930300Sjoerg /* setting/changing hisauth */ 524088600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 524188600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 524288600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 524388600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 524488600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 524530300Sjoerg AUTHKEYLEN); 524630300Sjoerg } 524788550Sjoerg /* set LCP restart timer timeout */ 524888600Sjoerg if (spr->defs.lcp.timeout != 0) 524988600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 525088723Sjoerg /* set VJ enable and IPv6 disable flags */ 525188723Sjoerg#ifdef INET 525288723Sjoerg if (spr->defs.enable_vj) 525388723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 525488723Sjoerg else 525588723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 525688723Sjoerg#endif 525788723Sjoerg#ifdef INET6 525888723Sjoerg if (spr->defs.enable_ipv6) 525988723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 526088723Sjoerg else 526188723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 526296349Sjoerg#endif 526330300Sjoerg break; 526430300Sjoerg 526530300Sjoerg default: 526688600Sjoerg rv = EINVAL; 526730300Sjoerg } 526830300Sjoerg 526988600Sjoerg quit: 527088600Sjoerg free(spr, M_TEMP); 527188600Sjoerg 527288600Sjoerg return (rv); 527330300Sjoerg} 527430300Sjoerg 527530300Sjoergstatic void 527630300Sjoergsppp_phase_network(struct sppp *sp) 527730300Sjoerg{ 527842066Sphk STDDCL; 527930300Sjoerg int i; 528030300Sjoerg u_long mask; 528130300Sjoerg 528230300Sjoerg sp->pp_phase = PHASE_NETWORK; 528330300Sjoerg 528442066Sphk if (debug) 528542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 528642066Sphk sppp_phase_name(sp->pp_phase)); 528730300Sjoerg 528830300Sjoerg /* Notify NCPs now. */ 528930300Sjoerg for (i = 0; i < IDX_COUNT; i++) 529030300Sjoerg if ((cps[i])->flags & CP_NCP) 529130300Sjoerg (cps[i])->Open(sp); 529230300Sjoerg 529330300Sjoerg /* Send Up events to all NCPs. */ 529430300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 529588706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 529630300Sjoerg (cps[i])->Up(sp); 529730300Sjoerg 529830300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 529930300Sjoerg sppp_lcp_check_and_close(sp); 530030300Sjoerg} 530130300Sjoerg 530270199Sjhay 530325706Sjoergstatic const char * 530425944Sjoergsppp_cp_type_name(u_char type) 53054910Swollman{ 530630300Sjoerg static char buf[12]; 53074910Swollman switch (type) { 530830300Sjoerg case CONF_REQ: return "conf-req"; 530930300Sjoerg case CONF_ACK: return "conf-ack"; 531030300Sjoerg case CONF_NAK: return "conf-nak"; 531130300Sjoerg case CONF_REJ: return "conf-rej"; 531230300Sjoerg case TERM_REQ: return "term-req"; 531330300Sjoerg case TERM_ACK: return "term-ack"; 531430300Sjoerg case CODE_REJ: return "code-rej"; 531530300Sjoerg case PROTO_REJ: return "proto-rej"; 531630300Sjoerg case ECHO_REQ: return "echo-req"; 531730300Sjoerg case ECHO_REPLY: return "echo-reply"; 531830300Sjoerg case DISC_REQ: return "discard-req"; 53194910Swollman } 532044145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 532130300Sjoerg return buf; 53224910Swollman} 53234910Swollman 532425706Sjoergstatic const char * 532530300Sjoergsppp_auth_type_name(u_short proto, u_char type) 532630300Sjoerg{ 532730300Sjoerg static char buf[12]; 532830300Sjoerg switch (proto) { 532930300Sjoerg case PPP_CHAP: 533030300Sjoerg switch (type) { 533130300Sjoerg case CHAP_CHALLENGE: return "challenge"; 533230300Sjoerg case CHAP_RESPONSE: return "response"; 533330300Sjoerg case CHAP_SUCCESS: return "success"; 533430300Sjoerg case CHAP_FAILURE: return "failure"; 533530300Sjoerg } 533630300Sjoerg case PPP_PAP: 533730300Sjoerg switch (type) { 533830300Sjoerg case PAP_REQ: return "req"; 533930300Sjoerg case PAP_ACK: return "ack"; 534030300Sjoerg case PAP_NAK: return "nak"; 534130300Sjoerg } 534230300Sjoerg } 534344145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 534430300Sjoerg return buf; 534530300Sjoerg} 534630300Sjoerg 534730300Sjoergstatic const char * 534825944Sjoergsppp_lcp_opt_name(u_char opt) 53494910Swollman{ 535030300Sjoerg static char buf[12]; 535125944Sjoerg switch (opt) { 535230300Sjoerg case LCP_OPT_MRU: return "mru"; 535330300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 535430300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 535530300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 535630300Sjoerg case LCP_OPT_MAGIC: return "magic"; 535730300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 535830300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 53594910Swollman } 536044145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 536130300Sjoerg return buf; 53624910Swollman} 53634910Swollman 5364184682Sbz#ifdef INET 536525944Sjoergstatic const char * 536625944Sjoergsppp_ipcp_opt_name(u_char opt) 536725944Sjoerg{ 536830300Sjoerg static char buf[12]; 536925944Sjoerg switch (opt) { 537030300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 537130300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 537230300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 537325944Sjoerg } 537444145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 537530300Sjoerg return buf; 537625944Sjoerg} 5377184682Sbz#endif 537825944Sjoerg 537978064Sume#ifdef INET6 538025944Sjoergstatic const char * 538178064Sumesppp_ipv6cp_opt_name(u_char opt) 538278064Sume{ 538378064Sume static char buf[12]; 538478064Sume switch (opt) { 538578064Sume case IPV6CP_OPT_IFID: return "ifid"; 538678064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 538778064Sume } 538878064Sume sprintf (buf, "0x%x", opt); 538978064Sume return buf; 539078064Sume} 539178064Sume#endif 539278064Sume 539378064Sumestatic const char * 539425944Sjoergsppp_state_name(int state) 539525944Sjoerg{ 539625944Sjoerg switch (state) { 539725944Sjoerg case STATE_INITIAL: return "initial"; 539825944Sjoerg case STATE_STARTING: return "starting"; 539925944Sjoerg case STATE_CLOSED: return "closed"; 540025944Sjoerg case STATE_STOPPED: return "stopped"; 540125944Sjoerg case STATE_CLOSING: return "closing"; 540225944Sjoerg case STATE_STOPPING: return "stopping"; 540325944Sjoerg case STATE_REQ_SENT: return "req-sent"; 540425944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 540525944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 540625944Sjoerg case STATE_OPENED: return "opened"; 540725944Sjoerg } 540825944Sjoerg return "illegal"; 540925944Sjoerg} 541025944Sjoerg 541125944Sjoergstatic const char * 541225944Sjoergsppp_phase_name(enum ppp_phase phase) 541325944Sjoerg{ 541425944Sjoerg switch (phase) { 541525944Sjoerg case PHASE_DEAD: return "dead"; 541625944Sjoerg case PHASE_ESTABLISH: return "establish"; 541725944Sjoerg case PHASE_TERMINATE: return "terminate"; 541825944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 541925944Sjoerg case PHASE_NETWORK: return "network"; 542025944Sjoerg } 542125944Sjoerg return "illegal"; 542225944Sjoerg} 542325944Sjoerg 542425944Sjoergstatic const char * 542525944Sjoergsppp_proto_name(u_short proto) 542625944Sjoerg{ 542725944Sjoerg static char buf[12]; 542825944Sjoerg switch (proto) { 542925944Sjoerg case PPP_LCP: return "lcp"; 543025944Sjoerg case PPP_IPCP: return "ipcp"; 543130300Sjoerg case PPP_PAP: return "pap"; 543230300Sjoerg case PPP_CHAP: return "chap"; 543378064Sume case PPP_IPV6CP: return "ipv6cp"; 543425944Sjoerg } 543544145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 543625944Sjoerg return buf; 543725944Sjoerg} 543825944Sjoerg 543912820Sphkstatic void 544030300Sjoergsppp_print_bytes(const u_char *p, u_short len) 54414910Swollman{ 544244145Sphk if (len) 544369211Sphk log(-1, " %*D", len, p, "-"); 54444910Swollman} 544525944Sjoerg 544630300Sjoergstatic void 544730300Sjoergsppp_print_string(const char *p, u_short len) 544830300Sjoerg{ 544930300Sjoerg u_char c; 545030300Sjoerg 545130300Sjoerg while (len-- > 0) { 545230300Sjoerg c = *p++; 545330300Sjoerg /* 545430300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 545530300Sjoerg * using only them, but we don't rely on it. */ 545630300Sjoerg if (c < ' ' || c > '~') 545769211Sphk log(-1, "\\x%x", c); 545830300Sjoerg else 545969211Sphk log(-1, "%c", c); 546030300Sjoerg } 546130300Sjoerg} 546230300Sjoerg 5463184682Sbz#ifdef INET 546430300Sjoergstatic const char * 546530300Sjoergsppp_dotted_quad(u_long addr) 546630300Sjoerg{ 546730300Sjoerg static char s[16]; 546830300Sjoerg sprintf(s, "%d.%d.%d.%d", 546940008Sjoerg (int)((addr >> 24) & 0xff), 547040008Sjoerg (int)((addr >> 16) & 0xff), 547140008Sjoerg (int)((addr >> 8) & 0xff), 547238372Sbde (int)(addr & 0xff)); 547330300Sjoerg return s; 547430300Sjoerg} 5475184682Sbz#endif 547630300Sjoerg 547730300Sjoergstatic int 547830300Sjoergsppp_strnlen(u_char *p, int max) 547930300Sjoerg{ 548030300Sjoerg int len; 548130300Sjoerg 548230300Sjoerg for (len = 0; len < max && *p; ++p) 548330300Sjoerg ++len; 548430300Sjoerg return len; 548530300Sjoerg} 548630300Sjoerg 548730300Sjoerg/* a dummy, used to drop uninteresting events */ 548830300Sjoergstatic void 548930300Sjoergsppp_null(struct sppp *unused) 549030300Sjoerg{ 549130300Sjoerg /* do just nothing */ 549230300Sjoerg} 5493