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$ 224910Swollman */ 234910Swollman 2440008Sjoerg#include <sys/param.h> 2540008Sjoerg 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2931742Seivind 304952Sbde#include <sys/systm.h> 314952Sbde#include <sys/kernel.h> 3270199Sjhay#include <sys/module.h> 3324204Sbde#include <sys/sockio.h> 344910Swollman#include <sys/socket.h> 3525706Sjoerg#include <sys/syslog.h> 3659604Sobrien#include <sys/random.h> 3729024Sbde#include <sys/malloc.h> 384910Swollman#include <sys/mbuf.h> 3940008Sjoerg 4030300Sjoerg#include <sys/md5.h> 414910Swollman 424910Swollman#include <net/if.h> 434910Swollman#include <net/netisr.h> 444910Swollman#include <net/if_types.h> 4542104Sphk#include <net/route.h> 46196019Srwatson#include <net/vnet.h> 4788534Sjoerg#include <netinet/in.h> 4888534Sjoerg#include <netinet/in_systm.h> 4988534Sjoerg#include <netinet/ip.h> 5088534Sjoerg#include <net/slcompress.h> 514910Swollman 5230300Sjoerg#include <machine/stdarg.h> 5330300Sjoerg 544910Swollman#include <netinet/in_var.h> 5588705Sjoerg 5688705Sjoerg#ifdef INET 574910Swollman#include <netinet/ip.h> 584910Swollman#include <netinet/tcp.h> 594910Swollman#endif 604910Swollman 61148385Sume#ifdef INET6 62148385Sume#include <netinet6/scope6_var.h> 63148385Sume#endif 64148385Sume 65182121Simp#include <netinet/if_ether.h> 6688705Sjoerg 6711819Sjulian#ifdef IPX 6811819Sjulian#include <netipx/ipx.h> 6911819Sjulian#include <netipx/ipx_if.h> 7011819Sjulian#endif 7111819Sjulian 724910Swollman#include <net/if_sppp.h> 734910Swollman 74182121Simp#define IOCTL_CMD_T u_long 754910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 764910Swollman 7725944Sjoerg/* 7825944Sjoerg * Interface flags that can be set in an ifconfig command. 7925944Sjoerg * 8025955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 8125944Sjoerg * as being administrative openable, but won't be opened to begin 8225944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 8325944Sjoerg * -link1 will cause the administrative open of the LCP layer. 8425955Sjoerg * 8525955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 8625955Sjoerg * arrive to be sent. 8730300Sjoerg * 8830300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 8930300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 9030300Sjoerg * like 9130300Sjoerg * 9230300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 9330300Sjoerg * 9430300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 9530300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 9625944Sjoerg */ 9725944Sjoerg 9825955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 9925955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 10045152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 10125944Sjoerg 10230300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 10330300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 10430300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 10530300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 10630300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 10730300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 10888534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 10988534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 11078064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 11130300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 11230300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 11330300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 11430300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 11578064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1164910Swollman 11725944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 11825944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 11925944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 12025944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 12125944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 12225944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 12325944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 12425944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 12525944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 12625944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 12725944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1284910Swollman 12930300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 13030300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 13130300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 13230300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 13330300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 13430300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 13530300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 13630300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1374910Swollman 13825944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 13925944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 14025944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1414910Swollman 14278064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 14378064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 14478064Sume 14588534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 14688534Sjoerg 14730300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 14830300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 14930300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1504910Swollman 15130300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 15230300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 15330300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 15430300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 15530300Sjoerg 15630300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 15730300Sjoerg 15830300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 15930300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 16030300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 16130300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 16230300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 16330300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 16430300Sjoerg 16525944Sjoerg/* states are named and numbered according to RFC 1661 */ 16625944Sjoerg#define STATE_INITIAL 0 16725944Sjoerg#define STATE_STARTING 1 16825944Sjoerg#define STATE_CLOSED 2 16925944Sjoerg#define STATE_STOPPED 3 17025944Sjoerg#define STATE_CLOSING 4 17125944Sjoerg#define STATE_STOPPING 5 17225944Sjoerg#define STATE_REQ_SENT 6 17325944Sjoerg#define STATE_ACK_RCVD 7 17425944Sjoerg#define STATE_ACK_SENT 8 17525944Sjoerg#define STATE_OPENED 9 17625944Sjoerg 177227293Sedstatic MALLOC_DEFINE(M_SPPP, "sppp", "synchronous PPP interface internals"); 178147256Sbrooks 1794910Swollmanstruct ppp_header { 18011189Sjkh u_char address; 18111189Sjkh u_char control; 18211189Sjkh u_short protocol; 183103842Salfred} __packed; 1844910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 1854910Swollman 1864910Swollmanstruct lcp_header { 18711189Sjkh u_char type; 18811189Sjkh u_char ident; 18911189Sjkh u_short len; 190103842Salfred} __packed; 1914910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 1924910Swollman 1934910Swollmanstruct cisco_packet { 19411189Sjkh u_long type; 19511189Sjkh u_long par1; 19611189Sjkh u_long par2; 19711189Sjkh u_short rel; 19811189Sjkh u_short time0; 19911189Sjkh u_short time1; 200103842Salfred} __packed; 20188704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 2024910Swollman 20325944Sjoerg/* 20425944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 20525944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 20625944Sjoerg * case you can't make sense out of these abbreviation; it will also 20725944Sjoerg * explain the semantics related to the various events and actions. 20825944Sjoerg */ 20925944Sjoergstruct cp { 21025944Sjoerg u_short proto; /* PPP control protocol number */ 21125944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 21225944Sjoerg u_char flags; 21325944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 21425944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 21525944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 21625944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 21725944Sjoerg const char *name; /* name of this control protocol */ 21825944Sjoerg /* event handlers */ 21925944Sjoerg void (*Up)(struct sppp *sp); 22025944Sjoerg void (*Down)(struct sppp *sp); 22125944Sjoerg void (*Open)(struct sppp *sp); 22225944Sjoerg void (*Close)(struct sppp *sp); 22325944Sjoerg void (*TO)(void *sp); 22425944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 22525944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 22625944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 22725944Sjoerg /* actions */ 22825944Sjoerg void (*tlu)(struct sppp *sp); 22925944Sjoerg void (*tld)(struct sppp *sp); 23025944Sjoerg void (*tls)(struct sppp *sp); 23125944Sjoerg void (*tlf)(struct sppp *sp); 23225944Sjoerg void (*scr)(struct sppp *sp); 23325944Sjoerg}; 23425944Sjoerg 23540008Sjoerg#define SPP_FMT "%s: " 23640008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 23740008Sjoerg 238188668Srwatson#define SPPP_LOCK(sp) mtx_lock (&(sp)->mtx) 239188668Srwatson#define SPPP_UNLOCK(sp) mtx_unlock (&(sp)->mtx) 240188668Srwatson#define SPPP_LOCK_ASSERT(sp) mtx_assert (&(sp)->mtx, MA_OWNED) 241190818Sed#define SPPP_LOCK_OWNED(sp) mtx_owned (&(sp)->mtx) 242138745Srik 24388705Sjoerg#ifdef INET 2444910Swollman/* 2454910Swollman * The following disgusting hack gets around the problem that IP TOS 2464910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2474910Swollman * priority queue. To decide if traffic is interactive, we check that 2484910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 24930300Sjoerg * 25030300Sjoerg * XXX is this really still necessary? - joerg - 2514910Swollman */ 252126910Srwatsonstatic const u_short interactive_ports[8] = { 2534910Swollman 0, 513, 0, 0, 2544910Swollman 0, 21, 0, 23, 2554910Swollman}; 2564910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 25788705Sjoerg#endif 2584910Swollman 25925944Sjoerg/* almost every function needs these */ 26025944Sjoerg#define STDDCL \ 261147256Sbrooks struct ifnet *ifp = SP2IFP(sp); \ 26225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 26311189Sjkh 26430300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 265249925Sglebius const struct sockaddr *dst, struct route *ro); 2664910Swollman 26725944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 26825944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 26925944Sjoerg 27025944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 27125944Sjoerg struct mbuf *m); 27225944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 27325944Sjoerg u_char ident, u_short len, void *data); 27442104Sphk/* static void sppp_cp_timeout(void *arg); */ 27525944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 27625944Sjoerg int newstate); 27730300Sjoergstatic void sppp_auth_send(const struct cp *cp, 27842104Sphk struct sppp *sp, unsigned int type, unsigned int id, 27930300Sjoerg ...); 28025944Sjoerg 28125944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 28225944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 28325944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 28425944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 28525944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 28625944Sjoerg 28730300Sjoergstatic void sppp_null(struct sppp *sp); 28830300Sjoerg 289138745Srikstatic void sppp_pp_up(struct sppp *sp); 290138745Srikstatic void sppp_pp_down(struct sppp *sp); 291138745Srik 29225944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 29325944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 29425944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 29525944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 29625944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 29725944Sjoergstatic void sppp_lcp_TO(void *sp); 29825944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 29925944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 30025944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 30125944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 30225944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 30325944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 30425944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 30525944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 30630300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 30730300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 30825944Sjoerg 30925944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 31025944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 31125944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 31225944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 31325944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 31425944Sjoergstatic void sppp_ipcp_TO(void *sp); 31525944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31625944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31725944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 31825944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 31925944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 32025944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 32125944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 32225944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 32325944Sjoerg 32478064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 32578064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 32678064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 32778064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 32878064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 32978064Sumestatic void sppp_ipv6cp_TO(void *sp); 33078064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33178064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33278064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33378064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 33478064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 33578064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 33678064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 33778064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 33878064Sume 33930300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 34030300Sjoergstatic void sppp_pap_init(struct sppp *sp); 34130300Sjoergstatic void sppp_pap_open(struct sppp *sp); 34230300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34330300Sjoergstatic void sppp_pap_TO(void *sp); 34430300Sjoergstatic void sppp_pap_my_TO(void *sp); 34530300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 34630300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 34730300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 34830300Sjoerg 34930300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 35030300Sjoergstatic void sppp_chap_init(struct sppp *sp); 35130300Sjoergstatic void sppp_chap_open(struct sppp *sp); 35230300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35330300Sjoergstatic void sppp_chap_TO(void *sp); 35430300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35530300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 35630300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 35730300Sjoerg 35830300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 35925944Sjoergstatic const char *sppp_cp_type_name(u_char type); 360184682Sbz#ifdef INET 36130300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 36230300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 363184682Sbz#endif 36478064Sume#ifdef INET6 36578064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 36678064Sume#endif 36725944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36825944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 36925944Sjoergstatic const char *sppp_proto_name(u_short proto); 37030300Sjoergstatic const char *sppp_state_name(int state); 37138343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37230300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37325944Sjoergstatic void sppp_keepalive(void *dummy); 37430300Sjoergstatic void sppp_phase_network(struct sppp *sp); 37530300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 37630300Sjoergstatic void sppp_print_string(const char *p, u_short len); 37725944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 378184682Sbz#ifdef INET 37925944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 380184682Sbz#endif 38178064Sume#ifdef INET6 38278064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 38378064Sume struct in6_addr *dst, struct in6_addr *srcmask); 38478064Sume#ifdef IPV6CP_MYIFID_DYN 38578064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38678064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 38778064Sume#endif 38878064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 38978064Sume#endif 39025944Sjoerg 391138745Srik/* if_start () wrapper */ 392138745Srikstatic void sppp_ifstart (struct ifnet *ifp); 393138745Srik 39425944Sjoerg/* our control protocol descriptors */ 39533181Seivindstatic const struct cp lcp = { 39625944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 39725944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 39825944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 39925944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 40025944Sjoerg sppp_lcp_scr 40125944Sjoerg}; 40225944Sjoerg 40333181Seivindstatic const struct cp ipcp = { 40488709Sjoerg PPP_IPCP, IDX_IPCP, 40588709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 40688709Sjoerg CP_NCP, 40788709Sjoerg#else 40888709Sjoerg 0, 40988709Sjoerg#endif 41088709Sjoerg "ipcp", 41125944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 41225944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 41325944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 41425944Sjoerg sppp_ipcp_scr 41525944Sjoerg}; 41625944Sjoerg 41778064Sumestatic const struct cp ipv6cp = { 41878064Sume PPP_IPV6CP, IDX_IPV6CP, 41978064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 42078064Sume CP_NCP, 42178064Sume#else 42278064Sume 0, 42378064Sume#endif 42478064Sume "ipv6cp", 42578064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 42678064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 42778064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 42878064Sume sppp_ipv6cp_scr 42978064Sume}; 43078064Sume 43133181Seivindstatic const struct cp pap = { 43230300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 43330300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 43430300Sjoerg sppp_pap_TO, 0, 0, 0, 43530300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 43630300Sjoerg sppp_pap_scr 43730300Sjoerg}; 43830300Sjoerg 43933181Seivindstatic const struct cp chap = { 44030300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 44130300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 44230300Sjoerg sppp_chap_TO, 0, 0, 0, 44330300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 44430300Sjoerg sppp_chap_scr 44530300Sjoerg}; 44630300Sjoerg 44733181Seivindstatic const struct cp *cps[IDX_COUNT] = { 44825944Sjoerg &lcp, /* IDX_LCP */ 44925944Sjoerg &ipcp, /* IDX_IPCP */ 45078064Sume &ipv6cp, /* IDX_IPV6CP */ 45130300Sjoerg &pap, /* IDX_PAP */ 45230300Sjoerg &chap, /* IDX_CHAP */ 45325944Sjoerg}; 45425944Sjoerg 455147256Sbrooksstatic void* 456147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp) 457147256Sbrooks{ 458147256Sbrooks struct sppp *sp; 459147256Sbrooks 460147256Sbrooks sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO); 461147256Sbrooks sp->pp_ifp = ifp; 462147256Sbrooks 463147256Sbrooks return (sp); 464147256Sbrooks} 465147256Sbrooks 466147256Sbrooksstatic void 467147256Sbrookssppp_free(void *com, u_char type) 468147256Sbrooks{ 469147256Sbrooks 470147256Sbrooks free(com, M_SPPP); 471147256Sbrooks} 472147256Sbrooks 47370199Sjhaystatic int 47470199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47570199Sjhay{ 47670199Sjhay switch (type) { 47770199Sjhay case MOD_LOAD: 478147256Sbrooks /* 479147256Sbrooks * XXX: should probably be IFT_SPPP, but it's fairly 480147256Sbrooks * harmless to allocate struct sppp's for non-sppp 481147256Sbrooks * interfaces. 482147256Sbrooks */ 483147256Sbrooks 484147256Sbrooks if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free); 48570199Sjhay break; 48670199Sjhay case MOD_UNLOAD: 487147256Sbrooks /* if_deregister_com_alloc(IFT_PPP); */ 48870199Sjhay return EACCES; 48970199Sjhay default: 490132199Sphk return EOPNOTSUPP; 49170199Sjhay } 49270199Sjhay return 0; 49370199Sjhay} 49470199Sjhaystatic moduledata_t spppmod = { 49570199Sjhay "sppp", 49670199Sjhay sppp_modevent, 497241394Skevlo 0 49870199Sjhay}; 49970199SjhayMODULE_VERSION(sppp, 1); 50070199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 50125944Sjoerg 50270199Sjhay/* 50325944Sjoerg * Exported functions, comprising our interface to the lower layer. 5044910Swollman */ 5054910Swollman 5064910Swollman/* 5074910Swollman * Process the received packet. 5084910Swollman */ 50925706Sjoergvoid 51025706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5114910Swollman{ 5124910Swollman struct ppp_header *h; 513111888Sjlemon int isr = -1; 514147256Sbrooks struct sppp *sp = IFP2SP(ifp); 515184682Sbz int debug, do_account = 0; 516184682Sbz#ifdef INET 517184682Sbz int hlen, vjlen; 51888700Sjoerg u_char *iphdr; 519184682Sbz#endif 5204910Swollman 521138745Srik SPPP_LOCK(sp); 522138745Srik debug = ifp->if_flags & IFF_DEBUG; 523138745Srik 5244910Swollman if (ifp->if_flags & IFF_UP) 5254910Swollman /* Count received bytes, add FCS and one flag */ 5264910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5274910Swollman 5284910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5294910Swollman /* Too small packet, drop it. */ 53025944Sjoerg if (debug) 53125706Sjoerg log(LOG_DEBUG, 53240008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 53340008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 53425944Sjoerg drop: 53588700Sjoerg m_freem (m); 536138745Srik SPPP_UNLOCK(sp); 53788700Sjoerg drop2: 53825944Sjoerg ++ifp->if_ierrors; 53925944Sjoerg ++ifp->if_iqdrops; 5404910Swollman return; 5414910Swollman } 5424910Swollman 543139365Srik if (sp->pp_mode == PP_FR) { 544139365Srik sppp_fr_input (sp, m); 545139365Srik SPPP_UNLOCK(sp); 546139365Srik return; 547139365Srik } 548139365Srik 5494910Swollman /* Get PPP header. */ 5504910Swollman h = mtod (m, struct ppp_header*); 5514910Swollman m_adj (m, PPP_HEADER_LEN); 5524910Swollman 5534910Swollman switch (h->address) { 5544910Swollman case PPP_ALLSTATIONS: 5554910Swollman if (h->control != PPP_UI) 5564910Swollman goto invalid; 55745152Sphk if (sp->pp_mode == IFF_CISCO) { 55825944Sjoerg if (debug) 55925706Sjoerg log(LOG_DEBUG, 56040008Sjoerg SPP_FMT "PPP packet in Cisco mode " 56125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 56240008Sjoerg SPP_ARGS(ifp), 56325706Sjoerg h->address, h->control, ntohs(h->protocol)); 56411189Sjkh goto drop; 56511189Sjkh } 5664910Swollman switch (ntohs (h->protocol)) { 5674910Swollman default: 56825944Sjoerg if (debug) 56925706Sjoerg log(LOG_DEBUG, 57044145Sphk SPP_FMT "rejecting protocol " 57125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 57240008Sjoerg SPP_ARGS(ifp), 57325706Sjoerg h->address, h->control, ntohs(h->protocol)); 57444145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 57544145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 57678064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 57744145Sphk &h->protocol); 5784910Swollman ++ifp->if_noproto; 5794910Swollman goto drop; 5804910Swollman case PPP_LCP: 58130300Sjoerg sppp_cp_input(&lcp, sp, m); 5824910Swollman m_freem (m); 583138745Srik SPPP_UNLOCK(sp); 5844910Swollman return; 58530300Sjoerg case PPP_PAP: 58630300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 58730300Sjoerg sppp_pap_input(sp, m); 58830300Sjoerg m_freem (m); 589138745Srik SPPP_UNLOCK(sp); 59030300Sjoerg return; 59130300Sjoerg case PPP_CHAP: 59230300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 59330300Sjoerg sppp_chap_input(sp, m); 59430300Sjoerg m_freem (m); 595138745Srik SPPP_UNLOCK(sp); 59630300Sjoerg return; 5974910Swollman#ifdef INET 5984910Swollman case PPP_IPCP: 59925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 60030300Sjoerg sppp_cp_input(&ipcp, sp, m); 6014910Swollman m_freem (m); 602138745Srik SPPP_UNLOCK(sp); 6034910Swollman return; 6044910Swollman case PPP_IP: 60525944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 606111888Sjlemon isr = NETISR_IP; 6074910Swollman } 60888577Sjoerg do_account++; 6094910Swollman break; 61088534Sjoerg case PPP_VJ_COMP: 61188534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 61288700Sjoerg if ((vjlen = 61388700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 61488700Sjoerg m->m_len, m->m_len, 61588700Sjoerg TYPE_COMPRESSED_TCP, 61688700Sjoerg sp->pp_comp, 61788700Sjoerg &iphdr, &hlen)) <= 0) { 61888700Sjoerg if (debug) 61988700Sjoerg log(LOG_INFO, 62088700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 62188700Sjoerg SPP_ARGS(ifp)); 62288534Sjoerg goto drop; 62388700Sjoerg } 62488700Sjoerg 62588700Sjoerg /* 62688700Sjoerg * Trim the VJ header off the packet, and prepend 62788700Sjoerg * the uncompressed IP header (which will usually 62888700Sjoerg * end up in two chained mbufs since there's not 62988700Sjoerg * enough leading space in the existing mbuf). 63088700Sjoerg */ 63188700Sjoerg m_adj(m, vjlen); 632243882Sglebius M_PREPEND(m, hlen, M_NOWAIT); 633138745Srik if (m == NULL) { 634138745Srik SPPP_UNLOCK(sp); 63588700Sjoerg goto drop2; 636138745Srik } 63788700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 638111888Sjlemon isr = NETISR_IP; 63988534Sjoerg } 64088599Sjoerg do_account++; 64188534Sjoerg break; 64288534Sjoerg case PPP_VJ_UCOMP: 64388534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 64488700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 64588700Sjoerg m->m_len, m->m_len, 64688700Sjoerg TYPE_UNCOMPRESSED_TCP, 64788700Sjoerg sp->pp_comp, 64888700Sjoerg &iphdr, &hlen) != 0) { 64988700Sjoerg if (debug) 65088700Sjoerg log(LOG_INFO, 65188700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 65288700Sjoerg SPP_ARGS(ifp)); 65388534Sjoerg goto drop; 65488700Sjoerg } 655111888Sjlemon isr = NETISR_IP; 65688534Sjoerg } 65788599Sjoerg do_account++; 65888534Sjoerg break; 65978064Sume#endif 66088599Sjoerg#ifdef INET6 66188599Sjoerg case PPP_IPV6CP: 66288599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 66388599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 66488599Sjoerg m_freem (m); 665138745Srik SPPP_UNLOCK(sp); 66688599Sjoerg return; 66788599Sjoerg 66888599Sjoerg case PPP_IPV6: 669111888Sjlemon if (sp->state[IDX_IPV6CP] == STATE_OPENED) 670111888Sjlemon isr = NETISR_IPV6; 67188599Sjoerg do_account++; 67288599Sjoerg break; 67388599Sjoerg#endif 67412495Speter#ifdef IPX 67512495Speter case PPP_IPX: 67612495Speter /* IPX IPXCP not implemented yet */ 677111888Sjlemon if (sp->pp_phase == PHASE_NETWORK) 678111888Sjlemon isr = NETISR_IPX; 67988577Sjoerg do_account++; 68012495Speter break; 68112495Speter#endif 6824910Swollman } 6834910Swollman break; 6844910Swollman case CISCO_MULTICAST: 6854910Swollman case CISCO_UNICAST: 6864910Swollman /* Don't check the control field here (RFC 1547). */ 68745152Sphk if (sp->pp_mode != IFF_CISCO) { 68825944Sjoerg if (debug) 68925706Sjoerg log(LOG_DEBUG, 69040008Sjoerg SPP_FMT "Cisco packet in PPP mode " 69125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 69240008Sjoerg SPP_ARGS(ifp), 69325706Sjoerg h->address, h->control, ntohs(h->protocol)); 69411189Sjkh goto drop; 69511189Sjkh } 6964910Swollman switch (ntohs (h->protocol)) { 6974910Swollman default: 6984910Swollman ++ifp->if_noproto; 6994910Swollman goto invalid; 7004910Swollman case CISCO_KEEPALIVE: 701147256Sbrooks sppp_cisco_input (sp, m); 7024910Swollman m_freem (m); 703138745Srik SPPP_UNLOCK(sp); 7044910Swollman return; 7054910Swollman#ifdef INET 7064910Swollman case ETHERTYPE_IP: 707111888Sjlemon isr = NETISR_IP; 70888577Sjoerg do_account++; 7094910Swollman break; 7104910Swollman#endif 71154263Sshin#ifdef INET6 71254263Sshin case ETHERTYPE_IPV6: 713111888Sjlemon isr = NETISR_IPV6; 71488577Sjoerg do_account++; 71554263Sshin break; 71654263Sshin#endif 71712495Speter#ifdef IPX 71812495Speter case ETHERTYPE_IPX: 719111888Sjlemon isr = NETISR_IPX; 72088577Sjoerg do_account++; 72112495Speter break; 72212495Speter#endif 7234910Swollman } 7244910Swollman break; 72525944Sjoerg default: /* Invalid PPP packet. */ 72625944Sjoerg invalid: 72725944Sjoerg if (debug) 72825944Sjoerg log(LOG_DEBUG, 72940008Sjoerg SPP_FMT "invalid input packet " 73025944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 73140008Sjoerg SPP_ARGS(ifp), 73225944Sjoerg h->address, h->control, ntohs(h->protocol)); 73325944Sjoerg goto drop; 7344910Swollman } 7354910Swollman 736111888Sjlemon if (! (ifp->if_flags & IFF_UP) || isr == -1) 7374910Swollman goto drop; 7384910Swollman 739138745Srik SPPP_UNLOCK(sp); 740223741Sbz M_SETFIB(m, ifp->if_fib); 7414910Swollman /* Check queue. */ 742134391Sandre if (netisr_queue(isr, m)) { /* (0) on success. */ 74325944Sjoerg if (debug) 74440008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 74540008Sjoerg SPP_ARGS(ifp)); 746131241Srik goto drop2; 7474910Swollman } 748138745Srik 74988577Sjoerg if (do_account) 75088577Sjoerg /* 75188577Sjoerg * Do only account for network packets, not for control 75288577Sjoerg * packets. This is used by some subsystems to detect 75388577Sjoerg * idle lines. 75488577Sjoerg */ 755150349Sandre sp->pp_last_recv = time_uptime; 7564910Swollman} 7574910Swollman 758138745Srikstatic void 759138745Sriksppp_ifstart_sched(void *dummy) 760138745Srik{ 761138745Srik struct sppp *sp = dummy; 762138745Srik 763147256Sbrooks sp->if_start(SP2IFP(sp)); 764138745Srik} 765138745Srik 766138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for 767138745Srik * execution. We can't call it directly 768138745Srik */ 769138745Srikstatic void 770138745Sriksppp_ifstart(struct ifnet *ifp) 771138745Srik{ 772147256Sbrooks struct sppp *sp = IFP2SP(ifp); 773138745Srik 774138745Srik if (SPPP_LOCK_OWNED(sp)) { 775138745Srik if (callout_pending(&sp->ifstart_callout)) 776138745Srik return; 777138745Srik callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched, 778138745Srik (void *)sp); 779138745Srik } else { 780138745Srik sp->if_start(ifp); 781138745Srik } 782138745Srik} 783138745Srik 7844910Swollman/* 7854910Swollman * Enqueue transmit packet. 7864910Swollman */ 78712820Sphkstatic int 788249925Sglebiussppp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 789249925Sglebius struct route *ro) 7904910Swollman{ 791147256Sbrooks struct sppp *sp = IFP2SP(ifp); 7924910Swollman struct ppp_header *h; 79378064Sume struct ifqueue *ifq = NULL; 794241686Sandre int error, rv = 0; 795184682Sbz#ifdef INET 79688534Sjoerg int ipproto = PPP_IP; 797184682Sbz#endif 79842066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7994910Swollman 800138745Srik SPPP_LOCK(sp); 80125944Sjoerg 802148887Srwatson if (!(ifp->if_flags & IFF_UP) || 803148887Srwatson (!(ifp->if_flags & IFF_AUTO) && 804148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING))) { 80588723Sjoerg#ifdef INET6 80688723Sjoerg drop: 80788723Sjoerg#endif 8084910Swollman m_freem (m); 809138745Srik SPPP_UNLOCK(sp); 8104910Swollman return (ENETDOWN); 8114910Swollman } 8124910Swollman 813148887Srwatson if ((ifp->if_flags & IFF_AUTO) && 814148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 81588723Sjoerg#ifdef INET6 81625944Sjoerg /* 81788723Sjoerg * XXX 81888723Sjoerg * 81988723Sjoerg * Hack to prevent the initialization-time generated 82088723Sjoerg * IPv6 multicast packet to erroneously cause a 82188723Sjoerg * dialout event in case IPv6 has been 82288723Sjoerg * administratively disabled on that interface. 82388723Sjoerg */ 82488723Sjoerg if (dst->sa_family == AF_INET6 && 82588723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 82688723Sjoerg goto drop; 82788723Sjoerg#endif 82888723Sjoerg /* 82925944Sjoerg * Interface is not yet running, but auto-dial. Need 83025944Sjoerg * to start LCP for it. 83125944Sjoerg */ 832148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 83325944Sjoerg lcp.Open(sp); 83425944Sjoerg } 83525944Sjoerg 8364910Swollman#ifdef INET 83712436Speter if (dst->sa_family == AF_INET) { 83840008Sjoerg /* XXX Check mbuf length here? */ 83912436Speter struct ip *ip = mtod (m, struct ip*); 84012436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8414910Swollman 84242104Sphk /* 84342104Sphk * When using dynamic local IP address assignment by using 84442104Sphk * 0.0.0.0 as a local address, the first TCP session will 84542104Sphk * not connect because the local TCP checksum is computed 84642104Sphk * using 0.0.0.0 which will later become our real IP address 84742104Sphk * so the TCP checksum computed at the remote end will 84842104Sphk * become invalid. So we 84942104Sphk * - don't let packets with src ip addr 0 thru 85042104Sphk * - we flag TCP packets with src ip 0 as an error 85170199Sjhay */ 85242104Sphk 85342104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 85442104Sphk { 85542104Sphk m_freem(m); 856138745Srik SPPP_UNLOCK(sp); 85742104Sphk if(ip->ip_p == IPPROTO_TCP) 85842104Sphk return(EADDRNOTAVAIL); 85942104Sphk else 86042104Sphk return(0); 86142104Sphk } 86270199Sjhay 86342104Sphk /* 86442104Sphk * Put low delay, telnet, rlogin and ftp control packets 865130549Smlaier * in front of the queue or let ALTQ take care. 86642104Sphk */ 867130549Smlaier if (ALTQ_IS_ENABLED(&ifp->if_snd)) 86841686Sphk ; 869130549Smlaier else if (_IF_QFULL(&sp->pp_fastq)) 870130549Smlaier ; 87141686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 87212436Speter ifq = &sp->pp_fastq; 87341686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 87441686Sphk ; 87541686Sphk else if (ip->ip_p != IPPROTO_TCP) 87641686Sphk ; 87741686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 87841686Sphk ifq = &sp->pp_fastq; 87941686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 88041686Sphk ifq = &sp->pp_fastq; 88188534Sjoerg 88288534Sjoerg /* 88388534Sjoerg * Do IP Header compression 88488534Sjoerg */ 885139365Srik if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR && 886138745Srik (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP) 88788599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 88888534Sjoerg sp->ipcp.compress_cid)) { 88988534Sjoerg case TYPE_COMPRESSED_TCP: 89088534Sjoerg ipproto = PPP_VJ_COMP; 89188534Sjoerg break; 89288534Sjoerg case TYPE_UNCOMPRESSED_TCP: 89388534Sjoerg ipproto = PPP_VJ_UCOMP; 89488534Sjoerg break; 89588534Sjoerg case TYPE_IP: 89688534Sjoerg ipproto = PPP_IP; 89788534Sjoerg break; 89888534Sjoerg default: 89988534Sjoerg m_freem(m); 900138745Srik SPPP_UNLOCK(sp); 90188534Sjoerg return (EINVAL); 90288534Sjoerg } 9034910Swollman } 9044910Swollman#endif 9054910Swollman 90678064Sume#ifdef INET6 90778064Sume if (dst->sa_family == AF_INET6) { 90878064Sume /* XXX do something tricky here? */ 90978064Sume } 91078064Sume#endif 91178064Sume 912139365Srik if (sp->pp_mode == PP_FR) { 913139365Srik /* Add frame relay header. */ 914139365Srik m = sppp_fr_header (sp, m, dst->sa_family); 915139365Srik if (! m) 916139365Srik goto nobufs; 917139365Srik goto out; 918139365Srik } 919139365Srik 9204910Swollman /* 9214910Swollman * Prepend general data packet PPP header. For now, IP only. 9224910Swollman */ 923243882Sglebius M_PREPEND (m, PPP_HEADER_LEN, M_NOWAIT); 9244910Swollman if (! m) { 925139365Sriknobufs: if (debug) 92640008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 92740008Sjoerg SPP_ARGS(ifp)); 92825944Sjoerg ++ifp->if_oerrors; 929138745Srik SPPP_UNLOCK(sp); 9304910Swollman return (ENOBUFS); 9314910Swollman } 93240008Sjoerg /* 93340008Sjoerg * May want to check size of packet 93440008Sjoerg * (albeit due to the implementation it's always enough) 93540008Sjoerg */ 9364910Swollman h = mtod (m, struct ppp_header*); 93745152Sphk if (sp->pp_mode == IFF_CISCO) { 93828088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9394910Swollman h->control = 0; 9404910Swollman } else { 9414910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9424910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9434910Swollman } 9444910Swollman 9454910Swollman switch (dst->sa_family) { 9464910Swollman#ifdef INET 9474910Swollman case AF_INET: /* Internet Protocol */ 94845152Sphk if (sp->pp_mode == IFF_CISCO) 94911189Sjkh h->protocol = htons (ETHERTYPE_IP); 95011189Sjkh else { 95125955Sjoerg /* 95225955Sjoerg * Don't choke with an ENETDOWN early. It's 95325955Sjoerg * possible that we just started dialing out, 95425955Sjoerg * so don't drop the packet immediately. If 95525955Sjoerg * we notice that we run out of buffer space 95625955Sjoerg * below, we will however remember that we are 95725955Sjoerg * not ready to carry IP packets, and return 95825955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 95925955Sjoerg */ 96088534Sjoerg h->protocol = htons(ipproto); 96125955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 96225955Sjoerg rv = ENETDOWN; 96311189Sjkh } 9644910Swollman break; 9654910Swollman#endif 96654263Sshin#ifdef INET6 96754263Sshin case AF_INET6: /* Internet Protocol */ 96854263Sshin if (sp->pp_mode == IFF_CISCO) 96954263Sshin h->protocol = htons (ETHERTYPE_IPV6); 97054263Sshin else { 97178064Sume /* 97278064Sume * Don't choke with an ENETDOWN early. It's 97378064Sume * possible that we just started dialing out, 97478064Sume * so don't drop the packet immediately. If 97578064Sume * we notice that we run out of buffer space 97678064Sume * below, we will however remember that we are 97778064Sume * not ready to carry IP packets, and return 97878064Sume * ENETDOWN, as opposed to ENOBUFS. 97978064Sume */ 98078064Sume h->protocol = htons(PPP_IPV6); 98178064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 98278064Sume rv = ENETDOWN; 98354263Sshin } 98454263Sshin break; 98554263Sshin#endif 98611819Sjulian#ifdef IPX 98712495Speter case AF_IPX: /* Novell IPX Protocol */ 98845152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 98912495Speter ETHERTYPE_IPX : PPP_IPX); 99011819Sjulian break; 99111819Sjulian#endif 9924910Swollman default: 9934910Swollman m_freem (m); 99425944Sjoerg ++ifp->if_oerrors; 995138745Srik SPPP_UNLOCK(sp); 9964910Swollman return (EAFNOSUPPORT); 9974910Swollman } 9984910Swollman 9994910Swollman /* 10004910Swollman * Queue message on interface, and start output if interface 100188577Sjoerg * not yet active. 10024910Swollman */ 1003139365Srikout: 1004130549Smlaier if (ifq != NULL) 1005130549Smlaier error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 1006130549Smlaier else 1007130549Smlaier IFQ_HANDOFF_ADJ(ifp, m, 3, error); 1008130549Smlaier if (error) { 100925944Sjoerg ++ifp->if_oerrors; 1010138745Srik SPPP_UNLOCK(sp); 101125955Sjoerg return (rv? rv: ENOBUFS); 10124910Swollman } 1013138745Srik SPPP_UNLOCK(sp); 101488577Sjoerg /* 101588577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 101688577Sjoerg * here since sppp_output() is only called on behalf of 101788577Sjoerg * network-layer traffic; control-layer traffic is handled 101888577Sjoerg * by sppp_cp_send(). 101988577Sjoerg */ 1020150349Sandre sp->pp_last_sent = time_uptime; 10214910Swollman return (0); 10224910Swollman} 10234910Swollman 102425706Sjoergvoid 102525706Sjoergsppp_attach(struct ifnet *ifp) 10264910Swollman{ 1027147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10284910Swollman 1029138745Srik /* Initialize mtx lock */ 1030138745Srik mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); 1031138745Srik 10324910Swollman /* Initialize keepalive handler. */ 1033188668Srwatson callout_init(&sp->keepalive_callout, CALLOUT_MPSAFE); 1034138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 1035138745Srik (void *)sp); 10364910Swollman 1037147256Sbrooks ifp->if_mtu = PP_MTU; 1038147256Sbrooks ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1039147256Sbrooks ifp->if_output = sppp_output; 104042104Sphk#if 0 104142064Sphk sp->pp_flags = PP_KEEPALIVE; 104242104Sphk#endif 1043147256Sbrooks ifp->if_snd.ifq_maxlen = 32; 104470199Sjhay sp->pp_fastq.ifq_maxlen = 32; 104570199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10464910Swollman sp->pp_loopcnt = 0; 10474910Swollman sp->pp_alivecnt = 0; 104878064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 104978064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 105025944Sjoerg sp->pp_phase = PHASE_DEAD; 1051138745Srik sp->pp_up = sppp_pp_up; 1052138745Srik sp->pp_down = sppp_pp_down; 105388716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 105493818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 105588716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 105693818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 1057150349Sandre sp->pp_last_recv = sp->pp_last_sent = time_uptime; 105888723Sjoerg sp->confflags = 0; 105988723Sjoerg#ifdef INET 106088723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 106188723Sjoerg#endif 106288723Sjoerg#ifdef INET6 106388723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 106488723Sjoerg#endif 1065188668Srwatson callout_init(&sp->ifstart_callout, CALLOUT_MPSAFE); 1066138745Srik sp->if_start = ifp->if_start; 1067138745Srik ifp->if_start = sppp_ifstart; 1068118072Sgj sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 106988599Sjoerg sl_compress_init(sp->pp_comp, -1); 107025944Sjoerg sppp_lcp_init(sp); 107125944Sjoerg sppp_ipcp_init(sp); 107278064Sume sppp_ipv6cp_init(sp); 107330300Sjoerg sppp_pap_init(sp); 107430300Sjoerg sppp_chap_init(sp); 10754910Swollman} 10764910Swollman 107730300Sjoergvoid 107825706Sjoergsppp_detach(struct ifnet *ifp) 10794910Swollman{ 1080147256Sbrooks struct sppp *sp = IFP2SP(ifp); 108125944Sjoerg int i; 10824910Swollman 1083138745Srik KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized")); 10844910Swollman 10854910Swollman /* Stop keepalive handler. */ 1086138745Srik if (!callout_drain(&sp->keepalive_callout)) 1087138745Srik callout_stop(&sp->keepalive_callout); 108825944Sjoerg 1089138745Srik for (i = 0; i < IDX_COUNT; i++) { 1090138745Srik if (!callout_drain(&sp->ch[i])) 1091138745Srik callout_stop(&sp->ch[i]); 1092138745Srik } 1093138745Srik if (!callout_drain(&sp->pap_my_to_ch)) 1094138745Srik callout_stop(&sp->pap_my_to_ch); 109569152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 109669152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 1097138745Srik mtx_destroy(&sp->mtx); 10984910Swollman} 10994910Swollman 11004910Swollman/* 11014910Swollman * Flush the interface output queue. 11024910Swollman */ 1103138745Srikstatic void 1104138745Sriksppp_flush_unlocked(struct ifnet *ifp) 11054910Swollman{ 1106147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11074910Swollman 1108147256Sbrooks sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd); 110925944Sjoerg sppp_qflush (&sp->pp_fastq); 111026018Sjoerg sppp_qflush (&sp->pp_cpq); 11114910Swollman} 11124910Swollman 1113138745Srikvoid 1114138745Sriksppp_flush(struct ifnet *ifp) 1115138745Srik{ 1116147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1117138745Srik 1118138745Srik SPPP_LOCK(sp); 1119138745Srik sppp_flush_unlocked (ifp); 1120138745Srik SPPP_UNLOCK(sp); 1121138745Srik} 1122138745Srik 11234910Swollman/* 112411189Sjkh * Check if the output queue is empty. 112511189Sjkh */ 112612820Sphkint 112725706Sjoergsppp_isempty(struct ifnet *ifp) 112811189Sjkh{ 1129147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1130241686Sandre int empty; 113111189Sjkh 1132138745Srik SPPP_LOCK(sp); 113326018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1134147256Sbrooks !SP2IFP(sp)->if_snd.ifq_head; 1135138745Srik SPPP_UNLOCK(sp); 113611189Sjkh return (empty); 113711189Sjkh} 113811189Sjkh 113911189Sjkh/* 11404910Swollman * Get next packet to send. 11414910Swollman */ 114225706Sjoergstruct mbuf * 114325706Sjoergsppp_dequeue(struct ifnet *ifp) 11444910Swollman{ 1145147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11464910Swollman struct mbuf *m; 11474910Swollman 1148138745Srik SPPP_LOCK(sp); 114926018Sjoerg /* 115030300Sjoerg * Process only the control protocol queue until we have at 115130300Sjoerg * least one NCP open. 115226018Sjoerg * 115326018Sjoerg * Do always serve all three queues in Cisco mode. 115426018Sjoerg */ 115526018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 115626018Sjoerg if (m == NULL && 1157139365Srik (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO || 1158139365Srik sp->pp_mode == PP_FR)) { 115926018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 116026018Sjoerg if (m == NULL) 1161147256Sbrooks IF_DEQUEUE (&SP2IFP(sp)->if_snd, m); 116226018Sjoerg } 1163138745Srik SPPP_UNLOCK(sp); 116426018Sjoerg return m; 11654910Swollman} 11664910Swollman 11674910Swollman/* 116830300Sjoerg * Pick the next packet, do not remove it from the queue. 116930300Sjoerg */ 117030300Sjoergstruct mbuf * 117130300Sjoergsppp_pick(struct ifnet *ifp) 117230300Sjoerg{ 1173147256Sbrooks struct sppp *sp = IFP2SP(ifp); 117430300Sjoerg struct mbuf *m; 117530300Sjoerg 1176138745Srik SPPP_LOCK(sp); 117730300Sjoerg 117830300Sjoerg m = sp->pp_cpq.ifq_head; 117930300Sjoerg if (m == NULL && 1180138745Srik (sp->pp_phase == PHASE_NETWORK || 1181139365Srik sp->pp_mode == IFF_CISCO || 1182139365Srik sp->pp_mode == PP_FR)) 118330300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 1184147256Sbrooks m = SP2IFP(sp)->if_snd.ifq_head; 1185138745Srik SPPP_UNLOCK(sp); 118630300Sjoerg return (m); 118730300Sjoerg} 118830300Sjoerg 118930300Sjoerg/* 119025944Sjoerg * Process an ioctl request. Called on low priority level. 11914910Swollman */ 119225944Sjoergint 119342104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 11944910Swollman{ 119525944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 1196147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1197241686Sandre int rv, going_up, going_down, newmode; 11984910Swollman 1199138745Srik SPPP_LOCK(sp); 120030300Sjoerg rv = 0; 120125944Sjoerg switch (cmd) { 120225944Sjoerg case SIOCAIFADDR: 120325944Sjoerg break; 12044910Swollman 120525944Sjoerg case SIOCSIFADDR: 120688503Sjoerg /* set the interface "up" when assigning an IP address */ 120788503Sjoerg ifp->if_flags |= IFF_UP; 1208102412Scharnier /* FALLTHROUGH */ 120911189Sjkh 121025944Sjoerg case SIOCSIFFLAGS: 121125944Sjoerg going_up = ifp->if_flags & IFF_UP && 1212148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 121325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1214148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 121545152Sphk 121645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 121745152Sphk if (!newmode) 121845152Sphk newmode = ifp->if_flags & IFF_AUTO; 121945152Sphk if (!newmode) 122045152Sphk newmode = ifp->if_flags & IFF_CISCO; 122145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 122245152Sphk ifp->if_flags |= newmode; 122345152Sphk 1224139365Srik if (!newmode) 1225139365Srik newmode = sp->pp_flags & PP_FR; 1226139365Srik 122745152Sphk if (newmode != sp->pp_mode) { 122845152Sphk going_down = 1; 122945152Sphk if (!going_up) 1230148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12314910Swollman } 12324910Swollman 123345152Sphk if (going_down) { 1234139365Srik if (sp->pp_mode != IFF_CISCO && 1235139365Srik sp->pp_mode != PP_FR) 123645152Sphk lcp.Close(sp); 123745152Sphk else if (sp->pp_tlf) 123845152Sphk (sp->pp_tlf)(sp); 1239138745Srik sppp_flush_unlocked(ifp); 1240148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 124145152Sphk sp->pp_mode = newmode; 124226018Sjoerg } 12434910Swollman 124445152Sphk if (going_up) { 1245139365Srik if (sp->pp_mode != IFF_CISCO && 1246139365Srik sp->pp_mode != PP_FR) 124745152Sphk lcp.Close(sp); 124845152Sphk sp->pp_mode = newmode; 124945152Sphk if (sp->pp_mode == 0) { 1250148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 125145152Sphk lcp.Open(sp); 125245152Sphk } 1253139365Srik if ((sp->pp_mode == IFF_CISCO) || 1254139365Srik (sp->pp_mode == PP_FR)) { 125545152Sphk if (sp->pp_tls) 125645152Sphk (sp->pp_tls)(sp); 1257148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 125845152Sphk } 125945152Sphk } 126045152Sphk 12614910Swollman break; 126211189Sjkh 126325944Sjoerg#ifdef SIOCSIFMTU 126425944Sjoerg#ifndef ifr_mtu 126525944Sjoerg#define ifr_mtu ifr_metric 126625944Sjoerg#endif 126725944Sjoerg case SIOCSIFMTU: 126825944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 126925944Sjoerg return (EINVAL); 127025944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12714910Swollman break; 127225944Sjoerg#endif 127325944Sjoerg#ifdef SLIOCSETMTU 127425944Sjoerg case SLIOCSETMTU: 127525944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 127625944Sjoerg return (EINVAL); 127725944Sjoerg ifp->if_mtu = *(short*)data; 12784910Swollman break; 127925944Sjoerg#endif 128025944Sjoerg#ifdef SIOCGIFMTU 128125944Sjoerg case SIOCGIFMTU: 128225944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 128311189Sjkh break; 128425944Sjoerg#endif 128525944Sjoerg#ifdef SLIOCGETMTU 128625944Sjoerg case SLIOCGETMTU: 128725944Sjoerg *(short*)data = ifp->if_mtu; 12884910Swollman break; 128925944Sjoerg#endif 129025944Sjoerg case SIOCADDMULTI: 129125944Sjoerg case SIOCDELMULTI: 12924910Swollman break; 129311189Sjkh 129430300Sjoerg case SIOCGIFGENERIC: 129530300Sjoerg case SIOCSIFGENERIC: 129630300Sjoerg rv = sppp_params(sp, cmd, data); 129730300Sjoerg break; 129830300Sjoerg 129925944Sjoerg default: 130030300Sjoerg rv = ENOTTY; 13014910Swollman } 1302138745Srik SPPP_UNLOCK(sp); 130330300Sjoerg return rv; 13044910Swollman} 13054910Swollman 130670199Sjhay/* 130725944Sjoerg * Cisco framing implementation. 130825944Sjoerg */ 130925944Sjoerg 13104910Swollman/* 13114910Swollman * Handle incoming Cisco keepalive protocol packets. 13124910Swollman */ 131330300Sjoergstatic void 131425706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 13154910Swollman{ 131625944Sjoerg STDDCL; 13174910Swollman struct cisco_packet *h; 131830300Sjoerg u_long me, mymask; 13194910Swollman 132027929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 132125706Sjoerg if (debug) 132225706Sjoerg log(LOG_DEBUG, 132340008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 132440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13254910Swollman return; 13264910Swollman } 13274910Swollman h = mtod (m, struct cisco_packet*); 132825706Sjoerg if (debug) 132925706Sjoerg log(LOG_DEBUG, 133040008Sjoerg SPP_FMT "cisco input: %d bytes " 133125706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 133240008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 133340008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 133440008Sjoerg (u_int)h->time0, (u_int)h->time1); 13354910Swollman switch (ntohl (h->type)) { 13364910Swollman default: 133725706Sjoerg if (debug) 133869211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 133940008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 13404910Swollman break; 13414910Swollman case CISCO_ADDR_REPLY: 13424910Swollman /* Reply on address request, ignore */ 13434910Swollman break; 13444910Swollman case CISCO_KEEPALIVE_REQ: 13454910Swollman sp->pp_alivecnt = 0; 134678064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 134778064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13484910Swollman /* Local and remote sequence numbers are equal. 13494910Swollman * Probably, the line is in loopback mode. */ 135011189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 135140008Sjoerg printf (SPP_FMT "loopback\n", 135240008Sjoerg SPP_ARGS(ifp)); 135311189Sjkh sp->pp_loopcnt = 0; 135411189Sjkh if (ifp->if_flags & IFF_UP) { 135511189Sjkh if_down (ifp); 135626018Sjoerg sppp_qflush (&sp->pp_cpq); 135711189Sjkh } 135811189Sjkh } 13594910Swollman ++sp->pp_loopcnt; 13604910Swollman 13614910Swollman /* Generate new local sequence number */ 136278064Sume sp->pp_seq[IDX_LCP] = random(); 136311189Sjkh break; 136411189Sjkh } 136530300Sjoerg sp->pp_loopcnt = 0; 136611189Sjkh if (! (ifp->if_flags & IFF_UP) && 1367148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 136830300Sjoerg if_up(ifp); 136940008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 137011189Sjkh } 13714910Swollman break; 13724910Swollman case CISCO_ADDR_REQ: 137330300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 137430300Sjoerg if (me != 0L) 137530300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13764910Swollman break; 13774910Swollman } 13784910Swollman} 13794910Swollman 13804910Swollman/* 138125944Sjoerg * Send Cisco keepalive packet. 13824910Swollman */ 138312820Sphkstatic void 138425944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 138525944Sjoerg{ 138625944Sjoerg STDDCL; 138725944Sjoerg struct ppp_header *h; 138825944Sjoerg struct cisco_packet *ch; 138925944Sjoerg struct mbuf *m; 139035029Sphk struct timeval tv; 139125944Sjoerg 139236119Sphk getmicrouptime(&tv); 139370199Sjhay 1394243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 139525944Sjoerg if (! m) 139625944Sjoerg return; 139725944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 139825944Sjoerg m->m_pkthdr.rcvif = 0; 139925944Sjoerg 140025944Sjoerg h = mtod (m, struct ppp_header*); 140125944Sjoerg h->address = CISCO_MULTICAST; 140225944Sjoerg h->control = 0; 140325944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 140425944Sjoerg 140525944Sjoerg ch = (struct cisco_packet*) (h + 1); 140625944Sjoerg ch->type = htonl (type); 140725944Sjoerg ch->par1 = htonl (par1); 140825944Sjoerg ch->par2 = htonl (par2); 140925944Sjoerg ch->rel = -1; 141040008Sjoerg 141135029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 141235029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 141325944Sjoerg 141425944Sjoerg if (debug) 141525944Sjoerg log(LOG_DEBUG, 141640008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 141740008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 141840008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 141925944Sjoerg 142069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 142169152Sjlemon ifp->if_oerrors++; 142225944Sjoerg} 142325944Sjoerg 142470199Sjhay/* 142525944Sjoerg * PPP protocol implementation. 142625944Sjoerg */ 142725944Sjoerg 142825944Sjoerg/* 142925944Sjoerg * Send PPP control protocol packet. 143025944Sjoerg */ 143125944Sjoergstatic void 143225706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 143325706Sjoerg u_char ident, u_short len, void *data) 14344910Swollman{ 143525944Sjoerg STDDCL; 14364910Swollman struct ppp_header *h; 14374910Swollman struct lcp_header *lh; 14384910Swollman struct mbuf *m; 14394910Swollman 14404910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14414910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1442243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 14434910Swollman if (! m) 14444910Swollman return; 14454910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14464910Swollman m->m_pkthdr.rcvif = 0; 14474910Swollman 14484910Swollman h = mtod (m, struct ppp_header*); 14494910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14504910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14514910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14524910Swollman 14534910Swollman lh = (struct lcp_header*) (h + 1); 14544910Swollman lh->type = type; 14554910Swollman lh->ident = ident; 14564910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14574910Swollman if (len) 14584910Swollman bcopy (data, lh+1, len); 14594910Swollman 146025706Sjoerg if (debug) { 146140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 146240008Sjoerg SPP_ARGS(ifp), 146325944Sjoerg sppp_proto_name(proto), 146425944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 146525944Sjoerg ntohs (lh->len)); 146644145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 146769211Sphk log(-1, ">\n"); 14684910Swollman } 146969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 147069152Sjlemon ifp->if_oerrors++; 14714910Swollman} 14724910Swollman 14734910Swollman/* 147425944Sjoerg * Handle incoming PPP control protocol packets. 14754910Swollman */ 147612820Sphkstatic void 147725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14784910Swollman{ 147925944Sjoerg STDDCL; 148025944Sjoerg struct lcp_header *h; 148125944Sjoerg int len = m->m_pkthdr.len; 148225944Sjoerg int rv; 148325944Sjoerg u_char *p; 14844910Swollman 148525944Sjoerg if (len < 4) { 148625944Sjoerg if (debug) 148725944Sjoerg log(LOG_DEBUG, 148840008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 148940008Sjoerg SPP_ARGS(ifp), cp->name, len); 14904910Swollman return; 149125944Sjoerg } 149225944Sjoerg h = mtod (m, struct lcp_header*); 149325944Sjoerg if (debug) { 149425944Sjoerg log(LOG_DEBUG, 149540008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 149640008Sjoerg SPP_ARGS(ifp), cp->name, 149725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 149825944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 149944145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 150069211Sphk log(-1, ">\n"); 150125944Sjoerg } 150225944Sjoerg if (len > ntohs (h->len)) 150325944Sjoerg len = ntohs (h->len); 150430300Sjoerg p = (u_char *)(h + 1); 150525944Sjoerg switch (h->type) { 150625944Sjoerg case CONF_REQ: 150725944Sjoerg if (len < 4) { 150825944Sjoerg if (debug) 150969211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 151040008Sjoerg SPP_ARGS(ifp), cp->name, 151125944Sjoerg len); 151225944Sjoerg ++ifp->if_ierrors; 151325944Sjoerg break; 151425944Sjoerg } 151530300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 151630300Sjoerg switch (sp->state[cp->protoidx]) { 151730300Sjoerg case STATE_CLOSING: 151830300Sjoerg case STATE_STOPPING: 151930300Sjoerg return; 152030300Sjoerg case STATE_CLOSED: 152130300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 152230300Sjoerg 0, 0); 152330300Sjoerg return; 152430300Sjoerg } 152525944Sjoerg rv = (cp->RCR)(sp, h, len); 152625944Sjoerg switch (sp->state[cp->protoidx]) { 152725944Sjoerg case STATE_OPENED: 152825944Sjoerg (cp->tld)(sp); 152925944Sjoerg (cp->scr)(sp); 1530102412Scharnier /* FALLTHROUGH */ 153125944Sjoerg case STATE_ACK_SENT: 153225944Sjoerg case STATE_REQ_SENT: 153370199Sjhay /* 153470199Sjhay * sppp_cp_change_state() have the side effect of 153570199Sjhay * restarting the timeouts. We want to avoid that 153670199Sjhay * if the state don't change, otherwise we won't 153770199Sjhay * ever timeout and resend a configuration request 153870199Sjhay * that got lost. 153970199Sjhay */ 154070199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 154170199Sjhay STATE_REQ_SENT)) 154270199Sjhay break; 154325944Sjoerg sppp_cp_change_state(cp, sp, rv? 154425944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 154525944Sjoerg break; 154625944Sjoerg case STATE_STOPPED: 154725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 154825944Sjoerg (cp->scr)(sp); 154925944Sjoerg sppp_cp_change_state(cp, sp, rv? 155025944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 155125944Sjoerg break; 155225944Sjoerg case STATE_ACK_RCVD: 155325944Sjoerg if (rv) { 155425944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 155525944Sjoerg if (debug) 155640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 155740008Sjoerg SPP_ARGS(ifp), 155826077Sjoerg cp->name); 155925944Sjoerg (cp->tlu)(sp); 156025944Sjoerg } else 156125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 156225944Sjoerg break; 156325944Sjoerg default: 156440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 156540008Sjoerg SPP_ARGS(ifp), cp->name, 156625944Sjoerg sppp_cp_type_name(h->type), 156725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 156825944Sjoerg ++ifp->if_ierrors; 156925944Sjoerg } 157025944Sjoerg break; 157125944Sjoerg case CONF_ACK: 157225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 157325944Sjoerg if (debug) 157469211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 157540008Sjoerg SPP_ARGS(ifp), cp->name, 157625944Sjoerg h->ident, sp->confid[cp->protoidx]); 157725944Sjoerg ++ifp->if_ierrors; 157825944Sjoerg break; 157925944Sjoerg } 158025944Sjoerg switch (sp->state[cp->protoidx]) { 158125944Sjoerg case STATE_CLOSED: 158225944Sjoerg case STATE_STOPPED: 158325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 158425944Sjoerg break; 158525944Sjoerg case STATE_CLOSING: 158625944Sjoerg case STATE_STOPPING: 158725944Sjoerg break; 158825944Sjoerg case STATE_REQ_SENT: 158925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 159025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 159125944Sjoerg break; 159225944Sjoerg case STATE_OPENED: 159325944Sjoerg (cp->tld)(sp); 1594102412Scharnier /* FALLTHROUGH */ 159525944Sjoerg case STATE_ACK_RCVD: 159625944Sjoerg (cp->scr)(sp); 159725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 159825944Sjoerg break; 159925944Sjoerg case STATE_ACK_SENT: 160025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 160125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 160225944Sjoerg if (debug) 160340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 160440008Sjoerg SPP_ARGS(ifp), cp->name); 160525944Sjoerg (cp->tlu)(sp); 160625944Sjoerg break; 160725944Sjoerg default: 160840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 160940008Sjoerg SPP_ARGS(ifp), cp->name, 161025944Sjoerg sppp_cp_type_name(h->type), 161125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 161225944Sjoerg ++ifp->if_ierrors; 161325944Sjoerg } 161425944Sjoerg break; 161525944Sjoerg case CONF_NAK: 161625944Sjoerg case CONF_REJ: 161725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 161825944Sjoerg if (debug) 161969211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 162040008Sjoerg SPP_ARGS(ifp), cp->name, 162125944Sjoerg h->ident, sp->confid[cp->protoidx]); 162225944Sjoerg ++ifp->if_ierrors; 162325944Sjoerg break; 162425944Sjoerg } 162525944Sjoerg if (h->type == CONF_NAK) 162625944Sjoerg (cp->RCN_nak)(sp, h, len); 162725944Sjoerg else /* CONF_REJ */ 162825944Sjoerg (cp->RCN_rej)(sp, h, len); 16294910Swollman 163025944Sjoerg switch (sp->state[cp->protoidx]) { 163125944Sjoerg case STATE_CLOSED: 163225944Sjoerg case STATE_STOPPED: 163325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 163425944Sjoerg break; 163525944Sjoerg case STATE_REQ_SENT: 163625944Sjoerg case STATE_ACK_SENT: 163725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 163870199Sjhay /* 163970199Sjhay * Slow things down a bit if we think we might be 164070199Sjhay * in loopback. Depend on the timeout to send the 164170199Sjhay * next configuration request. 164270199Sjhay */ 164370199Sjhay if (sp->pp_loopcnt) 164470199Sjhay break; 164525944Sjoerg (cp->scr)(sp); 164625944Sjoerg break; 164725944Sjoerg case STATE_OPENED: 164825944Sjoerg (cp->tld)(sp); 1649102412Scharnier /* FALLTHROUGH */ 165025944Sjoerg case STATE_ACK_RCVD: 165152633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 165225944Sjoerg (cp->scr)(sp); 165325944Sjoerg break; 165425944Sjoerg case STATE_CLOSING: 165525944Sjoerg case STATE_STOPPING: 165625944Sjoerg break; 165725944Sjoerg default: 165840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 165940008Sjoerg SPP_ARGS(ifp), cp->name, 166025944Sjoerg sppp_cp_type_name(h->type), 166125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166225944Sjoerg ++ifp->if_ierrors; 166325944Sjoerg } 166425944Sjoerg break; 16654910Swollman 166625944Sjoerg case TERM_REQ: 166725944Sjoerg switch (sp->state[cp->protoidx]) { 166825944Sjoerg case STATE_ACK_RCVD: 166925944Sjoerg case STATE_ACK_SENT: 167025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1671102412Scharnier /* FALLTHROUGH */ 167225944Sjoerg case STATE_CLOSED: 167325944Sjoerg case STATE_STOPPED: 167425944Sjoerg case STATE_CLOSING: 167525944Sjoerg case STATE_STOPPING: 167625944Sjoerg case STATE_REQ_SENT: 167725944Sjoerg sta: 167825944Sjoerg /* Send Terminate-Ack packet. */ 167925944Sjoerg if (debug) 168040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 168140008Sjoerg SPP_ARGS(ifp), cp->name); 168225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 168325944Sjoerg break; 168425944Sjoerg case STATE_OPENED: 168525944Sjoerg (cp->tld)(sp); 168625944Sjoerg sp->rst_counter[cp->protoidx] = 0; 168725944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 168825944Sjoerg goto sta; 168925944Sjoerg break; 169025944Sjoerg default: 169140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169240008Sjoerg SPP_ARGS(ifp), cp->name, 169325944Sjoerg sppp_cp_type_name(h->type), 169425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169525944Sjoerg ++ifp->if_ierrors; 169625944Sjoerg } 169725944Sjoerg break; 169825944Sjoerg case TERM_ACK: 169925944Sjoerg switch (sp->state[cp->protoidx]) { 170025944Sjoerg case STATE_CLOSED: 170125944Sjoerg case STATE_STOPPED: 170225944Sjoerg case STATE_REQ_SENT: 170325944Sjoerg case STATE_ACK_SENT: 170425944Sjoerg break; 170525944Sjoerg case STATE_CLOSING: 170641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 170725944Sjoerg (cp->tlf)(sp); 170825944Sjoerg break; 170925944Sjoerg case STATE_STOPPING: 171041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 171125944Sjoerg (cp->tlf)(sp); 171225944Sjoerg break; 171325944Sjoerg case STATE_ACK_RCVD: 171425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171525944Sjoerg break; 171625944Sjoerg case STATE_OPENED: 171725944Sjoerg (cp->tld)(sp); 171825944Sjoerg (cp->scr)(sp); 171925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 172025944Sjoerg break; 172125944Sjoerg default: 172240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 172340008Sjoerg SPP_ARGS(ifp), cp->name, 172425944Sjoerg sppp_cp_type_name(h->type), 172525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172625944Sjoerg ++ifp->if_ierrors; 172725944Sjoerg } 172825944Sjoerg break; 172925944Sjoerg case CODE_REJ: 173025944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 173130300Sjoerg log(LOG_INFO, 173240008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 173330300Sjoerg "danger will robinson\n", 173440008Sjoerg SPP_ARGS(ifp), cp->name, 173530300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 173625944Sjoerg switch (sp->state[cp->protoidx]) { 173725944Sjoerg case STATE_CLOSED: 173825944Sjoerg case STATE_STOPPED: 173925944Sjoerg case STATE_REQ_SENT: 174025944Sjoerg case STATE_ACK_SENT: 174125944Sjoerg case STATE_CLOSING: 174225944Sjoerg case STATE_STOPPING: 174325944Sjoerg case STATE_OPENED: 174425944Sjoerg break; 174525944Sjoerg case STATE_ACK_RCVD: 174625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174725944Sjoerg break; 174825944Sjoerg default: 174940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 175040008Sjoerg SPP_ARGS(ifp), cp->name, 175125944Sjoerg sppp_cp_type_name(h->type), 175225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 175325944Sjoerg ++ifp->if_ierrors; 175425944Sjoerg } 175525944Sjoerg break; 175680715Sume case PROTO_REJ: 175780715Sume { 175880715Sume int catastrophic; 175980715Sume const struct cp *upper; 176080715Sume int i; 176180715Sume u_int16_t proto; 176280715Sume 176380715Sume catastrophic = 0; 176480715Sume upper = NULL; 176580715Sume proto = ntohs(*((u_int16_t *)p)); 176680715Sume for (i = 0; i < IDX_COUNT; i++) { 176780715Sume if (cps[i]->proto == proto) { 176880715Sume upper = cps[i]; 176980715Sume break; 177080715Sume } 177180715Sume } 177280715Sume if (upper == NULL) 177380715Sume catastrophic++; 177480715Sume 177588508Sjoerg if (catastrophic || debug) 177688508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 177788508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 177888508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 177988508Sjoerg sppp_cp_type_name(h->type), proto, 178088508Sjoerg upper ? upper->name : "unknown", 178188508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 178280715Sume 178380715Sume /* 178480715Sume * if we got RXJ+ against conf-req, the peer does not implement 178580715Sume * this particular protocol type. terminate the protocol. 178680715Sume */ 178780715Sume if (upper && !catastrophic) { 178880715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 178980715Sume upper->Close(sp); 179080715Sume break; 179180715Sume } 179280715Sume } 179380715Sume 179480715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 179580715Sume switch (sp->state[cp->protoidx]) { 179680715Sume case STATE_CLOSED: 179780715Sume case STATE_STOPPED: 179880715Sume case STATE_REQ_SENT: 179980715Sume case STATE_ACK_SENT: 180080715Sume case STATE_CLOSING: 180180715Sume case STATE_STOPPING: 180280715Sume case STATE_OPENED: 180380715Sume break; 180480715Sume case STATE_ACK_RCVD: 180580715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 180680715Sume break; 180780715Sume default: 180880715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 180980715Sume SPP_ARGS(ifp), cp->name, 181080715Sume sppp_cp_type_name(h->type), 181180715Sume sppp_state_name(sp->state[cp->protoidx])); 181280715Sume ++ifp->if_ierrors; 181380715Sume } 181480715Sume break; 181580715Sume } 181625944Sjoerg case DISC_REQ: 181725944Sjoerg if (cp->proto != PPP_LCP) 181825944Sjoerg goto illegal; 181925944Sjoerg /* Discard the packet. */ 182025944Sjoerg break; 182125944Sjoerg case ECHO_REQ: 182225944Sjoerg if (cp->proto != PPP_LCP) 182325944Sjoerg goto illegal; 182425944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 182525944Sjoerg if (debug) 182669211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 182740008Sjoerg SPP_ARGS(ifp)); 182825944Sjoerg ++ifp->if_ierrors; 182925944Sjoerg break; 183025944Sjoerg } 183125944Sjoerg if (len < 8) { 183225944Sjoerg if (debug) 183369211Sphk log(-1, SPP_FMT "invalid lcp echo request " 183425944Sjoerg "packet length: %d bytes\n", 183540008Sjoerg SPP_ARGS(ifp), len); 183625944Sjoerg break; 183725944Sjoerg } 183844145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 183944145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 184025944Sjoerg /* Line loopback mode detected. */ 184140008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 184270199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 184325944Sjoerg if_down (ifp); 184426018Sjoerg sppp_qflush (&sp->pp_cpq); 18454910Swollman 184625944Sjoerg /* Shut down the PPP link. */ 184725944Sjoerg /* XXX */ 184825944Sjoerg lcp.Down(sp); 184925944Sjoerg lcp.Up(sp); 185025944Sjoerg break; 185125944Sjoerg } 185225944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 185325944Sjoerg if (debug) 185469211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 185540008Sjoerg SPP_ARGS(ifp)); 185625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 185725944Sjoerg break; 185825944Sjoerg case ECHO_REPLY: 185925944Sjoerg if (cp->proto != PPP_LCP) 186025944Sjoerg goto illegal; 186125944Sjoerg if (h->ident != sp->lcp.echoid) { 186225944Sjoerg ++ifp->if_ierrors; 186325944Sjoerg break; 186425944Sjoerg } 186525944Sjoerg if (len < 8) { 186625944Sjoerg if (debug) 186769211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 186825944Sjoerg "packet length: %d bytes\n", 186940008Sjoerg SPP_ARGS(ifp), len); 187025944Sjoerg break; 187125944Sjoerg } 187225944Sjoerg if (debug) 187369211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 187440008Sjoerg SPP_ARGS(ifp)); 187544145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 187644145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 187725944Sjoerg sp->pp_alivecnt = 0; 187825944Sjoerg break; 187925944Sjoerg default: 188025944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 188125944Sjoerg illegal: 188225944Sjoerg if (debug) 188369211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 188440008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 188578064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 188678064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 188725944Sjoerg ++ifp->if_ierrors; 188825944Sjoerg } 18894910Swollman} 18904910Swollman 189125944Sjoerg 18924910Swollman/* 189325944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 189425944Sjoerg * Basically, the state transition handling in the automaton. 18954910Swollman */ 189625944Sjoergstatic void 189725944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18984910Swollman{ 189925944Sjoerg STDDCL; 19004910Swollman 190125944Sjoerg if (debug) 190240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 190340008Sjoerg SPP_ARGS(ifp), cp->name, 190425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190525944Sjoerg 190625944Sjoerg switch (sp->state[cp->protoidx]) { 190725944Sjoerg case STATE_INITIAL: 190825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 190925944Sjoerg break; 191025944Sjoerg case STATE_STARTING: 191125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 191225944Sjoerg (cp->scr)(sp); 191325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 191425944Sjoerg break; 19154910Swollman default: 191640008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 191740008Sjoerg SPP_ARGS(ifp), cp->name, 191825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 191925944Sjoerg } 192025944Sjoerg} 19214910Swollman 192225944Sjoergstatic void 192325944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 192425944Sjoerg{ 192525944Sjoerg STDDCL; 192625944Sjoerg 192725944Sjoerg if (debug) 192840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 192940008Sjoerg SPP_ARGS(ifp), cp->name, 193025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 193125944Sjoerg 193225944Sjoerg switch (sp->state[cp->protoidx]) { 193325944Sjoerg case STATE_CLOSED: 193425944Sjoerg case STATE_CLOSING: 193525944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19364910Swollman break; 193725944Sjoerg case STATE_STOPPED: 193841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 193925944Sjoerg (cp->tls)(sp); 194041881Sphk break; 194125944Sjoerg case STATE_STOPPING: 194225944Sjoerg case STATE_REQ_SENT: 194325944Sjoerg case STATE_ACK_RCVD: 194425944Sjoerg case STATE_ACK_SENT: 194525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 194625944Sjoerg break; 194725944Sjoerg case STATE_OPENED: 194825944Sjoerg (cp->tld)(sp); 194925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 195025944Sjoerg break; 195125944Sjoerg default: 195240008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 195340008Sjoerg SPP_ARGS(ifp), cp->name, 195425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 195525944Sjoerg } 195625944Sjoerg} 19574910Swollman 195811189Sjkh 195925944Sjoergstatic void 196025944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 196125944Sjoerg{ 196225944Sjoerg STDDCL; 196325944Sjoerg 196425944Sjoerg if (debug) 196540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 196640008Sjoerg SPP_ARGS(ifp), cp->name, 196725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 196825944Sjoerg 196925944Sjoerg switch (sp->state[cp->protoidx]) { 197025944Sjoerg case STATE_INITIAL: 197141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 197225944Sjoerg (cp->tls)(sp); 19734910Swollman break; 197425944Sjoerg case STATE_STARTING: 197525944Sjoerg break; 197625944Sjoerg case STATE_CLOSED: 197725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 197825944Sjoerg (cp->scr)(sp); 197925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 198025944Sjoerg break; 198125944Sjoerg case STATE_STOPPED: 198274703Sjoerg /* 198374703Sjoerg * Try escaping stopped state. This seems to bite 198474703Sjoerg * people occasionally, in particular for IPCP, 198574703Sjoerg * presumably following previous IPCP negotiation 198674703Sjoerg * aborts. Somehow, we must have missed a Down event 198774703Sjoerg * which would have caused a transition into starting 198874703Sjoerg * state, so as a bandaid we force the Down event now. 198974703Sjoerg * This effectively implements (something like the) 199074703Sjoerg * `restart' option mentioned in the state transition 199174703Sjoerg * table of RFC 1661. 199274703Sjoerg */ 199374703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 199474703Sjoerg (cp->tls)(sp); 199574703Sjoerg break; 199625944Sjoerg case STATE_STOPPING: 199725944Sjoerg case STATE_REQ_SENT: 199825944Sjoerg case STATE_ACK_RCVD: 199925944Sjoerg case STATE_ACK_SENT: 200025944Sjoerg case STATE_OPENED: 200125944Sjoerg break; 200225944Sjoerg case STATE_CLOSING: 200325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 200425944Sjoerg break; 200525944Sjoerg } 200625944Sjoerg} 20074910Swollman 200825944Sjoerg 200925944Sjoergstatic void 201025944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 201125944Sjoerg{ 201225944Sjoerg STDDCL; 201325944Sjoerg 201425944Sjoerg if (debug) 201540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 201640008Sjoerg SPP_ARGS(ifp), cp->name, 201725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 201825944Sjoerg 201925944Sjoerg switch (sp->state[cp->protoidx]) { 202025944Sjoerg case STATE_INITIAL: 202125944Sjoerg case STATE_CLOSED: 202225944Sjoerg case STATE_CLOSING: 20234910Swollman break; 202425944Sjoerg case STATE_STARTING: 202541881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 202625944Sjoerg (cp->tlf)(sp); 20274910Swollman break; 202825944Sjoerg case STATE_STOPPED: 202925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20304910Swollman break; 203125944Sjoerg case STATE_STOPPING: 203225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20334910Swollman break; 203425944Sjoerg case STATE_OPENED: 203525944Sjoerg (cp->tld)(sp); 2036102412Scharnier /* FALLTHROUGH */ 203725944Sjoerg case STATE_REQ_SENT: 203825944Sjoerg case STATE_ACK_RCVD: 203925944Sjoerg case STATE_ACK_SENT: 204025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 204178064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 204278064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 204325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20444910Swollman break; 20454910Swollman } 20464910Swollman} 20474910Swollman 204825944Sjoergstatic void 204925944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 205025944Sjoerg{ 205125944Sjoerg STDDCL; 205225944Sjoerg 2053138745Srik SPPP_LOCK(sp); 205425944Sjoerg if (debug) 205540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 205640008Sjoerg SPP_ARGS(ifp), cp->name, 205725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 205825944Sjoerg sp->rst_counter[cp->protoidx]); 205925944Sjoerg 206025944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 206125944Sjoerg /* TO- event */ 206225944Sjoerg switch (sp->state[cp->protoidx]) { 206325944Sjoerg case STATE_CLOSING: 206441881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 206525944Sjoerg (cp->tlf)(sp); 206625944Sjoerg break; 206725944Sjoerg case STATE_STOPPING: 206841881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 206925944Sjoerg (cp->tlf)(sp); 207025944Sjoerg break; 207125944Sjoerg case STATE_REQ_SENT: 207225944Sjoerg case STATE_ACK_RCVD: 207325944Sjoerg case STATE_ACK_SENT: 207441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 207525944Sjoerg (cp->tlf)(sp); 207625944Sjoerg break; 207725944Sjoerg } 207825944Sjoerg else 207925944Sjoerg /* TO+ event */ 208025944Sjoerg switch (sp->state[cp->protoidx]) { 208125944Sjoerg case STATE_CLOSING: 208225944Sjoerg case STATE_STOPPING: 208378064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 208478064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2085138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2086138745Srik cp->TO, (void *)sp); 208725944Sjoerg break; 208825944Sjoerg case STATE_REQ_SENT: 208925944Sjoerg case STATE_ACK_RCVD: 209025944Sjoerg (cp->scr)(sp); 209125944Sjoerg /* sppp_cp_change_state() will restart the timer */ 209225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 209325944Sjoerg break; 209425944Sjoerg case STATE_ACK_SENT: 209525944Sjoerg (cp->scr)(sp); 2096138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2097138745Srik cp->TO, (void *)sp); 209825944Sjoerg break; 209925944Sjoerg } 210025944Sjoerg 2101138745Srik SPPP_UNLOCK(sp); 210225944Sjoerg} 210325944Sjoerg 210411189Sjkh/* 210525944Sjoerg * Change the state of a control protocol in the state automaton. 210625944Sjoerg * Takes care of starting/stopping the restart timer. 210711189Sjkh */ 2108105228Sphkstatic void 210925944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 211025944Sjoerg{ 211125944Sjoerg sp->state[cp->protoidx] = newstate; 211225944Sjoerg 2113138745Srik callout_stop (&sp->ch[cp->protoidx]); 2114138745Srik 211525944Sjoerg switch (newstate) { 211625944Sjoerg case STATE_INITIAL: 211725944Sjoerg case STATE_STARTING: 211825944Sjoerg case STATE_CLOSED: 211925944Sjoerg case STATE_STOPPED: 212025944Sjoerg case STATE_OPENED: 212125944Sjoerg break; 212225944Sjoerg case STATE_CLOSING: 212325944Sjoerg case STATE_STOPPING: 212425944Sjoerg case STATE_REQ_SENT: 212525944Sjoerg case STATE_ACK_RCVD: 212625944Sjoerg case STATE_ACK_SENT: 2127138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2128138745Srik cp->TO, (void *)sp); 212925944Sjoerg break; 213025944Sjoerg } 213125944Sjoerg} 213270199Sjhay 213370199Sjhay/* 213425944Sjoerg *--------------------------------------------------------------------------* 213525944Sjoerg * * 213625944Sjoerg * The LCP implementation. * 213725944Sjoerg * * 213825944Sjoerg *--------------------------------------------------------------------------* 213925944Sjoerg */ 214025944Sjoergstatic void 2141138745Sriksppp_pp_up(struct sppp *sp) 2142138745Srik{ 2143138745Srik SPPP_LOCK(sp); 2144138745Srik lcp.Up(sp); 2145138745Srik SPPP_UNLOCK(sp); 2146138745Srik} 2147138745Srik 2148138745Srikstatic void 2149138745Sriksppp_pp_down(struct sppp *sp) 2150138745Srik{ 2151138745Srik SPPP_LOCK(sp); 2152138745Srik lcp.Down(sp); 2153138745Srik SPPP_UNLOCK(sp); 2154138745Srik} 2155138745Srik 2156138745Srikstatic void 215725944Sjoergsppp_lcp_init(struct sppp *sp) 215825944Sjoerg{ 215925944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 216025944Sjoerg sp->lcp.magic = 0; 216125944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 216225944Sjoerg sp->fail_counter[IDX_LCP] = 0; 216378064Sume sp->pp_seq[IDX_LCP] = 0; 216478064Sume sp->pp_rseq[IDX_LCP] = 0; 216525944Sjoerg sp->lcp.protos = 0; 216625944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 216730300Sjoerg 216844145Sphk /* Note that these values are relevant for all control protocols */ 216944145Sphk sp->lcp.timeout = 3 * hz; 217025944Sjoerg sp->lcp.max_terminate = 2; 217125944Sjoerg sp->lcp.max_configure = 10; 217225944Sjoerg sp->lcp.max_failure = 10; 2173188668Srwatson callout_init(&sp->ch[IDX_LCP], CALLOUT_MPSAFE); 217425944Sjoerg} 217525944Sjoerg 217625944Sjoergstatic void 217725944Sjoergsppp_lcp_up(struct sppp *sp) 217825944Sjoerg{ 217925944Sjoerg STDDCL; 218025944Sjoerg 218170199Sjhay sp->pp_alivecnt = 0; 218270199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 218370199Sjhay sp->lcp.magic = 0; 218470199Sjhay sp->lcp.protos = 0; 218570199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 218625944Sjoerg /* 218775321Sjoerg * If we are authenticator, negotiate LCP_AUTH 218875321Sjoerg */ 218975321Sjoerg if (sp->hisauth.proto != 0) 219075321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 219175321Sjoerg else 219275321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 219375321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 219475321Sjoerg /* 219530300Sjoerg * If this interface is passive or dial-on-demand, and we are 219630300Sjoerg * still in Initial state, it means we've got an incoming 219730300Sjoerg * call. Activate the interface. 219825944Sjoerg */ 219925944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 220025944Sjoerg if (debug) 220125944Sjoerg log(LOG_DEBUG, 220240008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2203148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 220430300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 220530300Sjoerg if (debug) 220669211Sphk log(-1, "(incoming call)\n"); 220730300Sjoerg sp->pp_flags |= PP_CALLIN; 220830300Sjoerg lcp.Open(sp); 220930300Sjoerg } else if (debug) 221069211Sphk log(-1, "\n"); 221188710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 221288710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2213148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 221488710Sjoerg lcp.Open(sp); 221525944Sjoerg } 221625944Sjoerg 221725944Sjoerg sppp_up_event(&lcp, sp); 221825944Sjoerg} 221925944Sjoerg 222025944Sjoergstatic void 222125944Sjoergsppp_lcp_down(struct sppp *sp) 222225944Sjoerg{ 222325944Sjoerg STDDCL; 222425944Sjoerg 222525944Sjoerg sppp_down_event(&lcp, sp); 222625944Sjoerg 222725944Sjoerg /* 222825944Sjoerg * If this is neither a dial-on-demand nor a passive 222925944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 223025944Sjoerg * administrator can force a redial by another ``ifconfig 223125944Sjoerg * up''. XXX For leased line operation, should we immediately 223225944Sjoerg * try to reopen the connection here? 223325944Sjoerg */ 223425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 223525944Sjoerg log(LOG_INFO, 223642066Sphk SPP_FMT "Down event, taking interface down.\n", 223740008Sjoerg SPP_ARGS(ifp)); 223825944Sjoerg if_down(ifp); 223925944Sjoerg } else { 224025944Sjoerg if (debug) 224125944Sjoerg log(LOG_DEBUG, 224240008Sjoerg SPP_FMT "Down event (carrier loss)\n", 224340008Sjoerg SPP_ARGS(ifp)); 224470199Sjhay sp->pp_flags &= ~PP_CALLIN; 224570199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 224670199Sjhay lcp.Close(sp); 2247148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 224825944Sjoerg } 224925944Sjoerg} 225025944Sjoerg 225125944Sjoergstatic void 225225944Sjoergsppp_lcp_open(struct sppp *sp) 225325944Sjoerg{ 225425944Sjoerg sppp_open_event(&lcp, sp); 225525944Sjoerg} 225625944Sjoerg 225725944Sjoergstatic void 225825944Sjoergsppp_lcp_close(struct sppp *sp) 225925944Sjoerg{ 226025944Sjoerg sppp_close_event(&lcp, sp); 226125944Sjoerg} 226225944Sjoerg 226325944Sjoergstatic void 226425944Sjoergsppp_lcp_TO(void *cookie) 226525944Sjoerg{ 226625944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 226725944Sjoerg} 226825944Sjoerg 226925944Sjoerg/* 227025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 227125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 227225944Sjoerg * caused action scn. (The return value is used to make the state 227325944Sjoerg * transition decision in the state automaton.) 227425944Sjoerg */ 227512820Sphkstatic int 227625944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 22774910Swollman{ 227825944Sjoerg STDDCL; 227911189Sjkh u_char *buf, *r, *p; 228025944Sjoerg int origlen, rlen; 228125944Sjoerg u_long nmagic; 228230300Sjoerg u_short authproto; 22834910Swollman 228411189Sjkh len -= 4; 228525944Sjoerg origlen = len; 228611189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 228711189Sjkh if (! buf) 228811189Sjkh return (0); 22894910Swollman 229025706Sjoerg if (debug) 229140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 229240008Sjoerg SPP_ARGS(ifp)); 229325706Sjoerg 229425944Sjoerg /* pass 1: check for things that need to be rejected */ 229511189Sjkh p = (void*) (h+1); 2296161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2297161556Scperciva len-=p[1], p+=p[1]) { 229825944Sjoerg if (debug) 229969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 230011189Sjkh switch (*p) { 230111189Sjkh case LCP_OPT_MAGIC: 230225944Sjoerg /* Magic number. */ 230370199Sjhay if (len >= 6 && p[1] == 6) 230470199Sjhay continue; 230570199Sjhay if (debug) 230670199Sjhay log(-1, "[invalid] "); 230770199Sjhay break; 230825944Sjoerg case LCP_OPT_ASYNC_MAP: 230925944Sjoerg /* Async control character map. */ 231070199Sjhay if (len >= 6 && p[1] == 6) 231125944Sjoerg continue; 231225944Sjoerg if (debug) 231369211Sphk log(-1, "[invalid] "); 231425944Sjoerg break; 231525944Sjoerg case LCP_OPT_MRU: 231625944Sjoerg /* Maximum receive unit. */ 231725944Sjoerg if (len >= 4 && p[1] == 4) 231825944Sjoerg continue; 231925944Sjoerg if (debug) 232069211Sphk log(-1, "[invalid] "); 232125944Sjoerg break; 232230300Sjoerg case LCP_OPT_AUTH_PROTO: 232330300Sjoerg if (len < 4) { 232430300Sjoerg if (debug) 232569211Sphk log(-1, "[invalid] "); 232630300Sjoerg break; 232730300Sjoerg } 232830300Sjoerg authproto = (p[2] << 8) + p[3]; 232930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 233030300Sjoerg if (debug) 233169211Sphk log(-1, "[invalid chap len] "); 233230300Sjoerg break; 233330300Sjoerg } 233430300Sjoerg if (sp->myauth.proto == 0) { 233530300Sjoerg /* we are not configured to do auth */ 233630300Sjoerg if (debug) 233769211Sphk log(-1, "[not configured] "); 233830300Sjoerg break; 233930300Sjoerg } 234030300Sjoerg /* 234130300Sjoerg * Remote want us to authenticate, remember this, 234230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 234330300Sjoerg * up. 234430300Sjoerg */ 234530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 234630300Sjoerg continue; 234725944Sjoerg default: 234825944Sjoerg /* Others not supported. */ 234925944Sjoerg if (debug) 235069211Sphk log(-1, "[rej] "); 235125944Sjoerg break; 235225944Sjoerg } 235325944Sjoerg /* Add the option to rejected list. */ 235425944Sjoerg bcopy (p, r, p[1]); 235525944Sjoerg r += p[1]; 235625944Sjoerg rlen += p[1]; 235725944Sjoerg } 235825944Sjoerg if (rlen) { 235925944Sjoerg if (debug) 236069211Sphk log(-1, " send conf-rej\n"); 236125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 236225944Sjoerg return 0; 236325944Sjoerg } else if (debug) 236469211Sphk log(-1, "\n"); 236525944Sjoerg 236625944Sjoerg /* 236725944Sjoerg * pass 2: check for option values that are unacceptable and 236825944Sjoerg * thus require to be nak'ed. 236925944Sjoerg */ 237025944Sjoerg if (debug) 237140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 237240008Sjoerg SPP_ARGS(ifp)); 237325944Sjoerg 237425944Sjoerg p = (void*) (h+1); 237525944Sjoerg len = origlen; 2376161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2377161556Scperciva len-=p[1], p+=p[1]) { 237825944Sjoerg if (debug) 237969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 238025944Sjoerg switch (*p) { 238125944Sjoerg case LCP_OPT_MAGIC: 238211189Sjkh /* Magic number -- extract. */ 238325944Sjoerg nmagic = (u_long)p[2] << 24 | 238425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 238525944Sjoerg if (nmagic != sp->lcp.magic) { 238670199Sjhay sp->pp_loopcnt = 0; 238725706Sjoerg if (debug) 238869211Sphk log(-1, "0x%lx ", nmagic); 238911189Sjkh continue; 239011189Sjkh } 239170199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 239269211Sphk log(-1, "[glitch] "); 239325944Sjoerg ++sp->pp_loopcnt; 239425944Sjoerg /* 239525944Sjoerg * We negate our magic here, and NAK it. If 239625944Sjoerg * we see it later in an NAK packet, we 239725944Sjoerg * suggest a new one. 239825944Sjoerg */ 239925944Sjoerg nmagic = ~sp->lcp.magic; 240025944Sjoerg /* Gonna NAK it. */ 240125944Sjoerg p[2] = nmagic >> 24; 240225944Sjoerg p[3] = nmagic >> 16; 240325944Sjoerg p[4] = nmagic >> 8; 240425944Sjoerg p[5] = nmagic; 240511189Sjkh break; 240625944Sjoerg 240711189Sjkh case LCP_OPT_ASYNC_MAP: 240888506Sjoerg /* 240988506Sjoerg * Async control character map -- just ignore it. 241088506Sjoerg * 241188506Sjoerg * Quote from RFC 1662, chapter 6: 241288506Sjoerg * To enable this functionality, synchronous PPP 241388506Sjoerg * implementations MUST always respond to the 241488506Sjoerg * Async-Control-Character-Map Configuration 241588506Sjoerg * Option with the LCP Configure-Ack. However, 241688506Sjoerg * acceptance of the Configuration Option does 241788506Sjoerg * not imply that the synchronous implementation 241888506Sjoerg * will do any ACCM mapping. Instead, all such 241988506Sjoerg * octet mapping will be performed by the 242088506Sjoerg * asynchronous-to-synchronous converter. 242188506Sjoerg */ 242288506Sjoerg continue; 242325944Sjoerg 242411189Sjkh case LCP_OPT_MRU: 242525944Sjoerg /* 242625944Sjoerg * Maximum receive unit. Always agreeable, 242725944Sjoerg * but ignored by now. 242825944Sjoerg */ 242925944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 243025706Sjoerg if (debug) 243169211Sphk log(-1, "%lu ", sp->lcp.their_mru); 243211189Sjkh continue; 243330300Sjoerg 243430300Sjoerg case LCP_OPT_AUTH_PROTO: 243530300Sjoerg authproto = (p[2] << 8) + p[3]; 243630300Sjoerg if (sp->myauth.proto != authproto) { 243730300Sjoerg /* not agreed, nak */ 243830300Sjoerg if (debug) 243969211Sphk log(-1, "[mine %s != his %s] ", 244030300Sjoerg sppp_proto_name(sp->hisauth.proto), 244130300Sjoerg sppp_proto_name(authproto)); 244230300Sjoerg p[2] = sp->myauth.proto >> 8; 244330300Sjoerg p[3] = sp->myauth.proto; 244430300Sjoerg break; 244530300Sjoerg } 244630300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 244730300Sjoerg if (debug) 244869211Sphk log(-1, "[chap not MD5] "); 244939981Sjoerg p[4] = CHAP_MD5; 245030300Sjoerg break; 245130300Sjoerg } 245230300Sjoerg continue; 245311189Sjkh } 245425944Sjoerg /* Add the option to nak'ed list. */ 245525706Sjoerg bcopy (p, r, p[1]); 245625706Sjoerg r += p[1]; 245711189Sjkh rlen += p[1]; 245812436Speter } 245925706Sjoerg if (rlen) { 246070199Sjhay /* 246170199Sjhay * Local and remote magics equal -- loopback? 246270199Sjhay */ 246370199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 246470199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 246570199Sjhay printf (SPP_FMT "loopback\n", 246670199Sjhay SPP_ARGS(ifp)); 246770199Sjhay if (ifp->if_flags & IFF_UP) { 246870199Sjhay if_down(ifp); 246970199Sjhay sppp_qflush(&sp->pp_cpq); 247070199Sjhay /* XXX ? */ 247170199Sjhay lcp.Down(sp); 247270199Sjhay lcp.Up(sp); 247370199Sjhay } 2474131093Srik } else if (!sp->pp_loopcnt && 2475131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 247628036Sjoerg if (debug) 247769211Sphk log(-1, " max_failure (%d) exceeded, " 247828036Sjoerg "send conf-rej\n", 247928036Sjoerg sp->lcp.max_failure); 248028036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 248128036Sjoerg } else { 248228036Sjoerg if (debug) 248369211Sphk log(-1, " send conf-nak\n"); 248428036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 248528036Sjoerg } 248625944Sjoerg } else { 248725944Sjoerg if (debug) 248869211Sphk log(-1, " send conf-ack\n"); 248928036Sjoerg sp->fail_counter[IDX_LCP] = 0; 249025944Sjoerg sp->pp_loopcnt = 0; 249125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 249225944Sjoerg h->ident, origlen, h+1); 249325944Sjoerg } 249425944Sjoerg 249511189Sjkh free (buf, M_TEMP); 249611189Sjkh return (rlen == 0); 24974910Swollman} 24984910Swollman 249925944Sjoerg/* 250025944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 250125944Sjoerg * negotiation. 250225944Sjoerg */ 250312820Sphkstatic void 250425944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 25054910Swollman{ 250625944Sjoerg STDDCL; 250725944Sjoerg u_char *buf, *p; 25084910Swollman 250925944Sjoerg len -= 4; 251025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 251125944Sjoerg if (!buf) 25124910Swollman return; 251325944Sjoerg 251425944Sjoerg if (debug) 251540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 251640008Sjoerg SPP_ARGS(ifp)); 251725944Sjoerg 251825944Sjoerg p = (void*) (h+1); 2519161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2520161556Scperciva len -= p[1], p += p[1]) { 252125944Sjoerg if (debug) 252269211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 252325944Sjoerg switch (*p) { 252425944Sjoerg case LCP_OPT_MAGIC: 252525944Sjoerg /* Magic number -- can't use it, use 0 */ 252625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 252725944Sjoerg sp->lcp.magic = 0; 252825944Sjoerg break; 252925944Sjoerg case LCP_OPT_MRU: 253025944Sjoerg /* 253125944Sjoerg * Should not be rejected anyway, since we only 253225944Sjoerg * negotiate a MRU if explicitly requested by 253325944Sjoerg * peer. 253425944Sjoerg */ 253525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 253625944Sjoerg break; 253730300Sjoerg case LCP_OPT_AUTH_PROTO: 253830300Sjoerg /* 253930300Sjoerg * Peer doesn't want to authenticate himself, 254030300Sjoerg * deny unless this is a dialout call, and 254130300Sjoerg * AUTHFLAG_NOCALLOUT is set. 254230300Sjoerg */ 254330300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 254430300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 254530300Sjoerg if (debug) 254669211Sphk log(-1, "[don't insist on auth " 254730300Sjoerg "for callout]"); 254830300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 254930300Sjoerg break; 255030300Sjoerg } 255130300Sjoerg if (debug) 255269211Sphk log(-1, "[access denied]\n"); 255330300Sjoerg lcp.Close(sp); 255430300Sjoerg break; 255525944Sjoerg } 25564910Swollman } 255725944Sjoerg if (debug) 255869211Sphk log(-1, "\n"); 255925944Sjoerg free (buf, M_TEMP); 256025944Sjoerg return; 256125944Sjoerg} 256225944Sjoerg 256325944Sjoerg/* 256425944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 256525944Sjoerg * negotiation. 256625944Sjoerg */ 256725944Sjoergstatic void 256825944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 256925944Sjoerg{ 257025944Sjoerg STDDCL; 257125944Sjoerg u_char *buf, *p; 257225944Sjoerg u_long magic; 257325944Sjoerg 257425944Sjoerg len -= 4; 257525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 257625944Sjoerg if (!buf) 257725944Sjoerg return; 257825944Sjoerg 257925944Sjoerg if (debug) 258040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 258140008Sjoerg SPP_ARGS(ifp)); 258225944Sjoerg 258325944Sjoerg p = (void*) (h+1); 2584161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2585161556Scperciva len -= p[1], p += p[1]) { 258625706Sjoerg if (debug) 258769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 258825944Sjoerg switch (*p) { 258925944Sjoerg case LCP_OPT_MAGIC: 259025944Sjoerg /* Magic number -- renegotiate */ 259125944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 259225944Sjoerg len >= 6 && p[1] == 6) { 259325944Sjoerg magic = (u_long)p[2] << 24 | 259425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 259525944Sjoerg /* 259625944Sjoerg * If the remote magic is our negated one, 259725944Sjoerg * this looks like a loopback problem. 259825944Sjoerg * Suggest a new magic to make sure. 259925944Sjoerg */ 260025944Sjoerg if (magic == ~sp->lcp.magic) { 260125944Sjoerg if (debug) 260269211Sphk log(-1, "magic glitch "); 260335064Sphk sp->lcp.magic = random(); 260425944Sjoerg } else { 260525944Sjoerg sp->lcp.magic = magic; 260625944Sjoerg if (debug) 260769211Sphk log(-1, "%lu ", magic); 260825944Sjoerg } 260925944Sjoerg } 261025944Sjoerg break; 261125944Sjoerg case LCP_OPT_MRU: 261225944Sjoerg /* 261325944Sjoerg * Peer wants to advise us to negotiate an MRU. 261425944Sjoerg * Agree on it if it's reasonable, or use 261525944Sjoerg * default otherwise. 261625944Sjoerg */ 261725944Sjoerg if (len >= 4 && p[1] == 4) { 261825944Sjoerg u_int mru = p[2] * 256 + p[3]; 261925944Sjoerg if (debug) 262069211Sphk log(-1, "%d ", mru); 262125944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 262225944Sjoerg mru = PP_MTU; 262325944Sjoerg sp->lcp.mru = mru; 262425944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 262525944Sjoerg } 262625944Sjoerg break; 262730300Sjoerg case LCP_OPT_AUTH_PROTO: 262830300Sjoerg /* 262930300Sjoerg * Peer doesn't like our authentication method, 263030300Sjoerg * deny. 263130300Sjoerg */ 263230300Sjoerg if (debug) 263369211Sphk log(-1, "[access denied]\n"); 263430300Sjoerg lcp.Close(sp); 263530300Sjoerg break; 26364910Swollman } 263725944Sjoerg } 263825944Sjoerg if (debug) 263969211Sphk log(-1, "\n"); 264025944Sjoerg free (buf, M_TEMP); 264125944Sjoerg return; 264225944Sjoerg} 264311189Sjkh 264425944Sjoergstatic void 264525944Sjoergsppp_lcp_tlu(struct sppp *sp) 264625944Sjoerg{ 264742066Sphk STDDCL; 264825944Sjoerg int i; 264925944Sjoerg u_long mask; 265025944Sjoerg 265125944Sjoerg /* XXX ? */ 265225944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2653148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 265425944Sjoerg /* Coming out of loopback mode. */ 265525944Sjoerg if_up(ifp); 265640008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 265725944Sjoerg } 265825944Sjoerg 265925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 266025944Sjoerg if ((cps[i])->flags & CP_QUAL) 266125944Sjoerg (cps[i])->Open(sp); 266225944Sjoerg 266330300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 266430300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 266525944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 266625944Sjoerg else 266725944Sjoerg sp->pp_phase = PHASE_NETWORK; 266825944Sjoerg 266942066Sphk if (debug) 267042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 267142066Sphk sppp_phase_name(sp->pp_phase)); 267225944Sjoerg 267330300Sjoerg /* 267430300Sjoerg * Open all authentication protocols. This is even required 267530300Sjoerg * if we already proceeded to network phase, since it might be 267630300Sjoerg * that remote wants us to authenticate, so we might have to 267730300Sjoerg * send a PAP request. Undesired authentication protocols 267830300Sjoerg * don't do anything when they get an Open event. 267930300Sjoerg */ 268030300Sjoerg for (i = 0; i < IDX_COUNT; i++) 268130300Sjoerg if ((cps[i])->flags & CP_AUTH) 268230300Sjoerg (cps[i])->Open(sp); 268330300Sjoerg 268430300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 268525944Sjoerg /* Notify all NCPs. */ 268625944Sjoerg for (i = 0; i < IDX_COUNT; i++) 268788723Sjoerg if (((cps[i])->flags & CP_NCP) && 268888723Sjoerg /* 268988723Sjoerg * XXX 269088723Sjoerg * Hack to administratively disable IPv6 if 269188723Sjoerg * not desired. Perhaps we should have another 269288723Sjoerg * flag for this, but right now, we can make 269388723Sjoerg * all struct cp's read/only. 269488723Sjoerg */ 269588723Sjoerg (cps[i] != &ipv6cp || 269688723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 269725944Sjoerg (cps[i])->Open(sp); 269825944Sjoerg } 269925944Sjoerg 270025944Sjoerg /* Send Up events to all started protos. */ 270125944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 270288706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 270325944Sjoerg (cps[i])->Up(sp); 270425944Sjoerg 270542104Sphk /* notify low-level driver of state change */ 270642104Sphk if (sp->pp_chg) 270742104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 270842104Sphk 270925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 271025944Sjoerg /* if no NCP is starting, close down */ 271130300Sjoerg sppp_lcp_check_and_close(sp); 271225944Sjoerg} 271325944Sjoerg 271425944Sjoergstatic void 271525944Sjoergsppp_lcp_tld(struct sppp *sp) 271625944Sjoerg{ 271742066Sphk STDDCL; 271825944Sjoerg int i; 271925944Sjoerg u_long mask; 272025944Sjoerg 272125944Sjoerg sp->pp_phase = PHASE_TERMINATE; 272225944Sjoerg 272342066Sphk if (debug) 272442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 272542066Sphk sppp_phase_name(sp->pp_phase)); 272625944Sjoerg 272725944Sjoerg /* 272825944Sjoerg * Take upper layers down. We send the Down event first and 272925944Sjoerg * the Close second to prevent the upper layers from sending 273025944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 273125944Sjoerg * describes it. 273225944Sjoerg */ 273325944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 273488706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 273525944Sjoerg (cps[i])->Down(sp); 273625944Sjoerg (cps[i])->Close(sp); 273725944Sjoerg } 273825944Sjoerg} 273925944Sjoerg 274025944Sjoergstatic void 274125944Sjoergsppp_lcp_tls(struct sppp *sp) 274225944Sjoerg{ 274342066Sphk STDDCL; 274425944Sjoerg 274525944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 274625944Sjoerg 274742066Sphk if (debug) 274842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 274942066Sphk sppp_phase_name(sp->pp_phase)); 275025944Sjoerg 275125944Sjoerg /* Notify lower layer if desired. */ 275225944Sjoerg if (sp->pp_tls) 275325944Sjoerg (sp->pp_tls)(sp); 275441881Sphk else 275541881Sphk (sp->pp_up)(sp); 275625944Sjoerg} 275725944Sjoerg 275825944Sjoergstatic void 275925944Sjoergsppp_lcp_tlf(struct sppp *sp) 276025944Sjoerg{ 276142066Sphk STDDCL; 276225944Sjoerg 276325944Sjoerg sp->pp_phase = PHASE_DEAD; 276442066Sphk if (debug) 276542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 276642066Sphk sppp_phase_name(sp->pp_phase)); 276725944Sjoerg 276825944Sjoerg /* Notify lower layer if desired. */ 276925944Sjoerg if (sp->pp_tlf) 277025944Sjoerg (sp->pp_tlf)(sp); 277141881Sphk else 277241881Sphk (sp->pp_down)(sp); 277325944Sjoerg} 277425944Sjoerg 277525944Sjoergstatic void 277625944Sjoergsppp_lcp_scr(struct sppp *sp) 277725944Sjoerg{ 277830300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 277925944Sjoerg int i = 0; 278030300Sjoerg u_short authproto; 278125944Sjoerg 278225944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 278325944Sjoerg if (! sp->lcp.magic) 278435064Sphk sp->lcp.magic = random(); 278525944Sjoerg opt[i++] = LCP_OPT_MAGIC; 278625944Sjoerg opt[i++] = 6; 278725944Sjoerg opt[i++] = sp->lcp.magic >> 24; 278825944Sjoerg opt[i++] = sp->lcp.magic >> 16; 278925944Sjoerg opt[i++] = sp->lcp.magic >> 8; 279025944Sjoerg opt[i++] = sp->lcp.magic; 279125944Sjoerg } 279225944Sjoerg 279325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 279425944Sjoerg opt[i++] = LCP_OPT_MRU; 279525944Sjoerg opt[i++] = 4; 279625944Sjoerg opt[i++] = sp->lcp.mru >> 8; 279725944Sjoerg opt[i++] = sp->lcp.mru; 279825944Sjoerg } 279925944Sjoerg 280030300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 280130300Sjoerg authproto = sp->hisauth.proto; 280230300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 280330300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 280430300Sjoerg opt[i++] = authproto >> 8; 280530300Sjoerg opt[i++] = authproto; 280630300Sjoerg if (authproto == PPP_CHAP) 280730300Sjoerg opt[i++] = CHAP_MD5; 280830300Sjoerg } 280930300Sjoerg 281078064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 281125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 281225944Sjoerg} 281325944Sjoerg 281425944Sjoerg/* 281530300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 281630300Sjoerg */ 281730300Sjoergstatic int 281830300Sjoergsppp_ncp_check(struct sppp *sp) 281930300Sjoerg{ 282030300Sjoerg int i, mask; 282130300Sjoerg 282230300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 282388706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 282430300Sjoerg return 1; 282530300Sjoerg return 0; 282630300Sjoerg} 282730300Sjoerg 282830300Sjoerg/* 282925944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 283025944Sjoerg * Called by the NCPs during their tlf action handling. 283125944Sjoerg */ 283225944Sjoergstatic void 283330300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 283425944Sjoerg{ 283525944Sjoerg 283630300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 283730300Sjoerg /* don't bother, we are already going down */ 283830300Sjoerg return; 283930300Sjoerg 284030300Sjoerg if (sppp_ncp_check(sp)) 284130300Sjoerg return; 284230300Sjoerg 284325944Sjoerg lcp.Close(sp); 284425944Sjoerg} 284570199Sjhay 284670199Sjhay/* 284725944Sjoerg *--------------------------------------------------------------------------* 284825944Sjoerg * * 284925944Sjoerg * The IPCP implementation. * 285025944Sjoerg * * 285125944Sjoerg *--------------------------------------------------------------------------* 285225944Sjoerg */ 285325944Sjoerg 2854184682Sbz#ifdef INET 285525944Sjoergstatic void 285625944Sjoergsppp_ipcp_init(struct sppp *sp) 285725944Sjoerg{ 285825944Sjoerg sp->ipcp.opts = 0; 285925944Sjoerg sp->ipcp.flags = 0; 286025944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 286125944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 286278064Sume sp->pp_seq[IDX_IPCP] = 0; 286378064Sume sp->pp_rseq[IDX_IPCP] = 0; 2864188668Srwatson callout_init(&sp->ch[IDX_IPCP], CALLOUT_MPSAFE); 286525944Sjoerg} 286625944Sjoerg 286725944Sjoergstatic void 286825944Sjoergsppp_ipcp_up(struct sppp *sp) 286925944Sjoerg{ 287025944Sjoerg sppp_up_event(&ipcp, sp); 287125944Sjoerg} 287225944Sjoerg 287325944Sjoergstatic void 287425944Sjoergsppp_ipcp_down(struct sppp *sp) 287525944Sjoerg{ 287625944Sjoerg sppp_down_event(&ipcp, sp); 287725944Sjoerg} 287825944Sjoerg 287925944Sjoergstatic void 288025944Sjoergsppp_ipcp_open(struct sppp *sp) 288125944Sjoerg{ 288225944Sjoerg STDDCL; 288325944Sjoerg u_long myaddr, hisaddr; 288425944Sjoerg 288588534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 288688534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 288788700Sjoerg sp->ipcp.opts = 0; 288842104Sphk 288930300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 289025944Sjoerg /* 289125944Sjoerg * If we don't have his address, this probably means our 289225944Sjoerg * interface doesn't want to talk IP at all. (This could 289325944Sjoerg * be the case if somebody wants to speak only IPX, for 289425944Sjoerg * example.) Don't open IPCP in this case. 289525944Sjoerg */ 289625944Sjoerg if (hisaddr == 0L) { 289725944Sjoerg /* XXX this message should go away */ 289825944Sjoerg if (debug) 289940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 290040008Sjoerg SPP_ARGS(ifp)); 290125944Sjoerg return; 290225944Sjoerg } 290325944Sjoerg if (myaddr == 0L) { 290425944Sjoerg /* 290525944Sjoerg * I don't have an assigned address, so i need to 290625944Sjoerg * negotiate my address. 290725944Sjoerg */ 290825944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 290925944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 291042104Sphk } else 291142104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 291288723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 291388534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 291488534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 291588534Sjoerg sp->ipcp.compress_cid = 1; 291688534Sjoerg } 291725944Sjoerg sppp_open_event(&ipcp, sp); 291825944Sjoerg} 291925944Sjoerg 292025944Sjoergstatic void 292125944Sjoergsppp_ipcp_close(struct sppp *sp) 292225944Sjoerg{ 292325944Sjoerg sppp_close_event(&ipcp, sp); 292425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 292525944Sjoerg /* 292625944Sjoerg * My address was dynamic, clear it again. 292725944Sjoerg */ 292825944Sjoerg sppp_set_ip_addr(sp, 0L); 292925944Sjoerg} 293025944Sjoerg 293125944Sjoergstatic void 293225944Sjoergsppp_ipcp_TO(void *cookie) 293325944Sjoerg{ 293425944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 293525944Sjoerg} 293625944Sjoerg 293725944Sjoerg/* 293825944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 293925944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 294025944Sjoerg * caused action scn. (The return value is used to make the state 294125944Sjoerg * transition decision in the state automaton.) 294225944Sjoerg */ 294325944Sjoergstatic int 294425944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 294525944Sjoerg{ 294625944Sjoerg u_char *buf, *r, *p; 2947147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 294825944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 294925944Sjoerg u_long hisaddr, desiredaddr; 295042104Sphk int gotmyaddr = 0; 295188534Sjoerg int desiredcomp; 295225944Sjoerg 295325944Sjoerg len -= 4; 295425944Sjoerg origlen = len; 295525944Sjoerg /* 295625944Sjoerg * Make sure to allocate a buf that can at least hold a 295725944Sjoerg * conf-nak with an `address' option. We might need it below. 295825944Sjoerg */ 295925944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 296025944Sjoerg if (! buf) 296125944Sjoerg return (0); 296225944Sjoerg 296325944Sjoerg /* pass 1: see if we can recognize them */ 296425944Sjoerg if (debug) 296540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 296640008Sjoerg SPP_ARGS(ifp)); 296725944Sjoerg p = (void*) (h+1); 2968161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2969161556Scperciva len-=p[1], p+=p[1]) { 297025944Sjoerg if (debug) 297169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 297225944Sjoerg switch (*p) { 297388534Sjoerg case IPCP_OPT_COMPRESSION: 297488723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 297588534Sjoerg /* VJ compression administratively disabled */ 297688534Sjoerg if (debug) 297788534Sjoerg log(-1, "[locally disabled] "); 297888534Sjoerg break; 297988534Sjoerg } 298088534Sjoerg /* 298188534Sjoerg * In theory, we should only conf-rej an 298288534Sjoerg * option that is shorter than RFC 1618 298388534Sjoerg * requires (i.e. < 4), and should conf-nak 298488534Sjoerg * anything else that is not VJ. However, 298588534Sjoerg * since our algorithm always uses the 298688534Sjoerg * original option to NAK it with new values, 298788534Sjoerg * things would become more complicated. In 298888534Sjoerg * pratice, the only commonly implemented IP 298988534Sjoerg * compression option is VJ anyway, so the 299088534Sjoerg * difference is negligible. 299188534Sjoerg */ 299288534Sjoerg if (len >= 6 && p[1] == 6) { 299388534Sjoerg /* 299488534Sjoerg * correctly formed compression option 299588534Sjoerg * that could be VJ compression 299688534Sjoerg */ 299788534Sjoerg continue; 299888534Sjoerg } 299988534Sjoerg if (debug) 300088534Sjoerg log(-1, 300188534Sjoerg "optlen %d [invalid/unsupported] ", 300288534Sjoerg p[1]); 300388534Sjoerg break; 300425944Sjoerg case IPCP_OPT_ADDRESS: 300525944Sjoerg if (len >= 6 && p[1] == 6) { 300625944Sjoerg /* correctly formed address option */ 300725944Sjoerg continue; 300825944Sjoerg } 300925706Sjoerg if (debug) 301069211Sphk log(-1, "[invalid] "); 301111189Sjkh break; 301225944Sjoerg default: 301325944Sjoerg /* Others not supported. */ 301425944Sjoerg if (debug) 301569211Sphk log(-1, "[rej] "); 30164910Swollman break; 30174910Swollman } 301825944Sjoerg /* Add the option to rejected list. */ 301925944Sjoerg bcopy (p, r, p[1]); 302025944Sjoerg r += p[1]; 302125944Sjoerg rlen += p[1]; 302225944Sjoerg } 302325944Sjoerg if (rlen) { 302425944Sjoerg if (debug) 302569211Sphk log(-1, " send conf-rej\n"); 302625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 302725944Sjoerg return 0; 302825944Sjoerg } else if (debug) 302969211Sphk log(-1, "\n"); 303025944Sjoerg 303125944Sjoerg /* pass 2: parse option values */ 303230300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 303325944Sjoerg if (debug) 303440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 303540008Sjoerg SPP_ARGS(ifp)); 303625944Sjoerg p = (void*) (h+1); 303725944Sjoerg len = origlen; 3038161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3039161556Scperciva len-=p[1], p+=p[1]) { 304025944Sjoerg if (debug) 304169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 304225944Sjoerg switch (*p) { 304388534Sjoerg case IPCP_OPT_COMPRESSION: 304488534Sjoerg desiredcomp = p[2] << 8 | p[3]; 304588534Sjoerg /* We only support VJ */ 304688534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 304788534Sjoerg if (debug) 304888534Sjoerg log(-1, "VJ [ack] "); 304988534Sjoerg sp->ipcp.flags |= IPCP_VJ; 305088599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 305188534Sjoerg sp->ipcp.max_state = p[4]; 305288534Sjoerg sp->ipcp.compress_cid = p[5]; 305388534Sjoerg continue; 305488534Sjoerg } 305588534Sjoerg if (debug) 305688534Sjoerg log(-1, 305788534Sjoerg "compproto %#04x [not supported] ", 305888534Sjoerg desiredcomp); 305988534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 306088534Sjoerg p[3] = IPCP_COMP_VJ; 306188534Sjoerg p[4] = sp->ipcp.max_state; 306288534Sjoerg p[5] = sp->ipcp.compress_cid; 306388534Sjoerg break; 306425944Sjoerg case IPCP_OPT_ADDRESS: 306542104Sphk /* This is the address he wants in his end */ 306625944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 306725944Sjoerg p[4] << 8 | p[5]; 306833928Sphk if (desiredaddr == hisaddr || 306988702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 307025944Sjoerg /* 307125944Sjoerg * Peer's address is same as our value, 307288702Sjoerg * or we have set it to 0.0.0.* to 307333928Sphk * indicate that we do not really care, 307425944Sjoerg * this is agreeable. Gonna conf-ack 307525944Sjoerg * it. 307625944Sjoerg */ 307725944Sjoerg if (debug) 307869211Sphk log(-1, "%s [ack] ", 307942104Sphk sppp_dotted_quad(hisaddr)); 308025944Sjoerg /* record that we've seen it already */ 308125944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 308225944Sjoerg continue; 308325944Sjoerg } 308425944Sjoerg /* 308525944Sjoerg * The address wasn't agreeable. This is either 308625944Sjoerg * he sent us 0.0.0.0, asking to assign him an 308725944Sjoerg * address, or he send us another address not 308825944Sjoerg * matching our value. Either case, we gonna 308925944Sjoerg * conf-nak it with our value. 309042104Sphk * XXX: we should "rej" if hisaddr == 0 309125944Sjoerg */ 309225944Sjoerg if (debug) { 309325944Sjoerg if (desiredaddr == 0) 309469211Sphk log(-1, "[addr requested] "); 309525944Sjoerg else 309669211Sphk log(-1, "%s [not agreed] ", 309742104Sphk sppp_dotted_quad(desiredaddr)); 309825944Sjoerg 309925944Sjoerg } 310044235Sphk p[2] = hisaddr >> 24; 310144235Sphk p[3] = hisaddr >> 16; 310244235Sphk p[4] = hisaddr >> 8; 310344235Sphk p[5] = hisaddr; 310411189Sjkh break; 310525706Sjoerg } 310625944Sjoerg /* Add the option to nak'ed list. */ 310725944Sjoerg bcopy (p, r, p[1]); 310825944Sjoerg r += p[1]; 310925944Sjoerg rlen += p[1]; 311025944Sjoerg } 311125944Sjoerg 311225944Sjoerg /* 311325944Sjoerg * If we are about to conf-ack the request, but haven't seen 311425944Sjoerg * his address so far, gonna conf-nak it instead, with the 311525944Sjoerg * `address' option present and our idea of his address being 311625944Sjoerg * filled in there, to request negotiation of both addresses. 311725944Sjoerg * 311825944Sjoerg * XXX This can result in an endless req - nak loop if peer 311925944Sjoerg * doesn't want to send us his address. Q: What should we do 312025944Sjoerg * about it? XXX A: implement the max-failure counter. 312125944Sjoerg */ 312242104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 312325944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 312425944Sjoerg buf[1] = 6; 312525944Sjoerg buf[2] = hisaddr >> 24; 312625944Sjoerg buf[3] = hisaddr >> 16; 312725944Sjoerg buf[4] = hisaddr >> 8; 312825944Sjoerg buf[5] = hisaddr; 312925944Sjoerg rlen = 6; 313025706Sjoerg if (debug) 313169211Sphk log(-1, "still need hisaddr "); 313225944Sjoerg } 313325944Sjoerg 313425944Sjoerg if (rlen) { 313525706Sjoerg if (debug) 313669211Sphk log(-1, " send conf-nak\n"); 313725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 313825944Sjoerg } else { 313925706Sjoerg if (debug) 314069211Sphk log(-1, " send conf-ack\n"); 314125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 314225944Sjoerg h->ident, origlen, h+1); 314325944Sjoerg } 314425944Sjoerg 314525944Sjoerg free (buf, M_TEMP); 314625944Sjoerg return (rlen == 0); 314725944Sjoerg} 314825944Sjoerg 314925944Sjoerg/* 315025944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 315125944Sjoerg * negotiation. 315225944Sjoerg */ 315325944Sjoergstatic void 315425944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 315525944Sjoerg{ 315625944Sjoerg u_char *buf, *p; 3157147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 315825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 315925944Sjoerg 316025944Sjoerg len -= 4; 316125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 316225944Sjoerg if (!buf) 316325944Sjoerg return; 316425944Sjoerg 316525944Sjoerg if (debug) 316640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 316740008Sjoerg SPP_ARGS(ifp)); 316825944Sjoerg 316925944Sjoerg p = (void*) (h+1); 3170161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3171161556Scperciva len -= p[1], p += p[1]) { 317225706Sjoerg if (debug) 317369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 317425944Sjoerg switch (*p) { 317588534Sjoerg case IPCP_OPT_COMPRESSION: 317688534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 317788534Sjoerg break; 317825944Sjoerg case IPCP_OPT_ADDRESS: 317925944Sjoerg /* 318025944Sjoerg * Peer doesn't grok address option. This is 318125944Sjoerg * bad. XXX Should we better give up here? 318242104Sphk * XXX We could try old "addresses" option... 318325944Sjoerg */ 318425944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 318525944Sjoerg break; 318625944Sjoerg } 31874910Swollman } 318825944Sjoerg if (debug) 318969211Sphk log(-1, "\n"); 319025944Sjoerg free (buf, M_TEMP); 319125944Sjoerg return; 31924910Swollman} 31934910Swollman 319425944Sjoerg/* 319525944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 319625944Sjoerg * negotiation. 319725944Sjoerg */ 319812820Sphkstatic void 319925944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 32004910Swollman{ 320125944Sjoerg u_char *buf, *p; 3202147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 320325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 320488534Sjoerg int desiredcomp; 320525944Sjoerg u_long wantaddr; 32064910Swollman 320725944Sjoerg len -= 4; 320825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 320925944Sjoerg if (!buf) 321025944Sjoerg return; 321125944Sjoerg 321225944Sjoerg if (debug) 321340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 321440008Sjoerg SPP_ARGS(ifp)); 321525944Sjoerg 321625944Sjoerg p = (void*) (h+1); 3217161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3218161556Scperciva len -= p[1], p += p[1]) { 321925944Sjoerg if (debug) 322069211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 322125944Sjoerg switch (*p) { 322288534Sjoerg case IPCP_OPT_COMPRESSION: 322388534Sjoerg if (len >= 6 && p[1] == 6) { 322488534Sjoerg desiredcomp = p[2] << 8 | p[3]; 322588534Sjoerg if (debug) 322688534Sjoerg log(-1, "[wantcomp %#04x] ", 322788534Sjoerg desiredcomp); 322888534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 322988599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 323088534Sjoerg sp->ipcp.max_state = p[4]; 323188534Sjoerg sp->ipcp.compress_cid = p[5]; 323288534Sjoerg if (debug) 323388534Sjoerg log(-1, "[agree] "); 323488534Sjoerg } else 323588534Sjoerg sp->ipcp.opts &= 323688534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 323788534Sjoerg } 323888534Sjoerg break; 323925944Sjoerg case IPCP_OPT_ADDRESS: 324025944Sjoerg /* 324125944Sjoerg * Peer doesn't like our local IP address. See 324225944Sjoerg * if we can do something for him. We'll drop 324325944Sjoerg * him our address then. 324425944Sjoerg */ 324525944Sjoerg if (len >= 6 && p[1] == 6) { 324625944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 324725944Sjoerg p[4] << 8 | p[5]; 324825944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 324925944Sjoerg if (debug) 325069211Sphk log(-1, "[wantaddr %s] ", 325130300Sjoerg sppp_dotted_quad(wantaddr)); 325225944Sjoerg /* 325325944Sjoerg * When doing dynamic address assignment, 325425944Sjoerg * we accept his offer. Otherwise, we 325525944Sjoerg * ignore it and thus continue to negotiate 325625944Sjoerg * our already existing value. 325742104Sphk * XXX: Bogus, if he said no once, he'll 325842104Sphk * just say no again, might as well die. 325925944Sjoerg */ 326025944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 326125944Sjoerg sppp_set_ip_addr(sp, wantaddr); 326225944Sjoerg if (debug) 326369211Sphk log(-1, "[agree] "); 326442104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 326525944Sjoerg } 326625944Sjoerg } 326725944Sjoerg break; 326825944Sjoerg } 326925944Sjoerg } 327025944Sjoerg if (debug) 327169211Sphk log(-1, "\n"); 327225944Sjoerg free (buf, M_TEMP); 327325944Sjoerg return; 32744910Swollman} 32754910Swollman 327612820Sphkstatic void 327725944Sjoergsppp_ipcp_tlu(struct sppp *sp) 32784910Swollman{ 327942104Sphk /* we are up - notify isdn daemon */ 328042104Sphk if (sp->pp_con) 328142104Sphk sp->pp_con(sp); 32824910Swollman} 32834910Swollman 328425944Sjoergstatic void 328525944Sjoergsppp_ipcp_tld(struct sppp *sp) 328625944Sjoerg{ 328725944Sjoerg} 328825944Sjoerg 328925944Sjoergstatic void 329025944Sjoergsppp_ipcp_tls(struct sppp *sp) 329125944Sjoerg{ 329225944Sjoerg /* indicate to LCP that it must stay alive */ 329325944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 329425944Sjoerg} 329525944Sjoerg 329625944Sjoergstatic void 329725944Sjoergsppp_ipcp_tlf(struct sppp *sp) 329825944Sjoerg{ 329925944Sjoerg /* we no longer need LCP */ 330025944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 330130300Sjoerg sppp_lcp_check_and_close(sp); 330225944Sjoerg} 330325944Sjoerg 330425944Sjoergstatic void 330525944Sjoergsppp_ipcp_scr(struct sppp *sp) 330625944Sjoerg{ 330725944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 330825944Sjoerg u_long ouraddr; 330925944Sjoerg int i = 0; 331025944Sjoerg 331188534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 331288534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 331388534Sjoerg opt[i++] = 6; 331488534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 331588534Sjoerg opt[i++] = IPCP_COMP_VJ; 331688534Sjoerg opt[i++] = sp->ipcp.max_state; 331788534Sjoerg opt[i++] = sp->ipcp.compress_cid; 331888534Sjoerg } 331925944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 332030300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 332125944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 332225944Sjoerg opt[i++] = 6; 332325944Sjoerg opt[i++] = ouraddr >> 24; 332425944Sjoerg opt[i++] = ouraddr >> 16; 332525944Sjoerg opt[i++] = ouraddr >> 8; 332625944Sjoerg opt[i++] = ouraddr; 332725944Sjoerg } 332825944Sjoerg 332978064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 333025944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 333125944Sjoerg} 3332184682Sbz#else /* !INET */ 3333184682Sbzstatic void 3334184682Sbzsppp_ipcp_init(struct sppp *sp) 3335184682Sbz{ 3336184682Sbz} 333725944Sjoerg 3338184682Sbzstatic void 3339184682Sbzsppp_ipcp_up(struct sppp *sp) 3340184682Sbz{ 3341184682Sbz} 3342184682Sbz 3343184682Sbzstatic void 3344184682Sbzsppp_ipcp_down(struct sppp *sp) 3345184682Sbz{ 3346184682Sbz} 3347184682Sbz 3348184682Sbzstatic void 3349184682Sbzsppp_ipcp_open(struct sppp *sp) 3350184682Sbz{ 3351184682Sbz} 3352184682Sbz 3353184682Sbzstatic void 3354184682Sbzsppp_ipcp_close(struct sppp *sp) 3355184682Sbz{ 3356184682Sbz} 3357184682Sbz 3358184682Sbzstatic void 3359184682Sbzsppp_ipcp_TO(void *cookie) 3360184682Sbz{ 3361184682Sbz} 3362184682Sbz 3363184682Sbzstatic int 3364184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3365184682Sbz{ 3366184682Sbz return (0); 3367184682Sbz} 3368184682Sbz 3369184682Sbzstatic void 3370184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3371184682Sbz{ 3372184682Sbz} 3373184682Sbz 3374184682Sbzstatic void 3375184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3376184682Sbz{ 3377184682Sbz} 3378184682Sbz 3379184682Sbzstatic void 3380184682Sbzsppp_ipcp_tlu(struct sppp *sp) 3381184682Sbz{ 3382184682Sbz} 3383184682Sbz 3384184682Sbzstatic void 3385184682Sbzsppp_ipcp_tld(struct sppp *sp) 3386184682Sbz{ 3387184682Sbz} 3388184682Sbz 3389184682Sbzstatic void 3390184682Sbzsppp_ipcp_tls(struct sppp *sp) 3391184682Sbz{ 3392184682Sbz} 3393184682Sbz 3394184682Sbzstatic void 3395184682Sbzsppp_ipcp_tlf(struct sppp *sp) 3396184682Sbz{ 3397184682Sbz} 3398184682Sbz 3399184682Sbzstatic void 3400184682Sbzsppp_ipcp_scr(struct sppp *sp) 3401184682Sbz{ 3402184682Sbz} 3403184682Sbz#endif 3404184682Sbz 340570199Sjhay/* 340630300Sjoerg *--------------------------------------------------------------------------* 340730300Sjoerg * * 340878064Sume * The IPv6CP implementation. * 340978064Sume * * 341078064Sume *--------------------------------------------------------------------------* 341178064Sume */ 341278064Sume 341378064Sume#ifdef INET6 341478064Sumestatic void 341578064Sumesppp_ipv6cp_init(struct sppp *sp) 341678064Sume{ 341778064Sume sp->ipv6cp.opts = 0; 341878064Sume sp->ipv6cp.flags = 0; 341978064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 342078064Sume sp->fail_counter[IDX_IPV6CP] = 0; 342178064Sume sp->pp_seq[IDX_IPV6CP] = 0; 342278064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3423188668Srwatson callout_init(&sp->ch[IDX_IPV6CP], CALLOUT_MPSAFE); 342478064Sume} 342578064Sume 342678064Sumestatic void 342778064Sumesppp_ipv6cp_up(struct sppp *sp) 342878064Sume{ 342978064Sume sppp_up_event(&ipv6cp, sp); 343078064Sume} 343178064Sume 343278064Sumestatic void 343378064Sumesppp_ipv6cp_down(struct sppp *sp) 343478064Sume{ 343578064Sume sppp_down_event(&ipv6cp, sp); 343678064Sume} 343778064Sume 343878064Sumestatic void 343978064Sumesppp_ipv6cp_open(struct sppp *sp) 344078064Sume{ 344178064Sume STDDCL; 344278064Sume struct in6_addr myaddr, hisaddr; 344378064Sume 344478064Sume#ifdef IPV6CP_MYIFID_DYN 344578064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 344678064Sume#else 344778064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 344878064Sume#endif 344978064Sume 345078064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 345178064Sume /* 345278064Sume * If we don't have our address, this probably means our 345378064Sume * interface doesn't want to talk IPv6 at all. (This could 345478064Sume * be the case if somebody wants to speak only IPX, for 345578064Sume * example.) Don't open IPv6CP in this case. 345678064Sume */ 345778064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 345878064Sume /* XXX this message should go away */ 345978064Sume if (debug) 346078064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 346178064Sume SPP_ARGS(ifp)); 346278064Sume return; 346378064Sume } 346478064Sume 346578064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 346678064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 346778064Sume sppp_open_event(&ipv6cp, sp); 346878064Sume} 346978064Sume 347078064Sumestatic void 347178064Sumesppp_ipv6cp_close(struct sppp *sp) 347278064Sume{ 347378064Sume sppp_close_event(&ipv6cp, sp); 347478064Sume} 347578064Sume 347678064Sumestatic void 347778064Sumesppp_ipv6cp_TO(void *cookie) 347878064Sume{ 347978064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 348078064Sume} 348178064Sume 348278064Sume/* 348378064Sume * Analyze a configure request. Return true if it was agreeable, and 348478064Sume * caused action sca, false if it has been rejected or nak'ed, and 348578064Sume * caused action scn. (The return value is used to make the state 348678064Sume * transition decision in the state automaton.) 348778064Sume */ 348878064Sumestatic int 348978064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 349078064Sume{ 349178064Sume u_char *buf, *r, *p; 3492147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 349378064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 349478064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 349578064Sume int ifidcount; 349678064Sume int type; 349778064Sume int collision, nohisaddr; 3498165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 349978064Sume 350078064Sume len -= 4; 350178064Sume origlen = len; 350278064Sume /* 350378064Sume * Make sure to allocate a buf that can at least hold a 350478064Sume * conf-nak with an `address' option. We might need it below. 350578064Sume */ 350678064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 350778064Sume if (! buf) 350878064Sume return (0); 350978064Sume 351078064Sume /* pass 1: see if we can recognize them */ 351178064Sume if (debug) 351278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 351378064Sume SPP_ARGS(ifp)); 351478064Sume p = (void*) (h+1); 351578064Sume ifidcount = 0; 3516161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3517161556Scperciva len-=p[1], p+=p[1]) { 351878064Sume if (debug) 351978176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 352078064Sume switch (*p) { 352178064Sume case IPV6CP_OPT_IFID: 352278064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 352378064Sume /* correctly formed address option */ 352478064Sume ifidcount++; 352578064Sume continue; 352678064Sume } 352778064Sume if (debug) 352878176Sume log(-1, " [invalid]"); 352978064Sume break; 353078064Sume#ifdef notyet 353178064Sume case IPV6CP_OPT_COMPRESSION: 353278064Sume if (len >= 4 && p[1] >= 4) { 353378064Sume /* correctly formed compress option */ 353478064Sume continue; 353578064Sume } 353678064Sume if (debug) 353778176Sume log(-1, " [invalid]"); 353878064Sume break; 353978064Sume#endif 354078064Sume default: 354178064Sume /* Others not supported. */ 354278064Sume if (debug) 354378176Sume log(-1, " [rej]"); 354478064Sume break; 354578064Sume } 354678064Sume /* Add the option to rejected list. */ 354778064Sume bcopy (p, r, p[1]); 354878064Sume r += p[1]; 354978064Sume rlen += p[1]; 355078064Sume } 355178064Sume if (rlen) { 355278064Sume if (debug) 355378176Sume log(-1, " send conf-rej\n"); 355478064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 355578064Sume goto end; 355678064Sume } else if (debug) 355778176Sume log(-1, "\n"); 355878064Sume 355978064Sume /* pass 2: parse option values */ 356078064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 356178064Sume if (debug) 356278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 356378064Sume SPP_ARGS(ifp)); 356478064Sume p = (void*) (h+1); 356578064Sume len = origlen; 356678064Sume type = CONF_ACK; 3567161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3568161556Scperciva len-=p[1], p+=p[1]) { 356978064Sume if (debug) 357078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 357178064Sume switch (*p) { 357278064Sume#ifdef notyet 357378064Sume case IPV6CP_OPT_COMPRESSION: 357478064Sume continue; 357578064Sume#endif 357678064Sume case IPV6CP_OPT_IFID: 357778064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 357878064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 357978064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 358078064Sume &myaddr.s6_addr[8], 8) == 0); 358178064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 358278064Sume 358378064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3584148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 358578064Sume 358678064Sume if (!collision && !nohisaddr) { 358778064Sume /* no collision, hisaddr known - Conf-Ack */ 358878064Sume type = CONF_ACK; 358978064Sume 359078064Sume if (debug) { 359178176Sume log(-1, " %s [%s]", 3592165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3593165118Sbz sppp_cp_type_name(type)); 359478064Sume } 359578064Sume continue; 359678064Sume } 359778064Sume 3598250131Seadler bzero(&suggestaddr, sizeof(suggestaddr)); 359978064Sume if (collision && nohisaddr) { 360078064Sume /* collision, hisaddr unknown - Conf-Rej */ 360178064Sume type = CONF_REJ; 360278064Sume bzero(&p[2], 8); 360378064Sume } else { 360478064Sume /* 360578064Sume * - no collision, hisaddr unknown, or 360678064Sume * - collision, hisaddr known 360778064Sume * Conf-Nak, suggest hisaddr 360878064Sume */ 360978064Sume type = CONF_NAK; 361078064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 361178064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 361278064Sume } 361378064Sume if (debug) 3614165118Sbz log(-1, " %s [%s]", 3615165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3616165118Sbz sppp_cp_type_name(type)); 361778064Sume break; 361878064Sume } 361978064Sume /* Add the option to nak'ed list. */ 362078064Sume bcopy (p, r, p[1]); 362178064Sume r += p[1]; 362278064Sume rlen += p[1]; 362378064Sume } 362478064Sume 362578064Sume if (rlen == 0 && type == CONF_ACK) { 362678064Sume if (debug) 362778176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 362878064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 362978064Sume } else { 363078064Sume#ifdef DIAGNOSTIC 363178064Sume if (type == CONF_ACK) 363278064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 363378064Sume#endif 363478064Sume 363578064Sume if (debug) { 363678176Sume log(-1, " send %s suggest %s\n", 3637165118Sbz sppp_cp_type_name(type), 3638165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 363978064Sume } 364078064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 364178064Sume } 364278064Sume 364378064Sume end: 364478064Sume free (buf, M_TEMP); 364578064Sume return (rlen == 0); 364678064Sume} 364778064Sume 364878064Sume/* 364978064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 365078064Sume * negotiation. 365178064Sume */ 365278064Sumestatic void 365378064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 365478064Sume{ 365578064Sume u_char *buf, *p; 3656147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 365778064Sume int debug = ifp->if_flags & IFF_DEBUG; 365878064Sume 365978064Sume len -= 4; 366078064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 366178064Sume if (!buf) 366278064Sume return; 366378064Sume 366478064Sume if (debug) 366578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 366678064Sume SPP_ARGS(ifp)); 366778064Sume 366878064Sume p = (void*) (h+1); 3669161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3670161556Scperciva len -= p[1], p += p[1]) { 367178064Sume if (debug) 367278176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 367378064Sume switch (*p) { 367478064Sume case IPV6CP_OPT_IFID: 367578064Sume /* 367678064Sume * Peer doesn't grok address option. This is 367778064Sume * bad. XXX Should we better give up here? 367878064Sume */ 367978064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 368078064Sume break; 368178064Sume#ifdef notyet 368278064Sume case IPV6CP_OPT_COMPRESS: 368378064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 368478064Sume break; 368578064Sume#endif 368678064Sume } 368778064Sume } 368878064Sume if (debug) 368978176Sume log(-1, "\n"); 369078064Sume free (buf, M_TEMP); 369178064Sume return; 369278064Sume} 369378064Sume 369478064Sume/* 369578064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 369678064Sume * negotiation. 369778064Sume */ 369878064Sumestatic void 369978064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 370078064Sume{ 370178064Sume u_char *buf, *p; 3702147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 370378064Sume int debug = ifp->if_flags & IFF_DEBUG; 370478064Sume struct in6_addr suggestaddr; 3705165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 370678064Sume 370778064Sume len -= 4; 370878064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 370978064Sume if (!buf) 371078064Sume return; 371178064Sume 371278064Sume if (debug) 371378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 371478064Sume SPP_ARGS(ifp)); 371578064Sume 371678064Sume p = (void*) (h+1); 3717161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3718161556Scperciva len -= p[1], p += p[1]) { 371978064Sume if (debug) 372078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 372178064Sume switch (*p) { 372278064Sume case IPV6CP_OPT_IFID: 372378064Sume /* 372478064Sume * Peer doesn't like our local ifid. See 372578064Sume * if we can do something for him. We'll drop 372678064Sume * him our address then. 372778064Sume */ 372878064Sume if (len < 10 || p[1] != 10) 372978064Sume break; 373078064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 373178064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3732148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 373378064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 373478064Sume 373578064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 373678064Sume if (debug) 373778176Sume log(-1, " [suggestaddr %s]", 3738165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 373978064Sume#ifdef IPV6CP_MYIFID_DYN 374078064Sume /* 374178064Sume * When doing dynamic address assignment, 374278064Sume * we accept his offer. 374378064Sume */ 374478064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 374578064Sume struct in6_addr lastsuggest; 374678064Sume /* 374778064Sume * If <suggested myaddr from peer> equals to 374878064Sume * <hisaddr we have suggested last time>, 374978064Sume * we have a collision. generate new random 375078064Sume * ifid. 375178064Sume */ 375278064Sume sppp_suggest_ip6_addr(&lastsuggest); 375378064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 375478064Sume lastsuggest)) { 375578064Sume if (debug) 375678176Sume log(-1, " [random]"); 375778064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 375878064Sume } 375978064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 376078064Sume if (debug) 376178176Sume log(-1, " [agree]"); 376278064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 376378064Sume } 376478064Sume#else 376578064Sume /* 376678064Sume * Since we do not do dynamic address assignment, 376778064Sume * we ignore it and thus continue to negotiate 376878064Sume * our already existing value. This can possibly 376978064Sume * go into infinite request-reject loop. 377078064Sume * 377178064Sume * This is not likely because we normally use 377278064Sume * ifid based on MAC-address. 377378064Sume * If you have no ethernet card on the node, too bad. 377478064Sume * XXX should we use fail_counter? 377578064Sume */ 377678064Sume#endif 377778064Sume break; 377878064Sume#ifdef notyet 377978064Sume case IPV6CP_OPT_COMPRESS: 378078064Sume /* 378178064Sume * Peer wants different compression parameters. 378278064Sume */ 378378064Sume break; 378478064Sume#endif 378578064Sume } 378678064Sume } 378778064Sume if (debug) 378878176Sume log(-1, "\n"); 378978064Sume free (buf, M_TEMP); 379078064Sume return; 379178064Sume} 379278064Sumestatic void 379378064Sumesppp_ipv6cp_tlu(struct sppp *sp) 379478064Sume{ 379578064Sume /* we are up - notify isdn daemon */ 379678064Sume if (sp->pp_con) 379778064Sume sp->pp_con(sp); 379878064Sume} 379978064Sume 380078064Sumestatic void 380178064Sumesppp_ipv6cp_tld(struct sppp *sp) 380278064Sume{ 380378064Sume} 380478064Sume 380578064Sumestatic void 380678064Sumesppp_ipv6cp_tls(struct sppp *sp) 380778064Sume{ 380878064Sume /* indicate to LCP that it must stay alive */ 380978064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 381078064Sume} 381178064Sume 381278064Sumestatic void 381378064Sumesppp_ipv6cp_tlf(struct sppp *sp) 381478064Sume{ 381578064Sume 381678064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 381778064Sume /* we no longer need LCP */ 381878064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 381978064Sume sppp_lcp_check_and_close(sp); 382078064Sume#endif 382178064Sume} 382278064Sume 382378064Sumestatic void 382478064Sumesppp_ipv6cp_scr(struct sppp *sp) 382578064Sume{ 382678064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 382778064Sume struct in6_addr ouraddr; 382878064Sume int i = 0; 382978064Sume 383078064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 383178064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 383278064Sume opt[i++] = IPV6CP_OPT_IFID; 383378064Sume opt[i++] = 10; 383478064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 383578064Sume i += 8; 383678064Sume } 383778064Sume 383878064Sume#ifdef notyet 383978064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 384078064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 384178064Sume opt[i++] = 4; 384278064Sume opt[i++] = 0; /* TBD */ 384378064Sume opt[i++] = 0; /* TBD */ 384478064Sume /* variable length data may follow */ 384578064Sume } 384678064Sume#endif 384778064Sume 384878064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 384978064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 385078064Sume} 385178064Sume#else /*INET6*/ 385278064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 385378064Sume{ 385478064Sume} 385578064Sume 385678064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 385778064Sume{ 385878064Sume} 385978064Sume 386078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 386178064Sume{ 386278064Sume} 386378064Sume 386478064Sume 386578064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 386678064Sume{ 386778064Sume} 386878064Sume 386978064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 387078064Sume{ 387178064Sume} 387278064Sume 387378064Sumestatic void sppp_ipv6cp_TO(void *sp) 387478064Sume{ 387578064Sume} 387678064Sume 387778064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 387878064Sume{ 387978064Sume return 0; 388078064Sume} 388178064Sume 388278064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 388378064Sume{ 388478064Sume} 388578064Sume 388678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 388778064Sume{ 388878064Sume} 388978064Sume 389078064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 389178064Sume{ 389278064Sume} 389378064Sume 389478064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 389578064Sume{ 389678064Sume} 389778064Sume 389878064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 389978064Sume{ 390078064Sume} 390178064Sume 390278064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 390378064Sume{ 390478064Sume} 390578064Sume 390678064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 390778064Sume{ 390878064Sume} 390978064Sume#endif /*INET6*/ 391078064Sume 391178064Sume/* 391278064Sume *--------------------------------------------------------------------------* 391378064Sume * * 391430300Sjoerg * The CHAP implementation. * 391530300Sjoerg * * 391630300Sjoerg *--------------------------------------------------------------------------* 391730300Sjoerg */ 391830300Sjoerg 391930300Sjoerg/* 392030300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 392130300Sjoerg * the control protocols do, since they do have Open and Close events, but 392230300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 392330300Sjoerg * authentication protocols may be different in both directions (this makes 392430300Sjoerg * sense, think of a machine that never accepts incoming calls but only 392530300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 392630300Sjoerg * 392730300Sjoerg * Our state machine for the local authentication protocol (we are requesting 392830300Sjoerg * the peer to authenticate) looks like: 392930300Sjoerg * 393030300Sjoerg * RCA- 393130300Sjoerg * +--------------------------------------------+ 393230300Sjoerg * V scn,tld| 393330300Sjoerg * +--------+ Close +---------+ RCA+ 393430300Sjoerg * | |<----------------------------------| |------+ 393530300Sjoerg * +--->| Closed | TO* | Opened | sca | 393630300Sjoerg * | | |-----+ +-------| |<-----+ 393730300Sjoerg * | +--------+ irc | | +---------+ 393830300Sjoerg * | ^ | | ^ 393930300Sjoerg * | | | | | 394030300Sjoerg * | | | | | 394130300Sjoerg * | TO-| | | | 394230300Sjoerg * | |tld TO+ V | | 394330300Sjoerg * | | +------->+ | | 394430300Sjoerg * | | | | | | 394530300Sjoerg * | +--------+ V | | 394630300Sjoerg * | | |<----+<--------------------+ | 394730300Sjoerg * | | Req- | scr | 394830300Sjoerg * | | Sent | | 394930300Sjoerg * | | | | 395030300Sjoerg * | +--------+ | 395130300Sjoerg * | RCA- | | RCA+ | 395230300Sjoerg * +------+ +------------------------------------------+ 395330300Sjoerg * scn,tld sca,irc,ict,tlu 395430300Sjoerg * 395530300Sjoerg * 395630300Sjoerg * with: 395730300Sjoerg * 395830300Sjoerg * Open: LCP reached authentication phase 395930300Sjoerg * Close: LCP reached terminate phase 396030300Sjoerg * 396130300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 396230300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 396330300Sjoerg * TO+: timeout with restart counter >= 0 396430300Sjoerg * TO-: timeout with restart counter < 0 396530300Sjoerg * TO*: reschedule timeout for CHAP 396630300Sjoerg * 396730300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 396830300Sjoerg * sca: send ack packet (pap-ack, chap-success) 396930300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 397030300Sjoerg * ict: initialize re-challenge timer (CHAP only) 397130300Sjoerg * 397230300Sjoerg * tlu: this-layer-up, LCP reaches network phase 397330300Sjoerg * tld: this-layer-down, LCP enters terminate phase 397430300Sjoerg * 397530300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 397630300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 397730300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 397830300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 397930300Sjoerg * causing LCP to enter terminate phase. 398030300Sjoerg * 398130300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 398230300Sjoerg * expected to send one based on the successful negotiation of PAP as 398330300Sjoerg * the authentication protocol during the LCP option negotiation. 398430300Sjoerg * 398530300Sjoerg * Incoming authentication protocol requests (remote requests 398630300Sjoerg * authentication, we are peer) don't employ a state machine at all, 398730300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 398830300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 398930300Sjoerg * still in authentication phase (thereby violating the standard that 399030300Sjoerg * demands that these NCP packets are to be discarded), so we keep 399130300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 399230300Sjoerg * phase network once we've seen a positive acknowledge for the 399330300Sjoerg * authentication. 399430300Sjoerg */ 399530300Sjoerg 399630300Sjoerg/* 399730300Sjoerg * Handle incoming CHAP packets. 399830300Sjoerg */ 3999105228Sphkstatic void 400030300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 400130300Sjoerg{ 400230300Sjoerg STDDCL; 400330300Sjoerg struct lcp_header *h; 4004241686Sandre int len; 400530300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 400630300Sjoerg int value_len, name_len; 400730300Sjoerg MD5_CTX ctx; 400830300Sjoerg 400930300Sjoerg len = m->m_pkthdr.len; 401030300Sjoerg if (len < 4) { 401130300Sjoerg if (debug) 401230300Sjoerg log(LOG_DEBUG, 401340008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 401440008Sjoerg SPP_ARGS(ifp), len); 401530300Sjoerg return; 401630300Sjoerg } 401730300Sjoerg h = mtod (m, struct lcp_header*); 401830300Sjoerg if (len > ntohs (h->len)) 401930300Sjoerg len = ntohs (h->len); 402030300Sjoerg 402130300Sjoerg switch (h->type) { 402230300Sjoerg /* challenge, failure and success are his authproto */ 402330300Sjoerg case CHAP_CHALLENGE: 402430300Sjoerg value = 1 + (u_char*)(h+1); 402530300Sjoerg value_len = value[-1]; 402630300Sjoerg name = value + value_len; 402730300Sjoerg name_len = len - value_len - 5; 402830300Sjoerg if (name_len < 0) { 402930300Sjoerg if (debug) { 403030300Sjoerg log(LOG_DEBUG, 403140008Sjoerg SPP_FMT "chap corrupted challenge " 403230300Sjoerg "<%s id=0x%x len=%d", 403340008Sjoerg SPP_ARGS(ifp), 403430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 403530300Sjoerg h->ident, ntohs(h->len)); 403644145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 403769211Sphk log(-1, ">\n"); 403830300Sjoerg } 403930300Sjoerg break; 404030300Sjoerg } 404170199Sjhay 404230300Sjoerg if (debug) { 404330300Sjoerg log(LOG_DEBUG, 404440008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 404540008Sjoerg SPP_ARGS(ifp), 404630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 404730300Sjoerg ntohs(h->len)); 404830300Sjoerg sppp_print_string((char*) name, name_len); 404969211Sphk log(-1, " value-size=%d value=", value_len); 405030300Sjoerg sppp_print_bytes(value, value_len); 405169211Sphk log(-1, ">\n"); 405230300Sjoerg } 405330300Sjoerg 405430300Sjoerg /* Compute reply value. */ 405530300Sjoerg MD5Init(&ctx); 405630300Sjoerg MD5Update(&ctx, &h->ident, 1); 405730300Sjoerg MD5Update(&ctx, sp->myauth.secret, 405830300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 405930300Sjoerg MD5Update(&ctx, value, value_len); 406030300Sjoerg MD5Final(digest, &ctx); 406130300Sjoerg dsize = sizeof digest; 406230300Sjoerg 406330300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 406430300Sjoerg sizeof dsize, (const char *)&dsize, 406530300Sjoerg sizeof digest, digest, 406640008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 406730300Sjoerg sp->myauth.name, 406830300Sjoerg 0); 406930300Sjoerg break; 407030300Sjoerg 407130300Sjoerg case CHAP_SUCCESS: 407230300Sjoerg if (debug) { 407340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 407440008Sjoerg SPP_ARGS(ifp)); 407530300Sjoerg if (len > 4) { 407669211Sphk log(-1, ": "); 407730300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 407830300Sjoerg } 407969211Sphk log(-1, "\n"); 408030300Sjoerg } 4081138745Srik SPPP_LOCK(sp); 408230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 408330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 408432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 408530300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 408630300Sjoerg /* 408730300Sjoerg * We are authenticator for CHAP but didn't 408830300Sjoerg * complete yet. Leave it to tlu to proceed 408930300Sjoerg * to network phase. 409030300Sjoerg */ 4091138745Srik SPPP_UNLOCK(sp); 409230300Sjoerg break; 409330300Sjoerg } 4094138745Srik SPPP_UNLOCK(sp); 409530300Sjoerg sppp_phase_network(sp); 409630300Sjoerg break; 409730300Sjoerg 409830300Sjoerg case CHAP_FAILURE: 409930300Sjoerg if (debug) { 410040008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 410140008Sjoerg SPP_ARGS(ifp)); 410230300Sjoerg if (len > 4) { 410369211Sphk log(-1, ": "); 410430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 410530300Sjoerg } 410669211Sphk log(-1, "\n"); 410730300Sjoerg } else 410840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 410940008Sjoerg SPP_ARGS(ifp)); 411030300Sjoerg /* await LCP shutdown by authenticator */ 411130300Sjoerg break; 411230300Sjoerg 411330300Sjoerg /* response is my authproto */ 411430300Sjoerg case CHAP_RESPONSE: 411530300Sjoerg value = 1 + (u_char*)(h+1); 411630300Sjoerg value_len = value[-1]; 411730300Sjoerg name = value + value_len; 411830300Sjoerg name_len = len - value_len - 5; 411930300Sjoerg if (name_len < 0) { 412030300Sjoerg if (debug) { 412130300Sjoerg log(LOG_DEBUG, 412240008Sjoerg SPP_FMT "chap corrupted response " 412330300Sjoerg "<%s id=0x%x len=%d", 412440008Sjoerg SPP_ARGS(ifp), 412530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 412630300Sjoerg h->ident, ntohs(h->len)); 412744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 412869211Sphk log(-1, ">\n"); 412930300Sjoerg } 413030300Sjoerg break; 413130300Sjoerg } 413230300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 413330300Sjoerg if (debug) 413430300Sjoerg log(LOG_DEBUG, 413540008Sjoerg SPP_FMT "chap dropping response for old ID " 413630300Sjoerg "(got %d, expected %d)\n", 413740008Sjoerg SPP_ARGS(ifp), 413830300Sjoerg h->ident, sp->confid[IDX_CHAP]); 413930300Sjoerg break; 414030300Sjoerg } 414130300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 414230300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 414340008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 414440008Sjoerg SPP_ARGS(ifp)); 414530300Sjoerg sppp_print_string(name, name_len); 414669211Sphk log(-1, " != expected "); 414730300Sjoerg sppp_print_string(sp->hisauth.name, 414830300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 414969211Sphk log(-1, "\n"); 415070199Sjhay } 415130300Sjoerg if (debug) { 415240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 415330300Sjoerg "<%s id=0x%x len=%d name=", 415440008Sjoerg SPP_ARGS(ifp), 415530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 415630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 415730300Sjoerg h->ident, ntohs (h->len)); 415830300Sjoerg sppp_print_string((char*)name, name_len); 415969211Sphk log(-1, " value-size=%d value=", value_len); 416030300Sjoerg sppp_print_bytes(value, value_len); 416169211Sphk log(-1, ">\n"); 416230300Sjoerg } 416330300Sjoerg if (value_len != AUTHKEYLEN) { 416430300Sjoerg if (debug) 416530300Sjoerg log(LOG_DEBUG, 416640008Sjoerg SPP_FMT "chap bad hash value length: " 416730300Sjoerg "%d bytes, should be %d\n", 416840008Sjoerg SPP_ARGS(ifp), value_len, 416930300Sjoerg AUTHKEYLEN); 417030300Sjoerg break; 417130300Sjoerg } 417230300Sjoerg 417330300Sjoerg MD5Init(&ctx); 417430300Sjoerg MD5Update(&ctx, &h->ident, 1); 417530300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 417630300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 417730300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 417830300Sjoerg MD5Final(digest, &ctx); 417930300Sjoerg 418030300Sjoerg#define FAILMSG "Failed..." 418130300Sjoerg#define SUCCMSG "Welcome!" 418230300Sjoerg 418330300Sjoerg if (value_len != sizeof digest || 418430300Sjoerg bcmp(digest, value, value_len) != 0) { 418530300Sjoerg /* action scn, tld */ 418630300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 418730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 418830300Sjoerg 0); 418930300Sjoerg chap.tld(sp); 419030300Sjoerg break; 419130300Sjoerg } 419230300Sjoerg /* action sca, perhaps tlu */ 419330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 419430300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 419530300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 419630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 419730300Sjoerg 0); 419830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 419930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 420030300Sjoerg chap.tlu(sp); 420130300Sjoerg } 420230300Sjoerg break; 420330300Sjoerg 420430300Sjoerg default: 420530300Sjoerg /* Unknown CHAP packet type -- ignore. */ 420630300Sjoerg if (debug) { 420740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 420830300Sjoerg "<0x%x id=0x%xh len=%d", 420940008Sjoerg SPP_ARGS(ifp), 421030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 421130300Sjoerg h->type, h->ident, ntohs(h->len)); 421244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 421369211Sphk log(-1, ">\n"); 421430300Sjoerg } 421530300Sjoerg break; 421630300Sjoerg 421730300Sjoerg } 421830300Sjoerg} 421930300Sjoerg 422030300Sjoergstatic void 422130300Sjoergsppp_chap_init(struct sppp *sp) 422230300Sjoerg{ 422330300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 422430300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 422530300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 422678064Sume sp->pp_seq[IDX_CHAP] = 0; 422778064Sume sp->pp_rseq[IDX_CHAP] = 0; 4228188668Srwatson callout_init(&sp->ch[IDX_CHAP], CALLOUT_MPSAFE); 422930300Sjoerg} 423030300Sjoerg 423130300Sjoergstatic void 423230300Sjoergsppp_chap_open(struct sppp *sp) 423330300Sjoerg{ 423430300Sjoerg if (sp->myauth.proto == PPP_CHAP && 423530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 423630300Sjoerg /* we are authenticator for CHAP, start it */ 423730300Sjoerg chap.scr(sp); 423830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 423930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 424030300Sjoerg } 424130300Sjoerg /* nothing to be done if we are peer, await a challenge */ 424230300Sjoerg} 424330300Sjoerg 424430300Sjoergstatic void 424530300Sjoergsppp_chap_close(struct sppp *sp) 424630300Sjoerg{ 424730300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 424830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 424930300Sjoerg} 425030300Sjoerg 425130300Sjoergstatic void 425230300Sjoergsppp_chap_TO(void *cookie) 425330300Sjoerg{ 425430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 425530300Sjoerg STDDCL; 425630300Sjoerg 4257138745Srik SPPP_LOCK(sp); 425830300Sjoerg if (debug) 425940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 426040008Sjoerg SPP_ARGS(ifp), 426130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 426230300Sjoerg sp->rst_counter[IDX_CHAP]); 426330300Sjoerg 426430300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 426530300Sjoerg /* TO- event */ 426630300Sjoerg switch (sp->state[IDX_CHAP]) { 426730300Sjoerg case STATE_REQ_SENT: 426830300Sjoerg chap.tld(sp); 426930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 427030300Sjoerg break; 427130300Sjoerg } 427230300Sjoerg else 427330300Sjoerg /* TO+ (or TO*) event */ 427430300Sjoerg switch (sp->state[IDX_CHAP]) { 427530300Sjoerg case STATE_OPENED: 427630300Sjoerg /* TO* event */ 427730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4278102412Scharnier /* FALLTHROUGH */ 427930300Sjoerg case STATE_REQ_SENT: 428030300Sjoerg chap.scr(sp); 428130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 428230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 428330300Sjoerg break; 428430300Sjoerg } 428530300Sjoerg 4286138745Srik SPPP_UNLOCK(sp); 428730300Sjoerg} 428830300Sjoerg 428930300Sjoergstatic void 429030300Sjoergsppp_chap_tlu(struct sppp *sp) 429130300Sjoerg{ 429230300Sjoerg STDDCL; 4293241686Sandre int i; 429430300Sjoerg 429540010Sjoerg i = 0; 429630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 429730300Sjoerg 429830300Sjoerg /* 429930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 430030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 430130300Sjoerg * initial challenge-response exchange has taken place. 430230300Sjoerg * Provide for an option to avoid rechallenges. 430330300Sjoerg */ 430430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 430530300Sjoerg /* 430630300Sjoerg * Compute the re-challenge timeout. This will yield 430730300Sjoerg * a number between 300 and 810 seconds. 430830300Sjoerg */ 430930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4310138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 431130300Sjoerg } 431230300Sjoerg 431330300Sjoerg if (debug) { 431430300Sjoerg log(LOG_DEBUG, 431540008Sjoerg SPP_FMT "chap %s, ", 431640008Sjoerg SPP_ARGS(ifp), 431730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 431830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 431969211Sphk log(-1, "next re-challenge in %d seconds\n", i); 432030300Sjoerg else 432169211Sphk log(-1, "re-challenging supressed\n"); 432230300Sjoerg } 432330300Sjoerg 4324138745Srik SPPP_LOCK(sp); 432530300Sjoerg /* indicate to LCP that we need to be closed down */ 432630300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 432730300Sjoerg 432830300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 432930300Sjoerg /* 433030300Sjoerg * Remote is authenticator, but his auth proto didn't 433130300Sjoerg * complete yet. Defer the transition to network 433230300Sjoerg * phase. 433330300Sjoerg */ 4334138745Srik SPPP_UNLOCK(sp); 433530300Sjoerg return; 433630300Sjoerg } 4337138745Srik SPPP_UNLOCK(sp); 433830300Sjoerg 433930300Sjoerg /* 434030300Sjoerg * If we are already in phase network, we are done here. This 434130300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 434230300Sjoerg */ 434330300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 434430300Sjoerg sppp_phase_network(sp); 434530300Sjoerg} 434630300Sjoerg 434730300Sjoergstatic void 434830300Sjoergsppp_chap_tld(struct sppp *sp) 434930300Sjoerg{ 435030300Sjoerg STDDCL; 435130300Sjoerg 435230300Sjoerg if (debug) 435340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4354138745Srik callout_stop(&sp->ch[IDX_CHAP]); 435530300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 435630300Sjoerg 435730300Sjoerg lcp.Close(sp); 435830300Sjoerg} 435930300Sjoerg 436030300Sjoergstatic void 436130300Sjoergsppp_chap_scr(struct sppp *sp) 436230300Sjoerg{ 436330300Sjoerg u_long *ch, seed; 436430300Sjoerg u_char clen; 436530300Sjoerg 436630300Sjoerg /* Compute random challenge. */ 436730300Sjoerg ch = (u_long *)sp->myauth.challenge; 436835064Sphk read_random(&seed, sizeof seed); 436930300Sjoerg ch[0] = seed ^ random(); 437030300Sjoerg ch[1] = seed ^ random(); 437130300Sjoerg ch[2] = seed ^ random(); 437230300Sjoerg ch[3] = seed ^ random(); 437330300Sjoerg clen = AUTHKEYLEN; 437430300Sjoerg 437578064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 437630300Sjoerg 437730300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 437830300Sjoerg sizeof clen, (const char *)&clen, 437940008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 438040008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 438130300Sjoerg sp->myauth.name, 438230300Sjoerg 0); 438330300Sjoerg} 438470199Sjhay 438570199Sjhay/* 438630300Sjoerg *--------------------------------------------------------------------------* 438730300Sjoerg * * 438830300Sjoerg * The PAP implementation. * 438930300Sjoerg * * 439030300Sjoerg *--------------------------------------------------------------------------* 439130300Sjoerg */ 439230300Sjoerg/* 439330300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 439430300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 439530300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 439630300Sjoerg * retry counter is expired). 439730300Sjoerg */ 439830300Sjoerg 439930300Sjoerg/* 440030300Sjoerg * Handle incoming PAP packets. */ 440130300Sjoergstatic void 440230300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 440330300Sjoerg{ 440430300Sjoerg STDDCL; 440530300Sjoerg struct lcp_header *h; 4406241686Sandre int len; 440730300Sjoerg u_char *name, *passwd, mlen; 440830300Sjoerg int name_len, passwd_len; 440930300Sjoerg 441030300Sjoerg len = m->m_pkthdr.len; 441130300Sjoerg if (len < 5) { 441230300Sjoerg if (debug) 441330300Sjoerg log(LOG_DEBUG, 441440008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 441540008Sjoerg SPP_ARGS(ifp), len); 441630300Sjoerg return; 441730300Sjoerg } 441830300Sjoerg h = mtod (m, struct lcp_header*); 441930300Sjoerg if (len > ntohs (h->len)) 442030300Sjoerg len = ntohs (h->len); 442130300Sjoerg switch (h->type) { 442230300Sjoerg /* PAP request is my authproto */ 442330300Sjoerg case PAP_REQ: 442430300Sjoerg name = 1 + (u_char*)(h+1); 442530300Sjoerg name_len = name[-1]; 442630300Sjoerg passwd = name + name_len + 1; 442730300Sjoerg if (name_len > len - 6 || 442830300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 442930300Sjoerg if (debug) { 443040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 443130300Sjoerg "<%s id=0x%x len=%d", 443240008Sjoerg SPP_ARGS(ifp), 443330300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 443430300Sjoerg h->ident, ntohs(h->len)); 443544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 443669211Sphk log(-1, ">\n"); 443730300Sjoerg } 443830300Sjoerg break; 443930300Sjoerg } 444030300Sjoerg if (debug) { 444140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 444230300Sjoerg "<%s id=0x%x len=%d name=", 444340008Sjoerg SPP_ARGS(ifp), 444430300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 444530300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 444630300Sjoerg h->ident, ntohs(h->len)); 444730300Sjoerg sppp_print_string((char*)name, name_len); 444869211Sphk log(-1, " passwd="); 444930300Sjoerg sppp_print_string((char*)passwd, passwd_len); 445069211Sphk log(-1, ">\n"); 445130300Sjoerg } 445274774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 445374774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 445430300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 445530300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 445630300Sjoerg /* action scn, tld */ 445730300Sjoerg mlen = sizeof(FAILMSG) - 1; 445830300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 445930300Sjoerg sizeof mlen, (const char *)&mlen, 446030300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 446130300Sjoerg 0); 446230300Sjoerg pap.tld(sp); 446330300Sjoerg break; 446430300Sjoerg } 446530300Sjoerg /* action sca, perhaps tlu */ 446630300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 446730300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 446830300Sjoerg mlen = sizeof(SUCCMSG) - 1; 446930300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 447030300Sjoerg sizeof mlen, (const char *)&mlen, 447130300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 447230300Sjoerg 0); 447330300Sjoerg } 447430300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 447530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 447630300Sjoerg pap.tlu(sp); 447730300Sjoerg } 447830300Sjoerg break; 447930300Sjoerg 448030300Sjoerg /* ack and nak are his authproto */ 448130300Sjoerg case PAP_ACK: 4482138745Srik callout_stop(&sp->pap_my_to_ch); 448330300Sjoerg if (debug) { 448440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 448540008Sjoerg SPP_ARGS(ifp)); 448630300Sjoerg name_len = *((char *)h); 448730300Sjoerg if (len > 5 && name_len) { 448869211Sphk log(-1, ": "); 448930300Sjoerg sppp_print_string((char*)(h+1), name_len); 449030300Sjoerg } 449169211Sphk log(-1, "\n"); 449230300Sjoerg } 4493138745Srik SPPP_LOCK(sp); 449430300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 449530300Sjoerg if (sp->myauth.proto == PPP_PAP && 449632169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 449730300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 449830300Sjoerg /* 449930300Sjoerg * We are authenticator for PAP but didn't 450030300Sjoerg * complete yet. Leave it to tlu to proceed 450130300Sjoerg * to network phase. 450230300Sjoerg */ 4503138745Srik SPPP_UNLOCK(sp); 450430300Sjoerg break; 450530300Sjoerg } 4506138745Srik SPPP_UNLOCK(sp); 450730300Sjoerg sppp_phase_network(sp); 450830300Sjoerg break; 450930300Sjoerg 451030300Sjoerg case PAP_NAK: 4511138745Srik callout_stop (&sp->pap_my_to_ch); 451230300Sjoerg if (debug) { 451340008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 451440008Sjoerg SPP_ARGS(ifp)); 451530300Sjoerg name_len = *((char *)h); 451630300Sjoerg if (len > 5 && name_len) { 451769211Sphk log(-1, ": "); 451830300Sjoerg sppp_print_string((char*)(h+1), name_len); 451930300Sjoerg } 452069211Sphk log(-1, "\n"); 452130300Sjoerg } else 452240008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 452340008Sjoerg SPP_ARGS(ifp)); 452430300Sjoerg /* await LCP shutdown by authenticator */ 452530300Sjoerg break; 452630300Sjoerg 452730300Sjoerg default: 452830300Sjoerg /* Unknown PAP packet type -- ignore. */ 452930300Sjoerg if (debug) { 453040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 453130300Sjoerg "<0x%x id=0x%x len=%d", 453240008Sjoerg SPP_ARGS(ifp), 453330300Sjoerg h->type, h->ident, ntohs(h->len)); 453444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 453569211Sphk log(-1, ">\n"); 453630300Sjoerg } 453730300Sjoerg break; 453830300Sjoerg 453930300Sjoerg } 454030300Sjoerg} 454130300Sjoerg 454230300Sjoergstatic void 454330300Sjoergsppp_pap_init(struct sppp *sp) 454430300Sjoerg{ 454530300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 454630300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 454730300Sjoerg sp->fail_counter[IDX_PAP] = 0; 454878064Sume sp->pp_seq[IDX_PAP] = 0; 454978064Sume sp->pp_rseq[IDX_PAP] = 0; 4550188668Srwatson callout_init(&sp->ch[IDX_PAP], CALLOUT_MPSAFE); 4551188668Srwatson callout_init(&sp->pap_my_to_ch, CALLOUT_MPSAFE); 455230300Sjoerg} 455330300Sjoerg 455430300Sjoergstatic void 455530300Sjoergsppp_pap_open(struct sppp *sp) 455630300Sjoerg{ 455730300Sjoerg if (sp->hisauth.proto == PPP_PAP && 455830300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 455930300Sjoerg /* we are authenticator for PAP, start our timer */ 456030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 456130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 456230300Sjoerg } 456330300Sjoerg if (sp->myauth.proto == PPP_PAP) { 456430300Sjoerg /* we are peer, send a request, and start a timer */ 456530300Sjoerg pap.scr(sp); 4566138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4567138745Srik sppp_pap_my_TO, (void *)sp); 456830300Sjoerg } 456930300Sjoerg} 457030300Sjoerg 457130300Sjoergstatic void 457230300Sjoergsppp_pap_close(struct sppp *sp) 457330300Sjoerg{ 457430300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 457530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 457630300Sjoerg} 457730300Sjoerg 457830300Sjoerg/* 457930300Sjoerg * That's the timeout routine if we are authenticator. Since the 458030300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 458130300Sjoerg */ 458230300Sjoergstatic void 458330300Sjoergsppp_pap_TO(void *cookie) 458430300Sjoerg{ 458530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 458630300Sjoerg STDDCL; 458730300Sjoerg 4588138745Srik SPPP_LOCK(sp); 458930300Sjoerg if (debug) 459040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 459140008Sjoerg SPP_ARGS(ifp), 459230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 459330300Sjoerg sp->rst_counter[IDX_PAP]); 459430300Sjoerg 459530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 459630300Sjoerg /* TO- event */ 459730300Sjoerg switch (sp->state[IDX_PAP]) { 459830300Sjoerg case STATE_REQ_SENT: 459930300Sjoerg pap.tld(sp); 460030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 460130300Sjoerg break; 460230300Sjoerg } 460330300Sjoerg else 460430300Sjoerg /* TO+ event, not very much we could do */ 460530300Sjoerg switch (sp->state[IDX_PAP]) { 460630300Sjoerg case STATE_REQ_SENT: 460730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 460830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 460930300Sjoerg break; 461030300Sjoerg } 461130300Sjoerg 4612138745Srik SPPP_UNLOCK(sp); 461330300Sjoerg} 461430300Sjoerg 461530300Sjoerg/* 461630300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 461730300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 461830300Sjoerg * XXX We should impose a max counter. 461930300Sjoerg */ 462030300Sjoergstatic void 462130300Sjoergsppp_pap_my_TO(void *cookie) 462230300Sjoerg{ 462330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 462430300Sjoerg STDDCL; 462530300Sjoerg 462630300Sjoerg if (debug) 462740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 462840008Sjoerg SPP_ARGS(ifp)); 462930300Sjoerg 4630138745Srik SPPP_LOCK(sp); 463130300Sjoerg pap.scr(sp); 4632138745Srik SPPP_UNLOCK(sp); 463330300Sjoerg} 463430300Sjoerg 463530300Sjoergstatic void 463630300Sjoergsppp_pap_tlu(struct sppp *sp) 463730300Sjoerg{ 463830300Sjoerg STDDCL; 463930300Sjoerg 464030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 464130300Sjoerg 464230300Sjoerg if (debug) 464340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 464440008Sjoerg SPP_ARGS(ifp), pap.name); 464530300Sjoerg 4646138745Srik SPPP_LOCK(sp); 464730300Sjoerg /* indicate to LCP that we need to be closed down */ 464830300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 464930300Sjoerg 465030300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 465130300Sjoerg /* 465230300Sjoerg * Remote is authenticator, but his auth proto didn't 465330300Sjoerg * complete yet. Defer the transition to network 465430300Sjoerg * phase. 465530300Sjoerg */ 4656138745Srik SPPP_UNLOCK(sp); 465730300Sjoerg return; 465830300Sjoerg } 4659138745Srik SPPP_UNLOCK(sp); 466030300Sjoerg sppp_phase_network(sp); 466130300Sjoerg} 466230300Sjoerg 466330300Sjoergstatic void 466430300Sjoergsppp_pap_tld(struct sppp *sp) 466530300Sjoerg{ 466630300Sjoerg STDDCL; 466730300Sjoerg 466830300Sjoerg if (debug) 466940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4670138745Srik callout_stop (&sp->ch[IDX_PAP]); 4671138745Srik callout_stop (&sp->pap_my_to_ch); 467230300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 467330300Sjoerg 467430300Sjoerg lcp.Close(sp); 467530300Sjoerg} 467630300Sjoerg 467730300Sjoergstatic void 467830300Sjoergsppp_pap_scr(struct sppp *sp) 467930300Sjoerg{ 468030300Sjoerg u_char idlen, pwdlen; 468130300Sjoerg 468278064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 468330300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 468430300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 468530300Sjoerg 468630300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 468730300Sjoerg sizeof idlen, (const char *)&idlen, 468840008Sjoerg (size_t)idlen, sp->myauth.name, 468930300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 469040008Sjoerg (size_t)pwdlen, sp->myauth.secret, 469130300Sjoerg 0); 469230300Sjoerg} 469370199Sjhay 469470199Sjhay/* 469525944Sjoerg * Random miscellaneous functions. 469625944Sjoerg */ 469725944Sjoerg 46984910Swollman/* 469930300Sjoerg * Send a PAP or CHAP proto packet. 470030300Sjoerg * 470130300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 470240008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 470330300Sjoerg * mlen == 0. 470442104Sphk * NOTE: never declare variadic functions with types subject to type 470542104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 470642104Sphk * on the architecture you are on... 470730300Sjoerg */ 470830300Sjoerg 470930300Sjoergstatic void 471042104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 471142104Sphk unsigned int type, unsigned int id, 471230300Sjoerg ...) 471330300Sjoerg{ 471430300Sjoerg STDDCL; 471530300Sjoerg struct ppp_header *h; 471630300Sjoerg struct lcp_header *lh; 471730300Sjoerg struct mbuf *m; 471830300Sjoerg u_char *p; 471930300Sjoerg int len; 472042104Sphk unsigned int mlen; 472130300Sjoerg const char *msg; 472230300Sjoerg va_list ap; 472330300Sjoerg 4724243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 472530300Sjoerg if (! m) 472630300Sjoerg return; 472730300Sjoerg m->m_pkthdr.rcvif = 0; 472830300Sjoerg 472930300Sjoerg h = mtod (m, struct ppp_header*); 473030300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 473130300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 473230300Sjoerg h->protocol = htons(cp->proto); 473330300Sjoerg 473430300Sjoerg lh = (struct lcp_header*)(h + 1); 473530300Sjoerg lh->type = type; 473630300Sjoerg lh->ident = id; 473730300Sjoerg p = (u_char*) (lh+1); 473830300Sjoerg 473930300Sjoerg va_start(ap, id); 474030300Sjoerg len = 0; 474130300Sjoerg 474242104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 474330300Sjoerg msg = va_arg(ap, const char *); 474430300Sjoerg len += mlen; 474530300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 474630300Sjoerg va_end(ap); 474730300Sjoerg m_freem(m); 474830300Sjoerg return; 474930300Sjoerg } 475030300Sjoerg 475130300Sjoerg bcopy(msg, p, mlen); 475230300Sjoerg p += mlen; 475330300Sjoerg } 475430300Sjoerg va_end(ap); 475530300Sjoerg 475630300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 475730300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 475830300Sjoerg 475930300Sjoerg if (debug) { 476040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 476140008Sjoerg SPP_ARGS(ifp), cp->name, 476230300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 476330300Sjoerg lh->ident, ntohs(lh->len)); 476444145Sphk sppp_print_bytes((u_char*) (lh+1), len); 476569211Sphk log(-1, ">\n"); 476630300Sjoerg } 476769152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 476869152Sjlemon ifp->if_oerrors++; 476930300Sjoerg} 477030300Sjoerg 477130300Sjoerg/* 477225944Sjoerg * Flush interface queue. 47734910Swollman */ 477412820Sphkstatic void 477525944Sjoergsppp_qflush(struct ifqueue *ifq) 47764910Swollman{ 477725944Sjoerg struct mbuf *m, *n; 47784910Swollman 477925944Sjoerg n = ifq->ifq_head; 478025944Sjoerg while ((m = n)) { 478125944Sjoerg n = m->m_act; 478225944Sjoerg m_freem (m); 478311189Sjkh } 478425944Sjoerg ifq->ifq_head = 0; 478525944Sjoerg ifq->ifq_tail = 0; 478625944Sjoerg ifq->ifq_len = 0; 478725944Sjoerg} 478825944Sjoerg 478925944Sjoerg/* 479025944Sjoerg * Send keepalive packets, every 10 seconds. 479125944Sjoerg */ 479225944Sjoergstatic void 479325944Sjoergsppp_keepalive(void *dummy) 479425944Sjoerg{ 4795138745Srik struct sppp *sp = (struct sppp*)dummy; 4796147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 479725944Sjoerg 4798138745Srik SPPP_LOCK(sp); 4799138745Srik /* Keepalive mode disabled or channel down? */ 4800138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4801148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4802138745Srik goto out; 480325944Sjoerg 4804139365Srik if (sp->pp_mode == PP_FR) { 4805139365Srik sppp_fr_keepalive (sp); 4806139365Srik goto out; 4807139365Srik } 4808139365Srik 4809138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4810138745Srik if (sp->pp_mode != IFF_CISCO && 4811138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4812138745Srik goto out; 481325944Sjoerg 4814138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4815138745Srik /* No keepalive packets got. Stop the interface. */ 4816138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4817138745Srik if_down (ifp); 4818138745Srik sppp_qflush (&sp->pp_cpq); 4819138745Srik if (sp->pp_mode != IFF_CISCO) { 4820138745Srik /* XXX */ 4821138745Srik /* Shut down the PPP link. */ 4822138745Srik lcp.Down(sp); 4823138745Srik /* Initiate negotiation. XXX */ 4824138745Srik lcp.Up(sp); 48254910Swollman } 48264910Swollman } 4827138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4828138745Srik ++sp->pp_alivecnt; 4829138745Srik if (sp->pp_mode == IFF_CISCO) 4830138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4831138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4832138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4833138745Srik long nmagic = htonl (sp->lcp.magic); 4834138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4835138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4836138745Srik sp->lcp.echoid, 4, &nmagic); 4837138745Srik } 4838138745Srikout: 4839138745Srik SPPP_UNLOCK(sp); 4840138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4841138745Srik (void *)sp); 48424910Swollman} 48434910Swollman 484425944Sjoerg/* 484525944Sjoerg * Get both IP addresses. 484625944Sjoerg */ 4847139365Srikvoid 484830300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 484925944Sjoerg{ 4850147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 485125944Sjoerg struct ifaddr *ifa; 485230300Sjoerg struct sockaddr_in *si, *sm; 485325944Sjoerg u_long ssrc, ddst; 485425944Sjoerg 485540010Sjoerg sm = NULL; 485625944Sjoerg ssrc = ddst = 0L; 485725944Sjoerg /* 485825944Sjoerg * Pick the first AF_INET address from the list, 485925944Sjoerg * aliases don't make any sense on a p2p link anyway. 486025944Sjoerg */ 486142065Sphk si = 0; 4862195070Srwatson if_addr_rlock(ifp); 486342065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 486425944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 486525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 486630300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 486725944Sjoerg if (si) 486825944Sjoerg break; 486925944Sjoerg } 487025944Sjoerg if (ifa) { 487130300Sjoerg if (si && si->sin_addr.s_addr) { 487225944Sjoerg ssrc = si->sin_addr.s_addr; 487330300Sjoerg if (srcmask) 487430300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 487530300Sjoerg } 487625944Sjoerg 487725944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 487825944Sjoerg if (si && si->sin_addr.s_addr) 487925944Sjoerg ddst = si->sin_addr.s_addr; 488025944Sjoerg } 4881195070Srwatson if_addr_runlock(ifp); 488225944Sjoerg 488325944Sjoerg if (dst) *dst = ntohl(ddst); 488425944Sjoerg if (src) *src = ntohl(ssrc); 488525944Sjoerg} 488625944Sjoerg 4887184682Sbz#ifdef INET 488825944Sjoerg/* 4889241686Sandre * Set my IP address. 489025944Sjoerg */ 489125944Sjoergstatic void 489225944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 489325944Sjoerg{ 489442104Sphk STDDCL; 489525944Sjoerg struct ifaddr *ifa; 489625944Sjoerg struct sockaddr_in *si; 489784318Sjlemon struct in_ifaddr *ia; 489825944Sjoerg 489925944Sjoerg /* 490025944Sjoerg * Pick the first AF_INET address from the list, 490125944Sjoerg * aliases don't make any sense on a p2p link anyway. 490225944Sjoerg */ 490342065Sphk si = 0; 4904195070Srwatson if_addr_rlock(ifp); 4905194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 4906194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET) { 490725944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 4908194813Srwatson if (si != NULL) { 4909194813Srwatson ifa_ref(ifa); 491025944Sjoerg break; 4911194813Srwatson } 491225944Sjoerg } 491340008Sjoerg } 4914195070Srwatson if_addr_runlock(ifp); 491540008Sjoerg 4916194813Srwatson if (ifa != NULL) { 491742104Sphk int error; 4918194813Srwatson 491942104Sphk /* delete old route */ 492042104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 4921194813Srwatson if (debug && error) { 492242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 492342104Sphk SPP_ARGS(ifp), error); 492442104Sphk } 492542104Sphk 492642104Sphk /* set new address */ 492725944Sjoerg si->sin_addr.s_addr = htonl(src); 492884318Sjlemon ia = ifatoia(ifa); 4929194951Srwatson IN_IFADDR_WLOCK(); 493084318Sjlemon LIST_REMOVE(ia, ia_hash); 493184318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 4932194951Srwatson IN_IFADDR_WUNLOCK(); 493325944Sjoerg 493442104Sphk /* add new route */ 493570199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 4936194813Srwatson if (debug && error) { 493742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 493842104Sphk SPP_ARGS(ifp), error); 493942104Sphk } 4940194813Srwatson ifa_free(ifa); 494142104Sphk } 494288599Sjoerg} 4943184682Sbz#endif 494478064Sume 494578064Sume#ifdef INET6 494678064Sume/* 494778064Sume * Get both IPv6 addresses. 494878064Sume */ 494978064Sumestatic void 495078064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 495178064Sume struct in6_addr *srcmask) 495278064Sume{ 4953147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 495478064Sume struct ifaddr *ifa; 495578064Sume struct sockaddr_in6 *si, *sm; 495678064Sume struct in6_addr ssrc, ddst; 495778064Sume 495878064Sume sm = NULL; 495978064Sume bzero(&ssrc, sizeof(ssrc)); 496078064Sume bzero(&ddst, sizeof(ddst)); 496178064Sume /* 496278064Sume * Pick the first link-local AF_INET6 address from the list, 496378064Sume * aliases don't make any sense on a p2p link anyway. 496478064Sume */ 4965194813Srwatson si = NULL; 4966195070Srwatson if_addr_rlock(ifp); 4967160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 496878064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 496978064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 497078064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 497178064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 497278064Sume break; 497378064Sume } 497478064Sume if (ifa) { 497578064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 497678064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 497778064Sume if (srcmask) { 497878064Sume bcopy(&sm->sin6_addr, srcmask, 497978064Sume sizeof(*srcmask)); 498078064Sume } 498178064Sume } 498278064Sume 498378064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 498478064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 498578064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 498678064Sume } 498778064Sume 498878064Sume if (dst) 498978064Sume bcopy(&ddst, dst, sizeof(*dst)); 499078064Sume if (src) 499178064Sume bcopy(&ssrc, src, sizeof(*src)); 4992195070Srwatson if_addr_runlock(ifp); 499370199Sjhay} 499442104Sphk 499578064Sume#ifdef IPV6CP_MYIFID_DYN 499678064Sume/* 499778064Sume * Generate random ifid. 499878064Sume */ 499978064Sumestatic void 500078064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 500178064Sume{ 500278064Sume /* TBD */ 500378064Sume} 500478064Sume 500578064Sume/* 5006241686Sandre * Set my IPv6 address. 500778064Sume */ 500878064Sumestatic void 500978064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 501078064Sume{ 501178064Sume STDDCL; 501278064Sume struct ifaddr *ifa; 501378064Sume struct sockaddr_in6 *sin6; 501478064Sume 501578064Sume /* 501678064Sume * Pick the first link-local AF_INET6 address from the list, 501778064Sume * aliases don't make any sense on a p2p link anyway. 501878064Sume */ 501978064Sume 502078064Sume sin6 = NULL; 5021195070Srwatson if_addr_rlock(ifp); 5022194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 5023194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET6) { 502478064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 5025194813Srwatson if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5026194813Srwatson ifa_ref(ifa); 502778064Sume break; 5028194813Srwatson } 502978064Sume } 503078064Sume } 5031195070Srwatson if_addr_runlock(ifp); 503278064Sume 5033194813Srwatson if (ifa != NULL) { 503478064Sume int error; 503578064Sume struct sockaddr_in6 new_sin6 = *sin6; 503678064Sume 503778064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 503878064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 5039194813Srwatson if (debug && error) { 504078064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 504178064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 504278064Sume } 5043194813Srwatson ifa_free(ifa); 504478064Sume } 504578064Sume} 504678064Sume#endif 504778064Sume 504878064Sume/* 504978064Sume * Suggest a candidate address to be used by peer. 505078064Sume */ 505178064Sumestatic void 505278064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 505378064Sume{ 505478064Sume struct in6_addr myaddr; 505578064Sume struct timeval tv; 505678064Sume 505778064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 505878064Sume 505978064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 506078064Sume microtime(&tv); 506178064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 506278064Sume myaddr.s6_addr[14] ^= 0xff; 506378064Sume myaddr.s6_addr[15] ^= 0xff; 506478064Sume } else { 506578064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 506678064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 506778064Sume } 506878064Sume if (suggest) 506978064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 507078064Sume} 507178064Sume#endif /*INET6*/ 507278064Sume 507330300Sjoergstatic int 507438343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 507530300Sjoerg{ 507638343Sbde u_long subcmd; 507730300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 507888600Sjoerg struct spppreq *spr; 507988600Sjoerg int rv = 0; 508030300Sjoerg 508188600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 508288600Sjoerg return (EAGAIN); 508330300Sjoerg /* 508430300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 508530300Sjoerg * Check the cmd word first before attempting to fetch all the 508630300Sjoerg * data. 508730300Sjoerg */ 508888600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 508988600Sjoerg rv = EFAULT; 509088600Sjoerg goto quit; 509188600Sjoerg } 509230300Sjoerg 509388600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 509488600Sjoerg rv = EFAULT; 509588600Sjoerg goto quit; 509688600Sjoerg } 509730300Sjoerg 509830300Sjoerg switch (subcmd) { 5099170490Smjacob case (u_long)SPPPIOGDEFS: 510088600Sjoerg if (cmd != SIOCGIFGENERIC) { 510188600Sjoerg rv = EINVAL; 510288600Sjoerg break; 510388600Sjoerg } 510430300Sjoerg /* 510530300Sjoerg * We copy over the entire current state, but clean 510630300Sjoerg * out some of the stuff we don't wanna pass up. 510730300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 510830300Sjoerg * called by any user. No need to ever get PAP or 510930300Sjoerg * CHAP secrets back to userland anyway. 511030300Sjoerg */ 511188600Sjoerg spr->defs.pp_phase = sp->pp_phase; 511288723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 511388723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 511488600Sjoerg spr->defs.lcp = sp->lcp; 511588600Sjoerg spr->defs.ipcp = sp->ipcp; 511688600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 511788600Sjoerg spr->defs.myauth = sp->myauth; 511888600Sjoerg spr->defs.hisauth = sp->hisauth; 511988600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 512088600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 512188600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 512288600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 512388550Sjoerg /* 512488550Sjoerg * Fixup the LCP timeout value to milliseconds so 512588550Sjoerg * spppcontrol doesn't need to bother about the value 512688550Sjoerg * of "hz". We do the reverse calculation below when 512788550Sjoerg * setting it. 512888550Sjoerg */ 512988600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 513088600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 513188600Sjoerg sizeof(struct spppreq)); 513288600Sjoerg break; 513330300Sjoerg 5134170490Smjacob case (u_long)SPPPIOSDEFS: 513588600Sjoerg if (cmd != SIOCSIFGENERIC) { 513688600Sjoerg rv = EINVAL; 513788600Sjoerg break; 513888600Sjoerg } 513930300Sjoerg /* 514088550Sjoerg * We have a very specific idea of which fields we 514188550Sjoerg * allow being passed back from userland, so to not 514288550Sjoerg * clobber our current state. For one, we only allow 514388550Sjoerg * setting anything if LCP is in dead or establish 514488550Sjoerg * phase. Once the authentication negotiations 514588550Sjoerg * started, the authentication settings must not be 514688550Sjoerg * changed again. (The administrator can force an 514730300Sjoerg * ifconfig down in order to get LCP back into dead 514830300Sjoerg * phase.) 514930300Sjoerg * 515030300Sjoerg * Also, we only allow for authentication parameters to be 515130300Sjoerg * specified. 515230300Sjoerg * 515330300Sjoerg * XXX Should allow to set or clear pp_flags. 515430300Sjoerg * 515530300Sjoerg * Finally, if the respective authentication protocol to 515630300Sjoerg * be used is set differently than 0, but the secret is 515730300Sjoerg * passed as all zeros, we don't trash the existing secret. 515830300Sjoerg * This allows an administrator to change the system name 515930300Sjoerg * only without clobbering the secret (which he didn't get 516030300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 516130300Sjoerg * secrets are cleared if the authentication protocol is 516288550Sjoerg * reset to 0. */ 516388550Sjoerg if (sp->pp_phase != PHASE_DEAD && 516488600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 516588600Sjoerg rv = EBUSY; 516688600Sjoerg break; 516788600Sjoerg } 516830300Sjoerg 516988600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 517088600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 517188600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 517288600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 517388600Sjoerg rv = EINVAL; 517488600Sjoerg break; 517588600Sjoerg } 517630300Sjoerg 517788600Sjoerg if (spr->defs.myauth.proto == 0) 517830300Sjoerg /* resetting myauth */ 517930300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 518030300Sjoerg else { 518130300Sjoerg /* setting/changing myauth */ 518288600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 518388600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 518488600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 518588600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 518630300Sjoerg AUTHKEYLEN); 518730300Sjoerg } 518888600Sjoerg if (spr->defs.hisauth.proto == 0) 518930300Sjoerg /* resetting hisauth */ 519030300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 519130300Sjoerg else { 519230300Sjoerg /* setting/changing hisauth */ 519388600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 519488600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 519588600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 519688600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 519788600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 519830300Sjoerg AUTHKEYLEN); 519930300Sjoerg } 520088550Sjoerg /* set LCP restart timer timeout */ 520188600Sjoerg if (spr->defs.lcp.timeout != 0) 520288600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 520388723Sjoerg /* set VJ enable and IPv6 disable flags */ 520488723Sjoerg#ifdef INET 520588723Sjoerg if (spr->defs.enable_vj) 520688723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 520788723Sjoerg else 520888723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 520988723Sjoerg#endif 521088723Sjoerg#ifdef INET6 521188723Sjoerg if (spr->defs.enable_ipv6) 521288723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 521388723Sjoerg else 521488723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 521596349Sjoerg#endif 521630300Sjoerg break; 521730300Sjoerg 521830300Sjoerg default: 521988600Sjoerg rv = EINVAL; 522030300Sjoerg } 522130300Sjoerg 522288600Sjoerg quit: 522388600Sjoerg free(spr, M_TEMP); 522488600Sjoerg 522588600Sjoerg return (rv); 522630300Sjoerg} 522730300Sjoerg 522830300Sjoergstatic void 522930300Sjoergsppp_phase_network(struct sppp *sp) 523030300Sjoerg{ 523142066Sphk STDDCL; 523230300Sjoerg int i; 523330300Sjoerg u_long mask; 523430300Sjoerg 523530300Sjoerg sp->pp_phase = PHASE_NETWORK; 523630300Sjoerg 523742066Sphk if (debug) 523842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 523942066Sphk sppp_phase_name(sp->pp_phase)); 524030300Sjoerg 524130300Sjoerg /* Notify NCPs now. */ 524230300Sjoerg for (i = 0; i < IDX_COUNT; i++) 524330300Sjoerg if ((cps[i])->flags & CP_NCP) 524430300Sjoerg (cps[i])->Open(sp); 524530300Sjoerg 524630300Sjoerg /* Send Up events to all NCPs. */ 524730300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 524888706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 524930300Sjoerg (cps[i])->Up(sp); 525030300Sjoerg 525130300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 525230300Sjoerg sppp_lcp_check_and_close(sp); 525330300Sjoerg} 525430300Sjoerg 525570199Sjhay 525625706Sjoergstatic const char * 525725944Sjoergsppp_cp_type_name(u_char type) 52584910Swollman{ 525930300Sjoerg static char buf[12]; 52604910Swollman switch (type) { 526130300Sjoerg case CONF_REQ: return "conf-req"; 526230300Sjoerg case CONF_ACK: return "conf-ack"; 526330300Sjoerg case CONF_NAK: return "conf-nak"; 526430300Sjoerg case CONF_REJ: return "conf-rej"; 526530300Sjoerg case TERM_REQ: return "term-req"; 526630300Sjoerg case TERM_ACK: return "term-ack"; 526730300Sjoerg case CODE_REJ: return "code-rej"; 526830300Sjoerg case PROTO_REJ: return "proto-rej"; 526930300Sjoerg case ECHO_REQ: return "echo-req"; 527030300Sjoerg case ECHO_REPLY: return "echo-reply"; 527130300Sjoerg case DISC_REQ: return "discard-req"; 52724910Swollman } 527344145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 527430300Sjoerg return buf; 52754910Swollman} 52764910Swollman 527725706Sjoergstatic const char * 527830300Sjoergsppp_auth_type_name(u_short proto, u_char type) 527930300Sjoerg{ 528030300Sjoerg static char buf[12]; 528130300Sjoerg switch (proto) { 528230300Sjoerg case PPP_CHAP: 528330300Sjoerg switch (type) { 528430300Sjoerg case CHAP_CHALLENGE: return "challenge"; 528530300Sjoerg case CHAP_RESPONSE: return "response"; 528630300Sjoerg case CHAP_SUCCESS: return "success"; 528730300Sjoerg case CHAP_FAILURE: return "failure"; 528830300Sjoerg } 528930300Sjoerg case PPP_PAP: 529030300Sjoerg switch (type) { 529130300Sjoerg case PAP_REQ: return "req"; 529230300Sjoerg case PAP_ACK: return "ack"; 529330300Sjoerg case PAP_NAK: return "nak"; 529430300Sjoerg } 529530300Sjoerg } 529644145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 529730300Sjoerg return buf; 529830300Sjoerg} 529930300Sjoerg 530030300Sjoergstatic const char * 530125944Sjoergsppp_lcp_opt_name(u_char opt) 53024910Swollman{ 530330300Sjoerg static char buf[12]; 530425944Sjoerg switch (opt) { 530530300Sjoerg case LCP_OPT_MRU: return "mru"; 530630300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 530730300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 530830300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 530930300Sjoerg case LCP_OPT_MAGIC: return "magic"; 531030300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 531130300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 53124910Swollman } 531344145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 531430300Sjoerg return buf; 53154910Swollman} 53164910Swollman 5317184682Sbz#ifdef INET 531825944Sjoergstatic const char * 531925944Sjoergsppp_ipcp_opt_name(u_char opt) 532025944Sjoerg{ 532130300Sjoerg static char buf[12]; 532225944Sjoerg switch (opt) { 532330300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 532430300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 532530300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 532625944Sjoerg } 532744145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 532830300Sjoerg return buf; 532925944Sjoerg} 5330184682Sbz#endif 533125944Sjoerg 533278064Sume#ifdef INET6 533325944Sjoergstatic const char * 533478064Sumesppp_ipv6cp_opt_name(u_char opt) 533578064Sume{ 533678064Sume static char buf[12]; 533778064Sume switch (opt) { 533878064Sume case IPV6CP_OPT_IFID: return "ifid"; 533978064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 534078064Sume } 534178064Sume sprintf (buf, "0x%x", opt); 534278064Sume return buf; 534378064Sume} 534478064Sume#endif 534578064Sume 534678064Sumestatic const char * 534725944Sjoergsppp_state_name(int state) 534825944Sjoerg{ 534925944Sjoerg switch (state) { 535025944Sjoerg case STATE_INITIAL: return "initial"; 535125944Sjoerg case STATE_STARTING: return "starting"; 535225944Sjoerg case STATE_CLOSED: return "closed"; 535325944Sjoerg case STATE_STOPPED: return "stopped"; 535425944Sjoerg case STATE_CLOSING: return "closing"; 535525944Sjoerg case STATE_STOPPING: return "stopping"; 535625944Sjoerg case STATE_REQ_SENT: return "req-sent"; 535725944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 535825944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 535925944Sjoerg case STATE_OPENED: return "opened"; 536025944Sjoerg } 536125944Sjoerg return "illegal"; 536225944Sjoerg} 536325944Sjoerg 536425944Sjoergstatic const char * 536525944Sjoergsppp_phase_name(enum ppp_phase phase) 536625944Sjoerg{ 536725944Sjoerg switch (phase) { 536825944Sjoerg case PHASE_DEAD: return "dead"; 536925944Sjoerg case PHASE_ESTABLISH: return "establish"; 537025944Sjoerg case PHASE_TERMINATE: return "terminate"; 537125944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 537225944Sjoerg case PHASE_NETWORK: return "network"; 537325944Sjoerg } 537425944Sjoerg return "illegal"; 537525944Sjoerg} 537625944Sjoerg 537725944Sjoergstatic const char * 537825944Sjoergsppp_proto_name(u_short proto) 537925944Sjoerg{ 538025944Sjoerg static char buf[12]; 538125944Sjoerg switch (proto) { 538225944Sjoerg case PPP_LCP: return "lcp"; 538325944Sjoerg case PPP_IPCP: return "ipcp"; 538430300Sjoerg case PPP_PAP: return "pap"; 538530300Sjoerg case PPP_CHAP: return "chap"; 538678064Sume case PPP_IPV6CP: return "ipv6cp"; 538725944Sjoerg } 538844145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 538925944Sjoerg return buf; 539025944Sjoerg} 539125944Sjoerg 539212820Sphkstatic void 539330300Sjoergsppp_print_bytes(const u_char *p, u_short len) 53944910Swollman{ 539544145Sphk if (len) 539669211Sphk log(-1, " %*D", len, p, "-"); 53974910Swollman} 539825944Sjoerg 539930300Sjoergstatic void 540030300Sjoergsppp_print_string(const char *p, u_short len) 540130300Sjoerg{ 540230300Sjoerg u_char c; 540330300Sjoerg 540430300Sjoerg while (len-- > 0) { 540530300Sjoerg c = *p++; 540630300Sjoerg /* 540730300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 540830300Sjoerg * using only them, but we don't rely on it. */ 540930300Sjoerg if (c < ' ' || c > '~') 541069211Sphk log(-1, "\\x%x", c); 541130300Sjoerg else 541269211Sphk log(-1, "%c", c); 541330300Sjoerg } 541430300Sjoerg} 541530300Sjoerg 5416184682Sbz#ifdef INET 541730300Sjoergstatic const char * 541830300Sjoergsppp_dotted_quad(u_long addr) 541930300Sjoerg{ 542030300Sjoerg static char s[16]; 542130300Sjoerg sprintf(s, "%d.%d.%d.%d", 542240008Sjoerg (int)((addr >> 24) & 0xff), 542340008Sjoerg (int)((addr >> 16) & 0xff), 542440008Sjoerg (int)((addr >> 8) & 0xff), 542538372Sbde (int)(addr & 0xff)); 542630300Sjoerg return s; 542730300Sjoerg} 5428184682Sbz#endif 542930300Sjoerg 543030300Sjoergstatic int 543130300Sjoergsppp_strnlen(u_char *p, int max) 543230300Sjoerg{ 543330300Sjoerg int len; 543430300Sjoerg 543530300Sjoerg for (len = 0; len < max && *p; ++p) 543630300Sjoerg ++len; 543730300Sjoerg return len; 543830300Sjoerg} 543930300Sjoerg 544030300Sjoerg/* a dummy, used to drop uninteresting events */ 544130300Sjoergstatic void 544230300Sjoergsppp_null(struct sppp *unused) 544330300Sjoerg{ 544430300Sjoerg /* do just nothing */ 544530300Sjoerg} 5446