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: stable/11/sys/net/if_spppsubr.c 352481 2019-09-18 07:32:15Z hselasky $ 224910Swollman */ 234910Swollman 2440008Sjoerg#include <sys/param.h> 2540008Sjoerg 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind 294952Sbde#include <sys/systm.h> 304952Sbde#include <sys/kernel.h> 31286001Sae#include <sys/lock.h> 3270199Sjhay#include <sys/module.h> 33286001Sae#include <sys/rmlock.h> 3424204Sbde#include <sys/sockio.h> 354910Swollman#include <sys/socket.h> 3625706Sjoerg#include <sys/syslog.h> 3759604Sobrien#include <sys/random.h> 3829024Sbde#include <sys/malloc.h> 394910Swollman#include <sys/mbuf.h> 4040008Sjoerg 4130300Sjoerg#include <sys/md5.h> 424910Swollman 434910Swollman#include <net/if.h> 44257176Sglebius#include <net/if_var.h> 454910Swollman#include <net/netisr.h> 464910Swollman#include <net/if_types.h> 4742104Sphk#include <net/route.h> 48196019Srwatson#include <net/vnet.h> 4988534Sjoerg#include <netinet/in.h> 5088534Sjoerg#include <netinet/in_systm.h> 5188534Sjoerg#include <netinet/ip.h> 5288534Sjoerg#include <net/slcompress.h> 534910Swollman 5430300Sjoerg#include <machine/stdarg.h> 5530300Sjoerg 564910Swollman#include <netinet/in_var.h> 5788705Sjoerg 5888705Sjoerg#ifdef INET 594910Swollman#include <netinet/ip.h> 604910Swollman#include <netinet/tcp.h> 614910Swollman#endif 624910Swollman 63148385Sume#ifdef INET6 64148385Sume#include <netinet6/scope6_var.h> 65148385Sume#endif 66148385Sume 67182121Simp#include <netinet/if_ether.h> 6888705Sjoerg 694910Swollman#include <net/if_sppp.h> 704910Swollman 71182121Simp#define IOCTL_CMD_T u_long 724910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 734910Swollman 7425944Sjoerg/* 7525944Sjoerg * Interface flags that can be set in an ifconfig command. 7625944Sjoerg * 7725955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 7825944Sjoerg * as being administrative openable, but won't be opened to begin 7925944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 8025944Sjoerg * -link1 will cause the administrative open of the LCP layer. 8125955Sjoerg * 8225955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 8325955Sjoerg * arrive to be sent. 8430300Sjoerg * 8530300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 8630300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 8730300Sjoerg * like 8830300Sjoerg * 8930300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 9030300Sjoerg * 9130300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 9230300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 9325944Sjoerg */ 9425944Sjoerg 9525955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 9625955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 9745152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 9825944Sjoerg 9930300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 10030300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 10130300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 10230300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 10330300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 10430300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 10588534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 10688534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 10778064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 10830300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 10930300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 11030300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 11130300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 11278064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1134910Swollman 11425944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 11525944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 11625944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 11725944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 11825944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 11925944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 12025944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 12125944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 12225944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 12325944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 12425944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1254910Swollman 12630300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 12730300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 12830300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 12930300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 13030300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 13130300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 13230300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 13330300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1344910Swollman 13525944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 13625944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 13725944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1384910Swollman 13978064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 14078064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 14178064Sume 14288534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 14388534Sjoerg 14430300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 14530300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 14630300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1474910Swollman 14830300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 14930300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 15030300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 15130300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 15230300Sjoerg 15330300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 15430300Sjoerg 15530300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 15630300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 15730300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 15830300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 15930300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 16030300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 16130300Sjoerg 16225944Sjoerg/* states are named and numbered according to RFC 1661 */ 16325944Sjoerg#define STATE_INITIAL 0 16425944Sjoerg#define STATE_STARTING 1 16525944Sjoerg#define STATE_CLOSED 2 16625944Sjoerg#define STATE_STOPPED 3 16725944Sjoerg#define STATE_CLOSING 4 16825944Sjoerg#define STATE_STOPPING 5 16925944Sjoerg#define STATE_REQ_SENT 6 17025944Sjoerg#define STATE_ACK_RCVD 7 17125944Sjoerg#define STATE_ACK_SENT 8 17225944Sjoerg#define STATE_OPENED 9 17325944Sjoerg 174227293Sedstatic MALLOC_DEFINE(M_SPPP, "sppp", "synchronous PPP interface internals"); 175147256Sbrooks 1764910Swollmanstruct ppp_header { 17711189Sjkh u_char address; 17811189Sjkh u_char control; 17911189Sjkh u_short protocol; 180103842Salfred} __packed; 1814910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1824910Swollman 1834910Swollmanstruct lcp_header { 18411189Sjkh u_char type; 18511189Sjkh u_char ident; 18611189Sjkh u_short len; 187103842Salfred} __packed; 1884910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1894910Swollman 1904910Swollmanstruct cisco_packet { 19111189Sjkh u_long type; 19211189Sjkh u_long par1; 19311189Sjkh u_long par2; 19411189Sjkh u_short rel; 19511189Sjkh u_short time0; 19611189Sjkh u_short time1; 197103842Salfred} __packed; 19888704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 1994910Swollman 20025944Sjoerg/* 20125944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 20225944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 20325944Sjoerg * case you can't make sense out of these abbreviation; it will also 20425944Sjoerg * explain the semantics related to the various events and actions. 20525944Sjoerg */ 20625944Sjoergstruct cp { 20725944Sjoerg u_short proto; /* PPP control protocol number */ 20825944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 20925944Sjoerg u_char flags; 21025944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 21125944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 21225944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 21325944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 21425944Sjoerg const char *name; /* name of this control protocol */ 21525944Sjoerg /* event handlers */ 21625944Sjoerg void (*Up)(struct sppp *sp); 21725944Sjoerg void (*Down)(struct sppp *sp); 21825944Sjoerg void (*Open)(struct sppp *sp); 21925944Sjoerg void (*Close)(struct sppp *sp); 22025944Sjoerg void (*TO)(void *sp); 22125944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 22225944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 22325944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 22425944Sjoerg /* actions */ 22525944Sjoerg void (*tlu)(struct sppp *sp); 22625944Sjoerg void (*tld)(struct sppp *sp); 22725944Sjoerg void (*tls)(struct sppp *sp); 22825944Sjoerg void (*tlf)(struct sppp *sp); 22925944Sjoerg void (*scr)(struct sppp *sp); 23025944Sjoerg}; 23125944Sjoerg 23240008Sjoerg#define SPP_FMT "%s: " 23340008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 23440008Sjoerg 235188668Srwatson#define SPPP_LOCK(sp) mtx_lock (&(sp)->mtx) 236188668Srwatson#define SPPP_UNLOCK(sp) mtx_unlock (&(sp)->mtx) 237188668Srwatson#define SPPP_LOCK_ASSERT(sp) mtx_assert (&(sp)->mtx, MA_OWNED) 238190818Sed#define SPPP_LOCK_OWNED(sp) mtx_owned (&(sp)->mtx) 239138745Srik 24088705Sjoerg#ifdef INET 2414910Swollman/* 2424910Swollman * The following disgusting hack gets around the problem that IP TOS 2434910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2444910Swollman * priority queue. To decide if traffic is interactive, we check that 2454910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 24630300Sjoerg * 24730300Sjoerg * XXX is this really still necessary? - joerg - 2484910Swollman */ 249126910Srwatsonstatic const u_short interactive_ports[8] = { 2504910Swollman 0, 513, 0, 0, 2514910Swollman 0, 21, 0, 23, 2524910Swollman}; 2534910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 25488705Sjoerg#endif 2554910Swollman 25625944Sjoerg/* almost every function needs these */ 25725944Sjoerg#define STDDCL \ 258147256Sbrooks struct ifnet *ifp = SP2IFP(sp); \ 25925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 26011189Sjkh 26130300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 262249925Sglebius const struct sockaddr *dst, struct route *ro); 2634910Swollman 26425944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 26525944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 26625944Sjoerg 26725944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 26825944Sjoerg struct mbuf *m); 26925944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 27025944Sjoerg u_char ident, u_short len, void *data); 27142104Sphk/* static void sppp_cp_timeout(void *arg); */ 27225944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 27325944Sjoerg int newstate); 27430300Sjoergstatic void sppp_auth_send(const struct cp *cp, 27542104Sphk struct sppp *sp, unsigned int type, unsigned int id, 27630300Sjoerg ...); 27725944Sjoerg 27825944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 27925944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 28025944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 28125944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 28225944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 28325944Sjoerg 28430300Sjoergstatic void sppp_null(struct sppp *sp); 28530300Sjoerg 286138745Srikstatic void sppp_pp_up(struct sppp *sp); 287138745Srikstatic void sppp_pp_down(struct sppp *sp); 288138745Srik 28925944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 29025944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 29125944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 29225944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 29325944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 29425944Sjoergstatic void sppp_lcp_TO(void *sp); 29525944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 29625944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 29725944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 29825944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 29925944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 30025944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 30125944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 30225944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 30330300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 30430300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 30525944Sjoerg 30625944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 30725944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 30825944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 30925944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 31025944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 31125944Sjoergstatic void sppp_ipcp_TO(void *sp); 31225944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31325944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31425944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 31525944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 31625944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 31725944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 31825944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 31925944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 32025944Sjoerg 32178064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 32278064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 32378064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 32478064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 32578064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 32678064Sumestatic void sppp_ipv6cp_TO(void *sp); 32778064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32878064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 32978064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33078064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 33178064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 33278064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 33378064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 33478064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 33578064Sume 33630300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 33730300Sjoergstatic void sppp_pap_init(struct sppp *sp); 33830300Sjoergstatic void sppp_pap_open(struct sppp *sp); 33930300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34030300Sjoergstatic void sppp_pap_TO(void *sp); 34130300Sjoergstatic void sppp_pap_my_TO(void *sp); 34230300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 34330300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 34430300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 34530300Sjoerg 34630300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 34730300Sjoergstatic void sppp_chap_init(struct sppp *sp); 34830300Sjoergstatic void sppp_chap_open(struct sppp *sp); 34930300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35030300Sjoergstatic void sppp_chap_TO(void *sp); 35130300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35230300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 35330300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 35430300Sjoerg 35530300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 35625944Sjoergstatic const char *sppp_cp_type_name(u_char type); 357184682Sbz#ifdef INET 35830300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 35930300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 360184682Sbz#endif 36178064Sume#ifdef INET6 36278064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 36378064Sume#endif 36425944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36525944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 36625944Sjoergstatic const char *sppp_proto_name(u_short proto); 36730300Sjoergstatic const char *sppp_state_name(int state); 36838343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 36930300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37025944Sjoergstatic void sppp_keepalive(void *dummy); 37130300Sjoergstatic void sppp_phase_network(struct sppp *sp); 37230300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 37330300Sjoergstatic void sppp_print_string(const char *p, u_short len); 37425944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 375184682Sbz#ifdef INET 37625944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 377184682Sbz#endif 37878064Sume#ifdef INET6 37978064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 38078064Sume struct in6_addr *dst, struct in6_addr *srcmask); 38178064Sume#ifdef IPV6CP_MYIFID_DYN 38278064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38378064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38478064Sume#endif 38578064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 38678064Sume#endif 38725944Sjoerg 388138745Srik/* if_start () wrapper */ 389138745Srikstatic void sppp_ifstart (struct ifnet *ifp); 390138745Srik 39125944Sjoerg/* our control protocol descriptors */ 39233181Seivindstatic const struct cp lcp = { 39325944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 39425944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 39525944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 39625944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 39725944Sjoerg sppp_lcp_scr 39825944Sjoerg}; 39925944Sjoerg 40033181Seivindstatic const struct cp ipcp = { 40188709Sjoerg PPP_IPCP, IDX_IPCP, 40288709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 40388709Sjoerg CP_NCP, 40488709Sjoerg#else 40588709Sjoerg 0, 40688709Sjoerg#endif 40788709Sjoerg "ipcp", 40825944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 40925944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 41025944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 41125944Sjoerg sppp_ipcp_scr 41225944Sjoerg}; 41325944Sjoerg 41478064Sumestatic const struct cp ipv6cp = { 41578064Sume PPP_IPV6CP, IDX_IPV6CP, 41678064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 41778064Sume CP_NCP, 41878064Sume#else 41978064Sume 0, 42078064Sume#endif 42178064Sume "ipv6cp", 42278064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 42378064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 42478064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 42578064Sume sppp_ipv6cp_scr 42678064Sume}; 42778064Sume 42833181Seivindstatic const struct cp pap = { 42930300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 43030300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 43130300Sjoerg sppp_pap_TO, 0, 0, 0, 43230300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 43330300Sjoerg sppp_pap_scr 43430300Sjoerg}; 43530300Sjoerg 43633181Seivindstatic const struct cp chap = { 43730300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 43830300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 43930300Sjoerg sppp_chap_TO, 0, 0, 0, 44030300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 44130300Sjoerg sppp_chap_scr 44230300Sjoerg}; 44330300Sjoerg 44433181Seivindstatic const struct cp *cps[IDX_COUNT] = { 44525944Sjoerg &lcp, /* IDX_LCP */ 44625944Sjoerg &ipcp, /* IDX_IPCP */ 44778064Sume &ipv6cp, /* IDX_IPV6CP */ 44830300Sjoerg &pap, /* IDX_PAP */ 44930300Sjoerg &chap, /* IDX_CHAP */ 45025944Sjoerg}; 45125944Sjoerg 452147256Sbrooksstatic void* 453147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp) 454147256Sbrooks{ 455147256Sbrooks struct sppp *sp; 456147256Sbrooks 457147256Sbrooks sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO); 458147256Sbrooks sp->pp_ifp = ifp; 459147256Sbrooks 460147256Sbrooks return (sp); 461147256Sbrooks} 462147256Sbrooks 463147256Sbrooksstatic void 464147256Sbrookssppp_free(void *com, u_char type) 465147256Sbrooks{ 466147256Sbrooks 467147256Sbrooks free(com, M_SPPP); 468147256Sbrooks} 469147256Sbrooks 47070199Sjhaystatic int 47170199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47270199Sjhay{ 47370199Sjhay switch (type) { 47470199Sjhay case MOD_LOAD: 475147256Sbrooks /* 476147256Sbrooks * XXX: should probably be IFT_SPPP, but it's fairly 477147256Sbrooks * harmless to allocate struct sppp's for non-sppp 478147256Sbrooks * interfaces. 479147256Sbrooks */ 480147256Sbrooks 481147256Sbrooks if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free); 48270199Sjhay break; 48370199Sjhay case MOD_UNLOAD: 484147256Sbrooks /* if_deregister_com_alloc(IFT_PPP); */ 48570199Sjhay return EACCES; 48670199Sjhay default: 487132199Sphk return EOPNOTSUPP; 48870199Sjhay } 48970199Sjhay return 0; 49070199Sjhay} 49170199Sjhaystatic moduledata_t spppmod = { 49270199Sjhay "sppp", 49370199Sjhay sppp_modevent, 494241394Skevlo 0 49570199Sjhay}; 49670199SjhayMODULE_VERSION(sppp, 1); 49770199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 49825944Sjoerg 49970199Sjhay/* 50025944Sjoerg * Exported functions, comprising our interface to the lower layer. 5014910Swollman */ 5024910Swollman 5034910Swollman/* 5044910Swollman * Process the received packet. 5054910Swollman */ 50625706Sjoergvoid 50725706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5084910Swollman{ 5094910Swollman struct ppp_header *h; 510111888Sjlemon int isr = -1; 511147256Sbrooks struct sppp *sp = IFP2SP(ifp); 512184682Sbz int debug, do_account = 0; 513184682Sbz#ifdef INET 514184682Sbz int hlen, vjlen; 51588700Sjoerg u_char *iphdr; 516184682Sbz#endif 5174910Swollman 518138745Srik SPPP_LOCK(sp); 519138745Srik debug = ifp->if_flags & IFF_DEBUG; 520138745Srik 5214910Swollman if (ifp->if_flags & IFF_UP) 5224910Swollman /* Count received bytes, add FCS and one flag */ 523271867Sglebius if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len + 3); 5244910Swollman 5254910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5264910Swollman /* Too small packet, drop it. */ 52725944Sjoerg if (debug) 52825706Sjoerg log(LOG_DEBUG, 52940008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 53040008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 53125944Sjoerg drop: 53288700Sjoerg m_freem (m); 533138745Srik SPPP_UNLOCK(sp); 53488700Sjoerg drop2: 535271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 536271867Sglebius if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 5374910Swollman return; 5384910Swollman } 5394910Swollman 540139365Srik if (sp->pp_mode == PP_FR) { 541139365Srik sppp_fr_input (sp, m); 542139365Srik SPPP_UNLOCK(sp); 543139365Srik return; 544139365Srik } 545139365Srik 5464910Swollman /* Get PPP header. */ 5474910Swollman h = mtod (m, struct ppp_header*); 5484910Swollman m_adj (m, PPP_HEADER_LEN); 5494910Swollman 5504910Swollman switch (h->address) { 5514910Swollman case PPP_ALLSTATIONS: 5524910Swollman if (h->control != PPP_UI) 5534910Swollman goto invalid; 55445152Sphk if (sp->pp_mode == IFF_CISCO) { 55525944Sjoerg if (debug) 55625706Sjoerg log(LOG_DEBUG, 55740008Sjoerg SPP_FMT "PPP packet in Cisco mode " 55825706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55940008Sjoerg SPP_ARGS(ifp), 56025706Sjoerg h->address, h->control, ntohs(h->protocol)); 56111189Sjkh goto drop; 56211189Sjkh } 5634910Swollman switch (ntohs (h->protocol)) { 5644910Swollman default: 56525944Sjoerg if (debug) 56625706Sjoerg log(LOG_DEBUG, 56744145Sphk SPP_FMT "rejecting protocol " 56825706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 56940008Sjoerg SPP_ARGS(ifp), 57025706Sjoerg h->address, h->control, ntohs(h->protocol)); 57144145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 57244145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 57378064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 57444145Sphk &h->protocol); 575271867Sglebius if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); 5764910Swollman goto drop; 5774910Swollman case PPP_LCP: 57830300Sjoerg sppp_cp_input(&lcp, sp, m); 5794910Swollman m_freem (m); 580138745Srik SPPP_UNLOCK(sp); 5814910Swollman return; 58230300Sjoerg case PPP_PAP: 58330300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 58430300Sjoerg sppp_pap_input(sp, m); 58530300Sjoerg m_freem (m); 586138745Srik SPPP_UNLOCK(sp); 58730300Sjoerg return; 58830300Sjoerg case PPP_CHAP: 58930300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 59030300Sjoerg sppp_chap_input(sp, m); 59130300Sjoerg m_freem (m); 592138745Srik SPPP_UNLOCK(sp); 59330300Sjoerg return; 5944910Swollman#ifdef INET 5954910Swollman case PPP_IPCP: 59625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 59730300Sjoerg sppp_cp_input(&ipcp, sp, m); 5984910Swollman m_freem (m); 599138745Srik SPPP_UNLOCK(sp); 6004910Swollman return; 6014910Swollman case PPP_IP: 60225944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 603111888Sjlemon isr = NETISR_IP; 6044910Swollman } 60588577Sjoerg do_account++; 6064910Swollman break; 60788534Sjoerg case PPP_VJ_COMP: 60888534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 60988700Sjoerg if ((vjlen = 61088700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 61188700Sjoerg m->m_len, m->m_len, 61288700Sjoerg TYPE_COMPRESSED_TCP, 61388700Sjoerg sp->pp_comp, 61488700Sjoerg &iphdr, &hlen)) <= 0) { 61588700Sjoerg if (debug) 61688700Sjoerg log(LOG_INFO, 61788700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 61888700Sjoerg SPP_ARGS(ifp)); 61988534Sjoerg goto drop; 62088700Sjoerg } 62188700Sjoerg 62288700Sjoerg /* 62388700Sjoerg * Trim the VJ header off the packet, and prepend 62488700Sjoerg * the uncompressed IP header (which will usually 62588700Sjoerg * end up in two chained mbufs since there's not 62688700Sjoerg * enough leading space in the existing mbuf). 62788700Sjoerg */ 62888700Sjoerg m_adj(m, vjlen); 629243882Sglebius M_PREPEND(m, hlen, M_NOWAIT); 630138745Srik if (m == NULL) { 631138745Srik SPPP_UNLOCK(sp); 63288700Sjoerg goto drop2; 633138745Srik } 63488700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 635111888Sjlemon isr = NETISR_IP; 63688534Sjoerg } 63788599Sjoerg do_account++; 63888534Sjoerg break; 63988534Sjoerg case PPP_VJ_UCOMP: 64088534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 64188700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 64288700Sjoerg m->m_len, m->m_len, 64388700Sjoerg TYPE_UNCOMPRESSED_TCP, 64488700Sjoerg sp->pp_comp, 64588700Sjoerg &iphdr, &hlen) != 0) { 64688700Sjoerg if (debug) 64788700Sjoerg log(LOG_INFO, 64888700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 64988700Sjoerg SPP_ARGS(ifp)); 65088534Sjoerg goto drop; 65188700Sjoerg } 652111888Sjlemon isr = NETISR_IP; 65388534Sjoerg } 65488599Sjoerg do_account++; 65588534Sjoerg break; 65678064Sume#endif 65788599Sjoerg#ifdef INET6 65888599Sjoerg case PPP_IPV6CP: 65988599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 66088599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 66188599Sjoerg m_freem (m); 662138745Srik SPPP_UNLOCK(sp); 66388599Sjoerg return; 66488599Sjoerg 66588599Sjoerg case PPP_IPV6: 666111888Sjlemon if (sp->state[IDX_IPV6CP] == STATE_OPENED) 667111888Sjlemon isr = NETISR_IPV6; 66888599Sjoerg do_account++; 66988599Sjoerg break; 67088599Sjoerg#endif 6714910Swollman } 6724910Swollman break; 6734910Swollman case CISCO_MULTICAST: 6744910Swollman case CISCO_UNICAST: 6754910Swollman /* Don't check the control field here (RFC 1547). */ 67645152Sphk if (sp->pp_mode != IFF_CISCO) { 67725944Sjoerg if (debug) 67825706Sjoerg log(LOG_DEBUG, 67940008Sjoerg SPP_FMT "Cisco packet in PPP mode " 68025706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 68140008Sjoerg SPP_ARGS(ifp), 68225706Sjoerg h->address, h->control, ntohs(h->protocol)); 68311189Sjkh goto drop; 68411189Sjkh } 6854910Swollman switch (ntohs (h->protocol)) { 6864910Swollman default: 687271867Sglebius if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1); 6884910Swollman goto invalid; 6894910Swollman case CISCO_KEEPALIVE: 690147256Sbrooks sppp_cisco_input (sp, m); 6914910Swollman m_freem (m); 692138745Srik SPPP_UNLOCK(sp); 6934910Swollman return; 6944910Swollman#ifdef INET 6954910Swollman case ETHERTYPE_IP: 696111888Sjlemon isr = NETISR_IP; 69788577Sjoerg do_account++; 6984910Swollman break; 6994910Swollman#endif 70054263Sshin#ifdef INET6 70154263Sshin case ETHERTYPE_IPV6: 702111888Sjlemon isr = NETISR_IPV6; 70388577Sjoerg do_account++; 70454263Sshin break; 70554263Sshin#endif 7064910Swollman } 7074910Swollman break; 70825944Sjoerg default: /* Invalid PPP packet. */ 70925944Sjoerg invalid: 71025944Sjoerg if (debug) 71125944Sjoerg log(LOG_DEBUG, 71240008Sjoerg SPP_FMT "invalid input packet " 71325944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 71440008Sjoerg SPP_ARGS(ifp), 71525944Sjoerg h->address, h->control, ntohs(h->protocol)); 71625944Sjoerg goto drop; 7174910Swollman } 7184910Swollman 719111888Sjlemon if (! (ifp->if_flags & IFF_UP) || isr == -1) 7204910Swollman goto drop; 7214910Swollman 722138745Srik SPPP_UNLOCK(sp); 723223741Sbz M_SETFIB(m, ifp->if_fib); 7244910Swollman /* Check queue. */ 725134391Sandre if (netisr_queue(isr, m)) { /* (0) on success. */ 72625944Sjoerg if (debug) 72740008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 72840008Sjoerg SPP_ARGS(ifp)); 729131241Srik goto drop2; 7304910Swollman } 731138745Srik 73288577Sjoerg if (do_account) 73388577Sjoerg /* 73488577Sjoerg * Do only account for network packets, not for control 73588577Sjoerg * packets. This is used by some subsystems to detect 73688577Sjoerg * idle lines. 73788577Sjoerg */ 738150349Sandre sp->pp_last_recv = time_uptime; 7394910Swollman} 7404910Swollman 741138745Srikstatic void 742138745Sriksppp_ifstart_sched(void *dummy) 743138745Srik{ 744138745Srik struct sppp *sp = dummy; 745138745Srik 746147256Sbrooks sp->if_start(SP2IFP(sp)); 747138745Srik} 748138745Srik 749138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for 750138745Srik * execution. We can't call it directly 751138745Srik */ 752138745Srikstatic void 753138745Sriksppp_ifstart(struct ifnet *ifp) 754138745Srik{ 755147256Sbrooks struct sppp *sp = IFP2SP(ifp); 756138745Srik 757138745Srik if (SPPP_LOCK_OWNED(sp)) { 758138745Srik if (callout_pending(&sp->ifstart_callout)) 759138745Srik return; 760138745Srik callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched, 761138745Srik (void *)sp); 762138745Srik } else { 763138745Srik sp->if_start(ifp); 764138745Srik } 765138745Srik} 766138745Srik 7674910Swollman/* 7684910Swollman * Enqueue transmit packet. 7694910Swollman */ 77012820Sphkstatic int 771249925Sglebiussppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 772249925Sglebius struct route *ro) 7734910Swollman{ 774147256Sbrooks struct sppp *sp = IFP2SP(ifp); 7754910Swollman struct ppp_header *h; 77678064Sume struct ifqueue *ifq = NULL; 777241686Sandre int error, rv = 0; 778184682Sbz#ifdef INET 77988534Sjoerg int ipproto = PPP_IP; 780184682Sbz#endif 78142066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7824910Swollman 783138745Srik SPPP_LOCK(sp); 78425944Sjoerg 785148887Srwatson if (!(ifp->if_flags & IFF_UP) || 786148887Srwatson (!(ifp->if_flags & IFF_AUTO) && 787148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING))) { 78888723Sjoerg#ifdef INET6 78988723Sjoerg drop: 79088723Sjoerg#endif 7914910Swollman m_freem (m); 792138745Srik SPPP_UNLOCK(sp); 7934910Swollman return (ENETDOWN); 7944910Swollman } 7954910Swollman 796148887Srwatson if ((ifp->if_flags & IFF_AUTO) && 797148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 79888723Sjoerg#ifdef INET6 79925944Sjoerg /* 80088723Sjoerg * XXX 80188723Sjoerg * 80288723Sjoerg * Hack to prevent the initialization-time generated 80388723Sjoerg * IPv6 multicast packet to erroneously cause a 80488723Sjoerg * dialout event in case IPv6 has been 80588723Sjoerg * administratively disabled on that interface. 80688723Sjoerg */ 80788723Sjoerg if (dst->sa_family == AF_INET6 && 80888723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 80988723Sjoerg goto drop; 81088723Sjoerg#endif 81188723Sjoerg /* 81225944Sjoerg * Interface is not yet running, but auto-dial. Need 81325944Sjoerg * to start LCP for it. 81425944Sjoerg */ 815148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 81625944Sjoerg lcp.Open(sp); 81725944Sjoerg } 81825944Sjoerg 8194910Swollman#ifdef INET 82012436Speter if (dst->sa_family == AF_INET) { 82140008Sjoerg /* XXX Check mbuf length here? */ 82212436Speter struct ip *ip = mtod (m, struct ip*); 82312436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8244910Swollman 82542104Sphk /* 82642104Sphk * When using dynamic local IP address assignment by using 82742104Sphk * 0.0.0.0 as a local address, the first TCP session will 82842104Sphk * not connect because the local TCP checksum is computed 82942104Sphk * using 0.0.0.0 which will later become our real IP address 83042104Sphk * so the TCP checksum computed at the remote end will 83142104Sphk * become invalid. So we 83242104Sphk * - don't let packets with src ip addr 0 thru 83342104Sphk * - we flag TCP packets with src ip 0 as an error 83470199Sjhay */ 83542104Sphk 83642104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 83742104Sphk { 83842104Sphk m_freem(m); 839138745Srik SPPP_UNLOCK(sp); 84042104Sphk if(ip->ip_p == IPPROTO_TCP) 84142104Sphk return(EADDRNOTAVAIL); 84242104Sphk else 84342104Sphk return(0); 84442104Sphk } 84570199Sjhay 84642104Sphk /* 84742104Sphk * Put low delay, telnet, rlogin and ftp control packets 848130549Smlaier * in front of the queue or let ALTQ take care. 84942104Sphk */ 850130549Smlaier if (ALTQ_IS_ENABLED(&ifp->if_snd)) 85141686Sphk ; 852130549Smlaier else if (_IF_QFULL(&sp->pp_fastq)) 853130549Smlaier ; 85441686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 85512436Speter ifq = &sp->pp_fastq; 85641686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 85741686Sphk ; 85841686Sphk else if (ip->ip_p != IPPROTO_TCP) 85941686Sphk ; 86041686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 86141686Sphk ifq = &sp->pp_fastq; 86241686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 86341686Sphk ifq = &sp->pp_fastq; 86488534Sjoerg 86588534Sjoerg /* 86688534Sjoerg * Do IP Header compression 86788534Sjoerg */ 868139365Srik if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR && 869138745Srik (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP) 87088599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 87188534Sjoerg sp->ipcp.compress_cid)) { 87288534Sjoerg case TYPE_COMPRESSED_TCP: 87388534Sjoerg ipproto = PPP_VJ_COMP; 87488534Sjoerg break; 87588534Sjoerg case TYPE_UNCOMPRESSED_TCP: 87688534Sjoerg ipproto = PPP_VJ_UCOMP; 87788534Sjoerg break; 87888534Sjoerg case TYPE_IP: 87988534Sjoerg ipproto = PPP_IP; 88088534Sjoerg break; 88188534Sjoerg default: 88288534Sjoerg m_freem(m); 883138745Srik SPPP_UNLOCK(sp); 88488534Sjoerg return (EINVAL); 88588534Sjoerg } 8864910Swollman } 8874910Swollman#endif 8884910Swollman 88978064Sume#ifdef INET6 89078064Sume if (dst->sa_family == AF_INET6) { 89178064Sume /* XXX do something tricky here? */ 89278064Sume } 89378064Sume#endif 89478064Sume 895139365Srik if (sp->pp_mode == PP_FR) { 896139365Srik /* Add frame relay header. */ 897139365Srik m = sppp_fr_header (sp, m, dst->sa_family); 898139365Srik if (! m) 899139365Srik goto nobufs; 900139365Srik goto out; 901139365Srik } 902139365Srik 9034910Swollman /* 9044910Swollman * Prepend general data packet PPP header. For now, IP only. 9054910Swollman */ 906243882Sglebius M_PREPEND (m, PPP_HEADER_LEN, M_NOWAIT); 9074910Swollman if (! m) { 908139365Sriknobufs: if (debug) 90940008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 91040008Sjoerg SPP_ARGS(ifp)); 911271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 912138745Srik SPPP_UNLOCK(sp); 9134910Swollman return (ENOBUFS); 9144910Swollman } 91540008Sjoerg /* 91640008Sjoerg * May want to check size of packet 91740008Sjoerg * (albeit due to the implementation it's always enough) 91840008Sjoerg */ 9194910Swollman h = mtod (m, struct ppp_header*); 92045152Sphk if (sp->pp_mode == IFF_CISCO) { 92128088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9224910Swollman h->control = 0; 9234910Swollman } else { 9244910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9254910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9264910Swollman } 9274910Swollman 9284910Swollman switch (dst->sa_family) { 9294910Swollman#ifdef INET 9304910Swollman case AF_INET: /* Internet Protocol */ 93145152Sphk if (sp->pp_mode == IFF_CISCO) 93211189Sjkh h->protocol = htons (ETHERTYPE_IP); 93311189Sjkh else { 93425955Sjoerg /* 93525955Sjoerg * Don't choke with an ENETDOWN early. It's 93625955Sjoerg * possible that we just started dialing out, 93725955Sjoerg * so don't drop the packet immediately. If 93825955Sjoerg * we notice that we run out of buffer space 93925955Sjoerg * below, we will however remember that we are 94025955Sjoerg * not ready to carry IP packets, and return 94125955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 94225955Sjoerg */ 94388534Sjoerg h->protocol = htons(ipproto); 94425955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 94525955Sjoerg rv = ENETDOWN; 94611189Sjkh } 9474910Swollman break; 9484910Swollman#endif 94954263Sshin#ifdef INET6 95054263Sshin case AF_INET6: /* Internet Protocol */ 95154263Sshin if (sp->pp_mode == IFF_CISCO) 95254263Sshin h->protocol = htons (ETHERTYPE_IPV6); 95354263Sshin else { 95478064Sume /* 95578064Sume * Don't choke with an ENETDOWN early. It's 95678064Sume * possible that we just started dialing out, 95778064Sume * so don't drop the packet immediately. If 95878064Sume * we notice that we run out of buffer space 95978064Sume * below, we will however remember that we are 96078064Sume * not ready to carry IP packets, and return 96178064Sume * ENETDOWN, as opposed to ENOBUFS. 96278064Sume */ 96378064Sume h->protocol = htons(PPP_IPV6); 96478064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 96578064Sume rv = ENETDOWN; 96654263Sshin } 96754263Sshin break; 96854263Sshin#endif 9694910Swollman default: 9704910Swollman m_freem (m); 971271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 972138745Srik SPPP_UNLOCK(sp); 9734910Swollman return (EAFNOSUPPORT); 9744910Swollman } 9754910Swollman 9764910Swollman /* 9774910Swollman * Queue message on interface, and start output if interface 97888577Sjoerg * not yet active. 9794910Swollman */ 980139365Srikout: 981130549Smlaier if (ifq != NULL) 982130549Smlaier error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 983130549Smlaier else 984130549Smlaier IFQ_HANDOFF_ADJ(ifp, m, 3, error); 985130549Smlaier if (error) { 986271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 987138745Srik SPPP_UNLOCK(sp); 98825955Sjoerg return (rv? rv: ENOBUFS); 9894910Swollman } 990138745Srik SPPP_UNLOCK(sp); 99188577Sjoerg /* 99288577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 99388577Sjoerg * here since sppp_output() is only called on behalf of 99488577Sjoerg * network-layer traffic; control-layer traffic is handled 99588577Sjoerg * by sppp_cp_send(). 99688577Sjoerg */ 997150349Sandre sp->pp_last_sent = time_uptime; 9984910Swollman return (0); 9994910Swollman} 10004910Swollman 100125706Sjoergvoid 100225706Sjoergsppp_attach(struct ifnet *ifp) 10034910Swollman{ 1004147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10054910Swollman 1006138745Srik /* Initialize mtx lock */ 1007138745Srik mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); 1008138745Srik 10094910Swollman /* Initialize keepalive handler. */ 1010283291Sjkim callout_init(&sp->keepalive_callout, 1); 1011138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 1012138745Srik (void *)sp); 10134910Swollman 1014147256Sbrooks ifp->if_mtu = PP_MTU; 1015147256Sbrooks ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1016147256Sbrooks ifp->if_output = sppp_output; 101742104Sphk#if 0 101842064Sphk sp->pp_flags = PP_KEEPALIVE; 101942104Sphk#endif 1020147256Sbrooks ifp->if_snd.ifq_maxlen = 32; 102170199Sjhay sp->pp_fastq.ifq_maxlen = 32; 102270199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10234910Swollman sp->pp_loopcnt = 0; 10244910Swollman sp->pp_alivecnt = 0; 102578064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 102678064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 102725944Sjoerg sp->pp_phase = PHASE_DEAD; 1028138745Srik sp->pp_up = sppp_pp_up; 1029138745Srik sp->pp_down = sppp_pp_down; 103088716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 103193818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 103288716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 103393818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 1034150349Sandre sp->pp_last_recv = sp->pp_last_sent = time_uptime; 103588723Sjoerg sp->confflags = 0; 103688723Sjoerg#ifdef INET 103788723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 103888723Sjoerg#endif 103988723Sjoerg#ifdef INET6 104088723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 104188723Sjoerg#endif 1042283291Sjkim callout_init(&sp->ifstart_callout, 1); 1043138745Srik sp->if_start = ifp->if_start; 1044138745Srik ifp->if_start = sppp_ifstart; 1045118072Sgj sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 104688599Sjoerg sl_compress_init(sp->pp_comp, -1); 104725944Sjoerg sppp_lcp_init(sp); 104825944Sjoerg sppp_ipcp_init(sp); 104978064Sume sppp_ipv6cp_init(sp); 105030300Sjoerg sppp_pap_init(sp); 105130300Sjoerg sppp_chap_init(sp); 10524910Swollman} 10534910Swollman 105430300Sjoergvoid 105525706Sjoergsppp_detach(struct ifnet *ifp) 10564910Swollman{ 1057147256Sbrooks struct sppp *sp = IFP2SP(ifp); 105825944Sjoerg int i; 10594910Swollman 1060138745Srik KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized")); 10614910Swollman 10624910Swollman /* Stop keepalive handler. */ 1063352481Shselasky callout_drain(&sp->keepalive_callout); 106425944Sjoerg 1065138745Srik for (i = 0; i < IDX_COUNT; i++) { 1066352481Shselasky callout_drain(&sp->ch[i]); 1067138745Srik } 1068352481Shselasky callout_drain(&sp->pap_my_to_ch); 1069352481Shselasky 107069152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 107169152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 1072138745Srik mtx_destroy(&sp->mtx); 10734910Swollman} 10744910Swollman 10754910Swollman/* 10764910Swollman * Flush the interface output queue. 10774910Swollman */ 1078138745Srikstatic void 1079138745Sriksppp_flush_unlocked(struct ifnet *ifp) 10804910Swollman{ 1081147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10824910Swollman 1083147256Sbrooks sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd); 108425944Sjoerg sppp_qflush (&sp->pp_fastq); 108526018Sjoerg sppp_qflush (&sp->pp_cpq); 10864910Swollman} 10874910Swollman 1088138745Srikvoid 1089138745Sriksppp_flush(struct ifnet *ifp) 1090138745Srik{ 1091147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1092138745Srik 1093138745Srik SPPP_LOCK(sp); 1094138745Srik sppp_flush_unlocked (ifp); 1095138745Srik SPPP_UNLOCK(sp); 1096138745Srik} 1097138745Srik 10984910Swollman/* 109911189Sjkh * Check if the output queue is empty. 110011189Sjkh */ 110112820Sphkint 110225706Sjoergsppp_isempty(struct ifnet *ifp) 110311189Sjkh{ 1104147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1105241686Sandre int empty; 110611189Sjkh 1107138745Srik SPPP_LOCK(sp); 110826018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1109147256Sbrooks !SP2IFP(sp)->if_snd.ifq_head; 1110138745Srik SPPP_UNLOCK(sp); 111111189Sjkh return (empty); 111211189Sjkh} 111311189Sjkh 111411189Sjkh/* 11154910Swollman * Get next packet to send. 11164910Swollman */ 111725706Sjoergstruct mbuf * 111825706Sjoergsppp_dequeue(struct ifnet *ifp) 11194910Swollman{ 1120147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11214910Swollman struct mbuf *m; 11224910Swollman 1123138745Srik SPPP_LOCK(sp); 112426018Sjoerg /* 112530300Sjoerg * Process only the control protocol queue until we have at 112630300Sjoerg * least one NCP open. 112726018Sjoerg * 112826018Sjoerg * Do always serve all three queues in Cisco mode. 112926018Sjoerg */ 113026018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 113126018Sjoerg if (m == NULL && 1132139365Srik (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO || 1133139365Srik sp->pp_mode == PP_FR)) { 113426018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 113526018Sjoerg if (m == NULL) 1136147256Sbrooks IF_DEQUEUE (&SP2IFP(sp)->if_snd, m); 113726018Sjoerg } 1138138745Srik SPPP_UNLOCK(sp); 113926018Sjoerg return m; 11404910Swollman} 11414910Swollman 11424910Swollman/* 114330300Sjoerg * Pick the next packet, do not remove it from the queue. 114430300Sjoerg */ 114530300Sjoergstruct mbuf * 114630300Sjoergsppp_pick(struct ifnet *ifp) 114730300Sjoerg{ 1148147256Sbrooks struct sppp *sp = IFP2SP(ifp); 114930300Sjoerg struct mbuf *m; 115030300Sjoerg 1151138745Srik SPPP_LOCK(sp); 115230300Sjoerg 115330300Sjoerg m = sp->pp_cpq.ifq_head; 115430300Sjoerg if (m == NULL && 1155138745Srik (sp->pp_phase == PHASE_NETWORK || 1156139365Srik sp->pp_mode == IFF_CISCO || 1157139365Srik sp->pp_mode == PP_FR)) 115830300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 1159147256Sbrooks m = SP2IFP(sp)->if_snd.ifq_head; 1160138745Srik SPPP_UNLOCK(sp); 116130300Sjoerg return (m); 116230300Sjoerg} 116330300Sjoerg 116430300Sjoerg/* 116525944Sjoerg * Process an ioctl request. Called on low priority level. 11664910Swollman */ 116725944Sjoergint 116842104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 11694910Swollman{ 117025944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 1171147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1172241686Sandre int rv, going_up, going_down, newmode; 11734910Swollman 1174138745Srik SPPP_LOCK(sp); 117530300Sjoerg rv = 0; 117625944Sjoerg switch (cmd) { 117725944Sjoerg case SIOCAIFADDR: 117825944Sjoerg break; 11794910Swollman 118025944Sjoerg case SIOCSIFADDR: 118188503Sjoerg /* set the interface "up" when assigning an IP address */ 118288503Sjoerg ifp->if_flags |= IFF_UP; 1183102412Scharnier /* FALLTHROUGH */ 118411189Sjkh 118525944Sjoerg case SIOCSIFFLAGS: 118625944Sjoerg going_up = ifp->if_flags & IFF_UP && 1187148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 118825944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1189148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 119045152Sphk 119145152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 119245152Sphk if (!newmode) 119345152Sphk newmode = ifp->if_flags & IFF_AUTO; 119445152Sphk if (!newmode) 119545152Sphk newmode = ifp->if_flags & IFF_CISCO; 119645152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 119745152Sphk ifp->if_flags |= newmode; 119845152Sphk 1199139365Srik if (!newmode) 1200139365Srik newmode = sp->pp_flags & PP_FR; 1201139365Srik 120245152Sphk if (newmode != sp->pp_mode) { 120345152Sphk going_down = 1; 120445152Sphk if (!going_up) 1205148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12064910Swollman } 12074910Swollman 120845152Sphk if (going_down) { 1209139365Srik if (sp->pp_mode != IFF_CISCO && 1210139365Srik sp->pp_mode != PP_FR) 121145152Sphk lcp.Close(sp); 121245152Sphk else if (sp->pp_tlf) 121345152Sphk (sp->pp_tlf)(sp); 1214138745Srik sppp_flush_unlocked(ifp); 1215148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 121645152Sphk sp->pp_mode = newmode; 121726018Sjoerg } 12184910Swollman 121945152Sphk if (going_up) { 1220139365Srik if (sp->pp_mode != IFF_CISCO && 1221139365Srik sp->pp_mode != PP_FR) 122245152Sphk lcp.Close(sp); 122345152Sphk sp->pp_mode = newmode; 122445152Sphk if (sp->pp_mode == 0) { 1225148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 122645152Sphk lcp.Open(sp); 122745152Sphk } 1228139365Srik if ((sp->pp_mode == IFF_CISCO) || 1229139365Srik (sp->pp_mode == PP_FR)) { 123045152Sphk if (sp->pp_tls) 123145152Sphk (sp->pp_tls)(sp); 1232148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 123345152Sphk } 123445152Sphk } 123545152Sphk 12364910Swollman break; 123711189Sjkh 123825944Sjoerg#ifdef SIOCSIFMTU 123925944Sjoerg#ifndef ifr_mtu 124025944Sjoerg#define ifr_mtu ifr_metric 124125944Sjoerg#endif 124225944Sjoerg case SIOCSIFMTU: 124325944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 124425944Sjoerg return (EINVAL); 124525944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12464910Swollman break; 124725944Sjoerg#endif 124825944Sjoerg#ifdef SLIOCSETMTU 124925944Sjoerg case SLIOCSETMTU: 125025944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 125125944Sjoerg return (EINVAL); 125225944Sjoerg ifp->if_mtu = *(short*)data; 12534910Swollman break; 125425944Sjoerg#endif 125525944Sjoerg#ifdef SIOCGIFMTU 125625944Sjoerg case SIOCGIFMTU: 125725944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 125811189Sjkh break; 125925944Sjoerg#endif 126025944Sjoerg#ifdef SLIOCGETMTU 126125944Sjoerg case SLIOCGETMTU: 126225944Sjoerg *(short*)data = ifp->if_mtu; 12634910Swollman break; 126425944Sjoerg#endif 126525944Sjoerg case SIOCADDMULTI: 126625944Sjoerg case SIOCDELMULTI: 12674910Swollman break; 126811189Sjkh 126930300Sjoerg case SIOCGIFGENERIC: 127030300Sjoerg case SIOCSIFGENERIC: 127130300Sjoerg rv = sppp_params(sp, cmd, data); 127230300Sjoerg break; 127330300Sjoerg 127425944Sjoerg default: 127530300Sjoerg rv = ENOTTY; 12764910Swollman } 1277138745Srik SPPP_UNLOCK(sp); 127830300Sjoerg return rv; 12794910Swollman} 12804910Swollman 128170199Sjhay/* 128225944Sjoerg * Cisco framing implementation. 128325944Sjoerg */ 128425944Sjoerg 12854910Swollman/* 12864910Swollman * Handle incoming Cisco keepalive protocol packets. 12874910Swollman */ 128830300Sjoergstatic void 128925706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 12904910Swollman{ 129125944Sjoerg STDDCL; 12924910Swollman struct cisco_packet *h; 129330300Sjoerg u_long me, mymask; 12944910Swollman 129527929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 129625706Sjoerg if (debug) 129725706Sjoerg log(LOG_DEBUG, 129840008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 129940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13004910Swollman return; 13014910Swollman } 13024910Swollman h = mtod (m, struct cisco_packet*); 130325706Sjoerg if (debug) 130425706Sjoerg log(LOG_DEBUG, 130540008Sjoerg SPP_FMT "cisco input: %d bytes " 130625706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 130740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 130840008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 130940008Sjoerg (u_int)h->time0, (u_int)h->time1); 13104910Swollman switch (ntohl (h->type)) { 13114910Swollman default: 131225706Sjoerg if (debug) 131369211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 131440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 13154910Swollman break; 13164910Swollman case CISCO_ADDR_REPLY: 13174910Swollman /* Reply on address request, ignore */ 13184910Swollman break; 13194910Swollman case CISCO_KEEPALIVE_REQ: 13204910Swollman sp->pp_alivecnt = 0; 132178064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 132278064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13234910Swollman /* Local and remote sequence numbers are equal. 13244910Swollman * Probably, the line is in loopback mode. */ 132511189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 132640008Sjoerg printf (SPP_FMT "loopback\n", 132740008Sjoerg SPP_ARGS(ifp)); 132811189Sjkh sp->pp_loopcnt = 0; 132911189Sjkh if (ifp->if_flags & IFF_UP) { 133011189Sjkh if_down (ifp); 133126018Sjoerg sppp_qflush (&sp->pp_cpq); 133211189Sjkh } 133311189Sjkh } 13344910Swollman ++sp->pp_loopcnt; 13354910Swollman 13364910Swollman /* Generate new local sequence number */ 133778064Sume sp->pp_seq[IDX_LCP] = random(); 133811189Sjkh break; 133911189Sjkh } 134030300Sjoerg sp->pp_loopcnt = 0; 134111189Sjkh if (! (ifp->if_flags & IFF_UP) && 1342148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 134330300Sjoerg if_up(ifp); 134440008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 134511189Sjkh } 13464910Swollman break; 13474910Swollman case CISCO_ADDR_REQ: 134830300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 134930300Sjoerg if (me != 0L) 135030300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13514910Swollman break; 13524910Swollman } 13534910Swollman} 13544910Swollman 13554910Swollman/* 135625944Sjoerg * Send Cisco keepalive packet. 13574910Swollman */ 135812820Sphkstatic void 135925944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 136025944Sjoerg{ 136125944Sjoerg STDDCL; 136225944Sjoerg struct ppp_header *h; 136325944Sjoerg struct cisco_packet *ch; 136425944Sjoerg struct mbuf *m; 136535029Sphk struct timeval tv; 136625944Sjoerg 136736119Sphk getmicrouptime(&tv); 136870199Sjhay 1369243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 137025944Sjoerg if (! m) 137125944Sjoerg return; 137225944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 137325944Sjoerg m->m_pkthdr.rcvif = 0; 137425944Sjoerg 137525944Sjoerg h = mtod (m, struct ppp_header*); 137625944Sjoerg h->address = CISCO_MULTICAST; 137725944Sjoerg h->control = 0; 137825944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 137925944Sjoerg 138025944Sjoerg ch = (struct cisco_packet*) (h + 1); 138125944Sjoerg ch->type = htonl (type); 138225944Sjoerg ch->par1 = htonl (par1); 138325944Sjoerg ch->par2 = htonl (par2); 138425944Sjoerg ch->rel = -1; 138540008Sjoerg 138635029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 138735029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 138825944Sjoerg 138925944Sjoerg if (debug) 139025944Sjoerg log(LOG_DEBUG, 139140008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 139240008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 139340008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 139425944Sjoerg 139569152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 1396271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 139725944Sjoerg} 139825944Sjoerg 139970199Sjhay/* 140025944Sjoerg * PPP protocol implementation. 140125944Sjoerg */ 140225944Sjoerg 140325944Sjoerg/* 140425944Sjoerg * Send PPP control protocol packet. 140525944Sjoerg */ 140625944Sjoergstatic void 140725706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 140825706Sjoerg u_char ident, u_short len, void *data) 14094910Swollman{ 141025944Sjoerg STDDCL; 14114910Swollman struct ppp_header *h; 14124910Swollman struct lcp_header *lh; 14134910Swollman struct mbuf *m; 14144910Swollman 14154910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14164910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1417243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 14184910Swollman if (! m) 14194910Swollman return; 14204910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14214910Swollman m->m_pkthdr.rcvif = 0; 14224910Swollman 14234910Swollman h = mtod (m, struct ppp_header*); 14244910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14254910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14264910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14274910Swollman 14284910Swollman lh = (struct lcp_header*) (h + 1); 14294910Swollman lh->type = type; 14304910Swollman lh->ident = ident; 14314910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14324910Swollman if (len) 14334910Swollman bcopy (data, lh+1, len); 14344910Swollman 143525706Sjoerg if (debug) { 143640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 143740008Sjoerg SPP_ARGS(ifp), 143825944Sjoerg sppp_proto_name(proto), 143925944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 144025944Sjoerg ntohs (lh->len)); 144144145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 144269211Sphk log(-1, ">\n"); 14434910Swollman } 144469152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 1445271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 14464910Swollman} 14474910Swollman 14484910Swollman/* 144925944Sjoerg * Handle incoming PPP control protocol packets. 14504910Swollman */ 145112820Sphkstatic void 145225944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14534910Swollman{ 145425944Sjoerg STDDCL; 145525944Sjoerg struct lcp_header *h; 145625944Sjoerg int len = m->m_pkthdr.len; 145725944Sjoerg int rv; 145825944Sjoerg u_char *p; 14594910Swollman 146025944Sjoerg if (len < 4) { 146125944Sjoerg if (debug) 146225944Sjoerg log(LOG_DEBUG, 146340008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 146440008Sjoerg SPP_ARGS(ifp), cp->name, len); 14654910Swollman return; 146625944Sjoerg } 146725944Sjoerg h = mtod (m, struct lcp_header*); 146825944Sjoerg if (debug) { 146925944Sjoerg log(LOG_DEBUG, 147040008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 147140008Sjoerg SPP_ARGS(ifp), cp->name, 147225944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 147325944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 147444145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 147569211Sphk log(-1, ">\n"); 147625944Sjoerg } 147725944Sjoerg if (len > ntohs (h->len)) 147825944Sjoerg len = ntohs (h->len); 147930300Sjoerg p = (u_char *)(h + 1); 148025944Sjoerg switch (h->type) { 148125944Sjoerg case CONF_REQ: 148225944Sjoerg if (len < 4) { 148325944Sjoerg if (debug) 148469211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 148540008Sjoerg SPP_ARGS(ifp), cp->name, 148625944Sjoerg len); 1487271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 148825944Sjoerg break; 148925944Sjoerg } 149030300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 149130300Sjoerg switch (sp->state[cp->protoidx]) { 149230300Sjoerg case STATE_CLOSING: 149330300Sjoerg case STATE_STOPPING: 149430300Sjoerg return; 149530300Sjoerg case STATE_CLOSED: 149630300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 149730300Sjoerg 0, 0); 149830300Sjoerg return; 149930300Sjoerg } 150025944Sjoerg rv = (cp->RCR)(sp, h, len); 150125944Sjoerg switch (sp->state[cp->protoidx]) { 150225944Sjoerg case STATE_OPENED: 150325944Sjoerg (cp->tld)(sp); 150425944Sjoerg (cp->scr)(sp); 1505102412Scharnier /* FALLTHROUGH */ 150625944Sjoerg case STATE_ACK_SENT: 150725944Sjoerg case STATE_REQ_SENT: 150870199Sjhay /* 150970199Sjhay * sppp_cp_change_state() have the side effect of 151070199Sjhay * restarting the timeouts. We want to avoid that 151170199Sjhay * if the state don't change, otherwise we won't 151270199Sjhay * ever timeout and resend a configuration request 151370199Sjhay * that got lost. 151470199Sjhay */ 151570199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 151670199Sjhay STATE_REQ_SENT)) 151770199Sjhay break; 151825944Sjoerg sppp_cp_change_state(cp, sp, rv? 151925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 152025944Sjoerg break; 152125944Sjoerg case STATE_STOPPED: 152225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 152325944Sjoerg (cp->scr)(sp); 152425944Sjoerg sppp_cp_change_state(cp, sp, rv? 152525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 152625944Sjoerg break; 152725944Sjoerg case STATE_ACK_RCVD: 152825944Sjoerg if (rv) { 152925944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 153025944Sjoerg if (debug) 153140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 153240008Sjoerg SPP_ARGS(ifp), 153326077Sjoerg cp->name); 153425944Sjoerg (cp->tlu)(sp); 153525944Sjoerg } else 153625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 153725944Sjoerg break; 153825944Sjoerg default: 153940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 154040008Sjoerg SPP_ARGS(ifp), cp->name, 154125944Sjoerg sppp_cp_type_name(h->type), 154225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1543271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 154425944Sjoerg } 154525944Sjoerg break; 154625944Sjoerg case CONF_ACK: 154725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 154825944Sjoerg if (debug) 154969211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 155040008Sjoerg SPP_ARGS(ifp), cp->name, 155125944Sjoerg h->ident, sp->confid[cp->protoidx]); 1552271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 155325944Sjoerg break; 155425944Sjoerg } 155525944Sjoerg switch (sp->state[cp->protoidx]) { 155625944Sjoerg case STATE_CLOSED: 155725944Sjoerg case STATE_STOPPED: 155825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 155925944Sjoerg break; 156025944Sjoerg case STATE_CLOSING: 156125944Sjoerg case STATE_STOPPING: 156225944Sjoerg break; 156325944Sjoerg case STATE_REQ_SENT: 156425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 156525944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 156625944Sjoerg break; 156725944Sjoerg case STATE_OPENED: 156825944Sjoerg (cp->tld)(sp); 1569102412Scharnier /* FALLTHROUGH */ 157025944Sjoerg case STATE_ACK_RCVD: 157125944Sjoerg (cp->scr)(sp); 157225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 157325944Sjoerg break; 157425944Sjoerg case STATE_ACK_SENT: 157525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 157625944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 157725944Sjoerg if (debug) 157840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 157940008Sjoerg SPP_ARGS(ifp), cp->name); 158025944Sjoerg (cp->tlu)(sp); 158125944Sjoerg break; 158225944Sjoerg default: 158340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 158440008Sjoerg SPP_ARGS(ifp), cp->name, 158525944Sjoerg sppp_cp_type_name(h->type), 158625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1587271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 158825944Sjoerg } 158925944Sjoerg break; 159025944Sjoerg case CONF_NAK: 159125944Sjoerg case CONF_REJ: 159225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 159325944Sjoerg if (debug) 159469211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 159540008Sjoerg SPP_ARGS(ifp), cp->name, 159625944Sjoerg h->ident, sp->confid[cp->protoidx]); 1597271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 159825944Sjoerg break; 159925944Sjoerg } 160025944Sjoerg if (h->type == CONF_NAK) 160125944Sjoerg (cp->RCN_nak)(sp, h, len); 160225944Sjoerg else /* CONF_REJ */ 160325944Sjoerg (cp->RCN_rej)(sp, h, len); 16044910Swollman 160525944Sjoerg switch (sp->state[cp->protoidx]) { 160625944Sjoerg case STATE_CLOSED: 160725944Sjoerg case STATE_STOPPED: 160825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 160925944Sjoerg break; 161025944Sjoerg case STATE_REQ_SENT: 161125944Sjoerg case STATE_ACK_SENT: 161225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 161370199Sjhay /* 161470199Sjhay * Slow things down a bit if we think we might be 161570199Sjhay * in loopback. Depend on the timeout to send the 161670199Sjhay * next configuration request. 161770199Sjhay */ 161870199Sjhay if (sp->pp_loopcnt) 161970199Sjhay break; 162025944Sjoerg (cp->scr)(sp); 162125944Sjoerg break; 162225944Sjoerg case STATE_OPENED: 162325944Sjoerg (cp->tld)(sp); 1624102412Scharnier /* FALLTHROUGH */ 162525944Sjoerg case STATE_ACK_RCVD: 162652633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 162725944Sjoerg (cp->scr)(sp); 162825944Sjoerg break; 162925944Sjoerg case STATE_CLOSING: 163025944Sjoerg case STATE_STOPPING: 163125944Sjoerg break; 163225944Sjoerg default: 163340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163440008Sjoerg SPP_ARGS(ifp), cp->name, 163525944Sjoerg sppp_cp_type_name(h->type), 163625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1637271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 163825944Sjoerg } 163925944Sjoerg break; 16404910Swollman 164125944Sjoerg case TERM_REQ: 164225944Sjoerg switch (sp->state[cp->protoidx]) { 164325944Sjoerg case STATE_ACK_RCVD: 164425944Sjoerg case STATE_ACK_SENT: 164525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1646102412Scharnier /* FALLTHROUGH */ 164725944Sjoerg case STATE_CLOSED: 164825944Sjoerg case STATE_STOPPED: 164925944Sjoerg case STATE_CLOSING: 165025944Sjoerg case STATE_STOPPING: 165125944Sjoerg case STATE_REQ_SENT: 165225944Sjoerg sta: 165325944Sjoerg /* Send Terminate-Ack packet. */ 165425944Sjoerg if (debug) 165540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 165640008Sjoerg SPP_ARGS(ifp), cp->name); 165725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 165825944Sjoerg break; 165925944Sjoerg case STATE_OPENED: 166025944Sjoerg (cp->tld)(sp); 166125944Sjoerg sp->rst_counter[cp->protoidx] = 0; 166225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 166325944Sjoerg goto sta; 166425944Sjoerg break; 166525944Sjoerg default: 166640008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 166740008Sjoerg SPP_ARGS(ifp), cp->name, 166825944Sjoerg sppp_cp_type_name(h->type), 166925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1670271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 167125944Sjoerg } 167225944Sjoerg break; 167325944Sjoerg case TERM_ACK: 167425944Sjoerg switch (sp->state[cp->protoidx]) { 167525944Sjoerg case STATE_CLOSED: 167625944Sjoerg case STATE_STOPPED: 167725944Sjoerg case STATE_REQ_SENT: 167825944Sjoerg case STATE_ACK_SENT: 167925944Sjoerg break; 168025944Sjoerg case STATE_CLOSING: 168141881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 168225944Sjoerg (cp->tlf)(sp); 168325944Sjoerg break; 168425944Sjoerg case STATE_STOPPING: 168541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 168625944Sjoerg (cp->tlf)(sp); 168725944Sjoerg break; 168825944Sjoerg case STATE_ACK_RCVD: 168925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 169025944Sjoerg break; 169125944Sjoerg case STATE_OPENED: 169225944Sjoerg (cp->tld)(sp); 169325944Sjoerg (cp->scr)(sp); 169425944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 169525944Sjoerg break; 169625944Sjoerg default: 169740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169840008Sjoerg SPP_ARGS(ifp), cp->name, 169925944Sjoerg sppp_cp_type_name(h->type), 170025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1701271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 170225944Sjoerg } 170325944Sjoerg break; 170425944Sjoerg case CODE_REJ: 170525944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 170630300Sjoerg log(LOG_INFO, 170740008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 170830300Sjoerg "danger will robinson\n", 170940008Sjoerg SPP_ARGS(ifp), cp->name, 171030300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 171125944Sjoerg switch (sp->state[cp->protoidx]) { 171225944Sjoerg case STATE_CLOSED: 171325944Sjoerg case STATE_STOPPED: 171425944Sjoerg case STATE_REQ_SENT: 171525944Sjoerg case STATE_ACK_SENT: 171625944Sjoerg case STATE_CLOSING: 171725944Sjoerg case STATE_STOPPING: 171825944Sjoerg case STATE_OPENED: 171925944Sjoerg break; 172025944Sjoerg case STATE_ACK_RCVD: 172125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 172225944Sjoerg break; 172325944Sjoerg default: 172440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 172540008Sjoerg SPP_ARGS(ifp), cp->name, 172625944Sjoerg sppp_cp_type_name(h->type), 172725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 1728271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 172925944Sjoerg } 173025944Sjoerg break; 173180715Sume case PROTO_REJ: 173280715Sume { 173380715Sume int catastrophic; 173480715Sume const struct cp *upper; 173580715Sume int i; 173680715Sume u_int16_t proto; 173780715Sume 173880715Sume catastrophic = 0; 173980715Sume upper = NULL; 174080715Sume proto = ntohs(*((u_int16_t *)p)); 174180715Sume for (i = 0; i < IDX_COUNT; i++) { 174280715Sume if (cps[i]->proto == proto) { 174380715Sume upper = cps[i]; 174480715Sume break; 174580715Sume } 174680715Sume } 174780715Sume if (upper == NULL) 174880715Sume catastrophic++; 174980715Sume 175088508Sjoerg if (catastrophic || debug) 175188508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 175288508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 175388508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 175488508Sjoerg sppp_cp_type_name(h->type), proto, 175588508Sjoerg upper ? upper->name : "unknown", 175688508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 175780715Sume 175880715Sume /* 175980715Sume * if we got RXJ+ against conf-req, the peer does not implement 176080715Sume * this particular protocol type. terminate the protocol. 176180715Sume */ 176280715Sume if (upper && !catastrophic) { 176380715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 176480715Sume upper->Close(sp); 176580715Sume break; 176680715Sume } 176780715Sume } 176880715Sume 176980715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 177080715Sume switch (sp->state[cp->protoidx]) { 177180715Sume case STATE_CLOSED: 177280715Sume case STATE_STOPPED: 177380715Sume case STATE_REQ_SENT: 177480715Sume case STATE_ACK_SENT: 177580715Sume case STATE_CLOSING: 177680715Sume case STATE_STOPPING: 177780715Sume case STATE_OPENED: 177880715Sume break; 177980715Sume case STATE_ACK_RCVD: 178080715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 178180715Sume break; 178280715Sume default: 178380715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 178480715Sume SPP_ARGS(ifp), cp->name, 178580715Sume sppp_cp_type_name(h->type), 178680715Sume sppp_state_name(sp->state[cp->protoidx])); 1787271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 178880715Sume } 178980715Sume break; 179080715Sume } 179125944Sjoerg case DISC_REQ: 179225944Sjoerg if (cp->proto != PPP_LCP) 179325944Sjoerg goto illegal; 179425944Sjoerg /* Discard the packet. */ 179525944Sjoerg break; 179625944Sjoerg case ECHO_REQ: 179725944Sjoerg if (cp->proto != PPP_LCP) 179825944Sjoerg goto illegal; 179925944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 180025944Sjoerg if (debug) 180169211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 180240008Sjoerg SPP_ARGS(ifp)); 1803271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 180425944Sjoerg break; 180525944Sjoerg } 180625944Sjoerg if (len < 8) { 180725944Sjoerg if (debug) 180869211Sphk log(-1, SPP_FMT "invalid lcp echo request " 180925944Sjoerg "packet length: %d bytes\n", 181040008Sjoerg SPP_ARGS(ifp), len); 181125944Sjoerg break; 181225944Sjoerg } 181344145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 181444145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 181525944Sjoerg /* Line loopback mode detected. */ 181640008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 181770199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 181825944Sjoerg if_down (ifp); 181926018Sjoerg sppp_qflush (&sp->pp_cpq); 18204910Swollman 182125944Sjoerg /* Shut down the PPP link. */ 182225944Sjoerg /* XXX */ 182325944Sjoerg lcp.Down(sp); 182425944Sjoerg lcp.Up(sp); 182525944Sjoerg break; 182625944Sjoerg } 182725944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 182825944Sjoerg if (debug) 182969211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 183040008Sjoerg SPP_ARGS(ifp)); 183125944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 183225944Sjoerg break; 183325944Sjoerg case ECHO_REPLY: 183425944Sjoerg if (cp->proto != PPP_LCP) 183525944Sjoerg goto illegal; 183625944Sjoerg if (h->ident != sp->lcp.echoid) { 1837271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 183825944Sjoerg break; 183925944Sjoerg } 184025944Sjoerg if (len < 8) { 184125944Sjoerg if (debug) 184269211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 184325944Sjoerg "packet length: %d bytes\n", 184440008Sjoerg SPP_ARGS(ifp), len); 184525944Sjoerg break; 184625944Sjoerg } 184725944Sjoerg if (debug) 184869211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 184940008Sjoerg SPP_ARGS(ifp)); 185044145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 185144145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 185225944Sjoerg sp->pp_alivecnt = 0; 185325944Sjoerg break; 185425944Sjoerg default: 185525944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 185625944Sjoerg illegal: 185725944Sjoerg if (debug) 185869211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 185940008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 186078064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 186178064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 1862271867Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 186325944Sjoerg } 18644910Swollman} 18654910Swollman 186625944Sjoerg 18674910Swollman/* 186825944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 186925944Sjoerg * Basically, the state transition handling in the automaton. 18704910Swollman */ 187125944Sjoergstatic void 187225944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18734910Swollman{ 187425944Sjoerg STDDCL; 18754910Swollman 187625944Sjoerg if (debug) 187740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 187840008Sjoerg SPP_ARGS(ifp), cp->name, 187925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 188025944Sjoerg 188125944Sjoerg switch (sp->state[cp->protoidx]) { 188225944Sjoerg case STATE_INITIAL: 188325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 188425944Sjoerg break; 188525944Sjoerg case STATE_STARTING: 188625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 188725944Sjoerg (cp->scr)(sp); 188825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 188925944Sjoerg break; 18904910Swollman default: 189140008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 189240008Sjoerg SPP_ARGS(ifp), cp->name, 189325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 189425944Sjoerg } 189525944Sjoerg} 18964910Swollman 189725944Sjoergstatic void 189825944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 189925944Sjoerg{ 190025944Sjoerg STDDCL; 190125944Sjoerg 190225944Sjoerg if (debug) 190340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 190440008Sjoerg SPP_ARGS(ifp), cp->name, 190525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190625944Sjoerg 190725944Sjoerg switch (sp->state[cp->protoidx]) { 190825944Sjoerg case STATE_CLOSED: 190925944Sjoerg case STATE_CLOSING: 191025944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19114910Swollman break; 191225944Sjoerg case STATE_STOPPED: 191341881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 191425944Sjoerg (cp->tls)(sp); 191541881Sphk break; 191625944Sjoerg case STATE_STOPPING: 191725944Sjoerg case STATE_REQ_SENT: 191825944Sjoerg case STATE_ACK_RCVD: 191925944Sjoerg case STATE_ACK_SENT: 192025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 192125944Sjoerg break; 192225944Sjoerg case STATE_OPENED: 192325944Sjoerg (cp->tld)(sp); 192425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 192525944Sjoerg break; 192625944Sjoerg default: 192740008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 192840008Sjoerg SPP_ARGS(ifp), cp->name, 192925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 193025944Sjoerg } 193125944Sjoerg} 19324910Swollman 193311189Sjkh 193425944Sjoergstatic void 193525944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 193625944Sjoerg{ 193725944Sjoerg STDDCL; 193825944Sjoerg 193925944Sjoerg if (debug) 194040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 194140008Sjoerg SPP_ARGS(ifp), cp->name, 194225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 194325944Sjoerg 194425944Sjoerg switch (sp->state[cp->protoidx]) { 194525944Sjoerg case STATE_INITIAL: 194641881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 194725944Sjoerg (cp->tls)(sp); 19484910Swollman break; 194925944Sjoerg case STATE_STARTING: 195025944Sjoerg break; 195125944Sjoerg case STATE_CLOSED: 195225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 195325944Sjoerg (cp->scr)(sp); 195425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 195525944Sjoerg break; 195625944Sjoerg case STATE_STOPPED: 195774703Sjoerg /* 195874703Sjoerg * Try escaping stopped state. This seems to bite 195974703Sjoerg * people occasionally, in particular for IPCP, 196074703Sjoerg * presumably following previous IPCP negotiation 196174703Sjoerg * aborts. Somehow, we must have missed a Down event 196274703Sjoerg * which would have caused a transition into starting 196374703Sjoerg * state, so as a bandaid we force the Down event now. 196474703Sjoerg * This effectively implements (something like the) 196574703Sjoerg * `restart' option mentioned in the state transition 196674703Sjoerg * table of RFC 1661. 196774703Sjoerg */ 196874703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 196974703Sjoerg (cp->tls)(sp); 197074703Sjoerg break; 197125944Sjoerg case STATE_STOPPING: 197225944Sjoerg case STATE_REQ_SENT: 197325944Sjoerg case STATE_ACK_RCVD: 197425944Sjoerg case STATE_ACK_SENT: 197525944Sjoerg case STATE_OPENED: 197625944Sjoerg break; 197725944Sjoerg case STATE_CLOSING: 197825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 197925944Sjoerg break; 198025944Sjoerg } 198125944Sjoerg} 19824910Swollman 198325944Sjoerg 198425944Sjoergstatic void 198525944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 198625944Sjoerg{ 198725944Sjoerg STDDCL; 198825944Sjoerg 198925944Sjoerg if (debug) 199040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 199140008Sjoerg SPP_ARGS(ifp), cp->name, 199225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 199325944Sjoerg 199425944Sjoerg switch (sp->state[cp->protoidx]) { 199525944Sjoerg case STATE_INITIAL: 199625944Sjoerg case STATE_CLOSED: 199725944Sjoerg case STATE_CLOSING: 19984910Swollman break; 199925944Sjoerg case STATE_STARTING: 200041881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 200125944Sjoerg (cp->tlf)(sp); 20024910Swollman break; 200325944Sjoerg case STATE_STOPPED: 200425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20054910Swollman break; 200625944Sjoerg case STATE_STOPPING: 200725944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20084910Swollman break; 200925944Sjoerg case STATE_OPENED: 201025944Sjoerg (cp->tld)(sp); 2011102412Scharnier /* FALLTHROUGH */ 201225944Sjoerg case STATE_REQ_SENT: 201325944Sjoerg case STATE_ACK_RCVD: 201425944Sjoerg case STATE_ACK_SENT: 201525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 201678064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 201778064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 201825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20194910Swollman break; 20204910Swollman } 20214910Swollman} 20224910Swollman 202325944Sjoergstatic void 202425944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 202525944Sjoerg{ 202625944Sjoerg STDDCL; 202725944Sjoerg 2028138745Srik SPPP_LOCK(sp); 202925944Sjoerg if (debug) 203040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 203140008Sjoerg SPP_ARGS(ifp), cp->name, 203225944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 203325944Sjoerg sp->rst_counter[cp->protoidx]); 203425944Sjoerg 203525944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 203625944Sjoerg /* TO- event */ 203725944Sjoerg switch (sp->state[cp->protoidx]) { 203825944Sjoerg case STATE_CLOSING: 203941881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 204025944Sjoerg (cp->tlf)(sp); 204125944Sjoerg break; 204225944Sjoerg case STATE_STOPPING: 204341881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 204425944Sjoerg (cp->tlf)(sp); 204525944Sjoerg break; 204625944Sjoerg case STATE_REQ_SENT: 204725944Sjoerg case STATE_ACK_RCVD: 204825944Sjoerg case STATE_ACK_SENT: 204941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 205025944Sjoerg (cp->tlf)(sp); 205125944Sjoerg break; 205225944Sjoerg } 205325944Sjoerg else 205425944Sjoerg /* TO+ event */ 205525944Sjoerg switch (sp->state[cp->protoidx]) { 205625944Sjoerg case STATE_CLOSING: 205725944Sjoerg case STATE_STOPPING: 205878064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 205978064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2060138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2061138745Srik cp->TO, (void *)sp); 206225944Sjoerg break; 206325944Sjoerg case STATE_REQ_SENT: 206425944Sjoerg case STATE_ACK_RCVD: 206525944Sjoerg (cp->scr)(sp); 206625944Sjoerg /* sppp_cp_change_state() will restart the timer */ 206725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 206825944Sjoerg break; 206925944Sjoerg case STATE_ACK_SENT: 207025944Sjoerg (cp->scr)(sp); 2071138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2072138745Srik cp->TO, (void *)sp); 207325944Sjoerg break; 207425944Sjoerg } 207525944Sjoerg 2076138745Srik SPPP_UNLOCK(sp); 207725944Sjoerg} 207825944Sjoerg 207911189Sjkh/* 208025944Sjoerg * Change the state of a control protocol in the state automaton. 208125944Sjoerg * Takes care of starting/stopping the restart timer. 208211189Sjkh */ 2083105228Sphkstatic void 208425944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 208525944Sjoerg{ 208625944Sjoerg sp->state[cp->protoidx] = newstate; 208725944Sjoerg 2088138745Srik callout_stop (&sp->ch[cp->protoidx]); 2089138745Srik 209025944Sjoerg switch (newstate) { 209125944Sjoerg case STATE_INITIAL: 209225944Sjoerg case STATE_STARTING: 209325944Sjoerg case STATE_CLOSED: 209425944Sjoerg case STATE_STOPPED: 209525944Sjoerg case STATE_OPENED: 209625944Sjoerg break; 209725944Sjoerg case STATE_CLOSING: 209825944Sjoerg case STATE_STOPPING: 209925944Sjoerg case STATE_REQ_SENT: 210025944Sjoerg case STATE_ACK_RCVD: 210125944Sjoerg case STATE_ACK_SENT: 2102138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2103138745Srik cp->TO, (void *)sp); 210425944Sjoerg break; 210525944Sjoerg } 210625944Sjoerg} 210770199Sjhay 210870199Sjhay/* 210925944Sjoerg *--------------------------------------------------------------------------* 211025944Sjoerg * * 211125944Sjoerg * The LCP implementation. * 211225944Sjoerg * * 211325944Sjoerg *--------------------------------------------------------------------------* 211425944Sjoerg */ 211525944Sjoergstatic void 2116138745Sriksppp_pp_up(struct sppp *sp) 2117138745Srik{ 2118138745Srik SPPP_LOCK(sp); 2119138745Srik lcp.Up(sp); 2120138745Srik SPPP_UNLOCK(sp); 2121138745Srik} 2122138745Srik 2123138745Srikstatic void 2124138745Sriksppp_pp_down(struct sppp *sp) 2125138745Srik{ 2126138745Srik SPPP_LOCK(sp); 2127138745Srik lcp.Down(sp); 2128138745Srik SPPP_UNLOCK(sp); 2129138745Srik} 2130138745Srik 2131138745Srikstatic void 213225944Sjoergsppp_lcp_init(struct sppp *sp) 213325944Sjoerg{ 213425944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 213525944Sjoerg sp->lcp.magic = 0; 213625944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 213725944Sjoerg sp->fail_counter[IDX_LCP] = 0; 213878064Sume sp->pp_seq[IDX_LCP] = 0; 213978064Sume sp->pp_rseq[IDX_LCP] = 0; 214025944Sjoerg sp->lcp.protos = 0; 214125944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 214230300Sjoerg 214344145Sphk /* Note that these values are relevant for all control protocols */ 214444145Sphk sp->lcp.timeout = 3 * hz; 214525944Sjoerg sp->lcp.max_terminate = 2; 214625944Sjoerg sp->lcp.max_configure = 10; 214725944Sjoerg sp->lcp.max_failure = 10; 2148283291Sjkim callout_init(&sp->ch[IDX_LCP], 1); 214925944Sjoerg} 215025944Sjoerg 215125944Sjoergstatic void 215225944Sjoergsppp_lcp_up(struct sppp *sp) 215325944Sjoerg{ 215425944Sjoerg STDDCL; 215525944Sjoerg 215670199Sjhay sp->pp_alivecnt = 0; 215770199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 215870199Sjhay sp->lcp.magic = 0; 215970199Sjhay sp->lcp.protos = 0; 216070199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 216125944Sjoerg /* 216275321Sjoerg * If we are authenticator, negotiate LCP_AUTH 216375321Sjoerg */ 216475321Sjoerg if (sp->hisauth.proto != 0) 216575321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 216675321Sjoerg else 216775321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 216875321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 216975321Sjoerg /* 217030300Sjoerg * If this interface is passive or dial-on-demand, and we are 217130300Sjoerg * still in Initial state, it means we've got an incoming 217230300Sjoerg * call. Activate the interface. 217325944Sjoerg */ 217425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 217525944Sjoerg if (debug) 217625944Sjoerg log(LOG_DEBUG, 217740008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2178148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 217930300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 218030300Sjoerg if (debug) 218169211Sphk log(-1, "(incoming call)\n"); 218230300Sjoerg sp->pp_flags |= PP_CALLIN; 218330300Sjoerg lcp.Open(sp); 218430300Sjoerg } else if (debug) 218569211Sphk log(-1, "\n"); 218688710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 218788710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2188148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 218988710Sjoerg lcp.Open(sp); 219025944Sjoerg } 219125944Sjoerg 219225944Sjoerg sppp_up_event(&lcp, sp); 219325944Sjoerg} 219425944Sjoerg 219525944Sjoergstatic void 219625944Sjoergsppp_lcp_down(struct sppp *sp) 219725944Sjoerg{ 219825944Sjoerg STDDCL; 219925944Sjoerg 220025944Sjoerg sppp_down_event(&lcp, sp); 220125944Sjoerg 220225944Sjoerg /* 220325944Sjoerg * If this is neither a dial-on-demand nor a passive 220425944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 220525944Sjoerg * administrator can force a redial by another ``ifconfig 220625944Sjoerg * up''. XXX For leased line operation, should we immediately 220725944Sjoerg * try to reopen the connection here? 220825944Sjoerg */ 220925944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 221025944Sjoerg log(LOG_INFO, 221142066Sphk SPP_FMT "Down event, taking interface down.\n", 221240008Sjoerg SPP_ARGS(ifp)); 221325944Sjoerg if_down(ifp); 221425944Sjoerg } else { 221525944Sjoerg if (debug) 221625944Sjoerg log(LOG_DEBUG, 221740008Sjoerg SPP_FMT "Down event (carrier loss)\n", 221840008Sjoerg SPP_ARGS(ifp)); 221970199Sjhay sp->pp_flags &= ~PP_CALLIN; 222070199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 222170199Sjhay lcp.Close(sp); 2222148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 222325944Sjoerg } 222425944Sjoerg} 222525944Sjoerg 222625944Sjoergstatic void 222725944Sjoergsppp_lcp_open(struct sppp *sp) 222825944Sjoerg{ 222925944Sjoerg sppp_open_event(&lcp, sp); 223025944Sjoerg} 223125944Sjoerg 223225944Sjoergstatic void 223325944Sjoergsppp_lcp_close(struct sppp *sp) 223425944Sjoerg{ 223525944Sjoerg sppp_close_event(&lcp, sp); 223625944Sjoerg} 223725944Sjoerg 223825944Sjoergstatic void 223925944Sjoergsppp_lcp_TO(void *cookie) 224025944Sjoerg{ 224125944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 224225944Sjoerg} 224325944Sjoerg 224425944Sjoerg/* 224525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 224625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 224725944Sjoerg * caused action scn. (The return value is used to make the state 224825944Sjoerg * transition decision in the state automaton.) 224925944Sjoerg */ 225012820Sphkstatic int 225125944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 22524910Swollman{ 225325944Sjoerg STDDCL; 225411189Sjkh u_char *buf, *r, *p; 225525944Sjoerg int origlen, rlen; 225625944Sjoerg u_long nmagic; 225730300Sjoerg u_short authproto; 22584910Swollman 225911189Sjkh len -= 4; 226025944Sjoerg origlen = len; 226111189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 226211189Sjkh if (! buf) 226311189Sjkh return (0); 22644910Swollman 226525706Sjoerg if (debug) 226640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 226740008Sjoerg SPP_ARGS(ifp)); 226825706Sjoerg 226925944Sjoerg /* pass 1: check for things that need to be rejected */ 227011189Sjkh p = (void*) (h+1); 2271161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2272161556Scperciva len-=p[1], p+=p[1]) { 227325944Sjoerg if (debug) 227469211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 227511189Sjkh switch (*p) { 227611189Sjkh case LCP_OPT_MAGIC: 227725944Sjoerg /* Magic number. */ 227870199Sjhay if (len >= 6 && p[1] == 6) 227970199Sjhay continue; 228070199Sjhay if (debug) 228170199Sjhay log(-1, "[invalid] "); 228270199Sjhay break; 228325944Sjoerg case LCP_OPT_ASYNC_MAP: 228425944Sjoerg /* Async control character map. */ 228570199Sjhay if (len >= 6 && p[1] == 6) 228625944Sjoerg continue; 228725944Sjoerg if (debug) 228869211Sphk log(-1, "[invalid] "); 228925944Sjoerg break; 229025944Sjoerg case LCP_OPT_MRU: 229125944Sjoerg /* Maximum receive unit. */ 229225944Sjoerg if (len >= 4 && p[1] == 4) 229325944Sjoerg continue; 229425944Sjoerg if (debug) 229569211Sphk log(-1, "[invalid] "); 229625944Sjoerg break; 229730300Sjoerg case LCP_OPT_AUTH_PROTO: 229830300Sjoerg if (len < 4) { 229930300Sjoerg if (debug) 230069211Sphk log(-1, "[invalid] "); 230130300Sjoerg break; 230230300Sjoerg } 230330300Sjoerg authproto = (p[2] << 8) + p[3]; 230430300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 230530300Sjoerg if (debug) 230669211Sphk log(-1, "[invalid chap len] "); 230730300Sjoerg break; 230830300Sjoerg } 230930300Sjoerg if (sp->myauth.proto == 0) { 231030300Sjoerg /* we are not configured to do auth */ 231130300Sjoerg if (debug) 231269211Sphk log(-1, "[not configured] "); 231330300Sjoerg break; 231430300Sjoerg } 231530300Sjoerg /* 231630300Sjoerg * Remote want us to authenticate, remember this, 231730300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 231830300Sjoerg * up. 231930300Sjoerg */ 232030300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 232130300Sjoerg continue; 232225944Sjoerg default: 232325944Sjoerg /* Others not supported. */ 232425944Sjoerg if (debug) 232569211Sphk log(-1, "[rej] "); 232625944Sjoerg break; 232725944Sjoerg } 232825944Sjoerg /* Add the option to rejected list. */ 232925944Sjoerg bcopy (p, r, p[1]); 233025944Sjoerg r += p[1]; 233125944Sjoerg rlen += p[1]; 233225944Sjoerg } 233325944Sjoerg if (rlen) { 233425944Sjoerg if (debug) 233569211Sphk log(-1, " send conf-rej\n"); 233625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 233725944Sjoerg return 0; 233825944Sjoerg } else if (debug) 233969211Sphk log(-1, "\n"); 234025944Sjoerg 234125944Sjoerg /* 234225944Sjoerg * pass 2: check for option values that are unacceptable and 234325944Sjoerg * thus require to be nak'ed. 234425944Sjoerg */ 234525944Sjoerg if (debug) 234640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 234740008Sjoerg SPP_ARGS(ifp)); 234825944Sjoerg 234925944Sjoerg p = (void*) (h+1); 235025944Sjoerg len = origlen; 2351161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2352161556Scperciva len-=p[1], p+=p[1]) { 235325944Sjoerg if (debug) 235469211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 235525944Sjoerg switch (*p) { 235625944Sjoerg case LCP_OPT_MAGIC: 235711189Sjkh /* Magic number -- extract. */ 235825944Sjoerg nmagic = (u_long)p[2] << 24 | 235925944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 236025944Sjoerg if (nmagic != sp->lcp.magic) { 236170199Sjhay sp->pp_loopcnt = 0; 236225706Sjoerg if (debug) 236369211Sphk log(-1, "0x%lx ", nmagic); 236411189Sjkh continue; 236511189Sjkh } 236670199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 236769211Sphk log(-1, "[glitch] "); 236825944Sjoerg ++sp->pp_loopcnt; 236925944Sjoerg /* 237025944Sjoerg * We negate our magic here, and NAK it. If 237125944Sjoerg * we see it later in an NAK packet, we 237225944Sjoerg * suggest a new one. 237325944Sjoerg */ 237425944Sjoerg nmagic = ~sp->lcp.magic; 237525944Sjoerg /* Gonna NAK it. */ 237625944Sjoerg p[2] = nmagic >> 24; 237725944Sjoerg p[3] = nmagic >> 16; 237825944Sjoerg p[4] = nmagic >> 8; 237925944Sjoerg p[5] = nmagic; 238011189Sjkh break; 238125944Sjoerg 238211189Sjkh case LCP_OPT_ASYNC_MAP: 238388506Sjoerg /* 238488506Sjoerg * Async control character map -- just ignore it. 238588506Sjoerg * 238688506Sjoerg * Quote from RFC 1662, chapter 6: 238788506Sjoerg * To enable this functionality, synchronous PPP 238888506Sjoerg * implementations MUST always respond to the 238988506Sjoerg * Async-Control-Character-Map Configuration 239088506Sjoerg * Option with the LCP Configure-Ack. However, 239188506Sjoerg * acceptance of the Configuration Option does 239288506Sjoerg * not imply that the synchronous implementation 239388506Sjoerg * will do any ACCM mapping. Instead, all such 239488506Sjoerg * octet mapping will be performed by the 239588506Sjoerg * asynchronous-to-synchronous converter. 239688506Sjoerg */ 239788506Sjoerg continue; 239825944Sjoerg 239911189Sjkh case LCP_OPT_MRU: 240025944Sjoerg /* 240125944Sjoerg * Maximum receive unit. Always agreeable, 240225944Sjoerg * but ignored by now. 240325944Sjoerg */ 240425944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 240525706Sjoerg if (debug) 240669211Sphk log(-1, "%lu ", sp->lcp.their_mru); 240711189Sjkh continue; 240830300Sjoerg 240930300Sjoerg case LCP_OPT_AUTH_PROTO: 241030300Sjoerg authproto = (p[2] << 8) + p[3]; 241130300Sjoerg if (sp->myauth.proto != authproto) { 241230300Sjoerg /* not agreed, nak */ 241330300Sjoerg if (debug) 241469211Sphk log(-1, "[mine %s != his %s] ", 241530300Sjoerg sppp_proto_name(sp->hisauth.proto), 241630300Sjoerg sppp_proto_name(authproto)); 241730300Sjoerg p[2] = sp->myauth.proto >> 8; 241830300Sjoerg p[3] = sp->myauth.proto; 241930300Sjoerg break; 242030300Sjoerg } 242130300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 242230300Sjoerg if (debug) 242369211Sphk log(-1, "[chap not MD5] "); 242439981Sjoerg p[4] = CHAP_MD5; 242530300Sjoerg break; 242630300Sjoerg } 242730300Sjoerg continue; 242811189Sjkh } 242925944Sjoerg /* Add the option to nak'ed list. */ 243025706Sjoerg bcopy (p, r, p[1]); 243125706Sjoerg r += p[1]; 243211189Sjkh rlen += p[1]; 243312436Speter } 243425706Sjoerg if (rlen) { 243570199Sjhay /* 243670199Sjhay * Local and remote magics equal -- loopback? 243770199Sjhay */ 243870199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 243970199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 244070199Sjhay printf (SPP_FMT "loopback\n", 244170199Sjhay SPP_ARGS(ifp)); 244270199Sjhay if (ifp->if_flags & IFF_UP) { 244370199Sjhay if_down(ifp); 244470199Sjhay sppp_qflush(&sp->pp_cpq); 244570199Sjhay /* XXX ? */ 244670199Sjhay lcp.Down(sp); 244770199Sjhay lcp.Up(sp); 244870199Sjhay } 2449131093Srik } else if (!sp->pp_loopcnt && 2450131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 245128036Sjoerg if (debug) 245269211Sphk log(-1, " max_failure (%d) exceeded, " 245328036Sjoerg "send conf-rej\n", 245428036Sjoerg sp->lcp.max_failure); 245528036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 245628036Sjoerg } else { 245728036Sjoerg if (debug) 245869211Sphk log(-1, " send conf-nak\n"); 245928036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 246028036Sjoerg } 246125944Sjoerg } else { 246225944Sjoerg if (debug) 246369211Sphk log(-1, " send conf-ack\n"); 246428036Sjoerg sp->fail_counter[IDX_LCP] = 0; 246525944Sjoerg sp->pp_loopcnt = 0; 246625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 246725944Sjoerg h->ident, origlen, h+1); 246825944Sjoerg } 246925944Sjoerg 247011189Sjkh free (buf, M_TEMP); 247111189Sjkh return (rlen == 0); 24724910Swollman} 24734910Swollman 247425944Sjoerg/* 247525944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 247625944Sjoerg * negotiation. 247725944Sjoerg */ 247812820Sphkstatic void 247925944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 24804910Swollman{ 248125944Sjoerg STDDCL; 248225944Sjoerg u_char *buf, *p; 24834910Swollman 248425944Sjoerg len -= 4; 248525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 248625944Sjoerg if (!buf) 24874910Swollman return; 248825944Sjoerg 248925944Sjoerg if (debug) 249040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 249140008Sjoerg SPP_ARGS(ifp)); 249225944Sjoerg 249325944Sjoerg p = (void*) (h+1); 2494161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2495161556Scperciva len -= p[1], p += p[1]) { 249625944Sjoerg if (debug) 249769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 249825944Sjoerg switch (*p) { 249925944Sjoerg case LCP_OPT_MAGIC: 250025944Sjoerg /* Magic number -- can't use it, use 0 */ 250125944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 250225944Sjoerg sp->lcp.magic = 0; 250325944Sjoerg break; 250425944Sjoerg case LCP_OPT_MRU: 250525944Sjoerg /* 250625944Sjoerg * Should not be rejected anyway, since we only 250725944Sjoerg * negotiate a MRU if explicitly requested by 250825944Sjoerg * peer. 250925944Sjoerg */ 251025944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 251125944Sjoerg break; 251230300Sjoerg case LCP_OPT_AUTH_PROTO: 251330300Sjoerg /* 251430300Sjoerg * Peer doesn't want to authenticate himself, 251530300Sjoerg * deny unless this is a dialout call, and 251630300Sjoerg * AUTHFLAG_NOCALLOUT is set. 251730300Sjoerg */ 251830300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 251930300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 252030300Sjoerg if (debug) 252169211Sphk log(-1, "[don't insist on auth " 252230300Sjoerg "for callout]"); 252330300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 252430300Sjoerg break; 252530300Sjoerg } 252630300Sjoerg if (debug) 252769211Sphk log(-1, "[access denied]\n"); 252830300Sjoerg lcp.Close(sp); 252930300Sjoerg break; 253025944Sjoerg } 25314910Swollman } 253225944Sjoerg if (debug) 253369211Sphk log(-1, "\n"); 253425944Sjoerg free (buf, M_TEMP); 253525944Sjoerg return; 253625944Sjoerg} 253725944Sjoerg 253825944Sjoerg/* 253925944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 254025944Sjoerg * negotiation. 254125944Sjoerg */ 254225944Sjoergstatic void 254325944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 254425944Sjoerg{ 254525944Sjoerg STDDCL; 254625944Sjoerg u_char *buf, *p; 254725944Sjoerg u_long magic; 254825944Sjoerg 254925944Sjoerg len -= 4; 255025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 255125944Sjoerg if (!buf) 255225944Sjoerg return; 255325944Sjoerg 255425944Sjoerg if (debug) 255540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 255640008Sjoerg SPP_ARGS(ifp)); 255725944Sjoerg 255825944Sjoerg p = (void*) (h+1); 2559161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2560161556Scperciva len -= p[1], p += p[1]) { 256125706Sjoerg if (debug) 256269211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 256325944Sjoerg switch (*p) { 256425944Sjoerg case LCP_OPT_MAGIC: 256525944Sjoerg /* Magic number -- renegotiate */ 256625944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 256725944Sjoerg len >= 6 && p[1] == 6) { 256825944Sjoerg magic = (u_long)p[2] << 24 | 256925944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 257025944Sjoerg /* 257125944Sjoerg * If the remote magic is our negated one, 257225944Sjoerg * this looks like a loopback problem. 257325944Sjoerg * Suggest a new magic to make sure. 257425944Sjoerg */ 257525944Sjoerg if (magic == ~sp->lcp.magic) { 257625944Sjoerg if (debug) 257769211Sphk log(-1, "magic glitch "); 257835064Sphk sp->lcp.magic = random(); 257925944Sjoerg } else { 258025944Sjoerg sp->lcp.magic = magic; 258125944Sjoerg if (debug) 258269211Sphk log(-1, "%lu ", magic); 258325944Sjoerg } 258425944Sjoerg } 258525944Sjoerg break; 258625944Sjoerg case LCP_OPT_MRU: 258725944Sjoerg /* 258825944Sjoerg * Peer wants to advise us to negotiate an MRU. 258925944Sjoerg * Agree on it if it's reasonable, or use 259025944Sjoerg * default otherwise. 259125944Sjoerg */ 259225944Sjoerg if (len >= 4 && p[1] == 4) { 259325944Sjoerg u_int mru = p[2] * 256 + p[3]; 259425944Sjoerg if (debug) 259569211Sphk log(-1, "%d ", mru); 259625944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 259725944Sjoerg mru = PP_MTU; 259825944Sjoerg sp->lcp.mru = mru; 259925944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 260025944Sjoerg } 260125944Sjoerg break; 260230300Sjoerg case LCP_OPT_AUTH_PROTO: 260330300Sjoerg /* 260430300Sjoerg * Peer doesn't like our authentication method, 260530300Sjoerg * deny. 260630300Sjoerg */ 260730300Sjoerg if (debug) 260869211Sphk log(-1, "[access denied]\n"); 260930300Sjoerg lcp.Close(sp); 261030300Sjoerg break; 26114910Swollman } 261225944Sjoerg } 261325944Sjoerg if (debug) 261469211Sphk log(-1, "\n"); 261525944Sjoerg free (buf, M_TEMP); 261625944Sjoerg return; 261725944Sjoerg} 261811189Sjkh 261925944Sjoergstatic void 262025944Sjoergsppp_lcp_tlu(struct sppp *sp) 262125944Sjoerg{ 262242066Sphk STDDCL; 262325944Sjoerg int i; 262425944Sjoerg u_long mask; 262525944Sjoerg 262625944Sjoerg /* XXX ? */ 262725944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2628148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 262925944Sjoerg /* Coming out of loopback mode. */ 263025944Sjoerg if_up(ifp); 263140008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 263225944Sjoerg } 263325944Sjoerg 263425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 263525944Sjoerg if ((cps[i])->flags & CP_QUAL) 263625944Sjoerg (cps[i])->Open(sp); 263725944Sjoerg 263830300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 263930300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 264025944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 264125944Sjoerg else 264225944Sjoerg sp->pp_phase = PHASE_NETWORK; 264325944Sjoerg 264442066Sphk if (debug) 264542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 264642066Sphk sppp_phase_name(sp->pp_phase)); 264725944Sjoerg 264830300Sjoerg /* 264930300Sjoerg * Open all authentication protocols. This is even required 265030300Sjoerg * if we already proceeded to network phase, since it might be 265130300Sjoerg * that remote wants us to authenticate, so we might have to 265230300Sjoerg * send a PAP request. Undesired authentication protocols 265330300Sjoerg * don't do anything when they get an Open event. 265430300Sjoerg */ 265530300Sjoerg for (i = 0; i < IDX_COUNT; i++) 265630300Sjoerg if ((cps[i])->flags & CP_AUTH) 265730300Sjoerg (cps[i])->Open(sp); 265830300Sjoerg 265930300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 266025944Sjoerg /* Notify all NCPs. */ 266125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 266288723Sjoerg if (((cps[i])->flags & CP_NCP) && 266388723Sjoerg /* 266488723Sjoerg * XXX 266588723Sjoerg * Hack to administratively disable IPv6 if 266688723Sjoerg * not desired. Perhaps we should have another 266788723Sjoerg * flag for this, but right now, we can make 266888723Sjoerg * all struct cp's read/only. 266988723Sjoerg */ 267088723Sjoerg (cps[i] != &ipv6cp || 267188723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 267225944Sjoerg (cps[i])->Open(sp); 267325944Sjoerg } 267425944Sjoerg 267525944Sjoerg /* Send Up events to all started protos. */ 267625944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 267788706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 267825944Sjoerg (cps[i])->Up(sp); 267925944Sjoerg 268042104Sphk /* notify low-level driver of state change */ 268142104Sphk if (sp->pp_chg) 268242104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 268342104Sphk 268425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 268525944Sjoerg /* if no NCP is starting, close down */ 268630300Sjoerg sppp_lcp_check_and_close(sp); 268725944Sjoerg} 268825944Sjoerg 268925944Sjoergstatic void 269025944Sjoergsppp_lcp_tld(struct sppp *sp) 269125944Sjoerg{ 269242066Sphk STDDCL; 269325944Sjoerg int i; 269425944Sjoerg u_long mask; 269525944Sjoerg 269625944Sjoerg sp->pp_phase = PHASE_TERMINATE; 269725944Sjoerg 269842066Sphk if (debug) 269942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 270042066Sphk sppp_phase_name(sp->pp_phase)); 270125944Sjoerg 270225944Sjoerg /* 270325944Sjoerg * Take upper layers down. We send the Down event first and 270425944Sjoerg * the Close second to prevent the upper layers from sending 270525944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 270625944Sjoerg * describes it. 270725944Sjoerg */ 270825944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 270988706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 271025944Sjoerg (cps[i])->Down(sp); 271125944Sjoerg (cps[i])->Close(sp); 271225944Sjoerg } 271325944Sjoerg} 271425944Sjoerg 271525944Sjoergstatic void 271625944Sjoergsppp_lcp_tls(struct sppp *sp) 271725944Sjoerg{ 271842066Sphk STDDCL; 271925944Sjoerg 272025944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 272125944Sjoerg 272242066Sphk if (debug) 272342066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 272442066Sphk sppp_phase_name(sp->pp_phase)); 272525944Sjoerg 272625944Sjoerg /* Notify lower layer if desired. */ 272725944Sjoerg if (sp->pp_tls) 272825944Sjoerg (sp->pp_tls)(sp); 272941881Sphk else 273041881Sphk (sp->pp_up)(sp); 273125944Sjoerg} 273225944Sjoerg 273325944Sjoergstatic void 273425944Sjoergsppp_lcp_tlf(struct sppp *sp) 273525944Sjoerg{ 273642066Sphk STDDCL; 273725944Sjoerg 273825944Sjoerg sp->pp_phase = PHASE_DEAD; 273942066Sphk if (debug) 274042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 274142066Sphk sppp_phase_name(sp->pp_phase)); 274225944Sjoerg 274325944Sjoerg /* Notify lower layer if desired. */ 274425944Sjoerg if (sp->pp_tlf) 274525944Sjoerg (sp->pp_tlf)(sp); 274641881Sphk else 274741881Sphk (sp->pp_down)(sp); 274825944Sjoerg} 274925944Sjoerg 275025944Sjoergstatic void 275125944Sjoergsppp_lcp_scr(struct sppp *sp) 275225944Sjoerg{ 275330300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 275425944Sjoerg int i = 0; 275530300Sjoerg u_short authproto; 275625944Sjoerg 275725944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 275825944Sjoerg if (! sp->lcp.magic) 275935064Sphk sp->lcp.magic = random(); 276025944Sjoerg opt[i++] = LCP_OPT_MAGIC; 276125944Sjoerg opt[i++] = 6; 276225944Sjoerg opt[i++] = sp->lcp.magic >> 24; 276325944Sjoerg opt[i++] = sp->lcp.magic >> 16; 276425944Sjoerg opt[i++] = sp->lcp.magic >> 8; 276525944Sjoerg opt[i++] = sp->lcp.magic; 276625944Sjoerg } 276725944Sjoerg 276825944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 276925944Sjoerg opt[i++] = LCP_OPT_MRU; 277025944Sjoerg opt[i++] = 4; 277125944Sjoerg opt[i++] = sp->lcp.mru >> 8; 277225944Sjoerg opt[i++] = sp->lcp.mru; 277325944Sjoerg } 277425944Sjoerg 277530300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 277630300Sjoerg authproto = sp->hisauth.proto; 277730300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 277830300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 277930300Sjoerg opt[i++] = authproto >> 8; 278030300Sjoerg opt[i++] = authproto; 278130300Sjoerg if (authproto == PPP_CHAP) 278230300Sjoerg opt[i++] = CHAP_MD5; 278330300Sjoerg } 278430300Sjoerg 278578064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 278625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 278725944Sjoerg} 278825944Sjoerg 278925944Sjoerg/* 279030300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 279130300Sjoerg */ 279230300Sjoergstatic int 279330300Sjoergsppp_ncp_check(struct sppp *sp) 279430300Sjoerg{ 279530300Sjoerg int i, mask; 279630300Sjoerg 279730300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 279888706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 279930300Sjoerg return 1; 280030300Sjoerg return 0; 280130300Sjoerg} 280230300Sjoerg 280330300Sjoerg/* 280425944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 280525944Sjoerg * Called by the NCPs during their tlf action handling. 280625944Sjoerg */ 280725944Sjoergstatic void 280830300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 280925944Sjoerg{ 281025944Sjoerg 281130300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 281230300Sjoerg /* don't bother, we are already going down */ 281330300Sjoerg return; 281430300Sjoerg 281530300Sjoerg if (sppp_ncp_check(sp)) 281630300Sjoerg return; 281730300Sjoerg 281825944Sjoerg lcp.Close(sp); 281925944Sjoerg} 282070199Sjhay 282170199Sjhay/* 282225944Sjoerg *--------------------------------------------------------------------------* 282325944Sjoerg * * 282425944Sjoerg * The IPCP implementation. * 282525944Sjoerg * * 282625944Sjoerg *--------------------------------------------------------------------------* 282725944Sjoerg */ 282825944Sjoerg 2829184682Sbz#ifdef INET 283025944Sjoergstatic void 283125944Sjoergsppp_ipcp_init(struct sppp *sp) 283225944Sjoerg{ 283325944Sjoerg sp->ipcp.opts = 0; 283425944Sjoerg sp->ipcp.flags = 0; 283525944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 283625944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 283778064Sume sp->pp_seq[IDX_IPCP] = 0; 283878064Sume sp->pp_rseq[IDX_IPCP] = 0; 2839283291Sjkim callout_init(&sp->ch[IDX_IPCP], 1); 284025944Sjoerg} 284125944Sjoerg 284225944Sjoergstatic void 284325944Sjoergsppp_ipcp_up(struct sppp *sp) 284425944Sjoerg{ 284525944Sjoerg sppp_up_event(&ipcp, sp); 284625944Sjoerg} 284725944Sjoerg 284825944Sjoergstatic void 284925944Sjoergsppp_ipcp_down(struct sppp *sp) 285025944Sjoerg{ 285125944Sjoerg sppp_down_event(&ipcp, sp); 285225944Sjoerg} 285325944Sjoerg 285425944Sjoergstatic void 285525944Sjoergsppp_ipcp_open(struct sppp *sp) 285625944Sjoerg{ 285725944Sjoerg STDDCL; 285825944Sjoerg u_long myaddr, hisaddr; 285925944Sjoerg 286088534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 286188534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 286288700Sjoerg sp->ipcp.opts = 0; 286342104Sphk 286430300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 286525944Sjoerg /* 286625944Sjoerg * If we don't have his address, this probably means our 286725944Sjoerg * interface doesn't want to talk IP at all. (This could 286825944Sjoerg * be the case if somebody wants to speak only IPX, for 286925944Sjoerg * example.) Don't open IPCP in this case. 287025944Sjoerg */ 287125944Sjoerg if (hisaddr == 0L) { 287225944Sjoerg /* XXX this message should go away */ 287325944Sjoerg if (debug) 287440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 287540008Sjoerg SPP_ARGS(ifp)); 287625944Sjoerg return; 287725944Sjoerg } 287825944Sjoerg if (myaddr == 0L) { 287925944Sjoerg /* 288025944Sjoerg * I don't have an assigned address, so i need to 288125944Sjoerg * negotiate my address. 288225944Sjoerg */ 288325944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 288425944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 288542104Sphk } else 288642104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 288788723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 288888534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 288988534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 289088534Sjoerg sp->ipcp.compress_cid = 1; 289188534Sjoerg } 289225944Sjoerg sppp_open_event(&ipcp, sp); 289325944Sjoerg} 289425944Sjoerg 289525944Sjoergstatic void 289625944Sjoergsppp_ipcp_close(struct sppp *sp) 289725944Sjoerg{ 289825944Sjoerg sppp_close_event(&ipcp, sp); 289925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 290025944Sjoerg /* 290125944Sjoerg * My address was dynamic, clear it again. 290225944Sjoerg */ 290325944Sjoerg sppp_set_ip_addr(sp, 0L); 290425944Sjoerg} 290525944Sjoerg 290625944Sjoergstatic void 290725944Sjoergsppp_ipcp_TO(void *cookie) 290825944Sjoerg{ 290925944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 291025944Sjoerg} 291125944Sjoerg 291225944Sjoerg/* 291325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 291425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 291525944Sjoerg * caused action scn. (The return value is used to make the state 291625944Sjoerg * transition decision in the state automaton.) 291725944Sjoerg */ 291825944Sjoergstatic int 291925944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 292025944Sjoerg{ 292125944Sjoerg u_char *buf, *r, *p; 2922147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 292325944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 292425944Sjoerg u_long hisaddr, desiredaddr; 292542104Sphk int gotmyaddr = 0; 292688534Sjoerg int desiredcomp; 292725944Sjoerg 292825944Sjoerg len -= 4; 292925944Sjoerg origlen = len; 293025944Sjoerg /* 293125944Sjoerg * Make sure to allocate a buf that can at least hold a 293225944Sjoerg * conf-nak with an `address' option. We might need it below. 293325944Sjoerg */ 293425944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 293525944Sjoerg if (! buf) 293625944Sjoerg return (0); 293725944Sjoerg 293825944Sjoerg /* pass 1: see if we can recognize them */ 293925944Sjoerg if (debug) 294040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 294140008Sjoerg SPP_ARGS(ifp)); 294225944Sjoerg p = (void*) (h+1); 2943161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2944161556Scperciva len-=p[1], p+=p[1]) { 294525944Sjoerg if (debug) 294669211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 294725944Sjoerg switch (*p) { 294888534Sjoerg case IPCP_OPT_COMPRESSION: 294988723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 295088534Sjoerg /* VJ compression administratively disabled */ 295188534Sjoerg if (debug) 295288534Sjoerg log(-1, "[locally disabled] "); 295388534Sjoerg break; 295488534Sjoerg } 295588534Sjoerg /* 295688534Sjoerg * In theory, we should only conf-rej an 295788534Sjoerg * option that is shorter than RFC 1618 295888534Sjoerg * requires (i.e. < 4), and should conf-nak 295988534Sjoerg * anything else that is not VJ. However, 296088534Sjoerg * since our algorithm always uses the 296188534Sjoerg * original option to NAK it with new values, 296288534Sjoerg * things would become more complicated. In 2963298995Spfg * practice, the only commonly implemented IP 296488534Sjoerg * compression option is VJ anyway, so the 296588534Sjoerg * difference is negligible. 296688534Sjoerg */ 296788534Sjoerg if (len >= 6 && p[1] == 6) { 296888534Sjoerg /* 296988534Sjoerg * correctly formed compression option 297088534Sjoerg * that could be VJ compression 297188534Sjoerg */ 297288534Sjoerg continue; 297388534Sjoerg } 297488534Sjoerg if (debug) 297588534Sjoerg log(-1, 297688534Sjoerg "optlen %d [invalid/unsupported] ", 297788534Sjoerg p[1]); 297888534Sjoerg break; 297925944Sjoerg case IPCP_OPT_ADDRESS: 298025944Sjoerg if (len >= 6 && p[1] == 6) { 298125944Sjoerg /* correctly formed address option */ 298225944Sjoerg continue; 298325944Sjoerg } 298425706Sjoerg if (debug) 298569211Sphk log(-1, "[invalid] "); 298611189Sjkh break; 298725944Sjoerg default: 298825944Sjoerg /* Others not supported. */ 298925944Sjoerg if (debug) 299069211Sphk log(-1, "[rej] "); 29914910Swollman break; 29924910Swollman } 299325944Sjoerg /* Add the option to rejected list. */ 299425944Sjoerg bcopy (p, r, p[1]); 299525944Sjoerg r += p[1]; 299625944Sjoerg rlen += p[1]; 299725944Sjoerg } 299825944Sjoerg if (rlen) { 299925944Sjoerg if (debug) 300069211Sphk log(-1, " send conf-rej\n"); 300125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 300225944Sjoerg return 0; 300325944Sjoerg } else if (debug) 300469211Sphk log(-1, "\n"); 300525944Sjoerg 300625944Sjoerg /* pass 2: parse option values */ 300730300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 300825944Sjoerg if (debug) 300940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 301040008Sjoerg SPP_ARGS(ifp)); 301125944Sjoerg p = (void*) (h+1); 301225944Sjoerg len = origlen; 3013161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3014161556Scperciva len-=p[1], p+=p[1]) { 301525944Sjoerg if (debug) 301669211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 301725944Sjoerg switch (*p) { 301888534Sjoerg case IPCP_OPT_COMPRESSION: 301988534Sjoerg desiredcomp = p[2] << 8 | p[3]; 302088534Sjoerg /* We only support VJ */ 302188534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 302288534Sjoerg if (debug) 302388534Sjoerg log(-1, "VJ [ack] "); 302488534Sjoerg sp->ipcp.flags |= IPCP_VJ; 302588599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 302688534Sjoerg sp->ipcp.max_state = p[4]; 302788534Sjoerg sp->ipcp.compress_cid = p[5]; 302888534Sjoerg continue; 302988534Sjoerg } 303088534Sjoerg if (debug) 303188534Sjoerg log(-1, 303288534Sjoerg "compproto %#04x [not supported] ", 303388534Sjoerg desiredcomp); 303488534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 303588534Sjoerg p[3] = IPCP_COMP_VJ; 303688534Sjoerg p[4] = sp->ipcp.max_state; 303788534Sjoerg p[5] = sp->ipcp.compress_cid; 303888534Sjoerg break; 303925944Sjoerg case IPCP_OPT_ADDRESS: 304042104Sphk /* This is the address he wants in his end */ 304125944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 304225944Sjoerg p[4] << 8 | p[5]; 304333928Sphk if (desiredaddr == hisaddr || 304488702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 304525944Sjoerg /* 304625944Sjoerg * Peer's address is same as our value, 304788702Sjoerg * or we have set it to 0.0.0.* to 304833928Sphk * indicate that we do not really care, 304925944Sjoerg * this is agreeable. Gonna conf-ack 305025944Sjoerg * it. 305125944Sjoerg */ 305225944Sjoerg if (debug) 305369211Sphk log(-1, "%s [ack] ", 305442104Sphk sppp_dotted_quad(hisaddr)); 305525944Sjoerg /* record that we've seen it already */ 305625944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 305725944Sjoerg continue; 305825944Sjoerg } 305925944Sjoerg /* 306025944Sjoerg * The address wasn't agreeable. This is either 306125944Sjoerg * he sent us 0.0.0.0, asking to assign him an 306225944Sjoerg * address, or he send us another address not 306325944Sjoerg * matching our value. Either case, we gonna 306425944Sjoerg * conf-nak it with our value. 306542104Sphk * XXX: we should "rej" if hisaddr == 0 306625944Sjoerg */ 306725944Sjoerg if (debug) { 306825944Sjoerg if (desiredaddr == 0) 306969211Sphk log(-1, "[addr requested] "); 307025944Sjoerg else 307169211Sphk log(-1, "%s [not agreed] ", 307242104Sphk sppp_dotted_quad(desiredaddr)); 307325944Sjoerg 307425944Sjoerg } 307544235Sphk p[2] = hisaddr >> 24; 307644235Sphk p[3] = hisaddr >> 16; 307744235Sphk p[4] = hisaddr >> 8; 307844235Sphk p[5] = hisaddr; 307911189Sjkh break; 308025706Sjoerg } 308125944Sjoerg /* Add the option to nak'ed list. */ 308225944Sjoerg bcopy (p, r, p[1]); 308325944Sjoerg r += p[1]; 308425944Sjoerg rlen += p[1]; 308525944Sjoerg } 308625944Sjoerg 308725944Sjoerg /* 308825944Sjoerg * If we are about to conf-ack the request, but haven't seen 308925944Sjoerg * his address so far, gonna conf-nak it instead, with the 309025944Sjoerg * `address' option present and our idea of his address being 309125944Sjoerg * filled in there, to request negotiation of both addresses. 309225944Sjoerg * 309325944Sjoerg * XXX This can result in an endless req - nak loop if peer 309425944Sjoerg * doesn't want to send us his address. Q: What should we do 309525944Sjoerg * about it? XXX A: implement the max-failure counter. 309625944Sjoerg */ 309742104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 309825944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 309925944Sjoerg buf[1] = 6; 310025944Sjoerg buf[2] = hisaddr >> 24; 310125944Sjoerg buf[3] = hisaddr >> 16; 310225944Sjoerg buf[4] = hisaddr >> 8; 310325944Sjoerg buf[5] = hisaddr; 310425944Sjoerg rlen = 6; 310525706Sjoerg if (debug) 310669211Sphk log(-1, "still need hisaddr "); 310725944Sjoerg } 310825944Sjoerg 310925944Sjoerg if (rlen) { 311025706Sjoerg if (debug) 311169211Sphk log(-1, " send conf-nak\n"); 311225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 311325944Sjoerg } else { 311425706Sjoerg if (debug) 311569211Sphk log(-1, " send conf-ack\n"); 311625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 311725944Sjoerg h->ident, origlen, h+1); 311825944Sjoerg } 311925944Sjoerg 312025944Sjoerg free (buf, M_TEMP); 312125944Sjoerg return (rlen == 0); 312225944Sjoerg} 312325944Sjoerg 312425944Sjoerg/* 312525944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 312625944Sjoerg * negotiation. 312725944Sjoerg */ 312825944Sjoergstatic void 312925944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 313025944Sjoerg{ 313125944Sjoerg u_char *buf, *p; 3132147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 313325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 313425944Sjoerg 313525944Sjoerg len -= 4; 313625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 313725944Sjoerg if (!buf) 313825944Sjoerg return; 313925944Sjoerg 314025944Sjoerg if (debug) 314140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 314240008Sjoerg SPP_ARGS(ifp)); 314325944Sjoerg 314425944Sjoerg p = (void*) (h+1); 3145161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3146161556Scperciva len -= p[1], p += p[1]) { 314725706Sjoerg if (debug) 314869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 314925944Sjoerg switch (*p) { 315088534Sjoerg case IPCP_OPT_COMPRESSION: 315188534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 315288534Sjoerg break; 315325944Sjoerg case IPCP_OPT_ADDRESS: 315425944Sjoerg /* 315525944Sjoerg * Peer doesn't grok address option. This is 315625944Sjoerg * bad. XXX Should we better give up here? 315742104Sphk * XXX We could try old "addresses" option... 315825944Sjoerg */ 315925944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 316025944Sjoerg break; 316125944Sjoerg } 31624910Swollman } 316325944Sjoerg if (debug) 316469211Sphk log(-1, "\n"); 316525944Sjoerg free (buf, M_TEMP); 316625944Sjoerg return; 31674910Swollman} 31684910Swollman 316925944Sjoerg/* 317025944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 317125944Sjoerg * negotiation. 317225944Sjoerg */ 317312820Sphkstatic void 317425944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 31754910Swollman{ 317625944Sjoerg u_char *buf, *p; 3177147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 317825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 317988534Sjoerg int desiredcomp; 318025944Sjoerg u_long wantaddr; 31814910Swollman 318225944Sjoerg len -= 4; 318325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 318425944Sjoerg if (!buf) 318525944Sjoerg return; 318625944Sjoerg 318725944Sjoerg if (debug) 318840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 318940008Sjoerg SPP_ARGS(ifp)); 319025944Sjoerg 319125944Sjoerg p = (void*) (h+1); 3192161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3193161556Scperciva len -= p[1], p += p[1]) { 319425944Sjoerg if (debug) 319569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 319625944Sjoerg switch (*p) { 319788534Sjoerg case IPCP_OPT_COMPRESSION: 319888534Sjoerg if (len >= 6 && p[1] == 6) { 319988534Sjoerg desiredcomp = p[2] << 8 | p[3]; 320088534Sjoerg if (debug) 320188534Sjoerg log(-1, "[wantcomp %#04x] ", 320288534Sjoerg desiredcomp); 320388534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 320488599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 320588534Sjoerg sp->ipcp.max_state = p[4]; 320688534Sjoerg sp->ipcp.compress_cid = p[5]; 320788534Sjoerg if (debug) 320888534Sjoerg log(-1, "[agree] "); 320988534Sjoerg } else 321088534Sjoerg sp->ipcp.opts &= 321188534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 321288534Sjoerg } 321388534Sjoerg break; 321425944Sjoerg case IPCP_OPT_ADDRESS: 321525944Sjoerg /* 321625944Sjoerg * Peer doesn't like our local IP address. See 321725944Sjoerg * if we can do something for him. We'll drop 321825944Sjoerg * him our address then. 321925944Sjoerg */ 322025944Sjoerg if (len >= 6 && p[1] == 6) { 322125944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 322225944Sjoerg p[4] << 8 | p[5]; 322325944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 322425944Sjoerg if (debug) 322569211Sphk log(-1, "[wantaddr %s] ", 322630300Sjoerg sppp_dotted_quad(wantaddr)); 322725944Sjoerg /* 322825944Sjoerg * When doing dynamic address assignment, 322925944Sjoerg * we accept his offer. Otherwise, we 323025944Sjoerg * ignore it and thus continue to negotiate 323125944Sjoerg * our already existing value. 323242104Sphk * XXX: Bogus, if he said no once, he'll 323342104Sphk * just say no again, might as well die. 323425944Sjoerg */ 323525944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 323625944Sjoerg sppp_set_ip_addr(sp, wantaddr); 323725944Sjoerg if (debug) 323869211Sphk log(-1, "[agree] "); 323942104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 324025944Sjoerg } 324125944Sjoerg } 324225944Sjoerg break; 324325944Sjoerg } 324425944Sjoerg } 324525944Sjoerg if (debug) 324669211Sphk log(-1, "\n"); 324725944Sjoerg free (buf, M_TEMP); 324825944Sjoerg return; 32494910Swollman} 32504910Swollman 325112820Sphkstatic void 325225944Sjoergsppp_ipcp_tlu(struct sppp *sp) 32534910Swollman{ 325442104Sphk /* we are up - notify isdn daemon */ 325542104Sphk if (sp->pp_con) 325642104Sphk sp->pp_con(sp); 32574910Swollman} 32584910Swollman 325925944Sjoergstatic void 326025944Sjoergsppp_ipcp_tld(struct sppp *sp) 326125944Sjoerg{ 326225944Sjoerg} 326325944Sjoerg 326425944Sjoergstatic void 326525944Sjoergsppp_ipcp_tls(struct sppp *sp) 326625944Sjoerg{ 326725944Sjoerg /* indicate to LCP that it must stay alive */ 326825944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 326925944Sjoerg} 327025944Sjoerg 327125944Sjoergstatic void 327225944Sjoergsppp_ipcp_tlf(struct sppp *sp) 327325944Sjoerg{ 327425944Sjoerg /* we no longer need LCP */ 327525944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 327630300Sjoerg sppp_lcp_check_and_close(sp); 327725944Sjoerg} 327825944Sjoerg 327925944Sjoergstatic void 328025944Sjoergsppp_ipcp_scr(struct sppp *sp) 328125944Sjoerg{ 328225944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 328325944Sjoerg u_long ouraddr; 328425944Sjoerg int i = 0; 328525944Sjoerg 328688534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 328788534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 328888534Sjoerg opt[i++] = 6; 328988534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 329088534Sjoerg opt[i++] = IPCP_COMP_VJ; 329188534Sjoerg opt[i++] = sp->ipcp.max_state; 329288534Sjoerg opt[i++] = sp->ipcp.compress_cid; 329388534Sjoerg } 329425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 329530300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 329625944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 329725944Sjoerg opt[i++] = 6; 329825944Sjoerg opt[i++] = ouraddr >> 24; 329925944Sjoerg opt[i++] = ouraddr >> 16; 330025944Sjoerg opt[i++] = ouraddr >> 8; 330125944Sjoerg opt[i++] = ouraddr; 330225944Sjoerg } 330325944Sjoerg 330478064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 330525944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 330625944Sjoerg} 3307184682Sbz#else /* !INET */ 3308184682Sbzstatic void 3309184682Sbzsppp_ipcp_init(struct sppp *sp) 3310184682Sbz{ 3311184682Sbz} 331225944Sjoerg 3313184682Sbzstatic void 3314184682Sbzsppp_ipcp_up(struct sppp *sp) 3315184682Sbz{ 3316184682Sbz} 3317184682Sbz 3318184682Sbzstatic void 3319184682Sbzsppp_ipcp_down(struct sppp *sp) 3320184682Sbz{ 3321184682Sbz} 3322184682Sbz 3323184682Sbzstatic void 3324184682Sbzsppp_ipcp_open(struct sppp *sp) 3325184682Sbz{ 3326184682Sbz} 3327184682Sbz 3328184682Sbzstatic void 3329184682Sbzsppp_ipcp_close(struct sppp *sp) 3330184682Sbz{ 3331184682Sbz} 3332184682Sbz 3333184682Sbzstatic void 3334184682Sbzsppp_ipcp_TO(void *cookie) 3335184682Sbz{ 3336184682Sbz} 3337184682Sbz 3338184682Sbzstatic int 3339184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3340184682Sbz{ 3341184682Sbz return (0); 3342184682Sbz} 3343184682Sbz 3344184682Sbzstatic void 3345184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3346184682Sbz{ 3347184682Sbz} 3348184682Sbz 3349184682Sbzstatic void 3350184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3351184682Sbz{ 3352184682Sbz} 3353184682Sbz 3354184682Sbzstatic void 3355184682Sbzsppp_ipcp_tlu(struct sppp *sp) 3356184682Sbz{ 3357184682Sbz} 3358184682Sbz 3359184682Sbzstatic void 3360184682Sbzsppp_ipcp_tld(struct sppp *sp) 3361184682Sbz{ 3362184682Sbz} 3363184682Sbz 3364184682Sbzstatic void 3365184682Sbzsppp_ipcp_tls(struct sppp *sp) 3366184682Sbz{ 3367184682Sbz} 3368184682Sbz 3369184682Sbzstatic void 3370184682Sbzsppp_ipcp_tlf(struct sppp *sp) 3371184682Sbz{ 3372184682Sbz} 3373184682Sbz 3374184682Sbzstatic void 3375184682Sbzsppp_ipcp_scr(struct sppp *sp) 3376184682Sbz{ 3377184682Sbz} 3378184682Sbz#endif 3379184682Sbz 338070199Sjhay/* 338130300Sjoerg *--------------------------------------------------------------------------* 338230300Sjoerg * * 338378064Sume * The IPv6CP implementation. * 338478064Sume * * 338578064Sume *--------------------------------------------------------------------------* 338678064Sume */ 338778064Sume 338878064Sume#ifdef INET6 338978064Sumestatic void 339078064Sumesppp_ipv6cp_init(struct sppp *sp) 339178064Sume{ 339278064Sume sp->ipv6cp.opts = 0; 339378064Sume sp->ipv6cp.flags = 0; 339478064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 339578064Sume sp->fail_counter[IDX_IPV6CP] = 0; 339678064Sume sp->pp_seq[IDX_IPV6CP] = 0; 339778064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3398283291Sjkim callout_init(&sp->ch[IDX_IPV6CP], 1); 339978064Sume} 340078064Sume 340178064Sumestatic void 340278064Sumesppp_ipv6cp_up(struct sppp *sp) 340378064Sume{ 340478064Sume sppp_up_event(&ipv6cp, sp); 340578064Sume} 340678064Sume 340778064Sumestatic void 340878064Sumesppp_ipv6cp_down(struct sppp *sp) 340978064Sume{ 341078064Sume sppp_down_event(&ipv6cp, sp); 341178064Sume} 341278064Sume 341378064Sumestatic void 341478064Sumesppp_ipv6cp_open(struct sppp *sp) 341578064Sume{ 341678064Sume STDDCL; 341778064Sume struct in6_addr myaddr, hisaddr; 341878064Sume 341978064Sume#ifdef IPV6CP_MYIFID_DYN 342078064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 342178064Sume#else 342278064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 342378064Sume#endif 342478064Sume 342578064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 342678064Sume /* 342778064Sume * If we don't have our address, this probably means our 342878064Sume * interface doesn't want to talk IPv6 at all. (This could 342978064Sume * be the case if somebody wants to speak only IPX, for 343078064Sume * example.) Don't open IPv6CP in this case. 343178064Sume */ 343278064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 343378064Sume /* XXX this message should go away */ 343478064Sume if (debug) 343578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 343678064Sume SPP_ARGS(ifp)); 343778064Sume return; 343878064Sume } 343978064Sume 344078064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 344178064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 344278064Sume sppp_open_event(&ipv6cp, sp); 344378064Sume} 344478064Sume 344578064Sumestatic void 344678064Sumesppp_ipv6cp_close(struct sppp *sp) 344778064Sume{ 344878064Sume sppp_close_event(&ipv6cp, sp); 344978064Sume} 345078064Sume 345178064Sumestatic void 345278064Sumesppp_ipv6cp_TO(void *cookie) 345378064Sume{ 345478064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 345578064Sume} 345678064Sume 345778064Sume/* 345878064Sume * Analyze a configure request. Return true if it was agreeable, and 345978064Sume * caused action sca, false if it has been rejected or nak'ed, and 346078064Sume * caused action scn. (The return value is used to make the state 346178064Sume * transition decision in the state automaton.) 346278064Sume */ 346378064Sumestatic int 346478064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 346578064Sume{ 346678064Sume u_char *buf, *r, *p; 3467147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 346878064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 346978064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 347078064Sume int ifidcount; 347178064Sume int type; 347278064Sume int collision, nohisaddr; 3473165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 347478064Sume 347578064Sume len -= 4; 347678064Sume origlen = len; 347778064Sume /* 347878064Sume * Make sure to allocate a buf that can at least hold a 347978064Sume * conf-nak with an `address' option. We might need it below. 348078064Sume */ 348178064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 348278064Sume if (! buf) 348378064Sume return (0); 348478064Sume 348578064Sume /* pass 1: see if we can recognize them */ 348678064Sume if (debug) 348778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 348878064Sume SPP_ARGS(ifp)); 348978064Sume p = (void*) (h+1); 349078064Sume ifidcount = 0; 3491161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3492161556Scperciva len-=p[1], p+=p[1]) { 349378064Sume if (debug) 349478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 349578064Sume switch (*p) { 349678064Sume case IPV6CP_OPT_IFID: 349778064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 349878064Sume /* correctly formed address option */ 349978064Sume ifidcount++; 350078064Sume continue; 350178064Sume } 350278064Sume if (debug) 350378176Sume log(-1, " [invalid]"); 350478064Sume break; 350578064Sume#ifdef notyet 350678064Sume case IPV6CP_OPT_COMPRESSION: 350778064Sume if (len >= 4 && p[1] >= 4) { 350878064Sume /* correctly formed compress option */ 350978064Sume continue; 351078064Sume } 351178064Sume if (debug) 351278176Sume log(-1, " [invalid]"); 351378064Sume break; 351478064Sume#endif 351578064Sume default: 351678064Sume /* Others not supported. */ 351778064Sume if (debug) 351878176Sume log(-1, " [rej]"); 351978064Sume break; 352078064Sume } 352178064Sume /* Add the option to rejected list. */ 352278064Sume bcopy (p, r, p[1]); 352378064Sume r += p[1]; 352478064Sume rlen += p[1]; 352578064Sume } 352678064Sume if (rlen) { 352778064Sume if (debug) 352878176Sume log(-1, " send conf-rej\n"); 352978064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 353078064Sume goto end; 353178064Sume } else if (debug) 353278176Sume log(-1, "\n"); 353378064Sume 353478064Sume /* pass 2: parse option values */ 353578064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 353678064Sume if (debug) 353778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 353878064Sume SPP_ARGS(ifp)); 353978064Sume p = (void*) (h+1); 354078064Sume len = origlen; 354178064Sume type = CONF_ACK; 3542161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3543161556Scperciva len-=p[1], p+=p[1]) { 354478064Sume if (debug) 354578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 354678064Sume switch (*p) { 354778064Sume#ifdef notyet 354878064Sume case IPV6CP_OPT_COMPRESSION: 354978064Sume continue; 355078064Sume#endif 355178064Sume case IPV6CP_OPT_IFID: 355278064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 355378064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 355478064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 355578064Sume &myaddr.s6_addr[8], 8) == 0); 355678064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 355778064Sume 355878064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3559148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 356078064Sume 356178064Sume if (!collision && !nohisaddr) { 356278064Sume /* no collision, hisaddr known - Conf-Ack */ 356378064Sume type = CONF_ACK; 356478064Sume 356578064Sume if (debug) { 356678176Sume log(-1, " %s [%s]", 3567165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3568165118Sbz sppp_cp_type_name(type)); 356978064Sume } 357078064Sume continue; 357178064Sume } 357278064Sume 3573250131Seadler bzero(&suggestaddr, sizeof(suggestaddr)); 357478064Sume if (collision && nohisaddr) { 357578064Sume /* collision, hisaddr unknown - Conf-Rej */ 357678064Sume type = CONF_REJ; 357778064Sume bzero(&p[2], 8); 357878064Sume } else { 357978064Sume /* 358078064Sume * - no collision, hisaddr unknown, or 358178064Sume * - collision, hisaddr known 358278064Sume * Conf-Nak, suggest hisaddr 358378064Sume */ 358478064Sume type = CONF_NAK; 358578064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 358678064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 358778064Sume } 358878064Sume if (debug) 3589165118Sbz log(-1, " %s [%s]", 3590165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3591165118Sbz sppp_cp_type_name(type)); 359278064Sume break; 359378064Sume } 359478064Sume /* Add the option to nak'ed list. */ 359578064Sume bcopy (p, r, p[1]); 359678064Sume r += p[1]; 359778064Sume rlen += p[1]; 359878064Sume } 359978064Sume 360078064Sume if (rlen == 0 && type == CONF_ACK) { 360178064Sume if (debug) 360278176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 360378064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 360478064Sume } else { 360578064Sume#ifdef DIAGNOSTIC 360678064Sume if (type == CONF_ACK) 360778064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 360878064Sume#endif 360978064Sume 361078064Sume if (debug) { 361178176Sume log(-1, " send %s suggest %s\n", 3612165118Sbz sppp_cp_type_name(type), 3613165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 361478064Sume } 361578064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 361678064Sume } 361778064Sume 361878064Sume end: 361978064Sume free (buf, M_TEMP); 362078064Sume return (rlen == 0); 362178064Sume} 362278064Sume 362378064Sume/* 362478064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 362578064Sume * negotiation. 362678064Sume */ 362778064Sumestatic void 362878064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 362978064Sume{ 363078064Sume u_char *buf, *p; 3631147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 363278064Sume int debug = ifp->if_flags & IFF_DEBUG; 363378064Sume 363478064Sume len -= 4; 363578064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 363678064Sume if (!buf) 363778064Sume return; 363878064Sume 363978064Sume if (debug) 364078064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 364178064Sume SPP_ARGS(ifp)); 364278064Sume 364378064Sume p = (void*) (h+1); 3644161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3645161556Scperciva len -= p[1], p += p[1]) { 364678064Sume if (debug) 364778176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 364878064Sume switch (*p) { 364978064Sume case IPV6CP_OPT_IFID: 365078064Sume /* 365178064Sume * Peer doesn't grok address option. This is 365278064Sume * bad. XXX Should we better give up here? 365378064Sume */ 365478064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 365578064Sume break; 365678064Sume#ifdef notyet 365778064Sume case IPV6CP_OPT_COMPRESS: 365878064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 365978064Sume break; 366078064Sume#endif 366178064Sume } 366278064Sume } 366378064Sume if (debug) 366478176Sume log(-1, "\n"); 366578064Sume free (buf, M_TEMP); 366678064Sume return; 366778064Sume} 366878064Sume 366978064Sume/* 367078064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 367178064Sume * negotiation. 367278064Sume */ 367378064Sumestatic void 367478064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 367578064Sume{ 367678064Sume u_char *buf, *p; 3677147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 367878064Sume int debug = ifp->if_flags & IFF_DEBUG; 367978064Sume struct in6_addr suggestaddr; 3680165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 368178064Sume 368278064Sume len -= 4; 368378064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 368478064Sume if (!buf) 368578064Sume return; 368678064Sume 368778064Sume if (debug) 368878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 368978064Sume SPP_ARGS(ifp)); 369078064Sume 369178064Sume p = (void*) (h+1); 3692161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3693161556Scperciva len -= p[1], p += p[1]) { 369478064Sume if (debug) 369578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 369678064Sume switch (*p) { 369778064Sume case IPV6CP_OPT_IFID: 369878064Sume /* 369978064Sume * Peer doesn't like our local ifid. See 370078064Sume * if we can do something for him. We'll drop 370178064Sume * him our address then. 370278064Sume */ 370378064Sume if (len < 10 || p[1] != 10) 370478064Sume break; 370578064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 370678064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3707148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 370878064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 370978064Sume 371078064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 371178064Sume if (debug) 371278176Sume log(-1, " [suggestaddr %s]", 3713165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 371478064Sume#ifdef IPV6CP_MYIFID_DYN 371578064Sume /* 371678064Sume * When doing dynamic address assignment, 371778064Sume * we accept his offer. 371878064Sume */ 371978064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 372078064Sume struct in6_addr lastsuggest; 372178064Sume /* 372278064Sume * If <suggested myaddr from peer> equals to 372378064Sume * <hisaddr we have suggested last time>, 372478064Sume * we have a collision. generate new random 372578064Sume * ifid. 372678064Sume */ 372778064Sume sppp_suggest_ip6_addr(&lastsuggest); 372878064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 372978064Sume lastsuggest)) { 373078064Sume if (debug) 373178176Sume log(-1, " [random]"); 373278064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 373378064Sume } 373478064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 373578064Sume if (debug) 373678176Sume log(-1, " [agree]"); 373778064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 373878064Sume } 373978064Sume#else 374078064Sume /* 374178064Sume * Since we do not do dynamic address assignment, 374278064Sume * we ignore it and thus continue to negotiate 374378064Sume * our already existing value. This can possibly 374478064Sume * go into infinite request-reject loop. 374578064Sume * 374678064Sume * This is not likely because we normally use 374778064Sume * ifid based on MAC-address. 374878064Sume * If you have no ethernet card on the node, too bad. 374978064Sume * XXX should we use fail_counter? 375078064Sume */ 375178064Sume#endif 375278064Sume break; 375378064Sume#ifdef notyet 375478064Sume case IPV6CP_OPT_COMPRESS: 375578064Sume /* 375678064Sume * Peer wants different compression parameters. 375778064Sume */ 375878064Sume break; 375978064Sume#endif 376078064Sume } 376178064Sume } 376278064Sume if (debug) 376378176Sume log(-1, "\n"); 376478064Sume free (buf, M_TEMP); 376578064Sume return; 376678064Sume} 376778064Sumestatic void 376878064Sumesppp_ipv6cp_tlu(struct sppp *sp) 376978064Sume{ 377078064Sume /* we are up - notify isdn daemon */ 377178064Sume if (sp->pp_con) 377278064Sume sp->pp_con(sp); 377378064Sume} 377478064Sume 377578064Sumestatic void 377678064Sumesppp_ipv6cp_tld(struct sppp *sp) 377778064Sume{ 377878064Sume} 377978064Sume 378078064Sumestatic void 378178064Sumesppp_ipv6cp_tls(struct sppp *sp) 378278064Sume{ 378378064Sume /* indicate to LCP that it must stay alive */ 378478064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 378578064Sume} 378678064Sume 378778064Sumestatic void 378878064Sumesppp_ipv6cp_tlf(struct sppp *sp) 378978064Sume{ 379078064Sume 379178064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 379278064Sume /* we no longer need LCP */ 379378064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 379478064Sume sppp_lcp_check_and_close(sp); 379578064Sume#endif 379678064Sume} 379778064Sume 379878064Sumestatic void 379978064Sumesppp_ipv6cp_scr(struct sppp *sp) 380078064Sume{ 380178064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 380278064Sume struct in6_addr ouraddr; 380378064Sume int i = 0; 380478064Sume 380578064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 380678064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 380778064Sume opt[i++] = IPV6CP_OPT_IFID; 380878064Sume opt[i++] = 10; 380978064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 381078064Sume i += 8; 381178064Sume } 381278064Sume 381378064Sume#ifdef notyet 381478064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 381578064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 381678064Sume opt[i++] = 4; 381778064Sume opt[i++] = 0; /* TBD */ 381878064Sume opt[i++] = 0; /* TBD */ 381978064Sume /* variable length data may follow */ 382078064Sume } 382178064Sume#endif 382278064Sume 382378064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 382478064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 382578064Sume} 382678064Sume#else /*INET6*/ 382778064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 382878064Sume{ 382978064Sume} 383078064Sume 383178064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 383278064Sume{ 383378064Sume} 383478064Sume 383578064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 383678064Sume{ 383778064Sume} 383878064Sume 383978064Sume 384078064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 384178064Sume{ 384278064Sume} 384378064Sume 384478064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 384578064Sume{ 384678064Sume} 384778064Sume 384878064Sumestatic void sppp_ipv6cp_TO(void *sp) 384978064Sume{ 385078064Sume} 385178064Sume 385278064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 385378064Sume{ 385478064Sume return 0; 385578064Sume} 385678064Sume 385778064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 385878064Sume{ 385978064Sume} 386078064Sume 386178064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 386278064Sume{ 386378064Sume} 386478064Sume 386578064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 386678064Sume{ 386778064Sume} 386878064Sume 386978064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 387078064Sume{ 387178064Sume} 387278064Sume 387378064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 387478064Sume{ 387578064Sume} 387678064Sume 387778064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 387878064Sume{ 387978064Sume} 388078064Sume 388178064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 388278064Sume{ 388378064Sume} 388478064Sume#endif /*INET6*/ 388578064Sume 388678064Sume/* 388778064Sume *--------------------------------------------------------------------------* 388878064Sume * * 388930300Sjoerg * The CHAP implementation. * 389030300Sjoerg * * 389130300Sjoerg *--------------------------------------------------------------------------* 389230300Sjoerg */ 389330300Sjoerg 389430300Sjoerg/* 389530300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 389630300Sjoerg * the control protocols do, since they do have Open and Close events, but 389730300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 389830300Sjoerg * authentication protocols may be different in both directions (this makes 389930300Sjoerg * sense, think of a machine that never accepts incoming calls but only 390030300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 390130300Sjoerg * 390230300Sjoerg * Our state machine for the local authentication protocol (we are requesting 390330300Sjoerg * the peer to authenticate) looks like: 390430300Sjoerg * 390530300Sjoerg * RCA- 390630300Sjoerg * +--------------------------------------------+ 390730300Sjoerg * V scn,tld| 390830300Sjoerg * +--------+ Close +---------+ RCA+ 390930300Sjoerg * | |<----------------------------------| |------+ 391030300Sjoerg * +--->| Closed | TO* | Opened | sca | 391130300Sjoerg * | | |-----+ +-------| |<-----+ 391230300Sjoerg * | +--------+ irc | | +---------+ 391330300Sjoerg * | ^ | | ^ 391430300Sjoerg * | | | | | 391530300Sjoerg * | | | | | 391630300Sjoerg * | TO-| | | | 391730300Sjoerg * | |tld TO+ V | | 391830300Sjoerg * | | +------->+ | | 391930300Sjoerg * | | | | | | 392030300Sjoerg * | +--------+ V | | 392130300Sjoerg * | | |<----+<--------------------+ | 392230300Sjoerg * | | Req- | scr | 392330300Sjoerg * | | Sent | | 392430300Sjoerg * | | | | 392530300Sjoerg * | +--------+ | 392630300Sjoerg * | RCA- | | RCA+ | 392730300Sjoerg * +------+ +------------------------------------------+ 392830300Sjoerg * scn,tld sca,irc,ict,tlu 392930300Sjoerg * 393030300Sjoerg * 393130300Sjoerg * with: 393230300Sjoerg * 393330300Sjoerg * Open: LCP reached authentication phase 393430300Sjoerg * Close: LCP reached terminate phase 393530300Sjoerg * 393630300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 393730300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 393830300Sjoerg * TO+: timeout with restart counter >= 0 393930300Sjoerg * TO-: timeout with restart counter < 0 394030300Sjoerg * TO*: reschedule timeout for CHAP 394130300Sjoerg * 394230300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 394330300Sjoerg * sca: send ack packet (pap-ack, chap-success) 394430300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 394530300Sjoerg * ict: initialize re-challenge timer (CHAP only) 394630300Sjoerg * 394730300Sjoerg * tlu: this-layer-up, LCP reaches network phase 394830300Sjoerg * tld: this-layer-down, LCP enters terminate phase 394930300Sjoerg * 395030300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 395130300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 395230300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 395330300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 395430300Sjoerg * causing LCP to enter terminate phase. 395530300Sjoerg * 395630300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 395730300Sjoerg * expected to send one based on the successful negotiation of PAP as 395830300Sjoerg * the authentication protocol during the LCP option negotiation. 395930300Sjoerg * 396030300Sjoerg * Incoming authentication protocol requests (remote requests 396130300Sjoerg * authentication, we are peer) don't employ a state machine at all, 396230300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 396330300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 396430300Sjoerg * still in authentication phase (thereby violating the standard that 396530300Sjoerg * demands that these NCP packets are to be discarded), so we keep 396630300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 396730300Sjoerg * phase network once we've seen a positive acknowledge for the 396830300Sjoerg * authentication. 396930300Sjoerg */ 397030300Sjoerg 397130300Sjoerg/* 397230300Sjoerg * Handle incoming CHAP packets. 397330300Sjoerg */ 3974105228Sphkstatic void 397530300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 397630300Sjoerg{ 397730300Sjoerg STDDCL; 397830300Sjoerg struct lcp_header *h; 3979241686Sandre int len; 398030300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 398130300Sjoerg int value_len, name_len; 398230300Sjoerg MD5_CTX ctx; 398330300Sjoerg 398430300Sjoerg len = m->m_pkthdr.len; 398530300Sjoerg if (len < 4) { 398630300Sjoerg if (debug) 398730300Sjoerg log(LOG_DEBUG, 398840008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 398940008Sjoerg SPP_ARGS(ifp), len); 399030300Sjoerg return; 399130300Sjoerg } 399230300Sjoerg h = mtod (m, struct lcp_header*); 399330300Sjoerg if (len > ntohs (h->len)) 399430300Sjoerg len = ntohs (h->len); 399530300Sjoerg 399630300Sjoerg switch (h->type) { 399730300Sjoerg /* challenge, failure and success are his authproto */ 399830300Sjoerg case CHAP_CHALLENGE: 399930300Sjoerg value = 1 + (u_char*)(h+1); 400030300Sjoerg value_len = value[-1]; 400130300Sjoerg name = value + value_len; 400230300Sjoerg name_len = len - value_len - 5; 400330300Sjoerg if (name_len < 0) { 400430300Sjoerg if (debug) { 400530300Sjoerg log(LOG_DEBUG, 400640008Sjoerg SPP_FMT "chap corrupted challenge " 400730300Sjoerg "<%s id=0x%x len=%d", 400840008Sjoerg SPP_ARGS(ifp), 400930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 401030300Sjoerg h->ident, ntohs(h->len)); 401144145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 401269211Sphk log(-1, ">\n"); 401330300Sjoerg } 401430300Sjoerg break; 401530300Sjoerg } 401670199Sjhay 401730300Sjoerg if (debug) { 401830300Sjoerg log(LOG_DEBUG, 401940008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 402040008Sjoerg SPP_ARGS(ifp), 402130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 402230300Sjoerg ntohs(h->len)); 402330300Sjoerg sppp_print_string((char*) name, name_len); 402469211Sphk log(-1, " value-size=%d value=", value_len); 402530300Sjoerg sppp_print_bytes(value, value_len); 402669211Sphk log(-1, ">\n"); 402730300Sjoerg } 402830300Sjoerg 402930300Sjoerg /* Compute reply value. */ 403030300Sjoerg MD5Init(&ctx); 403130300Sjoerg MD5Update(&ctx, &h->ident, 1); 403230300Sjoerg MD5Update(&ctx, sp->myauth.secret, 403330300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 403430300Sjoerg MD5Update(&ctx, value, value_len); 403530300Sjoerg MD5Final(digest, &ctx); 403630300Sjoerg dsize = sizeof digest; 403730300Sjoerg 403830300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 403930300Sjoerg sizeof dsize, (const char *)&dsize, 404030300Sjoerg sizeof digest, digest, 404140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 404230300Sjoerg sp->myauth.name, 404330300Sjoerg 0); 404430300Sjoerg break; 404530300Sjoerg 404630300Sjoerg case CHAP_SUCCESS: 404730300Sjoerg if (debug) { 404840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 404940008Sjoerg SPP_ARGS(ifp)); 405030300Sjoerg if (len > 4) { 405169211Sphk log(-1, ": "); 405230300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 405330300Sjoerg } 405469211Sphk log(-1, "\n"); 405530300Sjoerg } 4056138745Srik SPPP_LOCK(sp); 405730300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 405830300Sjoerg if (sp->myauth.proto == PPP_CHAP && 405932169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 406030300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 406130300Sjoerg /* 406230300Sjoerg * We are authenticator for CHAP but didn't 406330300Sjoerg * complete yet. Leave it to tlu to proceed 406430300Sjoerg * to network phase. 406530300Sjoerg */ 4066138745Srik SPPP_UNLOCK(sp); 406730300Sjoerg break; 406830300Sjoerg } 4069138745Srik SPPP_UNLOCK(sp); 407030300Sjoerg sppp_phase_network(sp); 407130300Sjoerg break; 407230300Sjoerg 407330300Sjoerg case CHAP_FAILURE: 407430300Sjoerg if (debug) { 407540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 407640008Sjoerg SPP_ARGS(ifp)); 407730300Sjoerg if (len > 4) { 407869211Sphk log(-1, ": "); 407930300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 408030300Sjoerg } 408169211Sphk log(-1, "\n"); 408230300Sjoerg } else 408340008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 408440008Sjoerg SPP_ARGS(ifp)); 408530300Sjoerg /* await LCP shutdown by authenticator */ 408630300Sjoerg break; 408730300Sjoerg 408830300Sjoerg /* response is my authproto */ 408930300Sjoerg case CHAP_RESPONSE: 409030300Sjoerg value = 1 + (u_char*)(h+1); 409130300Sjoerg value_len = value[-1]; 409230300Sjoerg name = value + value_len; 409330300Sjoerg name_len = len - value_len - 5; 409430300Sjoerg if (name_len < 0) { 409530300Sjoerg if (debug) { 409630300Sjoerg log(LOG_DEBUG, 409740008Sjoerg SPP_FMT "chap corrupted response " 409830300Sjoerg "<%s id=0x%x len=%d", 409940008Sjoerg SPP_ARGS(ifp), 410030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 410130300Sjoerg h->ident, ntohs(h->len)); 410244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 410369211Sphk log(-1, ">\n"); 410430300Sjoerg } 410530300Sjoerg break; 410630300Sjoerg } 410730300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 410830300Sjoerg if (debug) 410930300Sjoerg log(LOG_DEBUG, 411040008Sjoerg SPP_FMT "chap dropping response for old ID " 411130300Sjoerg "(got %d, expected %d)\n", 411240008Sjoerg SPP_ARGS(ifp), 411330300Sjoerg h->ident, sp->confid[IDX_CHAP]); 411430300Sjoerg break; 411530300Sjoerg } 411630300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 411730300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 411840008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 411940008Sjoerg SPP_ARGS(ifp)); 412030300Sjoerg sppp_print_string(name, name_len); 412169211Sphk log(-1, " != expected "); 412230300Sjoerg sppp_print_string(sp->hisauth.name, 412330300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 412469211Sphk log(-1, "\n"); 412570199Sjhay } 412630300Sjoerg if (debug) { 412740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 412830300Sjoerg "<%s id=0x%x len=%d name=", 412940008Sjoerg SPP_ARGS(ifp), 413030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 413130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 413230300Sjoerg h->ident, ntohs (h->len)); 413330300Sjoerg sppp_print_string((char*)name, name_len); 413469211Sphk log(-1, " value-size=%d value=", value_len); 413530300Sjoerg sppp_print_bytes(value, value_len); 413669211Sphk log(-1, ">\n"); 413730300Sjoerg } 413830300Sjoerg if (value_len != AUTHKEYLEN) { 413930300Sjoerg if (debug) 414030300Sjoerg log(LOG_DEBUG, 414140008Sjoerg SPP_FMT "chap bad hash value length: " 414230300Sjoerg "%d bytes, should be %d\n", 414340008Sjoerg SPP_ARGS(ifp), value_len, 414430300Sjoerg AUTHKEYLEN); 414530300Sjoerg break; 414630300Sjoerg } 414730300Sjoerg 414830300Sjoerg MD5Init(&ctx); 414930300Sjoerg MD5Update(&ctx, &h->ident, 1); 415030300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 415130300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 415230300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 415330300Sjoerg MD5Final(digest, &ctx); 415430300Sjoerg 415530300Sjoerg#define FAILMSG "Failed..." 415630300Sjoerg#define SUCCMSG "Welcome!" 415730300Sjoerg 415830300Sjoerg if (value_len != sizeof digest || 415930300Sjoerg bcmp(digest, value, value_len) != 0) { 416030300Sjoerg /* action scn, tld */ 416130300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 416230300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 416330300Sjoerg 0); 416430300Sjoerg chap.tld(sp); 416530300Sjoerg break; 416630300Sjoerg } 416730300Sjoerg /* action sca, perhaps tlu */ 416830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 416930300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 417030300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 417130300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 417230300Sjoerg 0); 417330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 417430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 417530300Sjoerg chap.tlu(sp); 417630300Sjoerg } 417730300Sjoerg break; 417830300Sjoerg 417930300Sjoerg default: 418030300Sjoerg /* Unknown CHAP packet type -- ignore. */ 418130300Sjoerg if (debug) { 418240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 418330300Sjoerg "<0x%x id=0x%xh len=%d", 418440008Sjoerg SPP_ARGS(ifp), 418530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 418630300Sjoerg h->type, h->ident, ntohs(h->len)); 418744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 418869211Sphk log(-1, ">\n"); 418930300Sjoerg } 419030300Sjoerg break; 419130300Sjoerg 419230300Sjoerg } 419330300Sjoerg} 419430300Sjoerg 419530300Sjoergstatic void 419630300Sjoergsppp_chap_init(struct sppp *sp) 419730300Sjoerg{ 419830300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 419930300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 420030300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 420178064Sume sp->pp_seq[IDX_CHAP] = 0; 420278064Sume sp->pp_rseq[IDX_CHAP] = 0; 4203283291Sjkim callout_init(&sp->ch[IDX_CHAP], 1); 420430300Sjoerg} 420530300Sjoerg 420630300Sjoergstatic void 420730300Sjoergsppp_chap_open(struct sppp *sp) 420830300Sjoerg{ 420930300Sjoerg if (sp->myauth.proto == PPP_CHAP && 421030300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 421130300Sjoerg /* we are authenticator for CHAP, start it */ 421230300Sjoerg chap.scr(sp); 421330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 421430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 421530300Sjoerg } 421630300Sjoerg /* nothing to be done if we are peer, await a challenge */ 421730300Sjoerg} 421830300Sjoerg 421930300Sjoergstatic void 422030300Sjoergsppp_chap_close(struct sppp *sp) 422130300Sjoerg{ 422230300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 422330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 422430300Sjoerg} 422530300Sjoerg 422630300Sjoergstatic void 422730300Sjoergsppp_chap_TO(void *cookie) 422830300Sjoerg{ 422930300Sjoerg struct sppp *sp = (struct sppp *)cookie; 423030300Sjoerg STDDCL; 423130300Sjoerg 4232138745Srik SPPP_LOCK(sp); 423330300Sjoerg if (debug) 423440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 423540008Sjoerg SPP_ARGS(ifp), 423630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 423730300Sjoerg sp->rst_counter[IDX_CHAP]); 423830300Sjoerg 423930300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 424030300Sjoerg /* TO- event */ 424130300Sjoerg switch (sp->state[IDX_CHAP]) { 424230300Sjoerg case STATE_REQ_SENT: 424330300Sjoerg chap.tld(sp); 424430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 424530300Sjoerg break; 424630300Sjoerg } 424730300Sjoerg else 424830300Sjoerg /* TO+ (or TO*) event */ 424930300Sjoerg switch (sp->state[IDX_CHAP]) { 425030300Sjoerg case STATE_OPENED: 425130300Sjoerg /* TO* event */ 425230300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4253102412Scharnier /* FALLTHROUGH */ 425430300Sjoerg case STATE_REQ_SENT: 425530300Sjoerg chap.scr(sp); 425630300Sjoerg /* sppp_cp_change_state() will restart the timer */ 425730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 425830300Sjoerg break; 425930300Sjoerg } 426030300Sjoerg 4261138745Srik SPPP_UNLOCK(sp); 426230300Sjoerg} 426330300Sjoerg 426430300Sjoergstatic void 426530300Sjoergsppp_chap_tlu(struct sppp *sp) 426630300Sjoerg{ 426730300Sjoerg STDDCL; 4268241686Sandre int i; 426930300Sjoerg 427040010Sjoerg i = 0; 427130300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 427230300Sjoerg 427330300Sjoerg /* 427430300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 427530300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 427630300Sjoerg * initial challenge-response exchange has taken place. 427730300Sjoerg * Provide for an option to avoid rechallenges. 427830300Sjoerg */ 427930300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 428030300Sjoerg /* 428130300Sjoerg * Compute the re-challenge timeout. This will yield 428230300Sjoerg * a number between 300 and 810 seconds. 428330300Sjoerg */ 428430300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4285138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 428630300Sjoerg } 428730300Sjoerg 428830300Sjoerg if (debug) { 428930300Sjoerg log(LOG_DEBUG, 429040008Sjoerg SPP_FMT "chap %s, ", 429140008Sjoerg SPP_ARGS(ifp), 429230300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 429330300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 429469211Sphk log(-1, "next re-challenge in %d seconds\n", i); 429530300Sjoerg else 4296298995Spfg log(-1, "re-challenging suppressed\n"); 429730300Sjoerg } 429830300Sjoerg 4299138745Srik SPPP_LOCK(sp); 430030300Sjoerg /* indicate to LCP that we need to be closed down */ 430130300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 430230300Sjoerg 430330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 430430300Sjoerg /* 430530300Sjoerg * Remote is authenticator, but his auth proto didn't 430630300Sjoerg * complete yet. Defer the transition to network 430730300Sjoerg * phase. 430830300Sjoerg */ 4309138745Srik SPPP_UNLOCK(sp); 431030300Sjoerg return; 431130300Sjoerg } 4312138745Srik SPPP_UNLOCK(sp); 431330300Sjoerg 431430300Sjoerg /* 431530300Sjoerg * If we are already in phase network, we are done here. This 431630300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 431730300Sjoerg */ 431830300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 431930300Sjoerg sppp_phase_network(sp); 432030300Sjoerg} 432130300Sjoerg 432230300Sjoergstatic void 432330300Sjoergsppp_chap_tld(struct sppp *sp) 432430300Sjoerg{ 432530300Sjoerg STDDCL; 432630300Sjoerg 432730300Sjoerg if (debug) 432840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4329138745Srik callout_stop(&sp->ch[IDX_CHAP]); 433030300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 433130300Sjoerg 433230300Sjoerg lcp.Close(sp); 433330300Sjoerg} 433430300Sjoerg 433530300Sjoergstatic void 433630300Sjoergsppp_chap_scr(struct sppp *sp) 433730300Sjoerg{ 433830300Sjoerg u_long *ch, seed; 433930300Sjoerg u_char clen; 434030300Sjoerg 434130300Sjoerg /* Compute random challenge. */ 434230300Sjoerg ch = (u_long *)sp->myauth.challenge; 434335064Sphk read_random(&seed, sizeof seed); 434430300Sjoerg ch[0] = seed ^ random(); 434530300Sjoerg ch[1] = seed ^ random(); 434630300Sjoerg ch[2] = seed ^ random(); 434730300Sjoerg ch[3] = seed ^ random(); 434830300Sjoerg clen = AUTHKEYLEN; 434930300Sjoerg 435078064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 435130300Sjoerg 435230300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 435330300Sjoerg sizeof clen, (const char *)&clen, 435440008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 435540008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 435630300Sjoerg sp->myauth.name, 435730300Sjoerg 0); 435830300Sjoerg} 435970199Sjhay 436070199Sjhay/* 436130300Sjoerg *--------------------------------------------------------------------------* 436230300Sjoerg * * 436330300Sjoerg * The PAP implementation. * 436430300Sjoerg * * 436530300Sjoerg *--------------------------------------------------------------------------* 436630300Sjoerg */ 436730300Sjoerg/* 436830300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 436930300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 437030300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 437130300Sjoerg * retry counter is expired). 437230300Sjoerg */ 437330300Sjoerg 437430300Sjoerg/* 437530300Sjoerg * Handle incoming PAP packets. */ 437630300Sjoergstatic void 437730300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 437830300Sjoerg{ 437930300Sjoerg STDDCL; 438030300Sjoerg struct lcp_header *h; 4381241686Sandre int len; 438230300Sjoerg u_char *name, *passwd, mlen; 438330300Sjoerg int name_len, passwd_len; 438430300Sjoerg 438530300Sjoerg len = m->m_pkthdr.len; 438630300Sjoerg if (len < 5) { 438730300Sjoerg if (debug) 438830300Sjoerg log(LOG_DEBUG, 438940008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 439040008Sjoerg SPP_ARGS(ifp), len); 439130300Sjoerg return; 439230300Sjoerg } 439330300Sjoerg h = mtod (m, struct lcp_header*); 439430300Sjoerg if (len > ntohs (h->len)) 439530300Sjoerg len = ntohs (h->len); 439630300Sjoerg switch (h->type) { 439730300Sjoerg /* PAP request is my authproto */ 439830300Sjoerg case PAP_REQ: 439930300Sjoerg name = 1 + (u_char*)(h+1); 440030300Sjoerg name_len = name[-1]; 440130300Sjoerg passwd = name + name_len + 1; 440230300Sjoerg if (name_len > len - 6 || 440330300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 440430300Sjoerg if (debug) { 440540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 440630300Sjoerg "<%s id=0x%x len=%d", 440740008Sjoerg SPP_ARGS(ifp), 440830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 440930300Sjoerg h->ident, ntohs(h->len)); 441044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 441169211Sphk log(-1, ">\n"); 441230300Sjoerg } 441330300Sjoerg break; 441430300Sjoerg } 441530300Sjoerg if (debug) { 441640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 441730300Sjoerg "<%s id=0x%x len=%d name=", 441840008Sjoerg SPP_ARGS(ifp), 441930300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 442030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 442130300Sjoerg h->ident, ntohs(h->len)); 442230300Sjoerg sppp_print_string((char*)name, name_len); 442369211Sphk log(-1, " passwd="); 442430300Sjoerg sppp_print_string((char*)passwd, passwd_len); 442569211Sphk log(-1, ">\n"); 442630300Sjoerg } 442774774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 442874774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 442930300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 443030300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 443130300Sjoerg /* action scn, tld */ 443230300Sjoerg mlen = sizeof(FAILMSG) - 1; 443330300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 443430300Sjoerg sizeof mlen, (const char *)&mlen, 443530300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 443630300Sjoerg 0); 443730300Sjoerg pap.tld(sp); 443830300Sjoerg break; 443930300Sjoerg } 444030300Sjoerg /* action sca, perhaps tlu */ 444130300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 444230300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 444330300Sjoerg mlen = sizeof(SUCCMSG) - 1; 444430300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 444530300Sjoerg sizeof mlen, (const char *)&mlen, 444630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 444730300Sjoerg 0); 444830300Sjoerg } 444930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 445030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 445130300Sjoerg pap.tlu(sp); 445230300Sjoerg } 445330300Sjoerg break; 445430300Sjoerg 445530300Sjoerg /* ack and nak are his authproto */ 445630300Sjoerg case PAP_ACK: 4457138745Srik callout_stop(&sp->pap_my_to_ch); 445830300Sjoerg if (debug) { 445940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 446040008Sjoerg SPP_ARGS(ifp)); 446130300Sjoerg name_len = *((char *)h); 446230300Sjoerg if (len > 5 && name_len) { 446369211Sphk log(-1, ": "); 446430300Sjoerg sppp_print_string((char*)(h+1), name_len); 446530300Sjoerg } 446669211Sphk log(-1, "\n"); 446730300Sjoerg } 4468138745Srik SPPP_LOCK(sp); 446930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 447030300Sjoerg if (sp->myauth.proto == PPP_PAP && 447132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 447230300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 447330300Sjoerg /* 447430300Sjoerg * We are authenticator for PAP but didn't 447530300Sjoerg * complete yet. Leave it to tlu to proceed 447630300Sjoerg * to network phase. 447730300Sjoerg */ 4478138745Srik SPPP_UNLOCK(sp); 447930300Sjoerg break; 448030300Sjoerg } 4481138745Srik SPPP_UNLOCK(sp); 448230300Sjoerg sppp_phase_network(sp); 448330300Sjoerg break; 448430300Sjoerg 448530300Sjoerg case PAP_NAK: 4486138745Srik callout_stop (&sp->pap_my_to_ch); 448730300Sjoerg if (debug) { 448840008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 448940008Sjoerg SPP_ARGS(ifp)); 449030300Sjoerg name_len = *((char *)h); 449130300Sjoerg if (len > 5 && name_len) { 449269211Sphk log(-1, ": "); 449330300Sjoerg sppp_print_string((char*)(h+1), name_len); 449430300Sjoerg } 449569211Sphk log(-1, "\n"); 449630300Sjoerg } else 449740008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 449840008Sjoerg SPP_ARGS(ifp)); 449930300Sjoerg /* await LCP shutdown by authenticator */ 450030300Sjoerg break; 450130300Sjoerg 450230300Sjoerg default: 450330300Sjoerg /* Unknown PAP packet type -- ignore. */ 450430300Sjoerg if (debug) { 450540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 450630300Sjoerg "<0x%x id=0x%x len=%d", 450740008Sjoerg SPP_ARGS(ifp), 450830300Sjoerg h->type, h->ident, ntohs(h->len)); 450944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 451069211Sphk log(-1, ">\n"); 451130300Sjoerg } 451230300Sjoerg break; 451330300Sjoerg 451430300Sjoerg } 451530300Sjoerg} 451630300Sjoerg 451730300Sjoergstatic void 451830300Sjoergsppp_pap_init(struct sppp *sp) 451930300Sjoerg{ 452030300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 452130300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 452230300Sjoerg sp->fail_counter[IDX_PAP] = 0; 452378064Sume sp->pp_seq[IDX_PAP] = 0; 452478064Sume sp->pp_rseq[IDX_PAP] = 0; 4525283291Sjkim callout_init(&sp->ch[IDX_PAP], 1); 4526283291Sjkim callout_init(&sp->pap_my_to_ch, 1); 452730300Sjoerg} 452830300Sjoerg 452930300Sjoergstatic void 453030300Sjoergsppp_pap_open(struct sppp *sp) 453130300Sjoerg{ 453230300Sjoerg if (sp->hisauth.proto == PPP_PAP && 453330300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 453430300Sjoerg /* we are authenticator for PAP, start our timer */ 453530300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 453630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 453730300Sjoerg } 453830300Sjoerg if (sp->myauth.proto == PPP_PAP) { 453930300Sjoerg /* we are peer, send a request, and start a timer */ 454030300Sjoerg pap.scr(sp); 4541138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4542138745Srik sppp_pap_my_TO, (void *)sp); 454330300Sjoerg } 454430300Sjoerg} 454530300Sjoerg 454630300Sjoergstatic void 454730300Sjoergsppp_pap_close(struct sppp *sp) 454830300Sjoerg{ 454930300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 455030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 455130300Sjoerg} 455230300Sjoerg 455330300Sjoerg/* 455430300Sjoerg * That's the timeout routine if we are authenticator. Since the 455530300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 455630300Sjoerg */ 455730300Sjoergstatic void 455830300Sjoergsppp_pap_TO(void *cookie) 455930300Sjoerg{ 456030300Sjoerg struct sppp *sp = (struct sppp *)cookie; 456130300Sjoerg STDDCL; 456230300Sjoerg 4563138745Srik SPPP_LOCK(sp); 456430300Sjoerg if (debug) 456540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 456640008Sjoerg SPP_ARGS(ifp), 456730300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 456830300Sjoerg sp->rst_counter[IDX_PAP]); 456930300Sjoerg 457030300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 457130300Sjoerg /* TO- event */ 457230300Sjoerg switch (sp->state[IDX_PAP]) { 457330300Sjoerg case STATE_REQ_SENT: 457430300Sjoerg pap.tld(sp); 457530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 457630300Sjoerg break; 457730300Sjoerg } 457830300Sjoerg else 457930300Sjoerg /* TO+ event, not very much we could do */ 458030300Sjoerg switch (sp->state[IDX_PAP]) { 458130300Sjoerg case STATE_REQ_SENT: 458230300Sjoerg /* sppp_cp_change_state() will restart the timer */ 458330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 458430300Sjoerg break; 458530300Sjoerg } 458630300Sjoerg 4587138745Srik SPPP_UNLOCK(sp); 458830300Sjoerg} 458930300Sjoerg 459030300Sjoerg/* 459130300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 459230300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 459330300Sjoerg * XXX We should impose a max counter. 459430300Sjoerg */ 459530300Sjoergstatic void 459630300Sjoergsppp_pap_my_TO(void *cookie) 459730300Sjoerg{ 459830300Sjoerg struct sppp *sp = (struct sppp *)cookie; 459930300Sjoerg STDDCL; 460030300Sjoerg 460130300Sjoerg if (debug) 460240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 460340008Sjoerg SPP_ARGS(ifp)); 460430300Sjoerg 4605138745Srik SPPP_LOCK(sp); 460630300Sjoerg pap.scr(sp); 4607138745Srik SPPP_UNLOCK(sp); 460830300Sjoerg} 460930300Sjoerg 461030300Sjoergstatic void 461130300Sjoergsppp_pap_tlu(struct sppp *sp) 461230300Sjoerg{ 461330300Sjoerg STDDCL; 461430300Sjoerg 461530300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 461630300Sjoerg 461730300Sjoerg if (debug) 461840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 461940008Sjoerg SPP_ARGS(ifp), pap.name); 462030300Sjoerg 4621138745Srik SPPP_LOCK(sp); 462230300Sjoerg /* indicate to LCP that we need to be closed down */ 462330300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 462430300Sjoerg 462530300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 462630300Sjoerg /* 462730300Sjoerg * Remote is authenticator, but his auth proto didn't 462830300Sjoerg * complete yet. Defer the transition to network 462930300Sjoerg * phase. 463030300Sjoerg */ 4631138745Srik SPPP_UNLOCK(sp); 463230300Sjoerg return; 463330300Sjoerg } 4634138745Srik SPPP_UNLOCK(sp); 463530300Sjoerg sppp_phase_network(sp); 463630300Sjoerg} 463730300Sjoerg 463830300Sjoergstatic void 463930300Sjoergsppp_pap_tld(struct sppp *sp) 464030300Sjoerg{ 464130300Sjoerg STDDCL; 464230300Sjoerg 464330300Sjoerg if (debug) 464440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4645138745Srik callout_stop (&sp->ch[IDX_PAP]); 4646138745Srik callout_stop (&sp->pap_my_to_ch); 464730300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 464830300Sjoerg 464930300Sjoerg lcp.Close(sp); 465030300Sjoerg} 465130300Sjoerg 465230300Sjoergstatic void 465330300Sjoergsppp_pap_scr(struct sppp *sp) 465430300Sjoerg{ 465530300Sjoerg u_char idlen, pwdlen; 465630300Sjoerg 465778064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 465830300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 465930300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 466030300Sjoerg 466130300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 466230300Sjoerg sizeof idlen, (const char *)&idlen, 466340008Sjoerg (size_t)idlen, sp->myauth.name, 466430300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 466540008Sjoerg (size_t)pwdlen, sp->myauth.secret, 466630300Sjoerg 0); 466730300Sjoerg} 466870199Sjhay 466970199Sjhay/* 467025944Sjoerg * Random miscellaneous functions. 467125944Sjoerg */ 467225944Sjoerg 46734910Swollman/* 467430300Sjoerg * Send a PAP or CHAP proto packet. 467530300Sjoerg * 467630300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 467740008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 467830300Sjoerg * mlen == 0. 467942104Sphk * NOTE: never declare variadic functions with types subject to type 468042104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 468142104Sphk * on the architecture you are on... 468230300Sjoerg */ 468330300Sjoerg 468430300Sjoergstatic void 468542104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 468642104Sphk unsigned int type, unsigned int id, 468730300Sjoerg ...) 468830300Sjoerg{ 468930300Sjoerg STDDCL; 469030300Sjoerg struct ppp_header *h; 469130300Sjoerg struct lcp_header *lh; 469230300Sjoerg struct mbuf *m; 469330300Sjoerg u_char *p; 469430300Sjoerg int len; 469542104Sphk unsigned int mlen; 469630300Sjoerg const char *msg; 469730300Sjoerg va_list ap; 469830300Sjoerg 4699243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 470030300Sjoerg if (! m) 470130300Sjoerg return; 470230300Sjoerg m->m_pkthdr.rcvif = 0; 470330300Sjoerg 470430300Sjoerg h = mtod (m, struct ppp_header*); 470530300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 470630300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 470730300Sjoerg h->protocol = htons(cp->proto); 470830300Sjoerg 470930300Sjoerg lh = (struct lcp_header*)(h + 1); 471030300Sjoerg lh->type = type; 471130300Sjoerg lh->ident = id; 471230300Sjoerg p = (u_char*) (lh+1); 471330300Sjoerg 471430300Sjoerg va_start(ap, id); 471530300Sjoerg len = 0; 471630300Sjoerg 471742104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 471830300Sjoerg msg = va_arg(ap, const char *); 471930300Sjoerg len += mlen; 472030300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 472130300Sjoerg va_end(ap); 472230300Sjoerg m_freem(m); 472330300Sjoerg return; 472430300Sjoerg } 472530300Sjoerg 472630300Sjoerg bcopy(msg, p, mlen); 472730300Sjoerg p += mlen; 472830300Sjoerg } 472930300Sjoerg va_end(ap); 473030300Sjoerg 473130300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 473230300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 473330300Sjoerg 473430300Sjoerg if (debug) { 473540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 473640008Sjoerg SPP_ARGS(ifp), cp->name, 473730300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 473830300Sjoerg lh->ident, ntohs(lh->len)); 473944145Sphk sppp_print_bytes((u_char*) (lh+1), len); 474069211Sphk log(-1, ">\n"); 474130300Sjoerg } 474269152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 4743271867Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 474430300Sjoerg} 474530300Sjoerg 474630300Sjoerg/* 474725944Sjoerg * Flush interface queue. 47484910Swollman */ 474912820Sphkstatic void 475025944Sjoergsppp_qflush(struct ifqueue *ifq) 47514910Swollman{ 475225944Sjoerg struct mbuf *m, *n; 47534910Swollman 475425944Sjoerg n = ifq->ifq_head; 475525944Sjoerg while ((m = n)) { 4756268787Skevlo n = m->m_nextpkt; 475725944Sjoerg m_freem (m); 475811189Sjkh } 475925944Sjoerg ifq->ifq_head = 0; 476025944Sjoerg ifq->ifq_tail = 0; 476125944Sjoerg ifq->ifq_len = 0; 476225944Sjoerg} 476325944Sjoerg 476425944Sjoerg/* 476525944Sjoerg * Send keepalive packets, every 10 seconds. 476625944Sjoerg */ 476725944Sjoergstatic void 476825944Sjoergsppp_keepalive(void *dummy) 476925944Sjoerg{ 4770138745Srik struct sppp *sp = (struct sppp*)dummy; 4771147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 477225944Sjoerg 4773138745Srik SPPP_LOCK(sp); 4774138745Srik /* Keepalive mode disabled or channel down? */ 4775138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4776148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4777138745Srik goto out; 477825944Sjoerg 4779139365Srik if (sp->pp_mode == PP_FR) { 4780139365Srik sppp_fr_keepalive (sp); 4781139365Srik goto out; 4782139365Srik } 4783139365Srik 4784138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4785138745Srik if (sp->pp_mode != IFF_CISCO && 4786138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4787138745Srik goto out; 478825944Sjoerg 4789138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4790138745Srik /* No keepalive packets got. Stop the interface. */ 4791138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4792138745Srik if_down (ifp); 4793138745Srik sppp_qflush (&sp->pp_cpq); 4794138745Srik if (sp->pp_mode != IFF_CISCO) { 4795138745Srik /* XXX */ 4796138745Srik /* Shut down the PPP link. */ 4797138745Srik lcp.Down(sp); 4798138745Srik /* Initiate negotiation. XXX */ 4799138745Srik lcp.Up(sp); 48004910Swollman } 48014910Swollman } 4802138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4803138745Srik ++sp->pp_alivecnt; 4804138745Srik if (sp->pp_mode == IFF_CISCO) 4805138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4806138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4807138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4808351026Semaste uint32_t nmagic = htonl(sp->lcp.magic); 4809138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4810138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4811138745Srik sp->lcp.echoid, 4, &nmagic); 4812138745Srik } 4813138745Srikout: 4814138745Srik SPPP_UNLOCK(sp); 4815138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4816138745Srik (void *)sp); 48174910Swollman} 48184910Swollman 481925944Sjoerg/* 482025944Sjoerg * Get both IP addresses. 482125944Sjoerg */ 4822139365Srikvoid 482330300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 482425944Sjoerg{ 4825147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 482625944Sjoerg struct ifaddr *ifa; 482730300Sjoerg struct sockaddr_in *si, *sm; 482825944Sjoerg u_long ssrc, ddst; 482925944Sjoerg 483040010Sjoerg sm = NULL; 483125944Sjoerg ssrc = ddst = 0L; 483225944Sjoerg /* 483325944Sjoerg * Pick the first AF_INET address from the list, 483425944Sjoerg * aliases don't make any sense on a p2p link anyway. 483525944Sjoerg */ 4836298075Spfg si = NULL; 4837195070Srwatson if_addr_rlock(ifp); 483842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 483925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 484025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 484130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 484225944Sjoerg if (si) 484325944Sjoerg break; 484425944Sjoerg } 484525944Sjoerg if (ifa) { 484630300Sjoerg if (si && si->sin_addr.s_addr) { 484725944Sjoerg ssrc = si->sin_addr.s_addr; 484830300Sjoerg if (srcmask) 484930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 485030300Sjoerg } 485125944Sjoerg 485225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 485325944Sjoerg if (si && si->sin_addr.s_addr) 485425944Sjoerg ddst = si->sin_addr.s_addr; 485525944Sjoerg } 4856195070Srwatson if_addr_runlock(ifp); 485725944Sjoerg 485825944Sjoerg if (dst) *dst = ntohl(ddst); 485925944Sjoerg if (src) *src = ntohl(ssrc); 486025944Sjoerg} 486125944Sjoerg 4862184682Sbz#ifdef INET 486325944Sjoerg/* 4864241686Sandre * Set my IP address. 486525944Sjoerg */ 486625944Sjoergstatic void 486725944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 486825944Sjoerg{ 486942104Sphk STDDCL; 487025944Sjoerg struct ifaddr *ifa; 487125944Sjoerg struct sockaddr_in *si; 487284318Sjlemon struct in_ifaddr *ia; 487325944Sjoerg 487425944Sjoerg /* 487525944Sjoerg * Pick the first AF_INET address from the list, 487625944Sjoerg * aliases don't make any sense on a p2p link anyway. 487725944Sjoerg */ 4878298075Spfg si = NULL; 4879195070Srwatson if_addr_rlock(ifp); 4880194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 4881194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET) { 488225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 4883194813Srwatson if (si != NULL) { 4884194813Srwatson ifa_ref(ifa); 488525944Sjoerg break; 4886194813Srwatson } 488725944Sjoerg } 488840008Sjoerg } 4889195070Srwatson if_addr_runlock(ifp); 489040008Sjoerg 4891194813Srwatson if (ifa != NULL) { 489242104Sphk int error; 4893194813Srwatson 489442104Sphk /* delete old route */ 489542104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 4896194813Srwatson if (debug && error) { 489742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 489842104Sphk SPP_ARGS(ifp), error); 489942104Sphk } 490042104Sphk 490142104Sphk /* set new address */ 490225944Sjoerg si->sin_addr.s_addr = htonl(src); 490384318Sjlemon ia = ifatoia(ifa); 4904194951Srwatson IN_IFADDR_WLOCK(); 490584318Sjlemon LIST_REMOVE(ia, ia_hash); 490684318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 4907194951Srwatson IN_IFADDR_WUNLOCK(); 490825944Sjoerg 490942104Sphk /* add new route */ 491070199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 4911194813Srwatson if (debug && error) { 491242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 491342104Sphk SPP_ARGS(ifp), error); 491442104Sphk } 4915194813Srwatson ifa_free(ifa); 491642104Sphk } 491788599Sjoerg} 4918184682Sbz#endif 491978064Sume 492078064Sume#ifdef INET6 492178064Sume/* 492278064Sume * Get both IPv6 addresses. 492378064Sume */ 492478064Sumestatic void 492578064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 492678064Sume struct in6_addr *srcmask) 492778064Sume{ 4928147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 492978064Sume struct ifaddr *ifa; 493078064Sume struct sockaddr_in6 *si, *sm; 493178064Sume struct in6_addr ssrc, ddst; 493278064Sume 493378064Sume sm = NULL; 493478064Sume bzero(&ssrc, sizeof(ssrc)); 493578064Sume bzero(&ddst, sizeof(ddst)); 493678064Sume /* 493778064Sume * Pick the first link-local AF_INET6 address from the list, 493878064Sume * aliases don't make any sense on a p2p link anyway. 493978064Sume */ 4940194813Srwatson si = NULL; 4941195070Srwatson if_addr_rlock(ifp); 4942160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 494378064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 494478064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 494578064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 494678064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 494778064Sume break; 494878064Sume } 494978064Sume if (ifa) { 495078064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 495178064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 495278064Sume if (srcmask) { 495378064Sume bcopy(&sm->sin6_addr, srcmask, 495478064Sume sizeof(*srcmask)); 495578064Sume } 495678064Sume } 495778064Sume 495878064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 495978064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 496078064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 496178064Sume } 496278064Sume 496378064Sume if (dst) 496478064Sume bcopy(&ddst, dst, sizeof(*dst)); 496578064Sume if (src) 496678064Sume bcopy(&ssrc, src, sizeof(*src)); 4967195070Srwatson if_addr_runlock(ifp); 496870199Sjhay} 496942104Sphk 497078064Sume#ifdef IPV6CP_MYIFID_DYN 497178064Sume/* 497278064Sume * Generate random ifid. 497378064Sume */ 497478064Sumestatic void 497578064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 497678064Sume{ 497778064Sume /* TBD */ 497878064Sume} 497978064Sume 498078064Sume/* 4981241686Sandre * Set my IPv6 address. 498278064Sume */ 498378064Sumestatic void 498478064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 498578064Sume{ 498678064Sume STDDCL; 498778064Sume struct ifaddr *ifa; 498878064Sume struct sockaddr_in6 *sin6; 498978064Sume 499078064Sume /* 499178064Sume * Pick the first link-local AF_INET6 address from the list, 499278064Sume * aliases don't make any sense on a p2p link anyway. 499378064Sume */ 499478064Sume 499578064Sume sin6 = NULL; 4996195070Srwatson if_addr_rlock(ifp); 4997194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 4998194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET6) { 499978064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 5000194813Srwatson if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5001194813Srwatson ifa_ref(ifa); 500278064Sume break; 5003194813Srwatson } 500478064Sume } 500578064Sume } 5006195070Srwatson if_addr_runlock(ifp); 500778064Sume 5008194813Srwatson if (ifa != NULL) { 500978064Sume int error; 501078064Sume struct sockaddr_in6 new_sin6 = *sin6; 501178064Sume 501278064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 501378064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 5014194813Srwatson if (debug && error) { 501578064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 501678064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 501778064Sume } 5018194813Srwatson ifa_free(ifa); 501978064Sume } 502078064Sume} 502178064Sume#endif 502278064Sume 502378064Sume/* 502478064Sume * Suggest a candidate address to be used by peer. 502578064Sume */ 502678064Sumestatic void 502778064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 502878064Sume{ 502978064Sume struct in6_addr myaddr; 503078064Sume struct timeval tv; 503178064Sume 503278064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 503378064Sume 503478064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 503578064Sume microtime(&tv); 503678064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 503778064Sume myaddr.s6_addr[14] ^= 0xff; 503878064Sume myaddr.s6_addr[15] ^= 0xff; 503978064Sume } else { 504078064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 504178064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 504278064Sume } 504378064Sume if (suggest) 504478064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 504578064Sume} 504678064Sume#endif /*INET6*/ 504778064Sume 504830300Sjoergstatic int 504938343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 505030300Sjoerg{ 505138343Sbde u_long subcmd; 505230300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 505388600Sjoerg struct spppreq *spr; 505488600Sjoerg int rv = 0; 505530300Sjoerg 5056298075Spfg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == NULL) 505788600Sjoerg return (EAGAIN); 505830300Sjoerg /* 5059332288Sbrooks * ifr_data_get_ptr(ifr) is supposed to point to a struct spppreq. 506030300Sjoerg * Check the cmd word first before attempting to fetch all the 506130300Sjoerg * data. 506230300Sjoerg */ 5063332288Sbrooks rv = fueword(ifr_data_get_ptr(ifr), &subcmd); 5064273784Skib if (rv == -1) { 506588600Sjoerg rv = EFAULT; 506688600Sjoerg goto quit; 506788600Sjoerg } 506830300Sjoerg 5069332288Sbrooks if (copyin(ifr_data_get_ptr(ifr), spr, sizeof(struct spppreq)) != 0) { 507088600Sjoerg rv = EFAULT; 507188600Sjoerg goto quit; 507288600Sjoerg } 507330300Sjoerg 507430300Sjoerg switch (subcmd) { 5075170490Smjacob case (u_long)SPPPIOGDEFS: 507688600Sjoerg if (cmd != SIOCGIFGENERIC) { 507788600Sjoerg rv = EINVAL; 507888600Sjoerg break; 507988600Sjoerg } 508030300Sjoerg /* 508130300Sjoerg * We copy over the entire current state, but clean 508230300Sjoerg * out some of the stuff we don't wanna pass up. 508330300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 508430300Sjoerg * called by any user. No need to ever get PAP or 508530300Sjoerg * CHAP secrets back to userland anyway. 508630300Sjoerg */ 508788600Sjoerg spr->defs.pp_phase = sp->pp_phase; 508888723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 508988723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 509088600Sjoerg spr->defs.lcp = sp->lcp; 509188600Sjoerg spr->defs.ipcp = sp->ipcp; 509288600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 509388600Sjoerg spr->defs.myauth = sp->myauth; 509488600Sjoerg spr->defs.hisauth = sp->hisauth; 509588600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 509688600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 509788600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 509888600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 509988550Sjoerg /* 510088550Sjoerg * Fixup the LCP timeout value to milliseconds so 510188550Sjoerg * spppcontrol doesn't need to bother about the value 510288550Sjoerg * of "hz". We do the reverse calculation below when 510388550Sjoerg * setting it. 510488550Sjoerg */ 510588600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 5106332288Sbrooks rv = copyout(spr, ifr_data_get_ptr(ifr), 5107332288Sbrooks sizeof(struct spppreq)); 510888600Sjoerg break; 510930300Sjoerg 5110170490Smjacob case (u_long)SPPPIOSDEFS: 511188600Sjoerg if (cmd != SIOCSIFGENERIC) { 511288600Sjoerg rv = EINVAL; 511388600Sjoerg break; 511488600Sjoerg } 511530300Sjoerg /* 511688550Sjoerg * We have a very specific idea of which fields we 511788550Sjoerg * allow being passed back from userland, so to not 511888550Sjoerg * clobber our current state. For one, we only allow 511988550Sjoerg * setting anything if LCP is in dead or establish 512088550Sjoerg * phase. Once the authentication negotiations 512188550Sjoerg * started, the authentication settings must not be 512288550Sjoerg * changed again. (The administrator can force an 512330300Sjoerg * ifconfig down in order to get LCP back into dead 512430300Sjoerg * phase.) 512530300Sjoerg * 512630300Sjoerg * Also, we only allow for authentication parameters to be 512730300Sjoerg * specified. 512830300Sjoerg * 512930300Sjoerg * XXX Should allow to set or clear pp_flags. 513030300Sjoerg * 513130300Sjoerg * Finally, if the respective authentication protocol to 513230300Sjoerg * be used is set differently than 0, but the secret is 513330300Sjoerg * passed as all zeros, we don't trash the existing secret. 513430300Sjoerg * This allows an administrator to change the system name 513530300Sjoerg * only without clobbering the secret (which he didn't get 513630300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 513730300Sjoerg * secrets are cleared if the authentication protocol is 513888550Sjoerg * reset to 0. */ 513988550Sjoerg if (sp->pp_phase != PHASE_DEAD && 514088600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 514188600Sjoerg rv = EBUSY; 514288600Sjoerg break; 514388600Sjoerg } 514430300Sjoerg 514588600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 514688600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 514788600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 514888600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 514988600Sjoerg rv = EINVAL; 515088600Sjoerg break; 515188600Sjoerg } 515230300Sjoerg 515388600Sjoerg if (spr->defs.myauth.proto == 0) 515430300Sjoerg /* resetting myauth */ 515530300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 515630300Sjoerg else { 515730300Sjoerg /* setting/changing myauth */ 515888600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 515988600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 516088600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 516188600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 516230300Sjoerg AUTHKEYLEN); 516330300Sjoerg } 516488600Sjoerg if (spr->defs.hisauth.proto == 0) 516530300Sjoerg /* resetting hisauth */ 516630300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 516730300Sjoerg else { 516830300Sjoerg /* setting/changing hisauth */ 516988600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 517088600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 517188600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 517288600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 517388600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 517430300Sjoerg AUTHKEYLEN); 517530300Sjoerg } 517688550Sjoerg /* set LCP restart timer timeout */ 517788600Sjoerg if (spr->defs.lcp.timeout != 0) 517888600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 517988723Sjoerg /* set VJ enable and IPv6 disable flags */ 518088723Sjoerg#ifdef INET 518188723Sjoerg if (spr->defs.enable_vj) 518288723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 518388723Sjoerg else 518488723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 518588723Sjoerg#endif 518688723Sjoerg#ifdef INET6 518788723Sjoerg if (spr->defs.enable_ipv6) 518888723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 518988723Sjoerg else 519088723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 519196349Sjoerg#endif 519230300Sjoerg break; 519330300Sjoerg 519430300Sjoerg default: 519588600Sjoerg rv = EINVAL; 519630300Sjoerg } 519730300Sjoerg 519888600Sjoerg quit: 519988600Sjoerg free(spr, M_TEMP); 520088600Sjoerg 520188600Sjoerg return (rv); 520230300Sjoerg} 520330300Sjoerg 520430300Sjoergstatic void 520530300Sjoergsppp_phase_network(struct sppp *sp) 520630300Sjoerg{ 520742066Sphk STDDCL; 520830300Sjoerg int i; 520930300Sjoerg u_long mask; 521030300Sjoerg 521130300Sjoerg sp->pp_phase = PHASE_NETWORK; 521230300Sjoerg 521342066Sphk if (debug) 521442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 521542066Sphk sppp_phase_name(sp->pp_phase)); 521630300Sjoerg 521730300Sjoerg /* Notify NCPs now. */ 521830300Sjoerg for (i = 0; i < IDX_COUNT; i++) 521930300Sjoerg if ((cps[i])->flags & CP_NCP) 522030300Sjoerg (cps[i])->Open(sp); 522130300Sjoerg 522230300Sjoerg /* Send Up events to all NCPs. */ 522330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 522488706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 522530300Sjoerg (cps[i])->Up(sp); 522630300Sjoerg 522730300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 522830300Sjoerg sppp_lcp_check_and_close(sp); 522930300Sjoerg} 523030300Sjoerg 523170199Sjhay 523225706Sjoergstatic const char * 523325944Sjoergsppp_cp_type_name(u_char type) 52344910Swollman{ 523530300Sjoerg static char buf[12]; 52364910Swollman switch (type) { 523730300Sjoerg case CONF_REQ: return "conf-req"; 523830300Sjoerg case CONF_ACK: return "conf-ack"; 523930300Sjoerg case CONF_NAK: return "conf-nak"; 524030300Sjoerg case CONF_REJ: return "conf-rej"; 524130300Sjoerg case TERM_REQ: return "term-req"; 524230300Sjoerg case TERM_ACK: return "term-ack"; 524330300Sjoerg case CODE_REJ: return "code-rej"; 524430300Sjoerg case PROTO_REJ: return "proto-rej"; 524530300Sjoerg case ECHO_REQ: return "echo-req"; 524630300Sjoerg case ECHO_REPLY: return "echo-reply"; 524730300Sjoerg case DISC_REQ: return "discard-req"; 52484910Swollman } 524944145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 525030300Sjoerg return buf; 52514910Swollman} 52524910Swollman 525325706Sjoergstatic const char * 525430300Sjoergsppp_auth_type_name(u_short proto, u_char type) 525530300Sjoerg{ 525630300Sjoerg static char buf[12]; 525730300Sjoerg switch (proto) { 525830300Sjoerg case PPP_CHAP: 525930300Sjoerg switch (type) { 526030300Sjoerg case CHAP_CHALLENGE: return "challenge"; 526130300Sjoerg case CHAP_RESPONSE: return "response"; 526230300Sjoerg case CHAP_SUCCESS: return "success"; 526330300Sjoerg case CHAP_FAILURE: return "failure"; 526430300Sjoerg } 526530300Sjoerg case PPP_PAP: 526630300Sjoerg switch (type) { 526730300Sjoerg case PAP_REQ: return "req"; 526830300Sjoerg case PAP_ACK: return "ack"; 526930300Sjoerg case PAP_NAK: return "nak"; 527030300Sjoerg } 527130300Sjoerg } 527244145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 527330300Sjoerg return buf; 527430300Sjoerg} 527530300Sjoerg 527630300Sjoergstatic const char * 527725944Sjoergsppp_lcp_opt_name(u_char opt) 52784910Swollman{ 527930300Sjoerg static char buf[12]; 528025944Sjoerg switch (opt) { 528130300Sjoerg case LCP_OPT_MRU: return "mru"; 528230300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 528330300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 528430300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 528530300Sjoerg case LCP_OPT_MAGIC: return "magic"; 528630300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 528730300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 52884910Swollman } 528944145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 529030300Sjoerg return buf; 52914910Swollman} 52924910Swollman 5293184682Sbz#ifdef INET 529425944Sjoergstatic const char * 529525944Sjoergsppp_ipcp_opt_name(u_char opt) 529625944Sjoerg{ 529730300Sjoerg static char buf[12]; 529825944Sjoerg switch (opt) { 529930300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 530030300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 530130300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 530225944Sjoerg } 530344145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 530430300Sjoerg return buf; 530525944Sjoerg} 5306184682Sbz#endif 530725944Sjoerg 530878064Sume#ifdef INET6 530925944Sjoergstatic const char * 531078064Sumesppp_ipv6cp_opt_name(u_char opt) 531178064Sume{ 531278064Sume static char buf[12]; 531378064Sume switch (opt) { 531478064Sume case IPV6CP_OPT_IFID: return "ifid"; 531578064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 531678064Sume } 531778064Sume sprintf (buf, "0x%x", opt); 531878064Sume return buf; 531978064Sume} 532078064Sume#endif 532178064Sume 532278064Sumestatic const char * 532325944Sjoergsppp_state_name(int state) 532425944Sjoerg{ 532525944Sjoerg switch (state) { 532625944Sjoerg case STATE_INITIAL: return "initial"; 532725944Sjoerg case STATE_STARTING: return "starting"; 532825944Sjoerg case STATE_CLOSED: return "closed"; 532925944Sjoerg case STATE_STOPPED: return "stopped"; 533025944Sjoerg case STATE_CLOSING: return "closing"; 533125944Sjoerg case STATE_STOPPING: return "stopping"; 533225944Sjoerg case STATE_REQ_SENT: return "req-sent"; 533325944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 533425944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 533525944Sjoerg case STATE_OPENED: return "opened"; 533625944Sjoerg } 533725944Sjoerg return "illegal"; 533825944Sjoerg} 533925944Sjoerg 534025944Sjoergstatic const char * 534125944Sjoergsppp_phase_name(enum ppp_phase phase) 534225944Sjoerg{ 534325944Sjoerg switch (phase) { 534425944Sjoerg case PHASE_DEAD: return "dead"; 534525944Sjoerg case PHASE_ESTABLISH: return "establish"; 534625944Sjoerg case PHASE_TERMINATE: return "terminate"; 534725944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 534825944Sjoerg case PHASE_NETWORK: return "network"; 534925944Sjoerg } 535025944Sjoerg return "illegal"; 535125944Sjoerg} 535225944Sjoerg 535325944Sjoergstatic const char * 535425944Sjoergsppp_proto_name(u_short proto) 535525944Sjoerg{ 535625944Sjoerg static char buf[12]; 535725944Sjoerg switch (proto) { 535825944Sjoerg case PPP_LCP: return "lcp"; 535925944Sjoerg case PPP_IPCP: return "ipcp"; 536030300Sjoerg case PPP_PAP: return "pap"; 536130300Sjoerg case PPP_CHAP: return "chap"; 536278064Sume case PPP_IPV6CP: return "ipv6cp"; 536325944Sjoerg } 536444145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 536525944Sjoerg return buf; 536625944Sjoerg} 536725944Sjoerg 536812820Sphkstatic void 536930300Sjoergsppp_print_bytes(const u_char *p, u_short len) 53704910Swollman{ 537144145Sphk if (len) 537269211Sphk log(-1, " %*D", len, p, "-"); 53734910Swollman} 537425944Sjoerg 537530300Sjoergstatic void 537630300Sjoergsppp_print_string(const char *p, u_short len) 537730300Sjoerg{ 537830300Sjoerg u_char c; 537930300Sjoerg 538030300Sjoerg while (len-- > 0) { 538130300Sjoerg c = *p++; 538230300Sjoerg /* 538330300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 538430300Sjoerg * using only them, but we don't rely on it. */ 538530300Sjoerg if (c < ' ' || c > '~') 538669211Sphk log(-1, "\\x%x", c); 538730300Sjoerg else 538869211Sphk log(-1, "%c", c); 538930300Sjoerg } 539030300Sjoerg} 539130300Sjoerg 5392184682Sbz#ifdef INET 539330300Sjoergstatic const char * 539430300Sjoergsppp_dotted_quad(u_long addr) 539530300Sjoerg{ 539630300Sjoerg static char s[16]; 539730300Sjoerg sprintf(s, "%d.%d.%d.%d", 539840008Sjoerg (int)((addr >> 24) & 0xff), 539940008Sjoerg (int)((addr >> 16) & 0xff), 540040008Sjoerg (int)((addr >> 8) & 0xff), 540138372Sbde (int)(addr & 0xff)); 540230300Sjoerg return s; 540330300Sjoerg} 5404184682Sbz#endif 540530300Sjoerg 540630300Sjoergstatic int 540730300Sjoergsppp_strnlen(u_char *p, int max) 540830300Sjoerg{ 540930300Sjoerg int len; 541030300Sjoerg 541130300Sjoerg for (len = 0; len < max && *p; ++p) 541230300Sjoerg ++len; 541330300Sjoerg return len; 541430300Sjoerg} 541530300Sjoerg 541630300Sjoerg/* a dummy, used to drop uninteresting events */ 541730300Sjoergstatic void 541830300Sjoergsppp_null(struct sppp *unused) 541930300Sjoerg{ 542030300Sjoerg /* do just nothing */ 542130300Sjoerg} 5422