if_spppsubr.c revision 161556
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 161556 2006-08-23 22:06:08Z cperciva $ 224910Swollman */ 234910Swollman 2440008Sjoerg#include <sys/param.h> 2540008Sjoerg 2642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2732350Seivind#include "opt_inet.h" 2854263Sshin#include "opt_inet6.h" 2931742Seivind#include "opt_ipx.h" 3040008Sjoerg#endif 3131742Seivind 3240008Sjoerg#ifdef NetBSD1_3 3340008Sjoerg# if NetBSD1_3 > 6 3440008Sjoerg# include "opt_inet.h" 3554263Sshin# include "opt_inet6.h" 3640008Sjoerg# include "opt_iso.h" 3740008Sjoerg# endif 3840008Sjoerg#endif 3940008Sjoerg 404952Sbde#include <sys/systm.h> 414952Sbde#include <sys/kernel.h> 4270199Sjhay#include <sys/module.h> 4324204Sbde#include <sys/sockio.h> 444910Swollman#include <sys/socket.h> 4525706Sjoerg#include <sys/syslog.h> 4642104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4759604Sobrien#include <sys/random.h> 4842104Sphk#endif 4929024Sbde#include <sys/malloc.h> 504910Swollman#include <sys/mbuf.h> 5140008Sjoerg 5240008Sjoerg#if defined (__OpenBSD__) 5340008Sjoerg#include <sys/md5k.h> 5440008Sjoerg#else 5530300Sjoerg#include <sys/md5.h> 5640008Sjoerg#endif 574910Swollman 584910Swollman#include <net/if.h> 594910Swollman#include <net/netisr.h> 604910Swollman#include <net/if_types.h> 6142104Sphk#include <net/route.h> 6288534Sjoerg#include <netinet/in.h> 6388534Sjoerg#include <netinet/in_systm.h> 6488534Sjoerg#include <netinet/ip.h> 6588534Sjoerg#include <net/slcompress.h> 664910Swollman 6740008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6840008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6940008Sjoerg#endif 7042104Sphk 7130300Sjoerg#include <machine/stdarg.h> 7230300Sjoerg 734910Swollman#include <netinet/in_var.h> 7488705Sjoerg 7588705Sjoerg#ifdef INET 764910Swollman#include <netinet/ip.h> 774910Swollman#include <netinet/tcp.h> 784910Swollman#endif 794910Swollman 80148385Sume#ifdef INET6 81148385Sume#include <netinet6/scope6_var.h> 82148385Sume#endif 83148385Sume 8488705Sjoerg#if defined (__FreeBSD__) || defined (__OpenBSD__) 8588705Sjoerg# include <netinet/if_ether.h> 8688705Sjoerg#else 8788705Sjoerg# include <net/ethertypes.h> 8888705Sjoerg#endif 8988705Sjoerg 9011819Sjulian#ifdef IPX 9111819Sjulian#include <netipx/ipx.h> 9211819Sjulian#include <netipx/ipx_if.h> 9311819Sjulian#endif 9411819Sjulian 954910Swollman#include <net/if_sppp.h> 964910Swollman 9742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9842104Sphk# define IOCTL_CMD_T u_long 9940008Sjoerg#else 10042104Sphk# define IOCTL_CMD_T int 10140008Sjoerg#endif 10242104Sphk 1034910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1044910Swollman 10525944Sjoerg/* 10625944Sjoerg * Interface flags that can be set in an ifconfig command. 10725944Sjoerg * 10825955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 10925944Sjoerg * as being administrative openable, but won't be opened to begin 11025944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11125944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11225955Sjoerg * 11325955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11425955Sjoerg * arrive to be sent. 11530300Sjoerg * 11630300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11730300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 11830300Sjoerg * like 11930300Sjoerg * 12030300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12130300Sjoerg * 12230300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12330300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12425944Sjoerg */ 12525944Sjoerg 12625955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12725955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 12845152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 12925944Sjoerg 13030300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13130300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13230300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13330300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13430300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13530300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 13688534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 13788534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 13878064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 13930300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14030300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14130300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14230300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 14378064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1444910Swollman 14525944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 14625944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 14725944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 14825944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 14925944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 15025944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 15125944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15225944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15325944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15425944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15525944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1564910Swollman 15730300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 15830300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 15930300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 16030300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 16130300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16230300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16330300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16430300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1654910Swollman 16625944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 16725944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 16825944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1694910Swollman 17078064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 17178064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 17278064Sume 17388534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 17488534Sjoerg 17530300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 17630300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17730300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1784910Swollman 17930300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 18030300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 18130300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18230300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18330300Sjoerg 18430300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18530300Sjoerg 18630300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18730300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18830300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18930300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 19030300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 19130300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19230300Sjoerg 19325944Sjoerg/* states are named and numbered according to RFC 1661 */ 19425944Sjoerg#define STATE_INITIAL 0 19525944Sjoerg#define STATE_STARTING 1 19625944Sjoerg#define STATE_CLOSED 2 19725944Sjoerg#define STATE_STOPPED 3 19825944Sjoerg#define STATE_CLOSING 4 19925944Sjoerg#define STATE_STOPPING 5 20025944Sjoerg#define STATE_REQ_SENT 6 20125944Sjoerg#define STATE_ACK_RCVD 7 20225944Sjoerg#define STATE_ACK_SENT 8 20325944Sjoerg#define STATE_OPENED 9 20425944Sjoerg 205147256SbrooksMALLOC_DEFINE(M_SPPP, "sppp", "synchronous PPP interface internals"); 206147256Sbrooks 2074910Swollmanstruct ppp_header { 20811189Sjkh u_char address; 20911189Sjkh u_char control; 21011189Sjkh u_short protocol; 211103842Salfred} __packed; 2124910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2134910Swollman 2144910Swollmanstruct lcp_header { 21511189Sjkh u_char type; 21611189Sjkh u_char ident; 21711189Sjkh u_short len; 218103842Salfred} __packed; 2194910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2204910Swollman 2214910Swollmanstruct cisco_packet { 22211189Sjkh u_long type; 22311189Sjkh u_long par1; 22411189Sjkh u_long par2; 22511189Sjkh u_short rel; 22611189Sjkh u_short time0; 22711189Sjkh u_short time1; 228103842Salfred} __packed; 22988704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 2304910Swollman 23125944Sjoerg/* 23225944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 23325944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23425944Sjoerg * case you can't make sense out of these abbreviation; it will also 23525944Sjoerg * explain the semantics related to the various events and actions. 23625944Sjoerg */ 23725944Sjoergstruct cp { 23825944Sjoerg u_short proto; /* PPP control protocol number */ 23925944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 24025944Sjoerg u_char flags; 24125944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 24225944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 24325944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24425944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24525944Sjoerg const char *name; /* name of this control protocol */ 24625944Sjoerg /* event handlers */ 24725944Sjoerg void (*Up)(struct sppp *sp); 24825944Sjoerg void (*Down)(struct sppp *sp); 24925944Sjoerg void (*Open)(struct sppp *sp); 25025944Sjoerg void (*Close)(struct sppp *sp); 25125944Sjoerg void (*TO)(void *sp); 25225944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 25325944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25425944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25525944Sjoerg /* actions */ 25625944Sjoerg void (*tlu)(struct sppp *sp); 25725944Sjoerg void (*tld)(struct sppp *sp); 25825944Sjoerg void (*tls)(struct sppp *sp); 25925944Sjoerg void (*tlf)(struct sppp *sp); 26025944Sjoerg void (*scr)(struct sppp *sp); 26125944Sjoerg}; 26225944Sjoerg 263121816Sbrooks#if defined(__FreeBSD__) && __FreeBSD__ >= 3 && __FreeBSD_version < 501113 26440008Sjoerg#define SPP_FMT "%s%d: " 26540008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26640008Sjoerg#else 26740008Sjoerg#define SPP_FMT "%s: " 26840008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 26940008Sjoerg#endif 27040008Sjoerg 271138745Srik#define SPPP_LOCK(sp) \ 272138745Srik do { \ 273147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 274138745Srik mtx_lock (&(sp)->mtx); \ 275138745Srik } while (0) 276138745Srik#define SPPP_UNLOCK(sp) \ 277138745Srik do { \ 278147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 279138745Srik mtx_unlock (&(sp)->mtx); \ 280138745Srik } while (0) 281138745Srik 282138745Srik#define SPPP_LOCK_ASSERT(sp) \ 283138745Srik do { \ 284147256Sbrooks if (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT)) \ 285138745Srik mtx_assert (&(sp)->mtx, MA_OWNED); \ 286138745Srik } while (0) 287138745Srik#define SPPP_LOCK_OWNED(sp) \ 288147256Sbrooks (!(SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) && \ 289138745Srik mtx_owned (&sp->mtx)) 290138745Srik 29188705Sjoerg#ifdef INET 2924910Swollman/* 2934910Swollman * The following disgusting hack gets around the problem that IP TOS 2944910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2954910Swollman * priority queue. To decide if traffic is interactive, we check that 2964910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 29730300Sjoerg * 29830300Sjoerg * XXX is this really still necessary? - joerg - 2994910Swollman */ 300126910Srwatsonstatic const u_short interactive_ports[8] = { 3014910Swollman 0, 513, 0, 0, 3024910Swollman 0, 21, 0, 23, 3034910Swollman}; 3044910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 30588705Sjoerg#endif 3064910Swollman 30725944Sjoerg/* almost every function needs these */ 30825944Sjoerg#define STDDCL \ 309147256Sbrooks struct ifnet *ifp = SP2IFP(sp); \ 31025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 31111189Sjkh 31230300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 31325944Sjoerg struct sockaddr *dst, struct rtentry *rt); 3144910Swollman 31525944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 31625944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 31725944Sjoerg 31825944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 31925944Sjoerg struct mbuf *m); 32025944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 32125944Sjoerg u_char ident, u_short len, void *data); 32242104Sphk/* static void sppp_cp_timeout(void *arg); */ 32325944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 32425944Sjoerg int newstate); 32530300Sjoergstatic void sppp_auth_send(const struct cp *cp, 32642104Sphk struct sppp *sp, unsigned int type, unsigned int id, 32730300Sjoerg ...); 32825944Sjoerg 32925944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 33025944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 33125944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 33225944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 33325944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 33425944Sjoerg 33530300Sjoergstatic void sppp_null(struct sppp *sp); 33630300Sjoerg 337138745Srikstatic void sppp_pp_up(struct sppp *sp); 338138745Srikstatic void sppp_pp_down(struct sppp *sp); 339138745Srik 34025944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 34125944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 34225944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 34325944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 34425944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 34525944Sjoergstatic void sppp_lcp_TO(void *sp); 34625944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34725944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34825944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34925944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 35025944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 35125944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 35225944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 35325944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 35430300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 35530300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 35625944Sjoerg 35725944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 35825944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 35925944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 36025944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 36125944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 36225944Sjoergstatic void sppp_ipcp_TO(void *sp); 36325944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 36425944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 36525944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 36625944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 36725944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 36825944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 36925944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 37025944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 37125944Sjoerg 37278064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 37378064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 37478064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 37578064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 37678064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 37778064Sumestatic void sppp_ipv6cp_TO(void *sp); 37878064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 37978064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 38078064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 38178064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 38278064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 38378064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 38478064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 38578064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 38678064Sume 38730300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 38830300Sjoergstatic void sppp_pap_init(struct sppp *sp); 38930300Sjoergstatic void sppp_pap_open(struct sppp *sp); 39030300Sjoergstatic void sppp_pap_close(struct sppp *sp); 39130300Sjoergstatic void sppp_pap_TO(void *sp); 39230300Sjoergstatic void sppp_pap_my_TO(void *sp); 39330300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 39430300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 39530300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 39630300Sjoerg 39730300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 39830300Sjoergstatic void sppp_chap_init(struct sppp *sp); 39930300Sjoergstatic void sppp_chap_open(struct sppp *sp); 40030300Sjoergstatic void sppp_chap_close(struct sppp *sp); 40130300Sjoergstatic void sppp_chap_TO(void *sp); 40230300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 40330300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 40430300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 40530300Sjoerg 40630300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 40725944Sjoergstatic const char *sppp_cp_type_name(u_char type); 40830300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 40930300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 41078064Sume#ifdef INET6 41178064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 41278064Sume#endif 41325944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 41425944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 41525944Sjoergstatic const char *sppp_proto_name(u_short proto); 41630300Sjoergstatic const char *sppp_state_name(int state); 41738343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 41830300Sjoergstatic int sppp_strnlen(u_char *p, int max); 41925944Sjoergstatic void sppp_keepalive(void *dummy); 42030300Sjoergstatic void sppp_phase_network(struct sppp *sp); 42130300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 42230300Sjoergstatic void sppp_print_string(const char *p, u_short len); 42325944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 42425944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 42578064Sume#ifdef INET6 42678064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 42778064Sume struct in6_addr *dst, struct in6_addr *srcmask); 42878064Sume#ifdef IPV6CP_MYIFID_DYN 42978064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 43078064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 43178064Sume#endif 43278064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 43378064Sume#endif 43425944Sjoerg 435138745Srik/* if_start () wrapper */ 436138745Srikstatic void sppp_ifstart (struct ifnet *ifp); 437138745Srik 43825944Sjoerg/* our control protocol descriptors */ 43933181Seivindstatic const struct cp lcp = { 44025944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 44125944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 44225944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 44325944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 44425944Sjoerg sppp_lcp_scr 44525944Sjoerg}; 44625944Sjoerg 44733181Seivindstatic const struct cp ipcp = { 44888709Sjoerg PPP_IPCP, IDX_IPCP, 44988709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 45088709Sjoerg CP_NCP, 45188709Sjoerg#else 45288709Sjoerg 0, 45388709Sjoerg#endif 45488709Sjoerg "ipcp", 45525944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 45625944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 45725944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 45825944Sjoerg sppp_ipcp_scr 45925944Sjoerg}; 46025944Sjoerg 46178064Sumestatic const struct cp ipv6cp = { 46278064Sume PPP_IPV6CP, IDX_IPV6CP, 46378064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 46478064Sume CP_NCP, 46578064Sume#else 46678064Sume 0, 46778064Sume#endif 46878064Sume "ipv6cp", 46978064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 47078064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 47178064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 47278064Sume sppp_ipv6cp_scr 47378064Sume}; 47478064Sume 47533181Seivindstatic const struct cp pap = { 47630300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 47730300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 47830300Sjoerg sppp_pap_TO, 0, 0, 0, 47930300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 48030300Sjoerg sppp_pap_scr 48130300Sjoerg}; 48230300Sjoerg 48333181Seivindstatic const struct cp chap = { 48430300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 48530300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 48630300Sjoerg sppp_chap_TO, 0, 0, 0, 48730300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 48830300Sjoerg sppp_chap_scr 48930300Sjoerg}; 49030300Sjoerg 49133181Seivindstatic const struct cp *cps[IDX_COUNT] = { 49225944Sjoerg &lcp, /* IDX_LCP */ 49325944Sjoerg &ipcp, /* IDX_IPCP */ 49478064Sume &ipv6cp, /* IDX_IPV6CP */ 49530300Sjoerg &pap, /* IDX_PAP */ 49630300Sjoerg &chap, /* IDX_CHAP */ 49725944Sjoerg}; 49825944Sjoerg 499147256Sbrooksstatic void* 500147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp) 501147256Sbrooks{ 502147256Sbrooks struct sppp *sp; 503147256Sbrooks 504147256Sbrooks sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO); 505147256Sbrooks sp->pp_ifp = ifp; 506147256Sbrooks 507147256Sbrooks return (sp); 508147256Sbrooks} 509147256Sbrooks 510147256Sbrooksstatic void 511147256Sbrookssppp_free(void *com, u_char type) 512147256Sbrooks{ 513147256Sbrooks 514147256Sbrooks free(com, M_SPPP); 515147256Sbrooks} 516147256Sbrooks 51770199Sjhaystatic int 51870199Sjhaysppp_modevent(module_t mod, int type, void *unused) 51970199Sjhay{ 52070199Sjhay switch (type) { 52170199Sjhay case MOD_LOAD: 522147256Sbrooks /* 523147256Sbrooks * XXX: should probably be IFT_SPPP, but it's fairly 524147256Sbrooks * harmless to allocate struct sppp's for non-sppp 525147256Sbrooks * interfaces. 526147256Sbrooks */ 527147256Sbrooks 528147256Sbrooks if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free); 52970199Sjhay break; 53070199Sjhay case MOD_UNLOAD: 531147256Sbrooks /* if_deregister_com_alloc(IFT_PPP); */ 53270199Sjhay return EACCES; 53370199Sjhay default: 534132199Sphk return EOPNOTSUPP; 53570199Sjhay } 53670199Sjhay return 0; 53770199Sjhay} 53870199Sjhaystatic moduledata_t spppmod = { 53970199Sjhay "sppp", 54070199Sjhay sppp_modevent, 54170199Sjhay 0 54270199Sjhay}; 54370199SjhayMODULE_VERSION(sppp, 1); 54470199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 54525944Sjoerg 54670199Sjhay/* 54725944Sjoerg * Exported functions, comprising our interface to the lower layer. 5484910Swollman */ 5494910Swollman 5504910Swollman/* 5514910Swollman * Process the received packet. 5524910Swollman */ 55325706Sjoergvoid 55425706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5554910Swollman{ 5564910Swollman struct ppp_header *h; 557111888Sjlemon int isr = -1; 558147256Sbrooks struct sppp *sp = IFP2SP(ifp); 55988700Sjoerg u_char *iphdr; 56088700Sjoerg int hlen, vjlen, do_account = 0; 561138745Srik int debug; 5624910Swollman 563138745Srik SPPP_LOCK(sp); 564138745Srik debug = ifp->if_flags & IFF_DEBUG; 565138745Srik 5664910Swollman if (ifp->if_flags & IFF_UP) 5674910Swollman /* Count received bytes, add FCS and one flag */ 5684910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5694910Swollman 5704910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5714910Swollman /* Too small packet, drop it. */ 57225944Sjoerg if (debug) 57325706Sjoerg log(LOG_DEBUG, 57440008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 57540008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 57625944Sjoerg drop: 57788700Sjoerg m_freem (m); 578138745Srik SPPP_UNLOCK(sp); 57988700Sjoerg drop2: 58025944Sjoerg ++ifp->if_ierrors; 58125944Sjoerg ++ifp->if_iqdrops; 5824910Swollman return; 5834910Swollman } 5844910Swollman 585139365Srik if (sp->pp_mode == PP_FR) { 586139365Srik sppp_fr_input (sp, m); 587139365Srik SPPP_UNLOCK(sp); 588139365Srik return; 589139365Srik } 590139365Srik 5914910Swollman /* Get PPP header. */ 5924910Swollman h = mtod (m, struct ppp_header*); 5934910Swollman m_adj (m, PPP_HEADER_LEN); 5944910Swollman 5954910Swollman switch (h->address) { 5964910Swollman case PPP_ALLSTATIONS: 5974910Swollman if (h->control != PPP_UI) 5984910Swollman goto invalid; 59945152Sphk if (sp->pp_mode == IFF_CISCO) { 60025944Sjoerg if (debug) 60125706Sjoerg log(LOG_DEBUG, 60240008Sjoerg SPP_FMT "PPP packet in Cisco mode " 60325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 60440008Sjoerg SPP_ARGS(ifp), 60525706Sjoerg h->address, h->control, ntohs(h->protocol)); 60611189Sjkh goto drop; 60711189Sjkh } 6084910Swollman switch (ntohs (h->protocol)) { 6094910Swollman default: 61025944Sjoerg if (debug) 61125706Sjoerg log(LOG_DEBUG, 61244145Sphk SPP_FMT "rejecting protocol " 61325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 61440008Sjoerg SPP_ARGS(ifp), 61525706Sjoerg h->address, h->control, ntohs(h->protocol)); 61644145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 61744145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 61878064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 61944145Sphk &h->protocol); 6204910Swollman ++ifp->if_noproto; 6214910Swollman goto drop; 6224910Swollman case PPP_LCP: 62330300Sjoerg sppp_cp_input(&lcp, sp, m); 6244910Swollman m_freem (m); 625138745Srik SPPP_UNLOCK(sp); 6264910Swollman return; 62730300Sjoerg case PPP_PAP: 62830300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 62930300Sjoerg sppp_pap_input(sp, m); 63030300Sjoerg m_freem (m); 631138745Srik SPPP_UNLOCK(sp); 63230300Sjoerg return; 63330300Sjoerg case PPP_CHAP: 63430300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 63530300Sjoerg sppp_chap_input(sp, m); 63630300Sjoerg m_freem (m); 637138745Srik SPPP_UNLOCK(sp); 63830300Sjoerg return; 6394910Swollman#ifdef INET 6404910Swollman case PPP_IPCP: 64125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 64230300Sjoerg sppp_cp_input(&ipcp, sp, m); 6434910Swollman m_freem (m); 644138745Srik SPPP_UNLOCK(sp); 6454910Swollman return; 6464910Swollman case PPP_IP: 64725944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 648111888Sjlemon isr = NETISR_IP; 6494910Swollman } 65088577Sjoerg do_account++; 6514910Swollman break; 65288534Sjoerg case PPP_VJ_COMP: 65388534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 65488700Sjoerg if ((vjlen = 65588700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 65688700Sjoerg m->m_len, m->m_len, 65788700Sjoerg TYPE_COMPRESSED_TCP, 65888700Sjoerg sp->pp_comp, 65988700Sjoerg &iphdr, &hlen)) <= 0) { 66088700Sjoerg if (debug) 66188700Sjoerg log(LOG_INFO, 66288700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 66388700Sjoerg SPP_ARGS(ifp)); 66488534Sjoerg goto drop; 66588700Sjoerg } 66688700Sjoerg 66788700Sjoerg /* 66888700Sjoerg * Trim the VJ header off the packet, and prepend 66988700Sjoerg * the uncompressed IP header (which will usually 67088700Sjoerg * end up in two chained mbufs since there's not 67188700Sjoerg * enough leading space in the existing mbuf). 67288700Sjoerg */ 67388700Sjoerg m_adj(m, vjlen); 674111119Simp M_PREPEND(m, hlen, M_DONTWAIT); 675138745Srik if (m == NULL) { 676138745Srik SPPP_UNLOCK(sp); 67788700Sjoerg goto drop2; 678138745Srik } 67988700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 680111888Sjlemon isr = NETISR_IP; 68188534Sjoerg } 68288599Sjoerg do_account++; 68388534Sjoerg break; 68488534Sjoerg case PPP_VJ_UCOMP: 68588534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 68688700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 68788700Sjoerg m->m_len, m->m_len, 68888700Sjoerg TYPE_UNCOMPRESSED_TCP, 68988700Sjoerg sp->pp_comp, 69088700Sjoerg &iphdr, &hlen) != 0) { 69188700Sjoerg if (debug) 69288700Sjoerg log(LOG_INFO, 69388700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 69488700Sjoerg SPP_ARGS(ifp)); 69588534Sjoerg goto drop; 69688700Sjoerg } 697111888Sjlemon isr = NETISR_IP; 69888534Sjoerg } 69988599Sjoerg do_account++; 70088534Sjoerg break; 70178064Sume#endif 70288599Sjoerg#ifdef INET6 70388599Sjoerg case PPP_IPV6CP: 70488599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 70588599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 70688599Sjoerg m_freem (m); 707138745Srik SPPP_UNLOCK(sp); 70888599Sjoerg return; 70988599Sjoerg 71088599Sjoerg case PPP_IPV6: 711111888Sjlemon if (sp->state[IDX_IPV6CP] == STATE_OPENED) 712111888Sjlemon isr = NETISR_IPV6; 71388599Sjoerg do_account++; 71488599Sjoerg break; 71588599Sjoerg#endif 71612495Speter#ifdef IPX 71712495Speter case PPP_IPX: 71812495Speter /* IPX IPXCP not implemented yet */ 719111888Sjlemon if (sp->pp_phase == PHASE_NETWORK) 720111888Sjlemon isr = NETISR_IPX; 72188577Sjoerg do_account++; 72212495Speter break; 72312495Speter#endif 7244910Swollman } 7254910Swollman break; 7264910Swollman case CISCO_MULTICAST: 7274910Swollman case CISCO_UNICAST: 7284910Swollman /* Don't check the control field here (RFC 1547). */ 72945152Sphk if (sp->pp_mode != IFF_CISCO) { 73025944Sjoerg if (debug) 73125706Sjoerg log(LOG_DEBUG, 73240008Sjoerg SPP_FMT "Cisco packet in PPP mode " 73325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 73440008Sjoerg SPP_ARGS(ifp), 73525706Sjoerg h->address, h->control, ntohs(h->protocol)); 73611189Sjkh goto drop; 73711189Sjkh } 7384910Swollman switch (ntohs (h->protocol)) { 7394910Swollman default: 7404910Swollman ++ifp->if_noproto; 7414910Swollman goto invalid; 7424910Swollman case CISCO_KEEPALIVE: 743147256Sbrooks sppp_cisco_input (sp, m); 7444910Swollman m_freem (m); 745138745Srik SPPP_UNLOCK(sp); 7464910Swollman return; 7474910Swollman#ifdef INET 7484910Swollman case ETHERTYPE_IP: 749111888Sjlemon isr = NETISR_IP; 75088577Sjoerg do_account++; 7514910Swollman break; 7524910Swollman#endif 75354263Sshin#ifdef INET6 75454263Sshin case ETHERTYPE_IPV6: 755111888Sjlemon isr = NETISR_IPV6; 75688577Sjoerg do_account++; 75754263Sshin break; 75854263Sshin#endif 75912495Speter#ifdef IPX 76012495Speter case ETHERTYPE_IPX: 761111888Sjlemon isr = NETISR_IPX; 76288577Sjoerg do_account++; 76312495Speter break; 76412495Speter#endif 7654910Swollman } 7664910Swollman break; 76725944Sjoerg default: /* Invalid PPP packet. */ 76825944Sjoerg invalid: 76925944Sjoerg if (debug) 77025944Sjoerg log(LOG_DEBUG, 77140008Sjoerg SPP_FMT "invalid input packet " 77225944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 77340008Sjoerg SPP_ARGS(ifp), 77425944Sjoerg h->address, h->control, ntohs(h->protocol)); 77525944Sjoerg goto drop; 7764910Swollman } 7774910Swollman 778111888Sjlemon if (! (ifp->if_flags & IFF_UP) || isr == -1) 7794910Swollman goto drop; 7804910Swollman 781138745Srik SPPP_UNLOCK(sp); 7824910Swollman /* Check queue. */ 783134391Sandre if (netisr_queue(isr, m)) { /* (0) on success. */ 78425944Sjoerg if (debug) 78540008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 78640008Sjoerg SPP_ARGS(ifp)); 787131241Srik goto drop2; 7884910Swollman } 789138745Srik 79088577Sjoerg if (do_account) 79188577Sjoerg /* 79288577Sjoerg * Do only account for network packets, not for control 79388577Sjoerg * packets. This is used by some subsystems to detect 79488577Sjoerg * idle lines. 79588577Sjoerg */ 796150349Sandre sp->pp_last_recv = time_uptime; 7974910Swollman} 7984910Swollman 799138745Srikstatic void 800138745Sriksppp_ifstart_sched(void *dummy) 801138745Srik{ 802138745Srik struct sppp *sp = dummy; 803138745Srik 804147256Sbrooks sp->if_start(SP2IFP(sp)); 805138745Srik} 806138745Srik 807138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for 808138745Srik * execution. We can't call it directly 809138745Srik */ 810138745Srikstatic void 811138745Sriksppp_ifstart(struct ifnet *ifp) 812138745Srik{ 813147256Sbrooks struct sppp *sp = IFP2SP(ifp); 814138745Srik 815138745Srik if (SPPP_LOCK_OWNED(sp)) { 816138745Srik if (callout_pending(&sp->ifstart_callout)) 817138745Srik return; 818138745Srik callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched, 819138745Srik (void *)sp); 820138745Srik } else { 821138745Srik sp->if_start(ifp); 822138745Srik } 823138745Srik} 824138745Srik 8254910Swollman/* 8264910Swollman * Enqueue transmit packet. 8274910Swollman */ 82812820Sphkstatic int 82925706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 83025706Sjoerg struct sockaddr *dst, struct rtentry *rt) 8314910Swollman{ 832147256Sbrooks struct sppp *sp = IFP2SP(ifp); 8334910Swollman struct ppp_header *h; 83478064Sume struct ifqueue *ifq = NULL; 835130549Smlaier int s, error, rv = 0; 83688534Sjoerg int ipproto = PPP_IP; 83742066Sphk int debug = ifp->if_flags & IFF_DEBUG; 8384910Swollman 83925944Sjoerg s = splimp(); 840138745Srik SPPP_LOCK(sp); 84125944Sjoerg 842148887Srwatson if (!(ifp->if_flags & IFF_UP) || 843148887Srwatson (!(ifp->if_flags & IFF_AUTO) && 844148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING))) { 84588723Sjoerg#ifdef INET6 84688723Sjoerg drop: 84788723Sjoerg#endif 8484910Swollman m_freem (m); 849138745Srik SPPP_UNLOCK(sp); 8504910Swollman splx (s); 8514910Swollman return (ENETDOWN); 8524910Swollman } 8534910Swollman 854148887Srwatson if ((ifp->if_flags & IFF_AUTO) && 855148887Srwatson !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 85688723Sjoerg#ifdef INET6 85725944Sjoerg /* 85888723Sjoerg * XXX 85988723Sjoerg * 86088723Sjoerg * Hack to prevent the initialization-time generated 86188723Sjoerg * IPv6 multicast packet to erroneously cause a 86288723Sjoerg * dialout event in case IPv6 has been 86388723Sjoerg * administratively disabled on that interface. 86488723Sjoerg */ 86588723Sjoerg if (dst->sa_family == AF_INET6 && 86688723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 86788723Sjoerg goto drop; 86888723Sjoerg#endif 86988723Sjoerg /* 87025944Sjoerg * Interface is not yet running, but auto-dial. Need 87125944Sjoerg * to start LCP for it. 87225944Sjoerg */ 873148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 87425944Sjoerg splx(s); 87525944Sjoerg lcp.Open(sp); 87625944Sjoerg s = splimp(); 87725944Sjoerg } 87825944Sjoerg 8794910Swollman#ifdef INET 88012436Speter if (dst->sa_family == AF_INET) { 88140008Sjoerg /* XXX Check mbuf length here? */ 88212436Speter struct ip *ip = mtod (m, struct ip*); 88312436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8844910Swollman 88542104Sphk /* 88642104Sphk * When using dynamic local IP address assignment by using 88742104Sphk * 0.0.0.0 as a local address, the first TCP session will 88842104Sphk * not connect because the local TCP checksum is computed 88942104Sphk * using 0.0.0.0 which will later become our real IP address 89042104Sphk * so the TCP checksum computed at the remote end will 89142104Sphk * become invalid. So we 89242104Sphk * - don't let packets with src ip addr 0 thru 89342104Sphk * - we flag TCP packets with src ip 0 as an error 89470199Sjhay */ 89542104Sphk 89642104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 89742104Sphk { 89842104Sphk m_freem(m); 899138745Srik SPPP_UNLOCK(sp); 90042104Sphk splx(s); 90142104Sphk if(ip->ip_p == IPPROTO_TCP) 90242104Sphk return(EADDRNOTAVAIL); 90342104Sphk else 90442104Sphk return(0); 90542104Sphk } 90670199Sjhay 90742104Sphk /* 90842104Sphk * Put low delay, telnet, rlogin and ftp control packets 909130549Smlaier * in front of the queue or let ALTQ take care. 91042104Sphk */ 911130549Smlaier if (ALTQ_IS_ENABLED(&ifp->if_snd)) 91241686Sphk ; 913130549Smlaier else if (_IF_QFULL(&sp->pp_fastq)) 914130549Smlaier ; 91541686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 91612436Speter ifq = &sp->pp_fastq; 91741686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 91841686Sphk ; 91941686Sphk else if (ip->ip_p != IPPROTO_TCP) 92041686Sphk ; 92141686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 92241686Sphk ifq = &sp->pp_fastq; 92341686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 92441686Sphk ifq = &sp->pp_fastq; 92588534Sjoerg 92688534Sjoerg /* 92788534Sjoerg * Do IP Header compression 92888534Sjoerg */ 929139365Srik if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR && 930138745Srik (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP) 93188599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 93288534Sjoerg sp->ipcp.compress_cid)) { 93388534Sjoerg case TYPE_COMPRESSED_TCP: 93488534Sjoerg ipproto = PPP_VJ_COMP; 93588534Sjoerg break; 93688534Sjoerg case TYPE_UNCOMPRESSED_TCP: 93788534Sjoerg ipproto = PPP_VJ_UCOMP; 93888534Sjoerg break; 93988534Sjoerg case TYPE_IP: 94088534Sjoerg ipproto = PPP_IP; 94188534Sjoerg break; 94288534Sjoerg default: 94388534Sjoerg m_freem(m); 944138745Srik SPPP_UNLOCK(sp); 94588534Sjoerg splx(s); 94688534Sjoerg return (EINVAL); 94788534Sjoerg } 9484910Swollman } 9494910Swollman#endif 9504910Swollman 95178064Sume#ifdef INET6 95278064Sume if (dst->sa_family == AF_INET6) { 95378064Sume /* XXX do something tricky here? */ 95478064Sume } 95578064Sume#endif 95678064Sume 957139365Srik if (sp->pp_mode == PP_FR) { 958139365Srik /* Add frame relay header. */ 959139365Srik m = sppp_fr_header (sp, m, dst->sa_family); 960139365Srik if (! m) 961139365Srik goto nobufs; 962139365Srik goto out; 963139365Srik } 964139365Srik 9654910Swollman /* 9664910Swollman * Prepend general data packet PPP header. For now, IP only. 9674910Swollman */ 968111119Simp M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 9694910Swollman if (! m) { 970139365Sriknobufs: if (debug) 97140008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 97240008Sjoerg SPP_ARGS(ifp)); 97325944Sjoerg ++ifp->if_oerrors; 974138745Srik SPPP_UNLOCK(sp); 9754910Swollman splx (s); 9764910Swollman return (ENOBUFS); 9774910Swollman } 97840008Sjoerg /* 97940008Sjoerg * May want to check size of packet 98040008Sjoerg * (albeit due to the implementation it's always enough) 98140008Sjoerg */ 9824910Swollman h = mtod (m, struct ppp_header*); 98345152Sphk if (sp->pp_mode == IFF_CISCO) { 98428088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9854910Swollman h->control = 0; 9864910Swollman } else { 9874910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9884910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9894910Swollman } 9904910Swollman 9914910Swollman switch (dst->sa_family) { 9924910Swollman#ifdef INET 9934910Swollman case AF_INET: /* Internet Protocol */ 99445152Sphk if (sp->pp_mode == IFF_CISCO) 99511189Sjkh h->protocol = htons (ETHERTYPE_IP); 99611189Sjkh else { 99725955Sjoerg /* 99825955Sjoerg * Don't choke with an ENETDOWN early. It's 99925955Sjoerg * possible that we just started dialing out, 100025955Sjoerg * so don't drop the packet immediately. If 100125955Sjoerg * we notice that we run out of buffer space 100225955Sjoerg * below, we will however remember that we are 100325955Sjoerg * not ready to carry IP packets, and return 100425955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 100525955Sjoerg */ 100688534Sjoerg h->protocol = htons(ipproto); 100725955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 100825955Sjoerg rv = ENETDOWN; 100911189Sjkh } 10104910Swollman break; 10114910Swollman#endif 101254263Sshin#ifdef INET6 101354263Sshin case AF_INET6: /* Internet Protocol */ 101454263Sshin if (sp->pp_mode == IFF_CISCO) 101554263Sshin h->protocol = htons (ETHERTYPE_IPV6); 101654263Sshin else { 101778064Sume /* 101878064Sume * Don't choke with an ENETDOWN early. It's 101978064Sume * possible that we just started dialing out, 102078064Sume * so don't drop the packet immediately. If 102178064Sume * we notice that we run out of buffer space 102278064Sume * below, we will however remember that we are 102378064Sume * not ready to carry IP packets, and return 102478064Sume * ENETDOWN, as opposed to ENOBUFS. 102578064Sume */ 102678064Sume h->protocol = htons(PPP_IPV6); 102778064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 102878064Sume rv = ENETDOWN; 102954263Sshin } 103054263Sshin break; 103154263Sshin#endif 103211819Sjulian#ifdef IPX 103312495Speter case AF_IPX: /* Novell IPX Protocol */ 103445152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 103512495Speter ETHERTYPE_IPX : PPP_IPX); 103611819Sjulian break; 103711819Sjulian#endif 10384910Swollman default: 10394910Swollman m_freem (m); 104025944Sjoerg ++ifp->if_oerrors; 1041138745Srik SPPP_UNLOCK(sp); 10424910Swollman splx (s); 10434910Swollman return (EAFNOSUPPORT); 10444910Swollman } 10454910Swollman 10464910Swollman /* 10474910Swollman * Queue message on interface, and start output if interface 104888577Sjoerg * not yet active. 10494910Swollman */ 1050139365Srikout: 1051130549Smlaier if (ifq != NULL) 1052130549Smlaier error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 1053130549Smlaier else 1054130549Smlaier IFQ_HANDOFF_ADJ(ifp, m, 3, error); 1055130549Smlaier if (error) { 105625944Sjoerg ++ifp->if_oerrors; 1057138745Srik SPPP_UNLOCK(sp); 1058111038Smaxim splx (s); 105925955Sjoerg return (rv? rv: ENOBUFS); 10604910Swollman } 1061138745Srik SPPP_UNLOCK(sp); 1062111038Smaxim splx (s); 106388577Sjoerg /* 106488577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 106588577Sjoerg * here since sppp_output() is only called on behalf of 106688577Sjoerg * network-layer traffic; control-layer traffic is handled 106788577Sjoerg * by sppp_cp_send(). 106888577Sjoerg */ 1069150349Sandre sp->pp_last_sent = time_uptime; 10704910Swollman return (0); 10714910Swollman} 10724910Swollman 107325706Sjoergvoid 107425706Sjoergsppp_attach(struct ifnet *ifp) 10754910Swollman{ 1076147256Sbrooks struct sppp *sp = IFP2SP(ifp); 10774910Swollman 1078138745Srik /* Initialize mtx lock */ 1079138745Srik mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); 1080138745Srik 10814910Swollman /* Initialize keepalive handler. */ 1082138745Srik callout_init(&sp->keepalive_callout, 1083138745Srik (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 1084138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 1085138745Srik (void *)sp); 10864910Swollman 1087147256Sbrooks ifp->if_mtu = PP_MTU; 1088147256Sbrooks ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 1089147256Sbrooks ifp->if_output = sppp_output; 109042104Sphk#if 0 109142064Sphk sp->pp_flags = PP_KEEPALIVE; 109242104Sphk#endif 1093147256Sbrooks ifp->if_snd.ifq_maxlen = 32; 109470199Sjhay sp->pp_fastq.ifq_maxlen = 32; 109570199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10964910Swollman sp->pp_loopcnt = 0; 10974910Swollman sp->pp_alivecnt = 0; 109878064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 109978064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 110025944Sjoerg sp->pp_phase = PHASE_DEAD; 1101138745Srik sp->pp_up = sppp_pp_up; 1102138745Srik sp->pp_down = sppp_pp_down; 110388716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 110493818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 110588716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 110693818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 1107150349Sandre sp->pp_last_recv = sp->pp_last_sent = time_uptime; 110888723Sjoerg sp->confflags = 0; 110988723Sjoerg#ifdef INET 111088723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 111188723Sjoerg#endif 111288723Sjoerg#ifdef INET6 111388723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 111488723Sjoerg#endif 1115138745Srik callout_init(&sp->ifstart_callout, 1116138745Srik (ifp->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 1117138745Srik sp->if_start = ifp->if_start; 1118138745Srik ifp->if_start = sppp_ifstart; 1119118072Sgj sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 112088599Sjoerg sl_compress_init(sp->pp_comp, -1); 112125944Sjoerg sppp_lcp_init(sp); 112225944Sjoerg sppp_ipcp_init(sp); 112378064Sume sppp_ipv6cp_init(sp); 112430300Sjoerg sppp_pap_init(sp); 112530300Sjoerg sppp_chap_init(sp); 11264910Swollman} 11274910Swollman 112830300Sjoergvoid 112925706Sjoergsppp_detach(struct ifnet *ifp) 11304910Swollman{ 1131147256Sbrooks struct sppp *sp = IFP2SP(ifp); 113225944Sjoerg int i; 11334910Swollman 1134138745Srik KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized")); 11354910Swollman 11364910Swollman /* Stop keepalive handler. */ 1137138745Srik if (!callout_drain(&sp->keepalive_callout)) 1138138745Srik callout_stop(&sp->keepalive_callout); 113925944Sjoerg 1140138745Srik for (i = 0; i < IDX_COUNT; i++) { 1141138745Srik if (!callout_drain(&sp->ch[i])) 1142138745Srik callout_stop(&sp->ch[i]); 1143138745Srik } 1144138745Srik if (!callout_drain(&sp->pap_my_to_ch)) 1145138745Srik callout_stop(&sp->pap_my_to_ch); 114669152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 114769152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 1148138745Srik mtx_destroy(&sp->mtx); 11494910Swollman} 11504910Swollman 11514910Swollman/* 11524910Swollman * Flush the interface output queue. 11534910Swollman */ 1154138745Srikstatic void 1155138745Sriksppp_flush_unlocked(struct ifnet *ifp) 11564910Swollman{ 1157147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11584910Swollman 1159147256Sbrooks sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd); 116025944Sjoerg sppp_qflush (&sp->pp_fastq); 116126018Sjoerg sppp_qflush (&sp->pp_cpq); 11624910Swollman} 11634910Swollman 1164138745Srikvoid 1165138745Sriksppp_flush(struct ifnet *ifp) 1166138745Srik{ 1167147256Sbrooks struct sppp *sp = IFP2SP(ifp); 1168138745Srik 1169138745Srik SPPP_LOCK(sp); 1170138745Srik sppp_flush_unlocked (ifp); 1171138745Srik SPPP_UNLOCK(sp); 1172138745Srik} 1173138745Srik 11744910Swollman/* 117511189Sjkh * Check if the output queue is empty. 117611189Sjkh */ 117712820Sphkint 117825706Sjoergsppp_isempty(struct ifnet *ifp) 117911189Sjkh{ 1180147256Sbrooks struct sppp *sp = IFP2SP(ifp); 118125944Sjoerg int empty, s; 118211189Sjkh 118325944Sjoerg s = splimp(); 1184138745Srik SPPP_LOCK(sp); 118526018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1186147256Sbrooks !SP2IFP(sp)->if_snd.ifq_head; 1187138745Srik SPPP_UNLOCK(sp); 118825944Sjoerg splx(s); 118911189Sjkh return (empty); 119011189Sjkh} 119111189Sjkh 119211189Sjkh/* 11934910Swollman * Get next packet to send. 11944910Swollman */ 119525706Sjoergstruct mbuf * 119625706Sjoergsppp_dequeue(struct ifnet *ifp) 11974910Swollman{ 1198147256Sbrooks struct sppp *sp = IFP2SP(ifp); 11994910Swollman struct mbuf *m; 120025944Sjoerg int s; 12014910Swollman 120225944Sjoerg s = splimp(); 1203138745Srik SPPP_LOCK(sp); 120426018Sjoerg /* 120530300Sjoerg * Process only the control protocol queue until we have at 120630300Sjoerg * least one NCP open. 120726018Sjoerg * 120826018Sjoerg * Do always serve all three queues in Cisco mode. 120926018Sjoerg */ 121026018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 121126018Sjoerg if (m == NULL && 1212139365Srik (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO || 1213139365Srik sp->pp_mode == PP_FR)) { 121426018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 121526018Sjoerg if (m == NULL) 1216147256Sbrooks IF_DEQUEUE (&SP2IFP(sp)->if_snd, m); 121726018Sjoerg } 1218138745Srik SPPP_UNLOCK(sp); 121926018Sjoerg splx(s); 122026018Sjoerg return m; 12214910Swollman} 12224910Swollman 12234910Swollman/* 122430300Sjoerg * Pick the next packet, do not remove it from the queue. 122530300Sjoerg */ 122630300Sjoergstruct mbuf * 122730300Sjoergsppp_pick(struct ifnet *ifp) 122830300Sjoerg{ 1229147256Sbrooks struct sppp *sp = IFP2SP(ifp); 123030300Sjoerg struct mbuf *m; 123130300Sjoerg int s; 123230300Sjoerg 1233138745Srik s = splimp (); 1234138745Srik SPPP_LOCK(sp); 123530300Sjoerg 123630300Sjoerg m = sp->pp_cpq.ifq_head; 123730300Sjoerg if (m == NULL && 1238138745Srik (sp->pp_phase == PHASE_NETWORK || 1239139365Srik sp->pp_mode == IFF_CISCO || 1240139365Srik sp->pp_mode == PP_FR)) 124130300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 1242147256Sbrooks m = SP2IFP(sp)->if_snd.ifq_head; 1243138745Srik SPPP_UNLOCK(sp); 124430300Sjoerg splx (s); 124530300Sjoerg return (m); 124630300Sjoerg} 124730300Sjoerg 124830300Sjoerg/* 124925944Sjoerg * Process an ioctl request. Called on low priority level. 12504910Swollman */ 125125944Sjoergint 125242104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 12534910Swollman{ 125425944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 1255147256Sbrooks struct sppp *sp = IFP2SP(ifp); 125630300Sjoerg int s, rv, going_up, going_down, newmode; 12574910Swollman 125825944Sjoerg s = splimp(); 1259138745Srik SPPP_LOCK(sp); 126030300Sjoerg rv = 0; 126125944Sjoerg switch (cmd) { 126225944Sjoerg case SIOCAIFADDR: 126325944Sjoerg case SIOCSIFDSTADDR: 126425944Sjoerg break; 12654910Swollman 126625944Sjoerg case SIOCSIFADDR: 126788503Sjoerg /* set the interface "up" when assigning an IP address */ 126888503Sjoerg ifp->if_flags |= IFF_UP; 1269102412Scharnier /* FALLTHROUGH */ 127011189Sjkh 127125944Sjoerg case SIOCSIFFLAGS: 127225944Sjoerg going_up = ifp->if_flags & IFF_UP && 1273148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0; 127425944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 1275148887Srwatson ifp->if_drv_flags & IFF_DRV_RUNNING; 127645152Sphk 127745152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 127845152Sphk if (!newmode) 127945152Sphk newmode = ifp->if_flags & IFF_AUTO; 128045152Sphk if (!newmode) 128145152Sphk newmode = ifp->if_flags & IFF_CISCO; 128245152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 128345152Sphk ifp->if_flags |= newmode; 128445152Sphk 1285139365Srik if (!newmode) 1286139365Srik newmode = sp->pp_flags & PP_FR; 1287139365Srik 128845152Sphk if (newmode != sp->pp_mode) { 128945152Sphk going_down = 1; 129045152Sphk if (!going_up) 1291148887Srwatson going_up = ifp->if_drv_flags & IFF_DRV_RUNNING; 12924910Swollman } 12934910Swollman 129445152Sphk if (going_down) { 1295139365Srik if (sp->pp_mode != IFF_CISCO && 1296139365Srik sp->pp_mode != PP_FR) 129745152Sphk lcp.Close(sp); 129845152Sphk else if (sp->pp_tlf) 129945152Sphk (sp->pp_tlf)(sp); 1300138745Srik sppp_flush_unlocked(ifp); 1301148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 130245152Sphk sp->pp_mode = newmode; 130326018Sjoerg } 13044910Swollman 130545152Sphk if (going_up) { 1306139365Srik if (sp->pp_mode != IFF_CISCO && 1307139365Srik sp->pp_mode != PP_FR) 130845152Sphk lcp.Close(sp); 130945152Sphk sp->pp_mode = newmode; 131045152Sphk if (sp->pp_mode == 0) { 1311148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 131245152Sphk lcp.Open(sp); 131345152Sphk } 1314139365Srik if ((sp->pp_mode == IFF_CISCO) || 1315139365Srik (sp->pp_mode == PP_FR)) { 131645152Sphk if (sp->pp_tls) 131745152Sphk (sp->pp_tls)(sp); 1318148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 131945152Sphk } 132045152Sphk } 132145152Sphk 13224910Swollman break; 132311189Sjkh 132425944Sjoerg#ifdef SIOCSIFMTU 132525944Sjoerg#ifndef ifr_mtu 132625944Sjoerg#define ifr_mtu ifr_metric 132725944Sjoerg#endif 132825944Sjoerg case SIOCSIFMTU: 132925944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 133025944Sjoerg return (EINVAL); 133125944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 13324910Swollman break; 133325944Sjoerg#endif 133425944Sjoerg#ifdef SLIOCSETMTU 133525944Sjoerg case SLIOCSETMTU: 133625944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 133725944Sjoerg return (EINVAL); 133825944Sjoerg ifp->if_mtu = *(short*)data; 13394910Swollman break; 134025944Sjoerg#endif 134125944Sjoerg#ifdef SIOCGIFMTU 134225944Sjoerg case SIOCGIFMTU: 134325944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 134411189Sjkh break; 134525944Sjoerg#endif 134625944Sjoerg#ifdef SLIOCGETMTU 134725944Sjoerg case SLIOCGETMTU: 134825944Sjoerg *(short*)data = ifp->if_mtu; 13494910Swollman break; 135025944Sjoerg#endif 135125944Sjoerg case SIOCADDMULTI: 135225944Sjoerg case SIOCDELMULTI: 13534910Swollman break; 135411189Sjkh 135530300Sjoerg case SIOCGIFGENERIC: 135630300Sjoerg case SIOCSIFGENERIC: 135730300Sjoerg rv = sppp_params(sp, cmd, data); 135830300Sjoerg break; 135930300Sjoerg 136025944Sjoerg default: 136130300Sjoerg rv = ENOTTY; 13624910Swollman } 1363138745Srik SPPP_UNLOCK(sp); 136425944Sjoerg splx(s); 136530300Sjoerg return rv; 13664910Swollman} 13674910Swollman 136870199Sjhay/* 136925944Sjoerg * Cisco framing implementation. 137025944Sjoerg */ 137125944Sjoerg 13724910Swollman/* 13734910Swollman * Handle incoming Cisco keepalive protocol packets. 13744910Swollman */ 137530300Sjoergstatic void 137625706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 13774910Swollman{ 137825944Sjoerg STDDCL; 13794910Swollman struct cisco_packet *h; 138030300Sjoerg u_long me, mymask; 13814910Swollman 138227929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 138325706Sjoerg if (debug) 138425706Sjoerg log(LOG_DEBUG, 138540008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 138640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 13874910Swollman return; 13884910Swollman } 13894910Swollman h = mtod (m, struct cisco_packet*); 139025706Sjoerg if (debug) 139125706Sjoerg log(LOG_DEBUG, 139240008Sjoerg SPP_FMT "cisco input: %d bytes " 139325706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 139440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 139540008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 139640008Sjoerg (u_int)h->time0, (u_int)h->time1); 13974910Swollman switch (ntohl (h->type)) { 13984910Swollman default: 139925706Sjoerg if (debug) 140069211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 140140008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 14024910Swollman break; 14034910Swollman case CISCO_ADDR_REPLY: 14044910Swollman /* Reply on address request, ignore */ 14054910Swollman break; 14064910Swollman case CISCO_KEEPALIVE_REQ: 14074910Swollman sp->pp_alivecnt = 0; 140878064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 140978064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 14104910Swollman /* Local and remote sequence numbers are equal. 14114910Swollman * Probably, the line is in loopback mode. */ 141211189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 141340008Sjoerg printf (SPP_FMT "loopback\n", 141440008Sjoerg SPP_ARGS(ifp)); 141511189Sjkh sp->pp_loopcnt = 0; 141611189Sjkh if (ifp->if_flags & IFF_UP) { 141711189Sjkh if_down (ifp); 141826018Sjoerg sppp_qflush (&sp->pp_cpq); 141911189Sjkh } 142011189Sjkh } 14214910Swollman ++sp->pp_loopcnt; 14224910Swollman 14234910Swollman /* Generate new local sequence number */ 142442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 142578064Sume sp->pp_seq[IDX_LCP] = random(); 142640008Sjoerg#else 142778064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 142840008Sjoerg#endif 142911189Sjkh break; 143011189Sjkh } 143130300Sjoerg sp->pp_loopcnt = 0; 143211189Sjkh if (! (ifp->if_flags & IFF_UP) && 1433148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 143430300Sjoerg if_up(ifp); 143540008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 143611189Sjkh } 14374910Swollman break; 14384910Swollman case CISCO_ADDR_REQ: 143930300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 144030300Sjoerg if (me != 0L) 144130300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 14424910Swollman break; 14434910Swollman } 14444910Swollman} 14454910Swollman 14464910Swollman/* 144725944Sjoerg * Send Cisco keepalive packet. 14484910Swollman */ 144912820Sphkstatic void 145025944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 145125944Sjoerg{ 145225944Sjoerg STDDCL; 145325944Sjoerg struct ppp_header *h; 145425944Sjoerg struct cisco_packet *ch; 145525944Sjoerg struct mbuf *m; 145635029Sphk struct timeval tv; 145725944Sjoerg 145836119Sphk getmicrouptime(&tv); 145970199Sjhay 1460111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 146125944Sjoerg if (! m) 146225944Sjoerg return; 146325944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 146425944Sjoerg m->m_pkthdr.rcvif = 0; 146525944Sjoerg 146625944Sjoerg h = mtod (m, struct ppp_header*); 146725944Sjoerg h->address = CISCO_MULTICAST; 146825944Sjoerg h->control = 0; 146925944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 147025944Sjoerg 147125944Sjoerg ch = (struct cisco_packet*) (h + 1); 147225944Sjoerg ch->type = htonl (type); 147325944Sjoerg ch->par1 = htonl (par1); 147425944Sjoerg ch->par2 = htonl (par2); 147525944Sjoerg ch->rel = -1; 147640008Sjoerg 147735029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 147835029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 147925944Sjoerg 148025944Sjoerg if (debug) 148125944Sjoerg log(LOG_DEBUG, 148240008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 148340008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 148440008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 148525944Sjoerg 148669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 148769152Sjlemon ifp->if_oerrors++; 148825944Sjoerg} 148925944Sjoerg 149070199Sjhay/* 149125944Sjoerg * PPP protocol implementation. 149225944Sjoerg */ 149325944Sjoerg 149425944Sjoerg/* 149525944Sjoerg * Send PPP control protocol packet. 149625944Sjoerg */ 149725944Sjoergstatic void 149825706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 149925706Sjoerg u_char ident, u_short len, void *data) 15004910Swollman{ 150125944Sjoerg STDDCL; 15024910Swollman struct ppp_header *h; 15034910Swollman struct lcp_header *lh; 15044910Swollman struct mbuf *m; 15054910Swollman 15064910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 15074910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1508111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 15094910Swollman if (! m) 15104910Swollman return; 15114910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 15124910Swollman m->m_pkthdr.rcvif = 0; 15134910Swollman 15144910Swollman h = mtod (m, struct ppp_header*); 15154910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 15164910Swollman h->control = PPP_UI; /* Unnumbered Info */ 15174910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 15184910Swollman 15194910Swollman lh = (struct lcp_header*) (h + 1); 15204910Swollman lh->type = type; 15214910Swollman lh->ident = ident; 15224910Swollman lh->len = htons (LCP_HEADER_LEN + len); 15234910Swollman if (len) 15244910Swollman bcopy (data, lh+1, len); 15254910Swollman 152625706Sjoerg if (debug) { 152740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 152840008Sjoerg SPP_ARGS(ifp), 152925944Sjoerg sppp_proto_name(proto), 153025944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 153125944Sjoerg ntohs (lh->len)); 153244145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 153369211Sphk log(-1, ">\n"); 15344910Swollman } 153569152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 153669152Sjlemon ifp->if_oerrors++; 15374910Swollman} 15384910Swollman 15394910Swollman/* 154025944Sjoerg * Handle incoming PPP control protocol packets. 15414910Swollman */ 154212820Sphkstatic void 154325944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 15444910Swollman{ 154525944Sjoerg STDDCL; 154625944Sjoerg struct lcp_header *h; 154725944Sjoerg int len = m->m_pkthdr.len; 154825944Sjoerg int rv; 154925944Sjoerg u_char *p; 15504910Swollman 155125944Sjoerg if (len < 4) { 155225944Sjoerg if (debug) 155325944Sjoerg log(LOG_DEBUG, 155440008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 155540008Sjoerg SPP_ARGS(ifp), cp->name, len); 15564910Swollman return; 155725944Sjoerg } 155825944Sjoerg h = mtod (m, struct lcp_header*); 155925944Sjoerg if (debug) { 156025944Sjoerg log(LOG_DEBUG, 156140008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 156240008Sjoerg SPP_ARGS(ifp), cp->name, 156325944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 156425944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 156544145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 156669211Sphk log(-1, ">\n"); 156725944Sjoerg } 156825944Sjoerg if (len > ntohs (h->len)) 156925944Sjoerg len = ntohs (h->len); 157030300Sjoerg p = (u_char *)(h + 1); 157125944Sjoerg switch (h->type) { 157225944Sjoerg case CONF_REQ: 157325944Sjoerg if (len < 4) { 157425944Sjoerg if (debug) 157569211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 157640008Sjoerg SPP_ARGS(ifp), cp->name, 157725944Sjoerg len); 157825944Sjoerg ++ifp->if_ierrors; 157925944Sjoerg break; 158025944Sjoerg } 158130300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 158230300Sjoerg switch (sp->state[cp->protoidx]) { 158330300Sjoerg case STATE_CLOSING: 158430300Sjoerg case STATE_STOPPING: 158530300Sjoerg return; 158630300Sjoerg case STATE_CLOSED: 158730300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 158830300Sjoerg 0, 0); 158930300Sjoerg return; 159030300Sjoerg } 159125944Sjoerg rv = (cp->RCR)(sp, h, len); 159225944Sjoerg switch (sp->state[cp->protoidx]) { 159325944Sjoerg case STATE_OPENED: 159425944Sjoerg (cp->tld)(sp); 159525944Sjoerg (cp->scr)(sp); 1596102412Scharnier /* FALLTHROUGH */ 159725944Sjoerg case STATE_ACK_SENT: 159825944Sjoerg case STATE_REQ_SENT: 159970199Sjhay /* 160070199Sjhay * sppp_cp_change_state() have the side effect of 160170199Sjhay * restarting the timeouts. We want to avoid that 160270199Sjhay * if the state don't change, otherwise we won't 160370199Sjhay * ever timeout and resend a configuration request 160470199Sjhay * that got lost. 160570199Sjhay */ 160670199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 160770199Sjhay STATE_REQ_SENT)) 160870199Sjhay break; 160925944Sjoerg sppp_cp_change_state(cp, sp, rv? 161025944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 161125944Sjoerg break; 161225944Sjoerg case STATE_STOPPED: 161325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 161425944Sjoerg (cp->scr)(sp); 161525944Sjoerg sppp_cp_change_state(cp, sp, rv? 161625944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 161725944Sjoerg break; 161825944Sjoerg case STATE_ACK_RCVD: 161925944Sjoerg if (rv) { 162025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 162125944Sjoerg if (debug) 162240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 162340008Sjoerg SPP_ARGS(ifp), 162426077Sjoerg cp->name); 162525944Sjoerg (cp->tlu)(sp); 162625944Sjoerg } else 162725944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 162825944Sjoerg break; 162925944Sjoerg default: 163040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163140008Sjoerg SPP_ARGS(ifp), cp->name, 163225944Sjoerg sppp_cp_type_name(h->type), 163325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163425944Sjoerg ++ifp->if_ierrors; 163525944Sjoerg } 163625944Sjoerg break; 163725944Sjoerg case CONF_ACK: 163825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 163925944Sjoerg if (debug) 164069211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 164140008Sjoerg SPP_ARGS(ifp), cp->name, 164225944Sjoerg h->ident, sp->confid[cp->protoidx]); 164325944Sjoerg ++ifp->if_ierrors; 164425944Sjoerg break; 164525944Sjoerg } 164625944Sjoerg switch (sp->state[cp->protoidx]) { 164725944Sjoerg case STATE_CLOSED: 164825944Sjoerg case STATE_STOPPED: 164925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 165025944Sjoerg break; 165125944Sjoerg case STATE_CLOSING: 165225944Sjoerg case STATE_STOPPING: 165325944Sjoerg break; 165425944Sjoerg case STATE_REQ_SENT: 165525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 165625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 165725944Sjoerg break; 165825944Sjoerg case STATE_OPENED: 165925944Sjoerg (cp->tld)(sp); 1660102412Scharnier /* FALLTHROUGH */ 166125944Sjoerg case STATE_ACK_RCVD: 166225944Sjoerg (cp->scr)(sp); 166325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 166425944Sjoerg break; 166525944Sjoerg case STATE_ACK_SENT: 166625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 166725944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 166825944Sjoerg if (debug) 166940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 167040008Sjoerg SPP_ARGS(ifp), cp->name); 167125944Sjoerg (cp->tlu)(sp); 167225944Sjoerg break; 167325944Sjoerg default: 167440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 167540008Sjoerg SPP_ARGS(ifp), cp->name, 167625944Sjoerg sppp_cp_type_name(h->type), 167725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 167825944Sjoerg ++ifp->if_ierrors; 167925944Sjoerg } 168025944Sjoerg break; 168125944Sjoerg case CONF_NAK: 168225944Sjoerg case CONF_REJ: 168325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 168425944Sjoerg if (debug) 168569211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 168640008Sjoerg SPP_ARGS(ifp), cp->name, 168725944Sjoerg h->ident, sp->confid[cp->protoidx]); 168825944Sjoerg ++ifp->if_ierrors; 168925944Sjoerg break; 169025944Sjoerg } 169125944Sjoerg if (h->type == CONF_NAK) 169225944Sjoerg (cp->RCN_nak)(sp, h, len); 169325944Sjoerg else /* CONF_REJ */ 169425944Sjoerg (cp->RCN_rej)(sp, h, len); 16954910Swollman 169625944Sjoerg switch (sp->state[cp->protoidx]) { 169725944Sjoerg case STATE_CLOSED: 169825944Sjoerg case STATE_STOPPED: 169925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 170025944Sjoerg break; 170125944Sjoerg case STATE_REQ_SENT: 170225944Sjoerg case STATE_ACK_SENT: 170325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 170470199Sjhay /* 170570199Sjhay * Slow things down a bit if we think we might be 170670199Sjhay * in loopback. Depend on the timeout to send the 170770199Sjhay * next configuration request. 170870199Sjhay */ 170970199Sjhay if (sp->pp_loopcnt) 171070199Sjhay break; 171125944Sjoerg (cp->scr)(sp); 171225944Sjoerg break; 171325944Sjoerg case STATE_OPENED: 171425944Sjoerg (cp->tld)(sp); 1715102412Scharnier /* FALLTHROUGH */ 171625944Sjoerg case STATE_ACK_RCVD: 171752633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171825944Sjoerg (cp->scr)(sp); 171925944Sjoerg break; 172025944Sjoerg case STATE_CLOSING: 172125944Sjoerg case STATE_STOPPING: 172225944Sjoerg break; 172325944Sjoerg default: 172440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 172540008Sjoerg SPP_ARGS(ifp), cp->name, 172625944Sjoerg sppp_cp_type_name(h->type), 172725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172825944Sjoerg ++ifp->if_ierrors; 172925944Sjoerg } 173025944Sjoerg break; 17314910Swollman 173225944Sjoerg case TERM_REQ: 173325944Sjoerg switch (sp->state[cp->protoidx]) { 173425944Sjoerg case STATE_ACK_RCVD: 173525944Sjoerg case STATE_ACK_SENT: 173625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1737102412Scharnier /* FALLTHROUGH */ 173825944Sjoerg case STATE_CLOSED: 173925944Sjoerg case STATE_STOPPED: 174025944Sjoerg case STATE_CLOSING: 174125944Sjoerg case STATE_STOPPING: 174225944Sjoerg case STATE_REQ_SENT: 174325944Sjoerg sta: 174425944Sjoerg /* Send Terminate-Ack packet. */ 174525944Sjoerg if (debug) 174640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 174740008Sjoerg SPP_ARGS(ifp), cp->name); 174825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 174925944Sjoerg break; 175025944Sjoerg case STATE_OPENED: 175125944Sjoerg (cp->tld)(sp); 175225944Sjoerg sp->rst_counter[cp->protoidx] = 0; 175325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 175425944Sjoerg goto sta; 175525944Sjoerg break; 175625944Sjoerg default: 175740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 175840008Sjoerg SPP_ARGS(ifp), cp->name, 175925944Sjoerg sppp_cp_type_name(h->type), 176025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 176125944Sjoerg ++ifp->if_ierrors; 176225944Sjoerg } 176325944Sjoerg break; 176425944Sjoerg case TERM_ACK: 176525944Sjoerg switch (sp->state[cp->protoidx]) { 176625944Sjoerg case STATE_CLOSED: 176725944Sjoerg case STATE_STOPPED: 176825944Sjoerg case STATE_REQ_SENT: 176925944Sjoerg case STATE_ACK_SENT: 177025944Sjoerg break; 177125944Sjoerg case STATE_CLOSING: 177241881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 177325944Sjoerg (cp->tlf)(sp); 177425944Sjoerg break; 177525944Sjoerg case STATE_STOPPING: 177641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 177725944Sjoerg (cp->tlf)(sp); 177825944Sjoerg break; 177925944Sjoerg case STATE_ACK_RCVD: 178025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 178125944Sjoerg break; 178225944Sjoerg case STATE_OPENED: 178325944Sjoerg (cp->tld)(sp); 178425944Sjoerg (cp->scr)(sp); 178525944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 178625944Sjoerg break; 178725944Sjoerg default: 178840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 178940008Sjoerg SPP_ARGS(ifp), cp->name, 179025944Sjoerg sppp_cp_type_name(h->type), 179125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 179225944Sjoerg ++ifp->if_ierrors; 179325944Sjoerg } 179425944Sjoerg break; 179525944Sjoerg case CODE_REJ: 179625944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 179730300Sjoerg log(LOG_INFO, 179840008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 179930300Sjoerg "danger will robinson\n", 180040008Sjoerg SPP_ARGS(ifp), cp->name, 180130300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 180225944Sjoerg switch (sp->state[cp->protoidx]) { 180325944Sjoerg case STATE_CLOSED: 180425944Sjoerg case STATE_STOPPED: 180525944Sjoerg case STATE_REQ_SENT: 180625944Sjoerg case STATE_ACK_SENT: 180725944Sjoerg case STATE_CLOSING: 180825944Sjoerg case STATE_STOPPING: 180925944Sjoerg case STATE_OPENED: 181025944Sjoerg break; 181125944Sjoerg case STATE_ACK_RCVD: 181225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 181325944Sjoerg break; 181425944Sjoerg default: 181540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 181640008Sjoerg SPP_ARGS(ifp), cp->name, 181725944Sjoerg sppp_cp_type_name(h->type), 181825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 181925944Sjoerg ++ifp->if_ierrors; 182025944Sjoerg } 182125944Sjoerg break; 182280715Sume case PROTO_REJ: 182380715Sume { 182480715Sume int catastrophic; 182580715Sume const struct cp *upper; 182680715Sume int i; 182780715Sume u_int16_t proto; 182880715Sume 182980715Sume catastrophic = 0; 183080715Sume upper = NULL; 183180715Sume proto = ntohs(*((u_int16_t *)p)); 183280715Sume for (i = 0; i < IDX_COUNT; i++) { 183380715Sume if (cps[i]->proto == proto) { 183480715Sume upper = cps[i]; 183580715Sume break; 183680715Sume } 183780715Sume } 183880715Sume if (upper == NULL) 183980715Sume catastrophic++; 184080715Sume 184188508Sjoerg if (catastrophic || debug) 184288508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 184388508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 184488508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 184588508Sjoerg sppp_cp_type_name(h->type), proto, 184688508Sjoerg upper ? upper->name : "unknown", 184788508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 184880715Sume 184980715Sume /* 185080715Sume * if we got RXJ+ against conf-req, the peer does not implement 185180715Sume * this particular protocol type. terminate the protocol. 185280715Sume */ 185380715Sume if (upper && !catastrophic) { 185480715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 185580715Sume upper->Close(sp); 185680715Sume break; 185780715Sume } 185880715Sume } 185980715Sume 186080715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 186180715Sume switch (sp->state[cp->protoidx]) { 186280715Sume case STATE_CLOSED: 186380715Sume case STATE_STOPPED: 186480715Sume case STATE_REQ_SENT: 186580715Sume case STATE_ACK_SENT: 186680715Sume case STATE_CLOSING: 186780715Sume case STATE_STOPPING: 186880715Sume case STATE_OPENED: 186980715Sume break; 187080715Sume case STATE_ACK_RCVD: 187180715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 187280715Sume break; 187380715Sume default: 187480715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 187580715Sume SPP_ARGS(ifp), cp->name, 187680715Sume sppp_cp_type_name(h->type), 187780715Sume sppp_state_name(sp->state[cp->protoidx])); 187880715Sume ++ifp->if_ierrors; 187980715Sume } 188080715Sume break; 188180715Sume } 188225944Sjoerg case DISC_REQ: 188325944Sjoerg if (cp->proto != PPP_LCP) 188425944Sjoerg goto illegal; 188525944Sjoerg /* Discard the packet. */ 188625944Sjoerg break; 188725944Sjoerg case ECHO_REQ: 188825944Sjoerg if (cp->proto != PPP_LCP) 188925944Sjoerg goto illegal; 189025944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 189125944Sjoerg if (debug) 189269211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 189340008Sjoerg SPP_ARGS(ifp)); 189425944Sjoerg ++ifp->if_ierrors; 189525944Sjoerg break; 189625944Sjoerg } 189725944Sjoerg if (len < 8) { 189825944Sjoerg if (debug) 189969211Sphk log(-1, SPP_FMT "invalid lcp echo request " 190025944Sjoerg "packet length: %d bytes\n", 190140008Sjoerg SPP_ARGS(ifp), len); 190225944Sjoerg break; 190325944Sjoerg } 190444145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 190544145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 190625944Sjoerg /* Line loopback mode detected. */ 190740008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 190870199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 190925944Sjoerg if_down (ifp); 191026018Sjoerg sppp_qflush (&sp->pp_cpq); 19114910Swollman 191225944Sjoerg /* Shut down the PPP link. */ 191325944Sjoerg /* XXX */ 191425944Sjoerg lcp.Down(sp); 191525944Sjoerg lcp.Up(sp); 191625944Sjoerg break; 191725944Sjoerg } 191825944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 191925944Sjoerg if (debug) 192069211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 192140008Sjoerg SPP_ARGS(ifp)); 192225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 192325944Sjoerg break; 192425944Sjoerg case ECHO_REPLY: 192525944Sjoerg if (cp->proto != PPP_LCP) 192625944Sjoerg goto illegal; 192725944Sjoerg if (h->ident != sp->lcp.echoid) { 192825944Sjoerg ++ifp->if_ierrors; 192925944Sjoerg break; 193025944Sjoerg } 193125944Sjoerg if (len < 8) { 193225944Sjoerg if (debug) 193369211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 193425944Sjoerg "packet length: %d bytes\n", 193540008Sjoerg SPP_ARGS(ifp), len); 193625944Sjoerg break; 193725944Sjoerg } 193825944Sjoerg if (debug) 193969211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 194040008Sjoerg SPP_ARGS(ifp)); 194144145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 194244145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 194325944Sjoerg sp->pp_alivecnt = 0; 194425944Sjoerg break; 194525944Sjoerg default: 194625944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 194725944Sjoerg illegal: 194825944Sjoerg if (debug) 194969211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 195040008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 195178064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 195278064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 195325944Sjoerg ++ifp->if_ierrors; 195425944Sjoerg } 19554910Swollman} 19564910Swollman 195725944Sjoerg 19584910Swollman/* 195925944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 196025944Sjoerg * Basically, the state transition handling in the automaton. 19614910Swollman */ 196225944Sjoergstatic void 196325944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 19644910Swollman{ 196525944Sjoerg STDDCL; 19664910Swollman 196725944Sjoerg if (debug) 196840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 196940008Sjoerg SPP_ARGS(ifp), cp->name, 197025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 197125944Sjoerg 197225944Sjoerg switch (sp->state[cp->protoidx]) { 197325944Sjoerg case STATE_INITIAL: 197425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 197525944Sjoerg break; 197625944Sjoerg case STATE_STARTING: 197725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 197825944Sjoerg (cp->scr)(sp); 197925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 198025944Sjoerg break; 19814910Swollman default: 198240008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 198340008Sjoerg SPP_ARGS(ifp), cp->name, 198425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 198525944Sjoerg } 198625944Sjoerg} 19874910Swollman 198825944Sjoergstatic void 198925944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 199025944Sjoerg{ 199125944Sjoerg STDDCL; 199225944Sjoerg 199325944Sjoerg if (debug) 199440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 199540008Sjoerg SPP_ARGS(ifp), cp->name, 199625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 199725944Sjoerg 199825944Sjoerg switch (sp->state[cp->protoidx]) { 199925944Sjoerg case STATE_CLOSED: 200025944Sjoerg case STATE_CLOSING: 200125944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 20024910Swollman break; 200325944Sjoerg case STATE_STOPPED: 200441881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 200525944Sjoerg (cp->tls)(sp); 200641881Sphk break; 200725944Sjoerg case STATE_STOPPING: 200825944Sjoerg case STATE_REQ_SENT: 200925944Sjoerg case STATE_ACK_RCVD: 201025944Sjoerg case STATE_ACK_SENT: 201125944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 201225944Sjoerg break; 201325944Sjoerg case STATE_OPENED: 201425944Sjoerg (cp->tld)(sp); 201525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 201625944Sjoerg break; 201725944Sjoerg default: 201840008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 201940008Sjoerg SPP_ARGS(ifp), cp->name, 202025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 202125944Sjoerg } 202225944Sjoerg} 20234910Swollman 202411189Sjkh 202525944Sjoergstatic void 202625944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 202725944Sjoerg{ 202825944Sjoerg STDDCL; 202925944Sjoerg 203025944Sjoerg if (debug) 203140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 203240008Sjoerg SPP_ARGS(ifp), cp->name, 203325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 203425944Sjoerg 203525944Sjoerg switch (sp->state[cp->protoidx]) { 203625944Sjoerg case STATE_INITIAL: 203741881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 203825944Sjoerg (cp->tls)(sp); 20394910Swollman break; 204025944Sjoerg case STATE_STARTING: 204125944Sjoerg break; 204225944Sjoerg case STATE_CLOSED: 204325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 204425944Sjoerg (cp->scr)(sp); 204525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 204625944Sjoerg break; 204725944Sjoerg case STATE_STOPPED: 204874703Sjoerg /* 204974703Sjoerg * Try escaping stopped state. This seems to bite 205074703Sjoerg * people occasionally, in particular for IPCP, 205174703Sjoerg * presumably following previous IPCP negotiation 205274703Sjoerg * aborts. Somehow, we must have missed a Down event 205374703Sjoerg * which would have caused a transition into starting 205474703Sjoerg * state, so as a bandaid we force the Down event now. 205574703Sjoerg * This effectively implements (something like the) 205674703Sjoerg * `restart' option mentioned in the state transition 205774703Sjoerg * table of RFC 1661. 205874703Sjoerg */ 205974703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 206074703Sjoerg (cp->tls)(sp); 206174703Sjoerg break; 206225944Sjoerg case STATE_STOPPING: 206325944Sjoerg case STATE_REQ_SENT: 206425944Sjoerg case STATE_ACK_RCVD: 206525944Sjoerg case STATE_ACK_SENT: 206625944Sjoerg case STATE_OPENED: 206725944Sjoerg break; 206825944Sjoerg case STATE_CLOSING: 206925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 207025944Sjoerg break; 207125944Sjoerg } 207225944Sjoerg} 20734910Swollman 207425944Sjoerg 207525944Sjoergstatic void 207625944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 207725944Sjoerg{ 207825944Sjoerg STDDCL; 207925944Sjoerg 208025944Sjoerg if (debug) 208140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 208240008Sjoerg SPP_ARGS(ifp), cp->name, 208325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 208425944Sjoerg 208525944Sjoerg switch (sp->state[cp->protoidx]) { 208625944Sjoerg case STATE_INITIAL: 208725944Sjoerg case STATE_CLOSED: 208825944Sjoerg case STATE_CLOSING: 20894910Swollman break; 209025944Sjoerg case STATE_STARTING: 209141881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 209225944Sjoerg (cp->tlf)(sp); 20934910Swollman break; 209425944Sjoerg case STATE_STOPPED: 209525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 20964910Swollman break; 209725944Sjoerg case STATE_STOPPING: 209825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20994910Swollman break; 210025944Sjoerg case STATE_OPENED: 210125944Sjoerg (cp->tld)(sp); 2102102412Scharnier /* FALLTHROUGH */ 210325944Sjoerg case STATE_REQ_SENT: 210425944Sjoerg case STATE_ACK_RCVD: 210525944Sjoerg case STATE_ACK_SENT: 210625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 210778064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 210878064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 210925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 21104910Swollman break; 21114910Swollman } 21124910Swollman} 21134910Swollman 211425944Sjoergstatic void 211525944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 211625944Sjoerg{ 211725944Sjoerg STDDCL; 211825944Sjoerg int s; 211925944Sjoerg 212025944Sjoerg s = splimp(); 2121138745Srik SPPP_LOCK(sp); 212225944Sjoerg if (debug) 212340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 212440008Sjoerg SPP_ARGS(ifp), cp->name, 212525944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 212625944Sjoerg sp->rst_counter[cp->protoidx]); 212725944Sjoerg 212825944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 212925944Sjoerg /* TO- event */ 213025944Sjoerg switch (sp->state[cp->protoidx]) { 213125944Sjoerg case STATE_CLOSING: 213241881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 213325944Sjoerg (cp->tlf)(sp); 213425944Sjoerg break; 213525944Sjoerg case STATE_STOPPING: 213641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 213725944Sjoerg (cp->tlf)(sp); 213825944Sjoerg break; 213925944Sjoerg case STATE_REQ_SENT: 214025944Sjoerg case STATE_ACK_RCVD: 214125944Sjoerg case STATE_ACK_SENT: 214241881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 214325944Sjoerg (cp->tlf)(sp); 214425944Sjoerg break; 214525944Sjoerg } 214625944Sjoerg else 214725944Sjoerg /* TO+ event */ 214825944Sjoerg switch (sp->state[cp->protoidx]) { 214925944Sjoerg case STATE_CLOSING: 215025944Sjoerg case STATE_STOPPING: 215178064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 215278064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 2153138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2154138745Srik cp->TO, (void *)sp); 215525944Sjoerg break; 215625944Sjoerg case STATE_REQ_SENT: 215725944Sjoerg case STATE_ACK_RCVD: 215825944Sjoerg (cp->scr)(sp); 215925944Sjoerg /* sppp_cp_change_state() will restart the timer */ 216025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 216125944Sjoerg break; 216225944Sjoerg case STATE_ACK_SENT: 216325944Sjoerg (cp->scr)(sp); 2164138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2165138745Srik cp->TO, (void *)sp); 216625944Sjoerg break; 216725944Sjoerg } 216825944Sjoerg 2169138745Srik SPPP_UNLOCK(sp); 217025944Sjoerg splx(s); 217125944Sjoerg} 217225944Sjoerg 217311189Sjkh/* 217425944Sjoerg * Change the state of a control protocol in the state automaton. 217525944Sjoerg * Takes care of starting/stopping the restart timer. 217611189Sjkh */ 2177105228Sphkstatic void 217825944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 217925944Sjoerg{ 218025944Sjoerg sp->state[cp->protoidx] = newstate; 218125944Sjoerg 2182138745Srik callout_stop (&sp->ch[cp->protoidx]); 2183138745Srik 218425944Sjoerg switch (newstate) { 218525944Sjoerg case STATE_INITIAL: 218625944Sjoerg case STATE_STARTING: 218725944Sjoerg case STATE_CLOSED: 218825944Sjoerg case STATE_STOPPED: 218925944Sjoerg case STATE_OPENED: 219025944Sjoerg break; 219125944Sjoerg case STATE_CLOSING: 219225944Sjoerg case STATE_STOPPING: 219325944Sjoerg case STATE_REQ_SENT: 219425944Sjoerg case STATE_ACK_RCVD: 219525944Sjoerg case STATE_ACK_SENT: 2196138745Srik callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout, 2197138745Srik cp->TO, (void *)sp); 219825944Sjoerg break; 219925944Sjoerg } 220025944Sjoerg} 220170199Sjhay 220270199Sjhay/* 220325944Sjoerg *--------------------------------------------------------------------------* 220425944Sjoerg * * 220525944Sjoerg * The LCP implementation. * 220625944Sjoerg * * 220725944Sjoerg *--------------------------------------------------------------------------* 220825944Sjoerg */ 220925944Sjoergstatic void 2210138745Sriksppp_pp_up(struct sppp *sp) 2211138745Srik{ 2212138745Srik SPPP_LOCK(sp); 2213138745Srik lcp.Up(sp); 2214138745Srik SPPP_UNLOCK(sp); 2215138745Srik} 2216138745Srik 2217138745Srikstatic void 2218138745Sriksppp_pp_down(struct sppp *sp) 2219138745Srik{ 2220138745Srik SPPP_LOCK(sp); 2221138745Srik lcp.Down(sp); 2222138745Srik SPPP_UNLOCK(sp); 2223138745Srik} 2224138745Srik 2225138745Srikstatic void 222625944Sjoergsppp_lcp_init(struct sppp *sp) 222725944Sjoerg{ 222825944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 222925944Sjoerg sp->lcp.magic = 0; 223025944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 223125944Sjoerg sp->fail_counter[IDX_LCP] = 0; 223278064Sume sp->pp_seq[IDX_LCP] = 0; 223378064Sume sp->pp_rseq[IDX_LCP] = 0; 223425944Sjoerg sp->lcp.protos = 0; 223525944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 223630300Sjoerg 223744145Sphk /* Note that these values are relevant for all control protocols */ 223844145Sphk sp->lcp.timeout = 3 * hz; 223925944Sjoerg sp->lcp.max_terminate = 2; 224025944Sjoerg sp->lcp.max_configure = 10; 224125944Sjoerg sp->lcp.max_failure = 10; 2242138745Srik callout_init(&sp->ch[IDX_LCP], 2243147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 224425944Sjoerg} 224525944Sjoerg 224625944Sjoergstatic void 224725944Sjoergsppp_lcp_up(struct sppp *sp) 224825944Sjoerg{ 224925944Sjoerg STDDCL; 225025944Sjoerg 225170199Sjhay sp->pp_alivecnt = 0; 225270199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 225370199Sjhay sp->lcp.magic = 0; 225470199Sjhay sp->lcp.protos = 0; 225570199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 225625944Sjoerg /* 225775321Sjoerg * If we are authenticator, negotiate LCP_AUTH 225875321Sjoerg */ 225975321Sjoerg if (sp->hisauth.proto != 0) 226075321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 226175321Sjoerg else 226275321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 226375321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 226475321Sjoerg /* 226530300Sjoerg * If this interface is passive or dial-on-demand, and we are 226630300Sjoerg * still in Initial state, it means we've got an incoming 226730300Sjoerg * call. Activate the interface. 226825944Sjoerg */ 226925944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 227025944Sjoerg if (debug) 227125944Sjoerg log(LOG_DEBUG, 227240008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 2273148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 227430300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 227530300Sjoerg if (debug) 227669211Sphk log(-1, "(incoming call)\n"); 227730300Sjoerg sp->pp_flags |= PP_CALLIN; 227830300Sjoerg lcp.Open(sp); 227930300Sjoerg } else if (debug) 228069211Sphk log(-1, "\n"); 228188710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 228288710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 2283148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 228488710Sjoerg lcp.Open(sp); 228525944Sjoerg } 228625944Sjoerg 228725944Sjoerg sppp_up_event(&lcp, sp); 228825944Sjoerg} 228925944Sjoerg 229025944Sjoergstatic void 229125944Sjoergsppp_lcp_down(struct sppp *sp) 229225944Sjoerg{ 229325944Sjoerg STDDCL; 229425944Sjoerg 229525944Sjoerg sppp_down_event(&lcp, sp); 229625944Sjoerg 229725944Sjoerg /* 229825944Sjoerg * If this is neither a dial-on-demand nor a passive 229925944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 230025944Sjoerg * administrator can force a redial by another ``ifconfig 230125944Sjoerg * up''. XXX For leased line operation, should we immediately 230225944Sjoerg * try to reopen the connection here? 230325944Sjoerg */ 230425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 230525944Sjoerg log(LOG_INFO, 230642066Sphk SPP_FMT "Down event, taking interface down.\n", 230740008Sjoerg SPP_ARGS(ifp)); 230825944Sjoerg if_down(ifp); 230925944Sjoerg } else { 231025944Sjoerg if (debug) 231125944Sjoerg log(LOG_DEBUG, 231240008Sjoerg SPP_FMT "Down event (carrier loss)\n", 231340008Sjoerg SPP_ARGS(ifp)); 231470199Sjhay sp->pp_flags &= ~PP_CALLIN; 231570199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 231670199Sjhay lcp.Close(sp); 2317148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 231825944Sjoerg } 231925944Sjoerg} 232025944Sjoerg 232125944Sjoergstatic void 232225944Sjoergsppp_lcp_open(struct sppp *sp) 232325944Sjoerg{ 232425944Sjoerg sppp_open_event(&lcp, sp); 232525944Sjoerg} 232625944Sjoerg 232725944Sjoergstatic void 232825944Sjoergsppp_lcp_close(struct sppp *sp) 232925944Sjoerg{ 233025944Sjoerg sppp_close_event(&lcp, sp); 233125944Sjoerg} 233225944Sjoerg 233325944Sjoergstatic void 233425944Sjoergsppp_lcp_TO(void *cookie) 233525944Sjoerg{ 233625944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 233725944Sjoerg} 233825944Sjoerg 233925944Sjoerg/* 234025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 234125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 234225944Sjoerg * caused action scn. (The return value is used to make the state 234325944Sjoerg * transition decision in the state automaton.) 234425944Sjoerg */ 234512820Sphkstatic int 234625944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 23474910Swollman{ 234825944Sjoerg STDDCL; 234911189Sjkh u_char *buf, *r, *p; 235025944Sjoerg int origlen, rlen; 235125944Sjoerg u_long nmagic; 235230300Sjoerg u_short authproto; 23534910Swollman 235411189Sjkh len -= 4; 235525944Sjoerg origlen = len; 235611189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 235711189Sjkh if (! buf) 235811189Sjkh return (0); 23594910Swollman 236025706Sjoerg if (debug) 236140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 236240008Sjoerg SPP_ARGS(ifp)); 236325706Sjoerg 236425944Sjoerg /* pass 1: check for things that need to be rejected */ 236511189Sjkh p = (void*) (h+1); 2366161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2367161556Scperciva len-=p[1], p+=p[1]) { 236825944Sjoerg if (debug) 236969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 237011189Sjkh switch (*p) { 237111189Sjkh case LCP_OPT_MAGIC: 237225944Sjoerg /* Magic number. */ 237370199Sjhay if (len >= 6 && p[1] == 6) 237470199Sjhay continue; 237570199Sjhay if (debug) 237670199Sjhay log(-1, "[invalid] "); 237770199Sjhay break; 237825944Sjoerg case LCP_OPT_ASYNC_MAP: 237925944Sjoerg /* Async control character map. */ 238070199Sjhay if (len >= 6 && p[1] == 6) 238125944Sjoerg continue; 238225944Sjoerg if (debug) 238369211Sphk log(-1, "[invalid] "); 238425944Sjoerg break; 238525944Sjoerg case LCP_OPT_MRU: 238625944Sjoerg /* Maximum receive unit. */ 238725944Sjoerg if (len >= 4 && p[1] == 4) 238825944Sjoerg continue; 238925944Sjoerg if (debug) 239069211Sphk log(-1, "[invalid] "); 239125944Sjoerg break; 239230300Sjoerg case LCP_OPT_AUTH_PROTO: 239330300Sjoerg if (len < 4) { 239430300Sjoerg if (debug) 239569211Sphk log(-1, "[invalid] "); 239630300Sjoerg break; 239730300Sjoerg } 239830300Sjoerg authproto = (p[2] << 8) + p[3]; 239930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 240030300Sjoerg if (debug) 240169211Sphk log(-1, "[invalid chap len] "); 240230300Sjoerg break; 240330300Sjoerg } 240430300Sjoerg if (sp->myauth.proto == 0) { 240530300Sjoerg /* we are not configured to do auth */ 240630300Sjoerg if (debug) 240769211Sphk log(-1, "[not configured] "); 240830300Sjoerg break; 240930300Sjoerg } 241030300Sjoerg /* 241130300Sjoerg * Remote want us to authenticate, remember this, 241230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 241330300Sjoerg * up. 241430300Sjoerg */ 241530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 241630300Sjoerg continue; 241725944Sjoerg default: 241825944Sjoerg /* Others not supported. */ 241925944Sjoerg if (debug) 242069211Sphk log(-1, "[rej] "); 242125944Sjoerg break; 242225944Sjoerg } 242325944Sjoerg /* Add the option to rejected list. */ 242425944Sjoerg bcopy (p, r, p[1]); 242525944Sjoerg r += p[1]; 242625944Sjoerg rlen += p[1]; 242725944Sjoerg } 242825944Sjoerg if (rlen) { 242925944Sjoerg if (debug) 243069211Sphk log(-1, " send conf-rej\n"); 243125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 243225944Sjoerg return 0; 243325944Sjoerg } else if (debug) 243469211Sphk log(-1, "\n"); 243525944Sjoerg 243625944Sjoerg /* 243725944Sjoerg * pass 2: check for option values that are unacceptable and 243825944Sjoerg * thus require to be nak'ed. 243925944Sjoerg */ 244025944Sjoerg if (debug) 244140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 244240008Sjoerg SPP_ARGS(ifp)); 244325944Sjoerg 244425944Sjoerg p = (void*) (h+1); 244525944Sjoerg len = origlen; 2446161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 2447161556Scperciva len-=p[1], p+=p[1]) { 244825944Sjoerg if (debug) 244969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 245025944Sjoerg switch (*p) { 245125944Sjoerg case LCP_OPT_MAGIC: 245211189Sjkh /* Magic number -- extract. */ 245325944Sjoerg nmagic = (u_long)p[2] << 24 | 245425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 245525944Sjoerg if (nmagic != sp->lcp.magic) { 245670199Sjhay sp->pp_loopcnt = 0; 245725706Sjoerg if (debug) 245869211Sphk log(-1, "0x%lx ", nmagic); 245911189Sjkh continue; 246011189Sjkh } 246170199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 246269211Sphk log(-1, "[glitch] "); 246325944Sjoerg ++sp->pp_loopcnt; 246425944Sjoerg /* 246525944Sjoerg * We negate our magic here, and NAK it. If 246625944Sjoerg * we see it later in an NAK packet, we 246725944Sjoerg * suggest a new one. 246825944Sjoerg */ 246925944Sjoerg nmagic = ~sp->lcp.magic; 247025944Sjoerg /* Gonna NAK it. */ 247125944Sjoerg p[2] = nmagic >> 24; 247225944Sjoerg p[3] = nmagic >> 16; 247325944Sjoerg p[4] = nmagic >> 8; 247425944Sjoerg p[5] = nmagic; 247511189Sjkh break; 247625944Sjoerg 247711189Sjkh case LCP_OPT_ASYNC_MAP: 247888506Sjoerg /* 247988506Sjoerg * Async control character map -- just ignore it. 248088506Sjoerg * 248188506Sjoerg * Quote from RFC 1662, chapter 6: 248288506Sjoerg * To enable this functionality, synchronous PPP 248388506Sjoerg * implementations MUST always respond to the 248488506Sjoerg * Async-Control-Character-Map Configuration 248588506Sjoerg * Option with the LCP Configure-Ack. However, 248688506Sjoerg * acceptance of the Configuration Option does 248788506Sjoerg * not imply that the synchronous implementation 248888506Sjoerg * will do any ACCM mapping. Instead, all such 248988506Sjoerg * octet mapping will be performed by the 249088506Sjoerg * asynchronous-to-synchronous converter. 249188506Sjoerg */ 249288506Sjoerg continue; 249325944Sjoerg 249411189Sjkh case LCP_OPT_MRU: 249525944Sjoerg /* 249625944Sjoerg * Maximum receive unit. Always agreeable, 249725944Sjoerg * but ignored by now. 249825944Sjoerg */ 249925944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 250025706Sjoerg if (debug) 250169211Sphk log(-1, "%lu ", sp->lcp.their_mru); 250211189Sjkh continue; 250330300Sjoerg 250430300Sjoerg case LCP_OPT_AUTH_PROTO: 250530300Sjoerg authproto = (p[2] << 8) + p[3]; 250630300Sjoerg if (sp->myauth.proto != authproto) { 250730300Sjoerg /* not agreed, nak */ 250830300Sjoerg if (debug) 250969211Sphk log(-1, "[mine %s != his %s] ", 251030300Sjoerg sppp_proto_name(sp->hisauth.proto), 251130300Sjoerg sppp_proto_name(authproto)); 251230300Sjoerg p[2] = sp->myauth.proto >> 8; 251330300Sjoerg p[3] = sp->myauth.proto; 251430300Sjoerg break; 251530300Sjoerg } 251630300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 251730300Sjoerg if (debug) 251869211Sphk log(-1, "[chap not MD5] "); 251939981Sjoerg p[4] = CHAP_MD5; 252030300Sjoerg break; 252130300Sjoerg } 252230300Sjoerg continue; 252311189Sjkh } 252425944Sjoerg /* Add the option to nak'ed list. */ 252525706Sjoerg bcopy (p, r, p[1]); 252625706Sjoerg r += p[1]; 252711189Sjkh rlen += p[1]; 252812436Speter } 252925706Sjoerg if (rlen) { 253070199Sjhay /* 253170199Sjhay * Local and remote magics equal -- loopback? 253270199Sjhay */ 253370199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 253470199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 253570199Sjhay printf (SPP_FMT "loopback\n", 253670199Sjhay SPP_ARGS(ifp)); 253770199Sjhay if (ifp->if_flags & IFF_UP) { 253870199Sjhay if_down(ifp); 253970199Sjhay sppp_qflush(&sp->pp_cpq); 254070199Sjhay /* XXX ? */ 254170199Sjhay lcp.Down(sp); 254270199Sjhay lcp.Up(sp); 254370199Sjhay } 2544131093Srik } else if (!sp->pp_loopcnt && 2545131093Srik ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 254628036Sjoerg if (debug) 254769211Sphk log(-1, " max_failure (%d) exceeded, " 254828036Sjoerg "send conf-rej\n", 254928036Sjoerg sp->lcp.max_failure); 255028036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 255128036Sjoerg } else { 255228036Sjoerg if (debug) 255369211Sphk log(-1, " send conf-nak\n"); 255428036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 255528036Sjoerg } 255625944Sjoerg } else { 255725944Sjoerg if (debug) 255869211Sphk log(-1, " send conf-ack\n"); 255928036Sjoerg sp->fail_counter[IDX_LCP] = 0; 256025944Sjoerg sp->pp_loopcnt = 0; 256125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 256225944Sjoerg h->ident, origlen, h+1); 256325944Sjoerg } 256425944Sjoerg 256511189Sjkh free (buf, M_TEMP); 256611189Sjkh return (rlen == 0); 25674910Swollman} 25684910Swollman 256925944Sjoerg/* 257025944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 257125944Sjoerg * negotiation. 257225944Sjoerg */ 257312820Sphkstatic void 257425944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 25754910Swollman{ 257625944Sjoerg STDDCL; 257725944Sjoerg u_char *buf, *p; 25784910Swollman 257925944Sjoerg len -= 4; 258025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 258125944Sjoerg if (!buf) 25824910Swollman return; 258325944Sjoerg 258425944Sjoerg if (debug) 258540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 258640008Sjoerg SPP_ARGS(ifp)); 258725944Sjoerg 258825944Sjoerg p = (void*) (h+1); 2589161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2590161556Scperciva len -= p[1], p += p[1]) { 259125944Sjoerg if (debug) 259269211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 259325944Sjoerg switch (*p) { 259425944Sjoerg case LCP_OPT_MAGIC: 259525944Sjoerg /* Magic number -- can't use it, use 0 */ 259625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 259725944Sjoerg sp->lcp.magic = 0; 259825944Sjoerg break; 259925944Sjoerg case LCP_OPT_MRU: 260025944Sjoerg /* 260125944Sjoerg * Should not be rejected anyway, since we only 260225944Sjoerg * negotiate a MRU if explicitly requested by 260325944Sjoerg * peer. 260425944Sjoerg */ 260525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 260625944Sjoerg break; 260730300Sjoerg case LCP_OPT_AUTH_PROTO: 260830300Sjoerg /* 260930300Sjoerg * Peer doesn't want to authenticate himself, 261030300Sjoerg * deny unless this is a dialout call, and 261130300Sjoerg * AUTHFLAG_NOCALLOUT is set. 261230300Sjoerg */ 261330300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 261430300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 261530300Sjoerg if (debug) 261669211Sphk log(-1, "[don't insist on auth " 261730300Sjoerg "for callout]"); 261830300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 261930300Sjoerg break; 262030300Sjoerg } 262130300Sjoerg if (debug) 262269211Sphk log(-1, "[access denied]\n"); 262330300Sjoerg lcp.Close(sp); 262430300Sjoerg break; 262525944Sjoerg } 26264910Swollman } 262725944Sjoerg if (debug) 262869211Sphk log(-1, "\n"); 262925944Sjoerg free (buf, M_TEMP); 263025944Sjoerg return; 263125944Sjoerg} 263225944Sjoerg 263325944Sjoerg/* 263425944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 263525944Sjoerg * negotiation. 263625944Sjoerg */ 263725944Sjoergstatic void 263825944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 263925944Sjoerg{ 264025944Sjoerg STDDCL; 264125944Sjoerg u_char *buf, *p; 264225944Sjoerg u_long magic; 264325944Sjoerg 264425944Sjoerg len -= 4; 264525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 264625944Sjoerg if (!buf) 264725944Sjoerg return; 264825944Sjoerg 264925944Sjoerg if (debug) 265040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 265140008Sjoerg SPP_ARGS(ifp)); 265225944Sjoerg 265325944Sjoerg p = (void*) (h+1); 2654161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 2655161556Scperciva len -= p[1], p += p[1]) { 265625706Sjoerg if (debug) 265769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 265825944Sjoerg switch (*p) { 265925944Sjoerg case LCP_OPT_MAGIC: 266025944Sjoerg /* Magic number -- renegotiate */ 266125944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 266225944Sjoerg len >= 6 && p[1] == 6) { 266325944Sjoerg magic = (u_long)p[2] << 24 | 266425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 266525944Sjoerg /* 266625944Sjoerg * If the remote magic is our negated one, 266725944Sjoerg * this looks like a loopback problem. 266825944Sjoerg * Suggest a new magic to make sure. 266925944Sjoerg */ 267025944Sjoerg if (magic == ~sp->lcp.magic) { 267125944Sjoerg if (debug) 267269211Sphk log(-1, "magic glitch "); 267342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 267435064Sphk sp->lcp.magic = random(); 267540008Sjoerg#else 267640008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 267740008Sjoerg#endif 267825944Sjoerg } else { 267925944Sjoerg sp->lcp.magic = magic; 268025944Sjoerg if (debug) 268169211Sphk log(-1, "%lu ", magic); 268225944Sjoerg } 268325944Sjoerg } 268425944Sjoerg break; 268525944Sjoerg case LCP_OPT_MRU: 268625944Sjoerg /* 268725944Sjoerg * Peer wants to advise us to negotiate an MRU. 268825944Sjoerg * Agree on it if it's reasonable, or use 268925944Sjoerg * default otherwise. 269025944Sjoerg */ 269125944Sjoerg if (len >= 4 && p[1] == 4) { 269225944Sjoerg u_int mru = p[2] * 256 + p[3]; 269325944Sjoerg if (debug) 269469211Sphk log(-1, "%d ", mru); 269525944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 269625944Sjoerg mru = PP_MTU; 269725944Sjoerg sp->lcp.mru = mru; 269825944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 269925944Sjoerg } 270025944Sjoerg break; 270130300Sjoerg case LCP_OPT_AUTH_PROTO: 270230300Sjoerg /* 270330300Sjoerg * Peer doesn't like our authentication method, 270430300Sjoerg * deny. 270530300Sjoerg */ 270630300Sjoerg if (debug) 270769211Sphk log(-1, "[access denied]\n"); 270830300Sjoerg lcp.Close(sp); 270930300Sjoerg break; 27104910Swollman } 271125944Sjoerg } 271225944Sjoerg if (debug) 271369211Sphk log(-1, "\n"); 271425944Sjoerg free (buf, M_TEMP); 271525944Sjoerg return; 271625944Sjoerg} 271711189Sjkh 271825944Sjoergstatic void 271925944Sjoergsppp_lcp_tlu(struct sppp *sp) 272025944Sjoerg{ 272142066Sphk STDDCL; 272225944Sjoerg int i; 272325944Sjoerg u_long mask; 272425944Sjoerg 272525944Sjoerg /* XXX ? */ 272625944Sjoerg if (! (ifp->if_flags & IFF_UP) && 2727148887Srwatson (ifp->if_drv_flags & IFF_DRV_RUNNING)) { 272825944Sjoerg /* Coming out of loopback mode. */ 272925944Sjoerg if_up(ifp); 273040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 273125944Sjoerg } 273225944Sjoerg 273325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 273425944Sjoerg if ((cps[i])->flags & CP_QUAL) 273525944Sjoerg (cps[i])->Open(sp); 273625944Sjoerg 273730300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 273830300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 273925944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 274025944Sjoerg else 274125944Sjoerg sp->pp_phase = PHASE_NETWORK; 274225944Sjoerg 274342066Sphk if (debug) 274442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 274542066Sphk sppp_phase_name(sp->pp_phase)); 274625944Sjoerg 274730300Sjoerg /* 274830300Sjoerg * Open all authentication protocols. This is even required 274930300Sjoerg * if we already proceeded to network phase, since it might be 275030300Sjoerg * that remote wants us to authenticate, so we might have to 275130300Sjoerg * send a PAP request. Undesired authentication protocols 275230300Sjoerg * don't do anything when they get an Open event. 275330300Sjoerg */ 275430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 275530300Sjoerg if ((cps[i])->flags & CP_AUTH) 275630300Sjoerg (cps[i])->Open(sp); 275730300Sjoerg 275830300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 275925944Sjoerg /* Notify all NCPs. */ 276025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 276188723Sjoerg if (((cps[i])->flags & CP_NCP) && 276288723Sjoerg /* 276388723Sjoerg * XXX 276488723Sjoerg * Hack to administratively disable IPv6 if 276588723Sjoerg * not desired. Perhaps we should have another 276688723Sjoerg * flag for this, but right now, we can make 276788723Sjoerg * all struct cp's read/only. 276888723Sjoerg */ 276988723Sjoerg (cps[i] != &ipv6cp || 277088723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 277125944Sjoerg (cps[i])->Open(sp); 277225944Sjoerg } 277325944Sjoerg 277425944Sjoerg /* Send Up events to all started protos. */ 277525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 277688706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 277725944Sjoerg (cps[i])->Up(sp); 277825944Sjoerg 277942104Sphk /* notify low-level driver of state change */ 278042104Sphk if (sp->pp_chg) 278142104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 278242104Sphk 278325944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 278425944Sjoerg /* if no NCP is starting, close down */ 278530300Sjoerg sppp_lcp_check_and_close(sp); 278625944Sjoerg} 278725944Sjoerg 278825944Sjoergstatic void 278925944Sjoergsppp_lcp_tld(struct sppp *sp) 279025944Sjoerg{ 279142066Sphk STDDCL; 279225944Sjoerg int i; 279325944Sjoerg u_long mask; 279425944Sjoerg 279525944Sjoerg sp->pp_phase = PHASE_TERMINATE; 279625944Sjoerg 279742066Sphk if (debug) 279842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 279942066Sphk sppp_phase_name(sp->pp_phase)); 280025944Sjoerg 280125944Sjoerg /* 280225944Sjoerg * Take upper layers down. We send the Down event first and 280325944Sjoerg * the Close second to prevent the upper layers from sending 280425944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 280525944Sjoerg * describes it. 280625944Sjoerg */ 280725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 280888706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 280925944Sjoerg (cps[i])->Down(sp); 281025944Sjoerg (cps[i])->Close(sp); 281125944Sjoerg } 281225944Sjoerg} 281325944Sjoerg 281425944Sjoergstatic void 281525944Sjoergsppp_lcp_tls(struct sppp *sp) 281625944Sjoerg{ 281742066Sphk STDDCL; 281825944Sjoerg 281925944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 282025944Sjoerg 282142066Sphk if (debug) 282242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 282342066Sphk sppp_phase_name(sp->pp_phase)); 282425944Sjoerg 282525944Sjoerg /* Notify lower layer if desired. */ 282625944Sjoerg if (sp->pp_tls) 282725944Sjoerg (sp->pp_tls)(sp); 282841881Sphk else 282941881Sphk (sp->pp_up)(sp); 283025944Sjoerg} 283125944Sjoerg 283225944Sjoergstatic void 283325944Sjoergsppp_lcp_tlf(struct sppp *sp) 283425944Sjoerg{ 283542066Sphk STDDCL; 283625944Sjoerg 283725944Sjoerg sp->pp_phase = PHASE_DEAD; 283842066Sphk if (debug) 283942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 284042066Sphk sppp_phase_name(sp->pp_phase)); 284125944Sjoerg 284225944Sjoerg /* Notify lower layer if desired. */ 284325944Sjoerg if (sp->pp_tlf) 284425944Sjoerg (sp->pp_tlf)(sp); 284541881Sphk else 284641881Sphk (sp->pp_down)(sp); 284725944Sjoerg} 284825944Sjoerg 284925944Sjoergstatic void 285025944Sjoergsppp_lcp_scr(struct sppp *sp) 285125944Sjoerg{ 285230300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 285325944Sjoerg int i = 0; 285430300Sjoerg u_short authproto; 285525944Sjoerg 285625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 285725944Sjoerg if (! sp->lcp.magic) 285842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 285935064Sphk sp->lcp.magic = random(); 286040008Sjoerg#else 286140008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 286240008Sjoerg#endif 286325944Sjoerg opt[i++] = LCP_OPT_MAGIC; 286425944Sjoerg opt[i++] = 6; 286525944Sjoerg opt[i++] = sp->lcp.magic >> 24; 286625944Sjoerg opt[i++] = sp->lcp.magic >> 16; 286725944Sjoerg opt[i++] = sp->lcp.magic >> 8; 286825944Sjoerg opt[i++] = sp->lcp.magic; 286925944Sjoerg } 287025944Sjoerg 287125944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 287225944Sjoerg opt[i++] = LCP_OPT_MRU; 287325944Sjoerg opt[i++] = 4; 287425944Sjoerg opt[i++] = sp->lcp.mru >> 8; 287525944Sjoerg opt[i++] = sp->lcp.mru; 287625944Sjoerg } 287725944Sjoerg 287830300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 287930300Sjoerg authproto = sp->hisauth.proto; 288030300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 288130300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 288230300Sjoerg opt[i++] = authproto >> 8; 288330300Sjoerg opt[i++] = authproto; 288430300Sjoerg if (authproto == PPP_CHAP) 288530300Sjoerg opt[i++] = CHAP_MD5; 288630300Sjoerg } 288730300Sjoerg 288878064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 288925944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 289025944Sjoerg} 289125944Sjoerg 289225944Sjoerg/* 289330300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 289430300Sjoerg */ 289530300Sjoergstatic int 289630300Sjoergsppp_ncp_check(struct sppp *sp) 289730300Sjoerg{ 289830300Sjoerg int i, mask; 289930300Sjoerg 290030300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 290188706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 290230300Sjoerg return 1; 290330300Sjoerg return 0; 290430300Sjoerg} 290530300Sjoerg 290630300Sjoerg/* 290725944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 290825944Sjoerg * Called by the NCPs during their tlf action handling. 290925944Sjoerg */ 291025944Sjoergstatic void 291130300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 291225944Sjoerg{ 291325944Sjoerg 291430300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 291530300Sjoerg /* don't bother, we are already going down */ 291630300Sjoerg return; 291730300Sjoerg 291830300Sjoerg if (sppp_ncp_check(sp)) 291930300Sjoerg return; 292030300Sjoerg 292125944Sjoerg lcp.Close(sp); 292225944Sjoerg} 292370199Sjhay 292470199Sjhay/* 292525944Sjoerg *--------------------------------------------------------------------------* 292625944Sjoerg * * 292725944Sjoerg * The IPCP implementation. * 292825944Sjoerg * * 292925944Sjoerg *--------------------------------------------------------------------------* 293025944Sjoerg */ 293125944Sjoerg 293225944Sjoergstatic void 293325944Sjoergsppp_ipcp_init(struct sppp *sp) 293425944Sjoerg{ 293525944Sjoerg sp->ipcp.opts = 0; 293625944Sjoerg sp->ipcp.flags = 0; 293725944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 293825944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 293978064Sume sp->pp_seq[IDX_IPCP] = 0; 294078064Sume sp->pp_rseq[IDX_IPCP] = 0; 2941138745Srik callout_init(&sp->ch[IDX_IPCP], 2942147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 294325944Sjoerg} 294425944Sjoerg 294525944Sjoergstatic void 294625944Sjoergsppp_ipcp_up(struct sppp *sp) 294725944Sjoerg{ 294825944Sjoerg sppp_up_event(&ipcp, sp); 294925944Sjoerg} 295025944Sjoerg 295125944Sjoergstatic void 295225944Sjoergsppp_ipcp_down(struct sppp *sp) 295325944Sjoerg{ 295425944Sjoerg sppp_down_event(&ipcp, sp); 295525944Sjoerg} 295625944Sjoerg 295725944Sjoergstatic void 295825944Sjoergsppp_ipcp_open(struct sppp *sp) 295925944Sjoerg{ 296025944Sjoerg STDDCL; 296125944Sjoerg u_long myaddr, hisaddr; 296225944Sjoerg 296388534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 296488534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 296588700Sjoerg sp->ipcp.opts = 0; 296642104Sphk 296730300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 296825944Sjoerg /* 296925944Sjoerg * If we don't have his address, this probably means our 297025944Sjoerg * interface doesn't want to talk IP at all. (This could 297125944Sjoerg * be the case if somebody wants to speak only IPX, for 297225944Sjoerg * example.) Don't open IPCP in this case. 297325944Sjoerg */ 297425944Sjoerg if (hisaddr == 0L) { 297525944Sjoerg /* XXX this message should go away */ 297625944Sjoerg if (debug) 297740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 297840008Sjoerg SPP_ARGS(ifp)); 297925944Sjoerg return; 298025944Sjoerg } 298125944Sjoerg if (myaddr == 0L) { 298225944Sjoerg /* 298325944Sjoerg * I don't have an assigned address, so i need to 298425944Sjoerg * negotiate my address. 298525944Sjoerg */ 298625944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 298725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 298842104Sphk } else 298942104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 299088723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 299188534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 299288534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 299388534Sjoerg sp->ipcp.compress_cid = 1; 299488534Sjoerg } 299525944Sjoerg sppp_open_event(&ipcp, sp); 299625944Sjoerg} 299725944Sjoerg 299825944Sjoergstatic void 299925944Sjoergsppp_ipcp_close(struct sppp *sp) 300025944Sjoerg{ 300125944Sjoerg sppp_close_event(&ipcp, sp); 300225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 300325944Sjoerg /* 300425944Sjoerg * My address was dynamic, clear it again. 300525944Sjoerg */ 300625944Sjoerg sppp_set_ip_addr(sp, 0L); 300725944Sjoerg} 300825944Sjoerg 300925944Sjoergstatic void 301025944Sjoergsppp_ipcp_TO(void *cookie) 301125944Sjoerg{ 301225944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 301325944Sjoerg} 301425944Sjoerg 301525944Sjoerg/* 301625944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 301725944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 301825944Sjoerg * caused action scn. (The return value is used to make the state 301925944Sjoerg * transition decision in the state automaton.) 302025944Sjoerg */ 302125944Sjoergstatic int 302225944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 302325944Sjoerg{ 302425944Sjoerg u_char *buf, *r, *p; 3025147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 302625944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 302725944Sjoerg u_long hisaddr, desiredaddr; 302842104Sphk int gotmyaddr = 0; 302988534Sjoerg int desiredcomp; 303025944Sjoerg 303125944Sjoerg len -= 4; 303225944Sjoerg origlen = len; 303325944Sjoerg /* 303425944Sjoerg * Make sure to allocate a buf that can at least hold a 303525944Sjoerg * conf-nak with an `address' option. We might need it below. 303625944Sjoerg */ 303725944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 303825944Sjoerg if (! buf) 303925944Sjoerg return (0); 304025944Sjoerg 304125944Sjoerg /* pass 1: see if we can recognize them */ 304225944Sjoerg if (debug) 304340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 304440008Sjoerg SPP_ARGS(ifp)); 304525944Sjoerg p = (void*) (h+1); 3046161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3047161556Scperciva len-=p[1], p+=p[1]) { 304825944Sjoerg if (debug) 304969211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 305025944Sjoerg switch (*p) { 305188534Sjoerg case IPCP_OPT_COMPRESSION: 305288723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 305388534Sjoerg /* VJ compression administratively disabled */ 305488534Sjoerg if (debug) 305588534Sjoerg log(-1, "[locally disabled] "); 305688534Sjoerg break; 305788534Sjoerg } 305888534Sjoerg /* 305988534Sjoerg * In theory, we should only conf-rej an 306088534Sjoerg * option that is shorter than RFC 1618 306188534Sjoerg * requires (i.e. < 4), and should conf-nak 306288534Sjoerg * anything else that is not VJ. However, 306388534Sjoerg * since our algorithm always uses the 306488534Sjoerg * original option to NAK it with new values, 306588534Sjoerg * things would become more complicated. In 306688534Sjoerg * pratice, the only commonly implemented IP 306788534Sjoerg * compression option is VJ anyway, so the 306888534Sjoerg * difference is negligible. 306988534Sjoerg */ 307088534Sjoerg if (len >= 6 && p[1] == 6) { 307188534Sjoerg /* 307288534Sjoerg * correctly formed compression option 307388534Sjoerg * that could be VJ compression 307488534Sjoerg */ 307588534Sjoerg continue; 307688534Sjoerg } 307788534Sjoerg if (debug) 307888534Sjoerg log(-1, 307988534Sjoerg "optlen %d [invalid/unsupported] ", 308088534Sjoerg p[1]); 308188534Sjoerg break; 308225944Sjoerg case IPCP_OPT_ADDRESS: 308325944Sjoerg if (len >= 6 && p[1] == 6) { 308425944Sjoerg /* correctly formed address option */ 308525944Sjoerg continue; 308625944Sjoerg } 308725706Sjoerg if (debug) 308869211Sphk log(-1, "[invalid] "); 308911189Sjkh break; 309025944Sjoerg default: 309125944Sjoerg /* Others not supported. */ 309225944Sjoerg if (debug) 309369211Sphk log(-1, "[rej] "); 30944910Swollman break; 30954910Swollman } 309625944Sjoerg /* Add the option to rejected list. */ 309725944Sjoerg bcopy (p, r, p[1]); 309825944Sjoerg r += p[1]; 309925944Sjoerg rlen += p[1]; 310025944Sjoerg } 310125944Sjoerg if (rlen) { 310225944Sjoerg if (debug) 310369211Sphk log(-1, " send conf-rej\n"); 310425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 310525944Sjoerg return 0; 310625944Sjoerg } else if (debug) 310769211Sphk log(-1, "\n"); 310825944Sjoerg 310925944Sjoerg /* pass 2: parse option values */ 311030300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 311125944Sjoerg if (debug) 311240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 311340008Sjoerg SPP_ARGS(ifp)); 311425944Sjoerg p = (void*) (h+1); 311525944Sjoerg len = origlen; 3116161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3117161556Scperciva len-=p[1], p+=p[1]) { 311825944Sjoerg if (debug) 311969211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 312025944Sjoerg switch (*p) { 312188534Sjoerg case IPCP_OPT_COMPRESSION: 312288534Sjoerg desiredcomp = p[2] << 8 | p[3]; 312388534Sjoerg /* We only support VJ */ 312488534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 312588534Sjoerg if (debug) 312688534Sjoerg log(-1, "VJ [ack] "); 312788534Sjoerg sp->ipcp.flags |= IPCP_VJ; 312888599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 312988534Sjoerg sp->ipcp.max_state = p[4]; 313088534Sjoerg sp->ipcp.compress_cid = p[5]; 313188534Sjoerg continue; 313288534Sjoerg } 313388534Sjoerg if (debug) 313488534Sjoerg log(-1, 313588534Sjoerg "compproto %#04x [not supported] ", 313688534Sjoerg desiredcomp); 313788534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 313888534Sjoerg p[3] = IPCP_COMP_VJ; 313988534Sjoerg p[4] = sp->ipcp.max_state; 314088534Sjoerg p[5] = sp->ipcp.compress_cid; 314188534Sjoerg break; 314225944Sjoerg case IPCP_OPT_ADDRESS: 314342104Sphk /* This is the address he wants in his end */ 314425944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 314525944Sjoerg p[4] << 8 | p[5]; 314633928Sphk if (desiredaddr == hisaddr || 314788702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 314825944Sjoerg /* 314925944Sjoerg * Peer's address is same as our value, 315088702Sjoerg * or we have set it to 0.0.0.* to 315133928Sphk * indicate that we do not really care, 315225944Sjoerg * this is agreeable. Gonna conf-ack 315325944Sjoerg * it. 315425944Sjoerg */ 315525944Sjoerg if (debug) 315669211Sphk log(-1, "%s [ack] ", 315742104Sphk sppp_dotted_quad(hisaddr)); 315825944Sjoerg /* record that we've seen it already */ 315925944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 316025944Sjoerg continue; 316125944Sjoerg } 316225944Sjoerg /* 316325944Sjoerg * The address wasn't agreeable. This is either 316425944Sjoerg * he sent us 0.0.0.0, asking to assign him an 316525944Sjoerg * address, or he send us another address not 316625944Sjoerg * matching our value. Either case, we gonna 316725944Sjoerg * conf-nak it with our value. 316842104Sphk * XXX: we should "rej" if hisaddr == 0 316925944Sjoerg */ 317025944Sjoerg if (debug) { 317125944Sjoerg if (desiredaddr == 0) 317269211Sphk log(-1, "[addr requested] "); 317325944Sjoerg else 317469211Sphk log(-1, "%s [not agreed] ", 317542104Sphk sppp_dotted_quad(desiredaddr)); 317625944Sjoerg 317725944Sjoerg } 317844235Sphk p[2] = hisaddr >> 24; 317944235Sphk p[3] = hisaddr >> 16; 318044235Sphk p[4] = hisaddr >> 8; 318144235Sphk p[5] = hisaddr; 318211189Sjkh break; 318325706Sjoerg } 318425944Sjoerg /* Add the option to nak'ed list. */ 318525944Sjoerg bcopy (p, r, p[1]); 318625944Sjoerg r += p[1]; 318725944Sjoerg rlen += p[1]; 318825944Sjoerg } 318925944Sjoerg 319025944Sjoerg /* 319125944Sjoerg * If we are about to conf-ack the request, but haven't seen 319225944Sjoerg * his address so far, gonna conf-nak it instead, with the 319325944Sjoerg * `address' option present and our idea of his address being 319425944Sjoerg * filled in there, to request negotiation of both addresses. 319525944Sjoerg * 319625944Sjoerg * XXX This can result in an endless req - nak loop if peer 319725944Sjoerg * doesn't want to send us his address. Q: What should we do 319825944Sjoerg * about it? XXX A: implement the max-failure counter. 319925944Sjoerg */ 320042104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 320125944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 320225944Sjoerg buf[1] = 6; 320325944Sjoerg buf[2] = hisaddr >> 24; 320425944Sjoerg buf[3] = hisaddr >> 16; 320525944Sjoerg buf[4] = hisaddr >> 8; 320625944Sjoerg buf[5] = hisaddr; 320725944Sjoerg rlen = 6; 320825706Sjoerg if (debug) 320969211Sphk log(-1, "still need hisaddr "); 321025944Sjoerg } 321125944Sjoerg 321225944Sjoerg if (rlen) { 321325706Sjoerg if (debug) 321469211Sphk log(-1, " send conf-nak\n"); 321525944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 321625944Sjoerg } else { 321725706Sjoerg if (debug) 321869211Sphk log(-1, " send conf-ack\n"); 321925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 322025944Sjoerg h->ident, origlen, h+1); 322125944Sjoerg } 322225944Sjoerg 322325944Sjoerg free (buf, M_TEMP); 322425944Sjoerg return (rlen == 0); 322525944Sjoerg} 322625944Sjoerg 322725944Sjoerg/* 322825944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 322925944Sjoerg * negotiation. 323025944Sjoerg */ 323125944Sjoergstatic void 323225944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 323325944Sjoerg{ 323425944Sjoerg u_char *buf, *p; 3235147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 323625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 323725944Sjoerg 323825944Sjoerg len -= 4; 323925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 324025944Sjoerg if (!buf) 324125944Sjoerg return; 324225944Sjoerg 324325944Sjoerg if (debug) 324440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 324540008Sjoerg SPP_ARGS(ifp)); 324625944Sjoerg 324725944Sjoerg p = (void*) (h+1); 3248161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3249161556Scperciva len -= p[1], p += p[1]) { 325025706Sjoerg if (debug) 325169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 325225944Sjoerg switch (*p) { 325388534Sjoerg case IPCP_OPT_COMPRESSION: 325488534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 325588534Sjoerg break; 325625944Sjoerg case IPCP_OPT_ADDRESS: 325725944Sjoerg /* 325825944Sjoerg * Peer doesn't grok address option. This is 325925944Sjoerg * bad. XXX Should we better give up here? 326042104Sphk * XXX We could try old "addresses" option... 326125944Sjoerg */ 326225944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 326325944Sjoerg break; 326425944Sjoerg } 32654910Swollman } 326625944Sjoerg if (debug) 326769211Sphk log(-1, "\n"); 326825944Sjoerg free (buf, M_TEMP); 326925944Sjoerg return; 32704910Swollman} 32714910Swollman 327225944Sjoerg/* 327325944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 327425944Sjoerg * negotiation. 327525944Sjoerg */ 327612820Sphkstatic void 327725944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 32784910Swollman{ 327925944Sjoerg u_char *buf, *p; 3280147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 328125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 328288534Sjoerg int desiredcomp; 328325944Sjoerg u_long wantaddr; 32844910Swollman 328525944Sjoerg len -= 4; 328625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 328725944Sjoerg if (!buf) 328825944Sjoerg return; 328925944Sjoerg 329025944Sjoerg if (debug) 329140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 329240008Sjoerg SPP_ARGS(ifp)); 329325944Sjoerg 329425944Sjoerg p = (void*) (h+1); 3295161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3296161556Scperciva len -= p[1], p += p[1]) { 329725944Sjoerg if (debug) 329869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 329925944Sjoerg switch (*p) { 330088534Sjoerg case IPCP_OPT_COMPRESSION: 330188534Sjoerg if (len >= 6 && p[1] == 6) { 330288534Sjoerg desiredcomp = p[2] << 8 | p[3]; 330388534Sjoerg if (debug) 330488534Sjoerg log(-1, "[wantcomp %#04x] ", 330588534Sjoerg desiredcomp); 330688534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 330788599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 330888534Sjoerg sp->ipcp.max_state = p[4]; 330988534Sjoerg sp->ipcp.compress_cid = p[5]; 331088534Sjoerg if (debug) 331188534Sjoerg log(-1, "[agree] "); 331288534Sjoerg } else 331388534Sjoerg sp->ipcp.opts &= 331488534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 331588534Sjoerg } 331688534Sjoerg break; 331725944Sjoerg case IPCP_OPT_ADDRESS: 331825944Sjoerg /* 331925944Sjoerg * Peer doesn't like our local IP address. See 332025944Sjoerg * if we can do something for him. We'll drop 332125944Sjoerg * him our address then. 332225944Sjoerg */ 332325944Sjoerg if (len >= 6 && p[1] == 6) { 332425944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 332525944Sjoerg p[4] << 8 | p[5]; 332625944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 332725944Sjoerg if (debug) 332869211Sphk log(-1, "[wantaddr %s] ", 332930300Sjoerg sppp_dotted_quad(wantaddr)); 333025944Sjoerg /* 333125944Sjoerg * When doing dynamic address assignment, 333225944Sjoerg * we accept his offer. Otherwise, we 333325944Sjoerg * ignore it and thus continue to negotiate 333425944Sjoerg * our already existing value. 333542104Sphk * XXX: Bogus, if he said no once, he'll 333642104Sphk * just say no again, might as well die. 333725944Sjoerg */ 333825944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 333925944Sjoerg sppp_set_ip_addr(sp, wantaddr); 334025944Sjoerg if (debug) 334169211Sphk log(-1, "[agree] "); 334242104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 334325944Sjoerg } 334425944Sjoerg } 334525944Sjoerg break; 334625944Sjoerg } 334725944Sjoerg } 334825944Sjoerg if (debug) 334969211Sphk log(-1, "\n"); 335025944Sjoerg free (buf, M_TEMP); 335125944Sjoerg return; 33524910Swollman} 33534910Swollman 335412820Sphkstatic void 335525944Sjoergsppp_ipcp_tlu(struct sppp *sp) 33564910Swollman{ 335742104Sphk /* we are up - notify isdn daemon */ 335842104Sphk if (sp->pp_con) 335942104Sphk sp->pp_con(sp); 33604910Swollman} 33614910Swollman 336225944Sjoergstatic void 336325944Sjoergsppp_ipcp_tld(struct sppp *sp) 336425944Sjoerg{ 336525944Sjoerg} 336625944Sjoerg 336725944Sjoergstatic void 336825944Sjoergsppp_ipcp_tls(struct sppp *sp) 336925944Sjoerg{ 337025944Sjoerg /* indicate to LCP that it must stay alive */ 337125944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 337225944Sjoerg} 337325944Sjoerg 337425944Sjoergstatic void 337525944Sjoergsppp_ipcp_tlf(struct sppp *sp) 337625944Sjoerg{ 337725944Sjoerg /* we no longer need LCP */ 337825944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 337930300Sjoerg sppp_lcp_check_and_close(sp); 338025944Sjoerg} 338125944Sjoerg 338225944Sjoergstatic void 338325944Sjoergsppp_ipcp_scr(struct sppp *sp) 338425944Sjoerg{ 338525944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 338625944Sjoerg u_long ouraddr; 338725944Sjoerg int i = 0; 338825944Sjoerg 338988534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 339088534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 339188534Sjoerg opt[i++] = 6; 339288534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 339388534Sjoerg opt[i++] = IPCP_COMP_VJ; 339488534Sjoerg opt[i++] = sp->ipcp.max_state; 339588534Sjoerg opt[i++] = sp->ipcp.compress_cid; 339688534Sjoerg } 339725944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 339830300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 339925944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 340025944Sjoerg opt[i++] = 6; 340125944Sjoerg opt[i++] = ouraddr >> 24; 340225944Sjoerg opt[i++] = ouraddr >> 16; 340325944Sjoerg opt[i++] = ouraddr >> 8; 340425944Sjoerg opt[i++] = ouraddr; 340525944Sjoerg } 340625944Sjoerg 340778064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 340825944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 340925944Sjoerg} 341025944Sjoerg 341170199Sjhay/* 341230300Sjoerg *--------------------------------------------------------------------------* 341330300Sjoerg * * 341478064Sume * The IPv6CP implementation. * 341578064Sume * * 341678064Sume *--------------------------------------------------------------------------* 341778064Sume */ 341878064Sume 341978064Sume#ifdef INET6 342078064Sumestatic void 342178064Sumesppp_ipv6cp_init(struct sppp *sp) 342278064Sume{ 342378064Sume sp->ipv6cp.opts = 0; 342478064Sume sp->ipv6cp.flags = 0; 342578064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 342678064Sume sp->fail_counter[IDX_IPV6CP] = 0; 342778064Sume sp->pp_seq[IDX_IPV6CP] = 0; 342878064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 3429138745Srik callout_init(&sp->ch[IDX_IPV6CP], 3430147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 343178064Sume} 343278064Sume 343378064Sumestatic void 343478064Sumesppp_ipv6cp_up(struct sppp *sp) 343578064Sume{ 343678064Sume sppp_up_event(&ipv6cp, sp); 343778064Sume} 343878064Sume 343978064Sumestatic void 344078064Sumesppp_ipv6cp_down(struct sppp *sp) 344178064Sume{ 344278064Sume sppp_down_event(&ipv6cp, sp); 344378064Sume} 344478064Sume 344578064Sumestatic void 344678064Sumesppp_ipv6cp_open(struct sppp *sp) 344778064Sume{ 344878064Sume STDDCL; 344978064Sume struct in6_addr myaddr, hisaddr; 345078064Sume 345178064Sume#ifdef IPV6CP_MYIFID_DYN 345278064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 345378064Sume#else 345478064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 345578064Sume#endif 345678064Sume 345778064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 345878064Sume /* 345978064Sume * If we don't have our address, this probably means our 346078064Sume * interface doesn't want to talk IPv6 at all. (This could 346178064Sume * be the case if somebody wants to speak only IPX, for 346278064Sume * example.) Don't open IPv6CP in this case. 346378064Sume */ 346478064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 346578064Sume /* XXX this message should go away */ 346678064Sume if (debug) 346778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 346878064Sume SPP_ARGS(ifp)); 346978064Sume return; 347078064Sume } 347178064Sume 347278064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 347378064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 347478064Sume sppp_open_event(&ipv6cp, sp); 347578064Sume} 347678064Sume 347778064Sumestatic void 347878064Sumesppp_ipv6cp_close(struct sppp *sp) 347978064Sume{ 348078064Sume sppp_close_event(&ipv6cp, sp); 348178064Sume} 348278064Sume 348378064Sumestatic void 348478064Sumesppp_ipv6cp_TO(void *cookie) 348578064Sume{ 348678064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 348778064Sume} 348878064Sume 348978064Sume/* 349078064Sume * Analyze a configure request. Return true if it was agreeable, and 349178064Sume * caused action sca, false if it has been rejected or nak'ed, and 349278064Sume * caused action scn. (The return value is used to make the state 349378064Sume * transition decision in the state automaton.) 349478064Sume */ 349578064Sumestatic int 349678064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 349778064Sume{ 349878064Sume u_char *buf, *r, *p; 3499147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 350078064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 350178064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 350278064Sume int ifidcount; 350378064Sume int type; 350478064Sume int collision, nohisaddr; 350578064Sume 350678064Sume len -= 4; 350778064Sume origlen = len; 350878064Sume /* 350978064Sume * Make sure to allocate a buf that can at least hold a 351078064Sume * conf-nak with an `address' option. We might need it below. 351178064Sume */ 351278064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 351378064Sume if (! buf) 351478064Sume return (0); 351578064Sume 351678064Sume /* pass 1: see if we can recognize them */ 351778064Sume if (debug) 351878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 351978064Sume SPP_ARGS(ifp)); 352078064Sume p = (void*) (h+1); 352178064Sume ifidcount = 0; 3522161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3523161556Scperciva len-=p[1], p+=p[1]) { 352478064Sume if (debug) 352578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 352678064Sume switch (*p) { 352778064Sume case IPV6CP_OPT_IFID: 352878064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 352978064Sume /* correctly formed address option */ 353078064Sume ifidcount++; 353178064Sume continue; 353278064Sume } 353378064Sume if (debug) 353478176Sume log(-1, " [invalid]"); 353578064Sume break; 353678064Sume#ifdef notyet 353778064Sume case IPV6CP_OPT_COMPRESSION: 353878064Sume if (len >= 4 && p[1] >= 4) { 353978064Sume /* correctly formed compress option */ 354078064Sume continue; 354178064Sume } 354278064Sume if (debug) 354378176Sume log(-1, " [invalid]"); 354478064Sume break; 354578064Sume#endif 354678064Sume default: 354778064Sume /* Others not supported. */ 354878064Sume if (debug) 354978176Sume log(-1, " [rej]"); 355078064Sume break; 355178064Sume } 355278064Sume /* Add the option to rejected list. */ 355378064Sume bcopy (p, r, p[1]); 355478064Sume r += p[1]; 355578064Sume rlen += p[1]; 355678064Sume } 355778064Sume if (rlen) { 355878064Sume if (debug) 355978176Sume log(-1, " send conf-rej\n"); 356078064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 356178064Sume goto end; 356278064Sume } else if (debug) 356378176Sume log(-1, "\n"); 356478064Sume 356578064Sume /* pass 2: parse option values */ 356678064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 356778064Sume if (debug) 356878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 356978064Sume SPP_ARGS(ifp)); 357078064Sume p = (void*) (h+1); 357178064Sume len = origlen; 357278064Sume type = CONF_ACK; 3573161556Scperciva for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1]; 3574161556Scperciva len-=p[1], p+=p[1]) { 357578064Sume if (debug) 357678176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 357778064Sume switch (*p) { 357878064Sume#ifdef notyet 357978064Sume case IPV6CP_OPT_COMPRESSION: 358078064Sume continue; 358178064Sume#endif 358278064Sume case IPV6CP_OPT_IFID: 358378064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 358478064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 358578064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 358678064Sume &myaddr.s6_addr[8], 8) == 0); 358778064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 358878064Sume 358978064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 3590148385Sume (void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL); 359178064Sume 359278064Sume if (!collision && !nohisaddr) { 359378064Sume /* no collision, hisaddr known - Conf-Ack */ 359478064Sume type = CONF_ACK; 359578064Sume 359678064Sume if (debug) { 359778176Sume log(-1, " %s [%s]", 359878064Sume ip6_sprintf(&desiredaddr), 359978064Sume sppp_cp_type_name(type)); 360078064Sume } 360178064Sume continue; 360278064Sume } 360378064Sume 360478064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 360578064Sume if (collision && nohisaddr) { 360678064Sume /* collision, hisaddr unknown - Conf-Rej */ 360778064Sume type = CONF_REJ; 360878064Sume bzero(&p[2], 8); 360978064Sume } else { 361078064Sume /* 361178064Sume * - no collision, hisaddr unknown, or 361278064Sume * - collision, hisaddr known 361378064Sume * Conf-Nak, suggest hisaddr 361478064Sume */ 361578064Sume type = CONF_NAK; 361678064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 361778064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 361878064Sume } 361978064Sume if (debug) 362078176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 362178064Sume sppp_cp_type_name(type)); 362278064Sume break; 362378064Sume } 362478064Sume /* Add the option to nak'ed list. */ 362578064Sume bcopy (p, r, p[1]); 362678064Sume r += p[1]; 362778064Sume rlen += p[1]; 362878064Sume } 362978064Sume 363078064Sume if (rlen == 0 && type == CONF_ACK) { 363178064Sume if (debug) 363278176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 363378064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 363478064Sume } else { 363578064Sume#ifdef DIAGNOSTIC 363678064Sume if (type == CONF_ACK) 363778064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 363878064Sume#endif 363978064Sume 364078064Sume if (debug) { 364178176Sume log(-1, " send %s suggest %s\n", 364278064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 364378064Sume } 364478064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 364578064Sume } 364678064Sume 364778064Sume end: 364878064Sume free (buf, M_TEMP); 364978064Sume return (rlen == 0); 365078064Sume} 365178064Sume 365278064Sume/* 365378064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 365478064Sume * negotiation. 365578064Sume */ 365678064Sumestatic void 365778064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 365878064Sume{ 365978064Sume u_char *buf, *p; 3660147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 366178064Sume int debug = ifp->if_flags & IFF_DEBUG; 366278064Sume 366378064Sume len -= 4; 366478064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 366578064Sume if (!buf) 366678064Sume return; 366778064Sume 366878064Sume if (debug) 366978064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 367078064Sume SPP_ARGS(ifp)); 367178064Sume 367278064Sume p = (void*) (h+1); 3673161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3674161556Scperciva len -= p[1], p += p[1]) { 367578064Sume if (debug) 367678176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 367778064Sume switch (*p) { 367878064Sume case IPV6CP_OPT_IFID: 367978064Sume /* 368078064Sume * Peer doesn't grok address option. This is 368178064Sume * bad. XXX Should we better give up here? 368278064Sume */ 368378064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 368478064Sume break; 368578064Sume#ifdef notyet 368678064Sume case IPV6CP_OPT_COMPRESS: 368778064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 368878064Sume break; 368978064Sume#endif 369078064Sume } 369178064Sume } 369278064Sume if (debug) 369378176Sume log(-1, "\n"); 369478064Sume free (buf, M_TEMP); 369578064Sume return; 369678064Sume} 369778064Sume 369878064Sume/* 369978064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 370078064Sume * negotiation. 370178064Sume */ 370278064Sumestatic void 370378064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 370478064Sume{ 370578064Sume u_char *buf, *p; 3706147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 370778064Sume int debug = ifp->if_flags & IFF_DEBUG; 370878064Sume struct in6_addr suggestaddr; 370978064Sume 371078064Sume len -= 4; 371178064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 371278064Sume if (!buf) 371378064Sume return; 371478064Sume 371578064Sume if (debug) 371678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 371778064Sume SPP_ARGS(ifp)); 371878064Sume 371978064Sume p = (void*) (h+1); 3720161556Scperciva for (; len >= 2 && p[1] >= 2 && len >= p[1]; 3721161556Scperciva len -= p[1], p += p[1]) { 372278064Sume if (debug) 372378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 372478064Sume switch (*p) { 372578064Sume case IPV6CP_OPT_IFID: 372678064Sume /* 372778064Sume * Peer doesn't like our local ifid. See 372878064Sume * if we can do something for him. We'll drop 372978064Sume * him our address then. 373078064Sume */ 373178064Sume if (len < 10 || p[1] != 10) 373278064Sume break; 373378064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 373478064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 3735148385Sume (void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL); 373678064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 373778064Sume 373878064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 373978064Sume if (debug) 374078176Sume log(-1, " [suggestaddr %s]", 374178064Sume ip6_sprintf(&suggestaddr)); 374278064Sume#ifdef IPV6CP_MYIFID_DYN 374378064Sume /* 374478064Sume * When doing dynamic address assignment, 374578064Sume * we accept his offer. 374678064Sume */ 374778064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 374878064Sume struct in6_addr lastsuggest; 374978064Sume /* 375078064Sume * If <suggested myaddr from peer> equals to 375178064Sume * <hisaddr we have suggested last time>, 375278064Sume * we have a collision. generate new random 375378064Sume * ifid. 375478064Sume */ 375578064Sume sppp_suggest_ip6_addr(&lastsuggest); 375678064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 375778064Sume lastsuggest)) { 375878064Sume if (debug) 375978176Sume log(-1, " [random]"); 376078064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 376178064Sume } 376278064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 376378064Sume if (debug) 376478176Sume log(-1, " [agree]"); 376578064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 376678064Sume } 376778064Sume#else 376878064Sume /* 376978064Sume * Since we do not do dynamic address assignment, 377078064Sume * we ignore it and thus continue to negotiate 377178064Sume * our already existing value. This can possibly 377278064Sume * go into infinite request-reject loop. 377378064Sume * 377478064Sume * This is not likely because we normally use 377578064Sume * ifid based on MAC-address. 377678064Sume * If you have no ethernet card on the node, too bad. 377778064Sume * XXX should we use fail_counter? 377878064Sume */ 377978064Sume#endif 378078064Sume break; 378178064Sume#ifdef notyet 378278064Sume case IPV6CP_OPT_COMPRESS: 378378064Sume /* 378478064Sume * Peer wants different compression parameters. 378578064Sume */ 378678064Sume break; 378778064Sume#endif 378878064Sume } 378978064Sume } 379078064Sume if (debug) 379178176Sume log(-1, "\n"); 379278064Sume free (buf, M_TEMP); 379378064Sume return; 379478064Sume} 379578064Sumestatic void 379678064Sumesppp_ipv6cp_tlu(struct sppp *sp) 379778064Sume{ 379878064Sume /* we are up - notify isdn daemon */ 379978064Sume if (sp->pp_con) 380078064Sume sp->pp_con(sp); 380178064Sume} 380278064Sume 380378064Sumestatic void 380478064Sumesppp_ipv6cp_tld(struct sppp *sp) 380578064Sume{ 380678064Sume} 380778064Sume 380878064Sumestatic void 380978064Sumesppp_ipv6cp_tls(struct sppp *sp) 381078064Sume{ 381178064Sume /* indicate to LCP that it must stay alive */ 381278064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 381378064Sume} 381478064Sume 381578064Sumestatic void 381678064Sumesppp_ipv6cp_tlf(struct sppp *sp) 381778064Sume{ 381878064Sume 381978064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 382078064Sume /* we no longer need LCP */ 382178064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 382278064Sume sppp_lcp_check_and_close(sp); 382378064Sume#endif 382478064Sume} 382578064Sume 382678064Sumestatic void 382778064Sumesppp_ipv6cp_scr(struct sppp *sp) 382878064Sume{ 382978064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 383078064Sume struct in6_addr ouraddr; 383178064Sume int i = 0; 383278064Sume 383378064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 383478064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 383578064Sume opt[i++] = IPV6CP_OPT_IFID; 383678064Sume opt[i++] = 10; 383778064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 383878064Sume i += 8; 383978064Sume } 384078064Sume 384178064Sume#ifdef notyet 384278064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 384378064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 384478064Sume opt[i++] = 4; 384578064Sume opt[i++] = 0; /* TBD */ 384678064Sume opt[i++] = 0; /* TBD */ 384778064Sume /* variable length data may follow */ 384878064Sume } 384978064Sume#endif 385078064Sume 385178064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 385278064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 385378064Sume} 385478064Sume#else /*INET6*/ 385578064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 385678064Sume{ 385778064Sume} 385878064Sume 385978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 386078064Sume{ 386178064Sume} 386278064Sume 386378064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 386478064Sume{ 386578064Sume} 386678064Sume 386778064Sume 386878064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 386978064Sume{ 387078064Sume} 387178064Sume 387278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 387378064Sume{ 387478064Sume} 387578064Sume 387678064Sumestatic void sppp_ipv6cp_TO(void *sp) 387778064Sume{ 387878064Sume} 387978064Sume 388078064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 388178064Sume{ 388278064Sume return 0; 388378064Sume} 388478064Sume 388578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 388678064Sume{ 388778064Sume} 388878064Sume 388978064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 389078064Sume{ 389178064Sume} 389278064Sume 389378064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 389478064Sume{ 389578064Sume} 389678064Sume 389778064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 389878064Sume{ 389978064Sume} 390078064Sume 390178064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 390278064Sume{ 390378064Sume} 390478064Sume 390578064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 390678064Sume{ 390778064Sume} 390878064Sume 390978064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 391078064Sume{ 391178064Sume} 391278064Sume#endif /*INET6*/ 391378064Sume 391478064Sume/* 391578064Sume *--------------------------------------------------------------------------* 391678064Sume * * 391730300Sjoerg * The CHAP implementation. * 391830300Sjoerg * * 391930300Sjoerg *--------------------------------------------------------------------------* 392030300Sjoerg */ 392130300Sjoerg 392230300Sjoerg/* 392330300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 392430300Sjoerg * the control protocols do, since they do have Open and Close events, but 392530300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 392630300Sjoerg * authentication protocols may be different in both directions (this makes 392730300Sjoerg * sense, think of a machine that never accepts incoming calls but only 392830300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 392930300Sjoerg * 393030300Sjoerg * Our state machine for the local authentication protocol (we are requesting 393130300Sjoerg * the peer to authenticate) looks like: 393230300Sjoerg * 393330300Sjoerg * RCA- 393430300Sjoerg * +--------------------------------------------+ 393530300Sjoerg * V scn,tld| 393630300Sjoerg * +--------+ Close +---------+ RCA+ 393730300Sjoerg * | |<----------------------------------| |------+ 393830300Sjoerg * +--->| Closed | TO* | Opened | sca | 393930300Sjoerg * | | |-----+ +-------| |<-----+ 394030300Sjoerg * | +--------+ irc | | +---------+ 394130300Sjoerg * | ^ | | ^ 394230300Sjoerg * | | | | | 394330300Sjoerg * | | | | | 394430300Sjoerg * | TO-| | | | 394530300Sjoerg * | |tld TO+ V | | 394630300Sjoerg * | | +------->+ | | 394730300Sjoerg * | | | | | | 394830300Sjoerg * | +--------+ V | | 394930300Sjoerg * | | |<----+<--------------------+ | 395030300Sjoerg * | | Req- | scr | 395130300Sjoerg * | | Sent | | 395230300Sjoerg * | | | | 395330300Sjoerg * | +--------+ | 395430300Sjoerg * | RCA- | | RCA+ | 395530300Sjoerg * +------+ +------------------------------------------+ 395630300Sjoerg * scn,tld sca,irc,ict,tlu 395730300Sjoerg * 395830300Sjoerg * 395930300Sjoerg * with: 396030300Sjoerg * 396130300Sjoerg * Open: LCP reached authentication phase 396230300Sjoerg * Close: LCP reached terminate phase 396330300Sjoerg * 396430300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 396530300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 396630300Sjoerg * TO+: timeout with restart counter >= 0 396730300Sjoerg * TO-: timeout with restart counter < 0 396830300Sjoerg * TO*: reschedule timeout for CHAP 396930300Sjoerg * 397030300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 397130300Sjoerg * sca: send ack packet (pap-ack, chap-success) 397230300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 397330300Sjoerg * ict: initialize re-challenge timer (CHAP only) 397430300Sjoerg * 397530300Sjoerg * tlu: this-layer-up, LCP reaches network phase 397630300Sjoerg * tld: this-layer-down, LCP enters terminate phase 397730300Sjoerg * 397830300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 397930300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 398030300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 398130300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 398230300Sjoerg * causing LCP to enter terminate phase. 398330300Sjoerg * 398430300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 398530300Sjoerg * expected to send one based on the successful negotiation of PAP as 398630300Sjoerg * the authentication protocol during the LCP option negotiation. 398730300Sjoerg * 398830300Sjoerg * Incoming authentication protocol requests (remote requests 398930300Sjoerg * authentication, we are peer) don't employ a state machine at all, 399030300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 399130300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 399230300Sjoerg * still in authentication phase (thereby violating the standard that 399330300Sjoerg * demands that these NCP packets are to be discarded), so we keep 399430300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 399530300Sjoerg * phase network once we've seen a positive acknowledge for the 399630300Sjoerg * authentication. 399730300Sjoerg */ 399830300Sjoerg 399930300Sjoerg/* 400030300Sjoerg * Handle incoming CHAP packets. 400130300Sjoerg */ 4002105228Sphkstatic void 400330300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 400430300Sjoerg{ 400530300Sjoerg STDDCL; 400630300Sjoerg struct lcp_header *h; 400730300Sjoerg int len, x; 400830300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 400930300Sjoerg int value_len, name_len; 401030300Sjoerg MD5_CTX ctx; 401130300Sjoerg 401230300Sjoerg len = m->m_pkthdr.len; 401330300Sjoerg if (len < 4) { 401430300Sjoerg if (debug) 401530300Sjoerg log(LOG_DEBUG, 401640008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 401740008Sjoerg SPP_ARGS(ifp), len); 401830300Sjoerg return; 401930300Sjoerg } 402030300Sjoerg h = mtod (m, struct lcp_header*); 402130300Sjoerg if (len > ntohs (h->len)) 402230300Sjoerg len = ntohs (h->len); 402330300Sjoerg 402430300Sjoerg switch (h->type) { 402530300Sjoerg /* challenge, failure and success are his authproto */ 402630300Sjoerg case CHAP_CHALLENGE: 402730300Sjoerg value = 1 + (u_char*)(h+1); 402830300Sjoerg value_len = value[-1]; 402930300Sjoerg name = value + value_len; 403030300Sjoerg name_len = len - value_len - 5; 403130300Sjoerg if (name_len < 0) { 403230300Sjoerg if (debug) { 403330300Sjoerg log(LOG_DEBUG, 403440008Sjoerg SPP_FMT "chap corrupted challenge " 403530300Sjoerg "<%s id=0x%x len=%d", 403640008Sjoerg SPP_ARGS(ifp), 403730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 403830300Sjoerg h->ident, ntohs(h->len)); 403944145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 404069211Sphk log(-1, ">\n"); 404130300Sjoerg } 404230300Sjoerg break; 404330300Sjoerg } 404470199Sjhay 404530300Sjoerg if (debug) { 404630300Sjoerg log(LOG_DEBUG, 404740008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 404840008Sjoerg SPP_ARGS(ifp), 404930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 405030300Sjoerg ntohs(h->len)); 405130300Sjoerg sppp_print_string((char*) name, name_len); 405269211Sphk log(-1, " value-size=%d value=", value_len); 405330300Sjoerg sppp_print_bytes(value, value_len); 405469211Sphk log(-1, ">\n"); 405530300Sjoerg } 405630300Sjoerg 405730300Sjoerg /* Compute reply value. */ 405830300Sjoerg MD5Init(&ctx); 405930300Sjoerg MD5Update(&ctx, &h->ident, 1); 406030300Sjoerg MD5Update(&ctx, sp->myauth.secret, 406130300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 406230300Sjoerg MD5Update(&ctx, value, value_len); 406330300Sjoerg MD5Final(digest, &ctx); 406430300Sjoerg dsize = sizeof digest; 406530300Sjoerg 406630300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 406730300Sjoerg sizeof dsize, (const char *)&dsize, 406830300Sjoerg sizeof digest, digest, 406940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 407030300Sjoerg sp->myauth.name, 407130300Sjoerg 0); 407230300Sjoerg break; 407330300Sjoerg 407430300Sjoerg case CHAP_SUCCESS: 407530300Sjoerg if (debug) { 407640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 407740008Sjoerg SPP_ARGS(ifp)); 407830300Sjoerg if (len > 4) { 407969211Sphk log(-1, ": "); 408030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 408130300Sjoerg } 408269211Sphk log(-1, "\n"); 408330300Sjoerg } 408430300Sjoerg x = splimp(); 4085138745Srik SPPP_LOCK(sp); 408630300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 408730300Sjoerg if (sp->myauth.proto == PPP_CHAP && 408832169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 408930300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 409030300Sjoerg /* 409130300Sjoerg * We are authenticator for CHAP but didn't 409230300Sjoerg * complete yet. Leave it to tlu to proceed 409330300Sjoerg * to network phase. 409430300Sjoerg */ 4095138745Srik SPPP_UNLOCK(sp); 409630300Sjoerg splx(x); 409730300Sjoerg break; 409830300Sjoerg } 4099138745Srik SPPP_UNLOCK(sp); 410030300Sjoerg splx(x); 410130300Sjoerg sppp_phase_network(sp); 410230300Sjoerg break; 410330300Sjoerg 410430300Sjoerg case CHAP_FAILURE: 410530300Sjoerg if (debug) { 410640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 410740008Sjoerg SPP_ARGS(ifp)); 410830300Sjoerg if (len > 4) { 410969211Sphk log(-1, ": "); 411030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 411130300Sjoerg } 411269211Sphk log(-1, "\n"); 411330300Sjoerg } else 411440008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 411540008Sjoerg SPP_ARGS(ifp)); 411630300Sjoerg /* await LCP shutdown by authenticator */ 411730300Sjoerg break; 411830300Sjoerg 411930300Sjoerg /* response is my authproto */ 412030300Sjoerg case CHAP_RESPONSE: 412130300Sjoerg value = 1 + (u_char*)(h+1); 412230300Sjoerg value_len = value[-1]; 412330300Sjoerg name = value + value_len; 412430300Sjoerg name_len = len - value_len - 5; 412530300Sjoerg if (name_len < 0) { 412630300Sjoerg if (debug) { 412730300Sjoerg log(LOG_DEBUG, 412840008Sjoerg SPP_FMT "chap corrupted response " 412930300Sjoerg "<%s id=0x%x len=%d", 413040008Sjoerg SPP_ARGS(ifp), 413130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 413230300Sjoerg h->ident, ntohs(h->len)); 413344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 413469211Sphk log(-1, ">\n"); 413530300Sjoerg } 413630300Sjoerg break; 413730300Sjoerg } 413830300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 413930300Sjoerg if (debug) 414030300Sjoerg log(LOG_DEBUG, 414140008Sjoerg SPP_FMT "chap dropping response for old ID " 414230300Sjoerg "(got %d, expected %d)\n", 414340008Sjoerg SPP_ARGS(ifp), 414430300Sjoerg h->ident, sp->confid[IDX_CHAP]); 414530300Sjoerg break; 414630300Sjoerg } 414730300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 414830300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 414940008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 415040008Sjoerg SPP_ARGS(ifp)); 415130300Sjoerg sppp_print_string(name, name_len); 415269211Sphk log(-1, " != expected "); 415330300Sjoerg sppp_print_string(sp->hisauth.name, 415430300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 415569211Sphk log(-1, "\n"); 415670199Sjhay } 415730300Sjoerg if (debug) { 415840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 415930300Sjoerg "<%s id=0x%x len=%d name=", 416040008Sjoerg SPP_ARGS(ifp), 416130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 416230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 416330300Sjoerg h->ident, ntohs (h->len)); 416430300Sjoerg sppp_print_string((char*)name, name_len); 416569211Sphk log(-1, " value-size=%d value=", value_len); 416630300Sjoerg sppp_print_bytes(value, value_len); 416769211Sphk log(-1, ">\n"); 416830300Sjoerg } 416930300Sjoerg if (value_len != AUTHKEYLEN) { 417030300Sjoerg if (debug) 417130300Sjoerg log(LOG_DEBUG, 417240008Sjoerg SPP_FMT "chap bad hash value length: " 417330300Sjoerg "%d bytes, should be %d\n", 417440008Sjoerg SPP_ARGS(ifp), value_len, 417530300Sjoerg AUTHKEYLEN); 417630300Sjoerg break; 417730300Sjoerg } 417830300Sjoerg 417930300Sjoerg MD5Init(&ctx); 418030300Sjoerg MD5Update(&ctx, &h->ident, 1); 418130300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 418230300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 418330300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 418430300Sjoerg MD5Final(digest, &ctx); 418530300Sjoerg 418630300Sjoerg#define FAILMSG "Failed..." 418730300Sjoerg#define SUCCMSG "Welcome!" 418830300Sjoerg 418930300Sjoerg if (value_len != sizeof digest || 419030300Sjoerg bcmp(digest, value, value_len) != 0) { 419130300Sjoerg /* action scn, tld */ 419230300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 419330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 419430300Sjoerg 0); 419530300Sjoerg chap.tld(sp); 419630300Sjoerg break; 419730300Sjoerg } 419830300Sjoerg /* action sca, perhaps tlu */ 419930300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 420030300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 420130300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 420230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 420330300Sjoerg 0); 420430300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 420530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 420630300Sjoerg chap.tlu(sp); 420730300Sjoerg } 420830300Sjoerg break; 420930300Sjoerg 421030300Sjoerg default: 421130300Sjoerg /* Unknown CHAP packet type -- ignore. */ 421230300Sjoerg if (debug) { 421340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 421430300Sjoerg "<0x%x id=0x%xh len=%d", 421540008Sjoerg SPP_ARGS(ifp), 421630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 421730300Sjoerg h->type, h->ident, ntohs(h->len)); 421844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 421969211Sphk log(-1, ">\n"); 422030300Sjoerg } 422130300Sjoerg break; 422230300Sjoerg 422330300Sjoerg } 422430300Sjoerg} 422530300Sjoerg 422630300Sjoergstatic void 422730300Sjoergsppp_chap_init(struct sppp *sp) 422830300Sjoerg{ 422930300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 423030300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 423130300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 423278064Sume sp->pp_seq[IDX_CHAP] = 0; 423378064Sume sp->pp_rseq[IDX_CHAP] = 0; 4234138745Srik callout_init(&sp->ch[IDX_CHAP], 4235147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 423630300Sjoerg} 423730300Sjoerg 423830300Sjoergstatic void 423930300Sjoergsppp_chap_open(struct sppp *sp) 424030300Sjoerg{ 424130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 424230300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 424330300Sjoerg /* we are authenticator for CHAP, start it */ 424430300Sjoerg chap.scr(sp); 424530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 424630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 424730300Sjoerg } 424830300Sjoerg /* nothing to be done if we are peer, await a challenge */ 424930300Sjoerg} 425030300Sjoerg 425130300Sjoergstatic void 425230300Sjoergsppp_chap_close(struct sppp *sp) 425330300Sjoerg{ 425430300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 425530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 425630300Sjoerg} 425730300Sjoerg 425830300Sjoergstatic void 425930300Sjoergsppp_chap_TO(void *cookie) 426030300Sjoerg{ 426130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 426230300Sjoerg STDDCL; 426330300Sjoerg int s; 426430300Sjoerg 426530300Sjoerg s = splimp(); 4266138745Srik SPPP_LOCK(sp); 426730300Sjoerg if (debug) 426840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 426940008Sjoerg SPP_ARGS(ifp), 427030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 427130300Sjoerg sp->rst_counter[IDX_CHAP]); 427230300Sjoerg 427330300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 427430300Sjoerg /* TO- event */ 427530300Sjoerg switch (sp->state[IDX_CHAP]) { 427630300Sjoerg case STATE_REQ_SENT: 427730300Sjoerg chap.tld(sp); 427830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 427930300Sjoerg break; 428030300Sjoerg } 428130300Sjoerg else 428230300Sjoerg /* TO+ (or TO*) event */ 428330300Sjoerg switch (sp->state[IDX_CHAP]) { 428430300Sjoerg case STATE_OPENED: 428530300Sjoerg /* TO* event */ 428630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4287102412Scharnier /* FALLTHROUGH */ 428830300Sjoerg case STATE_REQ_SENT: 428930300Sjoerg chap.scr(sp); 429030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 429130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 429230300Sjoerg break; 429330300Sjoerg } 429430300Sjoerg 4295138745Srik SPPP_UNLOCK(sp); 429630300Sjoerg splx(s); 429730300Sjoerg} 429830300Sjoerg 429930300Sjoergstatic void 430030300Sjoergsppp_chap_tlu(struct sppp *sp) 430130300Sjoerg{ 430230300Sjoerg STDDCL; 430330300Sjoerg int i, x; 430430300Sjoerg 430540010Sjoerg i = 0; 430630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 430730300Sjoerg 430830300Sjoerg /* 430930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 431030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 431130300Sjoerg * initial challenge-response exchange has taken place. 431230300Sjoerg * Provide for an option to avoid rechallenges. 431330300Sjoerg */ 431430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 431530300Sjoerg /* 431630300Sjoerg * Compute the re-challenge timeout. This will yield 431730300Sjoerg * a number between 300 and 810 seconds. 431830300Sjoerg */ 431930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4320138745Srik callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp); 432130300Sjoerg } 432230300Sjoerg 432330300Sjoerg if (debug) { 432430300Sjoerg log(LOG_DEBUG, 432540008Sjoerg SPP_FMT "chap %s, ", 432640008Sjoerg SPP_ARGS(ifp), 432730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 432830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 432969211Sphk log(-1, "next re-challenge in %d seconds\n", i); 433030300Sjoerg else 433169211Sphk log(-1, "re-challenging supressed\n"); 433230300Sjoerg } 433330300Sjoerg 433430300Sjoerg x = splimp(); 4335138745Srik SPPP_LOCK(sp); 433630300Sjoerg /* indicate to LCP that we need to be closed down */ 433730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 433830300Sjoerg 433930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 434030300Sjoerg /* 434130300Sjoerg * Remote is authenticator, but his auth proto didn't 434230300Sjoerg * complete yet. Defer the transition to network 434330300Sjoerg * phase. 434430300Sjoerg */ 4345138745Srik SPPP_UNLOCK(sp); 434630300Sjoerg splx(x); 434730300Sjoerg return; 434830300Sjoerg } 4349138745Srik SPPP_UNLOCK(sp); 435030300Sjoerg splx(x); 435130300Sjoerg 435230300Sjoerg /* 435330300Sjoerg * If we are already in phase network, we are done here. This 435430300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 435530300Sjoerg */ 435630300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 435730300Sjoerg sppp_phase_network(sp); 435830300Sjoerg} 435930300Sjoerg 436030300Sjoergstatic void 436130300Sjoergsppp_chap_tld(struct sppp *sp) 436230300Sjoerg{ 436330300Sjoerg STDDCL; 436430300Sjoerg 436530300Sjoerg if (debug) 436640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4367138745Srik callout_stop(&sp->ch[IDX_CHAP]); 436830300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 436930300Sjoerg 437030300Sjoerg lcp.Close(sp); 437130300Sjoerg} 437230300Sjoerg 437330300Sjoergstatic void 437430300Sjoergsppp_chap_scr(struct sppp *sp) 437530300Sjoerg{ 437630300Sjoerg u_long *ch, seed; 437730300Sjoerg u_char clen; 437830300Sjoerg 437930300Sjoerg /* Compute random challenge. */ 438030300Sjoerg ch = (u_long *)sp->myauth.challenge; 438142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 438235064Sphk read_random(&seed, sizeof seed); 438340008Sjoerg#else 438442104Sphk { 438542104Sphk struct timeval tv; 438640008Sjoerg microtime(&tv); 438740008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 438842104Sphk } 438940008Sjoerg#endif 439030300Sjoerg ch[0] = seed ^ random(); 439130300Sjoerg ch[1] = seed ^ random(); 439230300Sjoerg ch[2] = seed ^ random(); 439330300Sjoerg ch[3] = seed ^ random(); 439430300Sjoerg clen = AUTHKEYLEN; 439530300Sjoerg 439678064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 439730300Sjoerg 439830300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 439930300Sjoerg sizeof clen, (const char *)&clen, 440040008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 440140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 440230300Sjoerg sp->myauth.name, 440330300Sjoerg 0); 440430300Sjoerg} 440570199Sjhay 440670199Sjhay/* 440730300Sjoerg *--------------------------------------------------------------------------* 440830300Sjoerg * * 440930300Sjoerg * The PAP implementation. * 441030300Sjoerg * * 441130300Sjoerg *--------------------------------------------------------------------------* 441230300Sjoerg */ 441330300Sjoerg/* 441430300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 441530300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 441630300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 441730300Sjoerg * retry counter is expired). 441830300Sjoerg */ 441930300Sjoerg 442030300Sjoerg/* 442130300Sjoerg * Handle incoming PAP packets. */ 442230300Sjoergstatic void 442330300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 442430300Sjoerg{ 442530300Sjoerg STDDCL; 442630300Sjoerg struct lcp_header *h; 442730300Sjoerg int len, x; 442830300Sjoerg u_char *name, *passwd, mlen; 442930300Sjoerg int name_len, passwd_len; 443030300Sjoerg 443130300Sjoerg len = m->m_pkthdr.len; 443230300Sjoerg if (len < 5) { 443330300Sjoerg if (debug) 443430300Sjoerg log(LOG_DEBUG, 443540008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 443640008Sjoerg SPP_ARGS(ifp), len); 443730300Sjoerg return; 443830300Sjoerg } 443930300Sjoerg h = mtod (m, struct lcp_header*); 444030300Sjoerg if (len > ntohs (h->len)) 444130300Sjoerg len = ntohs (h->len); 444230300Sjoerg switch (h->type) { 444330300Sjoerg /* PAP request is my authproto */ 444430300Sjoerg case PAP_REQ: 444530300Sjoerg name = 1 + (u_char*)(h+1); 444630300Sjoerg name_len = name[-1]; 444730300Sjoerg passwd = name + name_len + 1; 444830300Sjoerg if (name_len > len - 6 || 444930300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 445030300Sjoerg if (debug) { 445140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 445230300Sjoerg "<%s id=0x%x len=%d", 445340008Sjoerg SPP_ARGS(ifp), 445430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 445530300Sjoerg h->ident, ntohs(h->len)); 445644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 445769211Sphk log(-1, ">\n"); 445830300Sjoerg } 445930300Sjoerg break; 446030300Sjoerg } 446130300Sjoerg if (debug) { 446240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 446330300Sjoerg "<%s id=0x%x len=%d name=", 446440008Sjoerg SPP_ARGS(ifp), 446530300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 446630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 446730300Sjoerg h->ident, ntohs(h->len)); 446830300Sjoerg sppp_print_string((char*)name, name_len); 446969211Sphk log(-1, " passwd="); 447030300Sjoerg sppp_print_string((char*)passwd, passwd_len); 447169211Sphk log(-1, ">\n"); 447230300Sjoerg } 447374774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 447474774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 447530300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 447630300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 447730300Sjoerg /* action scn, tld */ 447830300Sjoerg mlen = sizeof(FAILMSG) - 1; 447930300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 448030300Sjoerg sizeof mlen, (const char *)&mlen, 448130300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 448230300Sjoerg 0); 448330300Sjoerg pap.tld(sp); 448430300Sjoerg break; 448530300Sjoerg } 448630300Sjoerg /* action sca, perhaps tlu */ 448730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 448830300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 448930300Sjoerg mlen = sizeof(SUCCMSG) - 1; 449030300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 449130300Sjoerg sizeof mlen, (const char *)&mlen, 449230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 449330300Sjoerg 0); 449430300Sjoerg } 449530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 449630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 449730300Sjoerg pap.tlu(sp); 449830300Sjoerg } 449930300Sjoerg break; 450030300Sjoerg 450130300Sjoerg /* ack and nak are his authproto */ 450230300Sjoerg case PAP_ACK: 4503138745Srik callout_stop(&sp->pap_my_to_ch); 450430300Sjoerg if (debug) { 450540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 450640008Sjoerg SPP_ARGS(ifp)); 450730300Sjoerg name_len = *((char *)h); 450830300Sjoerg if (len > 5 && name_len) { 450969211Sphk log(-1, ": "); 451030300Sjoerg sppp_print_string((char*)(h+1), name_len); 451130300Sjoerg } 451269211Sphk log(-1, "\n"); 451330300Sjoerg } 451430300Sjoerg x = splimp(); 4515138745Srik SPPP_LOCK(sp); 451630300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 451730300Sjoerg if (sp->myauth.proto == PPP_PAP && 451832169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 451930300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 452030300Sjoerg /* 452130300Sjoerg * We are authenticator for PAP but didn't 452230300Sjoerg * complete yet. Leave it to tlu to proceed 452330300Sjoerg * to network phase. 452430300Sjoerg */ 4525138745Srik SPPP_UNLOCK(sp); 452630300Sjoerg splx(x); 452730300Sjoerg break; 452830300Sjoerg } 4529138745Srik SPPP_UNLOCK(sp); 453030300Sjoerg splx(x); 453130300Sjoerg sppp_phase_network(sp); 453230300Sjoerg break; 453330300Sjoerg 453430300Sjoerg case PAP_NAK: 4535138745Srik callout_stop (&sp->pap_my_to_ch); 453630300Sjoerg if (debug) { 453740008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 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 } else 454640008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 454740008Sjoerg SPP_ARGS(ifp)); 454830300Sjoerg /* await LCP shutdown by authenticator */ 454930300Sjoerg break; 455030300Sjoerg 455130300Sjoerg default: 455230300Sjoerg /* Unknown PAP packet type -- ignore. */ 455330300Sjoerg if (debug) { 455440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 455530300Sjoerg "<0x%x id=0x%x len=%d", 455640008Sjoerg SPP_ARGS(ifp), 455730300Sjoerg h->type, h->ident, ntohs(h->len)); 455844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 455969211Sphk log(-1, ">\n"); 456030300Sjoerg } 456130300Sjoerg break; 456230300Sjoerg 456330300Sjoerg } 456430300Sjoerg} 456530300Sjoerg 456630300Sjoergstatic void 456730300Sjoergsppp_pap_init(struct sppp *sp) 456830300Sjoerg{ 456930300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 457030300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 457130300Sjoerg sp->fail_counter[IDX_PAP] = 0; 457278064Sume sp->pp_seq[IDX_PAP] = 0; 457378064Sume sp->pp_rseq[IDX_PAP] = 0; 4574138745Srik callout_init(&sp->ch[IDX_PAP], 4575147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 4576138745Srik callout_init(&sp->pap_my_to_ch, 4577147256Sbrooks (SP2IFP(sp)->if_flags & IFF_NEEDSGIANT) ? 0 : CALLOUT_MPSAFE); 457830300Sjoerg} 457930300Sjoerg 458030300Sjoergstatic void 458130300Sjoergsppp_pap_open(struct sppp *sp) 458230300Sjoerg{ 458330300Sjoerg if (sp->hisauth.proto == PPP_PAP && 458430300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 458530300Sjoerg /* we are authenticator for PAP, start our timer */ 458630300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 458730300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 458830300Sjoerg } 458930300Sjoerg if (sp->myauth.proto == PPP_PAP) { 459030300Sjoerg /* we are peer, send a request, and start a timer */ 459130300Sjoerg pap.scr(sp); 4592138745Srik callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout, 4593138745Srik sppp_pap_my_TO, (void *)sp); 459430300Sjoerg } 459530300Sjoerg} 459630300Sjoerg 459730300Sjoergstatic void 459830300Sjoergsppp_pap_close(struct sppp *sp) 459930300Sjoerg{ 460030300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 460130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 460230300Sjoerg} 460330300Sjoerg 460430300Sjoerg/* 460530300Sjoerg * That's the timeout routine if we are authenticator. Since the 460630300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 460730300Sjoerg */ 460830300Sjoergstatic void 460930300Sjoergsppp_pap_TO(void *cookie) 461030300Sjoerg{ 461130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 461230300Sjoerg STDDCL; 461330300Sjoerg int s; 461430300Sjoerg 461530300Sjoerg s = splimp(); 4616138745Srik SPPP_LOCK(sp); 461730300Sjoerg if (debug) 461840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 461940008Sjoerg SPP_ARGS(ifp), 462030300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 462130300Sjoerg sp->rst_counter[IDX_PAP]); 462230300Sjoerg 462330300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 462430300Sjoerg /* TO- event */ 462530300Sjoerg switch (sp->state[IDX_PAP]) { 462630300Sjoerg case STATE_REQ_SENT: 462730300Sjoerg pap.tld(sp); 462830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 462930300Sjoerg break; 463030300Sjoerg } 463130300Sjoerg else 463230300Sjoerg /* TO+ event, not very much we could do */ 463330300Sjoerg switch (sp->state[IDX_PAP]) { 463430300Sjoerg case STATE_REQ_SENT: 463530300Sjoerg /* sppp_cp_change_state() will restart the timer */ 463630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 463730300Sjoerg break; 463830300Sjoerg } 463930300Sjoerg 4640138745Srik SPPP_UNLOCK(sp); 464130300Sjoerg splx(s); 464230300Sjoerg} 464330300Sjoerg 464430300Sjoerg/* 464530300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 464630300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 464730300Sjoerg * XXX We should impose a max counter. 464830300Sjoerg */ 464930300Sjoergstatic void 465030300Sjoergsppp_pap_my_TO(void *cookie) 465130300Sjoerg{ 465230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 465330300Sjoerg STDDCL; 465430300Sjoerg 465530300Sjoerg if (debug) 465640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 465740008Sjoerg SPP_ARGS(ifp)); 465830300Sjoerg 4659138745Srik SPPP_LOCK(sp); 466030300Sjoerg pap.scr(sp); 4661138745Srik SPPP_UNLOCK(sp); 466230300Sjoerg} 466330300Sjoerg 466430300Sjoergstatic void 466530300Sjoergsppp_pap_tlu(struct sppp *sp) 466630300Sjoerg{ 466730300Sjoerg STDDCL; 466830300Sjoerg int x; 466930300Sjoerg 467030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 467130300Sjoerg 467230300Sjoerg if (debug) 467340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 467440008Sjoerg SPP_ARGS(ifp), pap.name); 467530300Sjoerg 467630300Sjoerg x = splimp(); 4677138745Srik SPPP_LOCK(sp); 467830300Sjoerg /* indicate to LCP that we need to be closed down */ 467930300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 468030300Sjoerg 468130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 468230300Sjoerg /* 468330300Sjoerg * Remote is authenticator, but his auth proto didn't 468430300Sjoerg * complete yet. Defer the transition to network 468530300Sjoerg * phase. 468630300Sjoerg */ 4687138745Srik SPPP_UNLOCK(sp); 468830300Sjoerg splx(x); 468930300Sjoerg return; 469030300Sjoerg } 4691138745Srik SPPP_UNLOCK(sp); 469230300Sjoerg splx(x); 469330300Sjoerg sppp_phase_network(sp); 469430300Sjoerg} 469530300Sjoerg 469630300Sjoergstatic void 469730300Sjoergsppp_pap_tld(struct sppp *sp) 469830300Sjoerg{ 469930300Sjoerg STDDCL; 470030300Sjoerg 470130300Sjoerg if (debug) 470240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4703138745Srik callout_stop (&sp->ch[IDX_PAP]); 4704138745Srik callout_stop (&sp->pap_my_to_ch); 470530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 470630300Sjoerg 470730300Sjoerg lcp.Close(sp); 470830300Sjoerg} 470930300Sjoerg 471030300Sjoergstatic void 471130300Sjoergsppp_pap_scr(struct sppp *sp) 471230300Sjoerg{ 471330300Sjoerg u_char idlen, pwdlen; 471430300Sjoerg 471578064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 471630300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 471730300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 471830300Sjoerg 471930300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 472030300Sjoerg sizeof idlen, (const char *)&idlen, 472140008Sjoerg (size_t)idlen, sp->myauth.name, 472230300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 472340008Sjoerg (size_t)pwdlen, sp->myauth.secret, 472430300Sjoerg 0); 472530300Sjoerg} 472670199Sjhay 472770199Sjhay/* 472825944Sjoerg * Random miscellaneous functions. 472925944Sjoerg */ 473025944Sjoerg 47314910Swollman/* 473230300Sjoerg * Send a PAP or CHAP proto packet. 473330300Sjoerg * 473430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 473540008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 473630300Sjoerg * mlen == 0. 473742104Sphk * NOTE: never declare variadic functions with types subject to type 473842104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 473942104Sphk * on the architecture you are on... 474030300Sjoerg */ 474130300Sjoerg 474230300Sjoergstatic void 474342104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 474442104Sphk unsigned int type, unsigned int id, 474530300Sjoerg ...) 474630300Sjoerg{ 474730300Sjoerg STDDCL; 474830300Sjoerg struct ppp_header *h; 474930300Sjoerg struct lcp_header *lh; 475030300Sjoerg struct mbuf *m; 475130300Sjoerg u_char *p; 475230300Sjoerg int len; 475342104Sphk unsigned int mlen; 475430300Sjoerg const char *msg; 475530300Sjoerg va_list ap; 475630300Sjoerg 4757111119Simp MGETHDR (m, M_DONTWAIT, MT_DATA); 475830300Sjoerg if (! m) 475930300Sjoerg return; 476030300Sjoerg m->m_pkthdr.rcvif = 0; 476130300Sjoerg 476230300Sjoerg h = mtod (m, struct ppp_header*); 476330300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 476430300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 476530300Sjoerg h->protocol = htons(cp->proto); 476630300Sjoerg 476730300Sjoerg lh = (struct lcp_header*)(h + 1); 476830300Sjoerg lh->type = type; 476930300Sjoerg lh->ident = id; 477030300Sjoerg p = (u_char*) (lh+1); 477130300Sjoerg 477230300Sjoerg va_start(ap, id); 477330300Sjoerg len = 0; 477430300Sjoerg 477542104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 477630300Sjoerg msg = va_arg(ap, const char *); 477730300Sjoerg len += mlen; 477830300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 477930300Sjoerg va_end(ap); 478030300Sjoerg m_freem(m); 478130300Sjoerg return; 478230300Sjoerg } 478330300Sjoerg 478430300Sjoerg bcopy(msg, p, mlen); 478530300Sjoerg p += mlen; 478630300Sjoerg } 478730300Sjoerg va_end(ap); 478830300Sjoerg 478930300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 479030300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 479130300Sjoerg 479230300Sjoerg if (debug) { 479340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 479440008Sjoerg SPP_ARGS(ifp), cp->name, 479530300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 479630300Sjoerg lh->ident, ntohs(lh->len)); 479744145Sphk sppp_print_bytes((u_char*) (lh+1), len); 479869211Sphk log(-1, ">\n"); 479930300Sjoerg } 480069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 480169152Sjlemon ifp->if_oerrors++; 480230300Sjoerg} 480330300Sjoerg 480430300Sjoerg/* 480525944Sjoerg * Flush interface queue. 48064910Swollman */ 480712820Sphkstatic void 480825944Sjoergsppp_qflush(struct ifqueue *ifq) 48094910Swollman{ 481025944Sjoerg struct mbuf *m, *n; 48114910Swollman 481225944Sjoerg n = ifq->ifq_head; 481325944Sjoerg while ((m = n)) { 481425944Sjoerg n = m->m_act; 481525944Sjoerg m_freem (m); 481611189Sjkh } 481725944Sjoerg ifq->ifq_head = 0; 481825944Sjoerg ifq->ifq_tail = 0; 481925944Sjoerg ifq->ifq_len = 0; 482025944Sjoerg} 482125944Sjoerg 482225944Sjoerg/* 482325944Sjoerg * Send keepalive packets, every 10 seconds. 482425944Sjoerg */ 482525944Sjoergstatic void 482625944Sjoergsppp_keepalive(void *dummy) 482725944Sjoerg{ 4828138745Srik struct sppp *sp = (struct sppp*)dummy; 4829147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 483025944Sjoerg int s; 483125944Sjoerg 483225944Sjoerg s = splimp(); 4833138745Srik SPPP_LOCK(sp); 4834138745Srik /* Keepalive mode disabled or channel down? */ 4835138745Srik if (! (sp->pp_flags & PP_KEEPALIVE) || 4836148887Srwatson ! (ifp->if_drv_flags & IFF_DRV_RUNNING)) 4837138745Srik goto out; 483825944Sjoerg 4839139365Srik if (sp->pp_mode == PP_FR) { 4840139365Srik sppp_fr_keepalive (sp); 4841139365Srik goto out; 4842139365Srik } 4843139365Srik 4844138745Srik /* No keepalive in PPP mode if LCP not opened yet. */ 4845138745Srik if (sp->pp_mode != IFF_CISCO && 4846138745Srik sp->pp_phase < PHASE_AUTHENTICATE) 4847138745Srik goto out; 484825944Sjoerg 4849138745Srik if (sp->pp_alivecnt == MAXALIVECNT) { 4850138745Srik /* No keepalive packets got. Stop the interface. */ 4851138745Srik printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4852138745Srik if_down (ifp); 4853138745Srik sppp_qflush (&sp->pp_cpq); 4854138745Srik if (sp->pp_mode != IFF_CISCO) { 4855138745Srik /* XXX */ 4856138745Srik /* Shut down the PPP link. */ 4857138745Srik lcp.Down(sp); 4858138745Srik /* Initiate negotiation. XXX */ 4859138745Srik lcp.Up(sp); 48604910Swollman } 48614910Swollman } 4862138745Srik if (sp->pp_alivecnt <= MAXALIVECNT) 4863138745Srik ++sp->pp_alivecnt; 4864138745Srik if (sp->pp_mode == IFF_CISCO) 4865138745Srik sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4866138745Srik ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4867138745Srik else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4868138745Srik long nmagic = htonl (sp->lcp.magic); 4869138745Srik sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4870138745Srik sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4871138745Srik sp->lcp.echoid, 4, &nmagic); 4872138745Srik } 4873138745Srikout: 4874138745Srik SPPP_UNLOCK(sp); 487525944Sjoerg splx(s); 4876138745Srik callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive, 4877138745Srik (void *)sp); 48784910Swollman} 48794910Swollman 488025944Sjoerg/* 488125944Sjoerg * Get both IP addresses. 488225944Sjoerg */ 4883139365Srikvoid 488430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 488525944Sjoerg{ 4886147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 488725944Sjoerg struct ifaddr *ifa; 488830300Sjoerg struct sockaddr_in *si, *sm; 488925944Sjoerg u_long ssrc, ddst; 489025944Sjoerg 489140010Sjoerg sm = NULL; 489225944Sjoerg ssrc = ddst = 0L; 489325944Sjoerg /* 489425944Sjoerg * Pick the first AF_INET address from the list, 489525944Sjoerg * aliases don't make any sense on a p2p link anyway. 489625944Sjoerg */ 489742065Sphk si = 0; 489842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 489942065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 490042104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 490171959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 490240008Sjoerg ifa; 490371959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 490442104Sphk#else 490542104Sphk for (ifa = ifp->if_addrlist; 490642104Sphk ifa; 490742104Sphk ifa = ifa->ifa_next) 490840008Sjoerg#endif 490925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 491025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 491130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 491225944Sjoerg if (si) 491325944Sjoerg break; 491425944Sjoerg } 491525944Sjoerg if (ifa) { 491630300Sjoerg if (si && si->sin_addr.s_addr) { 491725944Sjoerg ssrc = si->sin_addr.s_addr; 491830300Sjoerg if (srcmask) 491930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 492030300Sjoerg } 492125944Sjoerg 492225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 492325944Sjoerg if (si && si->sin_addr.s_addr) 492425944Sjoerg ddst = si->sin_addr.s_addr; 492525944Sjoerg } 492625944Sjoerg 492725944Sjoerg if (dst) *dst = ntohl(ddst); 492825944Sjoerg if (src) *src = ntohl(ssrc); 492925944Sjoerg} 493025944Sjoerg 493125944Sjoerg/* 493225944Sjoerg * Set my IP address. Must be called at splimp. 493325944Sjoerg */ 493425944Sjoergstatic void 493525944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 493625944Sjoerg{ 493742104Sphk STDDCL; 493825944Sjoerg struct ifaddr *ifa; 493925944Sjoerg struct sockaddr_in *si; 494084318Sjlemon struct in_ifaddr *ia; 494125944Sjoerg 494225944Sjoerg /* 494325944Sjoerg * Pick the first AF_INET address from the list, 494425944Sjoerg * aliases don't make any sense on a p2p link anyway. 494525944Sjoerg */ 494642065Sphk si = 0; 494742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 494842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 494942104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 495071959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 495140008Sjoerg ifa; 495271959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 495342104Sphk#else 495442104Sphk for (ifa = ifp->if_addrlist; 495542104Sphk ifa; 495642104Sphk ifa = ifa->ifa_next) 495740008Sjoerg#endif 495840008Sjoerg { 495940008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 496040008Sjoerg { 496125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 496225944Sjoerg if (si) 496325944Sjoerg break; 496425944Sjoerg } 496540008Sjoerg } 496640008Sjoerg 496725944Sjoerg if (ifa && si) 496842104Sphk { 496942104Sphk int error; 4970153084Sru#if defined(__NetBSD__) && __NetBSD_Version__ >= 103080000 497142104Sphk struct sockaddr_in new_sin = *si; 497242104Sphk 497342104Sphk new_sin.sin_addr.s_addr = htonl(src); 497442104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 497542104Sphk if(debug && error) 497642104Sphk { 497742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 497842104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 497942104Sphk } 498042104Sphk#else 498142104Sphk /* delete old route */ 498242104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 498342104Sphk if(debug && error) 498442104Sphk { 498542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 498642104Sphk SPP_ARGS(ifp), error); 498742104Sphk } 498842104Sphk 498942104Sphk /* set new address */ 499025944Sjoerg si->sin_addr.s_addr = htonl(src); 499184318Sjlemon ia = ifatoia(ifa); 499284318Sjlemon LIST_REMOVE(ia, ia_hash); 499384318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 499425944Sjoerg 499542104Sphk /* add new route */ 499670199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 499742104Sphk if (debug && error) 499842104Sphk { 499942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 500042104Sphk SPP_ARGS(ifp), error); 500142104Sphk } 500242104Sphk#endif 500342104Sphk } 500488599Sjoerg} 500578064Sume 500678064Sume#ifdef INET6 500778064Sume/* 500878064Sume * Get both IPv6 addresses. 500978064Sume */ 501078064Sumestatic void 501178064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 501278064Sume struct in6_addr *srcmask) 501378064Sume{ 5014147256Sbrooks struct ifnet *ifp = SP2IFP(sp); 501578064Sume struct ifaddr *ifa; 501678064Sume struct sockaddr_in6 *si, *sm; 501778064Sume struct in6_addr ssrc, ddst; 501878064Sume 501978064Sume sm = NULL; 502078064Sume bzero(&ssrc, sizeof(ssrc)); 502178064Sume bzero(&ddst, sizeof(ddst)); 502278064Sume /* 502378064Sume * Pick the first link-local AF_INET6 address from the list, 502478064Sume * aliases don't make any sense on a p2p link anyway. 502578064Sume */ 5026160377Sbrooks si = 0; 502778064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 5028160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 502978064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 5030160377Sbrooks for (ifa = ifp->if_addrlist.tqh_first; 503178064Sume ifa; 503278064Sume ifa = ifa->ifa_list.tqe_next) 503378064Sume#else 5034160377Sbrooks for (ifa = ifp->if_addrlist; 503578064Sume ifa; 503678064Sume ifa = ifa->ifa_next) 503778064Sume#endif 503878064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 503978064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 504078064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 504178064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 504278064Sume break; 504378064Sume } 504478064Sume if (ifa) { 504578064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 504678064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 504778064Sume if (srcmask) { 504878064Sume bcopy(&sm->sin6_addr, srcmask, 504978064Sume sizeof(*srcmask)); 505078064Sume } 505178064Sume } 505278064Sume 505378064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 505478064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 505578064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 505678064Sume } 505778064Sume 505878064Sume if (dst) 505978064Sume bcopy(&ddst, dst, sizeof(*dst)); 506078064Sume if (src) 506178064Sume bcopy(&ssrc, src, sizeof(*src)); 506270199Sjhay} 506342104Sphk 506478064Sume#ifdef IPV6CP_MYIFID_DYN 506578064Sume/* 506678064Sume * Generate random ifid. 506778064Sume */ 506878064Sumestatic void 506978064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 507078064Sume{ 507178064Sume /* TBD */ 507278064Sume} 507378064Sume 507478064Sume/* 507578064Sume * Set my IPv6 address. Must be called at splimp. 507678064Sume */ 507778064Sumestatic void 507878064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 507978064Sume{ 508078064Sume STDDCL; 508178064Sume struct ifaddr *ifa; 508278064Sume struct sockaddr_in6 *sin6; 508378064Sume 508478064Sume /* 508578064Sume * Pick the first link-local AF_INET6 address from the list, 508678064Sume * aliases don't make any sense on a p2p link anyway. 508778064Sume */ 508878064Sume 508978064Sume sin6 = NULL; 509078064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 5091160377Sbrooks TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 509278064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 509378064Sume for (ifa = ifp->if_addrlist.tqh_first; 509478064Sume ifa; 509578064Sume ifa = ifa->ifa_list.tqe_next) 509678064Sume#else 509778064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 509878064Sume#endif 509978064Sume { 510078064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 510178064Sume { 510278064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 510378064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 510478064Sume break; 510578064Sume } 510678064Sume } 510778064Sume 510878064Sume if (ifa && sin6) 510978064Sume { 511078064Sume int error; 511178064Sume struct sockaddr_in6 new_sin6 = *sin6; 511278064Sume 511378064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 511478064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 511578064Sume if (debug && error) 511678064Sume { 511778064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 511878064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 511978064Sume } 512078064Sume } 512178064Sume} 512278064Sume#endif 512378064Sume 512478064Sume/* 512578064Sume * Suggest a candidate address to be used by peer. 512678064Sume */ 512778064Sumestatic void 512878064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 512978064Sume{ 513078064Sume struct in6_addr myaddr; 513178064Sume struct timeval tv; 513278064Sume 513378064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 513478064Sume 513578064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 513678064Sume microtime(&tv); 513778064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 513878064Sume myaddr.s6_addr[14] ^= 0xff; 513978064Sume myaddr.s6_addr[15] ^= 0xff; 514078064Sume } else { 514178064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 514278064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 514378064Sume } 514478064Sume if (suggest) 514578064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 514678064Sume} 514778064Sume#endif /*INET6*/ 514878064Sume 514930300Sjoergstatic int 515038343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 515130300Sjoerg{ 515238343Sbde u_long subcmd; 515330300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 515488600Sjoerg struct spppreq *spr; 515588600Sjoerg int rv = 0; 515630300Sjoerg 515788600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 515888600Sjoerg return (EAGAIN); 515930300Sjoerg /* 516030300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 516130300Sjoerg * Check the cmd word first before attempting to fetch all the 516230300Sjoerg * data. 516330300Sjoerg */ 516488600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 516588600Sjoerg rv = EFAULT; 516688600Sjoerg goto quit; 516788600Sjoerg } 516830300Sjoerg 516988600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 517088600Sjoerg rv = EFAULT; 517188600Sjoerg goto quit; 517288600Sjoerg } 517330300Sjoerg 517430300Sjoerg switch (subcmd) { 517595848Sobrien case (int)SPPPIOGDEFS: 517688600Sjoerg if (cmd != SIOCGIFGENERIC) { 517788600Sjoerg rv = EINVAL; 517888600Sjoerg break; 517988600Sjoerg } 518030300Sjoerg /* 518130300Sjoerg * We copy over the entire current state, but clean 518230300Sjoerg * out some of the stuff we don't wanna pass up. 518330300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 518430300Sjoerg * called by any user. No need to ever get PAP or 518530300Sjoerg * CHAP secrets back to userland anyway. 518630300Sjoerg */ 518788600Sjoerg spr->defs.pp_phase = sp->pp_phase; 518888723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 518988723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 519088600Sjoerg spr->defs.lcp = sp->lcp; 519188600Sjoerg spr->defs.ipcp = sp->ipcp; 519288600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 519388600Sjoerg spr->defs.myauth = sp->myauth; 519488600Sjoerg spr->defs.hisauth = sp->hisauth; 519588600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 519688600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 519788600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 519888600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 519988550Sjoerg /* 520088550Sjoerg * Fixup the LCP timeout value to milliseconds so 520188550Sjoerg * spppcontrol doesn't need to bother about the value 520288550Sjoerg * of "hz". We do the reverse calculation below when 520388550Sjoerg * setting it. 520488550Sjoerg */ 520588600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 520688600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 520788600Sjoerg sizeof(struct spppreq)); 520888600Sjoerg break; 520930300Sjoerg 521095848Sobrien case (int)SPPPIOSDEFS: 521188600Sjoerg if (cmd != SIOCSIFGENERIC) { 521288600Sjoerg rv = EINVAL; 521388600Sjoerg break; 521488600Sjoerg } 521530300Sjoerg /* 521688550Sjoerg * We have a very specific idea of which fields we 521788550Sjoerg * allow being passed back from userland, so to not 521888550Sjoerg * clobber our current state. For one, we only allow 521988550Sjoerg * setting anything if LCP is in dead or establish 522088550Sjoerg * phase. Once the authentication negotiations 522188550Sjoerg * started, the authentication settings must not be 522288550Sjoerg * changed again. (The administrator can force an 522330300Sjoerg * ifconfig down in order to get LCP back into dead 522430300Sjoerg * phase.) 522530300Sjoerg * 522630300Sjoerg * Also, we only allow for authentication parameters to be 522730300Sjoerg * specified. 522830300Sjoerg * 522930300Sjoerg * XXX Should allow to set or clear pp_flags. 523030300Sjoerg * 523130300Sjoerg * Finally, if the respective authentication protocol to 523230300Sjoerg * be used is set differently than 0, but the secret is 523330300Sjoerg * passed as all zeros, we don't trash the existing secret. 523430300Sjoerg * This allows an administrator to change the system name 523530300Sjoerg * only without clobbering the secret (which he didn't get 523630300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 523730300Sjoerg * secrets are cleared if the authentication protocol is 523888550Sjoerg * reset to 0. */ 523988550Sjoerg if (sp->pp_phase != PHASE_DEAD && 524088600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 524188600Sjoerg rv = EBUSY; 524288600Sjoerg break; 524388600Sjoerg } 524430300Sjoerg 524588600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 524688600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 524788600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 524888600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 524988600Sjoerg rv = EINVAL; 525088600Sjoerg break; 525188600Sjoerg } 525230300Sjoerg 525388600Sjoerg if (spr->defs.myauth.proto == 0) 525430300Sjoerg /* resetting myauth */ 525530300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 525630300Sjoerg else { 525730300Sjoerg /* setting/changing myauth */ 525888600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 525988600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 526088600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 526188600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 526230300Sjoerg AUTHKEYLEN); 526330300Sjoerg } 526488600Sjoerg if (spr->defs.hisauth.proto == 0) 526530300Sjoerg /* resetting hisauth */ 526630300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 526730300Sjoerg else { 526830300Sjoerg /* setting/changing hisauth */ 526988600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 527088600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 527188600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 527288600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 527388600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 527430300Sjoerg AUTHKEYLEN); 527530300Sjoerg } 527688550Sjoerg /* set LCP restart timer timeout */ 527788600Sjoerg if (spr->defs.lcp.timeout != 0) 527888600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 527988723Sjoerg /* set VJ enable and IPv6 disable flags */ 528088723Sjoerg#ifdef INET 528188723Sjoerg if (spr->defs.enable_vj) 528288723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 528388723Sjoerg else 528488723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 528588723Sjoerg#endif 528688723Sjoerg#ifdef INET6 528788723Sjoerg if (spr->defs.enable_ipv6) 528888723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 528988723Sjoerg else 529088723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 529196349Sjoerg#endif 529230300Sjoerg break; 529330300Sjoerg 529430300Sjoerg default: 529588600Sjoerg rv = EINVAL; 529630300Sjoerg } 529730300Sjoerg 529888600Sjoerg quit: 529988600Sjoerg free(spr, M_TEMP); 530088600Sjoerg 530188600Sjoerg return (rv); 530230300Sjoerg} 530330300Sjoerg 530430300Sjoergstatic void 530530300Sjoergsppp_phase_network(struct sppp *sp) 530630300Sjoerg{ 530742066Sphk STDDCL; 530830300Sjoerg int i; 530930300Sjoerg u_long mask; 531030300Sjoerg 531130300Sjoerg sp->pp_phase = PHASE_NETWORK; 531230300Sjoerg 531342066Sphk if (debug) 531442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 531542066Sphk sppp_phase_name(sp->pp_phase)); 531630300Sjoerg 531730300Sjoerg /* Notify NCPs now. */ 531830300Sjoerg for (i = 0; i < IDX_COUNT; i++) 531930300Sjoerg if ((cps[i])->flags & CP_NCP) 532030300Sjoerg (cps[i])->Open(sp); 532130300Sjoerg 532230300Sjoerg /* Send Up events to all NCPs. */ 532330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 532488706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 532530300Sjoerg (cps[i])->Up(sp); 532630300Sjoerg 532730300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 532830300Sjoerg sppp_lcp_check_and_close(sp); 532930300Sjoerg} 533030300Sjoerg 533170199Sjhay 533225706Sjoergstatic const char * 533325944Sjoergsppp_cp_type_name(u_char type) 53344910Swollman{ 533530300Sjoerg static char buf[12]; 53364910Swollman switch (type) { 533730300Sjoerg case CONF_REQ: return "conf-req"; 533830300Sjoerg case CONF_ACK: return "conf-ack"; 533930300Sjoerg case CONF_NAK: return "conf-nak"; 534030300Sjoerg case CONF_REJ: return "conf-rej"; 534130300Sjoerg case TERM_REQ: return "term-req"; 534230300Sjoerg case TERM_ACK: return "term-ack"; 534330300Sjoerg case CODE_REJ: return "code-rej"; 534430300Sjoerg case PROTO_REJ: return "proto-rej"; 534530300Sjoerg case ECHO_REQ: return "echo-req"; 534630300Sjoerg case ECHO_REPLY: return "echo-reply"; 534730300Sjoerg case DISC_REQ: return "discard-req"; 53484910Swollman } 534944145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 535030300Sjoerg return buf; 53514910Swollman} 53524910Swollman 535325706Sjoergstatic const char * 535430300Sjoergsppp_auth_type_name(u_short proto, u_char type) 535530300Sjoerg{ 535630300Sjoerg static char buf[12]; 535730300Sjoerg switch (proto) { 535830300Sjoerg case PPP_CHAP: 535930300Sjoerg switch (type) { 536030300Sjoerg case CHAP_CHALLENGE: return "challenge"; 536130300Sjoerg case CHAP_RESPONSE: return "response"; 536230300Sjoerg case CHAP_SUCCESS: return "success"; 536330300Sjoerg case CHAP_FAILURE: return "failure"; 536430300Sjoerg } 536530300Sjoerg case PPP_PAP: 536630300Sjoerg switch (type) { 536730300Sjoerg case PAP_REQ: return "req"; 536830300Sjoerg case PAP_ACK: return "ack"; 536930300Sjoerg case PAP_NAK: return "nak"; 537030300Sjoerg } 537130300Sjoerg } 537244145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 537330300Sjoerg return buf; 537430300Sjoerg} 537530300Sjoerg 537630300Sjoergstatic const char * 537725944Sjoergsppp_lcp_opt_name(u_char opt) 53784910Swollman{ 537930300Sjoerg static char buf[12]; 538025944Sjoerg switch (opt) { 538130300Sjoerg case LCP_OPT_MRU: return "mru"; 538230300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 538330300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 538430300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 538530300Sjoerg case LCP_OPT_MAGIC: return "magic"; 538630300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 538730300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 53884910Swollman } 538944145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 539030300Sjoerg return buf; 53914910Swollman} 53924910Swollman 539325944Sjoergstatic const char * 539425944Sjoergsppp_ipcp_opt_name(u_char opt) 539525944Sjoerg{ 539630300Sjoerg static char buf[12]; 539725944Sjoerg switch (opt) { 539830300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 539930300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 540030300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 540125944Sjoerg } 540244145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 540330300Sjoerg return buf; 540425944Sjoerg} 540525944Sjoerg 540678064Sume#ifdef INET6 540725944Sjoergstatic const char * 540878064Sumesppp_ipv6cp_opt_name(u_char opt) 540978064Sume{ 541078064Sume static char buf[12]; 541178064Sume switch (opt) { 541278064Sume case IPV6CP_OPT_IFID: return "ifid"; 541378064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 541478064Sume } 541578064Sume sprintf (buf, "0x%x", opt); 541678064Sume return buf; 541778064Sume} 541878064Sume#endif 541978064Sume 542078064Sumestatic const char * 542125944Sjoergsppp_state_name(int state) 542225944Sjoerg{ 542325944Sjoerg switch (state) { 542425944Sjoerg case STATE_INITIAL: return "initial"; 542525944Sjoerg case STATE_STARTING: return "starting"; 542625944Sjoerg case STATE_CLOSED: return "closed"; 542725944Sjoerg case STATE_STOPPED: return "stopped"; 542825944Sjoerg case STATE_CLOSING: return "closing"; 542925944Sjoerg case STATE_STOPPING: return "stopping"; 543025944Sjoerg case STATE_REQ_SENT: return "req-sent"; 543125944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 543225944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 543325944Sjoerg case STATE_OPENED: return "opened"; 543425944Sjoerg } 543525944Sjoerg return "illegal"; 543625944Sjoerg} 543725944Sjoerg 543825944Sjoergstatic const char * 543925944Sjoergsppp_phase_name(enum ppp_phase phase) 544025944Sjoerg{ 544125944Sjoerg switch (phase) { 544225944Sjoerg case PHASE_DEAD: return "dead"; 544325944Sjoerg case PHASE_ESTABLISH: return "establish"; 544425944Sjoerg case PHASE_TERMINATE: return "terminate"; 544525944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 544625944Sjoerg case PHASE_NETWORK: return "network"; 544725944Sjoerg } 544825944Sjoerg return "illegal"; 544925944Sjoerg} 545025944Sjoerg 545125944Sjoergstatic const char * 545225944Sjoergsppp_proto_name(u_short proto) 545325944Sjoerg{ 545425944Sjoerg static char buf[12]; 545525944Sjoerg switch (proto) { 545625944Sjoerg case PPP_LCP: return "lcp"; 545725944Sjoerg case PPP_IPCP: return "ipcp"; 545830300Sjoerg case PPP_PAP: return "pap"; 545930300Sjoerg case PPP_CHAP: return "chap"; 546078064Sume case PPP_IPV6CP: return "ipv6cp"; 546125944Sjoerg } 546244145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 546325944Sjoerg return buf; 546425944Sjoerg} 546525944Sjoerg 546612820Sphkstatic void 546730300Sjoergsppp_print_bytes(const u_char *p, u_short len) 54684910Swollman{ 546944145Sphk if (len) 547069211Sphk log(-1, " %*D", len, p, "-"); 54714910Swollman} 547225944Sjoerg 547330300Sjoergstatic void 547430300Sjoergsppp_print_string(const char *p, u_short len) 547530300Sjoerg{ 547630300Sjoerg u_char c; 547730300Sjoerg 547830300Sjoerg while (len-- > 0) { 547930300Sjoerg c = *p++; 548030300Sjoerg /* 548130300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 548230300Sjoerg * using only them, but we don't rely on it. */ 548330300Sjoerg if (c < ' ' || c > '~') 548469211Sphk log(-1, "\\x%x", c); 548530300Sjoerg else 548669211Sphk log(-1, "%c", c); 548730300Sjoerg } 548830300Sjoerg} 548930300Sjoerg 549030300Sjoergstatic const char * 549130300Sjoergsppp_dotted_quad(u_long addr) 549230300Sjoerg{ 549330300Sjoerg static char s[16]; 549430300Sjoerg sprintf(s, "%d.%d.%d.%d", 549540008Sjoerg (int)((addr >> 24) & 0xff), 549640008Sjoerg (int)((addr >> 16) & 0xff), 549740008Sjoerg (int)((addr >> 8) & 0xff), 549838372Sbde (int)(addr & 0xff)); 549930300Sjoerg return s; 550030300Sjoerg} 550130300Sjoerg 550230300Sjoergstatic int 550330300Sjoergsppp_strnlen(u_char *p, int max) 550430300Sjoerg{ 550530300Sjoerg int len; 550630300Sjoerg 550730300Sjoerg for (len = 0; len < max && *p; ++p) 550830300Sjoerg ++len; 550930300Sjoerg return len; 551030300Sjoerg} 551130300Sjoerg 551230300Sjoerg/* a dummy, used to drop uninteresting events */ 551330300Sjoergstatic void 551430300Sjoergsppp_null(struct sppp *unused) 551530300Sjoerg{ 551630300Sjoerg /* do just nothing */ 551730300Sjoerg} 5518