if_spppsubr.c revision 78134
14910Swollman/* 24910Swollman * Synchronous PPP/Cisco link level subroutines. 34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes. 44910Swollman * 530300Sjoerg * Copyright (C) 1994-1996 Cronyx Engineering Ltd. 625944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru> 74910Swollman * 825944Sjoerg * Heavily revamped to conform to RFC 1661. 925944Sjoerg * Copyright (C) 1997, Joerg Wunsch. 1025944Sjoerg * 114910Swollman * This software is distributed with NO WARRANTIES, not even the implied 124910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 134910Swollman * 144910Swollman * Authors grant any other persons or organisations permission to use 154910Swollman * or modify this software as long as this message is kept with the software, 164910Swollman * all derivative works or modified versions. 174910Swollman * 1830300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 1916288Sgpalmer * 2050477Speter * $FreeBSD: head/sys/net/if_spppsubr.c 78134 2001-06-12 08:52:54Z ume $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2940008Sjoerg#endif 3031742Seivind 3140008Sjoerg#ifdef NetBSD1_3 3240008Sjoerg# if NetBSD1_3 > 6 3340008Sjoerg# include "opt_inet.h" 3454263Sshin# include "opt_inet6.h" 3540008Sjoerg# include "opt_iso.h" 3640008Sjoerg# endif 3740008Sjoerg#endif 3840008Sjoerg 394952Sbde#include <sys/systm.h> 404952Sbde#include <sys/kernel.h> 4170199Sjhay#include <sys/module.h> 4224204Sbde#include <sys/sockio.h> 434910Swollman#include <sys/socket.h> 4425706Sjoerg#include <sys/syslog.h> 4542104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4659604Sobrien#include <sys/random.h> 4742104Sphk#endif 4829024Sbde#include <sys/malloc.h> 494910Swollman#include <sys/mbuf.h> 5040008Sjoerg 5140008Sjoerg#if defined (__OpenBSD__) 5240008Sjoerg#include <sys/md5k.h> 5340008Sjoerg#else 5430300Sjoerg#include <sys/md5.h> 5540008Sjoerg#endif 564910Swollman 574910Swollman#include <net/if.h> 584910Swollman#include <net/netisr.h> 594910Swollman#include <net/if_types.h> 6042104Sphk#include <net/route.h> 614910Swollman 6240008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6340008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6440008Sjoerg#endif 6542104Sphk 6630300Sjoerg#include <machine/stdarg.h> 6730300Sjoerg 684910Swollman#ifdef INET 694910Swollman#include <netinet/in.h> 704910Swollman#include <netinet/in_systm.h> 714910Swollman#include <netinet/in_var.h> 724910Swollman#include <netinet/ip.h> 734910Swollman#include <netinet/tcp.h> 7440008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7540008Sjoerg# include <netinet/if_ether.h> 7640008Sjoerg# else 7740008Sjoerg# include <net/ethertypes.h> 7840008Sjoerg# endif 7932350Seivind#else 8040008Sjoerg# error Huh? sppp without INET? 814910Swollman#endif 824910Swollman 8311819Sjulian#ifdef IPX 8411819Sjulian#include <netipx/ipx.h> 8511819Sjulian#include <netipx/ipx_if.h> 8611819Sjulian#endif 8711819Sjulian 884910Swollman#ifdef NS 894910Swollman#include <netns/ns.h> 904910Swollman#include <netns/ns_if.h> 914910Swollman#endif 924910Swollman 934910Swollman#include <net/if_sppp.h> 944910Swollman 9542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9642064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9742064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 9842104Sphk# define IOCTL_CMD_T u_long 9940008Sjoerg#else 10042064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10142064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10242104Sphk# define IOCTL_CMD_T int 10340008Sjoerg#endif 10442104Sphk 1054910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1064910Swollman 10725944Sjoerg/* 10825944Sjoerg * Interface flags that can be set in an ifconfig command. 10925944Sjoerg * 11025955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11125944Sjoerg * as being administrative openable, but won't be opened to begin 11225944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11325944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11425955Sjoerg * 11525955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11625955Sjoerg * arrive to be sent. 11730300Sjoerg * 11830300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11930300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12030300Sjoerg * like 12130300Sjoerg * 12230300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12330300Sjoerg * 12430300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12530300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12625944Sjoerg */ 12725944Sjoerg 12825955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12925955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13045152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13125944Sjoerg 13230300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13330300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13430300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13530300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13630300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13730300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 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 17330300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 17430300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17530300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1764910Swollman 17730300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17830300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 17930300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18030300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18130300Sjoerg 18230300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18330300Sjoerg 18430300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18530300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18630300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18730300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18830300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 18930300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19030300Sjoerg 19125944Sjoerg/* states are named and numbered according to RFC 1661 */ 19225944Sjoerg#define STATE_INITIAL 0 19325944Sjoerg#define STATE_STARTING 1 19425944Sjoerg#define STATE_CLOSED 2 19525944Sjoerg#define STATE_STOPPED 3 19625944Sjoerg#define STATE_CLOSING 4 19725944Sjoerg#define STATE_STOPPING 5 19825944Sjoerg#define STATE_REQ_SENT 6 19925944Sjoerg#define STATE_ACK_RCVD 7 20025944Sjoerg#define STATE_ACK_SENT 8 20125944Sjoerg#define STATE_OPENED 9 20225944Sjoerg 2034910Swollmanstruct ppp_header { 20411189Sjkh u_char address; 20511189Sjkh u_char control; 20611189Sjkh u_short protocol; 2074910Swollman}; 2084910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2094910Swollman 2104910Swollmanstruct lcp_header { 21111189Sjkh u_char type; 21211189Sjkh u_char ident; 21311189Sjkh u_short len; 2144910Swollman}; 2154910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2164910Swollman 2174910Swollmanstruct cisco_packet { 21811189Sjkh u_long type; 21911189Sjkh u_long par1; 22011189Sjkh u_long par2; 22111189Sjkh u_short rel; 22211189Sjkh u_short time0; 22311189Sjkh u_short time1; 2244910Swollman}; 2254910Swollman#define CISCO_PACKET_LEN 18 2264910Swollman 22725944Sjoerg/* 22825944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 22925944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23025944Sjoerg * case you can't make sense out of these abbreviation; it will also 23125944Sjoerg * explain the semantics related to the various events and actions. 23225944Sjoerg */ 23325944Sjoergstruct cp { 23425944Sjoerg u_short proto; /* PPP control protocol number */ 23525944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23625944Sjoerg u_char flags; 23725944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23825944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 23925944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24025944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24125944Sjoerg const char *name; /* name of this control protocol */ 24225944Sjoerg /* event handlers */ 24325944Sjoerg void (*Up)(struct sppp *sp); 24425944Sjoerg void (*Down)(struct sppp *sp); 24525944Sjoerg void (*Open)(struct sppp *sp); 24625944Sjoerg void (*Close)(struct sppp *sp); 24725944Sjoerg void (*TO)(void *sp); 24825944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 24925944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25025944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25125944Sjoerg /* actions */ 25225944Sjoerg void (*tlu)(struct sppp *sp); 25325944Sjoerg void (*tld)(struct sppp *sp); 25425944Sjoerg void (*tls)(struct sppp *sp); 25525944Sjoerg void (*tlf)(struct sppp *sp); 25625944Sjoerg void (*scr)(struct sppp *sp); 25725944Sjoerg}; 25825944Sjoerg 25912820Sphkstatic struct sppp *spppq; 26042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26130300Sjoergstatic struct callout_handle keepalive_ch; 26240008Sjoerg#endif 2634910Swollman 26442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26540008Sjoerg#define SPP_FMT "%s%d: " 26640008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26740008Sjoerg#else 26840008Sjoerg#define SPP_FMT "%s: " 26940008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27040008Sjoerg#endif 27140008Sjoerg 2724910Swollman/* 2734910Swollman * The following disgusting hack gets around the problem that IP TOS 2744910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2754910Swollman * priority queue. To decide if traffic is interactive, we check that 2764910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27730300Sjoerg * 27830300Sjoerg * XXX is this really still necessary? - joerg - 2794910Swollman */ 28011189Sjkhstatic u_short interactive_ports[8] = { 2814910Swollman 0, 513, 0, 0, 2824910Swollman 0, 21, 0, 23, 2834910Swollman}; 2844910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2854910Swollman 28625944Sjoerg/* almost every function needs these */ 28725944Sjoerg#define STDDCL \ 28825944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 28925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29011189Sjkh 29130300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 29225944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2934910Swollman 29425944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 29525944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29625944Sjoerg 29725944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29825944Sjoerg struct mbuf *m); 29925944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30025944Sjoerg u_char ident, u_short len, void *data); 30142104Sphk/* static void sppp_cp_timeout(void *arg); */ 30225944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 30325944Sjoerg int newstate); 30430300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30542104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30630300Sjoerg ...); 30725944Sjoerg 30825944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 30925944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31025944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31125944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 31225944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 31325944Sjoerg 31430300Sjoergstatic void sppp_null(struct sppp *sp); 31530300Sjoerg 31625944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31725944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31825944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31925944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_TO(void *sp); 32225944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32325944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 32425944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32525944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32625944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33030300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33130300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 33225944Sjoerg 33325944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 33425944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33525944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33625944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_TO(void *sp); 33925944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34025944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34125944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34225944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 34325944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34725944Sjoerg 34878064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 34978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 35078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 35178064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 35278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 35378064Sumestatic void sppp_ipv6cp_TO(void *sp); 35478064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 35578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 35678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 35778064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 35878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 35978064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 36078064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 36178064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 36278064Sume 36330300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 36430300Sjoergstatic void sppp_pap_init(struct sppp *sp); 36530300Sjoergstatic void sppp_pap_open(struct sppp *sp); 36630300Sjoergstatic void sppp_pap_close(struct sppp *sp); 36730300Sjoergstatic void sppp_pap_TO(void *sp); 36830300Sjoergstatic void sppp_pap_my_TO(void *sp); 36930300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 37030300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 37130300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 37230300Sjoerg 37330300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 37430300Sjoergstatic void sppp_chap_init(struct sppp *sp); 37530300Sjoergstatic void sppp_chap_open(struct sppp *sp); 37630300Sjoergstatic void sppp_chap_close(struct sppp *sp); 37730300Sjoergstatic void sppp_chap_TO(void *sp); 37830300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 37930300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 38030300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 38130300Sjoerg 38230300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 38325944Sjoergstatic const char *sppp_cp_type_name(u_char type); 38430300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 38530300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 38678064Sume#ifdef INET6 38778064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 38878064Sume#endif 38925944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 39025944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 39125944Sjoergstatic const char *sppp_proto_name(u_short proto); 39230300Sjoergstatic const char *sppp_state_name(int state); 39338343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 39430300Sjoergstatic int sppp_strnlen(u_char *p, int max); 39530300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 39630300Sjoerg u_long *srcmask); 39725944Sjoergstatic void sppp_keepalive(void *dummy); 39830300Sjoergstatic void sppp_phase_network(struct sppp *sp); 39930300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 40030300Sjoergstatic void sppp_print_string(const char *p, u_short len); 40125944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 40225944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 40378064Sume#ifdef INET6 40478064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 40578064Sume struct in6_addr *dst, struct in6_addr *srcmask); 40678064Sume#ifdef IPV6CP_MYIFID_DYN 40778064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40878064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40978064Sume#endif 41078064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 41178064Sume#endif 41225944Sjoerg 41325944Sjoerg/* our control protocol descriptors */ 41433181Seivindstatic const struct cp lcp = { 41525944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 41625944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 41725944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 41825944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 41925944Sjoerg sppp_lcp_scr 42025944Sjoerg}; 42125944Sjoerg 42233181Seivindstatic const struct cp ipcp = { 42325944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 42425944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 42525944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 42625944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 42725944Sjoerg sppp_ipcp_scr 42825944Sjoerg}; 42925944Sjoerg 43078064Sumestatic const struct cp ipv6cp = { 43178064Sume PPP_IPV6CP, IDX_IPV6CP, 43278064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 43378064Sume CP_NCP, 43478064Sume#else 43578064Sume 0, 43678064Sume#endif 43778064Sume "ipv6cp", 43878064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 43978064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 44078064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 44178064Sume sppp_ipv6cp_scr 44278064Sume}; 44378064Sume 44433181Seivindstatic const struct cp pap = { 44530300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 44630300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 44730300Sjoerg sppp_pap_TO, 0, 0, 0, 44830300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 44930300Sjoerg sppp_pap_scr 45030300Sjoerg}; 45130300Sjoerg 45233181Seivindstatic const struct cp chap = { 45330300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 45430300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 45530300Sjoerg sppp_chap_TO, 0, 0, 0, 45630300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 45730300Sjoerg sppp_chap_scr 45830300Sjoerg}; 45930300Sjoerg 46033181Seivindstatic const struct cp *cps[IDX_COUNT] = { 46125944Sjoerg &lcp, /* IDX_LCP */ 46225944Sjoerg &ipcp, /* IDX_IPCP */ 46378064Sume &ipv6cp, /* IDX_IPV6CP */ 46430300Sjoerg &pap, /* IDX_PAP */ 46530300Sjoerg &chap, /* IDX_CHAP */ 46625944Sjoerg}; 46725944Sjoerg 46870199Sjhaystatic int 46970199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47070199Sjhay{ 47170199Sjhay switch (type) { 47270199Sjhay case MOD_LOAD: 47370199Sjhay break; 47470199Sjhay case MOD_UNLOAD: 47570199Sjhay return EACCES; 47670199Sjhay break; 47770199Sjhay default: 47870199Sjhay break; 47970199Sjhay } 48070199Sjhay return 0; 48170199Sjhay} 48270199Sjhaystatic moduledata_t spppmod = { 48370199Sjhay "sppp", 48470199Sjhay sppp_modevent, 48570199Sjhay 0 48670199Sjhay}; 48770199SjhayMODULE_VERSION(sppp, 1); 48870199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 48925944Sjoerg 49070199Sjhay/* 49125944Sjoerg * Exported functions, comprising our interface to the lower layer. 4924910Swollman */ 4934910Swollman 4944910Swollman/* 4954910Swollman * Process the received packet. 4964910Swollman */ 49725706Sjoergvoid 49825706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4994910Swollman{ 5004910Swollman struct ppp_header *h; 5014910Swollman struct ifqueue *inq = 0; 50225944Sjoerg struct sppp *sp = (struct sppp *)ifp; 50325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5044910Swollman 5054910Swollman if (ifp->if_flags & IFF_UP) 5064910Swollman /* Count received bytes, add FCS and one flag */ 5074910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5084910Swollman 5094910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5104910Swollman /* Too small packet, drop it. */ 51125944Sjoerg if (debug) 51225706Sjoerg log(LOG_DEBUG, 51340008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 51440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 51525944Sjoerg drop: 51625944Sjoerg ++ifp->if_ierrors; 51725944Sjoerg ++ifp->if_iqdrops; 5184910Swollman m_freem (m); 5194910Swollman return; 5204910Swollman } 5214910Swollman 5224910Swollman /* Get PPP header. */ 5234910Swollman h = mtod (m, struct ppp_header*); 5244910Swollman m_adj (m, PPP_HEADER_LEN); 5254910Swollman 5264910Swollman switch (h->address) { 5274910Swollman case PPP_ALLSTATIONS: 5284910Swollman if (h->control != PPP_UI) 5294910Swollman goto invalid; 53045152Sphk if (sp->pp_mode == IFF_CISCO) { 53125944Sjoerg if (debug) 53225706Sjoerg log(LOG_DEBUG, 53340008Sjoerg SPP_FMT "PPP packet in Cisco mode " 53425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 53540008Sjoerg SPP_ARGS(ifp), 53625706Sjoerg h->address, h->control, ntohs(h->protocol)); 53711189Sjkh goto drop; 53811189Sjkh } 5394910Swollman switch (ntohs (h->protocol)) { 5404910Swollman default: 54125944Sjoerg if (debug) 54225706Sjoerg log(LOG_DEBUG, 54344145Sphk SPP_FMT "rejecting protocol " 54425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54540008Sjoerg SPP_ARGS(ifp), 54625706Sjoerg h->address, h->control, ntohs(h->protocol)); 54744145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 54844145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 54978064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 55044145Sphk &h->protocol); 5514910Swollman ++ifp->if_noproto; 5524910Swollman goto drop; 5534910Swollman case PPP_LCP: 55430300Sjoerg sppp_cp_input(&lcp, sp, m); 5554910Swollman m_freem (m); 5564910Swollman return; 55730300Sjoerg case PPP_PAP: 55830300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 55930300Sjoerg sppp_pap_input(sp, m); 56030300Sjoerg m_freem (m); 56130300Sjoerg return; 56230300Sjoerg case PPP_CHAP: 56330300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 56430300Sjoerg sppp_chap_input(sp, m); 56530300Sjoerg m_freem (m); 56630300Sjoerg return; 5674910Swollman#ifdef INET 5684910Swollman case PPP_IPCP: 56925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 57030300Sjoerg sppp_cp_input(&ipcp, sp, m); 5714910Swollman m_freem (m); 5724910Swollman return; 5734910Swollman case PPP_IP: 57425944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5754910Swollman schednetisr (NETISR_IP); 5764910Swollman inq = &ipintrq; 5774910Swollman } 5784910Swollman break; 5794910Swollman#endif 58078064Sume#ifdef INET6 58178064Sume case PPP_IPV6CP: 58278064Sume if (sp->pp_phase == PHASE_NETWORK) 58378064Sume sppp_cp_input(&ipv6cp, sp, m); 58478064Sume m_freem (m); 58578064Sume return; 58678064Sume 58778064Sume case PPP_IPV6: 58878064Sume if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 58978064Sume schednetisr (NETISR_IPV6); 59078064Sume inq = &ip6intrq; 59178064Sume } 59278064Sume break; 59378064Sume#endif 59412495Speter#ifdef IPX 59512495Speter case PPP_IPX: 59612495Speter /* IPX IPXCP not implemented yet */ 59725944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 59812495Speter schednetisr (NETISR_IPX); 59912495Speter inq = &ipxintrq; 60012495Speter } 60112495Speter break; 60212495Speter#endif 6034910Swollman#ifdef NS 6044910Swollman case PPP_XNS: 6054910Swollman /* XNS IDPCP not implemented yet */ 60625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6074910Swollman schednetisr (NETISR_NS); 6084910Swollman inq = &nsintrq; 6094910Swollman } 6104910Swollman break; 6114910Swollman#endif 6124910Swollman } 6134910Swollman break; 6144910Swollman case CISCO_MULTICAST: 6154910Swollman case CISCO_UNICAST: 6164910Swollman /* Don't check the control field here (RFC 1547). */ 61745152Sphk if (sp->pp_mode != IFF_CISCO) { 61825944Sjoerg if (debug) 61925706Sjoerg log(LOG_DEBUG, 62040008Sjoerg SPP_FMT "Cisco packet in PPP mode " 62125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 62240008Sjoerg SPP_ARGS(ifp), 62325706Sjoerg h->address, h->control, ntohs(h->protocol)); 62411189Sjkh goto drop; 62511189Sjkh } 6264910Swollman switch (ntohs (h->protocol)) { 6274910Swollman default: 6284910Swollman ++ifp->if_noproto; 6294910Swollman goto invalid; 6304910Swollman case CISCO_KEEPALIVE: 6314910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 6324910Swollman m_freem (m); 6334910Swollman return; 6344910Swollman#ifdef INET 6354910Swollman case ETHERTYPE_IP: 6364910Swollman schednetisr (NETISR_IP); 6374910Swollman inq = &ipintrq; 6384910Swollman break; 6394910Swollman#endif 64054263Sshin#ifdef INET6 64154263Sshin case ETHERTYPE_IPV6: 64254263Sshin schednetisr (NETISR_IPV6); 64354263Sshin inq = &ip6intrq; 64454263Sshin break; 64554263Sshin#endif 64612495Speter#ifdef IPX 64712495Speter case ETHERTYPE_IPX: 64812495Speter schednetisr (NETISR_IPX); 64912495Speter inq = &ipxintrq; 65012495Speter break; 65112495Speter#endif 6524910Swollman#ifdef NS 6534910Swollman case ETHERTYPE_NS: 6544910Swollman schednetisr (NETISR_NS); 6554910Swollman inq = &nsintrq; 6564910Swollman break; 6574910Swollman#endif 6584910Swollman } 6594910Swollman break; 66025944Sjoerg default: /* Invalid PPP packet. */ 66125944Sjoerg invalid: 66225944Sjoerg if (debug) 66325944Sjoerg log(LOG_DEBUG, 66440008Sjoerg SPP_FMT "invalid input packet " 66525944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 66640008Sjoerg SPP_ARGS(ifp), 66725944Sjoerg h->address, h->control, ntohs(h->protocol)); 66825944Sjoerg goto drop; 6694910Swollman } 6704910Swollman 6714910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 6724910Swollman goto drop; 6734910Swollman 6744910Swollman /* Check queue. */ 67569152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 67625944Sjoerg if (debug) 67740008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 67840008Sjoerg SPP_ARGS(ifp)); 6794910Swollman goto drop; 6804910Swollman } 6814910Swollman} 6824910Swollman 6834910Swollman/* 6844910Swollman * Enqueue transmit packet. 6854910Swollman */ 68612820Sphkstatic int 68725706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 68825706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6894910Swollman{ 6904910Swollman struct sppp *sp = (struct sppp*) ifp; 6914910Swollman struct ppp_header *h; 69278064Sume struct ifqueue *ifq = NULL; 69325955Sjoerg int s, rv = 0; 69442066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6954910Swollman 69625944Sjoerg s = splimp(); 69725944Sjoerg 69825944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 69925944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 7004910Swollman m_freem (m); 7014910Swollman splx (s); 7024910Swollman return (ENETDOWN); 7034910Swollman } 7044910Swollman 70525944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 70625944Sjoerg /* 70725944Sjoerg * Interface is not yet running, but auto-dial. Need 70825944Sjoerg * to start LCP for it. 70925944Sjoerg */ 71025944Sjoerg ifp->if_flags |= IFF_RUNNING; 71125944Sjoerg splx(s); 71225944Sjoerg lcp.Open(sp); 71325944Sjoerg s = splimp(); 71425944Sjoerg } 71525944Sjoerg 71678134Sume ifq = &ifp->if_snd; 7174910Swollman#ifdef INET 71812436Speter if (dst->sa_family == AF_INET) { 71940008Sjoerg /* XXX Check mbuf length here? */ 72012436Speter struct ip *ip = mtod (m, struct ip*); 72112436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 7224910Swollman 72342104Sphk /* 72442104Sphk * When using dynamic local IP address assignment by using 72542104Sphk * 0.0.0.0 as a local address, the first TCP session will 72642104Sphk * not connect because the local TCP checksum is computed 72742104Sphk * using 0.0.0.0 which will later become our real IP address 72842104Sphk * so the TCP checksum computed at the remote end will 72942104Sphk * become invalid. So we 73042104Sphk * - don't let packets with src ip addr 0 thru 73142104Sphk * - we flag TCP packets with src ip 0 as an error 73270199Sjhay */ 73342104Sphk 73442104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 73542104Sphk { 73642104Sphk m_freem(m); 73742104Sphk splx(s); 73842104Sphk if(ip->ip_p == IPPROTO_TCP) 73942104Sphk return(EADDRNOTAVAIL); 74042104Sphk else 74142104Sphk return(0); 74242104Sphk } 74370199Sjhay 74442104Sphk /* 74542104Sphk * Put low delay, telnet, rlogin and ftp control packets 74642104Sphk * in front of the queue. 74742104Sphk */ 74869152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 74941686Sphk ; 75041686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 75112436Speter ifq = &sp->pp_fastq; 75241686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 75341686Sphk ; 75441686Sphk else if (ip->ip_p != IPPROTO_TCP) 75541686Sphk ; 75641686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 75741686Sphk ifq = &sp->pp_fastq; 75841686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 75941686Sphk ifq = &sp->pp_fastq; 7604910Swollman } 7614910Swollman#endif 7624910Swollman 76378064Sume#ifdef INET6 76478064Sume if (dst->sa_family == AF_INET6) { 76578064Sume /* XXX do something tricky here? */ 76678064Sume } 76778064Sume#endif 76878064Sume 7694910Swollman /* 7704910Swollman * Prepend general data packet PPP header. For now, IP only. 7714910Swollman */ 7724910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 7734910Swollman if (! m) { 77442066Sphk if (debug) 77540008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 77640008Sjoerg SPP_ARGS(ifp)); 77725944Sjoerg ++ifp->if_oerrors; 7784910Swollman splx (s); 7794910Swollman return (ENOBUFS); 7804910Swollman } 78140008Sjoerg /* 78240008Sjoerg * May want to check size of packet 78340008Sjoerg * (albeit due to the implementation it's always enough) 78440008Sjoerg */ 7854910Swollman h = mtod (m, struct ppp_header*); 78645152Sphk if (sp->pp_mode == IFF_CISCO) { 78728088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7884910Swollman h->control = 0; 7894910Swollman } else { 7904910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7914910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7924910Swollman } 7934910Swollman 7944910Swollman switch (dst->sa_family) { 7954910Swollman#ifdef INET 7964910Swollman case AF_INET: /* Internet Protocol */ 79745152Sphk if (sp->pp_mode == IFF_CISCO) 79811189Sjkh h->protocol = htons (ETHERTYPE_IP); 79911189Sjkh else { 80025955Sjoerg /* 80125955Sjoerg * Don't choke with an ENETDOWN early. It's 80225955Sjoerg * possible that we just started dialing out, 80325955Sjoerg * so don't drop the packet immediately. If 80425955Sjoerg * we notice that we run out of buffer space 80525955Sjoerg * below, we will however remember that we are 80625955Sjoerg * not ready to carry IP packets, and return 80725955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 80825955Sjoerg */ 80925955Sjoerg h->protocol = htons(PPP_IP); 81025955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 81125955Sjoerg rv = ENETDOWN; 81211189Sjkh } 8134910Swollman break; 8144910Swollman#endif 81554263Sshin#ifdef INET6 81654263Sshin case AF_INET6: /* Internet Protocol */ 81754263Sshin if (sp->pp_mode == IFF_CISCO) 81854263Sshin h->protocol = htons (ETHERTYPE_IPV6); 81954263Sshin else { 82078064Sume /* 82178064Sume * Don't choke with an ENETDOWN early. It's 82278064Sume * possible that we just started dialing out, 82378064Sume * so don't drop the packet immediately. If 82478064Sume * we notice that we run out of buffer space 82578064Sume * below, we will however remember that we are 82678064Sume * not ready to carry IP packets, and return 82778064Sume * ENETDOWN, as opposed to ENOBUFS. 82878064Sume */ 82978064Sume h->protocol = htons(PPP_IPV6); 83078064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 83178064Sume rv = ENETDOWN; 83254263Sshin } 83354263Sshin break; 83454263Sshin#endif 8354910Swollman#ifdef NS 8364910Swollman case AF_NS: /* Xerox NS Protocol */ 83745152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 8384910Swollman ETHERTYPE_NS : PPP_XNS); 8394910Swollman break; 8404910Swollman#endif 84111819Sjulian#ifdef IPX 84212495Speter case AF_IPX: /* Novell IPX Protocol */ 84345152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 84412495Speter ETHERTYPE_IPX : PPP_IPX); 84511819Sjulian break; 84611819Sjulian#endif 84712820Sphknosupport: 8484910Swollman default: 8494910Swollman m_freem (m); 85025944Sjoerg ++ifp->if_oerrors; 8514910Swollman splx (s); 8524910Swollman return (EAFNOSUPPORT); 8534910Swollman } 8544910Swollman 8554910Swollman /* 8564910Swollman * Queue message on interface, and start output if interface 85769152Sjlemon * not yet active. Also adjust output byte count. 85869152Sjlemon * The packet length includes header, FCS and 1 flag, 85969152Sjlemon * according to RFC 1333. 8604910Swollman */ 86169152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 86225944Sjoerg ++ifp->if_oerrors; 86325955Sjoerg return (rv? rv: ENOBUFS); 8644910Swollman } 8654910Swollman return (0); 8664910Swollman} 8674910Swollman 86825706Sjoergvoid 86925706Sjoergsppp_attach(struct ifnet *ifp) 8704910Swollman{ 8714910Swollman struct sppp *sp = (struct sppp*) ifp; 8724910Swollman 8734910Swollman /* Initialize keepalive handler. */ 8744910Swollman if (! spppq) 87542064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 8764910Swollman 8774910Swollman /* Insert new entry into the keepalive list. */ 8784910Swollman sp->pp_next = spppq; 8794910Swollman spppq = sp; 8804910Swollman 88142064Sphk sp->pp_if.if_mtu = PP_MTU; 88242064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8834910Swollman sp->pp_if.if_type = IFT_PPP; 8844910Swollman sp->pp_if.if_output = sppp_output; 88542104Sphk#if 0 88642064Sphk sp->pp_flags = PP_KEEPALIVE; 88742104Sphk#endif 88870199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 88970199Sjhay sp->pp_fastq.ifq_maxlen = 32; 89070199Sjhay sp->pp_cpq.ifq_maxlen = 20; 8914910Swollman sp->pp_loopcnt = 0; 8924910Swollman sp->pp_alivecnt = 0; 89378064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 89478064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 89525944Sjoerg sp->pp_phase = PHASE_DEAD; 89625944Sjoerg sp->pp_up = lcp.Up; 89725944Sjoerg sp->pp_down = lcp.Down; 89869152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 89969152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 90025944Sjoerg 90125944Sjoerg sppp_lcp_init(sp); 90225944Sjoerg sppp_ipcp_init(sp); 90378064Sume sppp_ipv6cp_init(sp); 90430300Sjoerg sppp_pap_init(sp); 90530300Sjoerg sppp_chap_init(sp); 9064910Swollman} 9074910Swollman 90830300Sjoergvoid 90925706Sjoergsppp_detach(struct ifnet *ifp) 9104910Swollman{ 9114910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 91225944Sjoerg int i; 9134910Swollman 9144910Swollman /* Remove the entry from the keepalive list. */ 9154910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 9164910Swollman if (p == sp) { 9174910Swollman *q = p->pp_next; 9184910Swollman break; 9194910Swollman } 9204910Swollman 9214910Swollman /* Stop keepalive handler. */ 9224910Swollman if (! spppq) 92340008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 92425944Sjoerg 92525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 92640008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 92740008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 92869152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 92969152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 9304910Swollman} 9314910Swollman 9324910Swollman/* 9334910Swollman * Flush the interface output queue. 9344910Swollman */ 93525706Sjoergvoid 93625706Sjoergsppp_flush(struct ifnet *ifp) 9374910Swollman{ 9384910Swollman struct sppp *sp = (struct sppp*) ifp; 9394910Swollman 94025944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 94125944Sjoerg sppp_qflush (&sp->pp_fastq); 94226018Sjoerg sppp_qflush (&sp->pp_cpq); 9434910Swollman} 9444910Swollman 9454910Swollman/* 94611189Sjkh * Check if the output queue is empty. 94711189Sjkh */ 94812820Sphkint 94925706Sjoergsppp_isempty(struct ifnet *ifp) 95011189Sjkh{ 95111189Sjkh struct sppp *sp = (struct sppp*) ifp; 95225944Sjoerg int empty, s; 95311189Sjkh 95425944Sjoerg s = splimp(); 95526018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 95626018Sjoerg !sp->pp_if.if_snd.ifq_head; 95725944Sjoerg splx(s); 95811189Sjkh return (empty); 95911189Sjkh} 96011189Sjkh 96111189Sjkh/* 9624910Swollman * Get next packet to send. 9634910Swollman */ 96425706Sjoergstruct mbuf * 96525706Sjoergsppp_dequeue(struct ifnet *ifp) 9664910Swollman{ 9674910Swollman struct sppp *sp = (struct sppp*) ifp; 9684910Swollman struct mbuf *m; 96925944Sjoerg int s; 9704910Swollman 97125944Sjoerg s = splimp(); 97226018Sjoerg /* 97330300Sjoerg * Process only the control protocol queue until we have at 97430300Sjoerg * least one NCP open. 97526018Sjoerg * 97626018Sjoerg * Do always serve all three queues in Cisco mode. 97726018Sjoerg */ 97826018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 97926018Sjoerg if (m == NULL && 98045152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 98126018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 98226018Sjoerg if (m == NULL) 98326018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 98426018Sjoerg } 98526018Sjoerg splx(s); 98626018Sjoerg return m; 9874910Swollman} 9884910Swollman 9894910Swollman/* 99030300Sjoerg * Pick the next packet, do not remove it from the queue. 99130300Sjoerg */ 99230300Sjoergstruct mbuf * 99330300Sjoergsppp_pick(struct ifnet *ifp) 99430300Sjoerg{ 99530300Sjoerg struct sppp *sp = (struct sppp*)ifp; 99630300Sjoerg struct mbuf *m; 99730300Sjoerg int s; 99830300Sjoerg 99930300Sjoerg s= splimp (); 100030300Sjoerg 100130300Sjoerg m = sp->pp_cpq.ifq_head; 100230300Sjoerg if (m == NULL && 100345152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 100430300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 100530300Sjoerg m = sp->pp_if.if_snd.ifq_head; 100630300Sjoerg splx (s); 100730300Sjoerg return (m); 100830300Sjoerg} 100930300Sjoerg 101030300Sjoerg/* 101125944Sjoerg * Process an ioctl request. Called on low priority level. 10124910Swollman */ 101325944Sjoergint 101442104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 10154910Swollman{ 101625944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 101725944Sjoerg struct sppp *sp = (struct sppp*) ifp; 101830300Sjoerg int s, rv, going_up, going_down, newmode; 10194910Swollman 102025944Sjoerg s = splimp(); 102130300Sjoerg rv = 0; 102225944Sjoerg switch (cmd) { 102325944Sjoerg case SIOCAIFADDR: 102425944Sjoerg case SIOCSIFDSTADDR: 102525944Sjoerg break; 10264910Swollman 102725944Sjoerg case SIOCSIFADDR: 102825944Sjoerg if_up(ifp); 102925944Sjoerg /* fall through... */ 103011189Sjkh 103125944Sjoerg case SIOCSIFFLAGS: 103225944Sjoerg going_up = ifp->if_flags & IFF_UP && 103325944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 103425944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 103525944Sjoerg ifp->if_flags & IFF_RUNNING; 103645152Sphk 103745152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 103845152Sphk if (!newmode) 103945152Sphk newmode = ifp->if_flags & IFF_AUTO; 104045152Sphk if (!newmode) 104145152Sphk newmode = ifp->if_flags & IFF_CISCO; 104245152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 104345152Sphk ifp->if_flags |= newmode; 104445152Sphk 104545152Sphk if (newmode != sp->pp_mode) { 104645152Sphk going_down = 1; 104745152Sphk if (!going_up) 104845152Sphk going_up = ifp->if_flags & IFF_RUNNING; 10494910Swollman } 10504910Swollman 105145152Sphk if (going_down) { 105270199Sjhay if (sp->pp_mode != IFF_CISCO) 105345152Sphk lcp.Close(sp); 105445152Sphk else if (sp->pp_tlf) 105545152Sphk (sp->pp_tlf)(sp); 105626018Sjoerg sppp_flush(ifp); 105725944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 105845152Sphk sp->pp_mode = newmode; 105926018Sjoerg } 10604910Swollman 106145152Sphk if (going_up) { 106270199Sjhay if (sp->pp_mode != IFF_CISCO) 106345152Sphk lcp.Close(sp); 106445152Sphk sp->pp_mode = newmode; 106545152Sphk if (sp->pp_mode == 0) { 106645152Sphk ifp->if_flags |= IFF_RUNNING; 106745152Sphk lcp.Open(sp); 106845152Sphk } 106945152Sphk if (sp->pp_mode == IFF_CISCO) { 107045152Sphk if (sp->pp_tls) 107145152Sphk (sp->pp_tls)(sp); 107245152Sphk ifp->if_flags |= IFF_RUNNING; 107345152Sphk } 107445152Sphk } 107545152Sphk 10764910Swollman break; 107711189Sjkh 107825944Sjoerg#ifdef SIOCSIFMTU 107925944Sjoerg#ifndef ifr_mtu 108025944Sjoerg#define ifr_mtu ifr_metric 108125944Sjoerg#endif 108225944Sjoerg case SIOCSIFMTU: 108325944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 108425944Sjoerg return (EINVAL); 108525944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10864910Swollman break; 108725944Sjoerg#endif 108825944Sjoerg#ifdef SLIOCSETMTU 108925944Sjoerg case SLIOCSETMTU: 109025944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 109125944Sjoerg return (EINVAL); 109225944Sjoerg ifp->if_mtu = *(short*)data; 10934910Swollman break; 109425944Sjoerg#endif 109525944Sjoerg#ifdef SIOCGIFMTU 109625944Sjoerg case SIOCGIFMTU: 109725944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 109811189Sjkh break; 109925944Sjoerg#endif 110025944Sjoerg#ifdef SLIOCGETMTU 110125944Sjoerg case SLIOCGETMTU: 110225944Sjoerg *(short*)data = ifp->if_mtu; 11034910Swollman break; 110425944Sjoerg#endif 110525944Sjoerg case SIOCADDMULTI: 110625944Sjoerg case SIOCDELMULTI: 11074910Swollman break; 110811189Sjkh 110930300Sjoerg case SIOCGIFGENERIC: 111030300Sjoerg case SIOCSIFGENERIC: 111130300Sjoerg rv = sppp_params(sp, cmd, data); 111230300Sjoerg break; 111330300Sjoerg 111425944Sjoerg default: 111530300Sjoerg rv = ENOTTY; 11164910Swollman } 111725944Sjoerg splx(s); 111830300Sjoerg return rv; 11194910Swollman} 11204910Swollman 112170199Sjhay/* 112225944Sjoerg * Cisco framing implementation. 112325944Sjoerg */ 112425944Sjoerg 11254910Swollman/* 11264910Swollman * Handle incoming Cisco keepalive protocol packets. 11274910Swollman */ 112830300Sjoergstatic void 112925706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 11304910Swollman{ 113125944Sjoerg STDDCL; 11324910Swollman struct cisco_packet *h; 113330300Sjoerg u_long me, mymask; 11344910Swollman 113527929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 113625706Sjoerg if (debug) 113725706Sjoerg log(LOG_DEBUG, 113840008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 113940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 11404910Swollman return; 11414910Swollman } 11424910Swollman h = mtod (m, struct cisco_packet*); 114325706Sjoerg if (debug) 114425706Sjoerg log(LOG_DEBUG, 114540008Sjoerg SPP_FMT "cisco input: %d bytes " 114625706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 114840008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 114940008Sjoerg (u_int)h->time0, (u_int)h->time1); 11504910Swollman switch (ntohl (h->type)) { 11514910Swollman default: 115225706Sjoerg if (debug) 115369211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 115440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 11554910Swollman break; 11564910Swollman case CISCO_ADDR_REPLY: 11574910Swollman /* Reply on address request, ignore */ 11584910Swollman break; 11594910Swollman case CISCO_KEEPALIVE_REQ: 11604910Swollman sp->pp_alivecnt = 0; 116178064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 116278064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 11634910Swollman /* Local and remote sequence numbers are equal. 11644910Swollman * Probably, the line is in loopback mode. */ 116511189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 116640008Sjoerg printf (SPP_FMT "loopback\n", 116740008Sjoerg SPP_ARGS(ifp)); 116811189Sjkh sp->pp_loopcnt = 0; 116911189Sjkh if (ifp->if_flags & IFF_UP) { 117011189Sjkh if_down (ifp); 117126018Sjoerg sppp_qflush (&sp->pp_cpq); 117211189Sjkh } 117311189Sjkh } 11744910Swollman ++sp->pp_loopcnt; 11754910Swollman 11764910Swollman /* Generate new local sequence number */ 117742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 117878064Sume sp->pp_seq[IDX_LCP] = random(); 117940008Sjoerg#else 118078064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 118140008Sjoerg#endif 118211189Sjkh break; 118311189Sjkh } 118430300Sjoerg sp->pp_loopcnt = 0; 118511189Sjkh if (! (ifp->if_flags & IFF_UP) && 118611189Sjkh (ifp->if_flags & IFF_RUNNING)) { 118730300Sjoerg if_up(ifp); 118840008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 118911189Sjkh } 11904910Swollman break; 11914910Swollman case CISCO_ADDR_REQ: 119230300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 119330300Sjoerg if (me != 0L) 119430300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11954910Swollman break; 11964910Swollman } 11974910Swollman} 11984910Swollman 11994910Swollman/* 120025944Sjoerg * Send Cisco keepalive packet. 12014910Swollman */ 120212820Sphkstatic void 120325944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 120425944Sjoerg{ 120525944Sjoerg STDDCL; 120625944Sjoerg struct ppp_header *h; 120725944Sjoerg struct cisco_packet *ch; 120825944Sjoerg struct mbuf *m; 120942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121035029Sphk struct timeval tv; 121140008Sjoerg#else 121240008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 121340008Sjoerg#endif 121425944Sjoerg 121542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121636119Sphk getmicrouptime(&tv); 121740008Sjoerg#endif 121870199Sjhay 121925944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 122025944Sjoerg if (! m) 122125944Sjoerg return; 122225944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 122325944Sjoerg m->m_pkthdr.rcvif = 0; 122425944Sjoerg 122525944Sjoerg h = mtod (m, struct ppp_header*); 122625944Sjoerg h->address = CISCO_MULTICAST; 122725944Sjoerg h->control = 0; 122825944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 122925944Sjoerg 123025944Sjoerg ch = (struct cisco_packet*) (h + 1); 123125944Sjoerg ch->type = htonl (type); 123225944Sjoerg ch->par1 = htonl (par1); 123325944Sjoerg ch->par2 = htonl (par2); 123425944Sjoerg ch->rel = -1; 123540008Sjoerg 123642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 123735029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 123835029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 123940008Sjoerg#else 124040008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 124140008Sjoerg ch->time1 = htons ((u_short) t); 124240008Sjoerg#endif 124325944Sjoerg 124425944Sjoerg if (debug) 124525944Sjoerg log(LOG_DEBUG, 124640008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 124740008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 124840008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 124925944Sjoerg 125069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 125169152Sjlemon ifp->if_oerrors++; 125225944Sjoerg} 125325944Sjoerg 125470199Sjhay/* 125525944Sjoerg * PPP protocol implementation. 125625944Sjoerg */ 125725944Sjoerg 125825944Sjoerg/* 125925944Sjoerg * Send PPP control protocol packet. 126025944Sjoerg */ 126125944Sjoergstatic void 126225706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 126325706Sjoerg u_char ident, u_short len, void *data) 12644910Swollman{ 126525944Sjoerg STDDCL; 12664910Swollman struct ppp_header *h; 12674910Swollman struct lcp_header *lh; 12684910Swollman struct mbuf *m; 12694910Swollman 12704910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 12714910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 12724910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 12734910Swollman if (! m) 12744910Swollman return; 12754910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 12764910Swollman m->m_pkthdr.rcvif = 0; 12774910Swollman 12784910Swollman h = mtod (m, struct ppp_header*); 12794910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12804910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12814910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12824910Swollman 12834910Swollman lh = (struct lcp_header*) (h + 1); 12844910Swollman lh->type = type; 12854910Swollman lh->ident = ident; 12864910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12874910Swollman if (len) 12884910Swollman bcopy (data, lh+1, len); 12894910Swollman 129025706Sjoerg if (debug) { 129140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 129240008Sjoerg SPP_ARGS(ifp), 129325944Sjoerg sppp_proto_name(proto), 129425944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 129525944Sjoerg ntohs (lh->len)); 129644145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 129769211Sphk log(-1, ">\n"); 12984910Swollman } 129969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 130069152Sjlemon ifp->if_oerrors++; 13014910Swollman} 13024910Swollman 13034910Swollman/* 130425944Sjoerg * Handle incoming PPP control protocol packets. 13054910Swollman */ 130612820Sphkstatic void 130725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13084910Swollman{ 130925944Sjoerg STDDCL; 131025944Sjoerg struct lcp_header *h; 131125944Sjoerg int len = m->m_pkthdr.len; 131225944Sjoerg int rv; 131325944Sjoerg u_char *p; 13144910Swollman 131525944Sjoerg if (len < 4) { 131625944Sjoerg if (debug) 131725944Sjoerg log(LOG_DEBUG, 131840008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 131940008Sjoerg SPP_ARGS(ifp), cp->name, len); 13204910Swollman return; 132125944Sjoerg } 132225944Sjoerg h = mtod (m, struct lcp_header*); 132325944Sjoerg if (debug) { 132425944Sjoerg log(LOG_DEBUG, 132540008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 132640008Sjoerg SPP_ARGS(ifp), cp->name, 132725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 132825944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 132944145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 133069211Sphk log(-1, ">\n"); 133125944Sjoerg } 133225944Sjoerg if (len > ntohs (h->len)) 133325944Sjoerg len = ntohs (h->len); 133430300Sjoerg p = (u_char *)(h + 1); 133525944Sjoerg switch (h->type) { 133625944Sjoerg case CONF_REQ: 133725944Sjoerg if (len < 4) { 133825944Sjoerg if (debug) 133969211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 134040008Sjoerg SPP_ARGS(ifp), cp->name, 134125944Sjoerg len); 134225944Sjoerg ++ifp->if_ierrors; 134325944Sjoerg break; 134425944Sjoerg } 134530300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 134630300Sjoerg switch (sp->state[cp->protoidx]) { 134730300Sjoerg case STATE_CLOSING: 134830300Sjoerg case STATE_STOPPING: 134930300Sjoerg return; 135030300Sjoerg case STATE_CLOSED: 135130300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 135230300Sjoerg 0, 0); 135330300Sjoerg return; 135430300Sjoerg } 135525944Sjoerg rv = (cp->RCR)(sp, h, len); 135625944Sjoerg switch (sp->state[cp->protoidx]) { 135725944Sjoerg case STATE_OPENED: 135825944Sjoerg (cp->tld)(sp); 135925944Sjoerg (cp->scr)(sp); 136025944Sjoerg /* fall through... */ 136125944Sjoerg case STATE_ACK_SENT: 136225944Sjoerg case STATE_REQ_SENT: 136370199Sjhay /* 136470199Sjhay * sppp_cp_change_state() have the side effect of 136570199Sjhay * restarting the timeouts. We want to avoid that 136670199Sjhay * if the state don't change, otherwise we won't 136770199Sjhay * ever timeout and resend a configuration request 136870199Sjhay * that got lost. 136970199Sjhay */ 137070199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 137170199Sjhay STATE_REQ_SENT)) 137270199Sjhay break; 137325944Sjoerg sppp_cp_change_state(cp, sp, rv? 137425944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 137525944Sjoerg break; 137625944Sjoerg case STATE_STOPPED: 137725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 137825944Sjoerg (cp->scr)(sp); 137925944Sjoerg sppp_cp_change_state(cp, sp, rv? 138025944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 138125944Sjoerg break; 138225944Sjoerg case STATE_ACK_RCVD: 138325944Sjoerg if (rv) { 138425944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 138525944Sjoerg if (debug) 138640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 138740008Sjoerg SPP_ARGS(ifp), 138826077Sjoerg cp->name); 138925944Sjoerg (cp->tlu)(sp); 139025944Sjoerg } else 139125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 139225944Sjoerg break; 139325944Sjoerg default: 139440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139540008Sjoerg SPP_ARGS(ifp), cp->name, 139625944Sjoerg sppp_cp_type_name(h->type), 139725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139825944Sjoerg ++ifp->if_ierrors; 139925944Sjoerg } 140025944Sjoerg break; 140125944Sjoerg case CONF_ACK: 140225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 140325944Sjoerg if (debug) 140469211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 140540008Sjoerg SPP_ARGS(ifp), cp->name, 140625944Sjoerg h->ident, sp->confid[cp->protoidx]); 140725944Sjoerg ++ifp->if_ierrors; 140825944Sjoerg break; 140925944Sjoerg } 141025944Sjoerg switch (sp->state[cp->protoidx]) { 141125944Sjoerg case STATE_CLOSED: 141225944Sjoerg case STATE_STOPPED: 141325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 141425944Sjoerg break; 141525944Sjoerg case STATE_CLOSING: 141625944Sjoerg case STATE_STOPPING: 141725944Sjoerg break; 141825944Sjoerg case STATE_REQ_SENT: 141925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 142025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 142125944Sjoerg break; 142225944Sjoerg case STATE_OPENED: 142325944Sjoerg (cp->tld)(sp); 142425944Sjoerg /* fall through */ 142525944Sjoerg case STATE_ACK_RCVD: 142625944Sjoerg (cp->scr)(sp); 142725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142825944Sjoerg break; 142925944Sjoerg case STATE_ACK_SENT: 143025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 143225944Sjoerg if (debug) 143340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 143440008Sjoerg SPP_ARGS(ifp), cp->name); 143525944Sjoerg (cp->tlu)(sp); 143625944Sjoerg break; 143725944Sjoerg default: 143840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 143940008Sjoerg SPP_ARGS(ifp), cp->name, 144025944Sjoerg sppp_cp_type_name(h->type), 144125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144225944Sjoerg ++ifp->if_ierrors; 144325944Sjoerg } 144425944Sjoerg break; 144525944Sjoerg case CONF_NAK: 144625944Sjoerg case CONF_REJ: 144725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 144825944Sjoerg if (debug) 144969211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 145040008Sjoerg SPP_ARGS(ifp), cp->name, 145125944Sjoerg h->ident, sp->confid[cp->protoidx]); 145225944Sjoerg ++ifp->if_ierrors; 145325944Sjoerg break; 145425944Sjoerg } 145525944Sjoerg if (h->type == CONF_NAK) 145625944Sjoerg (cp->RCN_nak)(sp, h, len); 145725944Sjoerg else /* CONF_REJ */ 145825944Sjoerg (cp->RCN_rej)(sp, h, len); 14594910Swollman 146025944Sjoerg switch (sp->state[cp->protoidx]) { 146125944Sjoerg case STATE_CLOSED: 146225944Sjoerg case STATE_STOPPED: 146325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 146425944Sjoerg break; 146525944Sjoerg case STATE_REQ_SENT: 146625944Sjoerg case STATE_ACK_SENT: 146725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 146870199Sjhay /* 146970199Sjhay * Slow things down a bit if we think we might be 147070199Sjhay * in loopback. Depend on the timeout to send the 147170199Sjhay * next configuration request. 147270199Sjhay */ 147370199Sjhay if (sp->pp_loopcnt) 147470199Sjhay break; 147525944Sjoerg (cp->scr)(sp); 147625944Sjoerg break; 147725944Sjoerg case STATE_OPENED: 147825944Sjoerg (cp->tld)(sp); 147925944Sjoerg /* fall through */ 148025944Sjoerg case STATE_ACK_RCVD: 148152633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148225944Sjoerg (cp->scr)(sp); 148325944Sjoerg break; 148425944Sjoerg case STATE_CLOSING: 148525944Sjoerg case STATE_STOPPING: 148625944Sjoerg break; 148725944Sjoerg default: 148840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 148940008Sjoerg SPP_ARGS(ifp), cp->name, 149025944Sjoerg sppp_cp_type_name(h->type), 149125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149225944Sjoerg ++ifp->if_ierrors; 149325944Sjoerg } 149425944Sjoerg break; 14954910Swollman 149625944Sjoerg case TERM_REQ: 149725944Sjoerg switch (sp->state[cp->protoidx]) { 149825944Sjoerg case STATE_ACK_RCVD: 149925944Sjoerg case STATE_ACK_SENT: 150025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 150125944Sjoerg /* fall through */ 150225944Sjoerg case STATE_CLOSED: 150325944Sjoerg case STATE_STOPPED: 150425944Sjoerg case STATE_CLOSING: 150525944Sjoerg case STATE_STOPPING: 150625944Sjoerg case STATE_REQ_SENT: 150725944Sjoerg sta: 150825944Sjoerg /* Send Terminate-Ack packet. */ 150925944Sjoerg if (debug) 151040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 151140008Sjoerg SPP_ARGS(ifp), cp->name); 151225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 151325944Sjoerg break; 151425944Sjoerg case STATE_OPENED: 151525944Sjoerg (cp->tld)(sp); 151625944Sjoerg sp->rst_counter[cp->protoidx] = 0; 151725944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 151825944Sjoerg goto sta; 151925944Sjoerg break; 152025944Sjoerg default: 152140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 152240008Sjoerg SPP_ARGS(ifp), cp->name, 152325944Sjoerg sppp_cp_type_name(h->type), 152425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152525944Sjoerg ++ifp->if_ierrors; 152625944Sjoerg } 152725944Sjoerg break; 152825944Sjoerg case TERM_ACK: 152925944Sjoerg switch (sp->state[cp->protoidx]) { 153025944Sjoerg case STATE_CLOSED: 153125944Sjoerg case STATE_STOPPED: 153225944Sjoerg case STATE_REQ_SENT: 153325944Sjoerg case STATE_ACK_SENT: 153425944Sjoerg break; 153525944Sjoerg case STATE_CLOSING: 153641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 153725944Sjoerg (cp->tlf)(sp); 153825944Sjoerg break; 153925944Sjoerg case STATE_STOPPING: 154041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 154125944Sjoerg (cp->tlf)(sp); 154225944Sjoerg break; 154325944Sjoerg case STATE_ACK_RCVD: 154425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154525944Sjoerg break; 154625944Sjoerg case STATE_OPENED: 154725944Sjoerg (cp->tld)(sp); 154825944Sjoerg (cp->scr)(sp); 154925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 155025944Sjoerg break; 155125944Sjoerg default: 155240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 155340008Sjoerg SPP_ARGS(ifp), cp->name, 155425944Sjoerg sppp_cp_type_name(h->type), 155525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155625944Sjoerg ++ifp->if_ierrors; 155725944Sjoerg } 155825944Sjoerg break; 155925944Sjoerg case CODE_REJ: 156025944Sjoerg case PROTO_REJ: 156125944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 156230300Sjoerg log(LOG_INFO, 156340008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 156430300Sjoerg "danger will robinson\n", 156540008Sjoerg SPP_ARGS(ifp), cp->name, 156630300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 156725944Sjoerg switch (sp->state[cp->protoidx]) { 156825944Sjoerg case STATE_CLOSED: 156925944Sjoerg case STATE_STOPPED: 157025944Sjoerg case STATE_REQ_SENT: 157125944Sjoerg case STATE_ACK_SENT: 157225944Sjoerg case STATE_CLOSING: 157325944Sjoerg case STATE_STOPPING: 157425944Sjoerg case STATE_OPENED: 157525944Sjoerg break; 157625944Sjoerg case STATE_ACK_RCVD: 157725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 157825944Sjoerg break; 157925944Sjoerg default: 158040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 158140008Sjoerg SPP_ARGS(ifp), cp->name, 158225944Sjoerg sppp_cp_type_name(h->type), 158325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158425944Sjoerg ++ifp->if_ierrors; 158525944Sjoerg } 158625944Sjoerg break; 158725944Sjoerg case DISC_REQ: 158825944Sjoerg if (cp->proto != PPP_LCP) 158925944Sjoerg goto illegal; 159025944Sjoerg /* Discard the packet. */ 159125944Sjoerg break; 159225944Sjoerg case ECHO_REQ: 159325944Sjoerg if (cp->proto != PPP_LCP) 159425944Sjoerg goto illegal; 159525944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 159625944Sjoerg if (debug) 159769211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 159840008Sjoerg SPP_ARGS(ifp)); 159925944Sjoerg ++ifp->if_ierrors; 160025944Sjoerg break; 160125944Sjoerg } 160225944Sjoerg if (len < 8) { 160325944Sjoerg if (debug) 160469211Sphk log(-1, SPP_FMT "invalid lcp echo request " 160525944Sjoerg "packet length: %d bytes\n", 160640008Sjoerg SPP_ARGS(ifp), len); 160725944Sjoerg break; 160825944Sjoerg } 160944145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 161044145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 161125944Sjoerg /* Line loopback mode detected. */ 161240008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 161370199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 161425944Sjoerg if_down (ifp); 161526018Sjoerg sppp_qflush (&sp->pp_cpq); 16164910Swollman 161725944Sjoerg /* Shut down the PPP link. */ 161825944Sjoerg /* XXX */ 161925944Sjoerg lcp.Down(sp); 162025944Sjoerg lcp.Up(sp); 162125944Sjoerg break; 162225944Sjoerg } 162325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 162425944Sjoerg if (debug) 162569211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 162640008Sjoerg SPP_ARGS(ifp)); 162725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 162825944Sjoerg break; 162925944Sjoerg case ECHO_REPLY: 163025944Sjoerg if (cp->proto != PPP_LCP) 163125944Sjoerg goto illegal; 163225944Sjoerg if (h->ident != sp->lcp.echoid) { 163325944Sjoerg ++ifp->if_ierrors; 163425944Sjoerg break; 163525944Sjoerg } 163625944Sjoerg if (len < 8) { 163725944Sjoerg if (debug) 163869211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 163925944Sjoerg "packet length: %d bytes\n", 164040008Sjoerg SPP_ARGS(ifp), len); 164125944Sjoerg break; 164225944Sjoerg } 164325944Sjoerg if (debug) 164469211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 164540008Sjoerg SPP_ARGS(ifp)); 164644145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 164744145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 164825944Sjoerg sp->pp_alivecnt = 0; 164925944Sjoerg break; 165025944Sjoerg default: 165125944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 165225944Sjoerg illegal: 165325944Sjoerg if (debug) 165469211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 165540008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 165678064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 165778064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 165825944Sjoerg ++ifp->if_ierrors; 165925944Sjoerg } 16604910Swollman} 16614910Swollman 166225944Sjoerg 16634910Swollman/* 166425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 166525944Sjoerg * Basically, the state transition handling in the automaton. 16664910Swollman */ 166725944Sjoergstatic void 166825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 16694910Swollman{ 167025944Sjoerg STDDCL; 16714910Swollman 167225944Sjoerg if (debug) 167340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 167440008Sjoerg SPP_ARGS(ifp), cp->name, 167525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 167625944Sjoerg 167725944Sjoerg switch (sp->state[cp->protoidx]) { 167825944Sjoerg case STATE_INITIAL: 167925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 168025944Sjoerg break; 168125944Sjoerg case STATE_STARTING: 168225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 168325944Sjoerg (cp->scr)(sp); 168425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 168525944Sjoerg break; 16864910Swollman default: 168740008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 168840008Sjoerg SPP_ARGS(ifp), cp->name, 168925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169025944Sjoerg } 169125944Sjoerg} 16924910Swollman 169325944Sjoergstatic void 169425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 169525944Sjoerg{ 169625944Sjoerg STDDCL; 169725944Sjoerg 169825944Sjoerg if (debug) 169940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 170040008Sjoerg SPP_ARGS(ifp), cp->name, 170125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 170225944Sjoerg 170325944Sjoerg switch (sp->state[cp->protoidx]) { 170425944Sjoerg case STATE_CLOSED: 170525944Sjoerg case STATE_CLOSING: 170625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 17074910Swollman break; 170825944Sjoerg case STATE_STOPPED: 170941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 171025944Sjoerg (cp->tls)(sp); 171141881Sphk break; 171225944Sjoerg case STATE_STOPPING: 171325944Sjoerg case STATE_REQ_SENT: 171425944Sjoerg case STATE_ACK_RCVD: 171525944Sjoerg case STATE_ACK_SENT: 171625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 171725944Sjoerg break; 171825944Sjoerg case STATE_OPENED: 171925944Sjoerg (cp->tld)(sp); 172025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 172125944Sjoerg break; 172225944Sjoerg default: 172340008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 172440008Sjoerg SPP_ARGS(ifp), cp->name, 172525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172625944Sjoerg } 172725944Sjoerg} 17284910Swollman 172911189Sjkh 173025944Sjoergstatic void 173125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 173225944Sjoerg{ 173325944Sjoerg STDDCL; 173425944Sjoerg 173525944Sjoerg if (debug) 173640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 173740008Sjoerg SPP_ARGS(ifp), cp->name, 173825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 173925944Sjoerg 174025944Sjoerg switch (sp->state[cp->protoidx]) { 174125944Sjoerg case STATE_INITIAL: 174241881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 174325944Sjoerg (cp->tls)(sp); 17444910Swollman break; 174525944Sjoerg case STATE_STARTING: 174625944Sjoerg break; 174725944Sjoerg case STATE_CLOSED: 174825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 174925944Sjoerg (cp->scr)(sp); 175025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 175125944Sjoerg break; 175225944Sjoerg case STATE_STOPPED: 175374703Sjoerg /* 175474703Sjoerg * Try escaping stopped state. This seems to bite 175574703Sjoerg * people occasionally, in particular for IPCP, 175674703Sjoerg * presumably following previous IPCP negotiation 175774703Sjoerg * aborts. Somehow, we must have missed a Down event 175874703Sjoerg * which would have caused a transition into starting 175974703Sjoerg * state, so as a bandaid we force the Down event now. 176074703Sjoerg * This effectively implements (something like the) 176174703Sjoerg * `restart' option mentioned in the state transition 176274703Sjoerg * table of RFC 1661. 176374703Sjoerg */ 176474703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 176574703Sjoerg (cp->tls)(sp); 176674703Sjoerg break; 176725944Sjoerg case STATE_STOPPING: 176825944Sjoerg case STATE_REQ_SENT: 176925944Sjoerg case STATE_ACK_RCVD: 177025944Sjoerg case STATE_ACK_SENT: 177125944Sjoerg case STATE_OPENED: 177225944Sjoerg break; 177325944Sjoerg case STATE_CLOSING: 177425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 177525944Sjoerg break; 177625944Sjoerg } 177725944Sjoerg} 17784910Swollman 177925944Sjoerg 178025944Sjoergstatic void 178125944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 178225944Sjoerg{ 178325944Sjoerg STDDCL; 178425944Sjoerg 178525944Sjoerg if (debug) 178640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 178740008Sjoerg SPP_ARGS(ifp), cp->name, 178825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 178925944Sjoerg 179025944Sjoerg switch (sp->state[cp->protoidx]) { 179125944Sjoerg case STATE_INITIAL: 179225944Sjoerg case STATE_CLOSED: 179325944Sjoerg case STATE_CLOSING: 17944910Swollman break; 179525944Sjoerg case STATE_STARTING: 179641881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 179725944Sjoerg (cp->tlf)(sp); 17984910Swollman break; 179925944Sjoerg case STATE_STOPPED: 180025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 18014910Swollman break; 180225944Sjoerg case STATE_STOPPING: 180325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18044910Swollman break; 180525944Sjoerg case STATE_OPENED: 180625944Sjoerg (cp->tld)(sp); 180725944Sjoerg /* fall through */ 180825944Sjoerg case STATE_REQ_SENT: 180925944Sjoerg case STATE_ACK_RCVD: 181025944Sjoerg case STATE_ACK_SENT: 181125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 181278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 181378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 181425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18154910Swollman break; 18164910Swollman } 18174910Swollman} 18184910Swollman 181925944Sjoergstatic void 182025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 182125944Sjoerg{ 182225944Sjoerg STDDCL; 182325944Sjoerg int s; 182425944Sjoerg 182525944Sjoerg s = splimp(); 182625944Sjoerg if (debug) 182740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 182840008Sjoerg SPP_ARGS(ifp), cp->name, 182925944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 183025944Sjoerg sp->rst_counter[cp->protoidx]); 183125944Sjoerg 183225944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 183325944Sjoerg /* TO- event */ 183425944Sjoerg switch (sp->state[cp->protoidx]) { 183525944Sjoerg case STATE_CLOSING: 183641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 183725944Sjoerg (cp->tlf)(sp); 183825944Sjoerg break; 183925944Sjoerg case STATE_STOPPING: 184041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 184125944Sjoerg (cp->tlf)(sp); 184225944Sjoerg break; 184325944Sjoerg case STATE_REQ_SENT: 184425944Sjoerg case STATE_ACK_RCVD: 184525944Sjoerg case STATE_ACK_SENT: 184641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 184725944Sjoerg (cp->tlf)(sp); 184825944Sjoerg break; 184925944Sjoerg } 185025944Sjoerg else 185125944Sjoerg /* TO+ event */ 185225944Sjoerg switch (sp->state[cp->protoidx]) { 185325944Sjoerg case STATE_CLOSING: 185425944Sjoerg case STATE_STOPPING: 185578064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 185678064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 185770199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 185842064Sphk sp->ch[cp->protoidx]); 185925944Sjoerg break; 186025944Sjoerg case STATE_REQ_SENT: 186125944Sjoerg case STATE_ACK_RCVD: 186225944Sjoerg (cp->scr)(sp); 186325944Sjoerg /* sppp_cp_change_state() will restart the timer */ 186425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 186525944Sjoerg break; 186625944Sjoerg case STATE_ACK_SENT: 186725944Sjoerg (cp->scr)(sp); 186842064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 186942064Sphk sp->ch[cp->protoidx]); 187025944Sjoerg break; 187125944Sjoerg } 187225944Sjoerg 187325944Sjoerg splx(s); 187425944Sjoerg} 187525944Sjoerg 187611189Sjkh/* 187725944Sjoerg * Change the state of a control protocol in the state automaton. 187825944Sjoerg * Takes care of starting/stopping the restart timer. 187911189Sjkh */ 188025944Sjoergvoid 188125944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 188225944Sjoerg{ 188325944Sjoerg sp->state[cp->protoidx] = newstate; 188425944Sjoerg 188540008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 188625944Sjoerg switch (newstate) { 188725944Sjoerg case STATE_INITIAL: 188825944Sjoerg case STATE_STARTING: 188925944Sjoerg case STATE_CLOSED: 189025944Sjoerg case STATE_STOPPED: 189125944Sjoerg case STATE_OPENED: 189225944Sjoerg break; 189325944Sjoerg case STATE_CLOSING: 189425944Sjoerg case STATE_STOPPING: 189525944Sjoerg case STATE_REQ_SENT: 189625944Sjoerg case STATE_ACK_RCVD: 189725944Sjoerg case STATE_ACK_SENT: 189870199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 189942064Sphk sp->ch[cp->protoidx]); 190025944Sjoerg break; 190125944Sjoerg } 190225944Sjoerg} 190370199Sjhay 190470199Sjhay/* 190525944Sjoerg *--------------------------------------------------------------------------* 190625944Sjoerg * * 190725944Sjoerg * The LCP implementation. * 190825944Sjoerg * * 190925944Sjoerg *--------------------------------------------------------------------------* 191025944Sjoerg */ 191125944Sjoergstatic void 191225944Sjoergsppp_lcp_init(struct sppp *sp) 191325944Sjoerg{ 191425944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 191525944Sjoerg sp->lcp.magic = 0; 191625944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 191725944Sjoerg sp->fail_counter[IDX_LCP] = 0; 191878064Sume sp->pp_seq[IDX_LCP] = 0; 191978064Sume sp->pp_rseq[IDX_LCP] = 0; 192025944Sjoerg sp->lcp.protos = 0; 192125944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 192230300Sjoerg 192344145Sphk /* Note that these values are relevant for all control protocols */ 192444145Sphk sp->lcp.timeout = 3 * hz; 192525944Sjoerg sp->lcp.max_terminate = 2; 192625944Sjoerg sp->lcp.max_configure = 10; 192725944Sjoerg sp->lcp.max_failure = 10; 192842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 192930300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 193040008Sjoerg#endif 193125944Sjoerg} 193225944Sjoerg 193325944Sjoergstatic void 193425944Sjoergsppp_lcp_up(struct sppp *sp) 193525944Sjoerg{ 193625944Sjoerg STDDCL; 193725944Sjoerg 193870199Sjhay sp->pp_alivecnt = 0; 193970199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 194070199Sjhay sp->lcp.magic = 0; 194170199Sjhay sp->lcp.protos = 0; 194270199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 194325944Sjoerg /* 194475321Sjoerg * If we are authenticator, negotiate LCP_AUTH 194575321Sjoerg */ 194675321Sjoerg if (sp->hisauth.proto != 0) 194775321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 194875321Sjoerg else 194975321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 195075321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 195175321Sjoerg /* 195230300Sjoerg * If this interface is passive or dial-on-demand, and we are 195330300Sjoerg * still in Initial state, it means we've got an incoming 195430300Sjoerg * call. Activate the interface. 195525944Sjoerg */ 195625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 195725944Sjoerg if (debug) 195825944Sjoerg log(LOG_DEBUG, 195940008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 196025944Sjoerg ifp->if_flags |= IFF_RUNNING; 196130300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 196230300Sjoerg if (debug) 196369211Sphk log(-1, "(incoming call)\n"); 196430300Sjoerg sp->pp_flags |= PP_CALLIN; 196530300Sjoerg lcp.Open(sp); 196630300Sjoerg } else if (debug) 196769211Sphk log(-1, "\n"); 196825944Sjoerg } 196925944Sjoerg 197025944Sjoerg sppp_up_event(&lcp, sp); 197125944Sjoerg} 197225944Sjoerg 197325944Sjoergstatic void 197425944Sjoergsppp_lcp_down(struct sppp *sp) 197525944Sjoerg{ 197625944Sjoerg STDDCL; 197725944Sjoerg 197825944Sjoerg sppp_down_event(&lcp, sp); 197925944Sjoerg 198025944Sjoerg /* 198125944Sjoerg * If this is neither a dial-on-demand nor a passive 198225944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 198325944Sjoerg * administrator can force a redial by another ``ifconfig 198425944Sjoerg * up''. XXX For leased line operation, should we immediately 198525944Sjoerg * try to reopen the connection here? 198625944Sjoerg */ 198725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 198825944Sjoerg log(LOG_INFO, 198942066Sphk SPP_FMT "Down event, taking interface down.\n", 199040008Sjoerg SPP_ARGS(ifp)); 199125944Sjoerg if_down(ifp); 199225944Sjoerg } else { 199325944Sjoerg if (debug) 199425944Sjoerg log(LOG_DEBUG, 199540008Sjoerg SPP_FMT "Down event (carrier loss)\n", 199640008Sjoerg SPP_ARGS(ifp)); 199770199Sjhay sp->pp_flags &= ~PP_CALLIN; 199870199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 199970199Sjhay lcp.Close(sp); 200070199Sjhay ifp->if_flags &= ~IFF_RUNNING; 200125944Sjoerg } 200225944Sjoerg} 200325944Sjoerg 200425944Sjoergstatic void 200525944Sjoergsppp_lcp_open(struct sppp *sp) 200625944Sjoerg{ 200725944Sjoerg sppp_open_event(&lcp, sp); 200825944Sjoerg} 200925944Sjoerg 201025944Sjoergstatic void 201125944Sjoergsppp_lcp_close(struct sppp *sp) 201225944Sjoerg{ 201325944Sjoerg sppp_close_event(&lcp, sp); 201425944Sjoerg} 201525944Sjoerg 201625944Sjoergstatic void 201725944Sjoergsppp_lcp_TO(void *cookie) 201825944Sjoerg{ 201925944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 202025944Sjoerg} 202125944Sjoerg 202225944Sjoerg/* 202325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 202425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 202525944Sjoerg * caused action scn. (The return value is used to make the state 202625944Sjoerg * transition decision in the state automaton.) 202725944Sjoerg */ 202812820Sphkstatic int 202925944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 20304910Swollman{ 203125944Sjoerg STDDCL; 203211189Sjkh u_char *buf, *r, *p; 203325944Sjoerg int origlen, rlen; 203425944Sjoerg u_long nmagic; 203530300Sjoerg u_short authproto; 20364910Swollman 203711189Sjkh len -= 4; 203825944Sjoerg origlen = len; 203911189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 204011189Sjkh if (! buf) 204111189Sjkh return (0); 20424910Swollman 204325706Sjoerg if (debug) 204440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 204540008Sjoerg SPP_ARGS(ifp)); 204625706Sjoerg 204725944Sjoerg /* pass 1: check for things that need to be rejected */ 204811189Sjkh p = (void*) (h+1); 204911189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 205025944Sjoerg if (debug) 205169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 205211189Sjkh switch (*p) { 205311189Sjkh case LCP_OPT_MAGIC: 205425944Sjoerg /* Magic number. */ 205570199Sjhay if (len >= 6 && p[1] == 6) 205670199Sjhay continue; 205770199Sjhay if (debug) 205870199Sjhay log(-1, "[invalid] "); 205970199Sjhay break; 206025944Sjoerg case LCP_OPT_ASYNC_MAP: 206125944Sjoerg /* Async control character map. */ 206270199Sjhay if (len >= 6 && p[1] == 6) 206325944Sjoerg continue; 206425944Sjoerg if (debug) 206569211Sphk log(-1, "[invalid] "); 206625944Sjoerg break; 206725944Sjoerg case LCP_OPT_MRU: 206825944Sjoerg /* Maximum receive unit. */ 206925944Sjoerg if (len >= 4 && p[1] == 4) 207025944Sjoerg continue; 207125944Sjoerg if (debug) 207269211Sphk log(-1, "[invalid] "); 207325944Sjoerg break; 207430300Sjoerg case LCP_OPT_AUTH_PROTO: 207530300Sjoerg if (len < 4) { 207630300Sjoerg if (debug) 207769211Sphk log(-1, "[invalid] "); 207830300Sjoerg break; 207930300Sjoerg } 208030300Sjoerg authproto = (p[2] << 8) + p[3]; 208130300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 208230300Sjoerg if (debug) 208369211Sphk log(-1, "[invalid chap len] "); 208430300Sjoerg break; 208530300Sjoerg } 208630300Sjoerg if (sp->myauth.proto == 0) { 208730300Sjoerg /* we are not configured to do auth */ 208830300Sjoerg if (debug) 208969211Sphk log(-1, "[not configured] "); 209030300Sjoerg break; 209130300Sjoerg } 209230300Sjoerg /* 209330300Sjoerg * Remote want us to authenticate, remember this, 209430300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 209530300Sjoerg * up. 209630300Sjoerg */ 209730300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 209830300Sjoerg continue; 209925944Sjoerg default: 210025944Sjoerg /* Others not supported. */ 210125944Sjoerg if (debug) 210269211Sphk log(-1, "[rej] "); 210325944Sjoerg break; 210425944Sjoerg } 210525944Sjoerg /* Add the option to rejected list. */ 210625944Sjoerg bcopy (p, r, p[1]); 210725944Sjoerg r += p[1]; 210825944Sjoerg rlen += p[1]; 210925944Sjoerg } 211025944Sjoerg if (rlen) { 211125944Sjoerg if (debug) 211269211Sphk log(-1, " send conf-rej\n"); 211325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 211425944Sjoerg return 0; 211525944Sjoerg } else if (debug) 211669211Sphk log(-1, "\n"); 211725944Sjoerg 211825944Sjoerg /* 211925944Sjoerg * pass 2: check for option values that are unacceptable and 212025944Sjoerg * thus require to be nak'ed. 212125944Sjoerg */ 212225944Sjoerg if (debug) 212340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 212440008Sjoerg SPP_ARGS(ifp)); 212525944Sjoerg 212625944Sjoerg p = (void*) (h+1); 212725944Sjoerg len = origlen; 212825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 212925944Sjoerg if (debug) 213069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 213125944Sjoerg switch (*p) { 213225944Sjoerg case LCP_OPT_MAGIC: 213311189Sjkh /* Magic number -- extract. */ 213425944Sjoerg nmagic = (u_long)p[2] << 24 | 213525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 213625944Sjoerg if (nmagic != sp->lcp.magic) { 213770199Sjhay sp->pp_loopcnt = 0; 213825706Sjoerg if (debug) 213969211Sphk log(-1, "0x%lx ", nmagic); 214011189Sjkh continue; 214111189Sjkh } 214270199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 214369211Sphk log(-1, "[glitch] "); 214425944Sjoerg ++sp->pp_loopcnt; 214525944Sjoerg /* 214625944Sjoerg * We negate our magic here, and NAK it. If 214725944Sjoerg * we see it later in an NAK packet, we 214825944Sjoerg * suggest a new one. 214925944Sjoerg */ 215025944Sjoerg nmagic = ~sp->lcp.magic; 215125944Sjoerg /* Gonna NAK it. */ 215225944Sjoerg p[2] = nmagic >> 24; 215325944Sjoerg p[3] = nmagic >> 16; 215425944Sjoerg p[4] = nmagic >> 8; 215525944Sjoerg p[5] = nmagic; 215611189Sjkh break; 215725944Sjoerg 215811189Sjkh case LCP_OPT_ASYNC_MAP: 215911189Sjkh /* Async control character map -- check to be zero. */ 216025944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 216125706Sjoerg if (debug) 216269211Sphk log(-1, "[empty] "); 216311189Sjkh continue; 216425706Sjoerg } 216525706Sjoerg if (debug) 216669211Sphk log(-1, "[non-empty] "); 216725944Sjoerg /* suggest a zero one */ 216825944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 216911189Sjkh break; 217025944Sjoerg 217111189Sjkh case LCP_OPT_MRU: 217225944Sjoerg /* 217325944Sjoerg * Maximum receive unit. Always agreeable, 217425944Sjoerg * but ignored by now. 217525944Sjoerg */ 217625944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 217725706Sjoerg if (debug) 217869211Sphk log(-1, "%lu ", sp->lcp.their_mru); 217911189Sjkh continue; 218030300Sjoerg 218130300Sjoerg case LCP_OPT_AUTH_PROTO: 218230300Sjoerg authproto = (p[2] << 8) + p[3]; 218330300Sjoerg if (sp->myauth.proto != authproto) { 218430300Sjoerg /* not agreed, nak */ 218530300Sjoerg if (debug) 218669211Sphk log(-1, "[mine %s != his %s] ", 218730300Sjoerg sppp_proto_name(sp->hisauth.proto), 218830300Sjoerg sppp_proto_name(authproto)); 218930300Sjoerg p[2] = sp->myauth.proto >> 8; 219030300Sjoerg p[3] = sp->myauth.proto; 219130300Sjoerg break; 219230300Sjoerg } 219330300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 219430300Sjoerg if (debug) 219569211Sphk log(-1, "[chap not MD5] "); 219639981Sjoerg p[4] = CHAP_MD5; 219730300Sjoerg break; 219830300Sjoerg } 219930300Sjoerg continue; 220011189Sjkh } 220125944Sjoerg /* Add the option to nak'ed list. */ 220225706Sjoerg bcopy (p, r, p[1]); 220325706Sjoerg r += p[1]; 220411189Sjkh rlen += p[1]; 220512436Speter } 220625706Sjoerg if (rlen) { 220770199Sjhay /* 220870199Sjhay * Local and remote magics equal -- loopback? 220970199Sjhay */ 221070199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 221170199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 221270199Sjhay printf (SPP_FMT "loopback\n", 221370199Sjhay SPP_ARGS(ifp)); 221470199Sjhay if (ifp->if_flags & IFF_UP) { 221570199Sjhay if_down(ifp); 221670199Sjhay sppp_qflush(&sp->pp_cpq); 221770199Sjhay /* XXX ? */ 221870199Sjhay lcp.Down(sp); 221970199Sjhay lcp.Up(sp); 222070199Sjhay } 222170199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 222228036Sjoerg if (debug) 222369211Sphk log(-1, " max_failure (%d) exceeded, " 222428036Sjoerg "send conf-rej\n", 222528036Sjoerg sp->lcp.max_failure); 222628036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 222728036Sjoerg } else { 222828036Sjoerg if (debug) 222969211Sphk log(-1, " send conf-nak\n"); 223028036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 223128036Sjoerg } 223225944Sjoerg } else { 223325944Sjoerg if (debug) 223469211Sphk log(-1, " send conf-ack\n"); 223528036Sjoerg sp->fail_counter[IDX_LCP] = 0; 223625944Sjoerg sp->pp_loopcnt = 0; 223725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 223825944Sjoerg h->ident, origlen, h+1); 223925944Sjoerg } 224025944Sjoerg 224111189Sjkh free (buf, M_TEMP); 224211189Sjkh return (rlen == 0); 22434910Swollman} 22444910Swollman 224525944Sjoerg/* 224625944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 224725944Sjoerg * negotiation. 224825944Sjoerg */ 224912820Sphkstatic void 225025944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 22514910Swollman{ 225225944Sjoerg STDDCL; 225325944Sjoerg u_char *buf, *p; 22544910Swollman 225525944Sjoerg len -= 4; 225625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 225725944Sjoerg if (!buf) 22584910Swollman return; 225925944Sjoerg 226025944Sjoerg if (debug) 226140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 226240008Sjoerg SPP_ARGS(ifp)); 226325944Sjoerg 226425944Sjoerg p = (void*) (h+1); 226525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 226625944Sjoerg if (debug) 226769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 226825944Sjoerg switch (*p) { 226925944Sjoerg case LCP_OPT_MAGIC: 227025944Sjoerg /* Magic number -- can't use it, use 0 */ 227125944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 227225944Sjoerg sp->lcp.magic = 0; 227325944Sjoerg break; 227425944Sjoerg case LCP_OPT_MRU: 227525944Sjoerg /* 227625944Sjoerg * Should not be rejected anyway, since we only 227725944Sjoerg * negotiate a MRU if explicitly requested by 227825944Sjoerg * peer. 227925944Sjoerg */ 228025944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 228125944Sjoerg break; 228230300Sjoerg case LCP_OPT_AUTH_PROTO: 228330300Sjoerg /* 228430300Sjoerg * Peer doesn't want to authenticate himself, 228530300Sjoerg * deny unless this is a dialout call, and 228630300Sjoerg * AUTHFLAG_NOCALLOUT is set. 228730300Sjoerg */ 228830300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 228930300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 229030300Sjoerg if (debug) 229169211Sphk log(-1, "[don't insist on auth " 229230300Sjoerg "for callout]"); 229330300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 229430300Sjoerg break; 229530300Sjoerg } 229630300Sjoerg if (debug) 229769211Sphk log(-1, "[access denied]\n"); 229830300Sjoerg lcp.Close(sp); 229930300Sjoerg break; 230025944Sjoerg } 23014910Swollman } 230225944Sjoerg if (debug) 230369211Sphk log(-1, "\n"); 230425944Sjoerg free (buf, M_TEMP); 230525944Sjoerg return; 230625944Sjoerg} 230725944Sjoerg 230825944Sjoerg/* 230925944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 231025944Sjoerg * negotiation. 231125944Sjoerg */ 231225944Sjoergstatic void 231325944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 231425944Sjoerg{ 231525944Sjoerg STDDCL; 231625944Sjoerg u_char *buf, *p; 231725944Sjoerg u_long magic; 231825944Sjoerg 231925944Sjoerg len -= 4; 232025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 232125944Sjoerg if (!buf) 232225944Sjoerg return; 232325944Sjoerg 232425944Sjoerg if (debug) 232540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 232640008Sjoerg SPP_ARGS(ifp)); 232725944Sjoerg 232825944Sjoerg p = (void*) (h+1); 232925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 233025706Sjoerg if (debug) 233169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 233225944Sjoerg switch (*p) { 233325944Sjoerg case LCP_OPT_MAGIC: 233425944Sjoerg /* Magic number -- renegotiate */ 233525944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 233625944Sjoerg len >= 6 && p[1] == 6) { 233725944Sjoerg magic = (u_long)p[2] << 24 | 233825944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 233925944Sjoerg /* 234025944Sjoerg * If the remote magic is our negated one, 234125944Sjoerg * this looks like a loopback problem. 234225944Sjoerg * Suggest a new magic to make sure. 234325944Sjoerg */ 234425944Sjoerg if (magic == ~sp->lcp.magic) { 234525944Sjoerg if (debug) 234669211Sphk log(-1, "magic glitch "); 234742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 234835064Sphk sp->lcp.magic = random(); 234940008Sjoerg#else 235040008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 235140008Sjoerg#endif 235225944Sjoerg } else { 235325944Sjoerg sp->lcp.magic = magic; 235425944Sjoerg if (debug) 235569211Sphk log(-1, "%lu ", magic); 235625944Sjoerg } 235725944Sjoerg } 235825944Sjoerg break; 235925944Sjoerg case LCP_OPT_MRU: 236025944Sjoerg /* 236125944Sjoerg * Peer wants to advise us to negotiate an MRU. 236225944Sjoerg * Agree on it if it's reasonable, or use 236325944Sjoerg * default otherwise. 236425944Sjoerg */ 236525944Sjoerg if (len >= 4 && p[1] == 4) { 236625944Sjoerg u_int mru = p[2] * 256 + p[3]; 236725944Sjoerg if (debug) 236869211Sphk log(-1, "%d ", mru); 236925944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 237025944Sjoerg mru = PP_MTU; 237125944Sjoerg sp->lcp.mru = mru; 237225944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 237325944Sjoerg } 237425944Sjoerg break; 237530300Sjoerg case LCP_OPT_AUTH_PROTO: 237630300Sjoerg /* 237730300Sjoerg * Peer doesn't like our authentication method, 237830300Sjoerg * deny. 237930300Sjoerg */ 238030300Sjoerg if (debug) 238169211Sphk log(-1, "[access denied]\n"); 238230300Sjoerg lcp.Close(sp); 238330300Sjoerg break; 23844910Swollman } 238525944Sjoerg } 238625944Sjoerg if (debug) 238769211Sphk log(-1, "\n"); 238825944Sjoerg free (buf, M_TEMP); 238925944Sjoerg return; 239025944Sjoerg} 239111189Sjkh 239225944Sjoergstatic void 239325944Sjoergsppp_lcp_tlu(struct sppp *sp) 239425944Sjoerg{ 239542066Sphk STDDCL; 239625944Sjoerg int i; 239725944Sjoerg u_long mask; 239825944Sjoerg 239925944Sjoerg /* XXX ? */ 240025944Sjoerg if (! (ifp->if_flags & IFF_UP) && 240125944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 240225944Sjoerg /* Coming out of loopback mode. */ 240325944Sjoerg if_up(ifp); 240440008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 240525944Sjoerg } 240625944Sjoerg 240725944Sjoerg for (i = 0; i < IDX_COUNT; i++) 240825944Sjoerg if ((cps[i])->flags & CP_QUAL) 240925944Sjoerg (cps[i])->Open(sp); 241025944Sjoerg 241130300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 241230300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 241325944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 241425944Sjoerg else 241525944Sjoerg sp->pp_phase = PHASE_NETWORK; 241625944Sjoerg 241742066Sphk if (debug) 241842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 241942066Sphk sppp_phase_name(sp->pp_phase)); 242025944Sjoerg 242130300Sjoerg /* 242230300Sjoerg * Open all authentication protocols. This is even required 242330300Sjoerg * if we already proceeded to network phase, since it might be 242430300Sjoerg * that remote wants us to authenticate, so we might have to 242530300Sjoerg * send a PAP request. Undesired authentication protocols 242630300Sjoerg * don't do anything when they get an Open event. 242730300Sjoerg */ 242830300Sjoerg for (i = 0; i < IDX_COUNT; i++) 242930300Sjoerg if ((cps[i])->flags & CP_AUTH) 243030300Sjoerg (cps[i])->Open(sp); 243130300Sjoerg 243230300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 243325944Sjoerg /* Notify all NCPs. */ 243425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 243525944Sjoerg if ((cps[i])->flags & CP_NCP) 243625944Sjoerg (cps[i])->Open(sp); 243725944Sjoerg } 243825944Sjoerg 243925944Sjoerg /* Send Up events to all started protos. */ 244025944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 244125944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 244225944Sjoerg (cps[i])->Up(sp); 244325944Sjoerg 244442104Sphk /* notify low-level driver of state change */ 244542104Sphk if (sp->pp_chg) 244642104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 244742104Sphk 244825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 244925944Sjoerg /* if no NCP is starting, close down */ 245030300Sjoerg sppp_lcp_check_and_close(sp); 245125944Sjoerg} 245225944Sjoerg 245325944Sjoergstatic void 245425944Sjoergsppp_lcp_tld(struct sppp *sp) 245525944Sjoerg{ 245642066Sphk STDDCL; 245725944Sjoerg int i; 245825944Sjoerg u_long mask; 245925944Sjoerg 246025944Sjoerg sp->pp_phase = PHASE_TERMINATE; 246125944Sjoerg 246242066Sphk if (debug) 246342066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 246442066Sphk sppp_phase_name(sp->pp_phase)); 246525944Sjoerg 246625944Sjoerg /* 246725944Sjoerg * Take upper layers down. We send the Down event first and 246825944Sjoerg * the Close second to prevent the upper layers from sending 246925944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 247025944Sjoerg * describes it. 247125944Sjoerg */ 247225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 247325944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 247425944Sjoerg (cps[i])->Down(sp); 247525944Sjoerg (cps[i])->Close(sp); 247625944Sjoerg } 247725944Sjoerg} 247825944Sjoerg 247925944Sjoergstatic void 248025944Sjoergsppp_lcp_tls(struct sppp *sp) 248125944Sjoerg{ 248242066Sphk STDDCL; 248325944Sjoerg 248425944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 248525944Sjoerg 248642066Sphk if (debug) 248742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 248842066Sphk sppp_phase_name(sp->pp_phase)); 248925944Sjoerg 249025944Sjoerg /* Notify lower layer if desired. */ 249125944Sjoerg if (sp->pp_tls) 249225944Sjoerg (sp->pp_tls)(sp); 249341881Sphk else 249441881Sphk (sp->pp_up)(sp); 249525944Sjoerg} 249625944Sjoerg 249725944Sjoergstatic void 249825944Sjoergsppp_lcp_tlf(struct sppp *sp) 249925944Sjoerg{ 250042066Sphk STDDCL; 250125944Sjoerg 250225944Sjoerg sp->pp_phase = PHASE_DEAD; 250342066Sphk if (debug) 250442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 250542066Sphk sppp_phase_name(sp->pp_phase)); 250625944Sjoerg 250725944Sjoerg /* Notify lower layer if desired. */ 250825944Sjoerg if (sp->pp_tlf) 250925944Sjoerg (sp->pp_tlf)(sp); 251041881Sphk else 251141881Sphk (sp->pp_down)(sp); 251225944Sjoerg} 251325944Sjoerg 251425944Sjoergstatic void 251525944Sjoergsppp_lcp_scr(struct sppp *sp) 251625944Sjoerg{ 251730300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 251825944Sjoerg int i = 0; 251930300Sjoerg u_short authproto; 252025944Sjoerg 252125944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 252225944Sjoerg if (! sp->lcp.magic) 252342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 252435064Sphk sp->lcp.magic = random(); 252540008Sjoerg#else 252640008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 252740008Sjoerg#endif 252825944Sjoerg opt[i++] = LCP_OPT_MAGIC; 252925944Sjoerg opt[i++] = 6; 253025944Sjoerg opt[i++] = sp->lcp.magic >> 24; 253125944Sjoerg opt[i++] = sp->lcp.magic >> 16; 253225944Sjoerg opt[i++] = sp->lcp.magic >> 8; 253325944Sjoerg opt[i++] = sp->lcp.magic; 253425944Sjoerg } 253525944Sjoerg 253625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 253725944Sjoerg opt[i++] = LCP_OPT_MRU; 253825944Sjoerg opt[i++] = 4; 253925944Sjoerg opt[i++] = sp->lcp.mru >> 8; 254025944Sjoerg opt[i++] = sp->lcp.mru; 254125944Sjoerg } 254225944Sjoerg 254330300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 254430300Sjoerg authproto = sp->hisauth.proto; 254530300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 254630300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 254730300Sjoerg opt[i++] = authproto >> 8; 254830300Sjoerg opt[i++] = authproto; 254930300Sjoerg if (authproto == PPP_CHAP) 255030300Sjoerg opt[i++] = CHAP_MD5; 255130300Sjoerg } 255230300Sjoerg 255378064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 255425944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 255525944Sjoerg} 255625944Sjoerg 255725944Sjoerg/* 255830300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 255930300Sjoerg */ 256030300Sjoergstatic int 256130300Sjoergsppp_ncp_check(struct sppp *sp) 256230300Sjoerg{ 256330300Sjoerg int i, mask; 256430300Sjoerg 256530300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 256630300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 256730300Sjoerg return 1; 256830300Sjoerg return 0; 256930300Sjoerg} 257030300Sjoerg 257130300Sjoerg/* 257225944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 257325944Sjoerg * Called by the NCPs during their tlf action handling. 257425944Sjoerg */ 257525944Sjoergstatic void 257630300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 257725944Sjoerg{ 257825944Sjoerg 257930300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 258030300Sjoerg /* don't bother, we are already going down */ 258130300Sjoerg return; 258230300Sjoerg 258330300Sjoerg if (sppp_ncp_check(sp)) 258430300Sjoerg return; 258530300Sjoerg 258625944Sjoerg lcp.Close(sp); 258725944Sjoerg} 258870199Sjhay 258970199Sjhay/* 259025944Sjoerg *--------------------------------------------------------------------------* 259125944Sjoerg * * 259225944Sjoerg * The IPCP implementation. * 259325944Sjoerg * * 259425944Sjoerg *--------------------------------------------------------------------------* 259525944Sjoerg */ 259625944Sjoerg 259725944Sjoergstatic void 259825944Sjoergsppp_ipcp_init(struct sppp *sp) 259925944Sjoerg{ 260025944Sjoerg sp->ipcp.opts = 0; 260125944Sjoerg sp->ipcp.flags = 0; 260225944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 260325944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 260478064Sume sp->pp_seq[IDX_IPCP] = 0; 260578064Sume sp->pp_rseq[IDX_IPCP] = 0; 260642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 260729681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 260840008Sjoerg#endif 260925944Sjoerg} 261025944Sjoerg 261125944Sjoergstatic void 261225944Sjoergsppp_ipcp_up(struct sppp *sp) 261325944Sjoerg{ 261425944Sjoerg sppp_up_event(&ipcp, sp); 261525944Sjoerg} 261625944Sjoerg 261725944Sjoergstatic void 261825944Sjoergsppp_ipcp_down(struct sppp *sp) 261925944Sjoerg{ 262025944Sjoerg sppp_down_event(&ipcp, sp); 262125944Sjoerg} 262225944Sjoerg 262325944Sjoergstatic void 262425944Sjoergsppp_ipcp_open(struct sppp *sp) 262525944Sjoerg{ 262625944Sjoerg STDDCL; 262725944Sjoerg u_long myaddr, hisaddr; 262825944Sjoerg 262942104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 263042104Sphk 263130300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 263225944Sjoerg /* 263325944Sjoerg * If we don't have his address, this probably means our 263425944Sjoerg * interface doesn't want to talk IP at all. (This could 263525944Sjoerg * be the case if somebody wants to speak only IPX, for 263625944Sjoerg * example.) Don't open IPCP in this case. 263725944Sjoerg */ 263825944Sjoerg if (hisaddr == 0L) { 263925944Sjoerg /* XXX this message should go away */ 264025944Sjoerg if (debug) 264140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 264240008Sjoerg SPP_ARGS(ifp)); 264325944Sjoerg return; 264425944Sjoerg } 264525944Sjoerg 264625944Sjoerg if (myaddr == 0L) { 264725944Sjoerg /* 264825944Sjoerg * I don't have an assigned address, so i need to 264925944Sjoerg * negotiate my address. 265025944Sjoerg */ 265125944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 265225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 265342104Sphk } else 265442104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 265525944Sjoerg sppp_open_event(&ipcp, sp); 265625944Sjoerg} 265725944Sjoerg 265825944Sjoergstatic void 265925944Sjoergsppp_ipcp_close(struct sppp *sp) 266025944Sjoerg{ 266125944Sjoerg sppp_close_event(&ipcp, sp); 266225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 266325944Sjoerg /* 266425944Sjoerg * My address was dynamic, clear it again. 266525944Sjoerg */ 266625944Sjoerg sppp_set_ip_addr(sp, 0L); 266725944Sjoerg} 266825944Sjoerg 266925944Sjoergstatic void 267025944Sjoergsppp_ipcp_TO(void *cookie) 267125944Sjoerg{ 267225944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 267325944Sjoerg} 267425944Sjoerg 267525944Sjoerg/* 267625944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 267725944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 267825944Sjoerg * caused action scn. (The return value is used to make the state 267925944Sjoerg * transition decision in the state automaton.) 268025944Sjoerg */ 268125944Sjoergstatic int 268225944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 268325944Sjoerg{ 268425944Sjoerg u_char *buf, *r, *p; 268525944Sjoerg struct ifnet *ifp = &sp->pp_if; 268625944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 268725944Sjoerg u_long hisaddr, desiredaddr; 268842104Sphk int gotmyaddr = 0; 268925944Sjoerg 269025944Sjoerg len -= 4; 269125944Sjoerg origlen = len; 269225944Sjoerg /* 269325944Sjoerg * Make sure to allocate a buf that can at least hold a 269425944Sjoerg * conf-nak with an `address' option. We might need it below. 269525944Sjoerg */ 269625944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 269725944Sjoerg if (! buf) 269825944Sjoerg return (0); 269925944Sjoerg 270025944Sjoerg /* pass 1: see if we can recognize them */ 270125944Sjoerg if (debug) 270240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 270340008Sjoerg SPP_ARGS(ifp)); 270425944Sjoerg p = (void*) (h+1); 270525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 270625944Sjoerg if (debug) 270769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 270825944Sjoerg switch (*p) { 270925944Sjoerg case IPCP_OPT_ADDRESS: 271025944Sjoerg if (len >= 6 && p[1] == 6) { 271125944Sjoerg /* correctly formed address option */ 271225944Sjoerg continue; 271325944Sjoerg } 271425706Sjoerg if (debug) 271569211Sphk log(-1, "[invalid] "); 271611189Sjkh break; 271725944Sjoerg default: 271825944Sjoerg /* Others not supported. */ 271925944Sjoerg if (debug) 272069211Sphk log(-1, "[rej] "); 27214910Swollman break; 27224910Swollman } 272325944Sjoerg /* Add the option to rejected list. */ 272425944Sjoerg bcopy (p, r, p[1]); 272525944Sjoerg r += p[1]; 272625944Sjoerg rlen += p[1]; 272725944Sjoerg } 272825944Sjoerg if (rlen) { 272925944Sjoerg if (debug) 273069211Sphk log(-1, " send conf-rej\n"); 273125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 273225944Sjoerg return 0; 273325944Sjoerg } else if (debug) 273469211Sphk log(-1, "\n"); 273525944Sjoerg 273625944Sjoerg /* pass 2: parse option values */ 273730300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 273825944Sjoerg if (debug) 273940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 274040008Sjoerg SPP_ARGS(ifp)); 274125944Sjoerg p = (void*) (h+1); 274225944Sjoerg len = origlen; 274325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 274425944Sjoerg if (debug) 274569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 274625944Sjoerg switch (*p) { 274725944Sjoerg case IPCP_OPT_ADDRESS: 274842104Sphk /* This is the address he wants in his end */ 274925944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 275025944Sjoerg p[4] << 8 | p[5]; 275133928Sphk if (desiredaddr == hisaddr || 275242104Sphk (hisaddr == 1 && desiredaddr != 0)) { 275325944Sjoerg /* 275425944Sjoerg * Peer's address is same as our value, 275570199Sjhay * or we have set it to 0.0.0.1 to 275633928Sphk * indicate that we do not really care, 275725944Sjoerg * this is agreeable. Gonna conf-ack 275825944Sjoerg * it. 275925944Sjoerg */ 276025944Sjoerg if (debug) 276169211Sphk log(-1, "%s [ack] ", 276242104Sphk sppp_dotted_quad(hisaddr)); 276325944Sjoerg /* record that we've seen it already */ 276425944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 276525944Sjoerg continue; 276625944Sjoerg } 276725944Sjoerg /* 276825944Sjoerg * The address wasn't agreeable. This is either 276925944Sjoerg * he sent us 0.0.0.0, asking to assign him an 277025944Sjoerg * address, or he send us another address not 277125944Sjoerg * matching our value. Either case, we gonna 277225944Sjoerg * conf-nak it with our value. 277342104Sphk * XXX: we should "rej" if hisaddr == 0 277425944Sjoerg */ 277525944Sjoerg if (debug) { 277625944Sjoerg if (desiredaddr == 0) 277769211Sphk log(-1, "[addr requested] "); 277825944Sjoerg else 277969211Sphk log(-1, "%s [not agreed] ", 278042104Sphk sppp_dotted_quad(desiredaddr)); 278125944Sjoerg 278225944Sjoerg } 278344235Sphk p[2] = hisaddr >> 24; 278444235Sphk p[3] = hisaddr >> 16; 278544235Sphk p[4] = hisaddr >> 8; 278644235Sphk p[5] = hisaddr; 278711189Sjkh break; 278825706Sjoerg } 278925944Sjoerg /* Add the option to nak'ed list. */ 279025944Sjoerg bcopy (p, r, p[1]); 279125944Sjoerg r += p[1]; 279225944Sjoerg rlen += p[1]; 279325944Sjoerg } 279425944Sjoerg 279525944Sjoerg /* 279625944Sjoerg * If we are about to conf-ack the request, but haven't seen 279725944Sjoerg * his address so far, gonna conf-nak it instead, with the 279825944Sjoerg * `address' option present and our idea of his address being 279925944Sjoerg * filled in there, to request negotiation of both addresses. 280025944Sjoerg * 280125944Sjoerg * XXX This can result in an endless req - nak loop if peer 280225944Sjoerg * doesn't want to send us his address. Q: What should we do 280325944Sjoerg * about it? XXX A: implement the max-failure counter. 280425944Sjoerg */ 280542104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 280625944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 280725944Sjoerg buf[1] = 6; 280825944Sjoerg buf[2] = hisaddr >> 24; 280925944Sjoerg buf[3] = hisaddr >> 16; 281025944Sjoerg buf[4] = hisaddr >> 8; 281125944Sjoerg buf[5] = hisaddr; 281225944Sjoerg rlen = 6; 281325706Sjoerg if (debug) 281469211Sphk log(-1, "still need hisaddr "); 281525944Sjoerg } 281625944Sjoerg 281725944Sjoerg if (rlen) { 281825706Sjoerg if (debug) 281969211Sphk log(-1, " send conf-nak\n"); 282025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 282125944Sjoerg } else { 282225706Sjoerg if (debug) 282369211Sphk log(-1, " send conf-ack\n"); 282425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 282525944Sjoerg h->ident, origlen, h+1); 282625944Sjoerg } 282725944Sjoerg 282825944Sjoerg free (buf, M_TEMP); 282925944Sjoerg return (rlen == 0); 283025944Sjoerg} 283125944Sjoerg 283225944Sjoerg/* 283325944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 283425944Sjoerg * negotiation. 283525944Sjoerg */ 283625944Sjoergstatic void 283725944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 283825944Sjoerg{ 283925944Sjoerg u_char *buf, *p; 284025944Sjoerg struct ifnet *ifp = &sp->pp_if; 284125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 284225944Sjoerg 284325944Sjoerg len -= 4; 284425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 284525944Sjoerg if (!buf) 284625944Sjoerg return; 284725944Sjoerg 284825944Sjoerg if (debug) 284940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 285040008Sjoerg SPP_ARGS(ifp)); 285125944Sjoerg 285225944Sjoerg p = (void*) (h+1); 285325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 285425706Sjoerg if (debug) 285569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 285625944Sjoerg switch (*p) { 285725944Sjoerg case IPCP_OPT_ADDRESS: 285825944Sjoerg /* 285925944Sjoerg * Peer doesn't grok address option. This is 286025944Sjoerg * bad. XXX Should we better give up here? 286142104Sphk * XXX We could try old "addresses" option... 286225944Sjoerg */ 286325944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 286425944Sjoerg break; 286525944Sjoerg } 28664910Swollman } 286725944Sjoerg if (debug) 286869211Sphk log(-1, "\n"); 286925944Sjoerg free (buf, M_TEMP); 287025944Sjoerg return; 28714910Swollman} 28724910Swollman 287325944Sjoerg/* 287425944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 287525944Sjoerg * negotiation. 287625944Sjoerg */ 287712820Sphkstatic void 287825944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 28794910Swollman{ 288025944Sjoerg u_char *buf, *p; 288125944Sjoerg struct ifnet *ifp = &sp->pp_if; 288225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 288325944Sjoerg u_long wantaddr; 28844910Swollman 288525944Sjoerg len -= 4; 288625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 288725944Sjoerg if (!buf) 288825944Sjoerg return; 288925944Sjoerg 289025944Sjoerg if (debug) 289140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 289240008Sjoerg SPP_ARGS(ifp)); 289325944Sjoerg 289425944Sjoerg p = (void*) (h+1); 289525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 289625944Sjoerg if (debug) 289769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 289825944Sjoerg switch (*p) { 289925944Sjoerg case IPCP_OPT_ADDRESS: 290025944Sjoerg /* 290125944Sjoerg * Peer doesn't like our local IP address. See 290225944Sjoerg * if we can do something for him. We'll drop 290325944Sjoerg * him our address then. 290425944Sjoerg */ 290525944Sjoerg if (len >= 6 && p[1] == 6) { 290625944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 290725944Sjoerg p[4] << 8 | p[5]; 290825944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 290925944Sjoerg if (debug) 291069211Sphk log(-1, "[wantaddr %s] ", 291130300Sjoerg sppp_dotted_quad(wantaddr)); 291225944Sjoerg /* 291325944Sjoerg * When doing dynamic address assignment, 291425944Sjoerg * we accept his offer. Otherwise, we 291525944Sjoerg * ignore it and thus continue to negotiate 291625944Sjoerg * our already existing value. 291742104Sphk * XXX: Bogus, if he said no once, he'll 291842104Sphk * just say no again, might as well die. 291925944Sjoerg */ 292025944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 292125944Sjoerg sppp_set_ip_addr(sp, wantaddr); 292225944Sjoerg if (debug) 292369211Sphk log(-1, "[agree] "); 292442104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 292525944Sjoerg } 292625944Sjoerg } 292725944Sjoerg break; 292825944Sjoerg } 292925944Sjoerg } 293025944Sjoerg if (debug) 293169211Sphk log(-1, "\n"); 293225944Sjoerg free (buf, M_TEMP); 293325944Sjoerg return; 29344910Swollman} 29354910Swollman 293612820Sphkstatic void 293725944Sjoergsppp_ipcp_tlu(struct sppp *sp) 29384910Swollman{ 293942104Sphk /* we are up - notify isdn daemon */ 294042104Sphk if (sp->pp_con) 294142104Sphk sp->pp_con(sp); 29424910Swollman} 29434910Swollman 294425944Sjoergstatic void 294525944Sjoergsppp_ipcp_tld(struct sppp *sp) 294625944Sjoerg{ 294725944Sjoerg} 294825944Sjoerg 294925944Sjoergstatic void 295025944Sjoergsppp_ipcp_tls(struct sppp *sp) 295125944Sjoerg{ 295225944Sjoerg /* indicate to LCP that it must stay alive */ 295325944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 295425944Sjoerg} 295525944Sjoerg 295625944Sjoergstatic void 295725944Sjoergsppp_ipcp_tlf(struct sppp *sp) 295825944Sjoerg{ 295925944Sjoerg /* we no longer need LCP */ 296025944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 296130300Sjoerg sppp_lcp_check_and_close(sp); 296225944Sjoerg} 296325944Sjoerg 296425944Sjoergstatic void 296525944Sjoergsppp_ipcp_scr(struct sppp *sp) 296625944Sjoerg{ 296725944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 296825944Sjoerg u_long ouraddr; 296925944Sjoerg int i = 0; 297025944Sjoerg 297125944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 297230300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 297325944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 297425944Sjoerg opt[i++] = 6; 297525944Sjoerg opt[i++] = ouraddr >> 24; 297625944Sjoerg opt[i++] = ouraddr >> 16; 297725944Sjoerg opt[i++] = ouraddr >> 8; 297825944Sjoerg opt[i++] = ouraddr; 297925944Sjoerg } 298025944Sjoerg 298178064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 298225944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 298325944Sjoerg} 298425944Sjoerg 298570199Sjhay/* 298630300Sjoerg *--------------------------------------------------------------------------* 298730300Sjoerg * * 298878064Sume * The IPv6CP implementation. * 298978064Sume * * 299078064Sume *--------------------------------------------------------------------------* 299178064Sume */ 299278064Sume 299378064Sume#ifdef INET6 299478064Sumestatic void 299578064Sumesppp_ipv6cp_init(struct sppp *sp) 299678064Sume{ 299778064Sume sp->ipv6cp.opts = 0; 299878064Sume sp->ipv6cp.flags = 0; 299978064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 300078064Sume sp->fail_counter[IDX_IPV6CP] = 0; 300178064Sume sp->pp_seq[IDX_IPV6CP] = 0; 300278064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 300378064Sume#if defined(__NetBSD__) 300478064Sume callout_init(&sp->ch[IDX_IPV6CP]); 300578064Sume#endif 300678064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 300778064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 300878064Sume#endif 300978064Sume} 301078064Sume 301178064Sumestatic void 301278064Sumesppp_ipv6cp_up(struct sppp *sp) 301378064Sume{ 301478064Sume sppp_up_event(&ipv6cp, sp); 301578064Sume} 301678064Sume 301778064Sumestatic void 301878064Sumesppp_ipv6cp_down(struct sppp *sp) 301978064Sume{ 302078064Sume sppp_down_event(&ipv6cp, sp); 302178064Sume} 302278064Sume 302378064Sumestatic void 302478064Sumesppp_ipv6cp_open(struct sppp *sp) 302578064Sume{ 302678064Sume STDDCL; 302778064Sume struct in6_addr myaddr, hisaddr; 302878064Sume 302978064Sume#ifdef IPV6CP_MYIFID_DYN 303078064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 303178064Sume#else 303278064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 303378064Sume#endif 303478064Sume 303578064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 303678064Sume /* 303778064Sume * If we don't have our address, this probably means our 303878064Sume * interface doesn't want to talk IPv6 at all. (This could 303978064Sume * be the case if somebody wants to speak only IPX, for 304078064Sume * example.) Don't open IPv6CP in this case. 304178064Sume */ 304278064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 304378064Sume /* XXX this message should go away */ 304478064Sume if (debug) 304578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 304678064Sume SPP_ARGS(ifp)); 304778064Sume return; 304878064Sume } 304978064Sume 305078064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 305178064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 305278064Sume sppp_open_event(&ipv6cp, sp); 305378064Sume} 305478064Sume 305578064Sumestatic void 305678064Sumesppp_ipv6cp_close(struct sppp *sp) 305778064Sume{ 305878064Sume sppp_close_event(&ipv6cp, sp); 305978064Sume} 306078064Sume 306178064Sumestatic void 306278064Sumesppp_ipv6cp_TO(void *cookie) 306378064Sume{ 306478064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 306578064Sume} 306678064Sume 306778064Sume/* 306878064Sume * Analyze a configure request. Return true if it was agreeable, and 306978064Sume * caused action sca, false if it has been rejected or nak'ed, and 307078064Sume * caused action scn. (The return value is used to make the state 307178064Sume * transition decision in the state automaton.) 307278064Sume */ 307378064Sumestatic int 307478064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 307578064Sume{ 307678064Sume u_char *buf, *r, *p; 307778064Sume struct ifnet *ifp = &sp->pp_if; 307878064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 307978064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 308078064Sume int ifidcount; 308178064Sume int type; 308278064Sume int collision, nohisaddr; 308378064Sume 308478064Sume len -= 4; 308578064Sume origlen = len; 308678064Sume /* 308778064Sume * Make sure to allocate a buf that can at least hold a 308878064Sume * conf-nak with an `address' option. We might need it below. 308978064Sume */ 309078064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 309178064Sume if (! buf) 309278064Sume return (0); 309378064Sume 309478064Sume /* pass 1: see if we can recognize them */ 309578064Sume if (debug) 309678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 309778064Sume SPP_ARGS(ifp)); 309878064Sume p = (void*) (h+1); 309978064Sume ifidcount = 0; 310078064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 310178064Sume if (debug) 310278064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 310378064Sume switch (*p) { 310478064Sume case IPV6CP_OPT_IFID: 310578064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 310678064Sume /* correctly formed address option */ 310778064Sume ifidcount++; 310878064Sume continue; 310978064Sume } 311078064Sume if (debug) 311178064Sume addlog(" [invalid]"); 311278064Sume break; 311378064Sume#ifdef notyet 311478064Sume case IPV6CP_OPT_COMPRESSION: 311578064Sume if (len >= 4 && p[1] >= 4) { 311678064Sume /* correctly formed compress option */ 311778064Sume continue; 311878064Sume } 311978064Sume if (debug) 312078064Sume addlog(" [invalid]"); 312178064Sume break; 312278064Sume#endif 312378064Sume default: 312478064Sume /* Others not supported. */ 312578064Sume if (debug) 312678064Sume addlog(" [rej]"); 312778064Sume break; 312878064Sume } 312978064Sume /* Add the option to rejected list. */ 313078064Sume bcopy (p, r, p[1]); 313178064Sume r += p[1]; 313278064Sume rlen += p[1]; 313378064Sume } 313478064Sume if (rlen) { 313578064Sume if (debug) 313678064Sume addlog(" send conf-rej\n"); 313778064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 313878064Sume goto end; 313978064Sume } else if (debug) 314078064Sume addlog("\n"); 314178064Sume 314278064Sume /* pass 2: parse option values */ 314378064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 314478064Sume if (debug) 314578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 314678064Sume SPP_ARGS(ifp)); 314778064Sume p = (void*) (h+1); 314878064Sume len = origlen; 314978064Sume type = CONF_ACK; 315078064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 315178064Sume if (debug) 315278064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 315378064Sume switch (*p) { 315478064Sume#ifdef notyet 315578064Sume case IPV6CP_OPT_COMPRESSION: 315678064Sume continue; 315778064Sume#endif 315878064Sume case IPV6CP_OPT_IFID: 315978064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 316078064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 316178064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 316278064Sume &myaddr.s6_addr[8], 8) == 0); 316378064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 316478064Sume 316578064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 316678064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 316778064Sume 316878064Sume if (!collision && !nohisaddr) { 316978064Sume /* no collision, hisaddr known - Conf-Ack */ 317078064Sume type = CONF_ACK; 317178064Sume 317278064Sume if (debug) { 317378064Sume addlog(" %s [%s]", 317478064Sume ip6_sprintf(&desiredaddr), 317578064Sume sppp_cp_type_name(type)); 317678064Sume } 317778064Sume continue; 317878064Sume } 317978064Sume 318078064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 318178064Sume if (collision && nohisaddr) { 318278064Sume /* collision, hisaddr unknown - Conf-Rej */ 318378064Sume type = CONF_REJ; 318478064Sume bzero(&p[2], 8); 318578064Sume } else { 318678064Sume /* 318778064Sume * - no collision, hisaddr unknown, or 318878064Sume * - collision, hisaddr known 318978064Sume * Conf-Nak, suggest hisaddr 319078064Sume */ 319178064Sume type = CONF_NAK; 319278064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 319378064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 319478064Sume } 319578064Sume if (debug) 319678064Sume addlog(" %s [%s]", ip6_sprintf(&desiredaddr), 319778064Sume sppp_cp_type_name(type)); 319878064Sume break; 319978064Sume } 320078064Sume /* Add the option to nak'ed list. */ 320178064Sume bcopy (p, r, p[1]); 320278064Sume r += p[1]; 320378064Sume rlen += p[1]; 320478064Sume } 320578064Sume 320678064Sume if (rlen == 0 && type == CONF_ACK) { 320778064Sume if (debug) 320878064Sume addlog(" send %s\n", sppp_cp_type_name(type)); 320978064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 321078064Sume } else { 321178064Sume#ifdef DIAGNOSTIC 321278064Sume if (type == CONF_ACK) 321378064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 321478064Sume#endif 321578064Sume 321678064Sume if (debug) { 321778064Sume addlog(" send %s suggest %s\n", 321878064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 321978064Sume } 322078064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 322178064Sume } 322278064Sume 322378064Sume end: 322478064Sume free (buf, M_TEMP); 322578064Sume return (rlen == 0); 322678064Sume} 322778064Sume 322878064Sume/* 322978064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 323078064Sume * negotiation. 323178064Sume */ 323278064Sumestatic void 323378064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 323478064Sume{ 323578064Sume u_char *buf, *p; 323678064Sume struct ifnet *ifp = &sp->pp_if; 323778064Sume int debug = ifp->if_flags & IFF_DEBUG; 323878064Sume 323978064Sume len -= 4; 324078064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 324178064Sume if (!buf) 324278064Sume return; 324378064Sume 324478064Sume if (debug) 324578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 324678064Sume SPP_ARGS(ifp)); 324778064Sume 324878064Sume p = (void*) (h+1); 324978064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 325078064Sume if (debug) 325178064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 325278064Sume switch (*p) { 325378064Sume case IPV6CP_OPT_IFID: 325478064Sume /* 325578064Sume * Peer doesn't grok address option. This is 325678064Sume * bad. XXX Should we better give up here? 325778064Sume */ 325878064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 325978064Sume break; 326078064Sume#ifdef notyet 326178064Sume case IPV6CP_OPT_COMPRESS: 326278064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 326378064Sume break; 326478064Sume#endif 326578064Sume } 326678064Sume } 326778064Sume if (debug) 326878064Sume addlog("\n"); 326978064Sume free (buf, M_TEMP); 327078064Sume return; 327178064Sume} 327278064Sume 327378064Sume/* 327478064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 327578064Sume * negotiation. 327678064Sume */ 327778064Sumestatic void 327878064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 327978064Sume{ 328078064Sume u_char *buf, *p; 328178064Sume struct ifnet *ifp = &sp->pp_if; 328278064Sume int debug = ifp->if_flags & IFF_DEBUG; 328378064Sume struct in6_addr suggestaddr; 328478064Sume 328578064Sume len -= 4; 328678064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 328778064Sume if (!buf) 328878064Sume return; 328978064Sume 329078064Sume if (debug) 329178064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 329278064Sume SPP_ARGS(ifp)); 329378064Sume 329478064Sume p = (void*) (h+1); 329578064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 329678064Sume if (debug) 329778064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 329878064Sume switch (*p) { 329978064Sume case IPV6CP_OPT_IFID: 330078064Sume /* 330178064Sume * Peer doesn't like our local ifid. See 330278064Sume * if we can do something for him. We'll drop 330378064Sume * him our address then. 330478064Sume */ 330578064Sume if (len < 10 || p[1] != 10) 330678064Sume break; 330778064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 330878064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 330978064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 331078064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 331178064Sume 331278064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 331378064Sume if (debug) 331478064Sume addlog(" [suggestaddr %s]", 331578064Sume ip6_sprintf(&suggestaddr)); 331678064Sume#ifdef IPV6CP_MYIFID_DYN 331778064Sume /* 331878064Sume * When doing dynamic address assignment, 331978064Sume * we accept his offer. 332078064Sume */ 332178064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 332278064Sume struct in6_addr lastsuggest; 332378064Sume /* 332478064Sume * If <suggested myaddr from peer> equals to 332578064Sume * <hisaddr we have suggested last time>, 332678064Sume * we have a collision. generate new random 332778064Sume * ifid. 332878064Sume */ 332978064Sume sppp_suggest_ip6_addr(&lastsuggest); 333078064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 333178064Sume lastsuggest)) { 333278064Sume if (debug) 333378064Sume addlog(" [random]"); 333478064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 333578064Sume } 333678064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 333778064Sume if (debug) 333878064Sume addlog(" [agree]"); 333978064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 334078064Sume } 334178064Sume#else 334278064Sume /* 334378064Sume * Since we do not do dynamic address assignment, 334478064Sume * we ignore it and thus continue to negotiate 334578064Sume * our already existing value. This can possibly 334678064Sume * go into infinite request-reject loop. 334778064Sume * 334878064Sume * This is not likely because we normally use 334978064Sume * ifid based on MAC-address. 335078064Sume * If you have no ethernet card on the node, too bad. 335178064Sume * XXX should we use fail_counter? 335278064Sume */ 335378064Sume#endif 335478064Sume break; 335578064Sume#ifdef notyet 335678064Sume case IPV6CP_OPT_COMPRESS: 335778064Sume /* 335878064Sume * Peer wants different compression parameters. 335978064Sume */ 336078064Sume break; 336178064Sume#endif 336278064Sume } 336378064Sume } 336478064Sume if (debug) 336578064Sume addlog("\n"); 336678064Sume free (buf, M_TEMP); 336778064Sume return; 336878064Sume} 336978064Sumestatic void 337078064Sumesppp_ipv6cp_tlu(struct sppp *sp) 337178064Sume{ 337278064Sume /* we are up - notify isdn daemon */ 337378064Sume if (sp->pp_con) 337478064Sume sp->pp_con(sp); 337578064Sume} 337678064Sume 337778064Sumestatic void 337878064Sumesppp_ipv6cp_tld(struct sppp *sp) 337978064Sume{ 338078064Sume} 338178064Sume 338278064Sumestatic void 338378064Sumesppp_ipv6cp_tls(struct sppp *sp) 338478064Sume{ 338578064Sume /* indicate to LCP that it must stay alive */ 338678064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 338778064Sume} 338878064Sume 338978064Sumestatic void 339078064Sumesppp_ipv6cp_tlf(struct sppp *sp) 339178064Sume{ 339278064Sume 339378064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 339478064Sume /* we no longer need LCP */ 339578064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 339678064Sume sppp_lcp_check_and_close(sp); 339778064Sume#endif 339878064Sume} 339978064Sume 340078064Sumestatic void 340178064Sumesppp_ipv6cp_scr(struct sppp *sp) 340278064Sume{ 340378064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 340478064Sume struct in6_addr ouraddr; 340578064Sume int i = 0; 340678064Sume 340778064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 340878064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 340978064Sume opt[i++] = IPV6CP_OPT_IFID; 341078064Sume opt[i++] = 10; 341178064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 341278064Sume i += 8; 341378064Sume } 341478064Sume 341578064Sume#ifdef notyet 341678064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 341778064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 341878064Sume opt[i++] = 4; 341978064Sume opt[i++] = 0; /* TBD */ 342078064Sume opt[i++] = 0; /* TBD */ 342178064Sume /* variable length data may follow */ 342278064Sume } 342378064Sume#endif 342478064Sume 342578064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 342678064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 342778064Sume} 342878064Sume#else /*INET6*/ 342978064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 343078064Sume{ 343178064Sume} 343278064Sume 343378064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 343478064Sume{ 343578064Sume} 343678064Sume 343778064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 343878064Sume{ 343978064Sume} 344078064Sume 344178064Sume 344278064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 344378064Sume{ 344478064Sume} 344578064Sume 344678064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 344778064Sume{ 344878064Sume} 344978064Sume 345078064Sumestatic void sppp_ipv6cp_TO(void *sp) 345178064Sume{ 345278064Sume} 345378064Sume 345478064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 345578064Sume{ 345678064Sume return 0; 345778064Sume} 345878064Sume 345978064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 346078064Sume{ 346178064Sume} 346278064Sume 346378064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 346478064Sume{ 346578064Sume} 346678064Sume 346778064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 346878064Sume{ 346978064Sume} 347078064Sume 347178064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 347278064Sume{ 347378064Sume} 347478064Sume 347578064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 347678064Sume{ 347778064Sume} 347878064Sume 347978064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 348078064Sume{ 348178064Sume} 348278064Sume 348378064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 348478064Sume{ 348578064Sume} 348678064Sume#endif /*INET6*/ 348778064Sume 348878064Sume/* 348978064Sume *--------------------------------------------------------------------------* 349078064Sume * * 349130300Sjoerg * The CHAP implementation. * 349230300Sjoerg * * 349330300Sjoerg *--------------------------------------------------------------------------* 349430300Sjoerg */ 349530300Sjoerg 349630300Sjoerg/* 349730300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 349830300Sjoerg * the control protocols do, since they do have Open and Close events, but 349930300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 350030300Sjoerg * authentication protocols may be different in both directions (this makes 350130300Sjoerg * sense, think of a machine that never accepts incoming calls but only 350230300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 350330300Sjoerg * 350430300Sjoerg * Our state machine for the local authentication protocol (we are requesting 350530300Sjoerg * the peer to authenticate) looks like: 350630300Sjoerg * 350730300Sjoerg * RCA- 350830300Sjoerg * +--------------------------------------------+ 350930300Sjoerg * V scn,tld| 351030300Sjoerg * +--------+ Close +---------+ RCA+ 351130300Sjoerg * | |<----------------------------------| |------+ 351230300Sjoerg * +--->| Closed | TO* | Opened | sca | 351330300Sjoerg * | | |-----+ +-------| |<-----+ 351430300Sjoerg * | +--------+ irc | | +---------+ 351530300Sjoerg * | ^ | | ^ 351630300Sjoerg * | | | | | 351730300Sjoerg * | | | | | 351830300Sjoerg * | TO-| | | | 351930300Sjoerg * | |tld TO+ V | | 352030300Sjoerg * | | +------->+ | | 352130300Sjoerg * | | | | | | 352230300Sjoerg * | +--------+ V | | 352330300Sjoerg * | | |<----+<--------------------+ | 352430300Sjoerg * | | Req- | scr | 352530300Sjoerg * | | Sent | | 352630300Sjoerg * | | | | 352730300Sjoerg * | +--------+ | 352830300Sjoerg * | RCA- | | RCA+ | 352930300Sjoerg * +------+ +------------------------------------------+ 353030300Sjoerg * scn,tld sca,irc,ict,tlu 353130300Sjoerg * 353230300Sjoerg * 353330300Sjoerg * with: 353430300Sjoerg * 353530300Sjoerg * Open: LCP reached authentication phase 353630300Sjoerg * Close: LCP reached terminate phase 353730300Sjoerg * 353830300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 353930300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 354030300Sjoerg * TO+: timeout with restart counter >= 0 354130300Sjoerg * TO-: timeout with restart counter < 0 354230300Sjoerg * TO*: reschedule timeout for CHAP 354330300Sjoerg * 354430300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 354530300Sjoerg * sca: send ack packet (pap-ack, chap-success) 354630300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 354730300Sjoerg * ict: initialize re-challenge timer (CHAP only) 354830300Sjoerg * 354930300Sjoerg * tlu: this-layer-up, LCP reaches network phase 355030300Sjoerg * tld: this-layer-down, LCP enters terminate phase 355130300Sjoerg * 355230300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 355330300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 355430300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 355530300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 355630300Sjoerg * causing LCP to enter terminate phase. 355730300Sjoerg * 355830300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 355930300Sjoerg * expected to send one based on the successful negotiation of PAP as 356030300Sjoerg * the authentication protocol during the LCP option negotiation. 356130300Sjoerg * 356230300Sjoerg * Incoming authentication protocol requests (remote requests 356330300Sjoerg * authentication, we are peer) don't employ a state machine at all, 356430300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 356530300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 356630300Sjoerg * still in authentication phase (thereby violating the standard that 356730300Sjoerg * demands that these NCP packets are to be discarded), so we keep 356830300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 356930300Sjoerg * phase network once we've seen a positive acknowledge for the 357030300Sjoerg * authentication. 357130300Sjoerg */ 357230300Sjoerg 357330300Sjoerg/* 357430300Sjoerg * Handle incoming CHAP packets. 357530300Sjoerg */ 357630300Sjoergvoid 357730300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 357830300Sjoerg{ 357930300Sjoerg STDDCL; 358030300Sjoerg struct lcp_header *h; 358130300Sjoerg int len, x; 358230300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 358330300Sjoerg int value_len, name_len; 358430300Sjoerg MD5_CTX ctx; 358530300Sjoerg 358630300Sjoerg len = m->m_pkthdr.len; 358730300Sjoerg if (len < 4) { 358830300Sjoerg if (debug) 358930300Sjoerg log(LOG_DEBUG, 359040008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 359140008Sjoerg SPP_ARGS(ifp), len); 359230300Sjoerg return; 359330300Sjoerg } 359430300Sjoerg h = mtod (m, struct lcp_header*); 359530300Sjoerg if (len > ntohs (h->len)) 359630300Sjoerg len = ntohs (h->len); 359730300Sjoerg 359830300Sjoerg switch (h->type) { 359930300Sjoerg /* challenge, failure and success are his authproto */ 360030300Sjoerg case CHAP_CHALLENGE: 360130300Sjoerg value = 1 + (u_char*)(h+1); 360230300Sjoerg value_len = value[-1]; 360330300Sjoerg name = value + value_len; 360430300Sjoerg name_len = len - value_len - 5; 360530300Sjoerg if (name_len < 0) { 360630300Sjoerg if (debug) { 360730300Sjoerg log(LOG_DEBUG, 360840008Sjoerg SPP_FMT "chap corrupted challenge " 360930300Sjoerg "<%s id=0x%x len=%d", 361040008Sjoerg SPP_ARGS(ifp), 361130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 361230300Sjoerg h->ident, ntohs(h->len)); 361344145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 361469211Sphk log(-1, ">\n"); 361530300Sjoerg } 361630300Sjoerg break; 361730300Sjoerg } 361870199Sjhay 361930300Sjoerg if (debug) { 362030300Sjoerg log(LOG_DEBUG, 362140008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 362240008Sjoerg SPP_ARGS(ifp), 362330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 362430300Sjoerg ntohs(h->len)); 362530300Sjoerg sppp_print_string((char*) name, name_len); 362669211Sphk log(-1, " value-size=%d value=", value_len); 362730300Sjoerg sppp_print_bytes(value, value_len); 362869211Sphk log(-1, ">\n"); 362930300Sjoerg } 363030300Sjoerg 363130300Sjoerg /* Compute reply value. */ 363230300Sjoerg MD5Init(&ctx); 363330300Sjoerg MD5Update(&ctx, &h->ident, 1); 363430300Sjoerg MD5Update(&ctx, sp->myauth.secret, 363530300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 363630300Sjoerg MD5Update(&ctx, value, value_len); 363730300Sjoerg MD5Final(digest, &ctx); 363830300Sjoerg dsize = sizeof digest; 363930300Sjoerg 364030300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 364130300Sjoerg sizeof dsize, (const char *)&dsize, 364230300Sjoerg sizeof digest, digest, 364340008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 364430300Sjoerg sp->myauth.name, 364530300Sjoerg 0); 364630300Sjoerg break; 364730300Sjoerg 364830300Sjoerg case CHAP_SUCCESS: 364930300Sjoerg if (debug) { 365040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 365140008Sjoerg SPP_ARGS(ifp)); 365230300Sjoerg if (len > 4) { 365369211Sphk log(-1, ": "); 365430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 365530300Sjoerg } 365669211Sphk log(-1, "\n"); 365730300Sjoerg } 365830300Sjoerg x = splimp(); 365930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 366030300Sjoerg if (sp->myauth.proto == PPP_CHAP && 366132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 366230300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 366330300Sjoerg /* 366430300Sjoerg * We are authenticator for CHAP but didn't 366530300Sjoerg * complete yet. Leave it to tlu to proceed 366630300Sjoerg * to network phase. 366730300Sjoerg */ 366830300Sjoerg splx(x); 366930300Sjoerg break; 367030300Sjoerg } 367130300Sjoerg splx(x); 367230300Sjoerg sppp_phase_network(sp); 367330300Sjoerg break; 367430300Sjoerg 367530300Sjoerg case CHAP_FAILURE: 367630300Sjoerg if (debug) { 367740008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 367840008Sjoerg SPP_ARGS(ifp)); 367930300Sjoerg if (len > 4) { 368069211Sphk log(-1, ": "); 368130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 368230300Sjoerg } 368369211Sphk log(-1, "\n"); 368430300Sjoerg } else 368540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 368640008Sjoerg SPP_ARGS(ifp)); 368730300Sjoerg /* await LCP shutdown by authenticator */ 368830300Sjoerg break; 368930300Sjoerg 369030300Sjoerg /* response is my authproto */ 369130300Sjoerg case CHAP_RESPONSE: 369230300Sjoerg value = 1 + (u_char*)(h+1); 369330300Sjoerg value_len = value[-1]; 369430300Sjoerg name = value + value_len; 369530300Sjoerg name_len = len - value_len - 5; 369630300Sjoerg if (name_len < 0) { 369730300Sjoerg if (debug) { 369830300Sjoerg log(LOG_DEBUG, 369940008Sjoerg SPP_FMT "chap corrupted response " 370030300Sjoerg "<%s id=0x%x len=%d", 370140008Sjoerg SPP_ARGS(ifp), 370230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 370330300Sjoerg h->ident, ntohs(h->len)); 370444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 370569211Sphk log(-1, ">\n"); 370630300Sjoerg } 370730300Sjoerg break; 370830300Sjoerg } 370930300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 371030300Sjoerg if (debug) 371130300Sjoerg log(LOG_DEBUG, 371240008Sjoerg SPP_FMT "chap dropping response for old ID " 371330300Sjoerg "(got %d, expected %d)\n", 371440008Sjoerg SPP_ARGS(ifp), 371530300Sjoerg h->ident, sp->confid[IDX_CHAP]); 371630300Sjoerg break; 371730300Sjoerg } 371830300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 371930300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 372040008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 372140008Sjoerg SPP_ARGS(ifp)); 372230300Sjoerg sppp_print_string(name, name_len); 372369211Sphk log(-1, " != expected "); 372430300Sjoerg sppp_print_string(sp->hisauth.name, 372530300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 372669211Sphk log(-1, "\n"); 372770199Sjhay } 372830300Sjoerg if (debug) { 372940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 373030300Sjoerg "<%s id=0x%x len=%d name=", 373140008Sjoerg SPP_ARGS(ifp), 373230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 373330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 373430300Sjoerg h->ident, ntohs (h->len)); 373530300Sjoerg sppp_print_string((char*)name, name_len); 373669211Sphk log(-1, " value-size=%d value=", value_len); 373730300Sjoerg sppp_print_bytes(value, value_len); 373869211Sphk log(-1, ">\n"); 373930300Sjoerg } 374030300Sjoerg if (value_len != AUTHKEYLEN) { 374130300Sjoerg if (debug) 374230300Sjoerg log(LOG_DEBUG, 374340008Sjoerg SPP_FMT "chap bad hash value length: " 374430300Sjoerg "%d bytes, should be %d\n", 374540008Sjoerg SPP_ARGS(ifp), value_len, 374630300Sjoerg AUTHKEYLEN); 374730300Sjoerg break; 374830300Sjoerg } 374930300Sjoerg 375030300Sjoerg MD5Init(&ctx); 375130300Sjoerg MD5Update(&ctx, &h->ident, 1); 375230300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 375330300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 375430300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 375530300Sjoerg MD5Final(digest, &ctx); 375630300Sjoerg 375730300Sjoerg#define FAILMSG "Failed..." 375830300Sjoerg#define SUCCMSG "Welcome!" 375930300Sjoerg 376030300Sjoerg if (value_len != sizeof digest || 376130300Sjoerg bcmp(digest, value, value_len) != 0) { 376230300Sjoerg /* action scn, tld */ 376330300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 376430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 376530300Sjoerg 0); 376630300Sjoerg chap.tld(sp); 376730300Sjoerg break; 376830300Sjoerg } 376930300Sjoerg /* action sca, perhaps tlu */ 377030300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 377130300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 377230300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 377330300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 377430300Sjoerg 0); 377530300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 377630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 377730300Sjoerg chap.tlu(sp); 377830300Sjoerg } 377930300Sjoerg break; 378030300Sjoerg 378130300Sjoerg default: 378230300Sjoerg /* Unknown CHAP packet type -- ignore. */ 378330300Sjoerg if (debug) { 378440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 378530300Sjoerg "<0x%x id=0x%xh len=%d", 378640008Sjoerg SPP_ARGS(ifp), 378730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 378830300Sjoerg h->type, h->ident, ntohs(h->len)); 378944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 379069211Sphk log(-1, ">\n"); 379130300Sjoerg } 379230300Sjoerg break; 379330300Sjoerg 379430300Sjoerg } 379530300Sjoerg} 379630300Sjoerg 379730300Sjoergstatic void 379830300Sjoergsppp_chap_init(struct sppp *sp) 379930300Sjoerg{ 380030300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 380130300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 380230300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 380378064Sume sp->pp_seq[IDX_CHAP] = 0; 380478064Sume sp->pp_rseq[IDX_CHAP] = 0; 380542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 380630300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 380740008Sjoerg#endif 380830300Sjoerg} 380930300Sjoerg 381030300Sjoergstatic void 381130300Sjoergsppp_chap_open(struct sppp *sp) 381230300Sjoerg{ 381330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 381430300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 381530300Sjoerg /* we are authenticator for CHAP, start it */ 381630300Sjoerg chap.scr(sp); 381730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 381830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 381930300Sjoerg } 382030300Sjoerg /* nothing to be done if we are peer, await a challenge */ 382130300Sjoerg} 382230300Sjoerg 382330300Sjoergstatic void 382430300Sjoergsppp_chap_close(struct sppp *sp) 382530300Sjoerg{ 382630300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 382730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 382830300Sjoerg} 382930300Sjoerg 383030300Sjoergstatic void 383130300Sjoergsppp_chap_TO(void *cookie) 383230300Sjoerg{ 383330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 383430300Sjoerg STDDCL; 383530300Sjoerg int s; 383630300Sjoerg 383730300Sjoerg s = splimp(); 383830300Sjoerg if (debug) 383940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 384040008Sjoerg SPP_ARGS(ifp), 384130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 384230300Sjoerg sp->rst_counter[IDX_CHAP]); 384330300Sjoerg 384430300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 384530300Sjoerg /* TO- event */ 384630300Sjoerg switch (sp->state[IDX_CHAP]) { 384730300Sjoerg case STATE_REQ_SENT: 384830300Sjoerg chap.tld(sp); 384930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 385030300Sjoerg break; 385130300Sjoerg } 385230300Sjoerg else 385330300Sjoerg /* TO+ (or TO*) event */ 385430300Sjoerg switch (sp->state[IDX_CHAP]) { 385530300Sjoerg case STATE_OPENED: 385630300Sjoerg /* TO* event */ 385730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 385830300Sjoerg /* fall through */ 385930300Sjoerg case STATE_REQ_SENT: 386030300Sjoerg chap.scr(sp); 386130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 386230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 386330300Sjoerg break; 386430300Sjoerg } 386530300Sjoerg 386630300Sjoerg splx(s); 386730300Sjoerg} 386830300Sjoerg 386930300Sjoergstatic void 387030300Sjoergsppp_chap_tlu(struct sppp *sp) 387130300Sjoerg{ 387230300Sjoerg STDDCL; 387330300Sjoerg int i, x; 387430300Sjoerg 387540010Sjoerg i = 0; 387630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 387730300Sjoerg 387830300Sjoerg /* 387930300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 388030300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 388130300Sjoerg * initial challenge-response exchange has taken place. 388230300Sjoerg * Provide for an option to avoid rechallenges. 388330300Sjoerg */ 388430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 388530300Sjoerg /* 388630300Sjoerg * Compute the re-challenge timeout. This will yield 388730300Sjoerg * a number between 300 and 810 seconds. 388830300Sjoerg */ 388930300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 389042064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 389130300Sjoerg } 389230300Sjoerg 389330300Sjoerg if (debug) { 389430300Sjoerg log(LOG_DEBUG, 389540008Sjoerg SPP_FMT "chap %s, ", 389640008Sjoerg SPP_ARGS(ifp), 389730300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 389830300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 389969211Sphk log(-1, "next re-challenge in %d seconds\n", i); 390030300Sjoerg else 390169211Sphk log(-1, "re-challenging supressed\n"); 390230300Sjoerg } 390330300Sjoerg 390430300Sjoerg x = splimp(); 390530300Sjoerg /* indicate to LCP that we need to be closed down */ 390630300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 390730300Sjoerg 390830300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 390930300Sjoerg /* 391030300Sjoerg * Remote is authenticator, but his auth proto didn't 391130300Sjoerg * complete yet. Defer the transition to network 391230300Sjoerg * phase. 391330300Sjoerg */ 391430300Sjoerg splx(x); 391530300Sjoerg return; 391630300Sjoerg } 391730300Sjoerg splx(x); 391830300Sjoerg 391930300Sjoerg /* 392030300Sjoerg * If we are already in phase network, we are done here. This 392130300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 392230300Sjoerg */ 392330300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 392430300Sjoerg sppp_phase_network(sp); 392530300Sjoerg} 392630300Sjoerg 392730300Sjoergstatic void 392830300Sjoergsppp_chap_tld(struct sppp *sp) 392930300Sjoerg{ 393030300Sjoerg STDDCL; 393130300Sjoerg 393230300Sjoerg if (debug) 393340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 393440008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 393530300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 393630300Sjoerg 393730300Sjoerg lcp.Close(sp); 393830300Sjoerg} 393930300Sjoerg 394030300Sjoergstatic void 394130300Sjoergsppp_chap_scr(struct sppp *sp) 394230300Sjoerg{ 394330300Sjoerg u_long *ch, seed; 394430300Sjoerg u_char clen; 394530300Sjoerg 394630300Sjoerg /* Compute random challenge. */ 394730300Sjoerg ch = (u_long *)sp->myauth.challenge; 394842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 394935064Sphk read_random(&seed, sizeof seed); 395040008Sjoerg#else 395142104Sphk { 395242104Sphk struct timeval tv; 395340008Sjoerg microtime(&tv); 395440008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 395542104Sphk } 395640008Sjoerg#endif 395730300Sjoerg ch[0] = seed ^ random(); 395830300Sjoerg ch[1] = seed ^ random(); 395930300Sjoerg ch[2] = seed ^ random(); 396030300Sjoerg ch[3] = seed ^ random(); 396130300Sjoerg clen = AUTHKEYLEN; 396230300Sjoerg 396378064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 396430300Sjoerg 396530300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 396630300Sjoerg sizeof clen, (const char *)&clen, 396740008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 396840008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 396930300Sjoerg sp->myauth.name, 397030300Sjoerg 0); 397130300Sjoerg} 397270199Sjhay 397370199Sjhay/* 397430300Sjoerg *--------------------------------------------------------------------------* 397530300Sjoerg * * 397630300Sjoerg * The PAP implementation. * 397730300Sjoerg * * 397830300Sjoerg *--------------------------------------------------------------------------* 397930300Sjoerg */ 398030300Sjoerg/* 398130300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 398230300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 398330300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 398430300Sjoerg * retry counter is expired). 398530300Sjoerg */ 398630300Sjoerg 398730300Sjoerg/* 398830300Sjoerg * Handle incoming PAP packets. */ 398930300Sjoergstatic void 399030300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 399130300Sjoerg{ 399230300Sjoerg STDDCL; 399330300Sjoerg struct lcp_header *h; 399430300Sjoerg int len, x; 399530300Sjoerg u_char *name, *passwd, mlen; 399630300Sjoerg int name_len, passwd_len; 399730300Sjoerg 399830300Sjoerg len = m->m_pkthdr.len; 399930300Sjoerg if (len < 5) { 400030300Sjoerg if (debug) 400130300Sjoerg log(LOG_DEBUG, 400240008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 400340008Sjoerg SPP_ARGS(ifp), len); 400430300Sjoerg return; 400530300Sjoerg } 400630300Sjoerg h = mtod (m, struct lcp_header*); 400730300Sjoerg if (len > ntohs (h->len)) 400830300Sjoerg len = ntohs (h->len); 400930300Sjoerg switch (h->type) { 401030300Sjoerg /* PAP request is my authproto */ 401130300Sjoerg case PAP_REQ: 401230300Sjoerg name = 1 + (u_char*)(h+1); 401330300Sjoerg name_len = name[-1]; 401430300Sjoerg passwd = name + name_len + 1; 401530300Sjoerg if (name_len > len - 6 || 401630300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 401730300Sjoerg if (debug) { 401840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 401930300Sjoerg "<%s id=0x%x len=%d", 402040008Sjoerg SPP_ARGS(ifp), 402130300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 402230300Sjoerg h->ident, ntohs(h->len)); 402344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 402469211Sphk log(-1, ">\n"); 402530300Sjoerg } 402630300Sjoerg break; 402730300Sjoerg } 402830300Sjoerg if (debug) { 402940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 403030300Sjoerg "<%s id=0x%x len=%d name=", 403140008Sjoerg SPP_ARGS(ifp), 403230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 403330300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 403430300Sjoerg h->ident, ntohs(h->len)); 403530300Sjoerg sppp_print_string((char*)name, name_len); 403669211Sphk log(-1, " passwd="); 403730300Sjoerg sppp_print_string((char*)passwd, passwd_len); 403869211Sphk log(-1, ">\n"); 403930300Sjoerg } 404074774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 404174774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 404230300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 404330300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 404430300Sjoerg /* action scn, tld */ 404530300Sjoerg mlen = sizeof(FAILMSG) - 1; 404630300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 404730300Sjoerg sizeof mlen, (const char *)&mlen, 404830300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 404930300Sjoerg 0); 405030300Sjoerg pap.tld(sp); 405130300Sjoerg break; 405230300Sjoerg } 405330300Sjoerg /* action sca, perhaps tlu */ 405430300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 405530300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 405630300Sjoerg mlen = sizeof(SUCCMSG) - 1; 405730300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 405830300Sjoerg sizeof mlen, (const char *)&mlen, 405930300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 406030300Sjoerg 0); 406130300Sjoerg } 406230300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 406330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 406430300Sjoerg pap.tlu(sp); 406530300Sjoerg } 406630300Sjoerg break; 406730300Sjoerg 406830300Sjoerg /* ack and nak are his authproto */ 406930300Sjoerg case PAP_ACK: 407040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 407130300Sjoerg if (debug) { 407240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 407340008Sjoerg SPP_ARGS(ifp)); 407430300Sjoerg name_len = *((char *)h); 407530300Sjoerg if (len > 5 && name_len) { 407669211Sphk log(-1, ": "); 407730300Sjoerg sppp_print_string((char*)(h+1), name_len); 407830300Sjoerg } 407969211Sphk log(-1, "\n"); 408030300Sjoerg } 408130300Sjoerg x = splimp(); 408230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 408330300Sjoerg if (sp->myauth.proto == PPP_PAP && 408432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 408530300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 408630300Sjoerg /* 408730300Sjoerg * We are authenticator for PAP but didn't 408830300Sjoerg * complete yet. Leave it to tlu to proceed 408930300Sjoerg * to network phase. 409030300Sjoerg */ 409130300Sjoerg splx(x); 409230300Sjoerg break; 409330300Sjoerg } 409430300Sjoerg splx(x); 409530300Sjoerg sppp_phase_network(sp); 409630300Sjoerg break; 409730300Sjoerg 409830300Sjoerg case PAP_NAK: 409940008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 410030300Sjoerg if (debug) { 410140008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 410240008Sjoerg SPP_ARGS(ifp)); 410330300Sjoerg name_len = *((char *)h); 410430300Sjoerg if (len > 5 && name_len) { 410569211Sphk log(-1, ": "); 410630300Sjoerg sppp_print_string((char*)(h+1), name_len); 410730300Sjoerg } 410869211Sphk log(-1, "\n"); 410930300Sjoerg } else 411040008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 411140008Sjoerg SPP_ARGS(ifp)); 411230300Sjoerg /* await LCP shutdown by authenticator */ 411330300Sjoerg break; 411430300Sjoerg 411530300Sjoerg default: 411630300Sjoerg /* Unknown PAP packet type -- ignore. */ 411730300Sjoerg if (debug) { 411840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 411930300Sjoerg "<0x%x id=0x%x len=%d", 412040008Sjoerg SPP_ARGS(ifp), 412130300Sjoerg h->type, h->ident, ntohs(h->len)); 412244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 412369211Sphk log(-1, ">\n"); 412430300Sjoerg } 412530300Sjoerg break; 412630300Sjoerg 412730300Sjoerg } 412830300Sjoerg} 412930300Sjoerg 413030300Sjoergstatic void 413130300Sjoergsppp_pap_init(struct sppp *sp) 413230300Sjoerg{ 413330300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 413430300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 413530300Sjoerg sp->fail_counter[IDX_PAP] = 0; 413678064Sume sp->pp_seq[IDX_PAP] = 0; 413778064Sume sp->pp_rseq[IDX_PAP] = 0; 413842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 413930300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 414030300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 414140008Sjoerg#endif 414230300Sjoerg} 414330300Sjoerg 414430300Sjoergstatic void 414530300Sjoergsppp_pap_open(struct sppp *sp) 414630300Sjoerg{ 414730300Sjoerg if (sp->hisauth.proto == PPP_PAP && 414830300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 414930300Sjoerg /* we are authenticator for PAP, start our timer */ 415030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 415130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 415230300Sjoerg } 415330300Sjoerg if (sp->myauth.proto == PPP_PAP) { 415430300Sjoerg /* we are peer, send a request, and start a timer */ 415530300Sjoerg pap.scr(sp); 415642064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 415742064Sphk sp->pap_my_to_ch); 415830300Sjoerg } 415930300Sjoerg} 416030300Sjoerg 416130300Sjoergstatic void 416230300Sjoergsppp_pap_close(struct sppp *sp) 416330300Sjoerg{ 416430300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 416530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 416630300Sjoerg} 416730300Sjoerg 416830300Sjoerg/* 416930300Sjoerg * That's the timeout routine if we are authenticator. Since the 417030300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 417130300Sjoerg */ 417230300Sjoergstatic void 417330300Sjoergsppp_pap_TO(void *cookie) 417430300Sjoerg{ 417530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 417630300Sjoerg STDDCL; 417730300Sjoerg int s; 417830300Sjoerg 417930300Sjoerg s = splimp(); 418030300Sjoerg if (debug) 418140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 418240008Sjoerg SPP_ARGS(ifp), 418330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 418430300Sjoerg sp->rst_counter[IDX_PAP]); 418530300Sjoerg 418630300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 418730300Sjoerg /* TO- event */ 418830300Sjoerg switch (sp->state[IDX_PAP]) { 418930300Sjoerg case STATE_REQ_SENT: 419030300Sjoerg pap.tld(sp); 419130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 419230300Sjoerg break; 419330300Sjoerg } 419430300Sjoerg else 419530300Sjoerg /* TO+ event, not very much we could do */ 419630300Sjoerg switch (sp->state[IDX_PAP]) { 419730300Sjoerg case STATE_REQ_SENT: 419830300Sjoerg /* sppp_cp_change_state() will restart the timer */ 419930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 420030300Sjoerg break; 420130300Sjoerg } 420230300Sjoerg 420330300Sjoerg splx(s); 420430300Sjoerg} 420530300Sjoerg 420630300Sjoerg/* 420730300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 420830300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 420930300Sjoerg * XXX We should impose a max counter. 421030300Sjoerg */ 421130300Sjoergstatic void 421230300Sjoergsppp_pap_my_TO(void *cookie) 421330300Sjoerg{ 421430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 421530300Sjoerg STDDCL; 421630300Sjoerg 421730300Sjoerg if (debug) 421840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 421940008Sjoerg SPP_ARGS(ifp)); 422030300Sjoerg 422130300Sjoerg pap.scr(sp); 422230300Sjoerg} 422330300Sjoerg 422430300Sjoergstatic void 422530300Sjoergsppp_pap_tlu(struct sppp *sp) 422630300Sjoerg{ 422730300Sjoerg STDDCL; 422830300Sjoerg int x; 422930300Sjoerg 423030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 423130300Sjoerg 423230300Sjoerg if (debug) 423340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 423440008Sjoerg SPP_ARGS(ifp), pap.name); 423530300Sjoerg 423630300Sjoerg x = splimp(); 423730300Sjoerg /* indicate to LCP that we need to be closed down */ 423830300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 423930300Sjoerg 424030300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 424130300Sjoerg /* 424230300Sjoerg * Remote is authenticator, but his auth proto didn't 424330300Sjoerg * complete yet. Defer the transition to network 424430300Sjoerg * phase. 424530300Sjoerg */ 424630300Sjoerg splx(x); 424730300Sjoerg return; 424830300Sjoerg } 424930300Sjoerg splx(x); 425030300Sjoerg sppp_phase_network(sp); 425130300Sjoerg} 425230300Sjoerg 425330300Sjoergstatic void 425430300Sjoergsppp_pap_tld(struct sppp *sp) 425530300Sjoerg{ 425630300Sjoerg STDDCL; 425730300Sjoerg 425830300Sjoerg if (debug) 425940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 426040008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 426140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 426230300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 426330300Sjoerg 426430300Sjoerg lcp.Close(sp); 426530300Sjoerg} 426630300Sjoerg 426730300Sjoergstatic void 426830300Sjoergsppp_pap_scr(struct sppp *sp) 426930300Sjoerg{ 427030300Sjoerg u_char idlen, pwdlen; 427130300Sjoerg 427278064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 427330300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 427430300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 427530300Sjoerg 427630300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 427730300Sjoerg sizeof idlen, (const char *)&idlen, 427840008Sjoerg (size_t)idlen, sp->myauth.name, 427930300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 428040008Sjoerg (size_t)pwdlen, sp->myauth.secret, 428130300Sjoerg 0); 428230300Sjoerg} 428370199Sjhay 428470199Sjhay/* 428525944Sjoerg * Random miscellaneous functions. 428625944Sjoerg */ 428725944Sjoerg 42884910Swollman/* 428930300Sjoerg * Send a PAP or CHAP proto packet. 429030300Sjoerg * 429130300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 429240008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 429330300Sjoerg * mlen == 0. 429442104Sphk * NOTE: never declare variadic functions with types subject to type 429542104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 429642104Sphk * on the architecture you are on... 429730300Sjoerg */ 429830300Sjoerg 429930300Sjoergstatic void 430042104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 430142104Sphk unsigned int type, unsigned int id, 430230300Sjoerg ...) 430330300Sjoerg{ 430430300Sjoerg STDDCL; 430530300Sjoerg struct ppp_header *h; 430630300Sjoerg struct lcp_header *lh; 430730300Sjoerg struct mbuf *m; 430830300Sjoerg u_char *p; 430930300Sjoerg int len; 431042104Sphk unsigned int mlen; 431130300Sjoerg const char *msg; 431230300Sjoerg va_list ap; 431330300Sjoerg 431430300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 431530300Sjoerg if (! m) 431630300Sjoerg return; 431730300Sjoerg m->m_pkthdr.rcvif = 0; 431830300Sjoerg 431930300Sjoerg h = mtod (m, struct ppp_header*); 432030300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 432130300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 432230300Sjoerg h->protocol = htons(cp->proto); 432330300Sjoerg 432430300Sjoerg lh = (struct lcp_header*)(h + 1); 432530300Sjoerg lh->type = type; 432630300Sjoerg lh->ident = id; 432730300Sjoerg p = (u_char*) (lh+1); 432830300Sjoerg 432930300Sjoerg va_start(ap, id); 433030300Sjoerg len = 0; 433130300Sjoerg 433242104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 433330300Sjoerg msg = va_arg(ap, const char *); 433430300Sjoerg len += mlen; 433530300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 433630300Sjoerg va_end(ap); 433730300Sjoerg m_freem(m); 433830300Sjoerg return; 433930300Sjoerg } 434030300Sjoerg 434130300Sjoerg bcopy(msg, p, mlen); 434230300Sjoerg p += mlen; 434330300Sjoerg } 434430300Sjoerg va_end(ap); 434530300Sjoerg 434630300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 434730300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 434830300Sjoerg 434930300Sjoerg if (debug) { 435040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 435140008Sjoerg SPP_ARGS(ifp), cp->name, 435230300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 435330300Sjoerg lh->ident, ntohs(lh->len)); 435444145Sphk sppp_print_bytes((u_char*) (lh+1), len); 435569211Sphk log(-1, ">\n"); 435630300Sjoerg } 435769152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 435869152Sjlemon ifp->if_oerrors++; 435930300Sjoerg} 436030300Sjoerg 436130300Sjoerg/* 436225944Sjoerg * Flush interface queue. 43634910Swollman */ 436412820Sphkstatic void 436525944Sjoergsppp_qflush(struct ifqueue *ifq) 43664910Swollman{ 436725944Sjoerg struct mbuf *m, *n; 43684910Swollman 436925944Sjoerg n = ifq->ifq_head; 437025944Sjoerg while ((m = n)) { 437125944Sjoerg n = m->m_act; 437225944Sjoerg m_freem (m); 437311189Sjkh } 437425944Sjoerg ifq->ifq_head = 0; 437525944Sjoerg ifq->ifq_tail = 0; 437625944Sjoerg ifq->ifq_len = 0; 437725944Sjoerg} 437825944Sjoerg 437925944Sjoerg/* 438025944Sjoerg * Send keepalive packets, every 10 seconds. 438125944Sjoerg */ 438225944Sjoergstatic void 438325944Sjoergsppp_keepalive(void *dummy) 438425944Sjoerg{ 438525944Sjoerg struct sppp *sp; 438625944Sjoerg int s; 438725944Sjoerg 438825944Sjoerg s = splimp(); 438925944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 439025944Sjoerg struct ifnet *ifp = &sp->pp_if; 439125944Sjoerg 439225944Sjoerg /* Keepalive mode disabled or channel down? */ 439325944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 439425944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 439525944Sjoerg continue; 439625944Sjoerg 439725944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 439845152Sphk if (sp->pp_mode != IFF_CISCO && 439925944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 440025944Sjoerg continue; 440125944Sjoerg 440225944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 440325944Sjoerg /* No keepalive packets got. Stop the interface. */ 440440008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 440525944Sjoerg if_down (ifp); 440626018Sjoerg sppp_qflush (&sp->pp_cpq); 440745152Sphk if (sp->pp_mode != IFF_CISCO) { 440825944Sjoerg /* XXX */ 440925944Sjoerg /* Shut down the PPP link. */ 441025944Sjoerg lcp.Down(sp); 441125944Sjoerg /* Initiate negotiation. XXX */ 441225944Sjoerg lcp.Up(sp); 441325944Sjoerg } 44144910Swollman } 441525944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 441625944Sjoerg ++sp->pp_alivecnt; 441745152Sphk if (sp->pp_mode == IFF_CISCO) 441878064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 441978064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 442025944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 442125944Sjoerg long nmagic = htonl (sp->lcp.magic); 442278064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 442325944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 442425944Sjoerg sp->lcp.echoid, 4, &nmagic); 442525944Sjoerg } 44264910Swollman } 442725944Sjoerg splx(s); 442842064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 44294910Swollman} 44304910Swollman 443125944Sjoerg/* 443225944Sjoerg * Get both IP addresses. 443325944Sjoerg */ 443425944Sjoergstatic void 443530300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 443625944Sjoerg{ 443725944Sjoerg struct ifnet *ifp = &sp->pp_if; 443825944Sjoerg struct ifaddr *ifa; 443930300Sjoerg struct sockaddr_in *si, *sm; 444025944Sjoerg u_long ssrc, ddst; 444125944Sjoerg 444240010Sjoerg sm = NULL; 444325944Sjoerg ssrc = ddst = 0L; 444425944Sjoerg /* 444525944Sjoerg * Pick the first AF_INET address from the list, 444625944Sjoerg * aliases don't make any sense on a p2p link anyway. 444725944Sjoerg */ 444842065Sphk si = 0; 444942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 445042065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 445142104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 445271959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 445340008Sjoerg ifa; 445471959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 445542104Sphk#else 445642104Sphk for (ifa = ifp->if_addrlist; 445742104Sphk ifa; 445842104Sphk ifa = ifa->ifa_next) 445940008Sjoerg#endif 446025944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 446125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 446230300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 446325944Sjoerg if (si) 446425944Sjoerg break; 446525944Sjoerg } 446625944Sjoerg if (ifa) { 446730300Sjoerg if (si && si->sin_addr.s_addr) { 446825944Sjoerg ssrc = si->sin_addr.s_addr; 446930300Sjoerg if (srcmask) 447030300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 447130300Sjoerg } 447225944Sjoerg 447325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 447425944Sjoerg if (si && si->sin_addr.s_addr) 447525944Sjoerg ddst = si->sin_addr.s_addr; 447625944Sjoerg } 447725944Sjoerg 447825944Sjoerg if (dst) *dst = ntohl(ddst); 447925944Sjoerg if (src) *src = ntohl(ssrc); 448025944Sjoerg} 448125944Sjoerg 448225944Sjoerg/* 448325944Sjoerg * Set my IP address. Must be called at splimp. 448425944Sjoerg */ 448525944Sjoergstatic void 448625944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 448725944Sjoerg{ 448842104Sphk STDDCL; 448925944Sjoerg struct ifaddr *ifa; 449025944Sjoerg struct sockaddr_in *si; 449125944Sjoerg 449225944Sjoerg /* 449325944Sjoerg * Pick the first AF_INET address from the list, 449425944Sjoerg * aliases don't make any sense on a p2p link anyway. 449525944Sjoerg */ 449642065Sphk si = 0; 449742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 449842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 449942104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 450071959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 450140008Sjoerg ifa; 450271959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 450342104Sphk#else 450442104Sphk for (ifa = ifp->if_addrlist; 450542104Sphk ifa; 450642104Sphk ifa = ifa->ifa_next) 450740008Sjoerg#endif 450840008Sjoerg { 450940008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 451040008Sjoerg { 451125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 451225944Sjoerg if (si) 451325944Sjoerg break; 451425944Sjoerg } 451540008Sjoerg } 451640008Sjoerg 451725944Sjoerg if (ifa && si) 451842104Sphk { 451942104Sphk int error; 452042104Sphk#if __NetBSD_Version__ >= 103080000 452142104Sphk struct sockaddr_in new_sin = *si; 452242104Sphk 452342104Sphk new_sin.sin_addr.s_addr = htonl(src); 452442104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 452542104Sphk if(debug && error) 452642104Sphk { 452742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 452842104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 452942104Sphk } 453042104Sphk#else 453142104Sphk /* delete old route */ 453242104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 453342104Sphk if(debug && error) 453442104Sphk { 453542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 453642104Sphk SPP_ARGS(ifp), error); 453742104Sphk } 453842104Sphk 453942104Sphk /* set new address */ 454025944Sjoerg si->sin_addr.s_addr = htonl(src); 454125944Sjoerg 454242104Sphk /* add new route */ 454370199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 454442104Sphk if (debug && error) 454542104Sphk { 454642104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 454742104Sphk SPP_ARGS(ifp), error); 454842104Sphk } 454942104Sphk#endif 455042104Sphk } 455178064Sume} 455278064Sume 455378064Sume#ifdef INET6 455478064Sume/* 455578064Sume * Get both IPv6 addresses. 455678064Sume */ 455778064Sumestatic void 455878064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 455978064Sume struct in6_addr *srcmask) 456078064Sume{ 456178064Sume struct ifnet *ifp = &sp->pp_if; 456278064Sume struct ifaddr *ifa; 456378064Sume struct sockaddr_in6 *si, *sm; 456478064Sume struct in6_addr ssrc, ddst; 456578064Sume 456678064Sume sm = NULL; 456778064Sume bzero(&ssrc, sizeof(ssrc)); 456878064Sume bzero(&ddst, sizeof(ddst)); 456978064Sume /* 457078064Sume * Pick the first link-local AF_INET6 address from the list, 457178064Sume * aliases don't make any sense on a p2p link anyway. 457278064Sume */ 457378064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 457478064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 457578064Sume ifa; 457678064Sume ifa = ifa->ifa_link.tqe_next) 457778064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 457878064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 457978064Sume ifa; 458078064Sume ifa = ifa->ifa_list.tqe_next) 458178064Sume#else 458278064Sume for (ifa = ifp->if_addrlist, si = 0; 458378064Sume ifa; 458478064Sume ifa = ifa->ifa_next) 458578064Sume#endif 458678064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 458778064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 458878064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 458978064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 459078064Sume break; 459178064Sume } 459278064Sume if (ifa) { 459378064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 459478064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 459578064Sume if (srcmask) { 459678064Sume bcopy(&sm->sin6_addr, srcmask, 459778064Sume sizeof(*srcmask)); 459878064Sume } 459978064Sume } 460078064Sume 460178064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 460278064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 460378064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 460478064Sume } 460578064Sume 460678064Sume if (dst) 460778064Sume bcopy(&ddst, dst, sizeof(*dst)); 460878064Sume if (src) 460978064Sume bcopy(&ssrc, src, sizeof(*src)); 461070199Sjhay} 461142104Sphk 461278064Sume#ifdef IPV6CP_MYIFID_DYN 461378064Sume/* 461478064Sume * Generate random ifid. 461578064Sume */ 461678064Sumestatic void 461778064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 461878064Sume{ 461978064Sume /* TBD */ 462078064Sume} 462178064Sume 462278064Sume/* 462378064Sume * Set my IPv6 address. Must be called at splimp. 462478064Sume */ 462578064Sumestatic void 462678064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 462778064Sume{ 462878064Sume STDDCL; 462978064Sume struct ifaddr *ifa; 463078064Sume struct sockaddr_in6 *sin6; 463178064Sume 463278064Sume /* 463378064Sume * Pick the first link-local AF_INET6 address from the list, 463478064Sume * aliases don't make any sense on a p2p link anyway. 463578064Sume */ 463678064Sume 463778064Sume sin6 = NULL; 463878064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 463978064Sume for (ifa = ifp->if_addrhead.tqh_first; 464078064Sume ifa; 464178064Sume ifa = ifa->ifa_link.tqe_next) 464278064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 464378064Sume for (ifa = ifp->if_addrlist.tqh_first; 464478064Sume ifa; 464578064Sume ifa = ifa->ifa_list.tqe_next) 464678064Sume#else 464778064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 464878064Sume#endif 464978064Sume { 465078064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 465178064Sume { 465278064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 465378064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 465478064Sume break; 465578064Sume } 465678064Sume } 465778064Sume 465878064Sume if (ifa && sin6) 465978064Sume { 466078064Sume int error; 466178064Sume struct sockaddr_in6 new_sin6 = *sin6; 466278064Sume 466378064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 466478064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 466578064Sume if (debug && error) 466678064Sume { 466778064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 466878064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 466978064Sume } 467078064Sume } 467178064Sume} 467278064Sume#endif 467378064Sume 467478064Sume/* 467578064Sume * Suggest a candidate address to be used by peer. 467678064Sume */ 467778064Sumestatic void 467878064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 467978064Sume{ 468078064Sume struct in6_addr myaddr; 468178064Sume struct timeval tv; 468278064Sume 468378064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 468478064Sume 468578064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 468678064Sume microtime(&tv); 468778064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 468878064Sume myaddr.s6_addr[14] ^= 0xff; 468978064Sume myaddr.s6_addr[15] ^= 0xff; 469078064Sume } else { 469178064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 469278064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 469378064Sume } 469478064Sume if (suggest) 469578064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 469678064Sume} 469778064Sume#endif /*INET6*/ 469878064Sume 469930300Sjoergstatic int 470038343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 470130300Sjoerg{ 470238343Sbde u_long subcmd; 470330300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 470430300Sjoerg struct spppreq spr; 470530300Sjoerg 470630300Sjoerg /* 470730300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 470830300Sjoerg * Check the cmd word first before attempting to fetch all the 470930300Sjoerg * data. 471030300Sjoerg */ 471130300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 471230300Sjoerg return EFAULT; 471330300Sjoerg 471430300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 471530300Sjoerg return EFAULT; 471630300Sjoerg 471730300Sjoerg switch (subcmd) { 471830300Sjoerg case SPPPIOGDEFS: 471930300Sjoerg if (cmd != SIOCGIFGENERIC) 472030300Sjoerg return EINVAL; 472130300Sjoerg /* 472230300Sjoerg * We copy over the entire current state, but clean 472330300Sjoerg * out some of the stuff we don't wanna pass up. 472430300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 472530300Sjoerg * called by any user. No need to ever get PAP or 472630300Sjoerg * CHAP secrets back to userland anyway. 472730300Sjoerg */ 472830300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 472930300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 473030300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 473130300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 473230300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 473330300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 473430300Sjoerg 473530300Sjoerg case SPPPIOSDEFS: 473630300Sjoerg if (cmd != SIOCSIFGENERIC) 473730300Sjoerg return EINVAL; 473830300Sjoerg /* 473930300Sjoerg * We have a very specific idea of which fields we allow 474030300Sjoerg * being passed back from userland, so to not clobber our 474130300Sjoerg * current state. For one, we only allow setting 474230300Sjoerg * anything if LCP is in dead phase. Once the LCP 474330300Sjoerg * negotiations started, the authentication settings must 474430300Sjoerg * not be changed again. (The administrator can force an 474530300Sjoerg * ifconfig down in order to get LCP back into dead 474630300Sjoerg * phase.) 474730300Sjoerg * 474830300Sjoerg * Also, we only allow for authentication parameters to be 474930300Sjoerg * specified. 475030300Sjoerg * 475130300Sjoerg * XXX Should allow to set or clear pp_flags. 475230300Sjoerg * 475330300Sjoerg * Finally, if the respective authentication protocol to 475430300Sjoerg * be used is set differently than 0, but the secret is 475530300Sjoerg * passed as all zeros, we don't trash the existing secret. 475630300Sjoerg * This allows an administrator to change the system name 475730300Sjoerg * only without clobbering the secret (which he didn't get 475830300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 475930300Sjoerg * secrets are cleared if the authentication protocol is 476030300Sjoerg * reset to 0. 476130300Sjoerg */ 476230300Sjoerg if (sp->pp_phase != PHASE_DEAD) 476330300Sjoerg return EBUSY; 476430300Sjoerg 476530300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 476630300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 476730300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 476830300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 476930300Sjoerg return EINVAL; 477030300Sjoerg 477130300Sjoerg if (spr.defs.myauth.proto == 0) 477230300Sjoerg /* resetting myauth */ 477330300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 477430300Sjoerg else { 477530300Sjoerg /* setting/changing myauth */ 477630300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 477730300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 477830300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 477930300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 478030300Sjoerg AUTHKEYLEN); 478130300Sjoerg } 478230300Sjoerg if (spr.defs.hisauth.proto == 0) 478330300Sjoerg /* resetting hisauth */ 478430300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 478530300Sjoerg else { 478630300Sjoerg /* setting/changing hisauth */ 478730300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 478830300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 478930300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 479030300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 479130300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 479230300Sjoerg AUTHKEYLEN); 479330300Sjoerg } 479430300Sjoerg break; 479530300Sjoerg 479630300Sjoerg default: 479730300Sjoerg return EINVAL; 479830300Sjoerg } 479930300Sjoerg 480030300Sjoerg return 0; 480130300Sjoerg} 480230300Sjoerg 480330300Sjoergstatic void 480430300Sjoergsppp_phase_network(struct sppp *sp) 480530300Sjoerg{ 480642066Sphk STDDCL; 480730300Sjoerg int i; 480830300Sjoerg u_long mask; 480930300Sjoerg 481030300Sjoerg sp->pp_phase = PHASE_NETWORK; 481130300Sjoerg 481242066Sphk if (debug) 481342066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 481442066Sphk sppp_phase_name(sp->pp_phase)); 481530300Sjoerg 481630300Sjoerg /* Notify NCPs now. */ 481730300Sjoerg for (i = 0; i < IDX_COUNT; i++) 481830300Sjoerg if ((cps[i])->flags & CP_NCP) 481930300Sjoerg (cps[i])->Open(sp); 482030300Sjoerg 482130300Sjoerg /* Send Up events to all NCPs. */ 482230300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 482330300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 482430300Sjoerg (cps[i])->Up(sp); 482530300Sjoerg 482630300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 482730300Sjoerg sppp_lcp_check_and_close(sp); 482830300Sjoerg} 482930300Sjoerg 483070199Sjhay 483125706Sjoergstatic const char * 483225944Sjoergsppp_cp_type_name(u_char type) 48334910Swollman{ 483430300Sjoerg static char buf[12]; 48354910Swollman switch (type) { 483630300Sjoerg case CONF_REQ: return "conf-req"; 483730300Sjoerg case CONF_ACK: return "conf-ack"; 483830300Sjoerg case CONF_NAK: return "conf-nak"; 483930300Sjoerg case CONF_REJ: return "conf-rej"; 484030300Sjoerg case TERM_REQ: return "term-req"; 484130300Sjoerg case TERM_ACK: return "term-ack"; 484230300Sjoerg case CODE_REJ: return "code-rej"; 484330300Sjoerg case PROTO_REJ: return "proto-rej"; 484430300Sjoerg case ECHO_REQ: return "echo-req"; 484530300Sjoerg case ECHO_REPLY: return "echo-reply"; 484630300Sjoerg case DISC_REQ: return "discard-req"; 48474910Swollman } 484844145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 484930300Sjoerg return buf; 48504910Swollman} 48514910Swollman 485225706Sjoergstatic const char * 485330300Sjoergsppp_auth_type_name(u_short proto, u_char type) 485430300Sjoerg{ 485530300Sjoerg static char buf[12]; 485630300Sjoerg switch (proto) { 485730300Sjoerg case PPP_CHAP: 485830300Sjoerg switch (type) { 485930300Sjoerg case CHAP_CHALLENGE: return "challenge"; 486030300Sjoerg case CHAP_RESPONSE: return "response"; 486130300Sjoerg case CHAP_SUCCESS: return "success"; 486230300Sjoerg case CHAP_FAILURE: return "failure"; 486330300Sjoerg } 486430300Sjoerg case PPP_PAP: 486530300Sjoerg switch (type) { 486630300Sjoerg case PAP_REQ: return "req"; 486730300Sjoerg case PAP_ACK: return "ack"; 486830300Sjoerg case PAP_NAK: return "nak"; 486930300Sjoerg } 487030300Sjoerg } 487144145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 487230300Sjoerg return buf; 487330300Sjoerg} 487430300Sjoerg 487530300Sjoergstatic const char * 487625944Sjoergsppp_lcp_opt_name(u_char opt) 48774910Swollman{ 487830300Sjoerg static char buf[12]; 487925944Sjoerg switch (opt) { 488030300Sjoerg case LCP_OPT_MRU: return "mru"; 488130300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 488230300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 488330300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 488430300Sjoerg case LCP_OPT_MAGIC: return "magic"; 488530300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 488630300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 48874910Swollman } 488844145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 488930300Sjoerg return buf; 48904910Swollman} 48914910Swollman 489225944Sjoergstatic const char * 489325944Sjoergsppp_ipcp_opt_name(u_char opt) 489425944Sjoerg{ 489530300Sjoerg static char buf[12]; 489625944Sjoerg switch (opt) { 489730300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 489830300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 489930300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 490025944Sjoerg } 490144145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 490230300Sjoerg return buf; 490325944Sjoerg} 490425944Sjoerg 490578064Sume#ifdef INET6 490625944Sjoergstatic const char * 490778064Sumesppp_ipv6cp_opt_name(u_char opt) 490878064Sume{ 490978064Sume static char buf[12]; 491078064Sume switch (opt) { 491178064Sume case IPV6CP_OPT_IFID: return "ifid"; 491278064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 491378064Sume } 491478064Sume sprintf (buf, "0x%x", opt); 491578064Sume return buf; 491678064Sume} 491778064Sume#endif 491878064Sume 491978064Sumestatic const char * 492025944Sjoergsppp_state_name(int state) 492125944Sjoerg{ 492225944Sjoerg switch (state) { 492325944Sjoerg case STATE_INITIAL: return "initial"; 492425944Sjoerg case STATE_STARTING: return "starting"; 492525944Sjoerg case STATE_CLOSED: return "closed"; 492625944Sjoerg case STATE_STOPPED: return "stopped"; 492725944Sjoerg case STATE_CLOSING: return "closing"; 492825944Sjoerg case STATE_STOPPING: return "stopping"; 492925944Sjoerg case STATE_REQ_SENT: return "req-sent"; 493025944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 493125944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 493225944Sjoerg case STATE_OPENED: return "opened"; 493325944Sjoerg } 493425944Sjoerg return "illegal"; 493525944Sjoerg} 493625944Sjoerg 493725944Sjoergstatic const char * 493825944Sjoergsppp_phase_name(enum ppp_phase phase) 493925944Sjoerg{ 494025944Sjoerg switch (phase) { 494125944Sjoerg case PHASE_DEAD: return "dead"; 494225944Sjoerg case PHASE_ESTABLISH: return "establish"; 494325944Sjoerg case PHASE_TERMINATE: return "terminate"; 494425944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 494525944Sjoerg case PHASE_NETWORK: return "network"; 494625944Sjoerg } 494725944Sjoerg return "illegal"; 494825944Sjoerg} 494925944Sjoerg 495025944Sjoergstatic const char * 495125944Sjoergsppp_proto_name(u_short proto) 495225944Sjoerg{ 495325944Sjoerg static char buf[12]; 495425944Sjoerg switch (proto) { 495525944Sjoerg case PPP_LCP: return "lcp"; 495625944Sjoerg case PPP_IPCP: return "ipcp"; 495730300Sjoerg case PPP_PAP: return "pap"; 495830300Sjoerg case PPP_CHAP: return "chap"; 495978064Sume case PPP_IPV6CP: return "ipv6cp"; 496025944Sjoerg } 496144145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 496225944Sjoerg return buf; 496325944Sjoerg} 496425944Sjoerg 496512820Sphkstatic void 496630300Sjoergsppp_print_bytes(const u_char *p, u_short len) 49674910Swollman{ 496844145Sphk if (len) 496969211Sphk log(-1, " %*D", len, p, "-"); 49704910Swollman} 497125944Sjoerg 497230300Sjoergstatic void 497330300Sjoergsppp_print_string(const char *p, u_short len) 497430300Sjoerg{ 497530300Sjoerg u_char c; 497630300Sjoerg 497730300Sjoerg while (len-- > 0) { 497830300Sjoerg c = *p++; 497930300Sjoerg /* 498030300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 498130300Sjoerg * using only them, but we don't rely on it. */ 498230300Sjoerg if (c < ' ' || c > '~') 498369211Sphk log(-1, "\\x%x", c); 498430300Sjoerg else 498569211Sphk log(-1, "%c", c); 498630300Sjoerg } 498730300Sjoerg} 498830300Sjoerg 498930300Sjoergstatic const char * 499030300Sjoergsppp_dotted_quad(u_long addr) 499130300Sjoerg{ 499230300Sjoerg static char s[16]; 499330300Sjoerg sprintf(s, "%d.%d.%d.%d", 499440008Sjoerg (int)((addr >> 24) & 0xff), 499540008Sjoerg (int)((addr >> 16) & 0xff), 499640008Sjoerg (int)((addr >> 8) & 0xff), 499738372Sbde (int)(addr & 0xff)); 499830300Sjoerg return s; 499930300Sjoerg} 500030300Sjoerg 500130300Sjoergstatic int 500230300Sjoergsppp_strnlen(u_char *p, int max) 500330300Sjoerg{ 500430300Sjoerg int len; 500530300Sjoerg 500630300Sjoerg for (len = 0; len < max && *p; ++p) 500730300Sjoerg ++len; 500830300Sjoerg return len; 500930300Sjoerg} 501030300Sjoerg 501130300Sjoerg/* a dummy, used to drop uninteresting events */ 501230300Sjoergstatic void 501330300Sjoergsppp_null(struct sppp *unused) 501430300Sjoerg{ 501530300Sjoerg /* do just nothing */ 501630300Sjoerg} 5017