if_spppsubr.c revision 184682
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 184682 2008-11-05 12:02:25Z bz $ 224910Swollman */ 234910Swollman 2440008Sjoerg#include <sys/param.h> 2540008Sjoerg 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2931742Seivind 304952Sbde#include <sys/systm.h> 314952Sbde#include <sys/kernel.h> 3270199Sjhay#include <sys/module.h> 3324204Sbde#include <sys/sockio.h> 344910Swollman#include <sys/socket.h> 3525706Sjoerg#include <sys/syslog.h> 3659604Sobrien#include <sys/random.h> 3729024Sbde#include <sys/malloc.h> 384910Swollman#include <sys/mbuf.h> 39181803Sbz#include <sys/vimage.h> 4040008Sjoerg 4130300Sjoerg#include <sys/md5.h> 424910Swollman 434910Swollman#include <net/if.h> 444910Swollman#include <net/netisr.h> 454910Swollman#include <net/if_types.h> 4642104Sphk#include <net/route.h> 4788534Sjoerg#include <netinet/in.h> 4888534Sjoerg#include <netinet/in_systm.h> 4988534Sjoerg#include <netinet/ip.h> 5088534Sjoerg#include <net/slcompress.h> 514910Swollman 5230300Sjoerg#include <machine/stdarg.h> 5330300Sjoerg 544910Swollman#include <netinet/in_var.h> 5588705Sjoerg 5688705Sjoerg#ifdef INET 574910Swollman#include <netinet/ip.h> 584910Swollman#include <netinet/tcp.h> 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 177147256SbrooksMALLOC_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 238138745Srik#define SPPP_LOCK(sp) \ 239138745Srik do { \ 240147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 241138745Srik mtx_lock (&(sp)->mtx); \ 242138745Srik } while (0) 243138745Srik#define SPPP_UNLOCK(sp) \ 244138745Srik do { \ 245147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 246138745Srik mtx_unlock (&(sp)->mtx); \ 247138745Srik } while (0) 248138745Srik 249138745Srik#define SPPP_LOCK_ASSERT(sp) \ 250138745Srik do { \ 251147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 252138745Srik mtx_assert (&(sp)->mtx, MA_OWNED); \ 253138745Srik } while (0) 254138745Srik#define SPPP_LOCK_OWNED(sp) \ 255147256Sbrooks (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) && \ 256138745Srik mtx_owned (&sp->mtx)) 257138745Srik 25888705Sjoerg#ifdef INET 2594910Swollman/* 2604910Swollman * The following disgusting hack gets around the problem that IP TOS 2614910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2624910Swollman * priority queue. To decide if traffic is interactive, we check that 2634910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 26430300Sjoerg * 26530300Sjoerg * XXX is this really still necessary? - joerg - 2664910Swollman */ 267126910Srwatsonstatic const u_short interactive_ports[8] = { 2684910Swollman 0, 513, 0, 0, 2694910Swollman 0, 21, 0, 23, 2704910Swollman}; 2714910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 27288705Sjoerg#endif 2734910Swollman 27425944Sjoerg/* almost every function needs these */ 27525944Sjoerg#define STDDCL \ 276147256Sbrooks struct ifnet *ifp = SP2IFP(sp); \ 27725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 27811189Sjkh 27930300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 28025944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2814910Swollman 28225944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 28325944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 28425944Sjoerg 28525944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 28625944Sjoerg struct mbuf *m); 28725944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 28825944Sjoerg u_char ident, u_short len, void *data); 28942104Sphk/* static void sppp_cp_timeout(void *arg); */ 29025944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 29125944Sjoerg int newstate); 29230300Sjoergstatic void sppp_auth_send(const struct cp *cp, 29342104Sphk struct sppp *sp, unsigned int type, unsigned int id, 29430300Sjoerg ...); 29525944Sjoerg 29625944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 29725944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 29825944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 29925944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 30025944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 30125944Sjoerg 30230300Sjoergstatic void sppp_null(struct sppp *sp); 30330300Sjoerg 304138745Srikstatic void sppp_pp_up(struct sppp *sp); 305138745Srikstatic void sppp_pp_down(struct sppp *sp); 306138745Srik 30725944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 30825944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 30925944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31025944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 31125944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 31225944Sjoergstatic void sppp_lcp_TO(void *sp); 31325944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31425944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31525944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 31625944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 31725944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 31825944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 31925944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 32130300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 32230300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 32325944Sjoerg 32425944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 32525944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 32625944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 32725944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 32825944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 32925944Sjoergstatic void sppp_ipcp_TO(void *sp); 33025944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33125944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33225944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33325944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 33425944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 33525944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 33625944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 33825944Sjoerg 33978064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 34078064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 34178064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 34278064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 34378064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 34478064Sumestatic void sppp_ipv6cp_TO(void *sp); 34578064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34678064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34778064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34878064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 34978064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 35078064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 35178064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 35278064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 35378064Sume 35430300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 35530300Sjoergstatic void sppp_pap_init(struct sppp *sp); 35630300Sjoergstatic void sppp_pap_open(struct sppp *sp); 35730300Sjoergstatic void sppp_pap_close(struct sppp *sp); 35830300Sjoergstatic void sppp_pap_TO(void *sp); 35930300Sjoergstatic void sppp_pap_my_TO(void *sp); 36030300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 36130300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 36230300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 36330300Sjoerg 36430300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 36530300Sjoergstatic void sppp_chap_init(struct sppp *sp); 36630300Sjoergstatic void sppp_chap_open(struct sppp *sp); 36730300Sjoergstatic void sppp_chap_close(struct sppp *sp); 36830300Sjoergstatic void sppp_chap_TO(void *sp); 36930300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 37030300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 37130300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 37230300Sjoerg 37330300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 37425944Sjoergstatic const char *sppp_cp_type_name(u_char type); 375184682Sbz#ifdef INET 37630300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 37730300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 378184682Sbz#endif 37978064Sume#ifdef INET6 38078064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 38178064Sume#endif 38225944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 38325944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 38425944Sjoergstatic const char *sppp_proto_name(u_short proto); 38530300Sjoergstatic const char *sppp_state_name(int state); 38638343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 38730300Sjoergstatic int sppp_strnlen(u_char *p, int max); 38825944Sjoergstatic void sppp_keepalive(void *dummy); 38930300Sjoergstatic void sppp_phase_network(struct sppp *sp); 39030300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 39130300Sjoergstatic void sppp_print_string(const char *p, u_short len); 39225944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 393184682Sbz#ifdef INET 39425944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 395184682Sbz#endif 39678064Sume#ifdef INET6 39778064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 39878064Sume struct in6_addr *dst, struct in6_addr *srcmask); 39978064Sume#ifdef IPV6CP_MYIFID_DYN 40078064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40178064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40278064Sume#endif 40378064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 40478064Sume#endif 40525944Sjoerg 406138745Srik/* if_start () wrapper */ 407138745Srikstatic void sppp_ifstart (struct ifnet *ifp); 408138745Srik 40925944Sjoerg/* our control protocol descriptors */ 41033181Seivindstatic const struct cp lcp = { 41125944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 41225944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 41325944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 41425944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 41525944Sjoerg sppp_lcp_scr 41625944Sjoerg}; 41725944Sjoerg 41833181Seivindstatic const struct cp ipcp = { 41988709Sjoerg PPP_IPCP, IDX_IPCP, 42088709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 42188709Sjoerg CP_NCP, 42288709Sjoerg#else 42388709Sjoerg 0, 42488709Sjoerg#endif 42588709Sjoerg "ipcp", 42625944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 42725944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 42825944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 42925944Sjoerg sppp_ipcp_scr 43025944Sjoerg}; 43125944Sjoerg 43278064Sumestatic const struct cp ipv6cp = { 43378064Sume PPP_IPV6CP, IDX_IPV6CP, 43478064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 43578064Sume CP_NCP, 43678064Sume#else 43778064Sume 0, 43878064Sume#endif 43978064Sume "ipv6cp", 44078064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 44178064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 44278064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 44378064Sume sppp_ipv6cp_scr 44478064Sume}; 44578064Sume 44633181Seivindstatic const struct cp pap = { 44730300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 44830300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 44930300Sjoerg sppp_pap_TO, 0, 0, 0, 45030300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 45130300Sjoerg sppp_pap_scr 45230300Sjoerg}; 45330300Sjoerg 45433181Seivindstatic const struct cp chap = { 45530300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 45630300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 45730300Sjoerg sppp_chap_TO, 0, 0, 0, 45830300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 45930300Sjoerg sppp_chap_scr 46030300Sjoerg}; 46130300Sjoerg 46233181Seivindstatic const struct cp *cps[IDX_COUNT] = { 46325944Sjoerg &lcp, /* IDX_LCP */ 46425944Sjoerg &ipcp, /* IDX_IPCP */ 46578064Sume &ipv6cp, /* IDX_IPV6CP */ 46630300Sjoerg &pap, /* IDX_PAP */ 46730300Sjoerg &chap, /* IDX_CHAP */ 46825944Sjoerg}; 46925944Sjoerg 470147256Sbrooksstatic void* 471147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp) 472147256Sbrooks{ 473147256Sbrooks struct sppp *sp; 474147256Sbrooks 475147256Sbrooks sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO); 476147256Sbrooks sp->pp_ifp = ifp; 477147256Sbrooks 478147256Sbrooks return (sp); 479147256Sbrooks} 480147256Sbrooks 481147256Sbrooksstatic void 482147256Sbrookssppp_free(void *com, u_char type) 483147256Sbrooks{ 484147256Sbrooks 485147256Sbrooks free(com, M_SPPP); 486147256Sbrooks} 487147256Sbrooks 48870199Sjhaystatic int 48970199Sjhaysppp_modevent(module_t mod, int type, void *unused) 49070199Sjhay{ 49170199Sjhay switch (type) { 49270199Sjhay case MOD_LOAD: 493147256Sbrooks /* 494147256Sbrooks * XXX: should probably be IFT_SPPP, but it's fairly 495147256Sbrooks * harmless to allocate struct sppp's for non-sppp 496147256Sbrooks * interfaces. 497147256Sbrooks */ 498147256Sbrooks 499147256Sbrooks if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free); 50070199Sjhay break; 50170199Sjhay case MOD_UNLOAD: 502147256Sbrooks /* if_deregister_com_alloc(IFT_PPP); */ 50370199Sjhay return EACCES; 50470199Sjhay default: 505132199Sphk return EOPNOTSUPP; 50670199Sjhay } 50770199Sjhay return 0; 50870199Sjhay} 50970199Sjhaystatic moduledata_t spppmod = { 51070199Sjhay "sppp", 51170199Sjhay sppp_modevent, 51270199Sjhay 0 51370199Sjhay}; 51470199SjhayMODULE_VERSION(sppp, 1); 51570199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 51625944Sjoerg 51770199Sjhay/* 51825944Sjoerg * Exported functions, comprising our interface to the lower layer. 5194910Swollman */ 5204910Swollman 5214910Swollman/* 5224910Swollman * Process the received packet. 5234910Swollman */ 52425706Sjoergvoid 52525706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5264910Swollman{ 5274910Swollman struct ppp_header *h; 528111888Sjlemon int isr = -1; 529147256Sbrooks struct sppp *sp = IFP2SP(ifp); 530184682Sbz int debug, do_account = 0; 531184682Sbz#ifdef INET 532184682Sbz int hlen, vjlen; 53388700Sjoerg u_char *iphdr; 534184682Sbz#endif 5354910Swollman 536138745Srik SPPP_LOCK(sp); 537138745Srik debug = ifp->if_flags & IFF_DEBUG; 538138745Srik 5394910Swollman if (ifp->if_flags & IFF_UP) 5404910Swollman /* Count received bytes, add FCS and one flag */ 5414910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5424910Swollman 5434910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5444910Swollman /* Too small packet, drop it. */ 54525944Sjoerg if (debug) 54625706Sjoerg log(LOG_DEBUG, 54740008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 54840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 54925944Sjoerg drop: 55088700Sjoerg m_freem (m); 551138745Srik SPPP_UNLOCK(sp); 55288700Sjoerg drop2: 55325944Sjoerg ++ifp->if_ierrors; 55425944Sjoerg ++ifp->if_iqdrops; 5554910Swollman return; 5564910Swollman } 5574910Swollman 558139365Srik if (sp->pp_mode == PP_FR) { 559139365Srik sppp_fr_input (sp, m); 560139365Srik SPPP_UNLOCK(sp); 561139365Srik return; 562139365Srik } 563139365Srik 5644910Swollman /* Get PPP header. */ 5654910Swollman h = mtod (m, struct ppp_header*); 5664910Swollman m_adj (m, PPP_HEADER_LEN); 5674910Swollman 5684910Swollman switch (h->address) { 5694910Swollman case PPP_ALLSTATIONS: 5704910Swollman if (h->control != PPP_UI) 5714910Swollman goto invalid; 57245152Sphk if (sp->pp_mode == IFF_CISCO) { 57325944Sjoerg if (debug) 57425706Sjoerg log(LOG_DEBUG, 57540008Sjoerg SPP_FMT "PPP packet in Cisco mode " 57625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 57740008Sjoerg SPP_ARGS(ifp), 57825706Sjoerg h->address, h->control, ntohs(h->protocol)); 57911189Sjkh goto drop; 58011189Sjkh } 5814910Swollman switch (ntohs (h->protocol)) { 5824910Swollman default: 58325944Sjoerg if (debug) 58425706Sjoerg log(LOG_DEBUG, 58544145Sphk SPP_FMT "rejecting protocol " 58625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 58740008Sjoerg SPP_ARGS(ifp), 58825706Sjoerg h->address, h->control, ntohs(h->protocol)); 58944145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 59044145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 59178064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 59244145Sphk &h->protocol); 5934910Swollman ++ifp->if_noproto; 5944910Swollman goto drop; 5954910Swollman case PPP_LCP: 59630300Sjoerg sppp_cp_input(&lcp, sp, m); 5974910Swollman m_freem (m); 598138745Srik SPPP_UNLOCK(sp); 5994910Swollman return; 60030300Sjoerg case PPP_PAP: 60130300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 60230300Sjoerg sppp_pap_input(sp, m); 60330300Sjoerg m_freem (m); 604138745Srik SPPP_UNLOCK(sp); 60530300Sjoerg return; 60630300Sjoerg case PPP_CHAP: 60730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 60830300Sjoerg sppp_chap_input(sp, m); 60930300Sjoerg m_freem (m); 610138745Srik SPPP_UNLOCK(sp); 61130300Sjoerg return; 6124910Swollman#ifdef INET 6134910Swollman case PPP_IPCP: 61425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 61530300Sjoerg sppp_cp_input(&ipcp, sp, m); 6164910Swollman m_freem (m); 617138745Srik SPPP_UNLOCK(sp); 6184910Swollman return; 6194910Swollman case PPP_IP: 62025944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 621111888Sjlemon isr = NETISR_IP; 6224910Swollman } 62388577Sjoerg do_account++; 6244910Swollman break; 62588534Sjoerg case PPP_VJ_COMP: 62688534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 62788700Sjoerg if ((vjlen = 62888700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 62988700Sjoerg m->m_len, m->m_len, 63088700Sjoerg TYPE_COMPRESSED_TCP, 63188700Sjoerg sp->pp_comp, 63288700Sjoerg &iphdr, &hlen)) <= 0) { 63388700Sjoerg if (debug) 63488700Sjoerg log(LOG_INFO, 63588700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 63688700Sjoerg SPP_ARGS(ifp)); 63788534Sjoerg goto drop; 63888700Sjoerg } 63988700Sjoerg 64088700Sjoerg /* 64188700Sjoerg * Trim the VJ header off the packet, and prepend 64288700Sjoerg * the uncompressed IP header (which will usually 64388700Sjoerg * end up in two chained mbufs since there's not 64488700Sjoerg * enough leading space in the existing mbuf). 64588700Sjoerg */ 64688700Sjoerg m_adj(m, vjlen); 647111119Simp M_PREPEND(m, hlen, M_DONTWAIT); 648138745Srik if (m == NULL) { 649138745Srik SPPP_UNLOCK(sp); 65088700Sjoerg goto drop2; 651138745Srik } 65288700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 653111888Sjlemon isr = NETISR_IP; 65488534Sjoerg } 65588599Sjoerg do_account++; 65688534Sjoerg break; 65788534Sjoerg case PPP_VJ_UCOMP: 65888534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 65988700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 66088700Sjoerg m->m_len, m->m_len, 66188700Sjoerg TYPE_UNCOMPRESSED_TCP, 66288700Sjoerg sp->pp_comp, 66388700Sjoerg &iphdr, &hlen) != 0) { 66488700Sjoerg if (debug) 66588700Sjoerg log(LOG_INFO, 66688700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 66788700Sjoerg SPP_ARGS(ifp)); 66888534Sjoerg goto drop; 66988700Sjoerg } 670111888Sjlemon isr = NETISR_IP; 67188534Sjoerg } 67288599Sjoerg do_account++; 67388534Sjoerg break; 67478064Sume#endif 67588599Sjoerg#ifdef INET6 67688599Sjoerg case PPP_IPV6CP: 67788599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 67888599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 67988599Sjoerg m_freem (m); 680138745Srik SPPP_UNLOCK(sp); 68188599Sjoerg return; 68288599Sjoerg 68388599Sjoerg case PPP_IPV6: 684111888Sjlemon if (sp->state[IDX_IPV6CP] == STATE_OPENED) 685111888Sjlemon isr = NETISR_IPV6; 68688599Sjoerg do_account++; 68788599Sjoerg break; 68888599Sjoerg#endif 68912495Speter#ifdef IPX 69012495Speter case PPP_IPX: 69112495Speter /* IPX IPXCP not implemented yet */ 692111888Sjlemon if (sp->pp_phase == PHASE_NETWORK) 693111888Sjlemon isr = NETISR_IPX; 69488577Sjoerg do_account++; 69512495Speter break; 69612495Speter#endif 6974910Swollman } 6984910Swollman break; 6994910Swollman case CISCO_MULTICAST: 7004910Swollman case CISCO_UNICAST: 7014910Swollman /* Don't check the control field here (RFC 1547). */ 70245152Sphk if (sp->pp_mode != IFF_CISCO) { 70325944Sjoerg if (debug) 70425706Sjoerg log(LOG_DEBUG, 70540008Sjoerg SPP_FMT "Cisco packet in PPP mode " 70625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 70740008Sjoerg SPP_ARGS(ifp), 70825706Sjoerg h->address, h->control, ntohs(h->protocol)); 70911189Sjkh goto drop; 71011189Sjkh } 7114910Swollman switch (ntohs (h->protocol)) { 7124910Swollman default: 7134910Swollman ++ifp->if_noproto; 7144910Swollman goto invalid; 7154910Swollman case CISCO_KEEPALIVE: 716147256Sbrooks sppp_cisco_input (sp, m); 7174910Swollman m_freem (m); 718138745Srik SPPP_UNLOCK(sp); 7194910Swollman return; 7204910Swollman#ifdef INET 7214910Swollman case ETHERTYPE_IP: 722111888Sjlemon isr = NETISR_IP; 72388577Sjoerg do_account++; 7244910Swollman break; 7254910Swollman#endif 72654263Sshin#ifdef INET6 72754263Sshin case ETHERTYPE_IPV6: 728111888Sjlemon isr = NETISR_IPV6; 72988577Sjoerg do_account++; 73054263Sshin break; 73154263Sshin#endif 73212495Speter#ifdef IPX 73312495Speter case ETHERTYPE_IPX: 734111888Sjlemon isr = NETISR_IPX; 73588577Sjoerg do_account++; 73612495Speter break; 73712495Speter#endif 7384910Swollman } 7394910Swollman break; 74025944Sjoerg default: /* Invalid PPP packet. */ 74125944Sjoerg invalid: 74225944Sjoerg if (debug) 74325944Sjoerg log(LOG_DEBUG, 74440008Sjoerg SPP_FMT "invalid input packet " 74525944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 74640008Sjoerg SPP_ARGS(ifp), 74725944Sjoerg h->address, h->control, ntohs(h->protocol)); 74825944Sjoerg goto drop; 7494910Swollman } 7504910Swollman 751111888Sjlemon if (! (ifp->if_flags & IFF_UP) || isr == -1) 7524910Swollman goto drop; 7534910Swollman 754138745Srik SPPP_UNLOCK(sp); 7554910Swollman /* Check queue. */ 756134391Sandre if (netisr_queue(isr, m)) { /* (0) on success. */ 75725944Sjoerg if (debug) 75840008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 75940008Sjoerg SPP_ARGS(ifp)); 760131241Srik goto drop2; 7614910Swollman } 762138745Srik 76388577Sjoerg if (do_account) 76488577Sjoerg /* 76588577Sjoerg * Do only account for network packets, not for control 76688577Sjoerg * packets. This is used by some subsystems to detect 76788577Sjoerg * idle lines. 76888577Sjoerg */ 769150349Sandre sp->pp_last_recv = time_uptime; 7704910Swollman} 7714910Swollman 772138745Srikstatic void 773138745Sriksppp_ifstart_sched(void *dummy) 774138745Srik{ 775138745Srik struct sppp *sp = dummy; 776138745Srik 777147256Sbrooks sp->if_start(SP2IFP(sp)); 778138745Srik} 779138745Srik 780138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for 781138745Srik * execution. We can't call it directly 782138745Srik */ 783138745Srikstatic void 784138745Sriksppp_ifstart(struct ifnet *ifp) 785138745Srik{ 786147256Sbrooks struct sppp *sp = IFP2SP(ifp); 787138745Srik 788138745Srik if (SPPP_LOCK_OWNED(sp)) { 789138745Srik if (callout_pending(&sp->ifstart_callout)) 790138745Srik return; 791138745Srik callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched, 792138745Srik (void *)sp); 793138745Srik } else { 794138745Srik sp->if_start(ifp); 795138745Srik } 796138745Srik} 797138745Srik 7984910Swollman/* 7994910Swollman * Enqueue transmit packet. 8004910Swollman */ 80112820Sphkstatic int 80225706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 80325706Sjoerg struct sockaddr *dst, struct rtentry *rt) 8044910Swollman{ 805147256Sbrooks struct sppp *sp = IFP2SP(ifp); 8064910Swollman struct ppp_header *h; 80778064Sume struct ifqueue *ifq = NULL; 808130549Smlaier int s, error, rv = 0; 809184682Sbz#ifdef INET 81088534Sjoerg int ipproto = PPP_IP; 811184682Sbz#endif 81242066Sphk int debug = ifp->if_flags & IFF_DEBUG; 8134910Swollman 81425944Sjoerg s = splimp(); 815138745Srik SPPP_LOCK(sp); 81625944Sjoerg 817148887Srwatson if (!(ifp->if_flags & IFF_UP) || 818148887Srwatson (!(ifp->if_flags & IFF_AUTO) && 819148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING))) { 82088723Sjoerg#ifdef INET6 82188723Sjoerg drop: 82288723Sjoerg#endif 8234910Swollman m_freem (m); 824138745Srik SPPP_UNLOCK(sp); 8254910Swollman splx (s); 8264910Swollman return (ENETDOWN); 8274910Swollman } 8284910Swollman 829148887Srwatson if ((ifp->if_flags & IFF_AUTO) && 830148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 83188723Sjoerg#ifdef INET6 83225944Sjoerg /* 83388723Sjoerg * XXX 83488723Sjoerg * 83588723Sjoerg * Hack to prevent the initialization-time generated 83688723Sjoerg * IPv6 multicast packet to erroneously cause a 83788723Sjoerg * dialout event in case IPv6 has been 83888723Sjoerg * administratively disabled on that interface. 83988723Sjoerg */ 84088723Sjoerg if (dst->sa_family == AF_INET6 && 84188723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 84288723Sjoerg goto drop; 84388723Sjoerg#endif 84488723Sjoerg /* 84525944Sjoerg * Interface is not yet running, but auto-dial. Need 84625944Sjoerg * to start LCP for it. 84725944Sjoerg */ 848148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 84925944Sjoerg splx(s); 85025944Sjoerg lcp.Open(sp); 85125944Sjoerg s = splimp(); 85225944Sjoerg } 85325944Sjoerg 8544910Swollman#ifdef INET 85512436Speter if (dst->sa_family == AF_INET) { 85640008Sjoerg /* XXX Check mbuf length here? */ 85712436Speter struct ip *ip = mtod (m, struct ip*); 85812436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8594910Swollman 86042104Sphk /* 86142104Sphk * When using dynamic local IP address assignment by using 86242104Sphk * 0.0.0.0 as a local address, the first TCP session will 86342104Sphk * not connect because the local TCP checksum is computed 86442104Sphk * using 0.0.0.0 which will later become our real IP address 86542104Sphk * so the TCP checksum computed at the remote end will 86642104Sphk * become invalid. So we 86742104Sphk * - don't let packets with src ip addr 0 thru 86842104Sphk * - we flag TCP packets with src ip 0 as an error 86970199Sjhay */ 87042104Sphk 87142104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 87242104Sphk { 87342104Sphk m_freem(m); 874138745Srik SPPP_UNLOCK(sp); 87542104Sphk splx(s); 87642104Sphk if(ip->ip_p == IPPROTO_TCP) 87742104Sphk return(EADDRNOTAVAIL); 87842104Sphk else 87942104Sphk return(0); 88042104Sphk } 88170199Sjhay 88242104Sphk /* 88342104Sphk * Put low delay, telnet, rlogin and ftp control packets 884130549Smlaier * in front of the queue or let ALTQ take care. 88542104Sphk */ 886130549Smlaier if (ALTQ_IS_ENABLED(&ifp->if_snd)) 88741686Sphk ; 888130549Smlaier else if (_IF_QFULL(&sp->pp_fastq)) 889130549Smlaier ; 89041686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 89112436Speter ifq = &sp->pp_fastq; 89241686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 89341686Sphk ; 89441686Sphk else if (ip->ip_p != IPPROTO_TCP) 89541686Sphk ; 89641686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 89741686Sphk ifq = &sp->pp_fastq; 89841686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 89941686Sphk ifq = &sp->pp_fastq; 90088534Sjoerg 90188534Sjoerg /* 90288534Sjoerg * Do IP Header compression 90388534Sjoerg */ 904139365Srik if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR && 905138745Srik (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP) 90688599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 90788534Sjoerg sp->ipcp.compress_cid)) { 90888534Sjoerg case TYPE_COMPRESSED_TCP: 90988534Sjoerg ipproto = PPP_VJ_COMP; 91088534Sjoerg break; 91188534Sjoerg case TYPE_UNCOMPRESSED_TCP: 91288534Sjoerg ipproto = PPP_VJ_UCOMP; 91388534Sjoerg break; 91488534Sjoerg case TYPE_IP: 91588534Sjoerg ipproto = PPP_IP; 91688534Sjoerg break; 91788534Sjoerg default: 91888534Sjoerg m_freem(m); 919138745Srik SPPP_UNLOCK(sp); 92088534Sjoerg splx(s); 92188534Sjoerg return (EINVAL); 92288534Sjoerg } 9234910Swollman } 9244910Swollman#endif 9254910Swollman 92678064Sume#ifdef INET6 92778064Sume if (dst->sa_family == AF_INET6) { 92878064Sume /* XXX do something tricky here? */ 92978064Sume } 93078064Sume#endif 93178064Sume 932139365Srik if (sp->pp_mode == PP_FR) { 933139365Srik /* Add frame relay header. */ 934139365Srik m = sppp_fr_header (sp, m, dst->sa_family); 935139365Srik if (! m) 936139365Srik goto nobufs; 937139365Srik goto out; 938139365Srik } 939139365Srik 9404910Swollman /* 9414910Swollman * Prepend general data packet PPP header. For now, IP only. 9424910Swollman */ 943111119Simp M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 9444910Swollman if (! m) { 945139365Sriknobufs: if (debug) 94640008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 94740008Sjoerg SPP_ARGS(ifp)); 94825944Sjoerg ++ifp->if_oerrors; 949138745Srik SPPP_UNLOCK(sp); 9504910Swollman splx (s); 9514910Swollman return (ENOBUFS); 9524910Swollman } 95340008Sjoerg /* 95440008Sjoerg * May want to check size of packet 95540008Sjoerg * (albeit due to the implementation it's always enough) 95640008Sjoerg */ 9574910Swollman h = mtod (m, struct ppp_header*); 95845152Sphk if (sp->pp_mode == IFF_CISCO) { 95928088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9604910Swollman h->control = 0; 9614910Swollman } else { 9624910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9634910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9644910Swollman } 9654910Swollman 9664910Swollman switch (dst->sa_family) { 9674910Swollman#ifdef INET 9684910Swollman case AF_INET: /* Internet Protocol */ 96945152Sphk if (sp->pp_mode == IFF_CISCO) 97011189Sjkh h->protocol = htons (ETHERTYPE_IP); 97111189Sjkh else { 97225955Sjoerg /* 97325955Sjoerg * Don't choke with an ENETDOWN early. It's 97425955Sjoerg * possible that we just started dialing out, 97525955Sjoerg * so don't drop the packet immediately. If 97625955Sjoerg * we notice that we run out of buffer space 97725955Sjoerg * below, we will however remember that we are 97825955Sjoerg * not ready to carry IP packets, and return 97925955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 98025955Sjoerg */ 98188534Sjoerg h->protocol = htons(ipproto); 98225955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 98325955Sjoerg rv = ENETDOWN; 98411189Sjkh } 9854910Swollman break; 9864910Swollman#endif 98754263Sshin#ifdef INET6 98854263Sshin case AF_INET6: /* Internet Protocol */ 98954263Sshin if (sp->pp_mode == IFF_CISCO) 99054263Sshin h->protocol = htons (ETHERTYPE_IPV6); 99154263Sshin else { 99278064Sume /* 99378064Sume * Don't choke with an ENETDOWN early. It's 99478064Sume * possible that we just started dialing out, 99578064Sume * so don't drop the packet immediately. If 99678064Sume * we notice that we run out of buffer space 99778064Sume * below, we will however remember that we are 99878064Sume * not ready to carry IP packets, and return 99978064Sume * ENETDOWN, as opposed to ENOBUFS. 100078064Sume */ 100178064Sume h->protocol = htons(PPP_IPV6); 100278064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 100378064Sume rv = ENETDOWN; 100454263Sshin } 100554263Sshin break; 100654263Sshin#endif 100711819Sjulian#ifdef IPX 100812495Speter case AF_IPX: /* Novell IPX Protocol */ 100945152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 101012495Speter ETHERTYPE_IPX : PPP_IPX); 101111819Sjulian break; 101211819Sjulian#endif 10134910Swollman default: 10144910Swollman m_freem (m); 101525944Sjoerg ++ifp->if_oerrors; 1016138745Srik SPPP_UNLOCK(sp); 10174910Swollman splx (s); 10184910Swollman return (EAFNOSUPPORT); 10194910Swollman } 10204910Swollman 10214910Swollman /* 10224910Swollman * Queue message on interface, and start output if interface 102388577Sjoerg * not yet active. 10244910Swollman */ 1025139365Srikout: 1026130549Smlaier if (ifq != NULL) 1027130549Smlaier error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 1028130549Smlaier else 1029130549Smlaier IFQ_HANDOFF_ADJ(ifp, m, 3, error); 1030130549Smlaier if (error) { 103125944Sjoerg ++ifp->if_oerrors; 1032138745Srik SPPP_UNLOCK(sp); 1033111038Smaxim splx (s); 103425955Sjoerg return (rv? rv: ENOBUFS); 10354910Swollman } 1036138745Srik SPPP_UNLOCK(sp); 1037111038Smaxim splx (s); 103888577Sjoerg /* 103988577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 104088577Sjoerg * here since sppp_output() is only called on behalf of 104188577Sjoerg * network-layer traffic; control-layer traffic is handled 104288577Sjoerg * by sppp_cp_send(). 104388577Sjoerg */ 1044150349Sandre sp->pp_last_sent = time_uptime; 10454910Swollman return (0); 10464910Swollman} 10474910Swollman 104825706Sjoergvoid 104925706Sjoergsppp_attach(struct ifnet *ifp) 10504910Swollman{ 1051147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10524910Swollman 1053138745Srik /* Initialize mtx lock */ 1054138745Srik mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); 1055138745Srik 10564910Swollman /* Initialize keepalive handler. */ 1057138745Srik callout_init(&sp->keepalive_callout, 1058138745Srik (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 1059138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 1060138745Srik (void *)sp); 10614910Swollman 1062147256Sbrooks ifp->if_mtu = PP_MTU; 1063147256Sbrooks ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1064147256Sbrooks ifp->if_output = sppp_output; 106542104Sphk#if 0 106642064Sphk sp->pp_flags = PP_KEEPALIVE; 106742104Sphk#endif 1068147256Sbrooks ifp->if_snd.ifq_maxlen = 32; 106970199Sjhay sp->pp_fastq.ifq_maxlen = 32; 107070199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10714910Swollman sp->pp_loopcnt = 0; 10724910Swollman sp->pp_alivecnt = 0; 107378064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 107478064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 107525944Sjoerg sp->pp_phase = PHASE_DEAD; 1076138745Srik sp->pp_up = sppp_pp_up; 1077138745Srik sp->pp_down = sppp_pp_down; 107888716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 107993818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 108088716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 108193818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 1082150349Sandre sp->pp_last_recv = sp->pp_last_sent = time_uptime; 108388723Sjoerg sp->confflags = 0; 108488723Sjoerg#ifdef INET 108588723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 108688723Sjoerg#endif 108788723Sjoerg#ifdef INET6 108888723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 108988723Sjoerg#endif 1090138745Srik callout_init(&sp->ifstart_callout, 1091138745Srik (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 1092138745Srik sp->if_start = ifp->if_start; 1093138745Srik ifp->if_start = sppp_ifstart; 1094118072Sgj sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 109588599Sjoerg sl_compress_init(sp->pp_comp, -1); 109625944Sjoerg sppp_lcp_init(sp); 109725944Sjoerg sppp_ipcp_init(sp); 109878064Sume sppp_ipv6cp_init(sp); 109930300Sjoerg sppp_pap_init(sp); 110030300Sjoerg sppp_chap_init(sp); 11014910Swollman} 11024910Swollman 110330300Sjoergvoid 110425706Sjoergsppp_detach(struct ifnet *ifp) 11054910Swollman{ 1106147256Sbrooks struct sppp *sp = IFP2SP(ifp); 110725944Sjoerg int i; 11084910Swollman 1109138745Srik KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized")); 11104910Swollman 11114910Swollman /* Stop keepalive handler. */ 1112138745Srik if (!callout_drain(&sp->keepalive_callout)) 1113138745Srik callout_stop(&sp->keepalive_callout); 111425944Sjoerg 1115138745Srik for (i = 0; i < IDX_COUNT; i++) { 1116138745Srik if (!callout_drain(&sp->ch[i])) 1117138745Srik callout_stop(&sp->ch[i]); 1118138745Srik } 1119138745Srik if (!callout_drain(&sp->pap_my_to_ch)) 1120138745Srik callout_stop(&sp->pap_my_to_ch); 112169152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 112269152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 1123138745Srik mtx_destroy(&sp->mtx); 11244910Swollman} 11254910Swollman 11264910Swollman/* 11274910Swollman * Flush the interface output queue. 11284910Swollman */ 1129138745Srikstatic void 1130138745Sriksppp_flush_unlocked(struct ifnet *ifp) 11314910Swollman{ 1132147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11334910Swollman 1134147256Sbrooks sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd); 113525944Sjoerg sppp_qflush (&sp->pp_fastq); 113626018Sjoerg sppp_qflush (&sp->pp_cpq); 11374910Swollman} 11384910Swollman 1139138745Srikvoid 1140138745Sriksppp_flush(struct ifnet *ifp) 1141138745Srik{ 1142147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1143138745Srik 1144138745Srik SPPP_LOCK(sp); 1145138745Srik sppp_flush_unlocked (ifp); 1146138745Srik SPPP_UNLOCK(sp); 1147138745Srik} 1148138745Srik 11494910Swollman/* 115011189Sjkh * Check if the output queue is empty. 115111189Sjkh */ 115212820Sphkint 115325706Sjoergsppp_isempty(struct ifnet *ifp) 115411189Sjkh{ 1155147256Sbrooks struct sppp *sp = IFP2SP(ifp); 115625944Sjoerg int empty, s; 115711189Sjkh 115825944Sjoerg s = splimp(); 1159138745Srik SPPP_LOCK(sp); 116026018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1161147256Sbrooks !SP2IFP(sp)->if_snd.ifq_head; 1162138745Srik SPPP_UNLOCK(sp); 116325944Sjoerg splx(s); 116411189Sjkh return (empty); 116511189Sjkh} 116611189Sjkh 116711189Sjkh/* 11684910Swollman * Get next packet to send. 11694910Swollman */ 117025706Sjoergstruct mbuf * 117125706Sjoergsppp_dequeue(struct ifnet *ifp) 11724910Swollman{ 1173147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11744910Swollman struct mbuf *m; 117525944Sjoerg int s; 11764910Swollman 117725944Sjoerg s = splimp(); 1178138745Srik SPPP_LOCK(sp); 117926018Sjoerg /* 118030300Sjoerg * Process only the control protocol queue until we have at 118130300Sjoerg * least one NCP open. 118226018Sjoerg * 118326018Sjoerg * Do always serve all three queues in Cisco mode. 118426018Sjoerg */ 118526018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 118626018Sjoerg if (m == NULL && 1187139365Srik (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO || 1188139365Srik sp->pp_mode == PP_FR)) { 118926018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 119026018Sjoerg if (m == NULL) 1191147256Sbrooks IF_DEQUEUE (&SP2IFP(sp)->if_snd, m); 119226018Sjoerg } 1193138745Srik SPPP_UNLOCK(sp); 119426018Sjoerg splx(s); 119526018Sjoerg return m; 11964910Swollman} 11974910Swollman 11984910Swollman/* 119930300Sjoerg * Pick the next packet, do not remove it from the queue. 120030300Sjoerg */ 120130300Sjoergstruct mbuf * 120230300Sjoergsppp_pick(struct ifnet *ifp) 120330300Sjoerg{ 1204147256Sbrooks struct sppp *sp = IFP2SP(ifp); 120530300Sjoerg struct mbuf *m; 120630300Sjoerg int s; 120730300Sjoerg 1208138745Srik s = splimp (); 1209138745Srik SPPP_LOCK(sp); 121030300Sjoerg 121130300Sjoerg m = sp->pp_cpq.ifq_head; 121230300Sjoerg if (m == NULL && 1213138745Srik (sp->pp_phase == PHASE_NETWORK || 1214139365Srik sp->pp_mode == IFF_CISCO || 1215139365Srik sp->pp_mode == PP_FR)) 121630300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 1217147256Sbrooks m = SP2IFP(sp)->if_snd.ifq_head; 1218138745Srik SPPP_UNLOCK(sp); 121930300Sjoerg splx (s); 122030300Sjoerg return (m); 122130300Sjoerg} 122230300Sjoerg 122330300Sjoerg/* 122425944Sjoerg * Process an ioctl request. Called on low priority level. 12254910Swollman */ 122625944Sjoergint 122742104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 12284910Swollman{ 122925944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 1230147256Sbrooks struct sppp *sp = IFP2SP(ifp); 123130300Sjoerg int s, rv, going_up, going_down, newmode; 12324910Swollman 123325944Sjoerg s = splimp(); 1234138745Srik SPPP_LOCK(sp); 123530300Sjoerg rv = 0; 123625944Sjoerg switch (cmd) { 123725944Sjoerg case SIOCAIFADDR: 123825944Sjoerg case SIOCSIFDSTADDR: 123925944Sjoerg break; 12404910Swollman 124125944Sjoerg case SIOCSIFADDR: 124288503Sjoerg /* set the interface "up" when assigning an IP address */ 124388503Sjoerg ifp->if_flags |= IFF_UP; 1244102412Scharnier /* FALLTHROUGH */ 124511189Sjkh 124625944Sjoerg case SIOCSIFFLAGS: 124725944Sjoerg going_up = ifp->if_flags & IFF_UP && 1248148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 124925944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1250148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 125145152Sphk 125245152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 125345152Sphk if (!newmode) 125445152Sphk newmode = ifp->if_flags & IFF_AUTO; 125545152Sphk if (!newmode) 125645152Sphk newmode = ifp->if_flags & IFF_CISCO; 125745152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 125845152Sphk ifp->if_flags |= newmode; 125945152Sphk 1260139365Srik if (!newmode) 1261139365Srik newmode = sp->pp_flags & PP_FR; 1262139365Srik 126345152Sphk if (newmode != sp->pp_mode) { 126445152Sphk going_down = 1; 126545152Sphk if (!going_up) 1266148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12674910Swollman } 12684910Swollman 126945152Sphk if (going_down) { 1270139365Srik if (sp->pp_mode != IFF_CISCO && 1271139365Srik sp->pp_mode != PP_FR) 127245152Sphk lcp.Close(sp); 127345152Sphk else if (sp->pp_tlf) 127445152Sphk (sp->pp_tlf)(sp); 1275138745Srik sppp_flush_unlocked(ifp); 1276148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 127745152Sphk sp->pp_mode = newmode; 127826018Sjoerg } 12794910Swollman 128045152Sphk if (going_up) { 1281139365Srik if (sp->pp_mode != IFF_CISCO && 1282139365Srik sp->pp_mode != PP_FR) 128345152Sphk lcp.Close(sp); 128445152Sphk sp->pp_mode = newmode; 128545152Sphk if (sp->pp_mode == 0) { 1286148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 128745152Sphk lcp.Open(sp); 128845152Sphk } 1289139365Srik if ((sp->pp_mode == IFF_CISCO) || 1290139365Srik (sp->pp_mode == PP_FR)) { 129145152Sphk if (sp->pp_tls) 129245152Sphk (sp->pp_tls)(sp); 1293148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 129445152Sphk } 129545152Sphk } 129645152Sphk 12974910Swollman break; 129811189Sjkh 129925944Sjoerg#ifdef SIOCSIFMTU 130025944Sjoerg#ifndef ifr_mtu 130125944Sjoerg#define ifr_mtu ifr_metric 130225944Sjoerg#endif 130325944Sjoerg case SIOCSIFMTU: 130425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 130525944Sjoerg return (EINVAL); 130625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 13074910Swollman break; 130825944Sjoerg#endif 130925944Sjoerg#ifdef SLIOCSETMTU 131025944Sjoerg case SLIOCSETMTU: 131125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 131225944Sjoerg return (EINVAL); 131325944Sjoerg ifp->if_mtu = *(short*)data; 13144910Swollman break; 131525944Sjoerg#endif 131625944Sjoerg#ifdef SIOCGIFMTU 131725944Sjoerg case SIOCGIFMTU: 131825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 131911189Sjkh break; 132025944Sjoerg#endif 132125944Sjoerg#ifdef SLIOCGETMTU 132225944Sjoerg case SLIOCGETMTU: 132325944Sjoerg *(short*)data = ifp->if_mtu; 13244910Swollman break; 132525944Sjoerg#endif 132625944Sjoerg case SIOCADDMULTI: 132725944Sjoerg case SIOCDELMULTI: 13284910Swollman break; 132911189Sjkh 133030300Sjoerg case SIOCGIFGENERIC: 133130300Sjoerg case SIOCSIFGENERIC: 133230300Sjoerg rv = sppp_params(sp, cmd, data); 133330300Sjoerg break; 133430300Sjoerg 133525944Sjoerg default: 133630300Sjoerg rv = ENOTTY; 13374910Swollman } 1338138745Srik SPPP_UNLOCK(sp); 133925944Sjoerg splx(s); 134030300Sjoerg return rv; 13414910Swollman} 13424910Swollman 134370199Sjhay/* 134425944Sjoerg * Cisco framing implementation. 134525944Sjoerg */ 134625944Sjoerg 13474910Swollman/* 13484910Swollman * Handle incoming Cisco keepalive protocol packets. 13494910Swollman */ 135030300Sjoergstatic void 135125706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 13524910Swollman{ 135325944Sjoerg STDDCL; 13544910Swollman struct cisco_packet *h; 135530300Sjoerg u_long me, mymask; 13564910Swollman 135727929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 135825706Sjoerg if (debug) 135925706Sjoerg log(LOG_DEBUG, 136040008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 136140008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13624910Swollman return; 13634910Swollman } 13644910Swollman h = mtod (m, struct cisco_packet*); 136525706Sjoerg if (debug) 136625706Sjoerg log(LOG_DEBUG, 136740008Sjoerg SPP_FMT "cisco input: %d bytes " 136825706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 136940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 137040008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 137140008Sjoerg (u_int)h->time0, (u_int)h->time1); 13724910Swollman switch (ntohl (h->type)) { 13734910Swollman default: 137425706Sjoerg if (debug) 137569211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 137640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 13774910Swollman break; 13784910Swollman case CISCO_ADDR_REPLY: 13794910Swollman /* Reply on address request, ignore */ 13804910Swollman break; 13814910Swollman case CISCO_KEEPALIVE_REQ: 13824910Swollman sp->pp_alivecnt = 0; 138378064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 138478064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13854910Swollman /* Local and remote sequence numbers are equal. 13864910Swollman * Probably, the line is in loopback mode. */ 138711189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 138840008Sjoerg printf (SPP_FMT "loopback\n", 138940008Sjoerg SPP_ARGS(ifp)); 139011189Sjkh sp->pp_loopcnt = 0; 139111189Sjkh if (ifp->if_flags & IFF_UP) { 139211189Sjkh if_down (ifp); 139326018Sjoerg sppp_qflush (&sp->pp_cpq); 139411189Sjkh } 139511189Sjkh } 13964910Swollman ++sp->pp_loopcnt; 13974910Swollman 13984910Swollman /* Generate new local sequence number */ 139978064Sume sp->pp_seq[IDX_LCP] = random(); 140011189Sjkh break; 140111189Sjkh } 140230300Sjoerg sp->pp_loopcnt = 0; 140311189Sjkh if (! (ifp->if_flags & IFF_UP) && 1404148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 140530300Sjoerg if_up(ifp); 140640008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 140711189Sjkh } 14084910Swollman break; 14094910Swollman case CISCO_ADDR_REQ: 141030300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 141130300Sjoerg if (me != 0L) 141230300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 14134910Swollman break; 14144910Swollman } 14154910Swollman} 14164910Swollman 14174910Swollman/* 141825944Sjoerg * Send Cisco keepalive packet. 14194910Swollman */ 142012820Sphkstatic void 142125944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 142225944Sjoerg{ 142325944Sjoerg STDDCL; 142425944Sjoerg struct ppp_header *h; 142525944Sjoerg struct cisco_packet *ch; 142625944Sjoerg struct mbuf *m; 142735029Sphk struct timeval tv; 142825944Sjoerg 142936119Sphk getmicrouptime(&tv); 143070199Sjhay 1431111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 143225944Sjoerg if (! m) 143325944Sjoerg return; 143425944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 143525944Sjoerg m->m_pkthdr.rcvif = 0; 143625944Sjoerg 143725944Sjoerg h = mtod (m, struct ppp_header*); 143825944Sjoerg h->address = CISCO_MULTICAST; 143925944Sjoerg h->control = 0; 144025944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 144125944Sjoerg 144225944Sjoerg ch = (struct cisco_packet*) (h + 1); 144325944Sjoerg ch->type = htonl (type); 144425944Sjoerg ch->par1 = htonl (par1); 144525944Sjoerg ch->par2 = htonl (par2); 144625944Sjoerg ch->rel = -1; 144740008Sjoerg 144835029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 144935029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 145025944Sjoerg 145125944Sjoerg if (debug) 145225944Sjoerg log(LOG_DEBUG, 145340008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 145440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 145540008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 145625944Sjoerg 145769152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 145869152Sjlemon ifp->if_oerrors++; 145925944Sjoerg} 146025944Sjoerg 146170199Sjhay/* 146225944Sjoerg * PPP protocol implementation. 146325944Sjoerg */ 146425944Sjoerg 146525944Sjoerg/* 146625944Sjoerg * Send PPP control protocol packet. 146725944Sjoerg */ 146825944Sjoergstatic void 146925706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 147025706Sjoerg u_char ident, u_short len, void *data) 14714910Swollman{ 147225944Sjoerg STDDCL; 14734910Swollman struct ppp_header *h; 14744910Swollman struct lcp_header *lh; 14754910Swollman struct mbuf *m; 14764910Swollman 14774910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14784910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1479111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 14804910Swollman if (! m) 14814910Swollman return; 14824910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14834910Swollman m->m_pkthdr.rcvif = 0; 14844910Swollman 14854910Swollman h = mtod (m, struct ppp_header*); 14864910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14874910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14884910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14894910Swollman 14904910Swollman lh = (struct lcp_header*) (h + 1); 14914910Swollman lh->type = type; 14924910Swollman lh->ident = ident; 14934910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14944910Swollman if (len) 14954910Swollman bcopy (data, lh+1, len); 14964910Swollman 149725706Sjoerg if (debug) { 149840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 149940008Sjoerg SPP_ARGS(ifp), 150025944Sjoerg sppp_proto_name(proto), 150125944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 150225944Sjoerg ntohs (lh->len)); 150344145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 150469211Sphk log(-1, ">\n"); 15054910Swollman } 150669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 150769152Sjlemon ifp->if_oerrors++; 15084910Swollman} 15094910Swollman 15104910Swollman/* 151125944Sjoerg * Handle incoming PPP control protocol packets. 15124910Swollman */ 151312820Sphkstatic void 151425944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 15154910Swollman{ 151625944Sjoerg STDDCL; 151725944Sjoerg struct lcp_header *h; 151825944Sjoerg int len = m->m_pkthdr.len; 151925944Sjoerg int rv; 152025944Sjoerg u_char *p; 15214910Swollman 152225944Sjoerg if (len < 4) { 152325944Sjoerg if (debug) 152425944Sjoerg log(LOG_DEBUG, 152540008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 152640008Sjoerg SPP_ARGS(ifp), cp->name, len); 15274910Swollman return; 152825944Sjoerg } 152925944Sjoerg h = mtod (m, struct lcp_header*); 153025944Sjoerg if (debug) { 153125944Sjoerg log(LOG_DEBUG, 153240008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 153340008Sjoerg SPP_ARGS(ifp), cp->name, 153425944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 153525944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 153644145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 153769211Sphk log(-1, ">\n"); 153825944Sjoerg } 153925944Sjoerg if (len > ntohs (h->len)) 154025944Sjoerg len = ntohs (h->len); 154130300Sjoerg p = (u_char *)(h + 1); 154225944Sjoerg switch (h->type) { 154325944Sjoerg case CONF_REQ: 154425944Sjoerg if (len < 4) { 154525944Sjoerg if (debug) 154669211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 154740008Sjoerg SPP_ARGS(ifp), cp->name, 154825944Sjoerg len); 154925944Sjoerg ++ifp->if_ierrors; 155025944Sjoerg break; 155125944Sjoerg } 155230300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 155330300Sjoerg switch (sp->state[cp->protoidx]) { 155430300Sjoerg case STATE_CLOSING: 155530300Sjoerg case STATE_STOPPING: 155630300Sjoerg return; 155730300Sjoerg case STATE_CLOSED: 155830300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 155930300Sjoerg 0, 0); 156030300Sjoerg return; 156130300Sjoerg } 156225944Sjoerg rv = (cp->RCR)(sp, h, len); 156325944Sjoerg switch (sp->state[cp->protoidx]) { 156425944Sjoerg case STATE_OPENED: 156525944Sjoerg (cp->tld)(sp); 156625944Sjoerg (cp->scr)(sp); 1567102412Scharnier /* FALLTHROUGH */ 156825944Sjoerg case STATE_ACK_SENT: 156925944Sjoerg case STATE_REQ_SENT: 157070199Sjhay /* 157170199Sjhay * sppp_cp_change_state() have the side effect of 157270199Sjhay * restarting the timeouts. We want to avoid that 157370199Sjhay * if the state don't change, otherwise we won't 157470199Sjhay * ever timeout and resend a configuration request 157570199Sjhay * that got lost. 157670199Sjhay */ 157770199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 157870199Sjhay STATE_REQ_SENT)) 157970199Sjhay break; 158025944Sjoerg sppp_cp_change_state(cp, sp, rv? 158125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 158225944Sjoerg break; 158325944Sjoerg case STATE_STOPPED: 158425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 158525944Sjoerg (cp->scr)(sp); 158625944Sjoerg sppp_cp_change_state(cp, sp, rv? 158725944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 158825944Sjoerg break; 158925944Sjoerg case STATE_ACK_RCVD: 159025944Sjoerg if (rv) { 159125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 159225944Sjoerg if (debug) 159340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 159440008Sjoerg SPP_ARGS(ifp), 159526077Sjoerg cp->name); 159625944Sjoerg (cp->tlu)(sp); 159725944Sjoerg } else 159825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 159925944Sjoerg break; 160025944Sjoerg default: 160140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 160240008Sjoerg SPP_ARGS(ifp), cp->name, 160325944Sjoerg sppp_cp_type_name(h->type), 160425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160525944Sjoerg ++ifp->if_ierrors; 160625944Sjoerg } 160725944Sjoerg break; 160825944Sjoerg case CONF_ACK: 160925944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 161025944Sjoerg if (debug) 161169211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 161240008Sjoerg SPP_ARGS(ifp), cp->name, 161325944Sjoerg h->ident, sp->confid[cp->protoidx]); 161425944Sjoerg ++ifp->if_ierrors; 161525944Sjoerg break; 161625944Sjoerg } 161725944Sjoerg switch (sp->state[cp->protoidx]) { 161825944Sjoerg case STATE_CLOSED: 161925944Sjoerg case STATE_STOPPED: 162025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 162125944Sjoerg break; 162225944Sjoerg case STATE_CLOSING: 162325944Sjoerg case STATE_STOPPING: 162425944Sjoerg break; 162525944Sjoerg case STATE_REQ_SENT: 162625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 162725944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 162825944Sjoerg break; 162925944Sjoerg case STATE_OPENED: 163025944Sjoerg (cp->tld)(sp); 1631102412Scharnier /* FALLTHROUGH */ 163225944Sjoerg case STATE_ACK_RCVD: 163325944Sjoerg (cp->scr)(sp); 163425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 163525944Sjoerg break; 163625944Sjoerg case STATE_ACK_SENT: 163725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 163825944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 163925944Sjoerg if (debug) 164040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 164140008Sjoerg SPP_ARGS(ifp), cp->name); 164225944Sjoerg (cp->tlu)(sp); 164325944Sjoerg break; 164425944Sjoerg default: 164540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 164640008Sjoerg SPP_ARGS(ifp), cp->name, 164725944Sjoerg sppp_cp_type_name(h->type), 164825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164925944Sjoerg ++ifp->if_ierrors; 165025944Sjoerg } 165125944Sjoerg break; 165225944Sjoerg case CONF_NAK: 165325944Sjoerg case CONF_REJ: 165425944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 165525944Sjoerg if (debug) 165669211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 165740008Sjoerg SPP_ARGS(ifp), cp->name, 165825944Sjoerg h->ident, sp->confid[cp->protoidx]); 165925944Sjoerg ++ifp->if_ierrors; 166025944Sjoerg break; 166125944Sjoerg } 166225944Sjoerg if (h->type == CONF_NAK) 166325944Sjoerg (cp->RCN_nak)(sp, h, len); 166425944Sjoerg else /* CONF_REJ */ 166525944Sjoerg (cp->RCN_rej)(sp, h, len); 16664910Swollman 166725944Sjoerg switch (sp->state[cp->protoidx]) { 166825944Sjoerg case STATE_CLOSED: 166925944Sjoerg case STATE_STOPPED: 167025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 167125944Sjoerg break; 167225944Sjoerg case STATE_REQ_SENT: 167325944Sjoerg case STATE_ACK_SENT: 167425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 167570199Sjhay /* 167670199Sjhay * Slow things down a bit if we think we might be 167770199Sjhay * in loopback. Depend on the timeout to send the 167870199Sjhay * next configuration request. 167970199Sjhay */ 168070199Sjhay if (sp->pp_loopcnt) 168170199Sjhay break; 168225944Sjoerg (cp->scr)(sp); 168325944Sjoerg break; 168425944Sjoerg case STATE_OPENED: 168525944Sjoerg (cp->tld)(sp); 1686102412Scharnier /* FALLTHROUGH */ 168725944Sjoerg case STATE_ACK_RCVD: 168852633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 168925944Sjoerg (cp->scr)(sp); 169025944Sjoerg break; 169125944Sjoerg case STATE_CLOSING: 169225944Sjoerg case STATE_STOPPING: 169325944Sjoerg break; 169425944Sjoerg default: 169540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169640008Sjoerg SPP_ARGS(ifp), cp->name, 169725944Sjoerg sppp_cp_type_name(h->type), 169825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169925944Sjoerg ++ifp->if_ierrors; 170025944Sjoerg } 170125944Sjoerg break; 17024910Swollman 170325944Sjoerg case TERM_REQ: 170425944Sjoerg switch (sp->state[cp->protoidx]) { 170525944Sjoerg case STATE_ACK_RCVD: 170625944Sjoerg case STATE_ACK_SENT: 170725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1708102412Scharnier /* FALLTHROUGH */ 170925944Sjoerg case STATE_CLOSED: 171025944Sjoerg case STATE_STOPPED: 171125944Sjoerg case STATE_CLOSING: 171225944Sjoerg case STATE_STOPPING: 171325944Sjoerg case STATE_REQ_SENT: 171425944Sjoerg sta: 171525944Sjoerg /* Send Terminate-Ack packet. */ 171625944Sjoerg if (debug) 171740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 171840008Sjoerg SPP_ARGS(ifp), cp->name); 171925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 172025944Sjoerg break; 172125944Sjoerg case STATE_OPENED: 172225944Sjoerg (cp->tld)(sp); 172325944Sjoerg sp->rst_counter[cp->protoidx] = 0; 172425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 172525944Sjoerg goto sta; 172625944Sjoerg break; 172725944Sjoerg default: 172840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 172940008Sjoerg SPP_ARGS(ifp), cp->name, 173025944Sjoerg sppp_cp_type_name(h->type), 173125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 173225944Sjoerg ++ifp->if_ierrors; 173325944Sjoerg } 173425944Sjoerg break; 173525944Sjoerg case TERM_ACK: 173625944Sjoerg switch (sp->state[cp->protoidx]) { 173725944Sjoerg case STATE_CLOSED: 173825944Sjoerg case STATE_STOPPED: 173925944Sjoerg case STATE_REQ_SENT: 174025944Sjoerg case STATE_ACK_SENT: 174125944Sjoerg break; 174225944Sjoerg case STATE_CLOSING: 174341881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 174425944Sjoerg (cp->tlf)(sp); 174525944Sjoerg break; 174625944Sjoerg case STATE_STOPPING: 174741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 174825944Sjoerg (cp->tlf)(sp); 174925944Sjoerg break; 175025944Sjoerg case STATE_ACK_RCVD: 175125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 175225944Sjoerg break; 175325944Sjoerg case STATE_OPENED: 175425944Sjoerg (cp->tld)(sp); 175525944Sjoerg (cp->scr)(sp); 175625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 175725944Sjoerg break; 175825944Sjoerg default: 175940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 176040008Sjoerg SPP_ARGS(ifp), cp->name, 176125944Sjoerg sppp_cp_type_name(h->type), 176225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 176325944Sjoerg ++ifp->if_ierrors; 176425944Sjoerg } 176525944Sjoerg break; 176625944Sjoerg case CODE_REJ: 176725944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 176830300Sjoerg log(LOG_INFO, 176940008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 177030300Sjoerg "danger will robinson\n", 177140008Sjoerg SPP_ARGS(ifp), cp->name, 177230300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 177325944Sjoerg switch (sp->state[cp->protoidx]) { 177425944Sjoerg case STATE_CLOSED: 177525944Sjoerg case STATE_STOPPED: 177625944Sjoerg case STATE_REQ_SENT: 177725944Sjoerg case STATE_ACK_SENT: 177825944Sjoerg case STATE_CLOSING: 177925944Sjoerg case STATE_STOPPING: 178025944Sjoerg case STATE_OPENED: 178125944Sjoerg break; 178225944Sjoerg case STATE_ACK_RCVD: 178325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 178425944Sjoerg break; 178525944Sjoerg default: 178640008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 178740008Sjoerg SPP_ARGS(ifp), cp->name, 178825944Sjoerg sppp_cp_type_name(h->type), 178925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 179025944Sjoerg ++ifp->if_ierrors; 179125944Sjoerg } 179225944Sjoerg break; 179380715Sume case PROTO_REJ: 179480715Sume { 179580715Sume int catastrophic; 179680715Sume const struct cp *upper; 179780715Sume int i; 179880715Sume u_int16_t proto; 179980715Sume 180080715Sume catastrophic = 0; 180180715Sume upper = NULL; 180280715Sume proto = ntohs(*((u_int16_t *)p)); 180380715Sume for (i = 0; i < IDX_COUNT; i++) { 180480715Sume if (cps[i]->proto == proto) { 180580715Sume upper = cps[i]; 180680715Sume break; 180780715Sume } 180880715Sume } 180980715Sume if (upper == NULL) 181080715Sume catastrophic++; 181180715Sume 181288508Sjoerg if (catastrophic || debug) 181388508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 181488508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 181588508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 181688508Sjoerg sppp_cp_type_name(h->type), proto, 181788508Sjoerg upper ? upper->name : "unknown", 181888508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 181980715Sume 182080715Sume /* 182180715Sume * if we got RXJ+ against conf-req, the peer does not implement 182280715Sume * this particular protocol type. terminate the protocol. 182380715Sume */ 182480715Sume if (upper && !catastrophic) { 182580715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 182680715Sume upper->Close(sp); 182780715Sume break; 182880715Sume } 182980715Sume } 183080715Sume 183180715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 183280715Sume switch (sp->state[cp->protoidx]) { 183380715Sume case STATE_CLOSED: 183480715Sume case STATE_STOPPED: 183580715Sume case STATE_REQ_SENT: 183680715Sume case STATE_ACK_SENT: 183780715Sume case STATE_CLOSING: 183880715Sume case STATE_STOPPING: 183980715Sume case STATE_OPENED: 184080715Sume break; 184180715Sume case STATE_ACK_RCVD: 184280715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 184380715Sume break; 184480715Sume default: 184580715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 184680715Sume SPP_ARGS(ifp), cp->name, 184780715Sume sppp_cp_type_name(h->type), 184880715Sume sppp_state_name(sp->state[cp->protoidx])); 184980715Sume ++ifp->if_ierrors; 185080715Sume } 185180715Sume break; 185280715Sume } 185325944Sjoerg case DISC_REQ: 185425944Sjoerg if (cp->proto != PPP_LCP) 185525944Sjoerg goto illegal; 185625944Sjoerg /* Discard the packet. */ 185725944Sjoerg break; 185825944Sjoerg case ECHO_REQ: 185925944Sjoerg if (cp->proto != PPP_LCP) 186025944Sjoerg goto illegal; 186125944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 186225944Sjoerg if (debug) 186369211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 186440008Sjoerg SPP_ARGS(ifp)); 186525944Sjoerg ++ifp->if_ierrors; 186625944Sjoerg break; 186725944Sjoerg } 186825944Sjoerg if (len < 8) { 186925944Sjoerg if (debug) 187069211Sphk log(-1, SPP_FMT "invalid lcp echo request " 187125944Sjoerg "packet length: %d bytes\n", 187240008Sjoerg SPP_ARGS(ifp), len); 187325944Sjoerg break; 187425944Sjoerg } 187544145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 187644145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 187725944Sjoerg /* Line loopback mode detected. */ 187840008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 187970199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 188025944Sjoerg if_down (ifp); 188126018Sjoerg sppp_qflush (&sp->pp_cpq); 18824910Swollman 188325944Sjoerg /* Shut down the PPP link. */ 188425944Sjoerg /* XXX */ 188525944Sjoerg lcp.Down(sp); 188625944Sjoerg lcp.Up(sp); 188725944Sjoerg break; 188825944Sjoerg } 188925944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 189025944Sjoerg if (debug) 189169211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 189240008Sjoerg SPP_ARGS(ifp)); 189325944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 189425944Sjoerg break; 189525944Sjoerg case ECHO_REPLY: 189625944Sjoerg if (cp->proto != PPP_LCP) 189725944Sjoerg goto illegal; 189825944Sjoerg if (h->ident != sp->lcp.echoid) { 189925944Sjoerg ++ifp->if_ierrors; 190025944Sjoerg break; 190125944Sjoerg } 190225944Sjoerg if (len < 8) { 190325944Sjoerg if (debug) 190469211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 190525944Sjoerg "packet length: %d bytes\n", 190640008Sjoerg SPP_ARGS(ifp), len); 190725944Sjoerg break; 190825944Sjoerg } 190925944Sjoerg if (debug) 191069211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 191140008Sjoerg SPP_ARGS(ifp)); 191244145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 191344145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 191425944Sjoerg sp->pp_alivecnt = 0; 191525944Sjoerg break; 191625944Sjoerg default: 191725944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 191825944Sjoerg illegal: 191925944Sjoerg if (debug) 192069211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 192140008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 192278064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 192378064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 192425944Sjoerg ++ifp->if_ierrors; 192525944Sjoerg } 19264910Swollman} 19274910Swollman 192825944Sjoerg 19294910Swollman/* 193025944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 193125944Sjoerg * Basically, the state transition handling in the automaton. 19324910Swollman */ 193325944Sjoergstatic void 193425944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 19354910Swollman{ 193625944Sjoerg STDDCL; 19374910Swollman 193825944Sjoerg if (debug) 193940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 194040008Sjoerg SPP_ARGS(ifp), cp->name, 194125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 194225944Sjoerg 194325944Sjoerg switch (sp->state[cp->protoidx]) { 194425944Sjoerg case STATE_INITIAL: 194525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 194625944Sjoerg break; 194725944Sjoerg case STATE_STARTING: 194825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 194925944Sjoerg (cp->scr)(sp); 195025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 195125944Sjoerg break; 19524910Swollman default: 195340008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 195440008Sjoerg SPP_ARGS(ifp), cp->name, 195525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 195625944Sjoerg } 195725944Sjoerg} 19584910Swollman 195925944Sjoergstatic void 196025944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 196125944Sjoerg{ 196225944Sjoerg STDDCL; 196325944Sjoerg 196425944Sjoerg if (debug) 196540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 196640008Sjoerg SPP_ARGS(ifp), cp->name, 196725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 196825944Sjoerg 196925944Sjoerg switch (sp->state[cp->protoidx]) { 197025944Sjoerg case STATE_CLOSED: 197125944Sjoerg case STATE_CLOSING: 197225944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19734910Swollman break; 197425944Sjoerg case STATE_STOPPED: 197541881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 197625944Sjoerg (cp->tls)(sp); 197741881Sphk break; 197825944Sjoerg case STATE_STOPPING: 197925944Sjoerg case STATE_REQ_SENT: 198025944Sjoerg case STATE_ACK_RCVD: 198125944Sjoerg case STATE_ACK_SENT: 198225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 198325944Sjoerg break; 198425944Sjoerg case STATE_OPENED: 198525944Sjoerg (cp->tld)(sp); 198625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 198725944Sjoerg break; 198825944Sjoerg default: 198940008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 199040008Sjoerg SPP_ARGS(ifp), cp->name, 199125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 199225944Sjoerg } 199325944Sjoerg} 19944910Swollman 199511189Sjkh 199625944Sjoergstatic void 199725944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 199825944Sjoerg{ 199925944Sjoerg STDDCL; 200025944Sjoerg 200125944Sjoerg if (debug) 200240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 200340008Sjoerg SPP_ARGS(ifp), cp->name, 200425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 200525944Sjoerg 200625944Sjoerg switch (sp->state[cp->protoidx]) { 200725944Sjoerg case STATE_INITIAL: 200841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 200925944Sjoerg (cp->tls)(sp); 20104910Swollman break; 201125944Sjoerg case STATE_STARTING: 201225944Sjoerg break; 201325944Sjoerg case STATE_CLOSED: 201425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 201525944Sjoerg (cp->scr)(sp); 201625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 201725944Sjoerg break; 201825944Sjoerg case STATE_STOPPED: 201974703Sjoerg /* 202074703Sjoerg * Try escaping stopped state. This seems to bite 202174703Sjoerg * people occasionally, in particular for IPCP, 202274703Sjoerg * presumably following previous IPCP negotiation 202374703Sjoerg * aborts. Somehow, we must have missed a Down event 202474703Sjoerg * which would have caused a transition into starting 202574703Sjoerg * state, so as a bandaid we force the Down event now. 202674703Sjoerg * This effectively implements (something like the) 202774703Sjoerg * `restart' option mentioned in the state transition 202874703Sjoerg * table of RFC 1661. 202974703Sjoerg */ 203074703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 203174703Sjoerg (cp->tls)(sp); 203274703Sjoerg break; 203325944Sjoerg case STATE_STOPPING: 203425944Sjoerg case STATE_REQ_SENT: 203525944Sjoerg case STATE_ACK_RCVD: 203625944Sjoerg case STATE_ACK_SENT: 203725944Sjoerg case STATE_OPENED: 203825944Sjoerg break; 203925944Sjoerg case STATE_CLOSING: 204025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 204125944Sjoerg break; 204225944Sjoerg } 204325944Sjoerg} 20444910Swollman 204525944Sjoerg 204625944Sjoergstatic void 204725944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 204825944Sjoerg{ 204925944Sjoerg STDDCL; 205025944Sjoerg 205125944Sjoerg if (debug) 205240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 205340008Sjoerg SPP_ARGS(ifp), cp->name, 205425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 205525944Sjoerg 205625944Sjoerg switch (sp->state[cp->protoidx]) { 205725944Sjoerg case STATE_INITIAL: 205825944Sjoerg case STATE_CLOSED: 205925944Sjoerg case STATE_CLOSING: 20604910Swollman break; 206125944Sjoerg case STATE_STARTING: 206241881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 206325944Sjoerg (cp->tlf)(sp); 20644910Swollman break; 206525944Sjoerg case STATE_STOPPED: 206625944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20674910Swollman break; 206825944Sjoerg case STATE_STOPPING: 206925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20704910Swollman break; 207125944Sjoerg case STATE_OPENED: 207225944Sjoerg (cp->tld)(sp); 2073102412Scharnier /* FALLTHROUGH */ 207425944Sjoerg case STATE_REQ_SENT: 207525944Sjoerg case STATE_ACK_RCVD: 207625944Sjoerg case STATE_ACK_SENT: 207725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 207878064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 207978064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 208025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20814910Swollman break; 20824910Swollman } 20834910Swollman} 20844910Swollman 208525944Sjoergstatic void 208625944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 208725944Sjoerg{ 208825944Sjoerg STDDCL; 208925944Sjoerg int s; 209025944Sjoerg 209125944Sjoerg s = splimp(); 2092138745Srik SPPP_LOCK(sp); 209325944Sjoerg if (debug) 209440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 209540008Sjoerg SPP_ARGS(ifp), cp->name, 209625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 209725944Sjoerg sp->rst_counter[cp->protoidx]); 209825944Sjoerg 209925944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 210025944Sjoerg /* TO- event */ 210125944Sjoerg switch (sp->state[cp->protoidx]) { 210225944Sjoerg case STATE_CLOSING: 210341881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 210425944Sjoerg (cp->tlf)(sp); 210525944Sjoerg break; 210625944Sjoerg case STATE_STOPPING: 210741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 210825944Sjoerg (cp->tlf)(sp); 210925944Sjoerg break; 211025944Sjoerg case STATE_REQ_SENT: 211125944Sjoerg case STATE_ACK_RCVD: 211225944Sjoerg case STATE_ACK_SENT: 211341881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 211425944Sjoerg (cp->tlf)(sp); 211525944Sjoerg break; 211625944Sjoerg } 211725944Sjoerg else 211825944Sjoerg /* TO+ event */ 211925944Sjoerg switch (sp->state[cp->protoidx]) { 212025944Sjoerg case STATE_CLOSING: 212125944Sjoerg case STATE_STOPPING: 212278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 212378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2124138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2125138745Srik cp->TO, (void *)sp); 212625944Sjoerg break; 212725944Sjoerg case STATE_REQ_SENT: 212825944Sjoerg case STATE_ACK_RCVD: 212925944Sjoerg (cp->scr)(sp); 213025944Sjoerg /* sppp_cp_change_state() will restart the timer */ 213125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 213225944Sjoerg break; 213325944Sjoerg case STATE_ACK_SENT: 213425944Sjoerg (cp->scr)(sp); 2135138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2136138745Srik cp->TO, (void *)sp); 213725944Sjoerg break; 213825944Sjoerg } 213925944Sjoerg 2140138745Srik SPPP_UNLOCK(sp); 214125944Sjoerg splx(s); 214225944Sjoerg} 214325944Sjoerg 214411189Sjkh/* 214525944Sjoerg * Change the state of a control protocol in the state automaton. 214625944Sjoerg * Takes care of starting/stopping the restart timer. 214711189Sjkh */ 2148105228Sphkstatic void 214925944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 215025944Sjoerg{ 215125944Sjoerg sp->state[cp->protoidx] = newstate; 215225944Sjoerg 2153138745Srik callout_stop (&sp->ch[cp->protoidx]); 2154138745Srik 215525944Sjoerg switch (newstate) { 215625944Sjoerg case STATE_INITIAL: 215725944Sjoerg case STATE_STARTING: 215825944Sjoerg case STATE_CLOSED: 215925944Sjoerg case STATE_STOPPED: 216025944Sjoerg case STATE_OPENED: 216125944Sjoerg break; 216225944Sjoerg case STATE_CLOSING: 216325944Sjoerg case STATE_STOPPING: 216425944Sjoerg case STATE_REQ_SENT: 216525944Sjoerg case STATE_ACK_RCVD: 216625944Sjoerg case STATE_ACK_SENT: 2167138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2168138745Srik cp->TO, (void *)sp); 216925944Sjoerg break; 217025944Sjoerg } 217125944Sjoerg} 217270199Sjhay 217370199Sjhay/* 217425944Sjoerg *--------------------------------------------------------------------------* 217525944Sjoerg * * 217625944Sjoerg * The LCP implementation. * 217725944Sjoerg * * 217825944Sjoerg *--------------------------------------------------------------------------* 217925944Sjoerg */ 218025944Sjoergstatic void 2181138745Sriksppp_pp_up(struct sppp *sp) 2182138745Srik{ 2183138745Srik SPPP_LOCK(sp); 2184138745Srik lcp.Up(sp); 2185138745Srik SPPP_UNLOCK(sp); 2186138745Srik} 2187138745Srik 2188138745Srikstatic void 2189138745Sriksppp_pp_down(struct sppp *sp) 2190138745Srik{ 2191138745Srik SPPP_LOCK(sp); 2192138745Srik lcp.Down(sp); 2193138745Srik SPPP_UNLOCK(sp); 2194138745Srik} 2195138745Srik 2196138745Srikstatic void 219725944Sjoergsppp_lcp_init(struct sppp *sp) 219825944Sjoerg{ 219925944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 220025944Sjoerg sp->lcp.magic = 0; 220125944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 220225944Sjoerg sp->fail_counter[IDX_LCP] = 0; 220378064Sume sp->pp_seq[IDX_LCP] = 0; 220478064Sume sp->pp_rseq[IDX_LCP] = 0; 220525944Sjoerg sp->lcp.protos = 0; 220625944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 220730300Sjoerg 220844145Sphk /* Note that these values are relevant for all control protocols */ 220944145Sphk sp->lcp.timeout = 3 * hz; 221025944Sjoerg sp->lcp.max_terminate = 2; 221125944Sjoerg sp->lcp.max_configure = 10; 221225944Sjoerg sp->lcp.max_failure = 10; 2213138745Srik callout_init(&sp->ch[IDX_LCP], 2214147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 221525944Sjoerg} 221625944Sjoerg 221725944Sjoergstatic void 221825944Sjoergsppp_lcp_up(struct sppp *sp) 221925944Sjoerg{ 222025944Sjoerg STDDCL; 222125944Sjoerg 222270199Sjhay sp->pp_alivecnt = 0; 222370199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 222470199Sjhay sp->lcp.magic = 0; 222570199Sjhay sp->lcp.protos = 0; 222670199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 222725944Sjoerg /* 222875321Sjoerg * If we are authenticator, negotiate LCP_AUTH 222975321Sjoerg */ 223075321Sjoerg if (sp->hisauth.proto != 0) 223175321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 223275321Sjoerg else 223375321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 223475321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 223575321Sjoerg /* 223630300Sjoerg * If this interface is passive or dial-on-demand, and we are 223730300Sjoerg * still in Initial state, it means we've got an incoming 223830300Sjoerg * call. Activate the interface. 223925944Sjoerg */ 224025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 224125944Sjoerg if (debug) 224225944Sjoerg log(LOG_DEBUG, 224340008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2244148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 224530300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 224630300Sjoerg if (debug) 224769211Sphk log(-1, "(incoming call)\n"); 224830300Sjoerg sp->pp_flags |= PP_CALLIN; 224930300Sjoerg lcp.Open(sp); 225030300Sjoerg } else if (debug) 225169211Sphk log(-1, "\n"); 225288710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 225388710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2254148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 225588710Sjoerg lcp.Open(sp); 225625944Sjoerg } 225725944Sjoerg 225825944Sjoerg sppp_up_event(&lcp, sp); 225925944Sjoerg} 226025944Sjoerg 226125944Sjoergstatic void 226225944Sjoergsppp_lcp_down(struct sppp *sp) 226325944Sjoerg{ 226425944Sjoerg STDDCL; 226525944Sjoerg 226625944Sjoerg sppp_down_event(&lcp, sp); 226725944Sjoerg 226825944Sjoerg /* 226925944Sjoerg * If this is neither a dial-on-demand nor a passive 227025944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 227125944Sjoerg * administrator can force a redial by another ``ifconfig 227225944Sjoerg * up''. XXX For leased line operation, should we immediately 227325944Sjoerg * try to reopen the connection here? 227425944Sjoerg */ 227525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 227625944Sjoerg log(LOG_INFO, 227742066Sphk SPP_FMT "Down event, taking interface down.\n", 227840008Sjoerg SPP_ARGS(ifp)); 227925944Sjoerg if_down(ifp); 228025944Sjoerg } else { 228125944Sjoerg if (debug) 228225944Sjoerg log(LOG_DEBUG, 228340008Sjoerg SPP_FMT "Down event (carrier loss)\n", 228440008Sjoerg SPP_ARGS(ifp)); 228570199Sjhay sp->pp_flags &= ~PP_CALLIN; 228670199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 228770199Sjhay lcp.Close(sp); 2288148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 228925944Sjoerg } 229025944Sjoerg} 229125944Sjoerg 229225944Sjoergstatic void 229325944Sjoergsppp_lcp_open(struct sppp *sp) 229425944Sjoerg{ 229525944Sjoerg sppp_open_event(&lcp, sp); 229625944Sjoerg} 229725944Sjoerg 229825944Sjoergstatic void 229925944Sjoergsppp_lcp_close(struct sppp *sp) 230025944Sjoerg{ 230125944Sjoerg sppp_close_event(&lcp, sp); 230225944Sjoerg} 230325944Sjoerg 230425944Sjoergstatic void 230525944Sjoergsppp_lcp_TO(void *cookie) 230625944Sjoerg{ 230725944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 230825944Sjoerg} 230925944Sjoerg 231025944Sjoerg/* 231125944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 231225944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 231325944Sjoerg * caused action scn. (The return value is used to make the state 231425944Sjoerg * transition decision in the state automaton.) 231525944Sjoerg */ 231612820Sphkstatic int 231725944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 23184910Swollman{ 231925944Sjoerg STDDCL; 232011189Sjkh u_char *buf, *r, *p; 232125944Sjoerg int origlen, rlen; 232225944Sjoerg u_long nmagic; 232330300Sjoerg u_short authproto; 23244910Swollman 232511189Sjkh len -= 4; 232625944Sjoerg origlen = len; 232711189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 232811189Sjkh if (! buf) 232911189Sjkh return (0); 23304910Swollman 233125706Sjoerg if (debug) 233240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 233340008Sjoerg SPP_ARGS(ifp)); 233425706Sjoerg 233525944Sjoerg /* pass 1: check for things that need to be rejected */ 233611189Sjkh p = (void*) (h+1); 2337161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2338161556Scperciva len-=p[1], p+=p[1]) { 233925944Sjoerg if (debug) 234069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 234111189Sjkh switch (*p) { 234211189Sjkh case LCP_OPT_MAGIC: 234325944Sjoerg /* Magic number. */ 234470199Sjhay if (len >= 6 && p[1] == 6) 234570199Sjhay continue; 234670199Sjhay if (debug) 234770199Sjhay log(-1, "[invalid] "); 234870199Sjhay break; 234925944Sjoerg case LCP_OPT_ASYNC_MAP: 235025944Sjoerg /* Async control character map. */ 235170199Sjhay if (len >= 6 && p[1] == 6) 235225944Sjoerg continue; 235325944Sjoerg if (debug) 235469211Sphk log(-1, "[invalid] "); 235525944Sjoerg break; 235625944Sjoerg case LCP_OPT_MRU: 235725944Sjoerg /* Maximum receive unit. */ 235825944Sjoerg if (len >= 4 && p[1] == 4) 235925944Sjoerg continue; 236025944Sjoerg if (debug) 236169211Sphk log(-1, "[invalid] "); 236225944Sjoerg break; 236330300Sjoerg case LCP_OPT_AUTH_PROTO: 236430300Sjoerg if (len < 4) { 236530300Sjoerg if (debug) 236669211Sphk log(-1, "[invalid] "); 236730300Sjoerg break; 236830300Sjoerg } 236930300Sjoerg authproto = (p[2] << 8) + p[3]; 237030300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 237130300Sjoerg if (debug) 237269211Sphk log(-1, "[invalid chap len] "); 237330300Sjoerg break; 237430300Sjoerg } 237530300Sjoerg if (sp->myauth.proto == 0) { 237630300Sjoerg /* we are not configured to do auth */ 237730300Sjoerg if (debug) 237869211Sphk log(-1, "[not configured] "); 237930300Sjoerg break; 238030300Sjoerg } 238130300Sjoerg /* 238230300Sjoerg * Remote want us to authenticate, remember this, 238330300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 238430300Sjoerg * up. 238530300Sjoerg */ 238630300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 238730300Sjoerg continue; 238825944Sjoerg default: 238925944Sjoerg /* Others not supported. */ 239025944Sjoerg if (debug) 239169211Sphk log(-1, "[rej] "); 239225944Sjoerg break; 239325944Sjoerg } 239425944Sjoerg /* Add the option to rejected list. */ 239525944Sjoerg bcopy (p, r, p[1]); 239625944Sjoerg r += p[1]; 239725944Sjoerg rlen += p[1]; 239825944Sjoerg } 239925944Sjoerg if (rlen) { 240025944Sjoerg if (debug) 240169211Sphk log(-1, " send conf-rej\n"); 240225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 240325944Sjoerg return 0; 240425944Sjoerg } else if (debug) 240569211Sphk log(-1, "\n"); 240625944Sjoerg 240725944Sjoerg /* 240825944Sjoerg * pass 2: check for option values that are unacceptable and 240925944Sjoerg * thus require to be nak'ed. 241025944Sjoerg */ 241125944Sjoerg if (debug) 241240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 241340008Sjoerg SPP_ARGS(ifp)); 241425944Sjoerg 241525944Sjoerg p = (void*) (h+1); 241625944Sjoerg len = origlen; 2417161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2418161556Scperciva len-=p[1], p+=p[1]) { 241925944Sjoerg if (debug) 242069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 242125944Sjoerg switch (*p) { 242225944Sjoerg case LCP_OPT_MAGIC: 242311189Sjkh /* Magic number -- extract. */ 242425944Sjoerg nmagic = (u_long)p[2] << 24 | 242525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 242625944Sjoerg if (nmagic != sp->lcp.magic) { 242770199Sjhay sp->pp_loopcnt = 0; 242825706Sjoerg if (debug) 242969211Sphk log(-1, "0x%lx ", nmagic); 243011189Sjkh continue; 243111189Sjkh } 243270199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 243369211Sphk log(-1, "[glitch] "); 243425944Sjoerg ++sp->pp_loopcnt; 243525944Sjoerg /* 243625944Sjoerg * We negate our magic here, and NAK it. If 243725944Sjoerg * we see it later in an NAK packet, we 243825944Sjoerg * suggest a new one. 243925944Sjoerg */ 244025944Sjoerg nmagic = ~sp->lcp.magic; 244125944Sjoerg /* Gonna NAK it. */ 244225944Sjoerg p[2] = nmagic >> 24; 244325944Sjoerg p[3] = nmagic >> 16; 244425944Sjoerg p[4] = nmagic >> 8; 244525944Sjoerg p[5] = nmagic; 244611189Sjkh break; 244725944Sjoerg 244811189Sjkh case LCP_OPT_ASYNC_MAP: 244988506Sjoerg /* 245088506Sjoerg * Async control character map -- just ignore it. 245188506Sjoerg * 245288506Sjoerg * Quote from RFC 1662, chapter 6: 245388506Sjoerg * To enable this functionality, synchronous PPP 245488506Sjoerg * implementations MUST always respond to the 245588506Sjoerg * Async-Control-Character-Map Configuration 245688506Sjoerg * Option with the LCP Configure-Ack. However, 245788506Sjoerg * acceptance of the Configuration Option does 245888506Sjoerg * not imply that the synchronous implementation 245988506Sjoerg * will do any ACCM mapping. Instead, all such 246088506Sjoerg * octet mapping will be performed by the 246188506Sjoerg * asynchronous-to-synchronous converter. 246288506Sjoerg */ 246388506Sjoerg continue; 246425944Sjoerg 246511189Sjkh case LCP_OPT_MRU: 246625944Sjoerg /* 246725944Sjoerg * Maximum receive unit. Always agreeable, 246825944Sjoerg * but ignored by now. 246925944Sjoerg */ 247025944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 247125706Sjoerg if (debug) 247269211Sphk log(-1, "%lu ", sp->lcp.their_mru); 247311189Sjkh continue; 247430300Sjoerg 247530300Sjoerg case LCP_OPT_AUTH_PROTO: 247630300Sjoerg authproto = (p[2] << 8) + p[3]; 247730300Sjoerg if (sp->myauth.proto != authproto) { 247830300Sjoerg /* not agreed, nak */ 247930300Sjoerg if (debug) 248069211Sphk log(-1, "[mine %s != his %s] ", 248130300Sjoerg sppp_proto_name(sp->hisauth.proto), 248230300Sjoerg sppp_proto_name(authproto)); 248330300Sjoerg p[2] = sp->myauth.proto >> 8; 248430300Sjoerg p[3] = sp->myauth.proto; 248530300Sjoerg break; 248630300Sjoerg } 248730300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 248830300Sjoerg if (debug) 248969211Sphk log(-1, "[chap not MD5] "); 249039981Sjoerg p[4] = CHAP_MD5; 249130300Sjoerg break; 249230300Sjoerg } 249330300Sjoerg continue; 249411189Sjkh } 249525944Sjoerg /* Add the option to nak'ed list. */ 249625706Sjoerg bcopy (p, r, p[1]); 249725706Sjoerg r += p[1]; 249811189Sjkh rlen += p[1]; 249912436Speter } 250025706Sjoerg if (rlen) { 250170199Sjhay /* 250270199Sjhay * Local and remote magics equal -- loopback? 250370199Sjhay */ 250470199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 250570199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 250670199Sjhay printf (SPP_FMT "loopback\n", 250770199Sjhay SPP_ARGS(ifp)); 250870199Sjhay if (ifp->if_flags & IFF_UP) { 250970199Sjhay if_down(ifp); 251070199Sjhay sppp_qflush(&sp->pp_cpq); 251170199Sjhay /* XXX ? */ 251270199Sjhay lcp.Down(sp); 251370199Sjhay lcp.Up(sp); 251470199Sjhay } 2515131093Srik } else if (!sp->pp_loopcnt && 2516131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 251728036Sjoerg if (debug) 251869211Sphk log(-1, " max_failure (%d) exceeded, " 251928036Sjoerg "send conf-rej\n", 252028036Sjoerg sp->lcp.max_failure); 252128036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 252228036Sjoerg } else { 252328036Sjoerg if (debug) 252469211Sphk log(-1, " send conf-nak\n"); 252528036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 252628036Sjoerg } 252725944Sjoerg } else { 252825944Sjoerg if (debug) 252969211Sphk log(-1, " send conf-ack\n"); 253028036Sjoerg sp->fail_counter[IDX_LCP] = 0; 253125944Sjoerg sp->pp_loopcnt = 0; 253225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 253325944Sjoerg h->ident, origlen, h+1); 253425944Sjoerg } 253525944Sjoerg 253611189Sjkh free (buf, M_TEMP); 253711189Sjkh return (rlen == 0); 25384910Swollman} 25394910Swollman 254025944Sjoerg/* 254125944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 254225944Sjoerg * negotiation. 254325944Sjoerg */ 254412820Sphkstatic void 254525944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 25464910Swollman{ 254725944Sjoerg STDDCL; 254825944Sjoerg u_char *buf, *p; 25494910Swollman 255025944Sjoerg len -= 4; 255125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 255225944Sjoerg if (!buf) 25534910Swollman return; 255425944Sjoerg 255525944Sjoerg if (debug) 255640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 255740008Sjoerg SPP_ARGS(ifp)); 255825944Sjoerg 255925944Sjoerg p = (void*) (h+1); 2560161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2561161556Scperciva len -= p[1], p += p[1]) { 256225944Sjoerg if (debug) 256369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 256425944Sjoerg switch (*p) { 256525944Sjoerg case LCP_OPT_MAGIC: 256625944Sjoerg /* Magic number -- can't use it, use 0 */ 256725944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 256825944Sjoerg sp->lcp.magic = 0; 256925944Sjoerg break; 257025944Sjoerg case LCP_OPT_MRU: 257125944Sjoerg /* 257225944Sjoerg * Should not be rejected anyway, since we only 257325944Sjoerg * negotiate a MRU if explicitly requested by 257425944Sjoerg * peer. 257525944Sjoerg */ 257625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 257725944Sjoerg break; 257830300Sjoerg case LCP_OPT_AUTH_PROTO: 257930300Sjoerg /* 258030300Sjoerg * Peer doesn't want to authenticate himself, 258130300Sjoerg * deny unless this is a dialout call, and 258230300Sjoerg * AUTHFLAG_NOCALLOUT is set. 258330300Sjoerg */ 258430300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 258530300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 258630300Sjoerg if (debug) 258769211Sphk log(-1, "[don't insist on auth " 258830300Sjoerg "for callout]"); 258930300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 259030300Sjoerg break; 259130300Sjoerg } 259230300Sjoerg if (debug) 259369211Sphk log(-1, "[access denied]\n"); 259430300Sjoerg lcp.Close(sp); 259530300Sjoerg break; 259625944Sjoerg } 25974910Swollman } 259825944Sjoerg if (debug) 259969211Sphk log(-1, "\n"); 260025944Sjoerg free (buf, M_TEMP); 260125944Sjoerg return; 260225944Sjoerg} 260325944Sjoerg 260425944Sjoerg/* 260525944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 260625944Sjoerg * negotiation. 260725944Sjoerg */ 260825944Sjoergstatic void 260925944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 261025944Sjoerg{ 261125944Sjoerg STDDCL; 261225944Sjoerg u_char *buf, *p; 261325944Sjoerg u_long magic; 261425944Sjoerg 261525944Sjoerg len -= 4; 261625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 261725944Sjoerg if (!buf) 261825944Sjoerg return; 261925944Sjoerg 262025944Sjoerg if (debug) 262140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 262240008Sjoerg SPP_ARGS(ifp)); 262325944Sjoerg 262425944Sjoerg p = (void*) (h+1); 2625161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2626161556Scperciva len -= p[1], p += p[1]) { 262725706Sjoerg if (debug) 262869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 262925944Sjoerg switch (*p) { 263025944Sjoerg case LCP_OPT_MAGIC: 263125944Sjoerg /* Magic number -- renegotiate */ 263225944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 263325944Sjoerg len >= 6 && p[1] == 6) { 263425944Sjoerg magic = (u_long)p[2] << 24 | 263525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 263625944Sjoerg /* 263725944Sjoerg * If the remote magic is our negated one, 263825944Sjoerg * this looks like a loopback problem. 263925944Sjoerg * Suggest a new magic to make sure. 264025944Sjoerg */ 264125944Sjoerg if (magic == ~sp->lcp.magic) { 264225944Sjoerg if (debug) 264369211Sphk log(-1, "magic glitch "); 264435064Sphk sp->lcp.magic = random(); 264525944Sjoerg } else { 264625944Sjoerg sp->lcp.magic = magic; 264725944Sjoerg if (debug) 264869211Sphk log(-1, "%lu ", magic); 264925944Sjoerg } 265025944Sjoerg } 265125944Sjoerg break; 265225944Sjoerg case LCP_OPT_MRU: 265325944Sjoerg /* 265425944Sjoerg * Peer wants to advise us to negotiate an MRU. 265525944Sjoerg * Agree on it if it's reasonable, or use 265625944Sjoerg * default otherwise. 265725944Sjoerg */ 265825944Sjoerg if (len >= 4 && p[1] == 4) { 265925944Sjoerg u_int mru = p[2] * 256 + p[3]; 266025944Sjoerg if (debug) 266169211Sphk log(-1, "%d ", mru); 266225944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 266325944Sjoerg mru = PP_MTU; 266425944Sjoerg sp->lcp.mru = mru; 266525944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 266625944Sjoerg } 266725944Sjoerg break; 266830300Sjoerg case LCP_OPT_AUTH_PROTO: 266930300Sjoerg /* 267030300Sjoerg * Peer doesn't like our authentication method, 267130300Sjoerg * deny. 267230300Sjoerg */ 267330300Sjoerg if (debug) 267469211Sphk log(-1, "[access denied]\n"); 267530300Sjoerg lcp.Close(sp); 267630300Sjoerg break; 26774910Swollman } 267825944Sjoerg } 267925944Sjoerg if (debug) 268069211Sphk log(-1, "\n"); 268125944Sjoerg free (buf, M_TEMP); 268225944Sjoerg return; 268325944Sjoerg} 268411189Sjkh 268525944Sjoergstatic void 268625944Sjoergsppp_lcp_tlu(struct sppp *sp) 268725944Sjoerg{ 268842066Sphk STDDCL; 268925944Sjoerg int i; 269025944Sjoerg u_long mask; 269125944Sjoerg 269225944Sjoerg /* XXX ? */ 269325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2694148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 269525944Sjoerg /* Coming out of loopback mode. */ 269625944Sjoerg if_up(ifp); 269740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 269825944Sjoerg } 269925944Sjoerg 270025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 270125944Sjoerg if ((cps[i])->flags & CP_QUAL) 270225944Sjoerg (cps[i])->Open(sp); 270325944Sjoerg 270430300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 270530300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 270625944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 270725944Sjoerg else 270825944Sjoerg sp->pp_phase = PHASE_NETWORK; 270925944Sjoerg 271042066Sphk if (debug) 271142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 271242066Sphk sppp_phase_name(sp->pp_phase)); 271325944Sjoerg 271430300Sjoerg /* 271530300Sjoerg * Open all authentication protocols. This is even required 271630300Sjoerg * if we already proceeded to network phase, since it might be 271730300Sjoerg * that remote wants us to authenticate, so we might have to 271830300Sjoerg * send a PAP request. Undesired authentication protocols 271930300Sjoerg * don't do anything when they get an Open event. 272030300Sjoerg */ 272130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 272230300Sjoerg if ((cps[i])->flags & CP_AUTH) 272330300Sjoerg (cps[i])->Open(sp); 272430300Sjoerg 272530300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 272625944Sjoerg /* Notify all NCPs. */ 272725944Sjoerg for (i = 0; i < IDX_COUNT; i++) 272888723Sjoerg if (((cps[i])->flags & CP_NCP) && 272988723Sjoerg /* 273088723Sjoerg * XXX 273188723Sjoerg * Hack to administratively disable IPv6 if 273288723Sjoerg * not desired. Perhaps we should have another 273388723Sjoerg * flag for this, but right now, we can make 273488723Sjoerg * all struct cp's read/only. 273588723Sjoerg */ 273688723Sjoerg (cps[i] != &ipv6cp || 273788723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 273825944Sjoerg (cps[i])->Open(sp); 273925944Sjoerg } 274025944Sjoerg 274125944Sjoerg /* Send Up events to all started protos. */ 274225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 274388706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 274425944Sjoerg (cps[i])->Up(sp); 274525944Sjoerg 274642104Sphk /* notify low-level driver of state change */ 274742104Sphk if (sp->pp_chg) 274842104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 274942104Sphk 275025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 275125944Sjoerg /* if no NCP is starting, close down */ 275230300Sjoerg sppp_lcp_check_and_close(sp); 275325944Sjoerg} 275425944Sjoerg 275525944Sjoergstatic void 275625944Sjoergsppp_lcp_tld(struct sppp *sp) 275725944Sjoerg{ 275842066Sphk STDDCL; 275925944Sjoerg int i; 276025944Sjoerg u_long mask; 276125944Sjoerg 276225944Sjoerg sp->pp_phase = PHASE_TERMINATE; 276325944Sjoerg 276442066Sphk if (debug) 276542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 276642066Sphk sppp_phase_name(sp->pp_phase)); 276725944Sjoerg 276825944Sjoerg /* 276925944Sjoerg * Take upper layers down. We send the Down event first and 277025944Sjoerg * the Close second to prevent the upper layers from sending 277125944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 277225944Sjoerg * describes it. 277325944Sjoerg */ 277425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 277588706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 277625944Sjoerg (cps[i])->Down(sp); 277725944Sjoerg (cps[i])->Close(sp); 277825944Sjoerg } 277925944Sjoerg} 278025944Sjoerg 278125944Sjoergstatic void 278225944Sjoergsppp_lcp_tls(struct sppp *sp) 278325944Sjoerg{ 278442066Sphk STDDCL; 278525944Sjoerg 278625944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 278725944Sjoerg 278842066Sphk if (debug) 278942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 279042066Sphk sppp_phase_name(sp->pp_phase)); 279125944Sjoerg 279225944Sjoerg /* Notify lower layer if desired. */ 279325944Sjoerg if (sp->pp_tls) 279425944Sjoerg (sp->pp_tls)(sp); 279541881Sphk else 279641881Sphk (sp->pp_up)(sp); 279725944Sjoerg} 279825944Sjoerg 279925944Sjoergstatic void 280025944Sjoergsppp_lcp_tlf(struct sppp *sp) 280125944Sjoerg{ 280242066Sphk STDDCL; 280325944Sjoerg 280425944Sjoerg sp->pp_phase = PHASE_DEAD; 280542066Sphk if (debug) 280642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 280742066Sphk sppp_phase_name(sp->pp_phase)); 280825944Sjoerg 280925944Sjoerg /* Notify lower layer if desired. */ 281025944Sjoerg if (sp->pp_tlf) 281125944Sjoerg (sp->pp_tlf)(sp); 281241881Sphk else 281341881Sphk (sp->pp_down)(sp); 281425944Sjoerg} 281525944Sjoerg 281625944Sjoergstatic void 281725944Sjoergsppp_lcp_scr(struct sppp *sp) 281825944Sjoerg{ 281930300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 282025944Sjoerg int i = 0; 282130300Sjoerg u_short authproto; 282225944Sjoerg 282325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 282425944Sjoerg if (! sp->lcp.magic) 282535064Sphk sp->lcp.magic = random(); 282625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 282725944Sjoerg opt[i++] = 6; 282825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 282925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 283025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 283125944Sjoerg opt[i++] = sp->lcp.magic; 283225944Sjoerg } 283325944Sjoerg 283425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 283525944Sjoerg opt[i++] = LCP_OPT_MRU; 283625944Sjoerg opt[i++] = 4; 283725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 283825944Sjoerg opt[i++] = sp->lcp.mru; 283925944Sjoerg } 284025944Sjoerg 284130300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 284230300Sjoerg authproto = sp->hisauth.proto; 284330300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 284430300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 284530300Sjoerg opt[i++] = authproto >> 8; 284630300Sjoerg opt[i++] = authproto; 284730300Sjoerg if (authproto == PPP_CHAP) 284830300Sjoerg opt[i++] = CHAP_MD5; 284930300Sjoerg } 285030300Sjoerg 285178064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 285225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 285325944Sjoerg} 285425944Sjoerg 285525944Sjoerg/* 285630300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 285730300Sjoerg */ 285830300Sjoergstatic int 285930300Sjoergsppp_ncp_check(struct sppp *sp) 286030300Sjoerg{ 286130300Sjoerg int i, mask; 286230300Sjoerg 286330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 286488706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 286530300Sjoerg return 1; 286630300Sjoerg return 0; 286730300Sjoerg} 286830300Sjoerg 286930300Sjoerg/* 287025944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 287125944Sjoerg * Called by the NCPs during their tlf action handling. 287225944Sjoerg */ 287325944Sjoergstatic void 287430300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 287525944Sjoerg{ 287625944Sjoerg 287730300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 287830300Sjoerg /* don't bother, we are already going down */ 287930300Sjoerg return; 288030300Sjoerg 288130300Sjoerg if (sppp_ncp_check(sp)) 288230300Sjoerg return; 288330300Sjoerg 288425944Sjoerg lcp.Close(sp); 288525944Sjoerg} 288670199Sjhay 288770199Sjhay/* 288825944Sjoerg *--------------------------------------------------------------------------* 288925944Sjoerg * * 289025944Sjoerg * The IPCP implementation. * 289125944Sjoerg * * 289225944Sjoerg *--------------------------------------------------------------------------* 289325944Sjoerg */ 289425944Sjoerg 2895184682Sbz#ifdef INET 289625944Sjoergstatic void 289725944Sjoergsppp_ipcp_init(struct sppp *sp) 289825944Sjoerg{ 289925944Sjoerg sp->ipcp.opts = 0; 290025944Sjoerg sp->ipcp.flags = 0; 290125944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 290225944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 290378064Sume sp->pp_seq[IDX_IPCP] = 0; 290478064Sume sp->pp_rseq[IDX_IPCP] = 0; 2905138745Srik callout_init(&sp->ch[IDX_IPCP], 2906147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 290725944Sjoerg} 290825944Sjoerg 290925944Sjoergstatic void 291025944Sjoergsppp_ipcp_up(struct sppp *sp) 291125944Sjoerg{ 291225944Sjoerg sppp_up_event(&ipcp, sp); 291325944Sjoerg} 291425944Sjoerg 291525944Sjoergstatic void 291625944Sjoergsppp_ipcp_down(struct sppp *sp) 291725944Sjoerg{ 291825944Sjoerg sppp_down_event(&ipcp, sp); 291925944Sjoerg} 292025944Sjoerg 292125944Sjoergstatic void 292225944Sjoergsppp_ipcp_open(struct sppp *sp) 292325944Sjoerg{ 292425944Sjoerg STDDCL; 292525944Sjoerg u_long myaddr, hisaddr; 292625944Sjoerg 292788534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 292888534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 292988700Sjoerg sp->ipcp.opts = 0; 293042104Sphk 293130300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 293225944Sjoerg /* 293325944Sjoerg * If we don't have his address, this probably means our 293425944Sjoerg * interface doesn't want to talk IP at all. (This could 293525944Sjoerg * be the case if somebody wants to speak only IPX, for 293625944Sjoerg * example.) Don't open IPCP in this case. 293725944Sjoerg */ 293825944Sjoerg if (hisaddr == 0L) { 293925944Sjoerg /* XXX this message should go away */ 294025944Sjoerg if (debug) 294140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 294240008Sjoerg SPP_ARGS(ifp)); 294325944Sjoerg return; 294425944Sjoerg } 294525944Sjoerg if (myaddr == 0L) { 294625944Sjoerg /* 294725944Sjoerg * I don't have an assigned address, so i need to 294825944Sjoerg * negotiate my address. 294925944Sjoerg */ 295025944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 295125944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 295242104Sphk } else 295342104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 295488723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 295588534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 295688534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 295788534Sjoerg sp->ipcp.compress_cid = 1; 295888534Sjoerg } 295925944Sjoerg sppp_open_event(&ipcp, sp); 296025944Sjoerg} 296125944Sjoerg 296225944Sjoergstatic void 296325944Sjoergsppp_ipcp_close(struct sppp *sp) 296425944Sjoerg{ 296525944Sjoerg sppp_close_event(&ipcp, sp); 296625944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 296725944Sjoerg /* 296825944Sjoerg * My address was dynamic, clear it again. 296925944Sjoerg */ 297025944Sjoerg sppp_set_ip_addr(sp, 0L); 297125944Sjoerg} 297225944Sjoerg 297325944Sjoergstatic void 297425944Sjoergsppp_ipcp_TO(void *cookie) 297525944Sjoerg{ 297625944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 297725944Sjoerg} 297825944Sjoerg 297925944Sjoerg/* 298025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 298125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 298225944Sjoerg * caused action scn. (The return value is used to make the state 298325944Sjoerg * transition decision in the state automaton.) 298425944Sjoerg */ 298525944Sjoergstatic int 298625944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 298725944Sjoerg{ 298825944Sjoerg u_char *buf, *r, *p; 2989147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 299025944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 299125944Sjoerg u_long hisaddr, desiredaddr; 299242104Sphk int gotmyaddr = 0; 299388534Sjoerg int desiredcomp; 299425944Sjoerg 299525944Sjoerg len -= 4; 299625944Sjoerg origlen = len; 299725944Sjoerg /* 299825944Sjoerg * Make sure to allocate a buf that can at least hold a 299925944Sjoerg * conf-nak with an `address' option. We might need it below. 300025944Sjoerg */ 300125944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 300225944Sjoerg if (! buf) 300325944Sjoerg return (0); 300425944Sjoerg 300525944Sjoerg /* pass 1: see if we can recognize them */ 300625944Sjoerg if (debug) 300740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 300840008Sjoerg SPP_ARGS(ifp)); 300925944Sjoerg p = (void*) (h+1); 3010161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3011161556Scperciva len-=p[1], p+=p[1]) { 301225944Sjoerg if (debug) 301369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 301425944Sjoerg switch (*p) { 301588534Sjoerg case IPCP_OPT_COMPRESSION: 301688723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 301788534Sjoerg /* VJ compression administratively disabled */ 301888534Sjoerg if (debug) 301988534Sjoerg log(-1, "[locally disabled] "); 302088534Sjoerg break; 302188534Sjoerg } 302288534Sjoerg /* 302388534Sjoerg * In theory, we should only conf-rej an 302488534Sjoerg * option that is shorter than RFC 1618 302588534Sjoerg * requires (i.e. < 4), and should conf-nak 302688534Sjoerg * anything else that is not VJ. However, 302788534Sjoerg * since our algorithm always uses the 302888534Sjoerg * original option to NAK it with new values, 302988534Sjoerg * things would become more complicated. In 303088534Sjoerg * pratice, the only commonly implemented IP 303188534Sjoerg * compression option is VJ anyway, so the 303288534Sjoerg * difference is negligible. 303388534Sjoerg */ 303488534Sjoerg if (len >= 6 && p[1] == 6) { 303588534Sjoerg /* 303688534Sjoerg * correctly formed compression option 303788534Sjoerg * that could be VJ compression 303888534Sjoerg */ 303988534Sjoerg continue; 304088534Sjoerg } 304188534Sjoerg if (debug) 304288534Sjoerg log(-1, 304388534Sjoerg "optlen %d [invalid/unsupported] ", 304488534Sjoerg p[1]); 304588534Sjoerg break; 304625944Sjoerg case IPCP_OPT_ADDRESS: 304725944Sjoerg if (len >= 6 && p[1] == 6) { 304825944Sjoerg /* correctly formed address option */ 304925944Sjoerg continue; 305025944Sjoerg } 305125706Sjoerg if (debug) 305269211Sphk log(-1, "[invalid] "); 305311189Sjkh break; 305425944Sjoerg default: 305525944Sjoerg /* Others not supported. */ 305625944Sjoerg if (debug) 305769211Sphk log(-1, "[rej] "); 30584910Swollman break; 30594910Swollman } 306025944Sjoerg /* Add the option to rejected list. */ 306125944Sjoerg bcopy (p, r, p[1]); 306225944Sjoerg r += p[1]; 306325944Sjoerg rlen += p[1]; 306425944Sjoerg } 306525944Sjoerg if (rlen) { 306625944Sjoerg if (debug) 306769211Sphk log(-1, " send conf-rej\n"); 306825944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 306925944Sjoerg return 0; 307025944Sjoerg } else if (debug) 307169211Sphk log(-1, "\n"); 307225944Sjoerg 307325944Sjoerg /* pass 2: parse option values */ 307430300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 307525944Sjoerg if (debug) 307640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 307740008Sjoerg SPP_ARGS(ifp)); 307825944Sjoerg p = (void*) (h+1); 307925944Sjoerg len = origlen; 3080161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3081161556Scperciva len-=p[1], p+=p[1]) { 308225944Sjoerg if (debug) 308369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 308425944Sjoerg switch (*p) { 308588534Sjoerg case IPCP_OPT_COMPRESSION: 308688534Sjoerg desiredcomp = p[2] << 8 | p[3]; 308788534Sjoerg /* We only support VJ */ 308888534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 308988534Sjoerg if (debug) 309088534Sjoerg log(-1, "VJ [ack] "); 309188534Sjoerg sp->ipcp.flags |= IPCP_VJ; 309288599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 309388534Sjoerg sp->ipcp.max_state = p[4]; 309488534Sjoerg sp->ipcp.compress_cid = p[5]; 309588534Sjoerg continue; 309688534Sjoerg } 309788534Sjoerg if (debug) 309888534Sjoerg log(-1, 309988534Sjoerg "compproto %#04x [not supported] ", 310088534Sjoerg desiredcomp); 310188534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 310288534Sjoerg p[3] = IPCP_COMP_VJ; 310388534Sjoerg p[4] = sp->ipcp.max_state; 310488534Sjoerg p[5] = sp->ipcp.compress_cid; 310588534Sjoerg break; 310625944Sjoerg case IPCP_OPT_ADDRESS: 310742104Sphk /* This is the address he wants in his end */ 310825944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 310925944Sjoerg p[4] << 8 | p[5]; 311033928Sphk if (desiredaddr == hisaddr || 311188702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 311225944Sjoerg /* 311325944Sjoerg * Peer's address is same as our value, 311488702Sjoerg * or we have set it to 0.0.0.* to 311533928Sphk * indicate that we do not really care, 311625944Sjoerg * this is agreeable. Gonna conf-ack 311725944Sjoerg * it. 311825944Sjoerg */ 311925944Sjoerg if (debug) 312069211Sphk log(-1, "%s [ack] ", 312142104Sphk sppp_dotted_quad(hisaddr)); 312225944Sjoerg /* record that we've seen it already */ 312325944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 312425944Sjoerg continue; 312525944Sjoerg } 312625944Sjoerg /* 312725944Sjoerg * The address wasn't agreeable. This is either 312825944Sjoerg * he sent us 0.0.0.0, asking to assign him an 312925944Sjoerg * address, or he send us another address not 313025944Sjoerg * matching our value. Either case, we gonna 313125944Sjoerg * conf-nak it with our value. 313242104Sphk * XXX: we should "rej" if hisaddr == 0 313325944Sjoerg */ 313425944Sjoerg if (debug) { 313525944Sjoerg if (desiredaddr == 0) 313669211Sphk log(-1, "[addr requested] "); 313725944Sjoerg else 313869211Sphk log(-1, "%s [not agreed] ", 313942104Sphk sppp_dotted_quad(desiredaddr)); 314025944Sjoerg 314125944Sjoerg } 314244235Sphk p[2] = hisaddr >> 24; 314344235Sphk p[3] = hisaddr >> 16; 314444235Sphk p[4] = hisaddr >> 8; 314544235Sphk p[5] = hisaddr; 314611189Sjkh break; 314725706Sjoerg } 314825944Sjoerg /* Add the option to nak'ed list. */ 314925944Sjoerg bcopy (p, r, p[1]); 315025944Sjoerg r += p[1]; 315125944Sjoerg rlen += p[1]; 315225944Sjoerg } 315325944Sjoerg 315425944Sjoerg /* 315525944Sjoerg * If we are about to conf-ack the request, but haven't seen 315625944Sjoerg * his address so far, gonna conf-nak it instead, with the 315725944Sjoerg * `address' option present and our idea of his address being 315825944Sjoerg * filled in there, to request negotiation of both addresses. 315925944Sjoerg * 316025944Sjoerg * XXX This can result in an endless req - nak loop if peer 316125944Sjoerg * doesn't want to send us his address. Q: What should we do 316225944Sjoerg * about it? XXX A: implement the max-failure counter. 316325944Sjoerg */ 316442104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 316525944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 316625944Sjoerg buf[1] = 6; 316725944Sjoerg buf[2] = hisaddr >> 24; 316825944Sjoerg buf[3] = hisaddr >> 16; 316925944Sjoerg buf[4] = hisaddr >> 8; 317025944Sjoerg buf[5] = hisaddr; 317125944Sjoerg rlen = 6; 317225706Sjoerg if (debug) 317369211Sphk log(-1, "still need hisaddr "); 317425944Sjoerg } 317525944Sjoerg 317625944Sjoerg if (rlen) { 317725706Sjoerg if (debug) 317869211Sphk log(-1, " send conf-nak\n"); 317925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 318025944Sjoerg } else { 318125706Sjoerg if (debug) 318269211Sphk log(-1, " send conf-ack\n"); 318325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 318425944Sjoerg h->ident, origlen, h+1); 318525944Sjoerg } 318625944Sjoerg 318725944Sjoerg free (buf, M_TEMP); 318825944Sjoerg return (rlen == 0); 318925944Sjoerg} 319025944Sjoerg 319125944Sjoerg/* 319225944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 319325944Sjoerg * negotiation. 319425944Sjoerg */ 319525944Sjoergstatic void 319625944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 319725944Sjoerg{ 319825944Sjoerg u_char *buf, *p; 3199147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 320025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 320125944Sjoerg 320225944Sjoerg len -= 4; 320325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 320425944Sjoerg if (!buf) 320525944Sjoerg return; 320625944Sjoerg 320725944Sjoerg if (debug) 320840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 320940008Sjoerg SPP_ARGS(ifp)); 321025944Sjoerg 321125944Sjoerg p = (void*) (h+1); 3212161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3213161556Scperciva len -= p[1], p += p[1]) { 321425706Sjoerg if (debug) 321569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 321625944Sjoerg switch (*p) { 321788534Sjoerg case IPCP_OPT_COMPRESSION: 321888534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 321988534Sjoerg break; 322025944Sjoerg case IPCP_OPT_ADDRESS: 322125944Sjoerg /* 322225944Sjoerg * Peer doesn't grok address option. This is 322325944Sjoerg * bad. XXX Should we better give up here? 322442104Sphk * XXX We could try old "addresses" option... 322525944Sjoerg */ 322625944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 322725944Sjoerg break; 322825944Sjoerg } 32294910Swollman } 323025944Sjoerg if (debug) 323169211Sphk log(-1, "\n"); 323225944Sjoerg free (buf, M_TEMP); 323325944Sjoerg return; 32344910Swollman} 32354910Swollman 323625944Sjoerg/* 323725944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 323825944Sjoerg * negotiation. 323925944Sjoerg */ 324012820Sphkstatic void 324125944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 32424910Swollman{ 324325944Sjoerg u_char *buf, *p; 3244147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 324525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 324688534Sjoerg int desiredcomp; 324725944Sjoerg u_long wantaddr; 32484910Swollman 324925944Sjoerg len -= 4; 325025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 325125944Sjoerg if (!buf) 325225944Sjoerg return; 325325944Sjoerg 325425944Sjoerg if (debug) 325540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 325640008Sjoerg SPP_ARGS(ifp)); 325725944Sjoerg 325825944Sjoerg p = (void*) (h+1); 3259161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3260161556Scperciva len -= p[1], p += p[1]) { 326125944Sjoerg if (debug) 326269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 326325944Sjoerg switch (*p) { 326488534Sjoerg case IPCP_OPT_COMPRESSION: 326588534Sjoerg if (len >= 6 && p[1] == 6) { 326688534Sjoerg desiredcomp = p[2] << 8 | p[3]; 326788534Sjoerg if (debug) 326888534Sjoerg log(-1, "[wantcomp %#04x] ", 326988534Sjoerg desiredcomp); 327088534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 327188599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 327288534Sjoerg sp->ipcp.max_state = p[4]; 327388534Sjoerg sp->ipcp.compress_cid = p[5]; 327488534Sjoerg if (debug) 327588534Sjoerg log(-1, "[agree] "); 327688534Sjoerg } else 327788534Sjoerg sp->ipcp.opts &= 327888534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 327988534Sjoerg } 328088534Sjoerg break; 328125944Sjoerg case IPCP_OPT_ADDRESS: 328225944Sjoerg /* 328325944Sjoerg * Peer doesn't like our local IP address. See 328425944Sjoerg * if we can do something for him. We'll drop 328525944Sjoerg * him our address then. 328625944Sjoerg */ 328725944Sjoerg if (len >= 6 && p[1] == 6) { 328825944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 328925944Sjoerg p[4] << 8 | p[5]; 329025944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 329125944Sjoerg if (debug) 329269211Sphk log(-1, "[wantaddr %s] ", 329330300Sjoerg sppp_dotted_quad(wantaddr)); 329425944Sjoerg /* 329525944Sjoerg * When doing dynamic address assignment, 329625944Sjoerg * we accept his offer. Otherwise, we 329725944Sjoerg * ignore it and thus continue to negotiate 329825944Sjoerg * our already existing value. 329942104Sphk * XXX: Bogus, if he said no once, he'll 330042104Sphk * just say no again, might as well die. 330125944Sjoerg */ 330225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 330325944Sjoerg sppp_set_ip_addr(sp, wantaddr); 330425944Sjoerg if (debug) 330569211Sphk log(-1, "[agree] "); 330642104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 330725944Sjoerg } 330825944Sjoerg } 330925944Sjoerg break; 331025944Sjoerg } 331125944Sjoerg } 331225944Sjoerg if (debug) 331369211Sphk log(-1, "\n"); 331425944Sjoerg free (buf, M_TEMP); 331525944Sjoerg return; 33164910Swollman} 33174910Swollman 331812820Sphkstatic void 331925944Sjoergsppp_ipcp_tlu(struct sppp *sp) 33204910Swollman{ 332142104Sphk /* we are up - notify isdn daemon */ 332242104Sphk if (sp->pp_con) 332342104Sphk sp->pp_con(sp); 33244910Swollman} 33254910Swollman 332625944Sjoergstatic void 332725944Sjoergsppp_ipcp_tld(struct sppp *sp) 332825944Sjoerg{ 332925944Sjoerg} 333025944Sjoerg 333125944Sjoergstatic void 333225944Sjoergsppp_ipcp_tls(struct sppp *sp) 333325944Sjoerg{ 333425944Sjoerg /* indicate to LCP that it must stay alive */ 333525944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 333625944Sjoerg} 333725944Sjoerg 333825944Sjoergstatic void 333925944Sjoergsppp_ipcp_tlf(struct sppp *sp) 334025944Sjoerg{ 334125944Sjoerg /* we no longer need LCP */ 334225944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 334330300Sjoerg sppp_lcp_check_and_close(sp); 334425944Sjoerg} 334525944Sjoerg 334625944Sjoergstatic void 334725944Sjoergsppp_ipcp_scr(struct sppp *sp) 334825944Sjoerg{ 334925944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 335025944Sjoerg u_long ouraddr; 335125944Sjoerg int i = 0; 335225944Sjoerg 335388534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 335488534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 335588534Sjoerg opt[i++] = 6; 335688534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 335788534Sjoerg opt[i++] = IPCP_COMP_VJ; 335888534Sjoerg opt[i++] = sp->ipcp.max_state; 335988534Sjoerg opt[i++] = sp->ipcp.compress_cid; 336088534Sjoerg } 336125944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 336230300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 336325944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 336425944Sjoerg opt[i++] = 6; 336525944Sjoerg opt[i++] = ouraddr >> 24; 336625944Sjoerg opt[i++] = ouraddr >> 16; 336725944Sjoerg opt[i++] = ouraddr >> 8; 336825944Sjoerg opt[i++] = ouraddr; 336925944Sjoerg } 337025944Sjoerg 337178064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 337225944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 337325944Sjoerg} 3374184682Sbz#else /* !INET */ 3375184682Sbzstatic void 3376184682Sbzsppp_ipcp_init(struct sppp *sp) 3377184682Sbz{ 3378184682Sbz} 337925944Sjoerg 3380184682Sbzstatic void 3381184682Sbzsppp_ipcp_up(struct sppp *sp) 3382184682Sbz{ 3383184682Sbz} 3384184682Sbz 3385184682Sbzstatic void 3386184682Sbzsppp_ipcp_down(struct sppp *sp) 3387184682Sbz{ 3388184682Sbz} 3389184682Sbz 3390184682Sbzstatic void 3391184682Sbzsppp_ipcp_open(struct sppp *sp) 3392184682Sbz{ 3393184682Sbz} 3394184682Sbz 3395184682Sbzstatic void 3396184682Sbzsppp_ipcp_close(struct sppp *sp) 3397184682Sbz{ 3398184682Sbz} 3399184682Sbz 3400184682Sbzstatic void 3401184682Sbzsppp_ipcp_TO(void *cookie) 3402184682Sbz{ 3403184682Sbz} 3404184682Sbz 3405184682Sbzstatic int 3406184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3407184682Sbz{ 3408184682Sbz return (0); 3409184682Sbz} 3410184682Sbz 3411184682Sbzstatic void 3412184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3413184682Sbz{ 3414184682Sbz} 3415184682Sbz 3416184682Sbzstatic void 3417184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3418184682Sbz{ 3419184682Sbz} 3420184682Sbz 3421184682Sbzstatic void 3422184682Sbzsppp_ipcp_tlu(struct sppp *sp) 3423184682Sbz{ 3424184682Sbz} 3425184682Sbz 3426184682Sbzstatic void 3427184682Sbzsppp_ipcp_tld(struct sppp *sp) 3428184682Sbz{ 3429184682Sbz} 3430184682Sbz 3431184682Sbzstatic void 3432184682Sbzsppp_ipcp_tls(struct sppp *sp) 3433184682Sbz{ 3434184682Sbz} 3435184682Sbz 3436184682Sbzstatic void 3437184682Sbzsppp_ipcp_tlf(struct sppp *sp) 3438184682Sbz{ 3439184682Sbz} 3440184682Sbz 3441184682Sbzstatic void 3442184682Sbzsppp_ipcp_scr(struct sppp *sp) 3443184682Sbz{ 3444184682Sbz} 3445184682Sbz#endif 3446184682Sbz 344770199Sjhay/* 344830300Sjoerg *--------------------------------------------------------------------------* 344930300Sjoerg * * 345078064Sume * The IPv6CP implementation. * 345178064Sume * * 345278064Sume *--------------------------------------------------------------------------* 345378064Sume */ 345478064Sume 345578064Sume#ifdef INET6 345678064Sumestatic void 345778064Sumesppp_ipv6cp_init(struct sppp *sp) 345878064Sume{ 345978064Sume sp->ipv6cp.opts = 0; 346078064Sume sp->ipv6cp.flags = 0; 346178064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 346278064Sume sp->fail_counter[IDX_IPV6CP] = 0; 346378064Sume sp->pp_seq[IDX_IPV6CP] = 0; 346478064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3465138745Srik callout_init(&sp->ch[IDX_IPV6CP], 3466147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 346778064Sume} 346878064Sume 346978064Sumestatic void 347078064Sumesppp_ipv6cp_up(struct sppp *sp) 347178064Sume{ 347278064Sume sppp_up_event(&ipv6cp, sp); 347378064Sume} 347478064Sume 347578064Sumestatic void 347678064Sumesppp_ipv6cp_down(struct sppp *sp) 347778064Sume{ 347878064Sume sppp_down_event(&ipv6cp, sp); 347978064Sume} 348078064Sume 348178064Sumestatic void 348278064Sumesppp_ipv6cp_open(struct sppp *sp) 348378064Sume{ 348478064Sume STDDCL; 348578064Sume struct in6_addr myaddr, hisaddr; 348678064Sume 348778064Sume#ifdef IPV6CP_MYIFID_DYN 348878064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 348978064Sume#else 349078064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 349178064Sume#endif 349278064Sume 349378064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 349478064Sume /* 349578064Sume * If we don't have our address, this probably means our 349678064Sume * interface doesn't want to talk IPv6 at all. (This could 349778064Sume * be the case if somebody wants to speak only IPX, for 349878064Sume * example.) Don't open IPv6CP in this case. 349978064Sume */ 350078064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 350178064Sume /* XXX this message should go away */ 350278064Sume if (debug) 350378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 350478064Sume SPP_ARGS(ifp)); 350578064Sume return; 350678064Sume } 350778064Sume 350878064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 350978064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 351078064Sume sppp_open_event(&ipv6cp, sp); 351178064Sume} 351278064Sume 351378064Sumestatic void 351478064Sumesppp_ipv6cp_close(struct sppp *sp) 351578064Sume{ 351678064Sume sppp_close_event(&ipv6cp, sp); 351778064Sume} 351878064Sume 351978064Sumestatic void 352078064Sumesppp_ipv6cp_TO(void *cookie) 352178064Sume{ 352278064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 352378064Sume} 352478064Sume 352578064Sume/* 352678064Sume * Analyze a configure request. Return true if it was agreeable, and 352778064Sume * caused action sca, false if it has been rejected or nak'ed, and 352878064Sume * caused action scn. (The return value is used to make the state 352978064Sume * transition decision in the state automaton.) 353078064Sume */ 353178064Sumestatic int 353278064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 353378064Sume{ 353478064Sume u_char *buf, *r, *p; 3535147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 353678064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 353778064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 353878064Sume int ifidcount; 353978064Sume int type; 354078064Sume int collision, nohisaddr; 3541165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 354278064Sume 354378064Sume len -= 4; 354478064Sume origlen = len; 354578064Sume /* 354678064Sume * Make sure to allocate a buf that can at least hold a 354778064Sume * conf-nak with an `address' option. We might need it below. 354878064Sume */ 354978064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 355078064Sume if (! buf) 355178064Sume return (0); 355278064Sume 355378064Sume /* pass 1: see if we can recognize them */ 355478064Sume if (debug) 355578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 355678064Sume SPP_ARGS(ifp)); 355778064Sume p = (void*) (h+1); 355878064Sume ifidcount = 0; 3559161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3560161556Scperciva len-=p[1], p+=p[1]) { 356178064Sume if (debug) 356278176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 356378064Sume switch (*p) { 356478064Sume case IPV6CP_OPT_IFID: 356578064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 356678064Sume /* correctly formed address option */ 356778064Sume ifidcount++; 356878064Sume continue; 356978064Sume } 357078064Sume if (debug) 357178176Sume log(-1, " [invalid]"); 357278064Sume break; 357378064Sume#ifdef notyet 357478064Sume case IPV6CP_OPT_COMPRESSION: 357578064Sume if (len >= 4 && p[1] >= 4) { 357678064Sume /* correctly formed compress option */ 357778064Sume continue; 357878064Sume } 357978064Sume if (debug) 358078176Sume log(-1, " [invalid]"); 358178064Sume break; 358278064Sume#endif 358378064Sume default: 358478064Sume /* Others not supported. */ 358578064Sume if (debug) 358678176Sume log(-1, " [rej]"); 358778064Sume break; 358878064Sume } 358978064Sume /* Add the option to rejected list. */ 359078064Sume bcopy (p, r, p[1]); 359178064Sume r += p[1]; 359278064Sume rlen += p[1]; 359378064Sume } 359478064Sume if (rlen) { 359578064Sume if (debug) 359678176Sume log(-1, " send conf-rej\n"); 359778064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 359878064Sume goto end; 359978064Sume } else if (debug) 360078176Sume log(-1, "\n"); 360178064Sume 360278064Sume /* pass 2: parse option values */ 360378064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 360478064Sume if (debug) 360578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 360678064Sume SPP_ARGS(ifp)); 360778064Sume p = (void*) (h+1); 360878064Sume len = origlen; 360978064Sume type = CONF_ACK; 3610161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3611161556Scperciva len-=p[1], p+=p[1]) { 361278064Sume if (debug) 361378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 361478064Sume switch (*p) { 361578064Sume#ifdef notyet 361678064Sume case IPV6CP_OPT_COMPRESSION: 361778064Sume continue; 361878064Sume#endif 361978064Sume case IPV6CP_OPT_IFID: 362078064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 362178064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 362278064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 362378064Sume &myaddr.s6_addr[8], 8) == 0); 362478064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 362578064Sume 362678064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3627148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 362878064Sume 362978064Sume if (!collision && !nohisaddr) { 363078064Sume /* no collision, hisaddr known - Conf-Ack */ 363178064Sume type = CONF_ACK; 363278064Sume 363378064Sume if (debug) { 363478176Sume log(-1, " %s [%s]", 3635165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3636165118Sbz sppp_cp_type_name(type)); 363778064Sume } 363878064Sume continue; 363978064Sume } 364078064Sume 364178064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 364278064Sume if (collision && nohisaddr) { 364378064Sume /* collision, hisaddr unknown - Conf-Rej */ 364478064Sume type = CONF_REJ; 364578064Sume bzero(&p[2], 8); 364678064Sume } else { 364778064Sume /* 364878064Sume * - no collision, hisaddr unknown, or 364978064Sume * - collision, hisaddr known 365078064Sume * Conf-Nak, suggest hisaddr 365178064Sume */ 365278064Sume type = CONF_NAK; 365378064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 365478064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 365578064Sume } 365678064Sume if (debug) 3657165118Sbz log(-1, " %s [%s]", 3658165118Sbz ip6_sprintf(ip6buf, &desiredaddr), 3659165118Sbz sppp_cp_type_name(type)); 366078064Sume break; 366178064Sume } 366278064Sume /* Add the option to nak'ed list. */ 366378064Sume bcopy (p, r, p[1]); 366478064Sume r += p[1]; 366578064Sume rlen += p[1]; 366678064Sume } 366778064Sume 366878064Sume if (rlen == 0 && type == CONF_ACK) { 366978064Sume if (debug) 367078176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 367178064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 367278064Sume } else { 367378064Sume#ifdef DIAGNOSTIC 367478064Sume if (type == CONF_ACK) 367578064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 367678064Sume#endif 367778064Sume 367878064Sume if (debug) { 367978176Sume log(-1, " send %s suggest %s\n", 3680165118Sbz sppp_cp_type_name(type), 3681165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 368278064Sume } 368378064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 368478064Sume } 368578064Sume 368678064Sume end: 368778064Sume free (buf, M_TEMP); 368878064Sume return (rlen == 0); 368978064Sume} 369078064Sume 369178064Sume/* 369278064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 369378064Sume * negotiation. 369478064Sume */ 369578064Sumestatic void 369678064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 369778064Sume{ 369878064Sume u_char *buf, *p; 3699147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 370078064Sume int debug = ifp->if_flags & IFF_DEBUG; 370178064Sume 370278064Sume len -= 4; 370378064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 370478064Sume if (!buf) 370578064Sume return; 370678064Sume 370778064Sume if (debug) 370878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 370978064Sume SPP_ARGS(ifp)); 371078064Sume 371178064Sume p = (void*) (h+1); 3712161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3713161556Scperciva len -= p[1], p += p[1]) { 371478064Sume if (debug) 371578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 371678064Sume switch (*p) { 371778064Sume case IPV6CP_OPT_IFID: 371878064Sume /* 371978064Sume * Peer doesn't grok address option. This is 372078064Sume * bad. XXX Should we better give up here? 372178064Sume */ 372278064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 372378064Sume break; 372478064Sume#ifdef notyet 372578064Sume case IPV6CP_OPT_COMPRESS: 372678064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 372778064Sume break; 372878064Sume#endif 372978064Sume } 373078064Sume } 373178064Sume if (debug) 373278176Sume log(-1, "\n"); 373378064Sume free (buf, M_TEMP); 373478064Sume return; 373578064Sume} 373678064Sume 373778064Sume/* 373878064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 373978064Sume * negotiation. 374078064Sume */ 374178064Sumestatic void 374278064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 374378064Sume{ 374478064Sume u_char *buf, *p; 3745147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 374678064Sume int debug = ifp->if_flags & IFF_DEBUG; 374778064Sume struct in6_addr suggestaddr; 3748165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 374978064Sume 375078064Sume len -= 4; 375178064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 375278064Sume if (!buf) 375378064Sume return; 375478064Sume 375578064Sume if (debug) 375678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 375778064Sume SPP_ARGS(ifp)); 375878064Sume 375978064Sume p = (void*) (h+1); 3760161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3761161556Scperciva len -= p[1], p += p[1]) { 376278064Sume if (debug) 376378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 376478064Sume switch (*p) { 376578064Sume case IPV6CP_OPT_IFID: 376678064Sume /* 376778064Sume * Peer doesn't like our local ifid. See 376878064Sume * if we can do something for him. We'll drop 376978064Sume * him our address then. 377078064Sume */ 377178064Sume if (len < 10 || p[1] != 10) 377278064Sume break; 377378064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 377478064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3775148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 377678064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 377778064Sume 377878064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 377978064Sume if (debug) 378078176Sume log(-1, " [suggestaddr %s]", 3781165118Sbz ip6_sprintf(ip6buf, &suggestaddr)); 378278064Sume#ifdef IPV6CP_MYIFID_DYN 378378064Sume /* 378478064Sume * When doing dynamic address assignment, 378578064Sume * we accept his offer. 378678064Sume */ 378778064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 378878064Sume struct in6_addr lastsuggest; 378978064Sume /* 379078064Sume * If <suggested myaddr from peer> equals to 379178064Sume * <hisaddr we have suggested last time>, 379278064Sume * we have a collision. generate new random 379378064Sume * ifid. 379478064Sume */ 379578064Sume sppp_suggest_ip6_addr(&lastsuggest); 379678064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 379778064Sume lastsuggest)) { 379878064Sume if (debug) 379978176Sume log(-1, " [random]"); 380078064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 380178064Sume } 380278064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 380378064Sume if (debug) 380478176Sume log(-1, " [agree]"); 380578064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 380678064Sume } 380778064Sume#else 380878064Sume /* 380978064Sume * Since we do not do dynamic address assignment, 381078064Sume * we ignore it and thus continue to negotiate 381178064Sume * our already existing value. This can possibly 381278064Sume * go into infinite request-reject loop. 381378064Sume * 381478064Sume * This is not likely because we normally use 381578064Sume * ifid based on MAC-address. 381678064Sume * If you have no ethernet card on the node, too bad. 381778064Sume * XXX should we use fail_counter? 381878064Sume */ 381978064Sume#endif 382078064Sume break; 382178064Sume#ifdef notyet 382278064Sume case IPV6CP_OPT_COMPRESS: 382378064Sume /* 382478064Sume * Peer wants different compression parameters. 382578064Sume */ 382678064Sume break; 382778064Sume#endif 382878064Sume } 382978064Sume } 383078064Sume if (debug) 383178176Sume log(-1, "\n"); 383278064Sume free (buf, M_TEMP); 383378064Sume return; 383478064Sume} 383578064Sumestatic void 383678064Sumesppp_ipv6cp_tlu(struct sppp *sp) 383778064Sume{ 383878064Sume /* we are up - notify isdn daemon */ 383978064Sume if (sp->pp_con) 384078064Sume sp->pp_con(sp); 384178064Sume} 384278064Sume 384378064Sumestatic void 384478064Sumesppp_ipv6cp_tld(struct sppp *sp) 384578064Sume{ 384678064Sume} 384778064Sume 384878064Sumestatic void 384978064Sumesppp_ipv6cp_tls(struct sppp *sp) 385078064Sume{ 385178064Sume /* indicate to LCP that it must stay alive */ 385278064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 385378064Sume} 385478064Sume 385578064Sumestatic void 385678064Sumesppp_ipv6cp_tlf(struct sppp *sp) 385778064Sume{ 385878064Sume 385978064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 386078064Sume /* we no longer need LCP */ 386178064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 386278064Sume sppp_lcp_check_and_close(sp); 386378064Sume#endif 386478064Sume} 386578064Sume 386678064Sumestatic void 386778064Sumesppp_ipv6cp_scr(struct sppp *sp) 386878064Sume{ 386978064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 387078064Sume struct in6_addr ouraddr; 387178064Sume int i = 0; 387278064Sume 387378064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 387478064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 387578064Sume opt[i++] = IPV6CP_OPT_IFID; 387678064Sume opt[i++] = 10; 387778064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 387878064Sume i += 8; 387978064Sume } 388078064Sume 388178064Sume#ifdef notyet 388278064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 388378064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 388478064Sume opt[i++] = 4; 388578064Sume opt[i++] = 0; /* TBD */ 388678064Sume opt[i++] = 0; /* TBD */ 388778064Sume /* variable length data may follow */ 388878064Sume } 388978064Sume#endif 389078064Sume 389178064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 389278064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 389378064Sume} 389478064Sume#else /*INET6*/ 389578064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 389678064Sume{ 389778064Sume} 389878064Sume 389978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 390078064Sume{ 390178064Sume} 390278064Sume 390378064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 390478064Sume{ 390578064Sume} 390678064Sume 390778064Sume 390878064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 390978064Sume{ 391078064Sume} 391178064Sume 391278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 391378064Sume{ 391478064Sume} 391578064Sume 391678064Sumestatic void sppp_ipv6cp_TO(void *sp) 391778064Sume{ 391878064Sume} 391978064Sume 392078064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 392178064Sume{ 392278064Sume return 0; 392378064Sume} 392478064Sume 392578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 392678064Sume{ 392778064Sume} 392878064Sume 392978064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 393078064Sume{ 393178064Sume} 393278064Sume 393378064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 393478064Sume{ 393578064Sume} 393678064Sume 393778064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 393878064Sume{ 393978064Sume} 394078064Sume 394178064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 394278064Sume{ 394378064Sume} 394478064Sume 394578064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 394678064Sume{ 394778064Sume} 394878064Sume 394978064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 395078064Sume{ 395178064Sume} 395278064Sume#endif /*INET6*/ 395378064Sume 395478064Sume/* 395578064Sume *--------------------------------------------------------------------------* 395678064Sume * * 395730300Sjoerg * The CHAP implementation. * 395830300Sjoerg * * 395930300Sjoerg *--------------------------------------------------------------------------* 396030300Sjoerg */ 396130300Sjoerg 396230300Sjoerg/* 396330300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 396430300Sjoerg * the control protocols do, since they do have Open and Close events, but 396530300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 396630300Sjoerg * authentication protocols may be different in both directions (this makes 396730300Sjoerg * sense, think of a machine that never accepts incoming calls but only 396830300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 396930300Sjoerg * 397030300Sjoerg * Our state machine for the local authentication protocol (we are requesting 397130300Sjoerg * the peer to authenticate) looks like: 397230300Sjoerg * 397330300Sjoerg * RCA- 397430300Sjoerg * +--------------------------------------------+ 397530300Sjoerg * V scn,tld| 397630300Sjoerg * +--------+ Close +---------+ RCA+ 397730300Sjoerg * | |<----------------------------------| |------+ 397830300Sjoerg * +--->| Closed | TO* | Opened | sca | 397930300Sjoerg * | | |-----+ +-------| |<-----+ 398030300Sjoerg * | +--------+ irc | | +---------+ 398130300Sjoerg * | ^ | | ^ 398230300Sjoerg * | | | | | 398330300Sjoerg * | | | | | 398430300Sjoerg * | TO-| | | | 398530300Sjoerg * | |tld TO+ V | | 398630300Sjoerg * | | +------->+ | | 398730300Sjoerg * | | | | | | 398830300Sjoerg * | +--------+ V | | 398930300Sjoerg * | | |<----+<--------------------+ | 399030300Sjoerg * | | Req- | scr | 399130300Sjoerg * | | Sent | | 399230300Sjoerg * | | | | 399330300Sjoerg * | +--------+ | 399430300Sjoerg * | RCA- | | RCA+ | 399530300Sjoerg * +------+ +------------------------------------------+ 399630300Sjoerg * scn,tld sca,irc,ict,tlu 399730300Sjoerg * 399830300Sjoerg * 399930300Sjoerg * with: 400030300Sjoerg * 400130300Sjoerg * Open: LCP reached authentication phase 400230300Sjoerg * Close: LCP reached terminate phase 400330300Sjoerg * 400430300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 400530300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 400630300Sjoerg * TO+: timeout with restart counter >= 0 400730300Sjoerg * TO-: timeout with restart counter < 0 400830300Sjoerg * TO*: reschedule timeout for CHAP 400930300Sjoerg * 401030300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 401130300Sjoerg * sca: send ack packet (pap-ack, chap-success) 401230300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 401330300Sjoerg * ict: initialize re-challenge timer (CHAP only) 401430300Sjoerg * 401530300Sjoerg * tlu: this-layer-up, LCP reaches network phase 401630300Sjoerg * tld: this-layer-down, LCP enters terminate phase 401730300Sjoerg * 401830300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 401930300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 402030300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 402130300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 402230300Sjoerg * causing LCP to enter terminate phase. 402330300Sjoerg * 402430300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 402530300Sjoerg * expected to send one based on the successful negotiation of PAP as 402630300Sjoerg * the authentication protocol during the LCP option negotiation. 402730300Sjoerg * 402830300Sjoerg * Incoming authentication protocol requests (remote requests 402930300Sjoerg * authentication, we are peer) don't employ a state machine at all, 403030300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 403130300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 403230300Sjoerg * still in authentication phase (thereby violating the standard that 403330300Sjoerg * demands that these NCP packets are to be discarded), so we keep 403430300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 403530300Sjoerg * phase network once we've seen a positive acknowledge for the 403630300Sjoerg * authentication. 403730300Sjoerg */ 403830300Sjoerg 403930300Sjoerg/* 404030300Sjoerg * Handle incoming CHAP packets. 404130300Sjoerg */ 4042105228Sphkstatic void 404330300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 404430300Sjoerg{ 404530300Sjoerg STDDCL; 404630300Sjoerg struct lcp_header *h; 404730300Sjoerg int len, x; 404830300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 404930300Sjoerg int value_len, name_len; 405030300Sjoerg MD5_CTX ctx; 405130300Sjoerg 405230300Sjoerg len = m->m_pkthdr.len; 405330300Sjoerg if (len < 4) { 405430300Sjoerg if (debug) 405530300Sjoerg log(LOG_DEBUG, 405640008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 405740008Sjoerg SPP_ARGS(ifp), len); 405830300Sjoerg return; 405930300Sjoerg } 406030300Sjoerg h = mtod (m, struct lcp_header*); 406130300Sjoerg if (len > ntohs (h->len)) 406230300Sjoerg len = ntohs (h->len); 406330300Sjoerg 406430300Sjoerg switch (h->type) { 406530300Sjoerg /* challenge, failure and success are his authproto */ 406630300Sjoerg case CHAP_CHALLENGE: 406730300Sjoerg value = 1 + (u_char*)(h+1); 406830300Sjoerg value_len = value[-1]; 406930300Sjoerg name = value + value_len; 407030300Sjoerg name_len = len - value_len - 5; 407130300Sjoerg if (name_len < 0) { 407230300Sjoerg if (debug) { 407330300Sjoerg log(LOG_DEBUG, 407440008Sjoerg SPP_FMT "chap corrupted challenge " 407530300Sjoerg "<%s id=0x%x len=%d", 407640008Sjoerg SPP_ARGS(ifp), 407730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 407830300Sjoerg h->ident, ntohs(h->len)); 407944145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 408069211Sphk log(-1, ">\n"); 408130300Sjoerg } 408230300Sjoerg break; 408330300Sjoerg } 408470199Sjhay 408530300Sjoerg if (debug) { 408630300Sjoerg log(LOG_DEBUG, 408740008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 408840008Sjoerg SPP_ARGS(ifp), 408930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 409030300Sjoerg ntohs(h->len)); 409130300Sjoerg sppp_print_string((char*) name, name_len); 409269211Sphk log(-1, " value-size=%d value=", value_len); 409330300Sjoerg sppp_print_bytes(value, value_len); 409469211Sphk log(-1, ">\n"); 409530300Sjoerg } 409630300Sjoerg 409730300Sjoerg /* Compute reply value. */ 409830300Sjoerg MD5Init(&ctx); 409930300Sjoerg MD5Update(&ctx, &h->ident, 1); 410030300Sjoerg MD5Update(&ctx, sp->myauth.secret, 410130300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 410230300Sjoerg MD5Update(&ctx, value, value_len); 410330300Sjoerg MD5Final(digest, &ctx); 410430300Sjoerg dsize = sizeof digest; 410530300Sjoerg 410630300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 410730300Sjoerg sizeof dsize, (const char *)&dsize, 410830300Sjoerg sizeof digest, digest, 410940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 411030300Sjoerg sp->myauth.name, 411130300Sjoerg 0); 411230300Sjoerg break; 411330300Sjoerg 411430300Sjoerg case CHAP_SUCCESS: 411530300Sjoerg if (debug) { 411640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 411740008Sjoerg SPP_ARGS(ifp)); 411830300Sjoerg if (len > 4) { 411969211Sphk log(-1, ": "); 412030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 412130300Sjoerg } 412269211Sphk log(-1, "\n"); 412330300Sjoerg } 412430300Sjoerg x = splimp(); 4125138745Srik SPPP_LOCK(sp); 412630300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 412730300Sjoerg if (sp->myauth.proto == PPP_CHAP && 412832169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 412930300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 413030300Sjoerg /* 413130300Sjoerg * We are authenticator for CHAP but didn't 413230300Sjoerg * complete yet. Leave it to tlu to proceed 413330300Sjoerg * to network phase. 413430300Sjoerg */ 4135138745Srik SPPP_UNLOCK(sp); 413630300Sjoerg splx(x); 413730300Sjoerg break; 413830300Sjoerg } 4139138745Srik SPPP_UNLOCK(sp); 414030300Sjoerg splx(x); 414130300Sjoerg sppp_phase_network(sp); 414230300Sjoerg break; 414330300Sjoerg 414430300Sjoerg case CHAP_FAILURE: 414530300Sjoerg if (debug) { 414640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 414740008Sjoerg SPP_ARGS(ifp)); 414830300Sjoerg if (len > 4) { 414969211Sphk log(-1, ": "); 415030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 415130300Sjoerg } 415269211Sphk log(-1, "\n"); 415330300Sjoerg } else 415440008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 415540008Sjoerg SPP_ARGS(ifp)); 415630300Sjoerg /* await LCP shutdown by authenticator */ 415730300Sjoerg break; 415830300Sjoerg 415930300Sjoerg /* response is my authproto */ 416030300Sjoerg case CHAP_RESPONSE: 416130300Sjoerg value = 1 + (u_char*)(h+1); 416230300Sjoerg value_len = value[-1]; 416330300Sjoerg name = value + value_len; 416430300Sjoerg name_len = len - value_len - 5; 416530300Sjoerg if (name_len < 0) { 416630300Sjoerg if (debug) { 416730300Sjoerg log(LOG_DEBUG, 416840008Sjoerg SPP_FMT "chap corrupted response " 416930300Sjoerg "<%s id=0x%x len=%d", 417040008Sjoerg SPP_ARGS(ifp), 417130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 417230300Sjoerg h->ident, ntohs(h->len)); 417344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 417469211Sphk log(-1, ">\n"); 417530300Sjoerg } 417630300Sjoerg break; 417730300Sjoerg } 417830300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 417930300Sjoerg if (debug) 418030300Sjoerg log(LOG_DEBUG, 418140008Sjoerg SPP_FMT "chap dropping response for old ID " 418230300Sjoerg "(got %d, expected %d)\n", 418340008Sjoerg SPP_ARGS(ifp), 418430300Sjoerg h->ident, sp->confid[IDX_CHAP]); 418530300Sjoerg break; 418630300Sjoerg } 418730300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 418830300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 418940008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 419040008Sjoerg SPP_ARGS(ifp)); 419130300Sjoerg sppp_print_string(name, name_len); 419269211Sphk log(-1, " != expected "); 419330300Sjoerg sppp_print_string(sp->hisauth.name, 419430300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 419569211Sphk log(-1, "\n"); 419670199Sjhay } 419730300Sjoerg if (debug) { 419840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 419930300Sjoerg "<%s id=0x%x len=%d name=", 420040008Sjoerg SPP_ARGS(ifp), 420130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 420230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 420330300Sjoerg h->ident, ntohs (h->len)); 420430300Sjoerg sppp_print_string((char*)name, name_len); 420569211Sphk log(-1, " value-size=%d value=", value_len); 420630300Sjoerg sppp_print_bytes(value, value_len); 420769211Sphk log(-1, ">\n"); 420830300Sjoerg } 420930300Sjoerg if (value_len != AUTHKEYLEN) { 421030300Sjoerg if (debug) 421130300Sjoerg log(LOG_DEBUG, 421240008Sjoerg SPP_FMT "chap bad hash value length: " 421330300Sjoerg "%d bytes, should be %d\n", 421440008Sjoerg SPP_ARGS(ifp), value_len, 421530300Sjoerg AUTHKEYLEN); 421630300Sjoerg break; 421730300Sjoerg } 421830300Sjoerg 421930300Sjoerg MD5Init(&ctx); 422030300Sjoerg MD5Update(&ctx, &h->ident, 1); 422130300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 422230300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 422330300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 422430300Sjoerg MD5Final(digest, &ctx); 422530300Sjoerg 422630300Sjoerg#define FAILMSG "Failed..." 422730300Sjoerg#define SUCCMSG "Welcome!" 422830300Sjoerg 422930300Sjoerg if (value_len != sizeof digest || 423030300Sjoerg bcmp(digest, value, value_len) != 0) { 423130300Sjoerg /* action scn, tld */ 423230300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 423330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 423430300Sjoerg 0); 423530300Sjoerg chap.tld(sp); 423630300Sjoerg break; 423730300Sjoerg } 423830300Sjoerg /* action sca, perhaps tlu */ 423930300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 424030300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 424130300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 424230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 424330300Sjoerg 0); 424430300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 424530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 424630300Sjoerg chap.tlu(sp); 424730300Sjoerg } 424830300Sjoerg break; 424930300Sjoerg 425030300Sjoerg default: 425130300Sjoerg /* Unknown CHAP packet type -- ignore. */ 425230300Sjoerg if (debug) { 425340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 425430300Sjoerg "<0x%x id=0x%xh len=%d", 425540008Sjoerg SPP_ARGS(ifp), 425630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 425730300Sjoerg h->type, h->ident, ntohs(h->len)); 425844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 425969211Sphk log(-1, ">\n"); 426030300Sjoerg } 426130300Sjoerg break; 426230300Sjoerg 426330300Sjoerg } 426430300Sjoerg} 426530300Sjoerg 426630300Sjoergstatic void 426730300Sjoergsppp_chap_init(struct sppp *sp) 426830300Sjoerg{ 426930300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 427030300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 427130300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 427278064Sume sp->pp_seq[IDX_CHAP] = 0; 427378064Sume sp->pp_rseq[IDX_CHAP] = 0; 4274138745Srik callout_init(&sp->ch[IDX_CHAP], 4275147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 427630300Sjoerg} 427730300Sjoerg 427830300Sjoergstatic void 427930300Sjoergsppp_chap_open(struct sppp *sp) 428030300Sjoerg{ 428130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 428230300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 428330300Sjoerg /* we are authenticator for CHAP, start it */ 428430300Sjoerg chap.scr(sp); 428530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 428630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 428730300Sjoerg } 428830300Sjoerg /* nothing to be done if we are peer, await a challenge */ 428930300Sjoerg} 429030300Sjoerg 429130300Sjoergstatic void 429230300Sjoergsppp_chap_close(struct sppp *sp) 429330300Sjoerg{ 429430300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 429530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 429630300Sjoerg} 429730300Sjoerg 429830300Sjoergstatic void 429930300Sjoergsppp_chap_TO(void *cookie) 430030300Sjoerg{ 430130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 430230300Sjoerg STDDCL; 430330300Sjoerg int s; 430430300Sjoerg 430530300Sjoerg s = splimp(); 4306138745Srik SPPP_LOCK(sp); 430730300Sjoerg if (debug) 430840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 430940008Sjoerg SPP_ARGS(ifp), 431030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 431130300Sjoerg sp->rst_counter[IDX_CHAP]); 431230300Sjoerg 431330300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 431430300Sjoerg /* TO- event */ 431530300Sjoerg switch (sp->state[IDX_CHAP]) { 431630300Sjoerg case STATE_REQ_SENT: 431730300Sjoerg chap.tld(sp); 431830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 431930300Sjoerg break; 432030300Sjoerg } 432130300Sjoerg else 432230300Sjoerg /* TO+ (or TO*) event */ 432330300Sjoerg switch (sp->state[IDX_CHAP]) { 432430300Sjoerg case STATE_OPENED: 432530300Sjoerg /* TO* event */ 432630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4327102412Scharnier /* FALLTHROUGH */ 432830300Sjoerg case STATE_REQ_SENT: 432930300Sjoerg chap.scr(sp); 433030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 433130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 433230300Sjoerg break; 433330300Sjoerg } 433430300Sjoerg 4335138745Srik SPPP_UNLOCK(sp); 433630300Sjoerg splx(s); 433730300Sjoerg} 433830300Sjoerg 433930300Sjoergstatic void 434030300Sjoergsppp_chap_tlu(struct sppp *sp) 434130300Sjoerg{ 434230300Sjoerg STDDCL; 434330300Sjoerg int i, x; 434430300Sjoerg 434540010Sjoerg i = 0; 434630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 434730300Sjoerg 434830300Sjoerg /* 434930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 435030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 435130300Sjoerg * initial challenge-response exchange has taken place. 435230300Sjoerg * Provide for an option to avoid rechallenges. 435330300Sjoerg */ 435430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 435530300Sjoerg /* 435630300Sjoerg * Compute the re-challenge timeout. This will yield 435730300Sjoerg * a number between 300 and 810 seconds. 435830300Sjoerg */ 435930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4360138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 436130300Sjoerg } 436230300Sjoerg 436330300Sjoerg if (debug) { 436430300Sjoerg log(LOG_DEBUG, 436540008Sjoerg SPP_FMT "chap %s, ", 436640008Sjoerg SPP_ARGS(ifp), 436730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 436830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 436969211Sphk log(-1, "next re-challenge in %d seconds\n", i); 437030300Sjoerg else 437169211Sphk log(-1, "re-challenging supressed\n"); 437230300Sjoerg } 437330300Sjoerg 437430300Sjoerg x = splimp(); 4375138745Srik SPPP_LOCK(sp); 437630300Sjoerg /* indicate to LCP that we need to be closed down */ 437730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 437830300Sjoerg 437930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 438030300Sjoerg /* 438130300Sjoerg * Remote is authenticator, but his auth proto didn't 438230300Sjoerg * complete yet. Defer the transition to network 438330300Sjoerg * phase. 438430300Sjoerg */ 4385138745Srik SPPP_UNLOCK(sp); 438630300Sjoerg splx(x); 438730300Sjoerg return; 438830300Sjoerg } 4389138745Srik SPPP_UNLOCK(sp); 439030300Sjoerg splx(x); 439130300Sjoerg 439230300Sjoerg /* 439330300Sjoerg * If we are already in phase network, we are done here. This 439430300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 439530300Sjoerg */ 439630300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 439730300Sjoerg sppp_phase_network(sp); 439830300Sjoerg} 439930300Sjoerg 440030300Sjoergstatic void 440130300Sjoergsppp_chap_tld(struct sppp *sp) 440230300Sjoerg{ 440330300Sjoerg STDDCL; 440430300Sjoerg 440530300Sjoerg if (debug) 440640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4407138745Srik callout_stop(&sp->ch[IDX_CHAP]); 440830300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 440930300Sjoerg 441030300Sjoerg lcp.Close(sp); 441130300Sjoerg} 441230300Sjoerg 441330300Sjoergstatic void 441430300Sjoergsppp_chap_scr(struct sppp *sp) 441530300Sjoerg{ 441630300Sjoerg u_long *ch, seed; 441730300Sjoerg u_char clen; 441830300Sjoerg 441930300Sjoerg /* Compute random challenge. */ 442030300Sjoerg ch = (u_long *)sp->myauth.challenge; 442135064Sphk read_random(&seed, sizeof seed); 442230300Sjoerg ch[0] = seed ^ random(); 442330300Sjoerg ch[1] = seed ^ random(); 442430300Sjoerg ch[2] = seed ^ random(); 442530300Sjoerg ch[3] = seed ^ random(); 442630300Sjoerg clen = AUTHKEYLEN; 442730300Sjoerg 442878064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 442930300Sjoerg 443030300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 443130300Sjoerg sizeof clen, (const char *)&clen, 443240008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 443340008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 443430300Sjoerg sp->myauth.name, 443530300Sjoerg 0); 443630300Sjoerg} 443770199Sjhay 443870199Sjhay/* 443930300Sjoerg *--------------------------------------------------------------------------* 444030300Sjoerg * * 444130300Sjoerg * The PAP implementation. * 444230300Sjoerg * * 444330300Sjoerg *--------------------------------------------------------------------------* 444430300Sjoerg */ 444530300Sjoerg/* 444630300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 444730300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 444830300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 444930300Sjoerg * retry counter is expired). 445030300Sjoerg */ 445130300Sjoerg 445230300Sjoerg/* 445330300Sjoerg * Handle incoming PAP packets. */ 445430300Sjoergstatic void 445530300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 445630300Sjoerg{ 445730300Sjoerg STDDCL; 445830300Sjoerg struct lcp_header *h; 445930300Sjoerg int len, x; 446030300Sjoerg u_char *name, *passwd, mlen; 446130300Sjoerg int name_len, passwd_len; 446230300Sjoerg 446330300Sjoerg len = m->m_pkthdr.len; 446430300Sjoerg if (len < 5) { 446530300Sjoerg if (debug) 446630300Sjoerg log(LOG_DEBUG, 446740008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 446840008Sjoerg SPP_ARGS(ifp), len); 446930300Sjoerg return; 447030300Sjoerg } 447130300Sjoerg h = mtod (m, struct lcp_header*); 447230300Sjoerg if (len > ntohs (h->len)) 447330300Sjoerg len = ntohs (h->len); 447430300Sjoerg switch (h->type) { 447530300Sjoerg /* PAP request is my authproto */ 447630300Sjoerg case PAP_REQ: 447730300Sjoerg name = 1 + (u_char*)(h+1); 447830300Sjoerg name_len = name[-1]; 447930300Sjoerg passwd = name + name_len + 1; 448030300Sjoerg if (name_len > len - 6 || 448130300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 448230300Sjoerg if (debug) { 448340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 448430300Sjoerg "<%s id=0x%x len=%d", 448540008Sjoerg SPP_ARGS(ifp), 448630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 448730300Sjoerg h->ident, ntohs(h->len)); 448844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 448969211Sphk log(-1, ">\n"); 449030300Sjoerg } 449130300Sjoerg break; 449230300Sjoerg } 449330300Sjoerg if (debug) { 449440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 449530300Sjoerg "<%s id=0x%x len=%d name=", 449640008Sjoerg SPP_ARGS(ifp), 449730300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 449830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 449930300Sjoerg h->ident, ntohs(h->len)); 450030300Sjoerg sppp_print_string((char*)name, name_len); 450169211Sphk log(-1, " passwd="); 450230300Sjoerg sppp_print_string((char*)passwd, passwd_len); 450369211Sphk log(-1, ">\n"); 450430300Sjoerg } 450574774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 450674774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 450730300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 450830300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 450930300Sjoerg /* action scn, tld */ 451030300Sjoerg mlen = sizeof(FAILMSG) - 1; 451130300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 451230300Sjoerg sizeof mlen, (const char *)&mlen, 451330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 451430300Sjoerg 0); 451530300Sjoerg pap.tld(sp); 451630300Sjoerg break; 451730300Sjoerg } 451830300Sjoerg /* action sca, perhaps tlu */ 451930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 452030300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 452130300Sjoerg mlen = sizeof(SUCCMSG) - 1; 452230300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 452330300Sjoerg sizeof mlen, (const char *)&mlen, 452430300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 452530300Sjoerg 0); 452630300Sjoerg } 452730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 452830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 452930300Sjoerg pap.tlu(sp); 453030300Sjoerg } 453130300Sjoerg break; 453230300Sjoerg 453330300Sjoerg /* ack and nak are his authproto */ 453430300Sjoerg case PAP_ACK: 4535138745Srik callout_stop(&sp->pap_my_to_ch); 453630300Sjoerg if (debug) { 453740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 453840008Sjoerg SPP_ARGS(ifp)); 453930300Sjoerg name_len = *((char *)h); 454030300Sjoerg if (len > 5 && name_len) { 454169211Sphk log(-1, ": "); 454230300Sjoerg sppp_print_string((char*)(h+1), name_len); 454330300Sjoerg } 454469211Sphk log(-1, "\n"); 454530300Sjoerg } 454630300Sjoerg x = splimp(); 4547138745Srik SPPP_LOCK(sp); 454830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 454930300Sjoerg if (sp->myauth.proto == PPP_PAP && 455032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 455130300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 455230300Sjoerg /* 455330300Sjoerg * We are authenticator for PAP but didn't 455430300Sjoerg * complete yet. Leave it to tlu to proceed 455530300Sjoerg * to network phase. 455630300Sjoerg */ 4557138745Srik SPPP_UNLOCK(sp); 455830300Sjoerg splx(x); 455930300Sjoerg break; 456030300Sjoerg } 4561138745Srik SPPP_UNLOCK(sp); 456230300Sjoerg splx(x); 456330300Sjoerg sppp_phase_network(sp); 456430300Sjoerg break; 456530300Sjoerg 456630300Sjoerg case PAP_NAK: 4567138745Srik callout_stop (&sp->pap_my_to_ch); 456830300Sjoerg if (debug) { 456940008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 457040008Sjoerg SPP_ARGS(ifp)); 457130300Sjoerg name_len = *((char *)h); 457230300Sjoerg if (len > 5 && name_len) { 457369211Sphk log(-1, ": "); 457430300Sjoerg sppp_print_string((char*)(h+1), name_len); 457530300Sjoerg } 457669211Sphk log(-1, "\n"); 457730300Sjoerg } else 457840008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 457940008Sjoerg SPP_ARGS(ifp)); 458030300Sjoerg /* await LCP shutdown by authenticator */ 458130300Sjoerg break; 458230300Sjoerg 458330300Sjoerg default: 458430300Sjoerg /* Unknown PAP packet type -- ignore. */ 458530300Sjoerg if (debug) { 458640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 458730300Sjoerg "<0x%x id=0x%x len=%d", 458840008Sjoerg SPP_ARGS(ifp), 458930300Sjoerg h->type, h->ident, ntohs(h->len)); 459044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 459169211Sphk log(-1, ">\n"); 459230300Sjoerg } 459330300Sjoerg break; 459430300Sjoerg 459530300Sjoerg } 459630300Sjoerg} 459730300Sjoerg 459830300Sjoergstatic void 459930300Sjoergsppp_pap_init(struct sppp *sp) 460030300Sjoerg{ 460130300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 460230300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 460330300Sjoerg sp->fail_counter[IDX_PAP] = 0; 460478064Sume sp->pp_seq[IDX_PAP] = 0; 460578064Sume sp->pp_rseq[IDX_PAP] = 0; 4606138745Srik callout_init(&sp->ch[IDX_PAP], 4607147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 4608138745Srik callout_init(&sp->pap_my_to_ch, 4609147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 461030300Sjoerg} 461130300Sjoerg 461230300Sjoergstatic void 461330300Sjoergsppp_pap_open(struct sppp *sp) 461430300Sjoerg{ 461530300Sjoerg if (sp->hisauth.proto == PPP_PAP && 461630300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 461730300Sjoerg /* we are authenticator for PAP, start our timer */ 461830300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 461930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 462030300Sjoerg } 462130300Sjoerg if (sp->myauth.proto == PPP_PAP) { 462230300Sjoerg /* we are peer, send a request, and start a timer */ 462330300Sjoerg pap.scr(sp); 4624138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4625138745Srik sppp_pap_my_TO, (void *)sp); 462630300Sjoerg } 462730300Sjoerg} 462830300Sjoerg 462930300Sjoergstatic void 463030300Sjoergsppp_pap_close(struct sppp *sp) 463130300Sjoerg{ 463230300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 463330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 463430300Sjoerg} 463530300Sjoerg 463630300Sjoerg/* 463730300Sjoerg * That's the timeout routine if we are authenticator. Since the 463830300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 463930300Sjoerg */ 464030300Sjoergstatic void 464130300Sjoergsppp_pap_TO(void *cookie) 464230300Sjoerg{ 464330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 464430300Sjoerg STDDCL; 464530300Sjoerg int s; 464630300Sjoerg 464730300Sjoerg s = splimp(); 4648138745Srik SPPP_LOCK(sp); 464930300Sjoerg if (debug) 465040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 465140008Sjoerg SPP_ARGS(ifp), 465230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 465330300Sjoerg sp->rst_counter[IDX_PAP]); 465430300Sjoerg 465530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 465630300Sjoerg /* TO- event */ 465730300Sjoerg switch (sp->state[IDX_PAP]) { 465830300Sjoerg case STATE_REQ_SENT: 465930300Sjoerg pap.tld(sp); 466030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 466130300Sjoerg break; 466230300Sjoerg } 466330300Sjoerg else 466430300Sjoerg /* TO+ event, not very much we could do */ 466530300Sjoerg switch (sp->state[IDX_PAP]) { 466630300Sjoerg case STATE_REQ_SENT: 466730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 466830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 466930300Sjoerg break; 467030300Sjoerg } 467130300Sjoerg 4672138745Srik SPPP_UNLOCK(sp); 467330300Sjoerg splx(s); 467430300Sjoerg} 467530300Sjoerg 467630300Sjoerg/* 467730300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 467830300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 467930300Sjoerg * XXX We should impose a max counter. 468030300Sjoerg */ 468130300Sjoergstatic void 468230300Sjoergsppp_pap_my_TO(void *cookie) 468330300Sjoerg{ 468430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 468530300Sjoerg STDDCL; 468630300Sjoerg 468730300Sjoerg if (debug) 468840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 468940008Sjoerg SPP_ARGS(ifp)); 469030300Sjoerg 4691138745Srik SPPP_LOCK(sp); 469230300Sjoerg pap.scr(sp); 4693138745Srik SPPP_UNLOCK(sp); 469430300Sjoerg} 469530300Sjoerg 469630300Sjoergstatic void 469730300Sjoergsppp_pap_tlu(struct sppp *sp) 469830300Sjoerg{ 469930300Sjoerg STDDCL; 470030300Sjoerg int x; 470130300Sjoerg 470230300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 470330300Sjoerg 470430300Sjoerg if (debug) 470540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 470640008Sjoerg SPP_ARGS(ifp), pap.name); 470730300Sjoerg 470830300Sjoerg x = splimp(); 4709138745Srik SPPP_LOCK(sp); 471030300Sjoerg /* indicate to LCP that we need to be closed down */ 471130300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 471230300Sjoerg 471330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 471430300Sjoerg /* 471530300Sjoerg * Remote is authenticator, but his auth proto didn't 471630300Sjoerg * complete yet. Defer the transition to network 471730300Sjoerg * phase. 471830300Sjoerg */ 4719138745Srik SPPP_UNLOCK(sp); 472030300Sjoerg splx(x); 472130300Sjoerg return; 472230300Sjoerg } 4723138745Srik SPPP_UNLOCK(sp); 472430300Sjoerg splx(x); 472530300Sjoerg sppp_phase_network(sp); 472630300Sjoerg} 472730300Sjoerg 472830300Sjoergstatic void 472930300Sjoergsppp_pap_tld(struct sppp *sp) 473030300Sjoerg{ 473130300Sjoerg STDDCL; 473230300Sjoerg 473330300Sjoerg if (debug) 473440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4735138745Srik callout_stop (&sp->ch[IDX_PAP]); 4736138745Srik callout_stop (&sp->pap_my_to_ch); 473730300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 473830300Sjoerg 473930300Sjoerg lcp.Close(sp); 474030300Sjoerg} 474130300Sjoerg 474230300Sjoergstatic void 474330300Sjoergsppp_pap_scr(struct sppp *sp) 474430300Sjoerg{ 474530300Sjoerg u_char idlen, pwdlen; 474630300Sjoerg 474778064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 474830300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 474930300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 475030300Sjoerg 475130300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 475230300Sjoerg sizeof idlen, (const char *)&idlen, 475340008Sjoerg (size_t)idlen, sp->myauth.name, 475430300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 475540008Sjoerg (size_t)pwdlen, sp->myauth.secret, 475630300Sjoerg 0); 475730300Sjoerg} 475870199Sjhay 475970199Sjhay/* 476025944Sjoerg * Random miscellaneous functions. 476125944Sjoerg */ 476225944Sjoerg 47634910Swollman/* 476430300Sjoerg * Send a PAP or CHAP proto packet. 476530300Sjoerg * 476630300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 476740008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 476830300Sjoerg * mlen == 0. 476942104Sphk * NOTE: never declare variadic functions with types subject to type 477042104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 477142104Sphk * on the architecture you are on... 477230300Sjoerg */ 477330300Sjoerg 477430300Sjoergstatic void 477542104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 477642104Sphk unsigned int type, unsigned int id, 477730300Sjoerg ...) 477830300Sjoerg{ 477930300Sjoerg STDDCL; 478030300Sjoerg struct ppp_header *h; 478130300Sjoerg struct lcp_header *lh; 478230300Sjoerg struct mbuf *m; 478330300Sjoerg u_char *p; 478430300Sjoerg int len; 478542104Sphk unsigned int mlen; 478630300Sjoerg const char *msg; 478730300Sjoerg va_list ap; 478830300Sjoerg 4789111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 479030300Sjoerg if (! m) 479130300Sjoerg return; 479230300Sjoerg m->m_pkthdr.rcvif = 0; 479330300Sjoerg 479430300Sjoerg h = mtod (m, struct ppp_header*); 479530300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 479630300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 479730300Sjoerg h->protocol = htons(cp->proto); 479830300Sjoerg 479930300Sjoerg lh = (struct lcp_header*)(h + 1); 480030300Sjoerg lh->type = type; 480130300Sjoerg lh->ident = id; 480230300Sjoerg p = (u_char*) (lh+1); 480330300Sjoerg 480430300Sjoerg va_start(ap, id); 480530300Sjoerg len = 0; 480630300Sjoerg 480742104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 480830300Sjoerg msg = va_arg(ap, const char *); 480930300Sjoerg len += mlen; 481030300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 481130300Sjoerg va_end(ap); 481230300Sjoerg m_freem(m); 481330300Sjoerg return; 481430300Sjoerg } 481530300Sjoerg 481630300Sjoerg bcopy(msg, p, mlen); 481730300Sjoerg p += mlen; 481830300Sjoerg } 481930300Sjoerg va_end(ap); 482030300Sjoerg 482130300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 482230300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 482330300Sjoerg 482430300Sjoerg if (debug) { 482540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 482640008Sjoerg SPP_ARGS(ifp), cp->name, 482730300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 482830300Sjoerg lh->ident, ntohs(lh->len)); 482944145Sphk sppp_print_bytes((u_char*) (lh+1), len); 483069211Sphk log(-1, ">\n"); 483130300Sjoerg } 483269152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 483369152Sjlemon ifp->if_oerrors++; 483430300Sjoerg} 483530300Sjoerg 483630300Sjoerg/* 483725944Sjoerg * Flush interface queue. 48384910Swollman */ 483912820Sphkstatic void 484025944Sjoergsppp_qflush(struct ifqueue *ifq) 48414910Swollman{ 484225944Sjoerg struct mbuf *m, *n; 48434910Swollman 484425944Sjoerg n = ifq->ifq_head; 484525944Sjoerg while ((m = n)) { 484625944Sjoerg n = m->m_act; 484725944Sjoerg m_freem (m); 484811189Sjkh } 484925944Sjoerg ifq->ifq_head = 0; 485025944Sjoerg ifq->ifq_tail = 0; 485125944Sjoerg ifq->ifq_len = 0; 485225944Sjoerg} 485325944Sjoerg 485425944Sjoerg/* 485525944Sjoerg * Send keepalive packets, every 10 seconds. 485625944Sjoerg */ 485725944Sjoergstatic void 485825944Sjoergsppp_keepalive(void *dummy) 485925944Sjoerg{ 4860138745Srik struct sppp *sp = (struct sppp*)dummy; 4861147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 486225944Sjoerg int s; 486325944Sjoerg 486425944Sjoerg s = splimp(); 4865138745Srik SPPP_LOCK(sp); 4866138745Srik /* Keepalive mode disabled or channel down? */ 4867138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4868148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4869138745Srik goto out; 487025944Sjoerg 4871139365Srik if (sp->pp_mode == PP_FR) { 4872139365Srik sppp_fr_keepalive (sp); 4873139365Srik goto out; 4874139365Srik } 4875139365Srik 4876138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4877138745Srik if (sp->pp_mode != IFF_CISCO && 4878138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4879138745Srik goto out; 488025944Sjoerg 4881138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4882138745Srik /* No keepalive packets got. Stop the interface. */ 4883138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4884138745Srik if_down (ifp); 4885138745Srik sppp_qflush (&sp->pp_cpq); 4886138745Srik if (sp->pp_mode != IFF_CISCO) { 4887138745Srik /* XXX */ 4888138745Srik /* Shut down the PPP link. */ 4889138745Srik lcp.Down(sp); 4890138745Srik /* Initiate negotiation. XXX */ 4891138745Srik lcp.Up(sp); 48924910Swollman } 48934910Swollman } 4894138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4895138745Srik ++sp->pp_alivecnt; 4896138745Srik if (sp->pp_mode == IFF_CISCO) 4897138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4898138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4899138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4900138745Srik long nmagic = htonl (sp->lcp.magic); 4901138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4902138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4903138745Srik sp->lcp.echoid, 4, &nmagic); 4904138745Srik } 4905138745Srikout: 4906138745Srik SPPP_UNLOCK(sp); 490725944Sjoerg splx(s); 4908138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4909138745Srik (void *)sp); 49104910Swollman} 49114910Swollman 491225944Sjoerg/* 491325944Sjoerg * Get both IP addresses. 491425944Sjoerg */ 4915139365Srikvoid 491630300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 491725944Sjoerg{ 4918147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 491925944Sjoerg struct ifaddr *ifa; 492030300Sjoerg struct sockaddr_in *si, *sm; 492125944Sjoerg u_long ssrc, ddst; 492225944Sjoerg 492340010Sjoerg sm = NULL; 492425944Sjoerg ssrc = ddst = 0L; 492525944Sjoerg /* 492625944Sjoerg * Pick the first AF_INET address from the list, 492725944Sjoerg * aliases don't make any sense on a p2p link anyway. 492825944Sjoerg */ 492942065Sphk si = 0; 493042065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 493125944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 493225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 493330300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 493425944Sjoerg if (si) 493525944Sjoerg break; 493625944Sjoerg } 493725944Sjoerg if (ifa) { 493830300Sjoerg if (si && si->sin_addr.s_addr) { 493925944Sjoerg ssrc = si->sin_addr.s_addr; 494030300Sjoerg if (srcmask) 494130300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 494230300Sjoerg } 494325944Sjoerg 494425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 494525944Sjoerg if (si && si->sin_addr.s_addr) 494625944Sjoerg ddst = si->sin_addr.s_addr; 494725944Sjoerg } 494825944Sjoerg 494925944Sjoerg if (dst) *dst = ntohl(ddst); 495025944Sjoerg if (src) *src = ntohl(ssrc); 495125944Sjoerg} 495225944Sjoerg 4953184682Sbz#ifdef INET 495425944Sjoerg/* 495525944Sjoerg * Set my IP address. Must be called at splimp. 495625944Sjoerg */ 495725944Sjoergstatic void 495825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 495925944Sjoerg{ 4960183550Szec INIT_VNET_INET(curvnet); 496142104Sphk STDDCL; 496225944Sjoerg struct ifaddr *ifa; 496325944Sjoerg struct sockaddr_in *si; 496484318Sjlemon struct in_ifaddr *ia; 496525944Sjoerg 496625944Sjoerg /* 496725944Sjoerg * Pick the first AF_INET address from the list, 496825944Sjoerg * aliases don't make any sense on a p2p link anyway. 496925944Sjoerg */ 497042065Sphk si = 0; 497142065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 497240008Sjoerg { 497340008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 497440008Sjoerg { 497525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 497625944Sjoerg if (si) 497725944Sjoerg break; 497825944Sjoerg } 497940008Sjoerg } 498040008Sjoerg 498125944Sjoerg if (ifa && si) 498242104Sphk { 498342104Sphk int error; 498442104Sphk /* delete old route */ 498542104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 498642104Sphk if(debug && error) 498742104Sphk { 498842104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 498942104Sphk SPP_ARGS(ifp), error); 499042104Sphk } 499142104Sphk 499242104Sphk /* set new address */ 499325944Sjoerg si->sin_addr.s_addr = htonl(src); 499484318Sjlemon ia = ifatoia(ifa); 499584318Sjlemon LIST_REMOVE(ia, ia_hash); 499684318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 499725944Sjoerg 499842104Sphk /* add new route */ 499970199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 500042104Sphk if (debug && error) 500142104Sphk { 500242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 500342104Sphk SPP_ARGS(ifp), error); 500442104Sphk } 500542104Sphk } 500688599Sjoerg} 5007184682Sbz#endif 500878064Sume 500978064Sume#ifdef INET6 501078064Sume/* 501178064Sume * Get both IPv6 addresses. 501278064Sume */ 501378064Sumestatic void 501478064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 501578064Sume struct in6_addr *srcmask) 501678064Sume{ 5017147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 501878064Sume struct ifaddr *ifa; 501978064Sume struct sockaddr_in6 *si, *sm; 502078064Sume struct in6_addr ssrc, ddst; 502178064Sume 502278064Sume sm = NULL; 502378064Sume bzero(&ssrc, sizeof(ssrc)); 502478064Sume bzero(&ddst, sizeof(ddst)); 502578064Sume /* 502678064Sume * Pick the first link-local AF_INET6 address from the list, 502778064Sume * aliases don't make any sense on a p2p link anyway. 502878064Sume */ 5029160377Sbrooks si = 0; 5030160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 503178064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 503278064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 503378064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 503478064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 503578064Sume break; 503678064Sume } 503778064Sume if (ifa) { 503878064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 503978064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 504078064Sume if (srcmask) { 504178064Sume bcopy(&sm->sin6_addr, srcmask, 504278064Sume sizeof(*srcmask)); 504378064Sume } 504478064Sume } 504578064Sume 504678064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 504778064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 504878064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 504978064Sume } 505078064Sume 505178064Sume if (dst) 505278064Sume bcopy(&ddst, dst, sizeof(*dst)); 505378064Sume if (src) 505478064Sume bcopy(&ssrc, src, sizeof(*src)); 505570199Sjhay} 505642104Sphk 505778064Sume#ifdef IPV6CP_MYIFID_DYN 505878064Sume/* 505978064Sume * Generate random ifid. 506078064Sume */ 506178064Sumestatic void 506278064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 506378064Sume{ 506478064Sume /* TBD */ 506578064Sume} 506678064Sume 506778064Sume/* 506878064Sume * Set my IPv6 address. Must be called at splimp. 506978064Sume */ 507078064Sumestatic void 507178064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 507278064Sume{ 507378064Sume STDDCL; 507478064Sume struct ifaddr *ifa; 507578064Sume struct sockaddr_in6 *sin6; 507678064Sume 507778064Sume /* 507878064Sume * Pick the first link-local AF_INET6 address from the list, 507978064Sume * aliases don't make any sense on a p2p link anyway. 508078064Sume */ 508178064Sume 508278064Sume sin6 = NULL; 5083160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 508478064Sume { 508578064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 508678064Sume { 508778064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 508878064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 508978064Sume break; 509078064Sume } 509178064Sume } 509278064Sume 509378064Sume if (ifa && sin6) 509478064Sume { 509578064Sume int error; 509678064Sume struct sockaddr_in6 new_sin6 = *sin6; 509778064Sume 509878064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 509978064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 510078064Sume if (debug && error) 510178064Sume { 510278064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 510378064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 510478064Sume } 510578064Sume } 510678064Sume} 510778064Sume#endif 510878064Sume 510978064Sume/* 511078064Sume * Suggest a candidate address to be used by peer. 511178064Sume */ 511278064Sumestatic void 511378064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 511478064Sume{ 511578064Sume struct in6_addr myaddr; 511678064Sume struct timeval tv; 511778064Sume 511878064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 511978064Sume 512078064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 512178064Sume microtime(&tv); 512278064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 512378064Sume myaddr.s6_addr[14] ^= 0xff; 512478064Sume myaddr.s6_addr[15] ^= 0xff; 512578064Sume } else { 512678064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 512778064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 512878064Sume } 512978064Sume if (suggest) 513078064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 513178064Sume} 513278064Sume#endif /*INET6*/ 513378064Sume 513430300Sjoergstatic int 513538343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 513630300Sjoerg{ 513738343Sbde u_long subcmd; 513830300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 513988600Sjoerg struct spppreq *spr; 514088600Sjoerg int rv = 0; 514130300Sjoerg 514288600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 514388600Sjoerg return (EAGAIN); 514430300Sjoerg /* 514530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 514630300Sjoerg * Check the cmd word first before attempting to fetch all the 514730300Sjoerg * data. 514830300Sjoerg */ 514988600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 515088600Sjoerg rv = EFAULT; 515188600Sjoerg goto quit; 515288600Sjoerg } 515330300Sjoerg 515488600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 515588600Sjoerg rv = EFAULT; 515688600Sjoerg goto quit; 515788600Sjoerg } 515830300Sjoerg 515930300Sjoerg switch (subcmd) { 5160170490Smjacob case (u_long)SPPPIOGDEFS: 516188600Sjoerg if (cmd != SIOCGIFGENERIC) { 516288600Sjoerg rv = EINVAL; 516388600Sjoerg break; 516488600Sjoerg } 516530300Sjoerg /* 516630300Sjoerg * We copy over the entire current state, but clean 516730300Sjoerg * out some of the stuff we don't wanna pass up. 516830300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 516930300Sjoerg * called by any user. No need to ever get PAP or 517030300Sjoerg * CHAP secrets back to userland anyway. 517130300Sjoerg */ 517288600Sjoerg spr->defs.pp_phase = sp->pp_phase; 517388723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 517488723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 517588600Sjoerg spr->defs.lcp = sp->lcp; 517688600Sjoerg spr->defs.ipcp = sp->ipcp; 517788600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 517888600Sjoerg spr->defs.myauth = sp->myauth; 517988600Sjoerg spr->defs.hisauth = sp->hisauth; 518088600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 518188600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 518288600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 518388600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 518488550Sjoerg /* 518588550Sjoerg * Fixup the LCP timeout value to milliseconds so 518688550Sjoerg * spppcontrol doesn't need to bother about the value 518788550Sjoerg * of "hz". We do the reverse calculation below when 518888550Sjoerg * setting it. 518988550Sjoerg */ 519088600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 519188600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 519288600Sjoerg sizeof(struct spppreq)); 519388600Sjoerg break; 519430300Sjoerg 5195170490Smjacob case (u_long)SPPPIOSDEFS: 519688600Sjoerg if (cmd != SIOCSIFGENERIC) { 519788600Sjoerg rv = EINVAL; 519888600Sjoerg break; 519988600Sjoerg } 520030300Sjoerg /* 520188550Sjoerg * We have a very specific idea of which fields we 520288550Sjoerg * allow being passed back from userland, so to not 520388550Sjoerg * clobber our current state. For one, we only allow 520488550Sjoerg * setting anything if LCP is in dead or establish 520588550Sjoerg * phase. Once the authentication negotiations 520688550Sjoerg * started, the authentication settings must not be 520788550Sjoerg * changed again. (The administrator can force an 520830300Sjoerg * ifconfig down in order to get LCP back into dead 520930300Sjoerg * phase.) 521030300Sjoerg * 521130300Sjoerg * Also, we only allow for authentication parameters to be 521230300Sjoerg * specified. 521330300Sjoerg * 521430300Sjoerg * XXX Should allow to set or clear pp_flags. 521530300Sjoerg * 521630300Sjoerg * Finally, if the respective authentication protocol to 521730300Sjoerg * be used is set differently than 0, but the secret is 521830300Sjoerg * passed as all zeros, we don't trash the existing secret. 521930300Sjoerg * This allows an administrator to change the system name 522030300Sjoerg * only without clobbering the secret (which he didn't get 522130300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 522230300Sjoerg * secrets are cleared if the authentication protocol is 522388550Sjoerg * reset to 0. */ 522488550Sjoerg if (sp->pp_phase != PHASE_DEAD && 522588600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 522688600Sjoerg rv = EBUSY; 522788600Sjoerg break; 522888600Sjoerg } 522930300Sjoerg 523088600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 523188600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 523288600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 523388600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 523488600Sjoerg rv = EINVAL; 523588600Sjoerg break; 523688600Sjoerg } 523730300Sjoerg 523888600Sjoerg if (spr->defs.myauth.proto == 0) 523930300Sjoerg /* resetting myauth */ 524030300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 524130300Sjoerg else { 524230300Sjoerg /* setting/changing myauth */ 524388600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 524488600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 524588600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 524688600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 524730300Sjoerg AUTHKEYLEN); 524830300Sjoerg } 524988600Sjoerg if (spr->defs.hisauth.proto == 0) 525030300Sjoerg /* resetting hisauth */ 525130300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 525230300Sjoerg else { 525330300Sjoerg /* setting/changing hisauth */ 525488600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 525588600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 525688600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 525788600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 525888600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 525930300Sjoerg AUTHKEYLEN); 526030300Sjoerg } 526188550Sjoerg /* set LCP restart timer timeout */ 526288600Sjoerg if (spr->defs.lcp.timeout != 0) 526388600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 526488723Sjoerg /* set VJ enable and IPv6 disable flags */ 526588723Sjoerg#ifdef INET 526688723Sjoerg if (spr->defs.enable_vj) 526788723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 526888723Sjoerg else 526988723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 527088723Sjoerg#endif 527188723Sjoerg#ifdef INET6 527288723Sjoerg if (spr->defs.enable_ipv6) 527388723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 527488723Sjoerg else 527588723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 527696349Sjoerg#endif 527730300Sjoerg break; 527830300Sjoerg 527930300Sjoerg default: 528088600Sjoerg rv = EINVAL; 528130300Sjoerg } 528230300Sjoerg 528388600Sjoerg quit: 528488600Sjoerg free(spr, M_TEMP); 528588600Sjoerg 528688600Sjoerg return (rv); 528730300Sjoerg} 528830300Sjoerg 528930300Sjoergstatic void 529030300Sjoergsppp_phase_network(struct sppp *sp) 529130300Sjoerg{ 529242066Sphk STDDCL; 529330300Sjoerg int i; 529430300Sjoerg u_long mask; 529530300Sjoerg 529630300Sjoerg sp->pp_phase = PHASE_NETWORK; 529730300Sjoerg 529842066Sphk if (debug) 529942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 530042066Sphk sppp_phase_name(sp->pp_phase)); 530130300Sjoerg 530230300Sjoerg /* Notify NCPs now. */ 530330300Sjoerg for (i = 0; i < IDX_COUNT; i++) 530430300Sjoerg if ((cps[i])->flags & CP_NCP) 530530300Sjoerg (cps[i])->Open(sp); 530630300Sjoerg 530730300Sjoerg /* Send Up events to all NCPs. */ 530830300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 530988706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 531030300Sjoerg (cps[i])->Up(sp); 531130300Sjoerg 531230300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 531330300Sjoerg sppp_lcp_check_and_close(sp); 531430300Sjoerg} 531530300Sjoerg 531670199Sjhay 531725706Sjoergstatic const char * 531825944Sjoergsppp_cp_type_name(u_char type) 53194910Swollman{ 532030300Sjoerg static char buf[12]; 53214910Swollman switch (type) { 532230300Sjoerg case CONF_REQ: return "conf-req"; 532330300Sjoerg case CONF_ACK: return "conf-ack"; 532430300Sjoerg case CONF_NAK: return "conf-nak"; 532530300Sjoerg case CONF_REJ: return "conf-rej"; 532630300Sjoerg case TERM_REQ: return "term-req"; 532730300Sjoerg case TERM_ACK: return "term-ack"; 532830300Sjoerg case CODE_REJ: return "code-rej"; 532930300Sjoerg case PROTO_REJ: return "proto-rej"; 533030300Sjoerg case ECHO_REQ: return "echo-req"; 533130300Sjoerg case ECHO_REPLY: return "echo-reply"; 533230300Sjoerg case DISC_REQ: return "discard-req"; 53334910Swollman } 533444145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 533530300Sjoerg return buf; 53364910Swollman} 53374910Swollman 533825706Sjoergstatic const char * 533930300Sjoergsppp_auth_type_name(u_short proto, u_char type) 534030300Sjoerg{ 534130300Sjoerg static char buf[12]; 534230300Sjoerg switch (proto) { 534330300Sjoerg case PPP_CHAP: 534430300Sjoerg switch (type) { 534530300Sjoerg case CHAP_CHALLENGE: return "challenge"; 534630300Sjoerg case CHAP_RESPONSE: return "response"; 534730300Sjoerg case CHAP_SUCCESS: return "success"; 534830300Sjoerg case CHAP_FAILURE: return "failure"; 534930300Sjoerg } 535030300Sjoerg case PPP_PAP: 535130300Sjoerg switch (type) { 535230300Sjoerg case PAP_REQ: return "req"; 535330300Sjoerg case PAP_ACK: return "ack"; 535430300Sjoerg case PAP_NAK: return "nak"; 535530300Sjoerg } 535630300Sjoerg } 535744145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 535830300Sjoerg return buf; 535930300Sjoerg} 536030300Sjoerg 536130300Sjoergstatic const char * 536225944Sjoergsppp_lcp_opt_name(u_char opt) 53634910Swollman{ 536430300Sjoerg static char buf[12]; 536525944Sjoerg switch (opt) { 536630300Sjoerg case LCP_OPT_MRU: return "mru"; 536730300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 536830300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 536930300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 537030300Sjoerg case LCP_OPT_MAGIC: return "magic"; 537130300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 537230300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 53734910Swollman } 537444145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 537530300Sjoerg return buf; 53764910Swollman} 53774910Swollman 5378184682Sbz#ifdef INET 537925944Sjoergstatic const char * 538025944Sjoergsppp_ipcp_opt_name(u_char opt) 538125944Sjoerg{ 538230300Sjoerg static char buf[12]; 538325944Sjoerg switch (opt) { 538430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 538530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 538630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 538725944Sjoerg } 538844145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 538930300Sjoerg return buf; 539025944Sjoerg} 5391184682Sbz#endif 539225944Sjoerg 539378064Sume#ifdef INET6 539425944Sjoergstatic const char * 539578064Sumesppp_ipv6cp_opt_name(u_char opt) 539678064Sume{ 539778064Sume static char buf[12]; 539878064Sume switch (opt) { 539978064Sume case IPV6CP_OPT_IFID: return "ifid"; 540078064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 540178064Sume } 540278064Sume sprintf (buf, "0x%x", opt); 540378064Sume return buf; 540478064Sume} 540578064Sume#endif 540678064Sume 540778064Sumestatic const char * 540825944Sjoergsppp_state_name(int state) 540925944Sjoerg{ 541025944Sjoerg switch (state) { 541125944Sjoerg case STATE_INITIAL: return "initial"; 541225944Sjoerg case STATE_STARTING: return "starting"; 541325944Sjoerg case STATE_CLOSED: return "closed"; 541425944Sjoerg case STATE_STOPPED: return "stopped"; 541525944Sjoerg case STATE_CLOSING: return "closing"; 541625944Sjoerg case STATE_STOPPING: return "stopping"; 541725944Sjoerg case STATE_REQ_SENT: return "req-sent"; 541825944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 541925944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 542025944Sjoerg case STATE_OPENED: return "opened"; 542125944Sjoerg } 542225944Sjoerg return "illegal"; 542325944Sjoerg} 542425944Sjoerg 542525944Sjoergstatic const char * 542625944Sjoergsppp_phase_name(enum ppp_phase phase) 542725944Sjoerg{ 542825944Sjoerg switch (phase) { 542925944Sjoerg case PHASE_DEAD: return "dead"; 543025944Sjoerg case PHASE_ESTABLISH: return "establish"; 543125944Sjoerg case PHASE_TERMINATE: return "terminate"; 543225944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 543325944Sjoerg case PHASE_NETWORK: return "network"; 543425944Sjoerg } 543525944Sjoerg return "illegal"; 543625944Sjoerg} 543725944Sjoerg 543825944Sjoergstatic const char * 543925944Sjoergsppp_proto_name(u_short proto) 544025944Sjoerg{ 544125944Sjoerg static char buf[12]; 544225944Sjoerg switch (proto) { 544325944Sjoerg case PPP_LCP: return "lcp"; 544425944Sjoerg case PPP_IPCP: return "ipcp"; 544530300Sjoerg case PPP_PAP: return "pap"; 544630300Sjoerg case PPP_CHAP: return "chap"; 544778064Sume case PPP_IPV6CP: return "ipv6cp"; 544825944Sjoerg } 544944145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 545025944Sjoerg return buf; 545125944Sjoerg} 545225944Sjoerg 545312820Sphkstatic void 545430300Sjoergsppp_print_bytes(const u_char *p, u_short len) 54554910Swollman{ 545644145Sphk if (len) 545769211Sphk log(-1, " %*D", len, p, "-"); 54584910Swollman} 545925944Sjoerg 546030300Sjoergstatic void 546130300Sjoergsppp_print_string(const char *p, u_short len) 546230300Sjoerg{ 546330300Sjoerg u_char c; 546430300Sjoerg 546530300Sjoerg while (len-- > 0) { 546630300Sjoerg c = *p++; 546730300Sjoerg /* 546830300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 546930300Sjoerg * using only them, but we don't rely on it. */ 547030300Sjoerg if (c < ' ' || c > '~') 547169211Sphk log(-1, "\\x%x", c); 547230300Sjoerg else 547369211Sphk log(-1, "%c", c); 547430300Sjoerg } 547530300Sjoerg} 547630300Sjoerg 5477184682Sbz#ifdef INET 547830300Sjoergstatic const char * 547930300Sjoergsppp_dotted_quad(u_long addr) 548030300Sjoerg{ 548130300Sjoerg static char s[16]; 548230300Sjoerg sprintf(s, "%d.%d.%d.%d", 548340008Sjoerg (int)((addr >> 24) & 0xff), 548440008Sjoerg (int)((addr >> 16) & 0xff), 548540008Sjoerg (int)((addr >> 8) & 0xff), 548638372Sbde (int)(addr & 0xff)); 548730300Sjoerg return s; 548830300Sjoerg} 5489184682Sbz#endif 549030300Sjoerg 549130300Sjoergstatic int 549230300Sjoergsppp_strnlen(u_char *p, int max) 549330300Sjoerg{ 549430300Sjoerg int len; 549530300Sjoerg 549630300Sjoerg for (len = 0; len < max && *p; ++p) 549730300Sjoerg ++len; 549830300Sjoerg return len; 549930300Sjoerg} 550030300Sjoerg 550130300Sjoerg/* a dummy, used to drop uninteresting events */ 550230300Sjoergstatic void 550330300Sjoergsppp_null(struct sppp *unused) 550430300Sjoerg{ 550530300Sjoerg /* do just nothing */ 550630300Sjoerg} 5507