if_spppsubr.c revision 243882
14910Swollman/* 2139365Srik * Synchronous PPP/Cisco/Frame Relay link level subroutines. 34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes. 4139823Simp */ 5139823Simp/*- 6139365Srik * Copyright (C) 1994-2000 Cronyx Engineering. 725944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru> 84910Swollman * 925944Sjoerg * Heavily revamped to conform to RFC 1661. 1088534Sjoerg * Copyright (C) 1997, 2001 Joerg Wunsch. 1125944Sjoerg * 124910Swollman * This software is distributed with NO WARRANTIES, not even the implied 134910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 144910Swollman * 154910Swollman * Authors grant any other persons or organisations permission to use 164910Swollman * or modify this software as long as this message is kept with the software, 174910Swollman * all derivative works or modified versions. 184910Swollman * 1930300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 2016288Sgpalmer * 2150477Speter * $FreeBSD: head/sys/net/if_spppsubr.c 243882 2012-12-05 08:04:20Z glebius $ 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, 265191148Skmacy 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 78825706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 789191148Skmacy struct sockaddr *dst, struct route *ro) 7904910Swollman{ 791147256Sbrooks struct sppp *sp = IFP2SP(ifp); 7924910Swollman struct ppp_header *h; 79378064Sume struct ifqueue *ifq = NULL; 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 case SIOCSIFDSTADDR: 120425944Sjoerg break; 12054910Swollman 120625944Sjoerg case SIOCSIFADDR: 120788503Sjoerg /* set the interface "up" when assigning an IP address */ 120888503Sjoerg ifp->if_flags |= IFF_UP; 1209102412Scharnier /* FALLTHROUGH */ 121011189Sjkh 121125944Sjoerg case SIOCSIFFLAGS: 121225944Sjoerg going_up = ifp->if_flags & IFF_UP && 1213148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 121425944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1215148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 121645152Sphk 121745152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 121845152Sphk if (!newmode) 121945152Sphk newmode = ifp->if_flags & IFF_AUTO; 122045152Sphk if (!newmode) 122145152Sphk newmode = ifp->if_flags & IFF_CISCO; 122245152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 122345152Sphk ifp->if_flags |= newmode; 122445152Sphk 1225139365Srik if (!newmode) 1226139365Srik newmode = sp->pp_flags & PP_FR; 1227139365Srik 122845152Sphk if (newmode != sp->pp_mode) { 122945152Sphk going_down = 1; 123045152Sphk if (!going_up) 1231148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12324910Swollman } 12334910Swollman 123445152Sphk if (going_down) { 1235139365Srik if (sp->pp_mode != IFF_CISCO && 1236139365Srik sp->pp_mode != PP_FR) 123745152Sphk lcp.Close(sp); 123845152Sphk else if (sp->pp_tlf) 123945152Sphk (sp->pp_tlf)(sp); 1240138745Srik sppp_flush_unlocked(ifp); 1241148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 124245152Sphk sp->pp_mode = newmode; 124326018Sjoerg } 12444910Swollman 124545152Sphk if (going_up) { 1246139365Srik if (sp->pp_mode != IFF_CISCO && 1247139365Srik sp->pp_mode != PP_FR) 124845152Sphk lcp.Close(sp); 124945152Sphk sp->pp_mode = newmode; 125045152Sphk if (sp->pp_mode == 0) { 1251148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 125245152Sphk lcp.Open(sp); 125345152Sphk } 1254139365Srik if ((sp->pp_mode == IFF_CISCO) || 1255139365Srik (sp->pp_mode == PP_FR)) { 125645152Sphk if (sp->pp_tls) 125745152Sphk (sp->pp_tls)(sp); 1258148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 125945152Sphk } 126045152Sphk } 126145152Sphk 12624910Swollman break; 126311189Sjkh 126425944Sjoerg#ifdef SIOCSIFMTU 126525944Sjoerg#ifndef ifr_mtu 126625944Sjoerg#define ifr_mtu ifr_metric 126725944Sjoerg#endif 126825944Sjoerg case SIOCSIFMTU: 126925944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 127025944Sjoerg return (EINVAL); 127125944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12724910Swollman break; 127325944Sjoerg#endif 127425944Sjoerg#ifdef SLIOCSETMTU 127525944Sjoerg case SLIOCSETMTU: 127625944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 127725944Sjoerg return (EINVAL); 127825944Sjoerg ifp->if_mtu = *(short*)data; 12794910Swollman break; 128025944Sjoerg#endif 128125944Sjoerg#ifdef SIOCGIFMTU 128225944Sjoerg case SIOCGIFMTU: 128325944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 128411189Sjkh break; 128525944Sjoerg#endif 128625944Sjoerg#ifdef SLIOCGETMTU 128725944Sjoerg case SLIOCGETMTU: 128825944Sjoerg *(short*)data = ifp->if_mtu; 12894910Swollman break; 129025944Sjoerg#endif 129125944Sjoerg case SIOCADDMULTI: 129225944Sjoerg case SIOCDELMULTI: 12934910Swollman break; 129411189Sjkh 129530300Sjoerg case SIOCGIFGENERIC: 129630300Sjoerg case SIOCSIFGENERIC: 129730300Sjoerg rv = sppp_params(sp, cmd, data); 129830300Sjoerg break; 129930300Sjoerg 130025944Sjoerg default: 130130300Sjoerg rv = ENOTTY; 13024910Swollman } 1303138745Srik SPPP_UNLOCK(sp); 130430300Sjoerg return rv; 13054910Swollman} 13064910Swollman 130770199Sjhay/* 130825944Sjoerg * Cisco framing implementation. 130925944Sjoerg */ 131025944Sjoerg 13114910Swollman/* 13124910Swollman * Handle incoming Cisco keepalive protocol packets. 13134910Swollman */ 131430300Sjoergstatic void 131525706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 13164910Swollman{ 131725944Sjoerg STDDCL; 13184910Swollman struct cisco_packet *h; 131930300Sjoerg u_long me, mymask; 13204910Swollman 132127929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 132225706Sjoerg if (debug) 132325706Sjoerg log(LOG_DEBUG, 132440008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 132540008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13264910Swollman return; 13274910Swollman } 13284910Swollman h = mtod (m, struct cisco_packet*); 132925706Sjoerg if (debug) 133025706Sjoerg log(LOG_DEBUG, 133140008Sjoerg SPP_FMT "cisco input: %d bytes " 133225706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 133340008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 133440008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 133540008Sjoerg (u_int)h->time0, (u_int)h->time1); 13364910Swollman switch (ntohl (h->type)) { 13374910Swollman default: 133825706Sjoerg if (debug) 133969211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 134040008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 13414910Swollman break; 13424910Swollman case CISCO_ADDR_REPLY: 13434910Swollman /* Reply on address request, ignore */ 13444910Swollman break; 13454910Swollman case CISCO_KEEPALIVE_REQ: 13464910Swollman sp->pp_alivecnt = 0; 134778064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 134878064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13494910Swollman /* Local and remote sequence numbers are equal. 13504910Swollman * Probably, the line is in loopback mode. */ 135111189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 135240008Sjoerg printf (SPP_FMT "loopback\n", 135340008Sjoerg SPP_ARGS(ifp)); 135411189Sjkh sp->pp_loopcnt = 0; 135511189Sjkh if (ifp->if_flags & IFF_UP) { 135611189Sjkh if_down (ifp); 135726018Sjoerg sppp_qflush (&sp->pp_cpq); 135811189Sjkh } 135911189Sjkh } 13604910Swollman ++sp->pp_loopcnt; 13614910Swollman 13624910Swollman /* Generate new local sequence number */ 136378064Sume sp->pp_seq[IDX_LCP] = random(); 136411189Sjkh break; 136511189Sjkh } 136630300Sjoerg sp->pp_loopcnt = 0; 136711189Sjkh if (! (ifp->if_flags & IFF_UP) && 1368148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 136930300Sjoerg if_up(ifp); 137040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 137111189Sjkh } 13724910Swollman break; 13734910Swollman case CISCO_ADDR_REQ: 137430300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 137530300Sjoerg if (me != 0L) 137630300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13774910Swollman break; 13784910Swollman } 13794910Swollman} 13804910Swollman 13814910Swollman/* 138225944Sjoerg * Send Cisco keepalive packet. 13834910Swollman */ 138412820Sphkstatic void 138525944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 138625944Sjoerg{ 138725944Sjoerg STDDCL; 138825944Sjoerg struct ppp_header *h; 138925944Sjoerg struct cisco_packet *ch; 139025944Sjoerg struct mbuf *m; 139135029Sphk struct timeval tv; 139225944Sjoerg 139336119Sphk getmicrouptime(&tv); 139470199Sjhay 1395243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 139625944Sjoerg if (! m) 139725944Sjoerg return; 139825944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 139925944Sjoerg m->m_pkthdr.rcvif = 0; 140025944Sjoerg 140125944Sjoerg h = mtod (m, struct ppp_header*); 140225944Sjoerg h->address = CISCO_MULTICAST; 140325944Sjoerg h->control = 0; 140425944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 140525944Sjoerg 140625944Sjoerg ch = (struct cisco_packet*) (h + 1); 140725944Sjoerg ch->type = htonl (type); 140825944Sjoerg ch->par1 = htonl (par1); 140925944Sjoerg ch->par2 = htonl (par2); 141025944Sjoerg ch->rel = -1; 141140008Sjoerg 141235029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 141335029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 141425944Sjoerg 141525944Sjoerg if (debug) 141625944Sjoerg log(LOG_DEBUG, 141740008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 141840008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 141940008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 142025944Sjoerg 142169152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 142269152Sjlemon ifp->if_oerrors++; 142325944Sjoerg} 142425944Sjoerg 142570199Sjhay/* 142625944Sjoerg * PPP protocol implementation. 142725944Sjoerg */ 142825944Sjoerg 142925944Sjoerg/* 143025944Sjoerg * Send PPP control protocol packet. 143125944Sjoerg */ 143225944Sjoergstatic void 143325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 143425706Sjoerg u_char ident, u_short len, void *data) 14354910Swollman{ 143625944Sjoerg STDDCL; 14374910Swollman struct ppp_header *h; 14384910Swollman struct lcp_header *lh; 14394910Swollman struct mbuf *m; 14404910Swollman 14414910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14424910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1443243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 14444910Swollman if (! m) 14454910Swollman return; 14464910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14474910Swollman m->m_pkthdr.rcvif = 0; 14484910Swollman 14494910Swollman h = mtod (m, struct ppp_header*); 14504910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14514910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14524910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14534910Swollman 14544910Swollman lh = (struct lcp_header*) (h + 1); 14554910Swollman lh->type = type; 14564910Swollman lh->ident = ident; 14574910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14584910Swollman if (len) 14594910Swollman bcopy (data, lh+1, len); 14604910Swollman 146125706Sjoerg if (debug) { 146240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 146340008Sjoerg SPP_ARGS(ifp), 146425944Sjoerg sppp_proto_name(proto), 146525944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 146625944Sjoerg ntohs (lh->len)); 146744145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 146869211Sphk log(-1, ">\n"); 14694910Swollman } 147069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 147169152Sjlemon ifp->if_oerrors++; 14724910Swollman} 14734910Swollman 14744910Swollman/* 147525944Sjoerg * Handle incoming PPP control protocol packets. 14764910Swollman */ 147712820Sphkstatic void 147825944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14794910Swollman{ 148025944Sjoerg STDDCL; 148125944Sjoerg struct lcp_header *h; 148225944Sjoerg int len = m->m_pkthdr.len; 148325944Sjoerg int rv; 148425944Sjoerg u_char *p; 14854910Swollman 148625944Sjoerg if (len < 4) { 148725944Sjoerg if (debug) 148825944Sjoerg log(LOG_DEBUG, 148940008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 149040008Sjoerg SPP_ARGS(ifp), cp->name, len); 14914910Swollman return; 149225944Sjoerg } 149325944Sjoerg h = mtod (m, struct lcp_header*); 149425944Sjoerg if (debug) { 149525944Sjoerg log(LOG_DEBUG, 149640008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 149740008Sjoerg SPP_ARGS(ifp), cp->name, 149825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 149925944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 150044145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 150169211Sphk log(-1, ">\n"); 150225944Sjoerg } 150325944Sjoerg if (len > ntohs (h->len)) 150425944Sjoerg len = ntohs (h->len); 150530300Sjoerg p = (u_char *)(h + 1); 150625944Sjoerg switch (h->type) { 150725944Sjoerg case CONF_REQ: 150825944Sjoerg if (len < 4) { 150925944Sjoerg if (debug) 151069211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 151140008Sjoerg SPP_ARGS(ifp), cp->name, 151225944Sjoerg len); 151325944Sjoerg ++ifp->if_ierrors; 151425944Sjoerg break; 151525944Sjoerg } 151630300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 151730300Sjoerg switch (sp->state[cp->protoidx]) { 151830300Sjoerg case STATE_CLOSING: 151930300Sjoerg case STATE_STOPPING: 152030300Sjoerg return; 152130300Sjoerg case STATE_CLOSED: 152230300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 152330300Sjoerg 0, 0); 152430300Sjoerg return; 152530300Sjoerg } 152625944Sjoerg rv = (cp->RCR)(sp, h, len); 152725944Sjoerg switch (sp->state[cp->protoidx]) { 152825944Sjoerg case STATE_OPENED: 152925944Sjoerg (cp->tld)(sp); 153025944Sjoerg (cp->scr)(sp); 1531102412Scharnier /* FALLTHROUGH */ 153225944Sjoerg case STATE_ACK_SENT: 153325944Sjoerg case STATE_REQ_SENT: 153470199Sjhay /* 153570199Sjhay * sppp_cp_change_state() have the side effect of 153670199Sjhay * restarting the timeouts. We want to avoid that 153770199Sjhay * if the state don't change, otherwise we won't 153870199Sjhay * ever timeout and resend a configuration request 153970199Sjhay * that got lost. 154070199Sjhay */ 154170199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 154270199Sjhay STATE_REQ_SENT)) 154370199Sjhay break; 154425944Sjoerg sppp_cp_change_state(cp, sp, rv? 154525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 154625944Sjoerg break; 154725944Sjoerg case STATE_STOPPED: 154825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 154925944Sjoerg (cp->scr)(sp); 155025944Sjoerg sppp_cp_change_state(cp, sp, rv? 155125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 155225944Sjoerg break; 155325944Sjoerg case STATE_ACK_RCVD: 155425944Sjoerg if (rv) { 155525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 155625944Sjoerg if (debug) 155740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 155840008Sjoerg SPP_ARGS(ifp), 155926077Sjoerg cp->name); 156025944Sjoerg (cp->tlu)(sp); 156125944Sjoerg } else 156225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 156325944Sjoerg break; 156425944Sjoerg default: 156540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 156640008Sjoerg SPP_ARGS(ifp), cp->name, 156725944Sjoerg sppp_cp_type_name(h->type), 156825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 156925944Sjoerg ++ifp->if_ierrors; 157025944Sjoerg } 157125944Sjoerg break; 157225944Sjoerg case CONF_ACK: 157325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 157425944Sjoerg if (debug) 157569211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 157640008Sjoerg SPP_ARGS(ifp), cp->name, 157725944Sjoerg h->ident, sp->confid[cp->protoidx]); 157825944Sjoerg ++ifp->if_ierrors; 157925944Sjoerg break; 158025944Sjoerg } 158125944Sjoerg switch (sp->state[cp->protoidx]) { 158225944Sjoerg case STATE_CLOSED: 158325944Sjoerg case STATE_STOPPED: 158425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 158525944Sjoerg break; 158625944Sjoerg case STATE_CLOSING: 158725944Sjoerg case STATE_STOPPING: 158825944Sjoerg break; 158925944Sjoerg case STATE_REQ_SENT: 159025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 159125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 159225944Sjoerg break; 159325944Sjoerg case STATE_OPENED: 159425944Sjoerg (cp->tld)(sp); 1595102412Scharnier /* FALLTHROUGH */ 159625944Sjoerg case STATE_ACK_RCVD: 159725944Sjoerg (cp->scr)(sp); 159825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 159925944Sjoerg break; 160025944Sjoerg case STATE_ACK_SENT: 160125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 160225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 160325944Sjoerg if (debug) 160440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 160540008Sjoerg SPP_ARGS(ifp), cp->name); 160625944Sjoerg (cp->tlu)(sp); 160725944Sjoerg break; 160825944Sjoerg default: 160940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 161040008Sjoerg SPP_ARGS(ifp), cp->name, 161125944Sjoerg sppp_cp_type_name(h->type), 161225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 161325944Sjoerg ++ifp->if_ierrors; 161425944Sjoerg } 161525944Sjoerg break; 161625944Sjoerg case CONF_NAK: 161725944Sjoerg case CONF_REJ: 161825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 161925944Sjoerg if (debug) 162069211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 162140008Sjoerg SPP_ARGS(ifp), cp->name, 162225944Sjoerg h->ident, sp->confid[cp->protoidx]); 162325944Sjoerg ++ifp->if_ierrors; 162425944Sjoerg break; 162525944Sjoerg } 162625944Sjoerg if (h->type == CONF_NAK) 162725944Sjoerg (cp->RCN_nak)(sp, h, len); 162825944Sjoerg else /* CONF_REJ */ 162925944Sjoerg (cp->RCN_rej)(sp, h, len); 16304910Swollman 163125944Sjoerg switch (sp->state[cp->protoidx]) { 163225944Sjoerg case STATE_CLOSED: 163325944Sjoerg case STATE_STOPPED: 163425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 163525944Sjoerg break; 163625944Sjoerg case STATE_REQ_SENT: 163725944Sjoerg case STATE_ACK_SENT: 163825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 163970199Sjhay /* 164070199Sjhay * Slow things down a bit if we think we might be 164170199Sjhay * in loopback. Depend on the timeout to send the 164270199Sjhay * next configuration request. 164370199Sjhay */ 164470199Sjhay if (sp->pp_loopcnt) 164570199Sjhay break; 164625944Sjoerg (cp->scr)(sp); 164725944Sjoerg break; 164825944Sjoerg case STATE_OPENED: 164925944Sjoerg (cp->tld)(sp); 1650102412Scharnier /* FALLTHROUGH */ 165125944Sjoerg case STATE_ACK_RCVD: 165252633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 165325944Sjoerg (cp->scr)(sp); 165425944Sjoerg break; 165525944Sjoerg case STATE_CLOSING: 165625944Sjoerg case STATE_STOPPING: 165725944Sjoerg break; 165825944Sjoerg default: 165940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 166040008Sjoerg SPP_ARGS(ifp), cp->name, 166125944Sjoerg sppp_cp_type_name(h->type), 166225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166325944Sjoerg ++ifp->if_ierrors; 166425944Sjoerg } 166525944Sjoerg break; 16664910Swollman 166725944Sjoerg case TERM_REQ: 166825944Sjoerg switch (sp->state[cp->protoidx]) { 166925944Sjoerg case STATE_ACK_RCVD: 167025944Sjoerg case STATE_ACK_SENT: 167125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1672102412Scharnier /* FALLTHROUGH */ 167325944Sjoerg case STATE_CLOSED: 167425944Sjoerg case STATE_STOPPED: 167525944Sjoerg case STATE_CLOSING: 167625944Sjoerg case STATE_STOPPING: 167725944Sjoerg case STATE_REQ_SENT: 167825944Sjoerg sta: 167925944Sjoerg /* Send Terminate-Ack packet. */ 168025944Sjoerg if (debug) 168140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 168240008Sjoerg SPP_ARGS(ifp), cp->name); 168325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 168425944Sjoerg break; 168525944Sjoerg case STATE_OPENED: 168625944Sjoerg (cp->tld)(sp); 168725944Sjoerg sp->rst_counter[cp->protoidx] = 0; 168825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 168925944Sjoerg goto sta; 169025944Sjoerg break; 169125944Sjoerg default: 169240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169340008Sjoerg SPP_ARGS(ifp), cp->name, 169425944Sjoerg sppp_cp_type_name(h->type), 169525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169625944Sjoerg ++ifp->if_ierrors; 169725944Sjoerg } 169825944Sjoerg break; 169925944Sjoerg case TERM_ACK: 170025944Sjoerg switch (sp->state[cp->protoidx]) { 170125944Sjoerg case STATE_CLOSED: 170225944Sjoerg case STATE_STOPPED: 170325944Sjoerg case STATE_REQ_SENT: 170425944Sjoerg case STATE_ACK_SENT: 170525944Sjoerg break; 170625944Sjoerg case STATE_CLOSING: 170741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 170825944Sjoerg (cp->tlf)(sp); 170925944Sjoerg break; 171025944Sjoerg case STATE_STOPPING: 171141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 171225944Sjoerg (cp->tlf)(sp); 171325944Sjoerg break; 171425944Sjoerg case STATE_ACK_RCVD: 171525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171625944Sjoerg break; 171725944Sjoerg case STATE_OPENED: 171825944Sjoerg (cp->tld)(sp); 171925944Sjoerg (cp->scr)(sp); 172025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 172125944Sjoerg break; 172225944Sjoerg default: 172340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 172440008Sjoerg SPP_ARGS(ifp), cp->name, 172525944Sjoerg sppp_cp_type_name(h->type), 172625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172725944Sjoerg ++ifp->if_ierrors; 172825944Sjoerg } 172925944Sjoerg break; 173025944Sjoerg case CODE_REJ: 173125944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 173230300Sjoerg log(LOG_INFO, 173340008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 173430300Sjoerg "danger will robinson\n", 173540008Sjoerg SPP_ARGS(ifp), cp->name, 173630300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 173725944Sjoerg switch (sp->state[cp->protoidx]) { 173825944Sjoerg case STATE_CLOSED: 173925944Sjoerg case STATE_STOPPED: 174025944Sjoerg case STATE_REQ_SENT: 174125944Sjoerg case STATE_ACK_SENT: 174225944Sjoerg case STATE_CLOSING: 174325944Sjoerg case STATE_STOPPING: 174425944Sjoerg case STATE_OPENED: 174525944Sjoerg break; 174625944Sjoerg case STATE_ACK_RCVD: 174725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174825944Sjoerg break; 174925944Sjoerg default: 175040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 175140008Sjoerg SPP_ARGS(ifp), cp->name, 175225944Sjoerg sppp_cp_type_name(h->type), 175325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 175425944Sjoerg ++ifp->if_ierrors; 175525944Sjoerg } 175625944Sjoerg break; 175780715Sume case PROTO_REJ: 175880715Sume { 175980715Sume int catastrophic; 176080715Sume const struct cp *upper; 176180715Sume int i; 176280715Sume u_int16_t proto; 176380715Sume 176480715Sume catastrophic = 0; 176580715Sume upper = NULL; 176680715Sume proto = ntohs(*((u_int16_t *)p)); 176780715Sume for (i = 0; i < IDX_COUNT; i++) { 176880715Sume if (cps[i]->proto == proto) { 176980715Sume upper = cps[i]; 177080715Sume break; 177180715Sume } 177280715Sume } 177380715Sume if (upper == NULL) 177480715Sume catastrophic++; 177580715Sume 177688508Sjoerg if (catastrophic || debug) 177788508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 177888508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 177988508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 178088508Sjoerg sppp_cp_type_name(h->type), proto, 178188508Sjoerg upper ? upper->name : "unknown", 178288508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 178380715Sume 178480715Sume /* 178580715Sume * if we got RXJ+ against conf-req, the peer does not implement 178680715Sume * this particular protocol type. terminate the protocol. 178780715Sume */ 178880715Sume if (upper && !catastrophic) { 178980715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 179080715Sume upper->Close(sp); 179180715Sume break; 179280715Sume } 179380715Sume } 179480715Sume 179580715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 179680715Sume switch (sp->state[cp->protoidx]) { 179780715Sume case STATE_CLOSED: 179880715Sume case STATE_STOPPED: 179980715Sume case STATE_REQ_SENT: 180080715Sume case STATE_ACK_SENT: 180180715Sume case STATE_CLOSING: 180280715Sume case STATE_STOPPING: 180380715Sume case STATE_OPENED: 180480715Sume break; 180580715Sume case STATE_ACK_RCVD: 180680715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 180780715Sume break; 180880715Sume default: 180980715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 181080715Sume SPP_ARGS(ifp), cp->name, 181180715Sume sppp_cp_type_name(h->type), 181280715Sume sppp_state_name(sp->state[cp->protoidx])); 181380715Sume ++ifp->if_ierrors; 181480715Sume } 181580715Sume break; 181680715Sume } 181725944Sjoerg case DISC_REQ: 181825944Sjoerg if (cp->proto != PPP_LCP) 181925944Sjoerg goto illegal; 182025944Sjoerg /* Discard the packet. */ 182125944Sjoerg break; 182225944Sjoerg case ECHO_REQ: 182325944Sjoerg if (cp->proto != PPP_LCP) 182425944Sjoerg goto illegal; 182525944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 182625944Sjoerg if (debug) 182769211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 182840008Sjoerg SPP_ARGS(ifp)); 182925944Sjoerg ++ifp->if_ierrors; 183025944Sjoerg break; 183125944Sjoerg } 183225944Sjoerg if (len < 8) { 183325944Sjoerg if (debug) 183469211Sphk log(-1, SPP_FMT "invalid lcp echo request " 183525944Sjoerg "packet length: %d bytes\n", 183640008Sjoerg SPP_ARGS(ifp), len); 183725944Sjoerg break; 183825944Sjoerg } 183944145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 184044145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 184125944Sjoerg /* Line loopback mode detected. */ 184240008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 184370199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 184425944Sjoerg if_down (ifp); 184526018Sjoerg sppp_qflush (&sp->pp_cpq); 18464910Swollman 184725944Sjoerg /* Shut down the PPP link. */ 184825944Sjoerg /* XXX */ 184925944Sjoerg lcp.Down(sp); 185025944Sjoerg lcp.Up(sp); 185125944Sjoerg break; 185225944Sjoerg } 185325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 185425944Sjoerg if (debug) 185569211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 185640008Sjoerg SPP_ARGS(ifp)); 185725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 185825944Sjoerg break; 185925944Sjoerg case ECHO_REPLY: 186025944Sjoerg if (cp->proto != PPP_LCP) 186125944Sjoerg goto illegal; 186225944Sjoerg if (h->ident != sp->lcp.echoid) { 186325944Sjoerg ++ifp->if_ierrors; 186425944Sjoerg break; 186525944Sjoerg } 186625944Sjoerg if (len < 8) { 186725944Sjoerg if (debug) 186869211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 186925944Sjoerg "packet length: %d bytes\n", 187040008Sjoerg SPP_ARGS(ifp), len); 187125944Sjoerg break; 187225944Sjoerg } 187325944Sjoerg if (debug) 187469211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 187540008Sjoerg SPP_ARGS(ifp)); 187644145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 187744145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 187825944Sjoerg sp->pp_alivecnt = 0; 187925944Sjoerg break; 188025944Sjoerg default: 188125944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 188225944Sjoerg illegal: 188325944Sjoerg if (debug) 188469211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 188540008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 188678064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 188778064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 188825944Sjoerg ++ifp->if_ierrors; 188925944Sjoerg } 18904910Swollman} 18914910Swollman 189225944Sjoerg 18934910Swollman/* 189425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 189525944Sjoerg * Basically, the state transition handling in the automaton. 18964910Swollman */ 189725944Sjoergstatic void 189825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18994910Swollman{ 190025944Sjoerg STDDCL; 19014910Swollman 190225944Sjoerg if (debug) 190340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 190440008Sjoerg SPP_ARGS(ifp), cp->name, 190525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190625944Sjoerg 190725944Sjoerg switch (sp->state[cp->protoidx]) { 190825944Sjoerg case STATE_INITIAL: 190925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 191025944Sjoerg break; 191125944Sjoerg case STATE_STARTING: 191225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 191325944Sjoerg (cp->scr)(sp); 191425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 191525944Sjoerg break; 19164910Swollman default: 191740008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 191840008Sjoerg SPP_ARGS(ifp), cp->name, 191925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 192025944Sjoerg } 192125944Sjoerg} 19224910Swollman 192325944Sjoergstatic void 192425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 192525944Sjoerg{ 192625944Sjoerg STDDCL; 192725944Sjoerg 192825944Sjoerg if (debug) 192940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 193040008Sjoerg SPP_ARGS(ifp), cp->name, 193125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 193225944Sjoerg 193325944Sjoerg switch (sp->state[cp->protoidx]) { 193425944Sjoerg case STATE_CLOSED: 193525944Sjoerg case STATE_CLOSING: 193625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19374910Swollman break; 193825944Sjoerg case STATE_STOPPED: 193941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 194025944Sjoerg (cp->tls)(sp); 194141881Sphk break; 194225944Sjoerg case STATE_STOPPING: 194325944Sjoerg case STATE_REQ_SENT: 194425944Sjoerg case STATE_ACK_RCVD: 194525944Sjoerg case STATE_ACK_SENT: 194625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 194725944Sjoerg break; 194825944Sjoerg case STATE_OPENED: 194925944Sjoerg (cp->tld)(sp); 195025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 195125944Sjoerg break; 195225944Sjoerg default: 195340008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 195440008Sjoerg SPP_ARGS(ifp), cp->name, 195525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 195625944Sjoerg } 195725944Sjoerg} 19584910Swollman 195911189Sjkh 196025944Sjoergstatic void 196125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 196225944Sjoerg{ 196325944Sjoerg STDDCL; 196425944Sjoerg 196525944Sjoerg if (debug) 196640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 196740008Sjoerg SPP_ARGS(ifp), cp->name, 196825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 196925944Sjoerg 197025944Sjoerg switch (sp->state[cp->protoidx]) { 197125944Sjoerg case STATE_INITIAL: 197241881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 197325944Sjoerg (cp->tls)(sp); 19744910Swollman break; 197525944Sjoerg case STATE_STARTING: 197625944Sjoerg break; 197725944Sjoerg case STATE_CLOSED: 197825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 197925944Sjoerg (cp->scr)(sp); 198025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 198125944Sjoerg break; 198225944Sjoerg case STATE_STOPPED: 198374703Sjoerg /* 198474703Sjoerg * Try escaping stopped state. This seems to bite 198574703Sjoerg * people occasionally, in particular for IPCP, 198674703Sjoerg * presumably following previous IPCP negotiation 198774703Sjoerg * aborts. Somehow, we must have missed a Down event 198874703Sjoerg * which would have caused a transition into starting 198974703Sjoerg * state, so as a bandaid we force the Down event now. 199074703Sjoerg * This effectively implements (something like the) 199174703Sjoerg * `restart' option mentioned in the state transition 199274703Sjoerg * table of RFC 1661. 199374703Sjoerg */ 199474703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 199574703Sjoerg (cp->tls)(sp); 199674703Sjoerg break; 199725944Sjoerg case STATE_STOPPING: 199825944Sjoerg case STATE_REQ_SENT: 199925944Sjoerg case STATE_ACK_RCVD: 200025944Sjoerg case STATE_ACK_SENT: 200125944Sjoerg case STATE_OPENED: 200225944Sjoerg break; 200325944Sjoerg case STATE_CLOSING: 200425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 200525944Sjoerg break; 200625944Sjoerg } 200725944Sjoerg} 20084910Swollman 200925944Sjoerg 201025944Sjoergstatic void 201125944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 201225944Sjoerg{ 201325944Sjoerg STDDCL; 201425944Sjoerg 201525944Sjoerg if (debug) 201640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 201740008Sjoerg SPP_ARGS(ifp), cp->name, 201825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 201925944Sjoerg 202025944Sjoerg switch (sp->state[cp->protoidx]) { 202125944Sjoerg case STATE_INITIAL: 202225944Sjoerg case STATE_CLOSED: 202325944Sjoerg case STATE_CLOSING: 20244910Swollman break; 202525944Sjoerg case STATE_STARTING: 202641881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 202725944Sjoerg (cp->tlf)(sp); 20284910Swollman break; 202925944Sjoerg case STATE_STOPPED: 203025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20314910Swollman break; 203225944Sjoerg case STATE_STOPPING: 203325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20344910Swollman break; 203525944Sjoerg case STATE_OPENED: 203625944Sjoerg (cp->tld)(sp); 2037102412Scharnier /* FALLTHROUGH */ 203825944Sjoerg case STATE_REQ_SENT: 203925944Sjoerg case STATE_ACK_RCVD: 204025944Sjoerg case STATE_ACK_SENT: 204125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 204278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 204378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 204425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20454910Swollman break; 20464910Swollman } 20474910Swollman} 20484910Swollman 204925944Sjoergstatic void 205025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 205125944Sjoerg{ 205225944Sjoerg STDDCL; 205325944Sjoerg 2054138745Srik SPPP_LOCK(sp); 205525944Sjoerg if (debug) 205640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 205740008Sjoerg SPP_ARGS(ifp), cp->name, 205825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 205925944Sjoerg sp->rst_counter[cp->protoidx]); 206025944Sjoerg 206125944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 206225944Sjoerg /* TO- event */ 206325944Sjoerg switch (sp->state[cp->protoidx]) { 206425944Sjoerg case STATE_CLOSING: 206541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 206625944Sjoerg (cp->tlf)(sp); 206725944Sjoerg break; 206825944Sjoerg case STATE_STOPPING: 206941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 207025944Sjoerg (cp->tlf)(sp); 207125944Sjoerg break; 207225944Sjoerg case STATE_REQ_SENT: 207325944Sjoerg case STATE_ACK_RCVD: 207425944Sjoerg case STATE_ACK_SENT: 207541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 207625944Sjoerg (cp->tlf)(sp); 207725944Sjoerg break; 207825944Sjoerg } 207925944Sjoerg else 208025944Sjoerg /* TO+ event */ 208125944Sjoerg switch (sp->state[cp->protoidx]) { 208225944Sjoerg case STATE_CLOSING: 208325944Sjoerg case STATE_STOPPING: 208478064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 208578064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2086138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2087138745Srik cp->TO, (void *)sp); 208825944Sjoerg break; 208925944Sjoerg case STATE_REQ_SENT: 209025944Sjoerg case STATE_ACK_RCVD: 209125944Sjoerg (cp->scr)(sp); 209225944Sjoerg /* sppp_cp_change_state() will restart the timer */ 209325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 209425944Sjoerg break; 209525944Sjoerg case STATE_ACK_SENT: 209625944Sjoerg (cp->scr)(sp); 2097138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2098138745Srik cp->TO, (void *)sp); 209925944Sjoerg break; 210025944Sjoerg } 210125944Sjoerg 2102138745Srik SPPP_UNLOCK(sp); 210325944Sjoerg} 210425944Sjoerg 210511189Sjkh/* 210625944Sjoerg * Change the state of a control protocol in the state automaton. 210725944Sjoerg * Takes care of starting/stopping the restart timer. 210811189Sjkh */ 2109105228Sphkstatic void 211025944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 211125944Sjoerg{ 211225944Sjoerg sp->state[cp->protoidx] = newstate; 211325944Sjoerg 2114138745Srik callout_stop (&sp->ch[cp->protoidx]); 2115138745Srik 211625944Sjoerg switch (newstate) { 211725944Sjoerg case STATE_INITIAL: 211825944Sjoerg case STATE_STARTING: 211925944Sjoerg case STATE_CLOSED: 212025944Sjoerg case STATE_STOPPED: 212125944Sjoerg case STATE_OPENED: 212225944Sjoerg break; 212325944Sjoerg case STATE_CLOSING: 212425944Sjoerg case STATE_STOPPING: 212525944Sjoerg case STATE_REQ_SENT: 212625944Sjoerg case STATE_ACK_RCVD: 212725944Sjoerg case STATE_ACK_SENT: 2128138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2129138745Srik cp->TO, (void *)sp); 213025944Sjoerg break; 213125944Sjoerg } 213225944Sjoerg} 213370199Sjhay 213470199Sjhay/* 213525944Sjoerg *--------------------------------------------------------------------------* 213625944Sjoerg * * 213725944Sjoerg * The LCP implementation. * 213825944Sjoerg * * 213925944Sjoerg *--------------------------------------------------------------------------* 214025944Sjoerg */ 214125944Sjoergstatic void 2142138745Sriksppp_pp_up(struct sppp *sp) 2143138745Srik{ 2144138745Srik SPPP_LOCK(sp); 2145138745Srik lcp.Up(sp); 2146138745Srik SPPP_UNLOCK(sp); 2147138745Srik} 2148138745Srik 2149138745Srikstatic void 2150138745Sriksppp_pp_down(struct sppp *sp) 2151138745Srik{ 2152138745Srik SPPP_LOCK(sp); 2153138745Srik lcp.Down(sp); 2154138745Srik SPPP_UNLOCK(sp); 2155138745Srik} 2156138745Srik 2157138745Srikstatic void 215825944Sjoergsppp_lcp_init(struct sppp *sp) 215925944Sjoerg{ 216025944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 216125944Sjoerg sp->lcp.magic = 0; 216225944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 216325944Sjoerg sp->fail_counter[IDX_LCP] = 0; 216478064Sume sp->pp_seq[IDX_LCP] = 0; 216578064Sume sp->pp_rseq[IDX_LCP] = 0; 216625944Sjoerg sp->lcp.protos = 0; 216725944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 216830300Sjoerg 216944145Sphk /* Note that these values are relevant for all control protocols */ 217044145Sphk sp->lcp.timeout = 3 * hz; 217125944Sjoerg sp->lcp.max_terminate = 2; 217225944Sjoerg sp->lcp.max_configure = 10; 217325944Sjoerg sp->lcp.max_failure = 10; 2174188668Srwatson callout_init(&sp->ch[IDX_LCP], CALLOUT_MPSAFE); 217525944Sjoerg} 217625944Sjoerg 217725944Sjoergstatic void 217825944Sjoergsppp_lcp_up(struct sppp *sp) 217925944Sjoerg{ 218025944Sjoerg STDDCL; 218125944Sjoerg 218270199Sjhay sp->pp_alivecnt = 0; 218370199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 218470199Sjhay sp->lcp.magic = 0; 218570199Sjhay sp->lcp.protos = 0; 218670199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 218725944Sjoerg /* 218875321Sjoerg * If we are authenticator, negotiate LCP_AUTH 218975321Sjoerg */ 219075321Sjoerg if (sp->hisauth.proto != 0) 219175321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 219275321Sjoerg else 219375321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 219475321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 219575321Sjoerg /* 219630300Sjoerg * If this interface is passive or dial-on-demand, and we are 219730300Sjoerg * still in Initial state, it means we've got an incoming 219830300Sjoerg * call. Activate the interface. 219925944Sjoerg */ 220025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 220125944Sjoerg if (debug) 220225944Sjoerg log(LOG_DEBUG, 220340008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2204148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 220530300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 220630300Sjoerg if (debug) 220769211Sphk log(-1, "(incoming call)\n"); 220830300Sjoerg sp->pp_flags |= PP_CALLIN; 220930300Sjoerg lcp.Open(sp); 221030300Sjoerg } else if (debug) 221169211Sphk log(-1, "\n"); 221288710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 221388710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2214148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 221588710Sjoerg lcp.Open(sp); 221625944Sjoerg } 221725944Sjoerg 221825944Sjoerg sppp_up_event(&lcp, sp); 221925944Sjoerg} 222025944Sjoerg 222125944Sjoergstatic void 222225944Sjoergsppp_lcp_down(struct sppp *sp) 222325944Sjoerg{ 222425944Sjoerg STDDCL; 222525944Sjoerg 222625944Sjoerg sppp_down_event(&lcp, sp); 222725944Sjoerg 222825944Sjoerg /* 222925944Sjoerg * If this is neither a dial-on-demand nor a passive 223025944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 223125944Sjoerg * administrator can force a redial by another ``ifconfig 223225944Sjoerg * up''. XXX For leased line operation, should we immediately 223325944Sjoerg * try to reopen the connection here? 223425944Sjoerg */ 223525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 223625944Sjoerg log(LOG_INFO, 223742066Sphk SPP_FMT "Down event, taking interface down.\n", 223840008Sjoerg SPP_ARGS(ifp)); 223925944Sjoerg if_down(ifp); 224025944Sjoerg } else { 224125944Sjoerg if (debug) 224225944Sjoerg log(LOG_DEBUG, 224340008Sjoerg SPP_FMT "Down event (carrier loss)\n", 224440008Sjoerg SPP_ARGS(ifp)); 224570199Sjhay sp->pp_flags &= ~PP_CALLIN; 224670199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 224770199Sjhay lcp.Close(sp); 2248148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 224925944Sjoerg } 225025944Sjoerg} 225125944Sjoerg 225225944Sjoergstatic void 225325944Sjoergsppp_lcp_open(struct sppp *sp) 225425944Sjoerg{ 225525944Sjoerg sppp_open_event(&lcp, sp); 225625944Sjoerg} 225725944Sjoerg 225825944Sjoergstatic void 225925944Sjoergsppp_lcp_close(struct sppp *sp) 226025944Sjoerg{ 226125944Sjoerg sppp_close_event(&lcp, sp); 226225944Sjoerg} 226325944Sjoerg 226425944Sjoergstatic void 226525944Sjoergsppp_lcp_TO(void *cookie) 226625944Sjoerg{ 226725944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 226825944Sjoerg} 226925944Sjoerg 227025944Sjoerg/* 227125944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 227225944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 227325944Sjoerg * caused action scn. (The return value is used to make the state 227425944Sjoerg * transition decision in the state automaton.) 227525944Sjoerg */ 227612820Sphkstatic int 227725944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 22784910Swollman{ 227925944Sjoerg STDDCL; 228011189Sjkh u_char *buf, *r, *p; 228125944Sjoerg int origlen, rlen; 228225944Sjoerg u_long nmagic; 228330300Sjoerg u_short authproto; 22844910Swollman 228511189Sjkh len -= 4; 228625944Sjoerg origlen = len; 228711189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 228811189Sjkh if (! buf) 228911189Sjkh return (0); 22904910Swollman 229125706Sjoerg if (debug) 229240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 229340008Sjoerg SPP_ARGS(ifp)); 229425706Sjoerg 229525944Sjoerg /* pass 1: check for things that need to be rejected */ 229611189Sjkh p = (void*) (h+1); 2297161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2298161556Scperciva len-=p[1], p+=p[1]) { 229925944Sjoerg if (debug) 230069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 230111189Sjkh switch (*p) { 230211189Sjkh case LCP_OPT_MAGIC: 230325944Sjoerg /* Magic number. */ 230470199Sjhay if (len >= 6 && p[1] == 6) 230570199Sjhay continue; 230670199Sjhay if (debug) 230770199Sjhay log(-1, "[invalid] "); 230870199Sjhay break; 230925944Sjoerg case LCP_OPT_ASYNC_MAP: 231025944Sjoerg /* Async control character map. */ 231170199Sjhay if (len >= 6 && p[1] == 6) 231225944Sjoerg continue; 231325944Sjoerg if (debug) 231469211Sphk log(-1, "[invalid] "); 231525944Sjoerg break; 231625944Sjoerg case LCP_OPT_MRU: 231725944Sjoerg /* Maximum receive unit. */ 231825944Sjoerg if (len >= 4 && p[1] == 4) 231925944Sjoerg continue; 232025944Sjoerg if (debug) 232169211Sphk log(-1, "[invalid] "); 232225944Sjoerg break; 232330300Sjoerg case LCP_OPT_AUTH_PROTO: 232430300Sjoerg if (len < 4) { 232530300Sjoerg if (debug) 232669211Sphk log(-1, "[invalid] "); 232730300Sjoerg break; 232830300Sjoerg } 232930300Sjoerg authproto = (p[2] << 8) + p[3]; 233030300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 233130300Sjoerg if (debug) 233269211Sphk log(-1, "[invalid chap len] "); 233330300Sjoerg break; 233430300Sjoerg } 233530300Sjoerg if (sp->myauth.proto == 0) { 233630300Sjoerg /* we are not configured to do auth */ 233730300Sjoerg if (debug) 233869211Sphk log(-1, "[not configured] "); 233930300Sjoerg break; 234030300Sjoerg } 234130300Sjoerg /* 234230300Sjoerg * Remote want us to authenticate, remember this, 234330300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 234430300Sjoerg * up. 234530300Sjoerg */ 234630300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 234730300Sjoerg continue; 234825944Sjoerg default: 234925944Sjoerg /* Others not supported. */ 235025944Sjoerg if (debug) 235169211Sphk log(-1, "[rej] "); 235225944Sjoerg break; 235325944Sjoerg } 235425944Sjoerg /* Add the option to rejected list. */ 235525944Sjoerg bcopy (p, r, p[1]); 235625944Sjoerg r += p[1]; 235725944Sjoerg rlen += p[1]; 235825944Sjoerg } 235925944Sjoerg if (rlen) { 236025944Sjoerg if (debug) 236169211Sphk log(-1, " send conf-rej\n"); 236225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 236325944Sjoerg return 0; 236425944Sjoerg } else if (debug) 236569211Sphk log(-1, "\n"); 236625944Sjoerg 236725944Sjoerg /* 236825944Sjoerg * pass 2: check for option values that are unacceptable and 236925944Sjoerg * thus require to be nak'ed. 237025944Sjoerg */ 237125944Sjoerg if (debug) 237240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 237340008Sjoerg SPP_ARGS(ifp)); 237425944Sjoerg 237525944Sjoerg p = (void*) (h+1); 237625944Sjoerg len = origlen; 2377161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2378161556Scperciva len-=p[1], p+=p[1]) { 237925944Sjoerg if (debug) 238069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 238125944Sjoerg switch (*p) { 238225944Sjoerg case LCP_OPT_MAGIC: 238311189Sjkh /* Magic number -- extract. */ 238425944Sjoerg nmagic = (u_long)p[2] << 24 | 238525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 238625944Sjoerg if (nmagic != sp->lcp.magic) { 238770199Sjhay sp->pp_loopcnt = 0; 238825706Sjoerg if (debug) 238969211Sphk log(-1, "0x%lx ", nmagic); 239011189Sjkh continue; 239111189Sjkh } 239270199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 239369211Sphk log(-1, "[glitch] "); 239425944Sjoerg ++sp->pp_loopcnt; 239525944Sjoerg /* 239625944Sjoerg * We negate our magic here, and NAK it. If 239725944Sjoerg * we see it later in an NAK packet, we 239825944Sjoerg * suggest a new one. 239925944Sjoerg */ 240025944Sjoerg nmagic = ~sp->lcp.magic; 240125944Sjoerg /* Gonna NAK it. */ 240225944Sjoerg p[2] = nmagic >> 24; 240325944Sjoerg p[3] = nmagic >> 16; 240425944Sjoerg p[4] = nmagic >> 8; 240525944Sjoerg p[5] = nmagic; 240611189Sjkh break; 240725944Sjoerg 240811189Sjkh case LCP_OPT_ASYNC_MAP: 240988506Sjoerg /* 241088506Sjoerg * Async control character map -- just ignore it. 241188506Sjoerg * 241288506Sjoerg * Quote from RFC 1662, chapter 6: 241388506Sjoerg * To enable this functionality, synchronous PPP 241488506Sjoerg * implementations MUST always respond to the 241588506Sjoerg * Async-Control-Character-Map Configuration 241688506Sjoerg * Option with the LCP Configure-Ack. However, 241788506Sjoerg * acceptance of the Configuration Option does 241888506Sjoerg * not imply that the synchronous implementation 241988506Sjoerg * will do any ACCM mapping. Instead, all such 242088506Sjoerg * octet mapping will be performed by the 242188506Sjoerg * asynchronous-to-synchronous converter. 242288506Sjoerg */ 242388506Sjoerg continue; 242425944Sjoerg 242511189Sjkh case LCP_OPT_MRU: 242625944Sjoerg /* 242725944Sjoerg * Maximum receive unit. Always agreeable, 242825944Sjoerg * but ignored by now. 242925944Sjoerg */ 243025944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 243125706Sjoerg if (debug) 243269211Sphk log(-1, "%lu ", sp->lcp.their_mru); 243311189Sjkh continue; 243430300Sjoerg 243530300Sjoerg case LCP_OPT_AUTH_PROTO: 243630300Sjoerg authproto = (p[2] << 8) + p[3]; 243730300Sjoerg if (sp->myauth.proto != authproto) { 243830300Sjoerg /* not agreed, nak */ 243930300Sjoerg if (debug) 244069211Sphk log(-1, "[mine %s != his %s] ", 244130300Sjoerg sppp_proto_name(sp->hisauth.proto), 244230300Sjoerg sppp_proto_name(authproto)); 244330300Sjoerg p[2] = sp->myauth.proto >> 8; 244430300Sjoerg p[3] = sp->myauth.proto; 244530300Sjoerg break; 244630300Sjoerg } 244730300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 244830300Sjoerg if (debug) 244969211Sphk log(-1, "[chap not MD5] "); 245039981Sjoerg p[4] = CHAP_MD5; 245130300Sjoerg break; 245230300Sjoerg } 245330300Sjoerg continue; 245411189Sjkh } 245525944Sjoerg /* Add the option to nak'ed list. */ 245625706Sjoerg bcopy (p, r, p[1]); 245725706Sjoerg r += p[1]; 245811189Sjkh rlen += p[1]; 245912436Speter } 246025706Sjoerg if (rlen) { 246170199Sjhay /* 246270199Sjhay * Local and remote magics equal -- loopback? 246370199Sjhay */ 246470199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 246570199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 246670199Sjhay printf (SPP_FMT "loopback\n", 246770199Sjhay SPP_ARGS(ifp)); 246870199Sjhay if (ifp->if_flags & IFF_UP) { 246970199Sjhay if_down(ifp); 247070199Sjhay sppp_qflush(&sp->pp_cpq); 247170199Sjhay /* XXX ? */ 247270199Sjhay lcp.Down(sp); 247370199Sjhay lcp.Up(sp); 247470199Sjhay } 2475131093Srik } else if (!sp->pp_loopcnt && 2476131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 247728036Sjoerg if (debug) 247869211Sphk log(-1, " max_failure (%d) exceeded, " 247928036Sjoerg "send conf-rej\n", 248028036Sjoerg sp->lcp.max_failure); 248128036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 248228036Sjoerg } else { 248328036Sjoerg if (debug) 248469211Sphk log(-1, " send conf-nak\n"); 248528036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 248628036Sjoerg } 248725944Sjoerg } else { 248825944Sjoerg if (debug) 248969211Sphk log(-1, " send conf-ack\n"); 249028036Sjoerg sp->fail_counter[IDX_LCP] = 0; 249125944Sjoerg sp->pp_loopcnt = 0; 249225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 249325944Sjoerg h->ident, origlen, h+1); 249425944Sjoerg } 249525944Sjoerg 249611189Sjkh free (buf, M_TEMP); 249711189Sjkh return (rlen == 0); 24984910Swollman} 24994910Swollman 250025944Sjoerg/* 250125944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 250225944Sjoerg * negotiation. 250325944Sjoerg */ 250412820Sphkstatic void 250525944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 25064910Swollman{ 250725944Sjoerg STDDCL; 250825944Sjoerg u_char *buf, *p; 25094910Swollman 251025944Sjoerg len -= 4; 251125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 251225944Sjoerg if (!buf) 25134910Swollman return; 251425944Sjoerg 251525944Sjoerg if (debug) 251640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 251740008Sjoerg SPP_ARGS(ifp)); 251825944Sjoerg 251925944Sjoerg p = (void*) (h+1); 2520161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2521161556Scperciva len -= p[1], p += p[1]) { 252225944Sjoerg if (debug) 252369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 252425944Sjoerg switch (*p) { 252525944Sjoerg case LCP_OPT_MAGIC: 252625944Sjoerg /* Magic number -- can't use it, use 0 */ 252725944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 252825944Sjoerg sp->lcp.magic = 0; 252925944Sjoerg break; 253025944Sjoerg case LCP_OPT_MRU: 253125944Sjoerg /* 253225944Sjoerg * Should not be rejected anyway, since we only 253325944Sjoerg * negotiate a MRU if explicitly requested by 253425944Sjoerg * peer. 253525944Sjoerg */ 253625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 253725944Sjoerg break; 253830300Sjoerg case LCP_OPT_AUTH_PROTO: 253930300Sjoerg /* 254030300Sjoerg * Peer doesn't want to authenticate himself, 254130300Sjoerg * deny unless this is a dialout call, and 254230300Sjoerg * AUTHFLAG_NOCALLOUT is set. 254330300Sjoerg */ 254430300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 254530300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 254630300Sjoerg if (debug) 254769211Sphk log(-1, "[don't insist on auth " 254830300Sjoerg "for callout]"); 254930300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 255030300Sjoerg break; 255130300Sjoerg } 255230300Sjoerg if (debug) 255369211Sphk log(-1, "[access denied]\n"); 255430300Sjoerg lcp.Close(sp); 255530300Sjoerg break; 255625944Sjoerg } 25574910Swollman } 255825944Sjoerg if (debug) 255969211Sphk log(-1, "\n"); 256025944Sjoerg free (buf, M_TEMP); 256125944Sjoerg return; 256225944Sjoerg} 256325944Sjoerg 256425944Sjoerg/* 256525944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 256625944Sjoerg * negotiation. 256725944Sjoerg */ 256825944Sjoergstatic void 256925944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 257025944Sjoerg{ 257125944Sjoerg STDDCL; 257225944Sjoerg u_char *buf, *p; 257325944Sjoerg u_long magic; 257425944Sjoerg 257525944Sjoerg len -= 4; 257625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 257725944Sjoerg if (!buf) 257825944Sjoerg return; 257925944Sjoerg 258025944Sjoerg if (debug) 258140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 258240008Sjoerg SPP_ARGS(ifp)); 258325944Sjoerg 258425944Sjoerg p = (void*) (h+1); 2585161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2586161556Scperciva len -= p[1], p += p[1]) { 258725706Sjoerg if (debug) 258869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 258925944Sjoerg switch (*p) { 259025944Sjoerg case LCP_OPT_MAGIC: 259125944Sjoerg /* Magic number -- renegotiate */ 259225944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 259325944Sjoerg len >= 6 && p[1] == 6) { 259425944Sjoerg magic = (u_long)p[2] << 24 | 259525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 259625944Sjoerg /* 259725944Sjoerg * If the remote magic is our negated one, 259825944Sjoerg * this looks like a loopback problem. 259925944Sjoerg * Suggest a new magic to make sure. 260025944Sjoerg */ 260125944Sjoerg if (magic == ~sp->lcp.magic) { 260225944Sjoerg if (debug) 260369211Sphk log(-1, "magic glitch "); 260435064Sphk sp->lcp.magic = random(); 260525944Sjoerg } else { 260625944Sjoerg sp->lcp.magic = magic; 260725944Sjoerg if (debug) 260869211Sphk log(-1, "%lu ", magic); 260925944Sjoerg } 261025944Sjoerg } 261125944Sjoerg break; 261225944Sjoerg case LCP_OPT_MRU: 261325944Sjoerg /* 261425944Sjoerg * Peer wants to advise us to negotiate an MRU. 261525944Sjoerg * Agree on it if it's reasonable, or use 261625944Sjoerg * default otherwise. 261725944Sjoerg */ 261825944Sjoerg if (len >= 4 && p[1] == 4) { 261925944Sjoerg u_int mru = p[2] * 256 + p[3]; 262025944Sjoerg if (debug) 262169211Sphk log(-1, "%d ", mru); 262225944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 262325944Sjoerg mru = PP_MTU; 262425944Sjoerg sp->lcp.mru = mru; 262525944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 262625944Sjoerg } 262725944Sjoerg break; 262830300Sjoerg case LCP_OPT_AUTH_PROTO: 262930300Sjoerg /* 263030300Sjoerg * Peer doesn't like our authentication method, 263130300Sjoerg * deny. 263230300Sjoerg */ 263330300Sjoerg if (debug) 263469211Sphk log(-1, "[access denied]\n"); 263530300Sjoerg lcp.Close(sp); 263630300Sjoerg break; 26374910Swollman } 263825944Sjoerg } 263925944Sjoerg if (debug) 264069211Sphk log(-1, "\n"); 264125944Sjoerg free (buf, M_TEMP); 264225944Sjoerg return; 264325944Sjoerg} 264411189Sjkh 264525944Sjoergstatic void 264625944Sjoergsppp_lcp_tlu(struct sppp *sp) 264725944Sjoerg{ 264842066Sphk STDDCL; 264925944Sjoerg int i; 265025944Sjoerg u_long mask; 265125944Sjoerg 265225944Sjoerg /* XXX ? */ 265325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2654148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 265525944Sjoerg /* Coming out of loopback mode. */ 265625944Sjoerg if_up(ifp); 265740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 265825944Sjoerg } 265925944Sjoerg 266025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 266125944Sjoerg if ((cps[i])->flags & CP_QUAL) 266225944Sjoerg (cps[i])->Open(sp); 266325944Sjoerg 266430300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 266530300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 266625944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 266725944Sjoerg else 266825944Sjoerg sp->pp_phase = PHASE_NETWORK; 266925944Sjoerg 267042066Sphk if (debug) 267142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 267242066Sphk sppp_phase_name(sp->pp_phase)); 267325944Sjoerg 267430300Sjoerg /* 267530300Sjoerg * Open all authentication protocols. This is even required 267630300Sjoerg * if we already proceeded to network phase, since it might be 267730300Sjoerg * that remote wants us to authenticate, so we might have to 267830300Sjoerg * send a PAP request. Undesired authentication protocols 267930300Sjoerg * don't do anything when they get an Open event. 268030300Sjoerg */ 268130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 268230300Sjoerg if ((cps[i])->flags & CP_AUTH) 268330300Sjoerg (cps[i])->Open(sp); 268430300Sjoerg 268530300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 268625944Sjoerg /* Notify all NCPs. */ 268725944Sjoerg for (i = 0; i < IDX_COUNT; i++) 268888723Sjoerg if (((cps[i])->flags & CP_NCP) && 268988723Sjoerg /* 269088723Sjoerg * XXX 269188723Sjoerg * Hack to administratively disable IPv6 if 269288723Sjoerg * not desired. Perhaps we should have another 269388723Sjoerg * flag for this, but right now, we can make 269488723Sjoerg * all struct cp's read/only. 269588723Sjoerg */ 269688723Sjoerg (cps[i] != &ipv6cp || 269788723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 269825944Sjoerg (cps[i])->Open(sp); 269925944Sjoerg } 270025944Sjoerg 270125944Sjoerg /* Send Up events to all started protos. */ 270225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 270388706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 270425944Sjoerg (cps[i])->Up(sp); 270525944Sjoerg 270642104Sphk /* notify low-level driver of state change */ 270742104Sphk if (sp->pp_chg) 270842104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 270942104Sphk 271025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 271125944Sjoerg /* if no NCP is starting, close down */ 271230300Sjoerg sppp_lcp_check_and_close(sp); 271325944Sjoerg} 271425944Sjoerg 271525944Sjoergstatic void 271625944Sjoergsppp_lcp_tld(struct sppp *sp) 271725944Sjoerg{ 271842066Sphk STDDCL; 271925944Sjoerg int i; 272025944Sjoerg u_long mask; 272125944Sjoerg 272225944Sjoerg sp->pp_phase = PHASE_TERMINATE; 272325944Sjoerg 272442066Sphk if (debug) 272542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 272642066Sphk sppp_phase_name(sp->pp_phase)); 272725944Sjoerg 272825944Sjoerg /* 272925944Sjoerg * Take upper layers down. We send the Down event first and 273025944Sjoerg * the Close second to prevent the upper layers from sending 273125944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 273225944Sjoerg * describes it. 273325944Sjoerg */ 273425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 273588706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 273625944Sjoerg (cps[i])->Down(sp); 273725944Sjoerg (cps[i])->Close(sp); 273825944Sjoerg } 273925944Sjoerg} 274025944Sjoerg 274125944Sjoergstatic void 274225944Sjoergsppp_lcp_tls(struct sppp *sp) 274325944Sjoerg{ 274442066Sphk STDDCL; 274525944Sjoerg 274625944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 274725944Sjoerg 274842066Sphk if (debug) 274942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 275042066Sphk sppp_phase_name(sp->pp_phase)); 275125944Sjoerg 275225944Sjoerg /* Notify lower layer if desired. */ 275325944Sjoerg if (sp->pp_tls) 275425944Sjoerg (sp->pp_tls)(sp); 275541881Sphk else 275641881Sphk (sp->pp_up)(sp); 275725944Sjoerg} 275825944Sjoerg 275925944Sjoergstatic void 276025944Sjoergsppp_lcp_tlf(struct sppp *sp) 276125944Sjoerg{ 276242066Sphk STDDCL; 276325944Sjoerg 276425944Sjoerg sp->pp_phase = PHASE_DEAD; 276542066Sphk if (debug) 276642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 276742066Sphk sppp_phase_name(sp->pp_phase)); 276825944Sjoerg 276925944Sjoerg /* Notify lower layer if desired. */ 277025944Sjoerg if (sp->pp_tlf) 277125944Sjoerg (sp->pp_tlf)(sp); 277241881Sphk else 277341881Sphk (sp->pp_down)(sp); 277425944Sjoerg} 277525944Sjoerg 277625944Sjoergstatic void 277725944Sjoergsppp_lcp_scr(struct sppp *sp) 277825944Sjoerg{ 277930300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 278025944Sjoerg int i = 0; 278130300Sjoerg u_short authproto; 278225944Sjoerg 278325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 278425944Sjoerg if (! sp->lcp.magic) 278535064Sphk sp->lcp.magic = random(); 278625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 278725944Sjoerg opt[i++] = 6; 278825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 278925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 279025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 279125944Sjoerg opt[i++] = sp->lcp.magic; 279225944Sjoerg } 279325944Sjoerg 279425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 279525944Sjoerg opt[i++] = LCP_OPT_MRU; 279625944Sjoerg opt[i++] = 4; 279725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 279825944Sjoerg opt[i++] = sp->lcp.mru; 279925944Sjoerg } 280025944Sjoerg 280130300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 280230300Sjoerg authproto = sp->hisauth.proto; 280330300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 280430300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 280530300Sjoerg opt[i++] = authproto >> 8; 280630300Sjoerg opt[i++] = authproto; 280730300Sjoerg if (authproto == PPP_CHAP) 280830300Sjoerg opt[i++] = CHAP_MD5; 280930300Sjoerg } 281030300Sjoerg 281178064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 281225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 281325944Sjoerg} 281425944Sjoerg 281525944Sjoerg/* 281630300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 281730300Sjoerg */ 281830300Sjoergstatic int 281930300Sjoergsppp_ncp_check(struct sppp *sp) 282030300Sjoerg{ 282130300Sjoerg int i, mask; 282230300Sjoerg 282330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 282488706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 282530300Sjoerg return 1; 282630300Sjoerg return 0; 282730300Sjoerg} 282830300Sjoerg 282930300Sjoerg/* 283025944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 283125944Sjoerg * Called by the NCPs during their tlf action handling. 283225944Sjoerg */ 283325944Sjoergstatic void 283430300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 283525944Sjoerg{ 283625944Sjoerg 283730300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 283830300Sjoerg /* don't bother, we are already going down */ 283930300Sjoerg return; 284030300Sjoerg 284130300Sjoerg if (sppp_ncp_check(sp)) 284230300Sjoerg return; 284330300Sjoerg 284425944Sjoerg lcp.Close(sp); 284525944Sjoerg} 284670199Sjhay 284770199Sjhay/* 284825944Sjoerg *--------------------------------------------------------------------------* 284925944Sjoerg * * 285025944Sjoerg * The IPCP implementation. * 285125944Sjoerg * * 285225944Sjoerg *--------------------------------------------------------------------------* 285325944Sjoerg */ 285425944Sjoerg 2855184682Sbz#ifdef INET 285625944Sjoergstatic void 285725944Sjoergsppp_ipcp_init(struct sppp *sp) 285825944Sjoerg{ 285925944Sjoerg sp->ipcp.opts = 0; 286025944Sjoerg sp->ipcp.flags = 0; 286125944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 286225944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 286378064Sume sp->pp_seq[IDX_IPCP] = 0; 286478064Sume sp->pp_rseq[IDX_IPCP] = 0; 2865188668Srwatson callout_init(&sp->ch[IDX_IPCP], CALLOUT_MPSAFE); 286625944Sjoerg} 286725944Sjoerg 286825944Sjoergstatic void 286925944Sjoergsppp_ipcp_up(struct sppp *sp) 287025944Sjoerg{ 287125944Sjoerg sppp_up_event(&ipcp, sp); 287225944Sjoerg} 287325944Sjoerg 287425944Sjoergstatic void 287525944Sjoergsppp_ipcp_down(struct sppp *sp) 287625944Sjoerg{ 287725944Sjoerg sppp_down_event(&ipcp, sp); 287825944Sjoerg} 287925944Sjoerg 288025944Sjoergstatic void 288125944Sjoergsppp_ipcp_open(struct sppp *sp) 288225944Sjoerg{ 288325944Sjoerg STDDCL; 288425944Sjoerg u_long myaddr, hisaddr; 288525944Sjoerg 288688534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 288788534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 288888700Sjoerg sp->ipcp.opts = 0; 288942104Sphk 289030300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 289125944Sjoerg /* 289225944Sjoerg * If we don't have his address, this probably means our 289325944Sjoerg * interface doesn't want to talk IP at all. (This could 289425944Sjoerg * be the case if somebody wants to speak only IPX, for 289525944Sjoerg * example.) Don't open IPCP in this case. 289625944Sjoerg */ 289725944Sjoerg if (hisaddr == 0L) { 289825944Sjoerg /* XXX this message should go away */ 289925944Sjoerg if (debug) 290040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 290140008Sjoerg SPP_ARGS(ifp)); 290225944Sjoerg return; 290325944Sjoerg } 290425944Sjoerg if (myaddr == 0L) { 290525944Sjoerg /* 290625944Sjoerg * I don't have an assigned address, so i need to 290725944Sjoerg * negotiate my address. 290825944Sjoerg */ 290925944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 291025944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 291142104Sphk } else 291242104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 291388723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 291488534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 291588534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 291688534Sjoerg sp->ipcp.compress_cid = 1; 291788534Sjoerg } 291825944Sjoerg sppp_open_event(&ipcp, sp); 291925944Sjoerg} 292025944Sjoerg 292125944Sjoergstatic void 292225944Sjoergsppp_ipcp_close(struct sppp *sp) 292325944Sjoerg{ 292425944Sjoerg sppp_close_event(&ipcp, sp); 292525944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 292625944Sjoerg /* 292725944Sjoerg * My address was dynamic, clear it again. 292825944Sjoerg */ 292925944Sjoerg sppp_set_ip_addr(sp, 0L); 293025944Sjoerg} 293125944Sjoerg 293225944Sjoergstatic void 293325944Sjoergsppp_ipcp_TO(void *cookie) 293425944Sjoerg{ 293525944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 293625944Sjoerg} 293725944Sjoerg 293825944Sjoerg/* 293925944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 294025944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 294125944Sjoerg * caused action scn. (The return value is used to make the state 294225944Sjoerg * transition decision in the state automaton.) 294325944Sjoerg */ 294425944Sjoergstatic int 294525944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 294625944Sjoerg{ 294725944Sjoerg u_char *buf, *r, *p; 2948147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 294925944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 295025944Sjoerg u_long hisaddr, desiredaddr; 295142104Sphk int gotmyaddr = 0; 295288534Sjoerg int desiredcomp; 295325944Sjoerg 295425944Sjoerg len -= 4; 295525944Sjoerg origlen = len; 295625944Sjoerg /* 295725944Sjoerg * Make sure to allocate a buf that can at least hold a 295825944Sjoerg * conf-nak with an `address' option. We might need it below. 295925944Sjoerg */ 296025944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 296125944Sjoerg if (! buf) 296225944Sjoerg return (0); 296325944Sjoerg 296425944Sjoerg /* pass 1: see if we can recognize them */ 296525944Sjoerg if (debug) 296640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 296740008Sjoerg SPP_ARGS(ifp)); 296825944Sjoerg p = (void*) (h+1); 2969161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2970161556Scperciva len-=p[1], p+=p[1]) { 297125944Sjoerg if (debug) 297269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 297325944Sjoerg switch (*p) { 297488534Sjoerg case IPCP_OPT_COMPRESSION: 297588723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 297688534Sjoerg /* VJ compression administratively disabled */ 297788534Sjoerg if (debug) 297888534Sjoerg log(-1, "[locally disabled] "); 297988534Sjoerg break; 298088534Sjoerg } 298188534Sjoerg /* 298288534Sjoerg * In theory, we should only conf-rej an 298388534Sjoerg * option that is shorter than RFC 1618 298488534Sjoerg * requires (i.e. < 4), and should conf-nak 298588534Sjoerg * anything else that is not VJ. However, 298688534Sjoerg * since our algorithm always uses the 298788534Sjoerg * original option to NAK it with new values, 298888534Sjoerg * things would become more complicated. In 298988534Sjoerg * pratice, the only commonly implemented IP 299088534Sjoerg * compression option is VJ anyway, so the 299188534Sjoerg * difference is negligible. 299288534Sjoerg */ 299388534Sjoerg if (len >= 6 && p[1] == 6) { 299488534Sjoerg /* 299588534Sjoerg * correctly formed compression option 299688534Sjoerg * that could be VJ compression 299788534Sjoerg */ 299888534Sjoerg continue; 299988534Sjoerg } 300088534Sjoerg if (debug) 300188534Sjoerg log(-1, 300288534Sjoerg "optlen %d [invalid/unsupported] ", 300388534Sjoerg p[1]); 300488534Sjoerg break; 300525944Sjoerg case IPCP_OPT_ADDRESS: 300625944Sjoerg if (len >= 6 && p[1] == 6) { 300725944Sjoerg /* correctly formed address option */ 300825944Sjoerg continue; 300925944Sjoerg } 301025706Sjoerg if (debug) 301169211Sphk log(-1, "[invalid] "); 301211189Sjkh break; 301325944Sjoerg default: 301425944Sjoerg /* Others not supported. */ 301525944Sjoerg if (debug) 301669211Sphk log(-1, "[rej] "); 30174910Swollman break; 30184910Swollman } 301925944Sjoerg /* Add the option to rejected list. */ 302025944Sjoerg bcopy (p, r, p[1]); 302125944Sjoerg r += p[1]; 302225944Sjoerg rlen += p[1]; 302325944Sjoerg } 302425944Sjoerg if (rlen) { 302525944Sjoerg if (debug) 302669211Sphk log(-1, " send conf-rej\n"); 302725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 302825944Sjoerg return 0; 302925944Sjoerg } else if (debug) 303069211Sphk log(-1, "\n"); 303125944Sjoerg 303225944Sjoerg /* pass 2: parse option values */ 303330300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 303425944Sjoerg if (debug) 303540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 303640008Sjoerg SPP_ARGS(ifp)); 303725944Sjoerg p = (void*) (h+1); 303825944Sjoerg len = origlen; 3039161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3040161556Scperciva len-=p[1], p+=p[1]) { 304125944Sjoerg if (debug) 304269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 304325944Sjoerg switch (*p) { 304488534Sjoerg case IPCP_OPT_COMPRESSION: 304588534Sjoerg desiredcomp = p[2] << 8 | p[3]; 304688534Sjoerg /* We only support VJ */ 304788534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 304888534Sjoerg if (debug) 304988534Sjoerg log(-1, "VJ [ack] "); 305088534Sjoerg sp->ipcp.flags |= IPCP_VJ; 305188599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 305288534Sjoerg sp->ipcp.max_state = p[4]; 305388534Sjoerg sp->ipcp.compress_cid = p[5]; 305488534Sjoerg continue; 305588534Sjoerg } 305688534Sjoerg if (debug) 305788534Sjoerg log(-1, 305888534Sjoerg "compproto %#04x [not supported] ", 305988534Sjoerg desiredcomp); 306088534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 306188534Sjoerg p[3] = IPCP_COMP_VJ; 306288534Sjoerg p[4] = sp->ipcp.max_state; 306388534Sjoerg p[5] = sp->ipcp.compress_cid; 306488534Sjoerg break; 306525944Sjoerg case IPCP_OPT_ADDRESS: 306642104Sphk /* This is the address he wants in his end */ 306725944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 306825944Sjoerg p[4] << 8 | p[5]; 306933928Sphk if (desiredaddr == hisaddr || 307088702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 307125944Sjoerg /* 307225944Sjoerg * Peer's address is same as our value, 307388702Sjoerg * or we have set it to 0.0.0.* to 307433928Sphk * indicate that we do not really care, 307525944Sjoerg * this is agreeable. Gonna conf-ack 307625944Sjoerg * it. 307725944Sjoerg */ 307825944Sjoerg if (debug) 307969211Sphk log(-1, "%s [ack] ", 308042104Sphk sppp_dotted_quad(hisaddr)); 308125944Sjoerg /* record that we've seen it already */ 308225944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 308325944Sjoerg continue; 308425944Sjoerg } 308525944Sjoerg /* 308625944Sjoerg * The address wasn't agreeable. This is either 308725944Sjoerg * he sent us 0.0.0.0, asking to assign him an 308825944Sjoerg * address, or he send us another address not 308925944Sjoerg * matching our value. Either case, we gonna 309025944Sjoerg * conf-nak it with our value. 309142104Sphk * XXX: we should "rej" if hisaddr == 0 309225944Sjoerg */ 309325944Sjoerg if (debug) { 309425944Sjoerg if (desiredaddr == 0) 309569211Sphk log(-1, "[addr requested] "); 309625944Sjoerg else 309769211Sphk log(-1, "%s [not agreed] ", 309842104Sphk sppp_dotted_quad(desiredaddr)); 309925944Sjoerg 310025944Sjoerg } 310144235Sphk p[2] = hisaddr >> 24; 310244235Sphk p[3] = hisaddr >> 16; 310344235Sphk p[4] = hisaddr >> 8; 310444235Sphk p[5] = hisaddr; 310511189Sjkh break; 310625706Sjoerg } 310725944Sjoerg /* Add the option to nak'ed list. */ 310825944Sjoerg bcopy (p, r, p[1]); 310925944Sjoerg r += p[1]; 311025944Sjoerg rlen += p[1]; 311125944Sjoerg } 311225944Sjoerg 311325944Sjoerg /* 311425944Sjoerg * If we are about to conf-ack the request, but haven't seen 311525944Sjoerg * his address so far, gonna conf-nak it instead, with the 311625944Sjoerg * `address' option present and our idea of his address being 311725944Sjoerg * filled in there, to request negotiation of both addresses. 311825944Sjoerg * 311925944Sjoerg * XXX This can result in an endless req - nak loop if peer 312025944Sjoerg * doesn't want to send us his address. Q: What should we do 312125944Sjoerg * about it? XXX A: implement the max-failure counter. 312225944Sjoerg */ 312342104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 312425944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 312525944Sjoerg buf[1] = 6; 312625944Sjoerg buf[2] = hisaddr >> 24; 312725944Sjoerg buf[3] = hisaddr >> 16; 312825944Sjoerg buf[4] = hisaddr >> 8; 312925944Sjoerg buf[5] = hisaddr; 313025944Sjoerg rlen = 6; 313125706Sjoerg if (debug) 313269211Sphk log(-1, "still need hisaddr "); 313325944Sjoerg } 313425944Sjoerg 313525944Sjoerg if (rlen) { 313625706Sjoerg if (debug) 313769211Sphk log(-1, " send conf-nak\n"); 313825944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 313925944Sjoerg } else { 314025706Sjoerg if (debug) 314169211Sphk log(-1, " send conf-ack\n"); 314225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 314325944Sjoerg h->ident, origlen, h+1); 314425944Sjoerg } 314525944Sjoerg 314625944Sjoerg free (buf, M_TEMP); 314725944Sjoerg return (rlen == 0); 314825944Sjoerg} 314925944Sjoerg 315025944Sjoerg/* 315125944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 315225944Sjoerg * negotiation. 315325944Sjoerg */ 315425944Sjoergstatic void 315525944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 315625944Sjoerg{ 315725944Sjoerg u_char *buf, *p; 3158147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 315925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 316025944Sjoerg 316125944Sjoerg len -= 4; 316225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 316325944Sjoerg if (!buf) 316425944Sjoerg return; 316525944Sjoerg 316625944Sjoerg if (debug) 316740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 316840008Sjoerg SPP_ARGS(ifp)); 316925944Sjoerg 317025944Sjoerg p = (void*) (h+1); 3171161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3172161556Scperciva len -= p[1], p += p[1]) { 317325706Sjoerg if (debug) 317469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 317525944Sjoerg switch (*p) { 317688534Sjoerg case IPCP_OPT_COMPRESSION: 317788534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 317888534Sjoerg break; 317925944Sjoerg case IPCP_OPT_ADDRESS: 318025944Sjoerg /* 318125944Sjoerg * Peer doesn't grok address option. This is 318225944Sjoerg * bad. XXX Should we better give up here? 318342104Sphk * XXX We could try old "addresses" option... 318425944Sjoerg */ 318525944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 318625944Sjoerg break; 318725944Sjoerg } 31884910Swollman } 318925944Sjoerg if (debug) 319069211Sphk log(-1, "\n"); 319125944Sjoerg free (buf, M_TEMP); 319225944Sjoerg return; 31934910Swollman} 31944910Swollman 319525944Sjoerg/* 319625944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 319725944Sjoerg * negotiation. 319825944Sjoerg */ 319912820Sphkstatic void 320025944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 32014910Swollman{ 320225944Sjoerg u_char *buf, *p; 3203147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 320425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 320588534Sjoerg int desiredcomp; 320625944Sjoerg u_long wantaddr; 32074910Swollman 320825944Sjoerg len -= 4; 320925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 321025944Sjoerg if (!buf) 321125944Sjoerg return; 321225944Sjoerg 321325944Sjoerg if (debug) 321440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 321540008Sjoerg SPP_ARGS(ifp)); 321625944Sjoerg 321725944Sjoerg p = (void*) (h+1); 3218161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3219161556Scperciva len -= p[1], p += p[1]) { 322025944Sjoerg if (debug) 322169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 322225944Sjoerg switch (*p) { 322388534Sjoerg case IPCP_OPT_COMPRESSION: 322488534Sjoerg if (len >= 6 && p[1] == 6) { 322588534Sjoerg desiredcomp = p[2] << 8 | p[3]; 322688534Sjoerg if (debug) 322788534Sjoerg log(-1, "[wantcomp %#04x] ", 322888534Sjoerg desiredcomp); 322988534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 323088599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 323188534Sjoerg sp->ipcp.max_state = p[4]; 323288534Sjoerg sp->ipcp.compress_cid = p[5]; 323388534Sjoerg if (debug) 323488534Sjoerg log(-1, "[agree] "); 323588534Sjoerg } else 323688534Sjoerg sp->ipcp.opts &= 323788534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 323888534Sjoerg } 323988534Sjoerg break; 324025944Sjoerg case IPCP_OPT_ADDRESS: 324125944Sjoerg /* 324225944Sjoerg * Peer doesn't like our local IP address. See 324325944Sjoerg * if we can do something for him. We'll drop 324425944Sjoerg * him our address then. 324525944Sjoerg */ 324625944Sjoerg if (len >= 6 && p[1] == 6) { 324725944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 324825944Sjoerg p[4] << 8 | p[5]; 324925944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 325025944Sjoerg if (debug) 325169211Sphk log(-1, "[wantaddr %s] ", 325230300Sjoerg sppp_dotted_quad(wantaddr)); 325325944Sjoerg /* 325425944Sjoerg * When doing dynamic address assignment, 325525944Sjoerg * we accept his offer. Otherwise, we 325625944Sjoerg * ignore it and thus continue to negotiate 325725944Sjoerg * our already existing value. 325842104Sphk * XXX: Bogus, if he said no once, he'll 325942104Sphk * just say no again, might as well die. 326025944Sjoerg */ 326125944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 326225944Sjoerg sppp_set_ip_addr(sp, wantaddr); 326325944Sjoerg if (debug) 326469211Sphk log(-1, "[agree] "); 326542104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 326625944Sjoerg } 326725944Sjoerg } 326825944Sjoerg break; 326925944Sjoerg } 327025944Sjoerg } 327125944Sjoerg if (debug) 327269211Sphk log(-1, "\n"); 327325944Sjoerg free (buf, M_TEMP); 327425944Sjoerg return; 32754910Swollman} 32764910Swollman 327712820Sphkstatic void 327825944Sjoergsppp_ipcp_tlu(struct sppp *sp) 32794910Swollman{ 328042104Sphk /* we are up - notify isdn daemon */ 328142104Sphk if (sp->pp_con) 328242104Sphk sp->pp_con(sp); 32834910Swollman} 32844910Swollman 328525944Sjoergstatic void 328625944Sjoergsppp_ipcp_tld(struct sppp *sp) 328725944Sjoerg{ 328825944Sjoerg} 328925944Sjoerg 329025944Sjoergstatic void 329125944Sjoergsppp_ipcp_tls(struct sppp *sp) 329225944Sjoerg{ 329325944Sjoerg /* indicate to LCP that it must stay alive */ 329425944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 329525944Sjoerg} 329625944Sjoerg 329725944Sjoergstatic void 329825944Sjoergsppp_ipcp_tlf(struct sppp *sp) 329925944Sjoerg{ 330025944Sjoerg /* we no longer need LCP */ 330125944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 330230300Sjoerg sppp_lcp_check_and_close(sp); 330325944Sjoerg} 330425944Sjoerg 330525944Sjoergstatic void 330625944Sjoergsppp_ipcp_scr(struct sppp *sp) 330725944Sjoerg{ 330825944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 330925944Sjoerg u_long ouraddr; 331025944Sjoerg int i = 0; 331125944Sjoerg 331288534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 331388534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 331488534Sjoerg opt[i++] = 6; 331588534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 331688534Sjoerg opt[i++] = IPCP_COMP_VJ; 331788534Sjoerg opt[i++] = sp->ipcp.max_state; 331888534Sjoerg opt[i++] = sp->ipcp.compress_cid; 331988534Sjoerg } 332025944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 332130300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 332225944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 332325944Sjoerg opt[i++] = 6; 332425944Sjoerg opt[i++] = ouraddr >> 24; 332525944Sjoerg opt[i++] = ouraddr >> 16; 332625944Sjoerg opt[i++] = ouraddr >> 8; 332725944Sjoerg opt[i++] = ouraddr; 332825944Sjoerg } 332925944Sjoerg 333078064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 333125944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 333225944Sjoerg} 3333184682Sbz#else /* !INET */ 3334184682Sbzstatic void 3335184682Sbzsppp_ipcp_init(struct sppp *sp) 3336184682Sbz{ 3337184682Sbz} 333825944Sjoerg 3339184682Sbzstatic void 3340184682Sbzsppp_ipcp_up(struct sppp *sp) 3341184682Sbz{ 3342184682Sbz} 3343184682Sbz 3344184682Sbzstatic void 3345184682Sbzsppp_ipcp_down(struct sppp *sp) 3346184682Sbz{ 3347184682Sbz} 3348184682Sbz 3349184682Sbzstatic void 3350184682Sbzsppp_ipcp_open(struct sppp *sp) 3351184682Sbz{ 3352184682Sbz} 3353184682Sbz 3354184682Sbzstatic void 3355184682Sbzsppp_ipcp_close(struct sppp *sp) 3356184682Sbz{ 3357184682Sbz} 3358184682Sbz 3359184682Sbzstatic void 3360184682Sbzsppp_ipcp_TO(void *cookie) 3361184682Sbz{ 3362184682Sbz} 3363184682Sbz 3364184682Sbzstatic int 3365184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3366184682Sbz{ 3367184682Sbz return (0); 3368184682Sbz} 3369184682Sbz 3370184682Sbzstatic void 3371184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3372184682Sbz{ 3373184682Sbz} 3374184682Sbz 3375184682Sbzstatic void 3376184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3377184682Sbz{ 3378184682Sbz} 3379184682Sbz 3380184682Sbzstatic void 3381184682Sbzsppp_ipcp_tlu(struct sppp *sp) 3382184682Sbz{ 3383184682Sbz} 3384184682Sbz 3385184682Sbzstatic void 3386184682Sbzsppp_ipcp_tld(struct sppp *sp) 3387184682Sbz{ 3388184682Sbz} 3389184682Sbz 3390184682Sbzstatic void 3391184682Sbzsppp_ipcp_tls(struct sppp *sp) 3392184682Sbz{ 3393184682Sbz} 3394184682Sbz 3395184682Sbzstatic void 3396184682Sbzsppp_ipcp_tlf(struct sppp *sp) 3397184682Sbz{ 3398184682Sbz} 3399184682Sbz 3400184682Sbzstatic void 3401184682Sbzsppp_ipcp_scr(struct sppp *sp) 3402184682Sbz{ 3403184682Sbz} 3404184682Sbz#endif 3405184682Sbz 340670199Sjhay/* 340730300Sjoerg *--------------------------------------------------------------------------* 340830300Sjoerg * * 340978064Sume * The IPv6CP implementation. * 341078064Sume * * 341178064Sume *--------------------------------------------------------------------------* 341278064Sume */ 341378064Sume 341478064Sume#ifdef INET6 341578064Sumestatic void 341678064Sumesppp_ipv6cp_init(struct sppp *sp) 341778064Sume{ 341878064Sume sp->ipv6cp.opts = 0; 341978064Sume sp->ipv6cp.flags = 0; 342078064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 342178064Sume sp->fail_counter[IDX_IPV6CP] = 0; 342278064Sume sp->pp_seq[IDX_IPV6CP] = 0; 342378064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3424188668Srwatson callout_init(&sp->ch[IDX_IPV6CP], CALLOUT_MPSAFE); 342578064Sume} 342678064Sume 342778064Sumestatic void 342878064Sumesppp_ipv6cp_up(struct sppp *sp) 342978064Sume{ 343078064Sume sppp_up_event(&ipv6cp, sp); 343178064Sume} 343278064Sume 343378064Sumestatic void 343478064Sumesppp_ipv6cp_down(struct sppp *sp) 343578064Sume{ 343678064Sume sppp_down_event(&ipv6cp, sp); 343778064Sume} 343878064Sume 343978064Sumestatic void 344078064Sumesppp_ipv6cp_open(struct sppp *sp) 344178064Sume{ 344278064Sume STDDCL; 344378064Sume struct in6_addr myaddr, hisaddr; 344478064Sume 344578064Sume#ifdef IPV6CP_MYIFID_DYN 344678064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 344778064Sume#else 344878064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 344978064Sume#endif 345078064Sume 345178064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 345278064Sume /* 345378064Sume * If we don't have our address, this probably means our 345478064Sume * interface doesn't want to talk IPv6 at all. (This could 345578064Sume * be the case if somebody wants to speak only IPX, for 345678064Sume * example.) Don't open IPv6CP in this case. 345778064Sume */ 345878064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 345978064Sume /* XXX this message should go away */ 346078064Sume if (debug) 346178064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 346278064Sume SPP_ARGS(ifp)); 346378064Sume return; 346478064Sume } 346578064Sume 346678064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 346778064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 346878064Sume sppp_open_event(&ipv6cp, sp); 346978064Sume} 347078064Sume 347178064Sumestatic void 347278064Sumesppp_ipv6cp_close(struct sppp *sp) 347378064Sume{ 347478064Sume sppp_close_event(&ipv6cp, sp); 347578064Sume} 347678064Sume 347778064Sumestatic void 347878064Sumesppp_ipv6cp_TO(void *cookie) 347978064Sume{ 348078064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 348178064Sume} 348278064Sume 348378064Sume/* 348478064Sume * Analyze a configure request. Return true if it was agreeable, and 348578064Sume * caused action sca, false if it has been rejected or nak'ed, and 348678064Sume * caused action scn. (The return value is used to make the state 348778064Sume * transition decision in the state automaton.) 348878064Sume */ 348978064Sumestatic int 349078064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 349178064Sume{ 349278064Sume u_char *buf, *r, *p; 3493147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 349478064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 349578064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 349678064Sume int ifidcount; 349778064Sume int type; 349878064Sume int collision, nohisaddr; 3499165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 350078064Sume 350178064Sume len -= 4; 350278064Sume origlen = len; 350378064Sume /* 350478064Sume * Make sure to allocate a buf that can at least hold a 350578064Sume * conf-nak with an `address' option. We might need it below. 350678064Sume */ 350778064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 350878064Sume if (! buf) 350978064Sume return (0); 351078064Sume 351178064Sume /* pass 1: see if we can recognize them */ 351278064Sume if (debug) 351378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 351478064Sume SPP_ARGS(ifp)); 351578064Sume p = (void*) (h+1); 351678064Sume ifidcount = 0; 3517161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3518161556Scperciva len-=p[1], p+=p[1]) { 351978064Sume if (debug) 352078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 352178064Sume switch (*p) { 352278064Sume case IPV6CP_OPT_IFID: 352378064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 352478064Sume /* correctly formed address option */ 352578064Sume ifidcount++; 352678064Sume continue; 352778064Sume } 352878064Sume if (debug) 352978176Sume log(-1, " [invalid]"); 353078064Sume break; 353178064Sume#ifdef notyet 353278064Sume case IPV6CP_OPT_COMPRESSION: 353378064Sume if (len >= 4 && p[1] >= 4) { 353478064Sume /* correctly formed compress option */ 353578064Sume continue; 353678064Sume } 353778064Sume if (debug) 353878176Sume log(-1, " [invalid]"); 353978064Sume break; 354078064Sume#endif 354178064Sume default: 354278064Sume /* Others not supported. */ 354378064Sume if (debug) 354478176Sume log(-1, " [rej]"); 354578064Sume break; 354678064Sume } 354778064Sume /* Add the option to rejected list. */ 354878064Sume bcopy (p, r, p[1]); 354978064Sume r += p[1]; 355078064Sume rlen += p[1]; 355178064Sume } 355278064Sume if (rlen) { 355378064Sume if (debug) 355478176Sume log(-1, " send conf-rej\n"); 355578064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 355678064Sume goto end; 355778064Sume } else if (debug) 355878176Sume log(-1, "\n"); 355978064Sume 356078064Sume /* pass 2: parse option values */ 356178064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 356278064Sume if (debug) 356378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 356478064Sume SPP_ARGS(ifp)); 356578064Sume p = (void*) (h+1); 356678064Sume len = origlen; 356778064Sume type = CONF_ACK; 3568161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3569161556Scperciva len-=p[1], p+=p[1]) { 357078064Sume if (debug) 357178176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 357278064Sume switch (*p) { 357378064Sume#ifdef notyet 357478064Sume case IPV6CP_OPT_COMPRESSION: 357578064Sume continue; 357678064Sume#endif 357778064Sume case IPV6CP_OPT_IFID: 357878064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 357978064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 358078064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 358178064Sume &myaddr.s6_addr[8], 8) == 0); 358278064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 358378064Sume 358478064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3585148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 358678064Sume 358778064Sume if (!collision && !nohisaddr) { 358878064Sume /* no collision, hisaddr known - Conf-Ack */ 358978064Sume type = CONF_ACK; 359078064Sume 359178064Sume if (debug) { 359278176Sume log(-1, " %s [%s]", 3593165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3594165118Sbz sppp_cp_type_name(type)); 359578064Sume } 359678064Sume continue; 359778064Sume } 359878064Sume 359978064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 360078064Sume if (collision && nohisaddr) { 360178064Sume /* collision, hisaddr unknown - Conf-Rej */ 360278064Sume type = CONF_REJ; 360378064Sume bzero(&p[2], 8); 360478064Sume } else { 360578064Sume /* 360678064Sume * - no collision, hisaddr unknown, or 360778064Sume * - collision, hisaddr known 360878064Sume * Conf-Nak, suggest hisaddr 360978064Sume */ 361078064Sume type = CONF_NAK; 361178064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 361278064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 361378064Sume } 361478064Sume if (debug) 3615165118Sbz log(-1, " %s [%s]", 3616165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3617165118Sbz sppp_cp_type_name(type)); 361878064Sume break; 361978064Sume } 362078064Sume /* Add the option to nak'ed list. */ 362178064Sume bcopy (p, r, p[1]); 362278064Sume r += p[1]; 362378064Sume rlen += p[1]; 362478064Sume } 362578064Sume 362678064Sume if (rlen == 0 && type == CONF_ACK) { 362778064Sume if (debug) 362878176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 362978064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 363078064Sume } else { 363178064Sume#ifdef DIAGNOSTIC 363278064Sume if (type == CONF_ACK) 363378064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 363478064Sume#endif 363578064Sume 363678064Sume if (debug) { 363778176Sume log(-1, " send %s suggest %s\n", 3638165118Sbz sppp_cp_type_name(type), 3639165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 364078064Sume } 364178064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 364278064Sume } 364378064Sume 364478064Sume end: 364578064Sume free (buf, M_TEMP); 364678064Sume return (rlen == 0); 364778064Sume} 364878064Sume 364978064Sume/* 365078064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 365178064Sume * negotiation. 365278064Sume */ 365378064Sumestatic void 365478064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 365578064Sume{ 365678064Sume u_char *buf, *p; 3657147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 365878064Sume int debug = ifp->if_flags & IFF_DEBUG; 365978064Sume 366078064Sume len -= 4; 366178064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 366278064Sume if (!buf) 366378064Sume return; 366478064Sume 366578064Sume if (debug) 366678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 366778064Sume SPP_ARGS(ifp)); 366878064Sume 366978064Sume p = (void*) (h+1); 3670161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3671161556Scperciva len -= p[1], p += p[1]) { 367278064Sume if (debug) 367378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 367478064Sume switch (*p) { 367578064Sume case IPV6CP_OPT_IFID: 367678064Sume /* 367778064Sume * Peer doesn't grok address option. This is 367878064Sume * bad. XXX Should we better give up here? 367978064Sume */ 368078064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 368178064Sume break; 368278064Sume#ifdef notyet 368378064Sume case IPV6CP_OPT_COMPRESS: 368478064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 368578064Sume break; 368678064Sume#endif 368778064Sume } 368878064Sume } 368978064Sume if (debug) 369078176Sume log(-1, "\n"); 369178064Sume free (buf, M_TEMP); 369278064Sume return; 369378064Sume} 369478064Sume 369578064Sume/* 369678064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 369778064Sume * negotiation. 369878064Sume */ 369978064Sumestatic void 370078064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 370178064Sume{ 370278064Sume u_char *buf, *p; 3703147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 370478064Sume int debug = ifp->if_flags & IFF_DEBUG; 370578064Sume struct in6_addr suggestaddr; 3706165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 370778064Sume 370878064Sume len -= 4; 370978064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 371078064Sume if (!buf) 371178064Sume return; 371278064Sume 371378064Sume if (debug) 371478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 371578064Sume SPP_ARGS(ifp)); 371678064Sume 371778064Sume p = (void*) (h+1); 3718161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3719161556Scperciva len -= p[1], p += p[1]) { 372078064Sume if (debug) 372178176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 372278064Sume switch (*p) { 372378064Sume case IPV6CP_OPT_IFID: 372478064Sume /* 372578064Sume * Peer doesn't like our local ifid. See 372678064Sume * if we can do something for him. We'll drop 372778064Sume * him our address then. 372878064Sume */ 372978064Sume if (len < 10 || p[1] != 10) 373078064Sume break; 373178064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 373278064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3733148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 373478064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 373578064Sume 373678064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 373778064Sume if (debug) 373878176Sume log(-1, " [suggestaddr %s]", 3739165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 374078064Sume#ifdef IPV6CP_MYIFID_DYN 374178064Sume /* 374278064Sume * When doing dynamic address assignment, 374378064Sume * we accept his offer. 374478064Sume */ 374578064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 374678064Sume struct in6_addr lastsuggest; 374778064Sume /* 374878064Sume * If <suggested myaddr from peer> equals to 374978064Sume * <hisaddr we have suggested last time>, 375078064Sume * we have a collision. generate new random 375178064Sume * ifid. 375278064Sume */ 375378064Sume sppp_suggest_ip6_addr(&lastsuggest); 375478064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 375578064Sume lastsuggest)) { 375678064Sume if (debug) 375778176Sume log(-1, " [random]"); 375878064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 375978064Sume } 376078064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 376178064Sume if (debug) 376278176Sume log(-1, " [agree]"); 376378064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 376478064Sume } 376578064Sume#else 376678064Sume /* 376778064Sume * Since we do not do dynamic address assignment, 376878064Sume * we ignore it and thus continue to negotiate 376978064Sume * our already existing value. This can possibly 377078064Sume * go into infinite request-reject loop. 377178064Sume * 377278064Sume * This is not likely because we normally use 377378064Sume * ifid based on MAC-address. 377478064Sume * If you have no ethernet card on the node, too bad. 377578064Sume * XXX should we use fail_counter? 377678064Sume */ 377778064Sume#endif 377878064Sume break; 377978064Sume#ifdef notyet 378078064Sume case IPV6CP_OPT_COMPRESS: 378178064Sume /* 378278064Sume * Peer wants different compression parameters. 378378064Sume */ 378478064Sume break; 378578064Sume#endif 378678064Sume } 378778064Sume } 378878064Sume if (debug) 378978176Sume log(-1, "\n"); 379078064Sume free (buf, M_TEMP); 379178064Sume return; 379278064Sume} 379378064Sumestatic void 379478064Sumesppp_ipv6cp_tlu(struct sppp *sp) 379578064Sume{ 379678064Sume /* we are up - notify isdn daemon */ 379778064Sume if (sp->pp_con) 379878064Sume sp->pp_con(sp); 379978064Sume} 380078064Sume 380178064Sumestatic void 380278064Sumesppp_ipv6cp_tld(struct sppp *sp) 380378064Sume{ 380478064Sume} 380578064Sume 380678064Sumestatic void 380778064Sumesppp_ipv6cp_tls(struct sppp *sp) 380878064Sume{ 380978064Sume /* indicate to LCP that it must stay alive */ 381078064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 381178064Sume} 381278064Sume 381378064Sumestatic void 381478064Sumesppp_ipv6cp_tlf(struct sppp *sp) 381578064Sume{ 381678064Sume 381778064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 381878064Sume /* we no longer need LCP */ 381978064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 382078064Sume sppp_lcp_check_and_close(sp); 382178064Sume#endif 382278064Sume} 382378064Sume 382478064Sumestatic void 382578064Sumesppp_ipv6cp_scr(struct sppp *sp) 382678064Sume{ 382778064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 382878064Sume struct in6_addr ouraddr; 382978064Sume int i = 0; 383078064Sume 383178064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 383278064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 383378064Sume opt[i++] = IPV6CP_OPT_IFID; 383478064Sume opt[i++] = 10; 383578064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 383678064Sume i += 8; 383778064Sume } 383878064Sume 383978064Sume#ifdef notyet 384078064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 384178064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 384278064Sume opt[i++] = 4; 384378064Sume opt[i++] = 0; /* TBD */ 384478064Sume opt[i++] = 0; /* TBD */ 384578064Sume /* variable length data may follow */ 384678064Sume } 384778064Sume#endif 384878064Sume 384978064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 385078064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 385178064Sume} 385278064Sume#else /*INET6*/ 385378064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 385478064Sume{ 385578064Sume} 385678064Sume 385778064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 385878064Sume{ 385978064Sume} 386078064Sume 386178064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 386278064Sume{ 386378064Sume} 386478064Sume 386578064Sume 386678064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 386778064Sume{ 386878064Sume} 386978064Sume 387078064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 387178064Sume{ 387278064Sume} 387378064Sume 387478064Sumestatic void sppp_ipv6cp_TO(void *sp) 387578064Sume{ 387678064Sume} 387778064Sume 387878064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 387978064Sume{ 388078064Sume return 0; 388178064Sume} 388278064Sume 388378064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 388478064Sume{ 388578064Sume} 388678064Sume 388778064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 388878064Sume{ 388978064Sume} 389078064Sume 389178064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 389278064Sume{ 389378064Sume} 389478064Sume 389578064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 389678064Sume{ 389778064Sume} 389878064Sume 389978064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 390078064Sume{ 390178064Sume} 390278064Sume 390378064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 390478064Sume{ 390578064Sume} 390678064Sume 390778064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 390878064Sume{ 390978064Sume} 391078064Sume#endif /*INET6*/ 391178064Sume 391278064Sume/* 391378064Sume *--------------------------------------------------------------------------* 391478064Sume * * 391530300Sjoerg * The CHAP implementation. * 391630300Sjoerg * * 391730300Sjoerg *--------------------------------------------------------------------------* 391830300Sjoerg */ 391930300Sjoerg 392030300Sjoerg/* 392130300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 392230300Sjoerg * the control protocols do, since they do have Open and Close events, but 392330300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 392430300Sjoerg * authentication protocols may be different in both directions (this makes 392530300Sjoerg * sense, think of a machine that never accepts incoming calls but only 392630300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 392730300Sjoerg * 392830300Sjoerg * Our state machine for the local authentication protocol (we are requesting 392930300Sjoerg * the peer to authenticate) looks like: 393030300Sjoerg * 393130300Sjoerg * RCA- 393230300Sjoerg * +--------------------------------------------+ 393330300Sjoerg * V scn,tld| 393430300Sjoerg * +--------+ Close +---------+ RCA+ 393530300Sjoerg * | |<----------------------------------| |------+ 393630300Sjoerg * +--->| Closed | TO* | Opened | sca | 393730300Sjoerg * | | |-----+ +-------| |<-----+ 393830300Sjoerg * | +--------+ irc | | +---------+ 393930300Sjoerg * | ^ | | ^ 394030300Sjoerg * | | | | | 394130300Sjoerg * | | | | | 394230300Sjoerg * | TO-| | | | 394330300Sjoerg * | |tld TO+ V | | 394430300Sjoerg * | | +------->+ | | 394530300Sjoerg * | | | | | | 394630300Sjoerg * | +--------+ V | | 394730300Sjoerg * | | |<----+<--------------------+ | 394830300Sjoerg * | | Req- | scr | 394930300Sjoerg * | | Sent | | 395030300Sjoerg * | | | | 395130300Sjoerg * | +--------+ | 395230300Sjoerg * | RCA- | | RCA+ | 395330300Sjoerg * +------+ +------------------------------------------+ 395430300Sjoerg * scn,tld sca,irc,ict,tlu 395530300Sjoerg * 395630300Sjoerg * 395730300Sjoerg * with: 395830300Sjoerg * 395930300Sjoerg * Open: LCP reached authentication phase 396030300Sjoerg * Close: LCP reached terminate phase 396130300Sjoerg * 396230300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 396330300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 396430300Sjoerg * TO+: timeout with restart counter >= 0 396530300Sjoerg * TO-: timeout with restart counter < 0 396630300Sjoerg * TO*: reschedule timeout for CHAP 396730300Sjoerg * 396830300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 396930300Sjoerg * sca: send ack packet (pap-ack, chap-success) 397030300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 397130300Sjoerg * ict: initialize re-challenge timer (CHAP only) 397230300Sjoerg * 397330300Sjoerg * tlu: this-layer-up, LCP reaches network phase 397430300Sjoerg * tld: this-layer-down, LCP enters terminate phase 397530300Sjoerg * 397630300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 397730300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 397830300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 397930300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 398030300Sjoerg * causing LCP to enter terminate phase. 398130300Sjoerg * 398230300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 398330300Sjoerg * expected to send one based on the successful negotiation of PAP as 398430300Sjoerg * the authentication protocol during the LCP option negotiation. 398530300Sjoerg * 398630300Sjoerg * Incoming authentication protocol requests (remote requests 398730300Sjoerg * authentication, we are peer) don't employ a state machine at all, 398830300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 398930300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 399030300Sjoerg * still in authentication phase (thereby violating the standard that 399130300Sjoerg * demands that these NCP packets are to be discarded), so we keep 399230300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 399330300Sjoerg * phase network once we've seen a positive acknowledge for the 399430300Sjoerg * authentication. 399530300Sjoerg */ 399630300Sjoerg 399730300Sjoerg/* 399830300Sjoerg * Handle incoming CHAP packets. 399930300Sjoerg */ 4000105228Sphkstatic void 400130300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 400230300Sjoerg{ 400330300Sjoerg STDDCL; 400430300Sjoerg struct lcp_header *h; 4005241686Sandre int len; 400630300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 400730300Sjoerg int value_len, name_len; 400830300Sjoerg MD5_CTX ctx; 400930300Sjoerg 401030300Sjoerg len = m->m_pkthdr.len; 401130300Sjoerg if (len < 4) { 401230300Sjoerg if (debug) 401330300Sjoerg log(LOG_DEBUG, 401440008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 401540008Sjoerg SPP_ARGS(ifp), len); 401630300Sjoerg return; 401730300Sjoerg } 401830300Sjoerg h = mtod (m, struct lcp_header*); 401930300Sjoerg if (len > ntohs (h->len)) 402030300Sjoerg len = ntohs (h->len); 402130300Sjoerg 402230300Sjoerg switch (h->type) { 402330300Sjoerg /* challenge, failure and success are his authproto */ 402430300Sjoerg case CHAP_CHALLENGE: 402530300Sjoerg value = 1 + (u_char*)(h+1); 402630300Sjoerg value_len = value[-1]; 402730300Sjoerg name = value + value_len; 402830300Sjoerg name_len = len - value_len - 5; 402930300Sjoerg if (name_len < 0) { 403030300Sjoerg if (debug) { 403130300Sjoerg log(LOG_DEBUG, 403240008Sjoerg SPP_FMT "chap corrupted challenge " 403330300Sjoerg "<%s id=0x%x len=%d", 403440008Sjoerg SPP_ARGS(ifp), 403530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 403630300Sjoerg h->ident, ntohs(h->len)); 403744145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 403869211Sphk log(-1, ">\n"); 403930300Sjoerg } 404030300Sjoerg break; 404130300Sjoerg } 404270199Sjhay 404330300Sjoerg if (debug) { 404430300Sjoerg log(LOG_DEBUG, 404540008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 404640008Sjoerg SPP_ARGS(ifp), 404730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 404830300Sjoerg ntohs(h->len)); 404930300Sjoerg sppp_print_string((char*) name, name_len); 405069211Sphk log(-1, " value-size=%d value=", value_len); 405130300Sjoerg sppp_print_bytes(value, value_len); 405269211Sphk log(-1, ">\n"); 405330300Sjoerg } 405430300Sjoerg 405530300Sjoerg /* Compute reply value. */ 405630300Sjoerg MD5Init(&ctx); 405730300Sjoerg MD5Update(&ctx, &h->ident, 1); 405830300Sjoerg MD5Update(&ctx, sp->myauth.secret, 405930300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 406030300Sjoerg MD5Update(&ctx, value, value_len); 406130300Sjoerg MD5Final(digest, &ctx); 406230300Sjoerg dsize = sizeof digest; 406330300Sjoerg 406430300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 406530300Sjoerg sizeof dsize, (const char *)&dsize, 406630300Sjoerg sizeof digest, digest, 406740008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 406830300Sjoerg sp->myauth.name, 406930300Sjoerg 0); 407030300Sjoerg break; 407130300Sjoerg 407230300Sjoerg case CHAP_SUCCESS: 407330300Sjoerg if (debug) { 407440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 407540008Sjoerg SPP_ARGS(ifp)); 407630300Sjoerg if (len > 4) { 407769211Sphk log(-1, ": "); 407830300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 407930300Sjoerg } 408069211Sphk log(-1, "\n"); 408130300Sjoerg } 4082138745Srik SPPP_LOCK(sp); 408330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 408430300Sjoerg if (sp->myauth.proto == PPP_CHAP && 408532169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 408630300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 408730300Sjoerg /* 408830300Sjoerg * We are authenticator for CHAP but didn't 408930300Sjoerg * complete yet. Leave it to tlu to proceed 409030300Sjoerg * to network phase. 409130300Sjoerg */ 4092138745Srik SPPP_UNLOCK(sp); 409330300Sjoerg break; 409430300Sjoerg } 4095138745Srik SPPP_UNLOCK(sp); 409630300Sjoerg sppp_phase_network(sp); 409730300Sjoerg break; 409830300Sjoerg 409930300Sjoerg case CHAP_FAILURE: 410030300Sjoerg if (debug) { 410140008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 410240008Sjoerg SPP_ARGS(ifp)); 410330300Sjoerg if (len > 4) { 410469211Sphk log(-1, ": "); 410530300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 410630300Sjoerg } 410769211Sphk log(-1, "\n"); 410830300Sjoerg } else 410940008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 411040008Sjoerg SPP_ARGS(ifp)); 411130300Sjoerg /* await LCP shutdown by authenticator */ 411230300Sjoerg break; 411330300Sjoerg 411430300Sjoerg /* response is my authproto */ 411530300Sjoerg case CHAP_RESPONSE: 411630300Sjoerg value = 1 + (u_char*)(h+1); 411730300Sjoerg value_len = value[-1]; 411830300Sjoerg name = value + value_len; 411930300Sjoerg name_len = len - value_len - 5; 412030300Sjoerg if (name_len < 0) { 412130300Sjoerg if (debug) { 412230300Sjoerg log(LOG_DEBUG, 412340008Sjoerg SPP_FMT "chap corrupted response " 412430300Sjoerg "<%s id=0x%x len=%d", 412540008Sjoerg SPP_ARGS(ifp), 412630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 412730300Sjoerg h->ident, ntohs(h->len)); 412844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 412969211Sphk log(-1, ">\n"); 413030300Sjoerg } 413130300Sjoerg break; 413230300Sjoerg } 413330300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 413430300Sjoerg if (debug) 413530300Sjoerg log(LOG_DEBUG, 413640008Sjoerg SPP_FMT "chap dropping response for old ID " 413730300Sjoerg "(got %d, expected %d)\n", 413840008Sjoerg SPP_ARGS(ifp), 413930300Sjoerg h->ident, sp->confid[IDX_CHAP]); 414030300Sjoerg break; 414130300Sjoerg } 414230300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 414330300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 414440008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 414540008Sjoerg SPP_ARGS(ifp)); 414630300Sjoerg sppp_print_string(name, name_len); 414769211Sphk log(-1, " != expected "); 414830300Sjoerg sppp_print_string(sp->hisauth.name, 414930300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 415069211Sphk log(-1, "\n"); 415170199Sjhay } 415230300Sjoerg if (debug) { 415340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 415430300Sjoerg "<%s id=0x%x len=%d name=", 415540008Sjoerg SPP_ARGS(ifp), 415630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 415730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 415830300Sjoerg h->ident, ntohs (h->len)); 415930300Sjoerg sppp_print_string((char*)name, name_len); 416069211Sphk log(-1, " value-size=%d value=", value_len); 416130300Sjoerg sppp_print_bytes(value, value_len); 416269211Sphk log(-1, ">\n"); 416330300Sjoerg } 416430300Sjoerg if (value_len != AUTHKEYLEN) { 416530300Sjoerg if (debug) 416630300Sjoerg log(LOG_DEBUG, 416740008Sjoerg SPP_FMT "chap bad hash value length: " 416830300Sjoerg "%d bytes, should be %d\n", 416940008Sjoerg SPP_ARGS(ifp), value_len, 417030300Sjoerg AUTHKEYLEN); 417130300Sjoerg break; 417230300Sjoerg } 417330300Sjoerg 417430300Sjoerg MD5Init(&ctx); 417530300Sjoerg MD5Update(&ctx, &h->ident, 1); 417630300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 417730300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 417830300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 417930300Sjoerg MD5Final(digest, &ctx); 418030300Sjoerg 418130300Sjoerg#define FAILMSG "Failed..." 418230300Sjoerg#define SUCCMSG "Welcome!" 418330300Sjoerg 418430300Sjoerg if (value_len != sizeof digest || 418530300Sjoerg bcmp(digest, value, value_len) != 0) { 418630300Sjoerg /* action scn, tld */ 418730300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 418830300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 418930300Sjoerg 0); 419030300Sjoerg chap.tld(sp); 419130300Sjoerg break; 419230300Sjoerg } 419330300Sjoerg /* action sca, perhaps tlu */ 419430300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 419530300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 419630300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 419730300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 419830300Sjoerg 0); 419930300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 420030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 420130300Sjoerg chap.tlu(sp); 420230300Sjoerg } 420330300Sjoerg break; 420430300Sjoerg 420530300Sjoerg default: 420630300Sjoerg /* Unknown CHAP packet type -- ignore. */ 420730300Sjoerg if (debug) { 420840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 420930300Sjoerg "<0x%x id=0x%xh len=%d", 421040008Sjoerg SPP_ARGS(ifp), 421130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 421230300Sjoerg h->type, h->ident, ntohs(h->len)); 421344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 421469211Sphk log(-1, ">\n"); 421530300Sjoerg } 421630300Sjoerg break; 421730300Sjoerg 421830300Sjoerg } 421930300Sjoerg} 422030300Sjoerg 422130300Sjoergstatic void 422230300Sjoergsppp_chap_init(struct sppp *sp) 422330300Sjoerg{ 422430300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 422530300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 422630300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 422778064Sume sp->pp_seq[IDX_CHAP] = 0; 422878064Sume sp->pp_rseq[IDX_CHAP] = 0; 4229188668Srwatson callout_init(&sp->ch[IDX_CHAP], CALLOUT_MPSAFE); 423030300Sjoerg} 423130300Sjoerg 423230300Sjoergstatic void 423330300Sjoergsppp_chap_open(struct sppp *sp) 423430300Sjoerg{ 423530300Sjoerg if (sp->myauth.proto == PPP_CHAP && 423630300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 423730300Sjoerg /* we are authenticator for CHAP, start it */ 423830300Sjoerg chap.scr(sp); 423930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 424030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 424130300Sjoerg } 424230300Sjoerg /* nothing to be done if we are peer, await a challenge */ 424330300Sjoerg} 424430300Sjoerg 424530300Sjoergstatic void 424630300Sjoergsppp_chap_close(struct sppp *sp) 424730300Sjoerg{ 424830300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 424930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 425030300Sjoerg} 425130300Sjoerg 425230300Sjoergstatic void 425330300Sjoergsppp_chap_TO(void *cookie) 425430300Sjoerg{ 425530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 425630300Sjoerg STDDCL; 425730300Sjoerg 4258138745Srik SPPP_LOCK(sp); 425930300Sjoerg if (debug) 426040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 426140008Sjoerg SPP_ARGS(ifp), 426230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 426330300Sjoerg sp->rst_counter[IDX_CHAP]); 426430300Sjoerg 426530300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 426630300Sjoerg /* TO- event */ 426730300Sjoerg switch (sp->state[IDX_CHAP]) { 426830300Sjoerg case STATE_REQ_SENT: 426930300Sjoerg chap.tld(sp); 427030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 427130300Sjoerg break; 427230300Sjoerg } 427330300Sjoerg else 427430300Sjoerg /* TO+ (or TO*) event */ 427530300Sjoerg switch (sp->state[IDX_CHAP]) { 427630300Sjoerg case STATE_OPENED: 427730300Sjoerg /* TO* event */ 427830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4279102412Scharnier /* FALLTHROUGH */ 428030300Sjoerg case STATE_REQ_SENT: 428130300Sjoerg chap.scr(sp); 428230300Sjoerg /* sppp_cp_change_state() will restart the timer */ 428330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 428430300Sjoerg break; 428530300Sjoerg } 428630300Sjoerg 4287138745Srik SPPP_UNLOCK(sp); 428830300Sjoerg} 428930300Sjoerg 429030300Sjoergstatic void 429130300Sjoergsppp_chap_tlu(struct sppp *sp) 429230300Sjoerg{ 429330300Sjoerg STDDCL; 4294241686Sandre int i; 429530300Sjoerg 429640010Sjoerg i = 0; 429730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 429830300Sjoerg 429930300Sjoerg /* 430030300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 430130300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 430230300Sjoerg * initial challenge-response exchange has taken place. 430330300Sjoerg * Provide for an option to avoid rechallenges. 430430300Sjoerg */ 430530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 430630300Sjoerg /* 430730300Sjoerg * Compute the re-challenge timeout. This will yield 430830300Sjoerg * a number between 300 and 810 seconds. 430930300Sjoerg */ 431030300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4311138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 431230300Sjoerg } 431330300Sjoerg 431430300Sjoerg if (debug) { 431530300Sjoerg log(LOG_DEBUG, 431640008Sjoerg SPP_FMT "chap %s, ", 431740008Sjoerg SPP_ARGS(ifp), 431830300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 431930300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 432069211Sphk log(-1, "next re-challenge in %d seconds\n", i); 432130300Sjoerg else 432269211Sphk log(-1, "re-challenging supressed\n"); 432330300Sjoerg } 432430300Sjoerg 4325138745Srik SPPP_LOCK(sp); 432630300Sjoerg /* indicate to LCP that we need to be closed down */ 432730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 432830300Sjoerg 432930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 433030300Sjoerg /* 433130300Sjoerg * Remote is authenticator, but his auth proto didn't 433230300Sjoerg * complete yet. Defer the transition to network 433330300Sjoerg * phase. 433430300Sjoerg */ 4335138745Srik SPPP_UNLOCK(sp); 433630300Sjoerg return; 433730300Sjoerg } 4338138745Srik SPPP_UNLOCK(sp); 433930300Sjoerg 434030300Sjoerg /* 434130300Sjoerg * If we are already in phase network, we are done here. This 434230300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 434330300Sjoerg */ 434430300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 434530300Sjoerg sppp_phase_network(sp); 434630300Sjoerg} 434730300Sjoerg 434830300Sjoergstatic void 434930300Sjoergsppp_chap_tld(struct sppp *sp) 435030300Sjoerg{ 435130300Sjoerg STDDCL; 435230300Sjoerg 435330300Sjoerg if (debug) 435440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4355138745Srik callout_stop(&sp->ch[IDX_CHAP]); 435630300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 435730300Sjoerg 435830300Sjoerg lcp.Close(sp); 435930300Sjoerg} 436030300Sjoerg 436130300Sjoergstatic void 436230300Sjoergsppp_chap_scr(struct sppp *sp) 436330300Sjoerg{ 436430300Sjoerg u_long *ch, seed; 436530300Sjoerg u_char clen; 436630300Sjoerg 436730300Sjoerg /* Compute random challenge. */ 436830300Sjoerg ch = (u_long *)sp->myauth.challenge; 436935064Sphk read_random(&seed, sizeof seed); 437030300Sjoerg ch[0] = seed ^ random(); 437130300Sjoerg ch[1] = seed ^ random(); 437230300Sjoerg ch[2] = seed ^ random(); 437330300Sjoerg ch[3] = seed ^ random(); 437430300Sjoerg clen = AUTHKEYLEN; 437530300Sjoerg 437678064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 437730300Sjoerg 437830300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 437930300Sjoerg sizeof clen, (const char *)&clen, 438040008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 438140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 438230300Sjoerg sp->myauth.name, 438330300Sjoerg 0); 438430300Sjoerg} 438570199Sjhay 438670199Sjhay/* 438730300Sjoerg *--------------------------------------------------------------------------* 438830300Sjoerg * * 438930300Sjoerg * The PAP implementation. * 439030300Sjoerg * * 439130300Sjoerg *--------------------------------------------------------------------------* 439230300Sjoerg */ 439330300Sjoerg/* 439430300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 439530300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 439630300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 439730300Sjoerg * retry counter is expired). 439830300Sjoerg */ 439930300Sjoerg 440030300Sjoerg/* 440130300Sjoerg * Handle incoming PAP packets. */ 440230300Sjoergstatic void 440330300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 440430300Sjoerg{ 440530300Sjoerg STDDCL; 440630300Sjoerg struct lcp_header *h; 4407241686Sandre int len; 440830300Sjoerg u_char *name, *passwd, mlen; 440930300Sjoerg int name_len, passwd_len; 441030300Sjoerg 441130300Sjoerg len = m->m_pkthdr.len; 441230300Sjoerg if (len < 5) { 441330300Sjoerg if (debug) 441430300Sjoerg log(LOG_DEBUG, 441540008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 441640008Sjoerg SPP_ARGS(ifp), len); 441730300Sjoerg return; 441830300Sjoerg } 441930300Sjoerg h = mtod (m, struct lcp_header*); 442030300Sjoerg if (len > ntohs (h->len)) 442130300Sjoerg len = ntohs (h->len); 442230300Sjoerg switch (h->type) { 442330300Sjoerg /* PAP request is my authproto */ 442430300Sjoerg case PAP_REQ: 442530300Sjoerg name = 1 + (u_char*)(h+1); 442630300Sjoerg name_len = name[-1]; 442730300Sjoerg passwd = name + name_len + 1; 442830300Sjoerg if (name_len > len - 6 || 442930300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 443030300Sjoerg if (debug) { 443140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 443230300Sjoerg "<%s id=0x%x len=%d", 443340008Sjoerg SPP_ARGS(ifp), 443430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 443530300Sjoerg h->ident, ntohs(h->len)); 443644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 443769211Sphk log(-1, ">\n"); 443830300Sjoerg } 443930300Sjoerg break; 444030300Sjoerg } 444130300Sjoerg if (debug) { 444240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 444330300Sjoerg "<%s id=0x%x len=%d name=", 444440008Sjoerg SPP_ARGS(ifp), 444530300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 444630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 444730300Sjoerg h->ident, ntohs(h->len)); 444830300Sjoerg sppp_print_string((char*)name, name_len); 444969211Sphk log(-1, " passwd="); 445030300Sjoerg sppp_print_string((char*)passwd, passwd_len); 445169211Sphk log(-1, ">\n"); 445230300Sjoerg } 445374774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 445474774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 445530300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 445630300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 445730300Sjoerg /* action scn, tld */ 445830300Sjoerg mlen = sizeof(FAILMSG) - 1; 445930300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 446030300Sjoerg sizeof mlen, (const char *)&mlen, 446130300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 446230300Sjoerg 0); 446330300Sjoerg pap.tld(sp); 446430300Sjoerg break; 446530300Sjoerg } 446630300Sjoerg /* action sca, perhaps tlu */ 446730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 446830300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 446930300Sjoerg mlen = sizeof(SUCCMSG) - 1; 447030300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 447130300Sjoerg sizeof mlen, (const char *)&mlen, 447230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 447330300Sjoerg 0); 447430300Sjoerg } 447530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 447630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 447730300Sjoerg pap.tlu(sp); 447830300Sjoerg } 447930300Sjoerg break; 448030300Sjoerg 448130300Sjoerg /* ack and nak are his authproto */ 448230300Sjoerg case PAP_ACK: 4483138745Srik callout_stop(&sp->pap_my_to_ch); 448430300Sjoerg if (debug) { 448540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 448640008Sjoerg SPP_ARGS(ifp)); 448730300Sjoerg name_len = *((char *)h); 448830300Sjoerg if (len > 5 && name_len) { 448969211Sphk log(-1, ": "); 449030300Sjoerg sppp_print_string((char*)(h+1), name_len); 449130300Sjoerg } 449269211Sphk log(-1, "\n"); 449330300Sjoerg } 4494138745Srik SPPP_LOCK(sp); 449530300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 449630300Sjoerg if (sp->myauth.proto == PPP_PAP && 449732169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 449830300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 449930300Sjoerg /* 450030300Sjoerg * We are authenticator for PAP but didn't 450130300Sjoerg * complete yet. Leave it to tlu to proceed 450230300Sjoerg * to network phase. 450330300Sjoerg */ 4504138745Srik SPPP_UNLOCK(sp); 450530300Sjoerg break; 450630300Sjoerg } 4507138745Srik SPPP_UNLOCK(sp); 450830300Sjoerg sppp_phase_network(sp); 450930300Sjoerg break; 451030300Sjoerg 451130300Sjoerg case PAP_NAK: 4512138745Srik callout_stop (&sp->pap_my_to_ch); 451330300Sjoerg if (debug) { 451440008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 451540008Sjoerg SPP_ARGS(ifp)); 451630300Sjoerg name_len = *((char *)h); 451730300Sjoerg if (len > 5 && name_len) { 451869211Sphk log(-1, ": "); 451930300Sjoerg sppp_print_string((char*)(h+1), name_len); 452030300Sjoerg } 452169211Sphk log(-1, "\n"); 452230300Sjoerg } else 452340008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 452440008Sjoerg SPP_ARGS(ifp)); 452530300Sjoerg /* await LCP shutdown by authenticator */ 452630300Sjoerg break; 452730300Sjoerg 452830300Sjoerg default: 452930300Sjoerg /* Unknown PAP packet type -- ignore. */ 453030300Sjoerg if (debug) { 453140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 453230300Sjoerg "<0x%x id=0x%x len=%d", 453340008Sjoerg SPP_ARGS(ifp), 453430300Sjoerg h->type, h->ident, ntohs(h->len)); 453544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 453669211Sphk log(-1, ">\n"); 453730300Sjoerg } 453830300Sjoerg break; 453930300Sjoerg 454030300Sjoerg } 454130300Sjoerg} 454230300Sjoerg 454330300Sjoergstatic void 454430300Sjoergsppp_pap_init(struct sppp *sp) 454530300Sjoerg{ 454630300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 454730300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 454830300Sjoerg sp->fail_counter[IDX_PAP] = 0; 454978064Sume sp->pp_seq[IDX_PAP] = 0; 455078064Sume sp->pp_rseq[IDX_PAP] = 0; 4551188668Srwatson callout_init(&sp->ch[IDX_PAP], CALLOUT_MPSAFE); 4552188668Srwatson callout_init(&sp->pap_my_to_ch, CALLOUT_MPSAFE); 455330300Sjoerg} 455430300Sjoerg 455530300Sjoergstatic void 455630300Sjoergsppp_pap_open(struct sppp *sp) 455730300Sjoerg{ 455830300Sjoerg if (sp->hisauth.proto == PPP_PAP && 455930300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 456030300Sjoerg /* we are authenticator for PAP, start our timer */ 456130300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 456230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 456330300Sjoerg } 456430300Sjoerg if (sp->myauth.proto == PPP_PAP) { 456530300Sjoerg /* we are peer, send a request, and start a timer */ 456630300Sjoerg pap.scr(sp); 4567138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4568138745Srik sppp_pap_my_TO, (void *)sp); 456930300Sjoerg } 457030300Sjoerg} 457130300Sjoerg 457230300Sjoergstatic void 457330300Sjoergsppp_pap_close(struct sppp *sp) 457430300Sjoerg{ 457530300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 457630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 457730300Sjoerg} 457830300Sjoerg 457930300Sjoerg/* 458030300Sjoerg * That's the timeout routine if we are authenticator. Since the 458130300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 458230300Sjoerg */ 458330300Sjoergstatic void 458430300Sjoergsppp_pap_TO(void *cookie) 458530300Sjoerg{ 458630300Sjoerg struct sppp *sp = (struct sppp *)cookie; 458730300Sjoerg STDDCL; 458830300Sjoerg 4589138745Srik SPPP_LOCK(sp); 459030300Sjoerg if (debug) 459140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 459240008Sjoerg SPP_ARGS(ifp), 459330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 459430300Sjoerg sp->rst_counter[IDX_PAP]); 459530300Sjoerg 459630300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 459730300Sjoerg /* TO- event */ 459830300Sjoerg switch (sp->state[IDX_PAP]) { 459930300Sjoerg case STATE_REQ_SENT: 460030300Sjoerg pap.tld(sp); 460130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 460230300Sjoerg break; 460330300Sjoerg } 460430300Sjoerg else 460530300Sjoerg /* TO+ event, not very much we could do */ 460630300Sjoerg switch (sp->state[IDX_PAP]) { 460730300Sjoerg case STATE_REQ_SENT: 460830300Sjoerg /* sppp_cp_change_state() will restart the timer */ 460930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 461030300Sjoerg break; 461130300Sjoerg } 461230300Sjoerg 4613138745Srik SPPP_UNLOCK(sp); 461430300Sjoerg} 461530300Sjoerg 461630300Sjoerg/* 461730300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 461830300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 461930300Sjoerg * XXX We should impose a max counter. 462030300Sjoerg */ 462130300Sjoergstatic void 462230300Sjoergsppp_pap_my_TO(void *cookie) 462330300Sjoerg{ 462430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 462530300Sjoerg STDDCL; 462630300Sjoerg 462730300Sjoerg if (debug) 462840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 462940008Sjoerg SPP_ARGS(ifp)); 463030300Sjoerg 4631138745Srik SPPP_LOCK(sp); 463230300Sjoerg pap.scr(sp); 4633138745Srik SPPP_UNLOCK(sp); 463430300Sjoerg} 463530300Sjoerg 463630300Sjoergstatic void 463730300Sjoergsppp_pap_tlu(struct sppp *sp) 463830300Sjoerg{ 463930300Sjoerg STDDCL; 464030300Sjoerg 464130300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 464230300Sjoerg 464330300Sjoerg if (debug) 464440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 464540008Sjoerg SPP_ARGS(ifp), pap.name); 464630300Sjoerg 4647138745Srik SPPP_LOCK(sp); 464830300Sjoerg /* indicate to LCP that we need to be closed down */ 464930300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 465030300Sjoerg 465130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 465230300Sjoerg /* 465330300Sjoerg * Remote is authenticator, but his auth proto didn't 465430300Sjoerg * complete yet. Defer the transition to network 465530300Sjoerg * phase. 465630300Sjoerg */ 4657138745Srik SPPP_UNLOCK(sp); 465830300Sjoerg return; 465930300Sjoerg } 4660138745Srik SPPP_UNLOCK(sp); 466130300Sjoerg sppp_phase_network(sp); 466230300Sjoerg} 466330300Sjoerg 466430300Sjoergstatic void 466530300Sjoergsppp_pap_tld(struct sppp *sp) 466630300Sjoerg{ 466730300Sjoerg STDDCL; 466830300Sjoerg 466930300Sjoerg if (debug) 467040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4671138745Srik callout_stop (&sp->ch[IDX_PAP]); 4672138745Srik callout_stop (&sp->pap_my_to_ch); 467330300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 467430300Sjoerg 467530300Sjoerg lcp.Close(sp); 467630300Sjoerg} 467730300Sjoerg 467830300Sjoergstatic void 467930300Sjoergsppp_pap_scr(struct sppp *sp) 468030300Sjoerg{ 468130300Sjoerg u_char idlen, pwdlen; 468230300Sjoerg 468378064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 468430300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 468530300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 468630300Sjoerg 468730300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 468830300Sjoerg sizeof idlen, (const char *)&idlen, 468940008Sjoerg (size_t)idlen, sp->myauth.name, 469030300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 469140008Sjoerg (size_t)pwdlen, sp->myauth.secret, 469230300Sjoerg 0); 469330300Sjoerg} 469470199Sjhay 469570199Sjhay/* 469625944Sjoerg * Random miscellaneous functions. 469725944Sjoerg */ 469825944Sjoerg 46994910Swollman/* 470030300Sjoerg * Send a PAP or CHAP proto packet. 470130300Sjoerg * 470230300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 470340008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 470430300Sjoerg * mlen == 0. 470542104Sphk * NOTE: never declare variadic functions with types subject to type 470642104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 470742104Sphk * on the architecture you are on... 470830300Sjoerg */ 470930300Sjoerg 471030300Sjoergstatic void 471142104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 471242104Sphk unsigned int type, unsigned int id, 471330300Sjoerg ...) 471430300Sjoerg{ 471530300Sjoerg STDDCL; 471630300Sjoerg struct ppp_header *h; 471730300Sjoerg struct lcp_header *lh; 471830300Sjoerg struct mbuf *m; 471930300Sjoerg u_char *p; 472030300Sjoerg int len; 472142104Sphk unsigned int mlen; 472230300Sjoerg const char *msg; 472330300Sjoerg va_list ap; 472430300Sjoerg 4725243882Sglebius MGETHDR (m, M_NOWAIT, MT_DATA); 472630300Sjoerg if (! m) 472730300Sjoerg return; 472830300Sjoerg m->m_pkthdr.rcvif = 0; 472930300Sjoerg 473030300Sjoerg h = mtod (m, struct ppp_header*); 473130300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 473230300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 473330300Sjoerg h->protocol = htons(cp->proto); 473430300Sjoerg 473530300Sjoerg lh = (struct lcp_header*)(h + 1); 473630300Sjoerg lh->type = type; 473730300Sjoerg lh->ident = id; 473830300Sjoerg p = (u_char*) (lh+1); 473930300Sjoerg 474030300Sjoerg va_start(ap, id); 474130300Sjoerg len = 0; 474230300Sjoerg 474342104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 474430300Sjoerg msg = va_arg(ap, const char *); 474530300Sjoerg len += mlen; 474630300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 474730300Sjoerg va_end(ap); 474830300Sjoerg m_freem(m); 474930300Sjoerg return; 475030300Sjoerg } 475130300Sjoerg 475230300Sjoerg bcopy(msg, p, mlen); 475330300Sjoerg p += mlen; 475430300Sjoerg } 475530300Sjoerg va_end(ap); 475630300Sjoerg 475730300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 475830300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 475930300Sjoerg 476030300Sjoerg if (debug) { 476140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 476240008Sjoerg SPP_ARGS(ifp), cp->name, 476330300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 476430300Sjoerg lh->ident, ntohs(lh->len)); 476544145Sphk sppp_print_bytes((u_char*) (lh+1), len); 476669211Sphk log(-1, ">\n"); 476730300Sjoerg } 476869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 476969152Sjlemon ifp->if_oerrors++; 477030300Sjoerg} 477130300Sjoerg 477230300Sjoerg/* 477325944Sjoerg * Flush interface queue. 47744910Swollman */ 477512820Sphkstatic void 477625944Sjoergsppp_qflush(struct ifqueue *ifq) 47774910Swollman{ 477825944Sjoerg struct mbuf *m, *n; 47794910Swollman 478025944Sjoerg n = ifq->ifq_head; 478125944Sjoerg while ((m = n)) { 478225944Sjoerg n = m->m_act; 478325944Sjoerg m_freem (m); 478411189Sjkh } 478525944Sjoerg ifq->ifq_head = 0; 478625944Sjoerg ifq->ifq_tail = 0; 478725944Sjoerg ifq->ifq_len = 0; 478825944Sjoerg} 478925944Sjoerg 479025944Sjoerg/* 479125944Sjoerg * Send keepalive packets, every 10 seconds. 479225944Sjoerg */ 479325944Sjoergstatic void 479425944Sjoergsppp_keepalive(void *dummy) 479525944Sjoerg{ 4796138745Srik struct sppp *sp = (struct sppp*)dummy; 4797147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 479825944Sjoerg 4799138745Srik SPPP_LOCK(sp); 4800138745Srik /* Keepalive mode disabled or channel down? */ 4801138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4802148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4803138745Srik goto out; 480425944Sjoerg 4805139365Srik if (sp->pp_mode == PP_FR) { 4806139365Srik sppp_fr_keepalive (sp); 4807139365Srik goto out; 4808139365Srik } 4809139365Srik 4810138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4811138745Srik if (sp->pp_mode != IFF_CISCO && 4812138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4813138745Srik goto out; 481425944Sjoerg 4815138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4816138745Srik /* No keepalive packets got. Stop the interface. */ 4817138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4818138745Srik if_down (ifp); 4819138745Srik sppp_qflush (&sp->pp_cpq); 4820138745Srik if (sp->pp_mode != IFF_CISCO) { 4821138745Srik /* XXX */ 4822138745Srik /* Shut down the PPP link. */ 4823138745Srik lcp.Down(sp); 4824138745Srik /* Initiate negotiation. XXX */ 4825138745Srik lcp.Up(sp); 48264910Swollman } 48274910Swollman } 4828138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4829138745Srik ++sp->pp_alivecnt; 4830138745Srik if (sp->pp_mode == IFF_CISCO) 4831138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4832138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4833138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4834138745Srik long nmagic = htonl (sp->lcp.magic); 4835138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4836138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4837138745Srik sp->lcp.echoid, 4, &nmagic); 4838138745Srik } 4839138745Srikout: 4840138745Srik SPPP_UNLOCK(sp); 4841138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4842138745Srik (void *)sp); 48434910Swollman} 48444910Swollman 484525944Sjoerg/* 484625944Sjoerg * Get both IP addresses. 484725944Sjoerg */ 4848139365Srikvoid 484930300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 485025944Sjoerg{ 4851147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 485225944Sjoerg struct ifaddr *ifa; 485330300Sjoerg struct sockaddr_in *si, *sm; 485425944Sjoerg u_long ssrc, ddst; 485525944Sjoerg 485640010Sjoerg sm = NULL; 485725944Sjoerg ssrc = ddst = 0L; 485825944Sjoerg /* 485925944Sjoerg * Pick the first AF_INET address from the list, 486025944Sjoerg * aliases don't make any sense on a p2p link anyway. 486125944Sjoerg */ 486242065Sphk si = 0; 4863195070Srwatson if_addr_rlock(ifp); 486442065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 486525944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 486625944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 486730300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 486825944Sjoerg if (si) 486925944Sjoerg break; 487025944Sjoerg } 487125944Sjoerg if (ifa) { 487230300Sjoerg if (si && si->sin_addr.s_addr) { 487325944Sjoerg ssrc = si->sin_addr.s_addr; 487430300Sjoerg if (srcmask) 487530300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 487630300Sjoerg } 487725944Sjoerg 487825944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 487925944Sjoerg if (si && si->sin_addr.s_addr) 488025944Sjoerg ddst = si->sin_addr.s_addr; 488125944Sjoerg } 4882195070Srwatson if_addr_runlock(ifp); 488325944Sjoerg 488425944Sjoerg if (dst) *dst = ntohl(ddst); 488525944Sjoerg if (src) *src = ntohl(ssrc); 488625944Sjoerg} 488725944Sjoerg 4888184682Sbz#ifdef INET 488925944Sjoerg/* 4890241686Sandre * Set my IP address. 489125944Sjoerg */ 489225944Sjoergstatic void 489325944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 489425944Sjoerg{ 489542104Sphk STDDCL; 489625944Sjoerg struct ifaddr *ifa; 489725944Sjoerg struct sockaddr_in *si; 489884318Sjlemon struct in_ifaddr *ia; 489925944Sjoerg 490025944Sjoerg /* 490125944Sjoerg * Pick the first AF_INET address from the list, 490225944Sjoerg * aliases don't make any sense on a p2p link anyway. 490325944Sjoerg */ 490442065Sphk si = 0; 4905195070Srwatson if_addr_rlock(ifp); 4906194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 4907194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET) { 490825944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 4909194813Srwatson if (si != NULL) { 4910194813Srwatson ifa_ref(ifa); 491125944Sjoerg break; 4912194813Srwatson } 491325944Sjoerg } 491440008Sjoerg } 4915195070Srwatson if_addr_runlock(ifp); 491640008Sjoerg 4917194813Srwatson if (ifa != NULL) { 491842104Sphk int error; 4919194813Srwatson 492042104Sphk /* delete old route */ 492142104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 4922194813Srwatson if (debug && error) { 492342104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 492442104Sphk SPP_ARGS(ifp), error); 492542104Sphk } 492642104Sphk 492742104Sphk /* set new address */ 492825944Sjoerg si->sin_addr.s_addr = htonl(src); 492984318Sjlemon ia = ifatoia(ifa); 4930194951Srwatson IN_IFADDR_WLOCK(); 493184318Sjlemon LIST_REMOVE(ia, ia_hash); 493284318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 4933194951Srwatson IN_IFADDR_WUNLOCK(); 493425944Sjoerg 493542104Sphk /* add new route */ 493670199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 4937194813Srwatson if (debug && error) { 493842104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 493942104Sphk SPP_ARGS(ifp), error); 494042104Sphk } 4941194813Srwatson ifa_free(ifa); 494242104Sphk } 494388599Sjoerg} 4944184682Sbz#endif 494578064Sume 494678064Sume#ifdef INET6 494778064Sume/* 494878064Sume * Get both IPv6 addresses. 494978064Sume */ 495078064Sumestatic void 495178064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 495278064Sume struct in6_addr *srcmask) 495378064Sume{ 4954147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 495578064Sume struct ifaddr *ifa; 495678064Sume struct sockaddr_in6 *si, *sm; 495778064Sume struct in6_addr ssrc, ddst; 495878064Sume 495978064Sume sm = NULL; 496078064Sume bzero(&ssrc, sizeof(ssrc)); 496178064Sume bzero(&ddst, sizeof(ddst)); 496278064Sume /* 496378064Sume * Pick the first link-local AF_INET6 address from the list, 496478064Sume * aliases don't make any sense on a p2p link anyway. 496578064Sume */ 4966194813Srwatson si = NULL; 4967195070Srwatson if_addr_rlock(ifp); 4968160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 496978064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 497078064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 497178064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 497278064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 497378064Sume break; 497478064Sume } 497578064Sume if (ifa) { 497678064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 497778064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 497878064Sume if (srcmask) { 497978064Sume bcopy(&sm->sin6_addr, srcmask, 498078064Sume sizeof(*srcmask)); 498178064Sume } 498278064Sume } 498378064Sume 498478064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 498578064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 498678064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 498778064Sume } 498878064Sume 498978064Sume if (dst) 499078064Sume bcopy(&ddst, dst, sizeof(*dst)); 499178064Sume if (src) 499278064Sume bcopy(&ssrc, src, sizeof(*src)); 4993195070Srwatson if_addr_runlock(ifp); 499470199Sjhay} 499542104Sphk 499678064Sume#ifdef IPV6CP_MYIFID_DYN 499778064Sume/* 499878064Sume * Generate random ifid. 499978064Sume */ 500078064Sumestatic void 500178064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 500278064Sume{ 500378064Sume /* TBD */ 500478064Sume} 500578064Sume 500678064Sume/* 5007241686Sandre * Set my IPv6 address. 500878064Sume */ 500978064Sumestatic void 501078064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 501178064Sume{ 501278064Sume STDDCL; 501378064Sume struct ifaddr *ifa; 501478064Sume struct sockaddr_in6 *sin6; 501578064Sume 501678064Sume /* 501778064Sume * Pick the first link-local AF_INET6 address from the list, 501878064Sume * aliases don't make any sense on a p2p link anyway. 501978064Sume */ 502078064Sume 502178064Sume sin6 = NULL; 5022195070Srwatson if_addr_rlock(ifp); 5023194813Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 5024194813Srwatson if (ifa->ifa_addr->sa_family == AF_INET6) { 502578064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 5026194813Srwatson if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 5027194813Srwatson ifa_ref(ifa); 502878064Sume break; 5029194813Srwatson } 503078064Sume } 503178064Sume } 5032195070Srwatson if_addr_runlock(ifp); 503378064Sume 5034194813Srwatson if (ifa != NULL) { 503578064Sume int error; 503678064Sume struct sockaddr_in6 new_sin6 = *sin6; 503778064Sume 503878064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 503978064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 5040194813Srwatson if (debug && error) { 504178064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 504278064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 504378064Sume } 5044194813Srwatson ifa_free(ifa); 504578064Sume } 504678064Sume} 504778064Sume#endif 504878064Sume 504978064Sume/* 505078064Sume * Suggest a candidate address to be used by peer. 505178064Sume */ 505278064Sumestatic void 505378064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 505478064Sume{ 505578064Sume struct in6_addr myaddr; 505678064Sume struct timeval tv; 505778064Sume 505878064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 505978064Sume 506078064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 506178064Sume microtime(&tv); 506278064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 506378064Sume myaddr.s6_addr[14] ^= 0xff; 506478064Sume myaddr.s6_addr[15] ^= 0xff; 506578064Sume } else { 506678064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 506778064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 506878064Sume } 506978064Sume if (suggest) 507078064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 507178064Sume} 507278064Sume#endif /*INET6*/ 507378064Sume 507430300Sjoergstatic int 507538343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 507630300Sjoerg{ 507738343Sbde u_long subcmd; 507830300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 507988600Sjoerg struct spppreq *spr; 508088600Sjoerg int rv = 0; 508130300Sjoerg 508288600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 508388600Sjoerg return (EAGAIN); 508430300Sjoerg /* 508530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 508630300Sjoerg * Check the cmd word first before attempting to fetch all the 508730300Sjoerg * data. 508830300Sjoerg */ 508988600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 509088600Sjoerg rv = EFAULT; 509188600Sjoerg goto quit; 509288600Sjoerg } 509330300Sjoerg 509488600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 509588600Sjoerg rv = EFAULT; 509688600Sjoerg goto quit; 509788600Sjoerg } 509830300Sjoerg 509930300Sjoerg switch (subcmd) { 5100170490Smjacob case (u_long)SPPPIOGDEFS: 510188600Sjoerg if (cmd != SIOCGIFGENERIC) { 510288600Sjoerg rv = EINVAL; 510388600Sjoerg break; 510488600Sjoerg } 510530300Sjoerg /* 510630300Sjoerg * We copy over the entire current state, but clean 510730300Sjoerg * out some of the stuff we don't wanna pass up. 510830300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 510930300Sjoerg * called by any user. No need to ever get PAP or 511030300Sjoerg * CHAP secrets back to userland anyway. 511130300Sjoerg */ 511288600Sjoerg spr->defs.pp_phase = sp->pp_phase; 511388723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 511488723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 511588600Sjoerg spr->defs.lcp = sp->lcp; 511688600Sjoerg spr->defs.ipcp = sp->ipcp; 511788600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 511888600Sjoerg spr->defs.myauth = sp->myauth; 511988600Sjoerg spr->defs.hisauth = sp->hisauth; 512088600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 512188600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 512288600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 512388600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 512488550Sjoerg /* 512588550Sjoerg * Fixup the LCP timeout value to milliseconds so 512688550Sjoerg * spppcontrol doesn't need to bother about the value 512788550Sjoerg * of "hz". We do the reverse calculation below when 512888550Sjoerg * setting it. 512988550Sjoerg */ 513088600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 513188600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 513288600Sjoerg sizeof(struct spppreq)); 513388600Sjoerg break; 513430300Sjoerg 5135170490Smjacob case (u_long)SPPPIOSDEFS: 513688600Sjoerg if (cmd != SIOCSIFGENERIC) { 513788600Sjoerg rv = EINVAL; 513888600Sjoerg break; 513988600Sjoerg } 514030300Sjoerg /* 514188550Sjoerg * We have a very specific idea of which fields we 514288550Sjoerg * allow being passed back from userland, so to not 514388550Sjoerg * clobber our current state. For one, we only allow 514488550Sjoerg * setting anything if LCP is in dead or establish 514588550Sjoerg * phase. Once the authentication negotiations 514688550Sjoerg * started, the authentication settings must not be 514788550Sjoerg * changed again. (The administrator can force an 514830300Sjoerg * ifconfig down in order to get LCP back into dead 514930300Sjoerg * phase.) 515030300Sjoerg * 515130300Sjoerg * Also, we only allow for authentication parameters to be 515230300Sjoerg * specified. 515330300Sjoerg * 515430300Sjoerg * XXX Should allow to set or clear pp_flags. 515530300Sjoerg * 515630300Sjoerg * Finally, if the respective authentication protocol to 515730300Sjoerg * be used is set differently than 0, but the secret is 515830300Sjoerg * passed as all zeros, we don't trash the existing secret. 515930300Sjoerg * This allows an administrator to change the system name 516030300Sjoerg * only without clobbering the secret (which he didn't get 516130300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 516230300Sjoerg * secrets are cleared if the authentication protocol is 516388550Sjoerg * reset to 0. */ 516488550Sjoerg if (sp->pp_phase != PHASE_DEAD && 516588600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 516688600Sjoerg rv = EBUSY; 516788600Sjoerg break; 516888600Sjoerg } 516930300Sjoerg 517088600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 517188600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 517288600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 517388600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 517488600Sjoerg rv = EINVAL; 517588600Sjoerg break; 517688600Sjoerg } 517730300Sjoerg 517888600Sjoerg if (spr->defs.myauth.proto == 0) 517930300Sjoerg /* resetting myauth */ 518030300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 518130300Sjoerg else { 518230300Sjoerg /* setting/changing myauth */ 518388600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 518488600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 518588600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 518688600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 518730300Sjoerg AUTHKEYLEN); 518830300Sjoerg } 518988600Sjoerg if (spr->defs.hisauth.proto == 0) 519030300Sjoerg /* resetting hisauth */ 519130300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 519230300Sjoerg else { 519330300Sjoerg /* setting/changing hisauth */ 519488600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 519588600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 519688600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 519788600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 519888600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 519930300Sjoerg AUTHKEYLEN); 520030300Sjoerg } 520188550Sjoerg /* set LCP restart timer timeout */ 520288600Sjoerg if (spr->defs.lcp.timeout != 0) 520388600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 520488723Sjoerg /* set VJ enable and IPv6 disable flags */ 520588723Sjoerg#ifdef INET 520688723Sjoerg if (spr->defs.enable_vj) 520788723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 520888723Sjoerg else 520988723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 521088723Sjoerg#endif 521188723Sjoerg#ifdef INET6 521288723Sjoerg if (spr->defs.enable_ipv6) 521388723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 521488723Sjoerg else 521588723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 521696349Sjoerg#endif 521730300Sjoerg break; 521830300Sjoerg 521930300Sjoerg default: 522088600Sjoerg rv = EINVAL; 522130300Sjoerg } 522230300Sjoerg 522388600Sjoerg quit: 522488600Sjoerg free(spr, M_TEMP); 522588600Sjoerg 522688600Sjoerg return (rv); 522730300Sjoerg} 522830300Sjoerg 522930300Sjoergstatic void 523030300Sjoergsppp_phase_network(struct sppp *sp) 523130300Sjoerg{ 523242066Sphk STDDCL; 523330300Sjoerg int i; 523430300Sjoerg u_long mask; 523530300Sjoerg 523630300Sjoerg sp->pp_phase = PHASE_NETWORK; 523730300Sjoerg 523842066Sphk if (debug) 523942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 524042066Sphk sppp_phase_name(sp->pp_phase)); 524130300Sjoerg 524230300Sjoerg /* Notify NCPs now. */ 524330300Sjoerg for (i = 0; i < IDX_COUNT; i++) 524430300Sjoerg if ((cps[i])->flags & CP_NCP) 524530300Sjoerg (cps[i])->Open(sp); 524630300Sjoerg 524730300Sjoerg /* Send Up events to all NCPs. */ 524830300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 524988706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 525030300Sjoerg (cps[i])->Up(sp); 525130300Sjoerg 525230300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 525330300Sjoerg sppp_lcp_check_and_close(sp); 525430300Sjoerg} 525530300Sjoerg 525670199Sjhay 525725706Sjoergstatic const char * 525825944Sjoergsppp_cp_type_name(u_char type) 52594910Swollman{ 526030300Sjoerg static char buf[12]; 52614910Swollman switch (type) { 526230300Sjoerg case CONF_REQ: return "conf-req"; 526330300Sjoerg case CONF_ACK: return "conf-ack"; 526430300Sjoerg case CONF_NAK: return "conf-nak"; 526530300Sjoerg case CONF_REJ: return "conf-rej"; 526630300Sjoerg case TERM_REQ: return "term-req"; 526730300Sjoerg case TERM_ACK: return "term-ack"; 526830300Sjoerg case CODE_REJ: return "code-rej"; 526930300Sjoerg case PROTO_REJ: return "proto-rej"; 527030300Sjoerg case ECHO_REQ: return "echo-req"; 527130300Sjoerg case ECHO_REPLY: return "echo-reply"; 527230300Sjoerg case DISC_REQ: return "discard-req"; 52734910Swollman } 527444145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 527530300Sjoerg return buf; 52764910Swollman} 52774910Swollman 527825706Sjoergstatic const char * 527930300Sjoergsppp_auth_type_name(u_short proto, u_char type) 528030300Sjoerg{ 528130300Sjoerg static char buf[12]; 528230300Sjoerg switch (proto) { 528330300Sjoerg case PPP_CHAP: 528430300Sjoerg switch (type) { 528530300Sjoerg case CHAP_CHALLENGE: return "challenge"; 528630300Sjoerg case CHAP_RESPONSE: return "response"; 528730300Sjoerg case CHAP_SUCCESS: return "success"; 528830300Sjoerg case CHAP_FAILURE: return "failure"; 528930300Sjoerg } 529030300Sjoerg case PPP_PAP: 529130300Sjoerg switch (type) { 529230300Sjoerg case PAP_REQ: return "req"; 529330300Sjoerg case PAP_ACK: return "ack"; 529430300Sjoerg case PAP_NAK: return "nak"; 529530300Sjoerg } 529630300Sjoerg } 529744145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 529830300Sjoerg return buf; 529930300Sjoerg} 530030300Sjoerg 530130300Sjoergstatic const char * 530225944Sjoergsppp_lcp_opt_name(u_char opt) 53034910Swollman{ 530430300Sjoerg static char buf[12]; 530525944Sjoerg switch (opt) { 530630300Sjoerg case LCP_OPT_MRU: return "mru"; 530730300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 530830300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 530930300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 531030300Sjoerg case LCP_OPT_MAGIC: return "magic"; 531130300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 531230300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 53134910Swollman } 531444145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 531530300Sjoerg return buf; 53164910Swollman} 53174910Swollman 5318184682Sbz#ifdef INET 531925944Sjoergstatic const char * 532025944Sjoergsppp_ipcp_opt_name(u_char opt) 532125944Sjoerg{ 532230300Sjoerg static char buf[12]; 532325944Sjoerg switch (opt) { 532430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 532530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 532630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 532725944Sjoerg } 532844145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 532930300Sjoerg return buf; 533025944Sjoerg} 5331184682Sbz#endif 533225944Sjoerg 533378064Sume#ifdef INET6 533425944Sjoergstatic const char * 533578064Sumesppp_ipv6cp_opt_name(u_char opt) 533678064Sume{ 533778064Sume static char buf[12]; 533878064Sume switch (opt) { 533978064Sume case IPV6CP_OPT_IFID: return "ifid"; 534078064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 534178064Sume } 534278064Sume sprintf (buf, "0x%x", opt); 534378064Sume return buf; 534478064Sume} 534578064Sume#endif 534678064Sume 534778064Sumestatic const char * 534825944Sjoergsppp_state_name(int state) 534925944Sjoerg{ 535025944Sjoerg switch (state) { 535125944Sjoerg case STATE_INITIAL: return "initial"; 535225944Sjoerg case STATE_STARTING: return "starting"; 535325944Sjoerg case STATE_CLOSED: return "closed"; 535425944Sjoerg case STATE_STOPPED: return "stopped"; 535525944Sjoerg case STATE_CLOSING: return "closing"; 535625944Sjoerg case STATE_STOPPING: return "stopping"; 535725944Sjoerg case STATE_REQ_SENT: return "req-sent"; 535825944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 535925944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 536025944Sjoerg case STATE_OPENED: return "opened"; 536125944Sjoerg } 536225944Sjoerg return "illegal"; 536325944Sjoerg} 536425944Sjoerg 536525944Sjoergstatic const char * 536625944Sjoergsppp_phase_name(enum ppp_phase phase) 536725944Sjoerg{ 536825944Sjoerg switch (phase) { 536925944Sjoerg case PHASE_DEAD: return "dead"; 537025944Sjoerg case PHASE_ESTABLISH: return "establish"; 537125944Sjoerg case PHASE_TERMINATE: return "terminate"; 537225944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 537325944Sjoerg case PHASE_NETWORK: return "network"; 537425944Sjoerg } 537525944Sjoerg return "illegal"; 537625944Sjoerg} 537725944Sjoerg 537825944Sjoergstatic const char * 537925944Sjoergsppp_proto_name(u_short proto) 538025944Sjoerg{ 538125944Sjoerg static char buf[12]; 538225944Sjoerg switch (proto) { 538325944Sjoerg case PPP_LCP: return "lcp"; 538425944Sjoerg case PPP_IPCP: return "ipcp"; 538530300Sjoerg case PPP_PAP: return "pap"; 538630300Sjoerg case PPP_CHAP: return "chap"; 538778064Sume case PPP_IPV6CP: return "ipv6cp"; 538825944Sjoerg } 538944145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 539025944Sjoerg return buf; 539125944Sjoerg} 539225944Sjoerg 539312820Sphkstatic void 539430300Sjoergsppp_print_bytes(const u_char *p, u_short len) 53954910Swollman{ 539644145Sphk if (len) 539769211Sphk log(-1, " %*D", len, p, "-"); 53984910Swollman} 539925944Sjoerg 540030300Sjoergstatic void 540130300Sjoergsppp_print_string(const char *p, u_short len) 540230300Sjoerg{ 540330300Sjoerg u_char c; 540430300Sjoerg 540530300Sjoerg while (len-- > 0) { 540630300Sjoerg c = *p++; 540730300Sjoerg /* 540830300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 540930300Sjoerg * using only them, but we don't rely on it. */ 541030300Sjoerg if (c < ' ' || c > '~') 541169211Sphk log(-1, "\\x%x", c); 541230300Sjoerg else 541369211Sphk log(-1, "%c", c); 541430300Sjoerg } 541530300Sjoerg} 541630300Sjoerg 5417184682Sbz#ifdef INET 541830300Sjoergstatic const char * 541930300Sjoergsppp_dotted_quad(u_long addr) 542030300Sjoerg{ 542130300Sjoerg static char s[16]; 542230300Sjoerg sprintf(s, "%d.%d.%d.%d", 542340008Sjoerg (int)((addr >> 24) & 0xff), 542440008Sjoerg (int)((addr >> 16) & 0xff), 542540008Sjoerg (int)((addr >> 8) & 0xff), 542638372Sbde (int)(addr & 0xff)); 542730300Sjoerg return s; 542830300Sjoerg} 5429184682Sbz#endif 543030300Sjoerg 543130300Sjoergstatic int 543230300Sjoergsppp_strnlen(u_char *p, int max) 543330300Sjoerg{ 543430300Sjoerg int len; 543530300Sjoerg 543630300Sjoerg for (len = 0; len < max && *p; ++p) 543730300Sjoerg ++len; 543830300Sjoerg return len; 543930300Sjoerg} 544030300Sjoerg 544130300Sjoerg/* a dummy, used to drop uninteresting events */ 544230300Sjoergstatic void 544330300Sjoergsppp_null(struct sppp *unused) 544430300Sjoerg{ 544530300Sjoerg /* do just nothing */ 544630300Sjoerg} 5447