if_spppsubr.c revision 80715
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 80715 2001-07-31 07:27:01Z 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 8474910Swollman default: 8484910Swollman m_freem (m); 84925944Sjoerg ++ifp->if_oerrors; 8504910Swollman splx (s); 8514910Swollman return (EAFNOSUPPORT); 8524910Swollman } 8534910Swollman 8544910Swollman /* 8554910Swollman * Queue message on interface, and start output if interface 85669152Sjlemon * not yet active. Also adjust output byte count. 85769152Sjlemon * The packet length includes header, FCS and 1 flag, 85869152Sjlemon * according to RFC 1333. 8594910Swollman */ 86069152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 86125944Sjoerg ++ifp->if_oerrors; 86225955Sjoerg return (rv? rv: ENOBUFS); 8634910Swollman } 8644910Swollman return (0); 8654910Swollman} 8664910Swollman 86725706Sjoergvoid 86825706Sjoergsppp_attach(struct ifnet *ifp) 8694910Swollman{ 8704910Swollman struct sppp *sp = (struct sppp*) ifp; 8714910Swollman 8724910Swollman /* Initialize keepalive handler. */ 8734910Swollman if (! spppq) 87442064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 8754910Swollman 8764910Swollman /* Insert new entry into the keepalive list. */ 8774910Swollman sp->pp_next = spppq; 8784910Swollman spppq = sp; 8794910Swollman 88042064Sphk sp->pp_if.if_mtu = PP_MTU; 88142064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8824910Swollman sp->pp_if.if_type = IFT_PPP; 8834910Swollman sp->pp_if.if_output = sppp_output; 88442104Sphk#if 0 88542064Sphk sp->pp_flags = PP_KEEPALIVE; 88642104Sphk#endif 88770199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 88870199Sjhay sp->pp_fastq.ifq_maxlen = 32; 88970199Sjhay sp->pp_cpq.ifq_maxlen = 20; 8904910Swollman sp->pp_loopcnt = 0; 8914910Swollman sp->pp_alivecnt = 0; 89278064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 89378064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 89425944Sjoerg sp->pp_phase = PHASE_DEAD; 89525944Sjoerg sp->pp_up = lcp.Up; 89625944Sjoerg sp->pp_down = lcp.Down; 89769152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 89869152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 89925944Sjoerg 90025944Sjoerg sppp_lcp_init(sp); 90125944Sjoerg sppp_ipcp_init(sp); 90278064Sume sppp_ipv6cp_init(sp); 90330300Sjoerg sppp_pap_init(sp); 90430300Sjoerg sppp_chap_init(sp); 9054910Swollman} 9064910Swollman 90730300Sjoergvoid 90825706Sjoergsppp_detach(struct ifnet *ifp) 9094910Swollman{ 9104910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 91125944Sjoerg int i; 9124910Swollman 9134910Swollman /* Remove the entry from the keepalive list. */ 9144910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 9154910Swollman if (p == sp) { 9164910Swollman *q = p->pp_next; 9174910Swollman break; 9184910Swollman } 9194910Swollman 9204910Swollman /* Stop keepalive handler. */ 9214910Swollman if (! spppq) 92240008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 92325944Sjoerg 92425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 92540008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 92640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 92769152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 92869152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 9294910Swollman} 9304910Swollman 9314910Swollman/* 9324910Swollman * Flush the interface output queue. 9334910Swollman */ 93425706Sjoergvoid 93525706Sjoergsppp_flush(struct ifnet *ifp) 9364910Swollman{ 9374910Swollman struct sppp *sp = (struct sppp*) ifp; 9384910Swollman 93925944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 94025944Sjoerg sppp_qflush (&sp->pp_fastq); 94126018Sjoerg sppp_qflush (&sp->pp_cpq); 9424910Swollman} 9434910Swollman 9444910Swollman/* 94511189Sjkh * Check if the output queue is empty. 94611189Sjkh */ 94712820Sphkint 94825706Sjoergsppp_isempty(struct ifnet *ifp) 94911189Sjkh{ 95011189Sjkh struct sppp *sp = (struct sppp*) ifp; 95125944Sjoerg int empty, s; 95211189Sjkh 95325944Sjoerg s = splimp(); 95426018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 95526018Sjoerg !sp->pp_if.if_snd.ifq_head; 95625944Sjoerg splx(s); 95711189Sjkh return (empty); 95811189Sjkh} 95911189Sjkh 96011189Sjkh/* 9614910Swollman * Get next packet to send. 9624910Swollman */ 96325706Sjoergstruct mbuf * 96425706Sjoergsppp_dequeue(struct ifnet *ifp) 9654910Swollman{ 9664910Swollman struct sppp *sp = (struct sppp*) ifp; 9674910Swollman struct mbuf *m; 96825944Sjoerg int s; 9694910Swollman 97025944Sjoerg s = splimp(); 97126018Sjoerg /* 97230300Sjoerg * Process only the control protocol queue until we have at 97330300Sjoerg * least one NCP open. 97426018Sjoerg * 97526018Sjoerg * Do always serve all three queues in Cisco mode. 97626018Sjoerg */ 97726018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 97826018Sjoerg if (m == NULL && 97945152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 98026018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 98126018Sjoerg if (m == NULL) 98226018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 98326018Sjoerg } 98426018Sjoerg splx(s); 98526018Sjoerg return m; 9864910Swollman} 9874910Swollman 9884910Swollman/* 98930300Sjoerg * Pick the next packet, do not remove it from the queue. 99030300Sjoerg */ 99130300Sjoergstruct mbuf * 99230300Sjoergsppp_pick(struct ifnet *ifp) 99330300Sjoerg{ 99430300Sjoerg struct sppp *sp = (struct sppp*)ifp; 99530300Sjoerg struct mbuf *m; 99630300Sjoerg int s; 99730300Sjoerg 99830300Sjoerg s= splimp (); 99930300Sjoerg 100030300Sjoerg m = sp->pp_cpq.ifq_head; 100130300Sjoerg if (m == NULL && 100245152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 100330300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 100430300Sjoerg m = sp->pp_if.if_snd.ifq_head; 100530300Sjoerg splx (s); 100630300Sjoerg return (m); 100730300Sjoerg} 100830300Sjoerg 100930300Sjoerg/* 101025944Sjoerg * Process an ioctl request. Called on low priority level. 10114910Swollman */ 101225944Sjoergint 101342104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 10144910Swollman{ 101525944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 101625944Sjoerg struct sppp *sp = (struct sppp*) ifp; 101730300Sjoerg int s, rv, going_up, going_down, newmode; 10184910Swollman 101925944Sjoerg s = splimp(); 102030300Sjoerg rv = 0; 102125944Sjoerg switch (cmd) { 102225944Sjoerg case SIOCAIFADDR: 102325944Sjoerg case SIOCSIFDSTADDR: 102425944Sjoerg break; 10254910Swollman 102625944Sjoerg case SIOCSIFADDR: 102725944Sjoerg if_up(ifp); 102825944Sjoerg /* fall through... */ 102911189Sjkh 103025944Sjoerg case SIOCSIFFLAGS: 103125944Sjoerg going_up = ifp->if_flags & IFF_UP && 103225944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 103325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 103425944Sjoerg ifp->if_flags & IFF_RUNNING; 103545152Sphk 103645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 103745152Sphk if (!newmode) 103845152Sphk newmode = ifp->if_flags & IFF_AUTO; 103945152Sphk if (!newmode) 104045152Sphk newmode = ifp->if_flags & IFF_CISCO; 104145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 104245152Sphk ifp->if_flags |= newmode; 104345152Sphk 104445152Sphk if (newmode != sp->pp_mode) { 104545152Sphk going_down = 1; 104645152Sphk if (!going_up) 104745152Sphk going_up = ifp->if_flags & IFF_RUNNING; 10484910Swollman } 10494910Swollman 105045152Sphk if (going_down) { 105170199Sjhay if (sp->pp_mode != IFF_CISCO) 105245152Sphk lcp.Close(sp); 105345152Sphk else if (sp->pp_tlf) 105445152Sphk (sp->pp_tlf)(sp); 105526018Sjoerg sppp_flush(ifp); 105625944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 105745152Sphk sp->pp_mode = newmode; 105826018Sjoerg } 10594910Swollman 106045152Sphk if (going_up) { 106170199Sjhay if (sp->pp_mode != IFF_CISCO) 106245152Sphk lcp.Close(sp); 106345152Sphk sp->pp_mode = newmode; 106445152Sphk if (sp->pp_mode == 0) { 106545152Sphk ifp->if_flags |= IFF_RUNNING; 106645152Sphk lcp.Open(sp); 106745152Sphk } 106845152Sphk if (sp->pp_mode == IFF_CISCO) { 106945152Sphk if (sp->pp_tls) 107045152Sphk (sp->pp_tls)(sp); 107145152Sphk ifp->if_flags |= IFF_RUNNING; 107245152Sphk } 107345152Sphk } 107445152Sphk 10754910Swollman break; 107611189Sjkh 107725944Sjoerg#ifdef SIOCSIFMTU 107825944Sjoerg#ifndef ifr_mtu 107925944Sjoerg#define ifr_mtu ifr_metric 108025944Sjoerg#endif 108125944Sjoerg case SIOCSIFMTU: 108225944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 108325944Sjoerg return (EINVAL); 108425944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10854910Swollman break; 108625944Sjoerg#endif 108725944Sjoerg#ifdef SLIOCSETMTU 108825944Sjoerg case SLIOCSETMTU: 108925944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 109025944Sjoerg return (EINVAL); 109125944Sjoerg ifp->if_mtu = *(short*)data; 10924910Swollman break; 109325944Sjoerg#endif 109425944Sjoerg#ifdef SIOCGIFMTU 109525944Sjoerg case SIOCGIFMTU: 109625944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 109711189Sjkh break; 109825944Sjoerg#endif 109925944Sjoerg#ifdef SLIOCGETMTU 110025944Sjoerg case SLIOCGETMTU: 110125944Sjoerg *(short*)data = ifp->if_mtu; 11024910Swollman break; 110325944Sjoerg#endif 110425944Sjoerg case SIOCADDMULTI: 110525944Sjoerg case SIOCDELMULTI: 11064910Swollman break; 110711189Sjkh 110830300Sjoerg case SIOCGIFGENERIC: 110930300Sjoerg case SIOCSIFGENERIC: 111030300Sjoerg rv = sppp_params(sp, cmd, data); 111130300Sjoerg break; 111230300Sjoerg 111325944Sjoerg default: 111430300Sjoerg rv = ENOTTY; 11154910Swollman } 111625944Sjoerg splx(s); 111730300Sjoerg return rv; 11184910Swollman} 11194910Swollman 112070199Sjhay/* 112125944Sjoerg * Cisco framing implementation. 112225944Sjoerg */ 112325944Sjoerg 11244910Swollman/* 11254910Swollman * Handle incoming Cisco keepalive protocol packets. 11264910Swollman */ 112730300Sjoergstatic void 112825706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 11294910Swollman{ 113025944Sjoerg STDDCL; 11314910Swollman struct cisco_packet *h; 113230300Sjoerg u_long me, mymask; 11334910Swollman 113427929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 113525706Sjoerg if (debug) 113625706Sjoerg log(LOG_DEBUG, 113740008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 113840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 11394910Swollman return; 11404910Swollman } 11414910Swollman h = mtod (m, struct cisco_packet*); 114225706Sjoerg if (debug) 114325706Sjoerg log(LOG_DEBUG, 114440008Sjoerg SPP_FMT "cisco input: %d bytes " 114525706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 114740008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 114840008Sjoerg (u_int)h->time0, (u_int)h->time1); 11494910Swollman switch (ntohl (h->type)) { 11504910Swollman default: 115125706Sjoerg if (debug) 115269211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 115340008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 11544910Swollman break; 11554910Swollman case CISCO_ADDR_REPLY: 11564910Swollman /* Reply on address request, ignore */ 11574910Swollman break; 11584910Swollman case CISCO_KEEPALIVE_REQ: 11594910Swollman sp->pp_alivecnt = 0; 116078064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 116178064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 11624910Swollman /* Local and remote sequence numbers are equal. 11634910Swollman * Probably, the line is in loopback mode. */ 116411189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 116540008Sjoerg printf (SPP_FMT "loopback\n", 116640008Sjoerg SPP_ARGS(ifp)); 116711189Sjkh sp->pp_loopcnt = 0; 116811189Sjkh if (ifp->if_flags & IFF_UP) { 116911189Sjkh if_down (ifp); 117026018Sjoerg sppp_qflush (&sp->pp_cpq); 117111189Sjkh } 117211189Sjkh } 11734910Swollman ++sp->pp_loopcnt; 11744910Swollman 11754910Swollman /* Generate new local sequence number */ 117642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 117778064Sume sp->pp_seq[IDX_LCP] = random(); 117840008Sjoerg#else 117978064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 118040008Sjoerg#endif 118111189Sjkh break; 118211189Sjkh } 118330300Sjoerg sp->pp_loopcnt = 0; 118411189Sjkh if (! (ifp->if_flags & IFF_UP) && 118511189Sjkh (ifp->if_flags & IFF_RUNNING)) { 118630300Sjoerg if_up(ifp); 118740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 118811189Sjkh } 11894910Swollman break; 11904910Swollman case CISCO_ADDR_REQ: 119130300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 119230300Sjoerg if (me != 0L) 119330300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11944910Swollman break; 11954910Swollman } 11964910Swollman} 11974910Swollman 11984910Swollman/* 119925944Sjoerg * Send Cisco keepalive packet. 12004910Swollman */ 120112820Sphkstatic void 120225944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 120325944Sjoerg{ 120425944Sjoerg STDDCL; 120525944Sjoerg struct ppp_header *h; 120625944Sjoerg struct cisco_packet *ch; 120725944Sjoerg struct mbuf *m; 120842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 120935029Sphk struct timeval tv; 121040008Sjoerg#else 121140008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 121240008Sjoerg#endif 121325944Sjoerg 121442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121536119Sphk getmicrouptime(&tv); 121640008Sjoerg#endif 121770199Sjhay 121825944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 121925944Sjoerg if (! m) 122025944Sjoerg return; 122125944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 122225944Sjoerg m->m_pkthdr.rcvif = 0; 122325944Sjoerg 122425944Sjoerg h = mtod (m, struct ppp_header*); 122525944Sjoerg h->address = CISCO_MULTICAST; 122625944Sjoerg h->control = 0; 122725944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 122825944Sjoerg 122925944Sjoerg ch = (struct cisco_packet*) (h + 1); 123025944Sjoerg ch->type = htonl (type); 123125944Sjoerg ch->par1 = htonl (par1); 123225944Sjoerg ch->par2 = htonl (par2); 123325944Sjoerg ch->rel = -1; 123440008Sjoerg 123542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 123635029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 123735029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 123840008Sjoerg#else 123940008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 124040008Sjoerg ch->time1 = htons ((u_short) t); 124140008Sjoerg#endif 124225944Sjoerg 124325944Sjoerg if (debug) 124425944Sjoerg log(LOG_DEBUG, 124540008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 124640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 124740008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 124825944Sjoerg 124969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 125069152Sjlemon ifp->if_oerrors++; 125125944Sjoerg} 125225944Sjoerg 125370199Sjhay/* 125425944Sjoerg * PPP protocol implementation. 125525944Sjoerg */ 125625944Sjoerg 125725944Sjoerg/* 125825944Sjoerg * Send PPP control protocol packet. 125925944Sjoerg */ 126025944Sjoergstatic void 126125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 126225706Sjoerg u_char ident, u_short len, void *data) 12634910Swollman{ 126425944Sjoerg STDDCL; 12654910Swollman struct ppp_header *h; 12664910Swollman struct lcp_header *lh; 12674910Swollman struct mbuf *m; 12684910Swollman 12694910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 12704910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 12714910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 12724910Swollman if (! m) 12734910Swollman return; 12744910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 12754910Swollman m->m_pkthdr.rcvif = 0; 12764910Swollman 12774910Swollman h = mtod (m, struct ppp_header*); 12784910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12794910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12804910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12814910Swollman 12824910Swollman lh = (struct lcp_header*) (h + 1); 12834910Swollman lh->type = type; 12844910Swollman lh->ident = ident; 12854910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12864910Swollman if (len) 12874910Swollman bcopy (data, lh+1, len); 12884910Swollman 128925706Sjoerg if (debug) { 129040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 129140008Sjoerg SPP_ARGS(ifp), 129225944Sjoerg sppp_proto_name(proto), 129325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 129425944Sjoerg ntohs (lh->len)); 129544145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 129669211Sphk log(-1, ">\n"); 12974910Swollman } 129869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 129969152Sjlemon ifp->if_oerrors++; 13004910Swollman} 13014910Swollman 13024910Swollman/* 130325944Sjoerg * Handle incoming PPP control protocol packets. 13044910Swollman */ 130512820Sphkstatic void 130625944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13074910Swollman{ 130825944Sjoerg STDDCL; 130925944Sjoerg struct lcp_header *h; 131025944Sjoerg int len = m->m_pkthdr.len; 131125944Sjoerg int rv; 131225944Sjoerg u_char *p; 13134910Swollman 131425944Sjoerg if (len < 4) { 131525944Sjoerg if (debug) 131625944Sjoerg log(LOG_DEBUG, 131740008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 131840008Sjoerg SPP_ARGS(ifp), cp->name, len); 13194910Swollman return; 132025944Sjoerg } 132125944Sjoerg h = mtod (m, struct lcp_header*); 132225944Sjoerg if (debug) { 132325944Sjoerg log(LOG_DEBUG, 132440008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 132540008Sjoerg SPP_ARGS(ifp), cp->name, 132625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 132725944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 132844145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 132969211Sphk log(-1, ">\n"); 133025944Sjoerg } 133125944Sjoerg if (len > ntohs (h->len)) 133225944Sjoerg len = ntohs (h->len); 133330300Sjoerg p = (u_char *)(h + 1); 133425944Sjoerg switch (h->type) { 133525944Sjoerg case CONF_REQ: 133625944Sjoerg if (len < 4) { 133725944Sjoerg if (debug) 133869211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 133940008Sjoerg SPP_ARGS(ifp), cp->name, 134025944Sjoerg len); 134125944Sjoerg ++ifp->if_ierrors; 134225944Sjoerg break; 134325944Sjoerg } 134430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 134530300Sjoerg switch (sp->state[cp->protoidx]) { 134630300Sjoerg case STATE_CLOSING: 134730300Sjoerg case STATE_STOPPING: 134830300Sjoerg return; 134930300Sjoerg case STATE_CLOSED: 135030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 135130300Sjoerg 0, 0); 135230300Sjoerg return; 135330300Sjoerg } 135425944Sjoerg rv = (cp->RCR)(sp, h, len); 135525944Sjoerg switch (sp->state[cp->protoidx]) { 135625944Sjoerg case STATE_OPENED: 135725944Sjoerg (cp->tld)(sp); 135825944Sjoerg (cp->scr)(sp); 135925944Sjoerg /* fall through... */ 136025944Sjoerg case STATE_ACK_SENT: 136125944Sjoerg case STATE_REQ_SENT: 136270199Sjhay /* 136370199Sjhay * sppp_cp_change_state() have the side effect of 136470199Sjhay * restarting the timeouts. We want to avoid that 136570199Sjhay * if the state don't change, otherwise we won't 136670199Sjhay * ever timeout and resend a configuration request 136770199Sjhay * that got lost. 136870199Sjhay */ 136970199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 137070199Sjhay STATE_REQ_SENT)) 137170199Sjhay break; 137225944Sjoerg sppp_cp_change_state(cp, sp, rv? 137325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 137425944Sjoerg break; 137525944Sjoerg case STATE_STOPPED: 137625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 137725944Sjoerg (cp->scr)(sp); 137825944Sjoerg sppp_cp_change_state(cp, sp, rv? 137925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 138025944Sjoerg break; 138125944Sjoerg case STATE_ACK_RCVD: 138225944Sjoerg if (rv) { 138325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 138425944Sjoerg if (debug) 138540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 138640008Sjoerg SPP_ARGS(ifp), 138726077Sjoerg cp->name); 138825944Sjoerg (cp->tlu)(sp); 138925944Sjoerg } else 139025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 139125944Sjoerg break; 139225944Sjoerg default: 139340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139440008Sjoerg SPP_ARGS(ifp), cp->name, 139525944Sjoerg sppp_cp_type_name(h->type), 139625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139725944Sjoerg ++ifp->if_ierrors; 139825944Sjoerg } 139925944Sjoerg break; 140025944Sjoerg case CONF_ACK: 140125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 140225944Sjoerg if (debug) 140369211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 140440008Sjoerg SPP_ARGS(ifp), cp->name, 140525944Sjoerg h->ident, sp->confid[cp->protoidx]); 140625944Sjoerg ++ifp->if_ierrors; 140725944Sjoerg break; 140825944Sjoerg } 140925944Sjoerg switch (sp->state[cp->protoidx]) { 141025944Sjoerg case STATE_CLOSED: 141125944Sjoerg case STATE_STOPPED: 141225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 141325944Sjoerg break; 141425944Sjoerg case STATE_CLOSING: 141525944Sjoerg case STATE_STOPPING: 141625944Sjoerg break; 141725944Sjoerg case STATE_REQ_SENT: 141825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 141925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 142025944Sjoerg break; 142125944Sjoerg case STATE_OPENED: 142225944Sjoerg (cp->tld)(sp); 142325944Sjoerg /* fall through */ 142425944Sjoerg case STATE_ACK_RCVD: 142525944Sjoerg (cp->scr)(sp); 142625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142725944Sjoerg break; 142825944Sjoerg case STATE_ACK_SENT: 142925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 143125944Sjoerg if (debug) 143240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 143340008Sjoerg SPP_ARGS(ifp), cp->name); 143425944Sjoerg (cp->tlu)(sp); 143525944Sjoerg break; 143625944Sjoerg default: 143740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 143840008Sjoerg SPP_ARGS(ifp), cp->name, 143925944Sjoerg sppp_cp_type_name(h->type), 144025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144125944Sjoerg ++ifp->if_ierrors; 144225944Sjoerg } 144325944Sjoerg break; 144425944Sjoerg case CONF_NAK: 144525944Sjoerg case CONF_REJ: 144625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 144725944Sjoerg if (debug) 144869211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 144940008Sjoerg SPP_ARGS(ifp), cp->name, 145025944Sjoerg h->ident, sp->confid[cp->protoidx]); 145125944Sjoerg ++ifp->if_ierrors; 145225944Sjoerg break; 145325944Sjoerg } 145425944Sjoerg if (h->type == CONF_NAK) 145525944Sjoerg (cp->RCN_nak)(sp, h, len); 145625944Sjoerg else /* CONF_REJ */ 145725944Sjoerg (cp->RCN_rej)(sp, h, len); 14584910Swollman 145925944Sjoerg switch (sp->state[cp->protoidx]) { 146025944Sjoerg case STATE_CLOSED: 146125944Sjoerg case STATE_STOPPED: 146225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 146325944Sjoerg break; 146425944Sjoerg case STATE_REQ_SENT: 146525944Sjoerg case STATE_ACK_SENT: 146625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 146770199Sjhay /* 146870199Sjhay * Slow things down a bit if we think we might be 146970199Sjhay * in loopback. Depend on the timeout to send the 147070199Sjhay * next configuration request. 147170199Sjhay */ 147270199Sjhay if (sp->pp_loopcnt) 147370199Sjhay break; 147425944Sjoerg (cp->scr)(sp); 147525944Sjoerg break; 147625944Sjoerg case STATE_OPENED: 147725944Sjoerg (cp->tld)(sp); 147825944Sjoerg /* fall through */ 147925944Sjoerg case STATE_ACK_RCVD: 148052633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148125944Sjoerg (cp->scr)(sp); 148225944Sjoerg break; 148325944Sjoerg case STATE_CLOSING: 148425944Sjoerg case STATE_STOPPING: 148525944Sjoerg break; 148625944Sjoerg default: 148740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 148840008Sjoerg SPP_ARGS(ifp), cp->name, 148925944Sjoerg sppp_cp_type_name(h->type), 149025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149125944Sjoerg ++ifp->if_ierrors; 149225944Sjoerg } 149325944Sjoerg break; 14944910Swollman 149525944Sjoerg case TERM_REQ: 149625944Sjoerg switch (sp->state[cp->protoidx]) { 149725944Sjoerg case STATE_ACK_RCVD: 149825944Sjoerg case STATE_ACK_SENT: 149925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 150025944Sjoerg /* fall through */ 150125944Sjoerg case STATE_CLOSED: 150225944Sjoerg case STATE_STOPPED: 150325944Sjoerg case STATE_CLOSING: 150425944Sjoerg case STATE_STOPPING: 150525944Sjoerg case STATE_REQ_SENT: 150625944Sjoerg sta: 150725944Sjoerg /* Send Terminate-Ack packet. */ 150825944Sjoerg if (debug) 150940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 151040008Sjoerg SPP_ARGS(ifp), cp->name); 151125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 151225944Sjoerg break; 151325944Sjoerg case STATE_OPENED: 151425944Sjoerg (cp->tld)(sp); 151525944Sjoerg sp->rst_counter[cp->protoidx] = 0; 151625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 151725944Sjoerg goto sta; 151825944Sjoerg break; 151925944Sjoerg default: 152040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 152140008Sjoerg SPP_ARGS(ifp), cp->name, 152225944Sjoerg sppp_cp_type_name(h->type), 152325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152425944Sjoerg ++ifp->if_ierrors; 152525944Sjoerg } 152625944Sjoerg break; 152725944Sjoerg case TERM_ACK: 152825944Sjoerg switch (sp->state[cp->protoidx]) { 152925944Sjoerg case STATE_CLOSED: 153025944Sjoerg case STATE_STOPPED: 153125944Sjoerg case STATE_REQ_SENT: 153225944Sjoerg case STATE_ACK_SENT: 153325944Sjoerg break; 153425944Sjoerg case STATE_CLOSING: 153541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 153625944Sjoerg (cp->tlf)(sp); 153725944Sjoerg break; 153825944Sjoerg case STATE_STOPPING: 153941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 154025944Sjoerg (cp->tlf)(sp); 154125944Sjoerg break; 154225944Sjoerg case STATE_ACK_RCVD: 154325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154425944Sjoerg break; 154525944Sjoerg case STATE_OPENED: 154625944Sjoerg (cp->tld)(sp); 154725944Sjoerg (cp->scr)(sp); 154825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 154925944Sjoerg break; 155025944Sjoerg default: 155140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 155240008Sjoerg SPP_ARGS(ifp), cp->name, 155325944Sjoerg sppp_cp_type_name(h->type), 155425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155525944Sjoerg ++ifp->if_ierrors; 155625944Sjoerg } 155725944Sjoerg break; 155825944Sjoerg case CODE_REJ: 155925944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 156030300Sjoerg log(LOG_INFO, 156140008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 156230300Sjoerg "danger will robinson\n", 156340008Sjoerg SPP_ARGS(ifp), cp->name, 156430300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 156525944Sjoerg switch (sp->state[cp->protoidx]) { 156625944Sjoerg case STATE_CLOSED: 156725944Sjoerg case STATE_STOPPED: 156825944Sjoerg case STATE_REQ_SENT: 156925944Sjoerg case STATE_ACK_SENT: 157025944Sjoerg case STATE_CLOSING: 157125944Sjoerg case STATE_STOPPING: 157225944Sjoerg case STATE_OPENED: 157325944Sjoerg break; 157425944Sjoerg case STATE_ACK_RCVD: 157525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 157625944Sjoerg break; 157725944Sjoerg default: 157840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 157940008Sjoerg SPP_ARGS(ifp), cp->name, 158025944Sjoerg sppp_cp_type_name(h->type), 158125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158225944Sjoerg ++ifp->if_ierrors; 158325944Sjoerg } 158425944Sjoerg break; 158580715Sume case PROTO_REJ: 158680715Sume { 158780715Sume int catastrophic; 158880715Sume const struct cp *upper; 158980715Sume int i; 159080715Sume u_int16_t proto; 159180715Sume 159280715Sume catastrophic = 0; 159380715Sume upper = NULL; 159480715Sume proto = ntohs(*((u_int16_t *)p)); 159580715Sume for (i = 0; i < IDX_COUNT; i++) { 159680715Sume if (cps[i]->proto == proto) { 159780715Sume upper = cps[i]; 159880715Sume break; 159980715Sume } 160080715Sume } 160180715Sume if (upper == NULL) 160280715Sume catastrophic++; 160380715Sume 160480715Sume log(LOG_INFO, 160580715Sume SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 160680715Sume SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 160780715Sume sppp_cp_type_name(h->type), proto, 160880715Sume upper ? upper->name : "unknown", 160980715Sume upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 161080715Sume 161180715Sume /* 161280715Sume * if we got RXJ+ against conf-req, the peer does not implement 161380715Sume * this particular protocol type. terminate the protocol. 161480715Sume */ 161580715Sume if (upper && !catastrophic) { 161680715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 161780715Sume upper->Close(sp); 161880715Sume break; 161980715Sume } 162080715Sume } 162180715Sume 162280715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 162380715Sume switch (sp->state[cp->protoidx]) { 162480715Sume case STATE_CLOSED: 162580715Sume case STATE_STOPPED: 162680715Sume case STATE_REQ_SENT: 162780715Sume case STATE_ACK_SENT: 162880715Sume case STATE_CLOSING: 162980715Sume case STATE_STOPPING: 163080715Sume case STATE_OPENED: 163180715Sume break; 163280715Sume case STATE_ACK_RCVD: 163380715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 163480715Sume break; 163580715Sume default: 163680715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 163780715Sume SPP_ARGS(ifp), cp->name, 163880715Sume sppp_cp_type_name(h->type), 163980715Sume sppp_state_name(sp->state[cp->protoidx])); 164080715Sume ++ifp->if_ierrors; 164180715Sume } 164280715Sume break; 164380715Sume } 164425944Sjoerg case DISC_REQ: 164525944Sjoerg if (cp->proto != PPP_LCP) 164625944Sjoerg goto illegal; 164725944Sjoerg /* Discard the packet. */ 164825944Sjoerg break; 164925944Sjoerg case ECHO_REQ: 165025944Sjoerg if (cp->proto != PPP_LCP) 165125944Sjoerg goto illegal; 165225944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 165325944Sjoerg if (debug) 165469211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 165540008Sjoerg SPP_ARGS(ifp)); 165625944Sjoerg ++ifp->if_ierrors; 165725944Sjoerg break; 165825944Sjoerg } 165925944Sjoerg if (len < 8) { 166025944Sjoerg if (debug) 166169211Sphk log(-1, SPP_FMT "invalid lcp echo request " 166225944Sjoerg "packet length: %d bytes\n", 166340008Sjoerg SPP_ARGS(ifp), len); 166425944Sjoerg break; 166525944Sjoerg } 166644145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 166744145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 166825944Sjoerg /* Line loopback mode detected. */ 166940008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 167070199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 167125944Sjoerg if_down (ifp); 167226018Sjoerg sppp_qflush (&sp->pp_cpq); 16734910Swollman 167425944Sjoerg /* Shut down the PPP link. */ 167525944Sjoerg /* XXX */ 167625944Sjoerg lcp.Down(sp); 167725944Sjoerg lcp.Up(sp); 167825944Sjoerg break; 167925944Sjoerg } 168025944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 168125944Sjoerg if (debug) 168269211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 168340008Sjoerg SPP_ARGS(ifp)); 168425944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 168525944Sjoerg break; 168625944Sjoerg case ECHO_REPLY: 168725944Sjoerg if (cp->proto != PPP_LCP) 168825944Sjoerg goto illegal; 168925944Sjoerg if (h->ident != sp->lcp.echoid) { 169025944Sjoerg ++ifp->if_ierrors; 169125944Sjoerg break; 169225944Sjoerg } 169325944Sjoerg if (len < 8) { 169425944Sjoerg if (debug) 169569211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 169625944Sjoerg "packet length: %d bytes\n", 169740008Sjoerg SPP_ARGS(ifp), len); 169825944Sjoerg break; 169925944Sjoerg } 170025944Sjoerg if (debug) 170169211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 170240008Sjoerg SPP_ARGS(ifp)); 170344145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 170444145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 170525944Sjoerg sp->pp_alivecnt = 0; 170625944Sjoerg break; 170725944Sjoerg default: 170825944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 170925944Sjoerg illegal: 171025944Sjoerg if (debug) 171169211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 171240008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 171378064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 171478064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 171525944Sjoerg ++ifp->if_ierrors; 171625944Sjoerg } 17174910Swollman} 17184910Swollman 171925944Sjoerg 17204910Swollman/* 172125944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 172225944Sjoerg * Basically, the state transition handling in the automaton. 17234910Swollman */ 172425944Sjoergstatic void 172525944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 17264910Swollman{ 172725944Sjoerg STDDCL; 17284910Swollman 172925944Sjoerg if (debug) 173040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 173140008Sjoerg SPP_ARGS(ifp), cp->name, 173225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 173325944Sjoerg 173425944Sjoerg switch (sp->state[cp->protoidx]) { 173525944Sjoerg case STATE_INITIAL: 173625944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 173725944Sjoerg break; 173825944Sjoerg case STATE_STARTING: 173925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 174025944Sjoerg (cp->scr)(sp); 174125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174225944Sjoerg break; 17434910Swollman default: 174440008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 174540008Sjoerg SPP_ARGS(ifp), cp->name, 174625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 174725944Sjoerg } 174825944Sjoerg} 17494910Swollman 175025944Sjoergstatic void 175125944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 175225944Sjoerg{ 175325944Sjoerg STDDCL; 175425944Sjoerg 175525944Sjoerg if (debug) 175640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 175740008Sjoerg SPP_ARGS(ifp), cp->name, 175825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 175925944Sjoerg 176025944Sjoerg switch (sp->state[cp->protoidx]) { 176125944Sjoerg case STATE_CLOSED: 176225944Sjoerg case STATE_CLOSING: 176325944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 17644910Swollman break; 176525944Sjoerg case STATE_STOPPED: 176641881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 176725944Sjoerg (cp->tls)(sp); 176841881Sphk break; 176925944Sjoerg case STATE_STOPPING: 177025944Sjoerg case STATE_REQ_SENT: 177125944Sjoerg case STATE_ACK_RCVD: 177225944Sjoerg case STATE_ACK_SENT: 177325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 177425944Sjoerg break; 177525944Sjoerg case STATE_OPENED: 177625944Sjoerg (cp->tld)(sp); 177725944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 177825944Sjoerg break; 177925944Sjoerg default: 178040008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 178140008Sjoerg SPP_ARGS(ifp), cp->name, 178225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 178325944Sjoerg } 178425944Sjoerg} 17854910Swollman 178611189Sjkh 178725944Sjoergstatic void 178825944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 178925944Sjoerg{ 179025944Sjoerg STDDCL; 179125944Sjoerg 179225944Sjoerg if (debug) 179340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 179440008Sjoerg SPP_ARGS(ifp), cp->name, 179525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 179625944Sjoerg 179725944Sjoerg switch (sp->state[cp->protoidx]) { 179825944Sjoerg case STATE_INITIAL: 179941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 180025944Sjoerg (cp->tls)(sp); 18014910Swollman break; 180225944Sjoerg case STATE_STARTING: 180325944Sjoerg break; 180425944Sjoerg case STATE_CLOSED: 180525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 180625944Sjoerg (cp->scr)(sp); 180725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 180825944Sjoerg break; 180925944Sjoerg case STATE_STOPPED: 181074703Sjoerg /* 181174703Sjoerg * Try escaping stopped state. This seems to bite 181274703Sjoerg * people occasionally, in particular for IPCP, 181374703Sjoerg * presumably following previous IPCP negotiation 181474703Sjoerg * aborts. Somehow, we must have missed a Down event 181574703Sjoerg * which would have caused a transition into starting 181674703Sjoerg * state, so as a bandaid we force the Down event now. 181774703Sjoerg * This effectively implements (something like the) 181874703Sjoerg * `restart' option mentioned in the state transition 181974703Sjoerg * table of RFC 1661. 182074703Sjoerg */ 182174703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 182274703Sjoerg (cp->tls)(sp); 182374703Sjoerg break; 182425944Sjoerg case STATE_STOPPING: 182525944Sjoerg case STATE_REQ_SENT: 182625944Sjoerg case STATE_ACK_RCVD: 182725944Sjoerg case STATE_ACK_SENT: 182825944Sjoerg case STATE_OPENED: 182925944Sjoerg break; 183025944Sjoerg case STATE_CLOSING: 183125944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 183225944Sjoerg break; 183325944Sjoerg } 183425944Sjoerg} 18354910Swollman 183625944Sjoerg 183725944Sjoergstatic void 183825944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 183925944Sjoerg{ 184025944Sjoerg STDDCL; 184125944Sjoerg 184225944Sjoerg if (debug) 184340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 184440008Sjoerg SPP_ARGS(ifp), cp->name, 184525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 184625944Sjoerg 184725944Sjoerg switch (sp->state[cp->protoidx]) { 184825944Sjoerg case STATE_INITIAL: 184925944Sjoerg case STATE_CLOSED: 185025944Sjoerg case STATE_CLOSING: 18514910Swollman break; 185225944Sjoerg case STATE_STARTING: 185341881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 185425944Sjoerg (cp->tlf)(sp); 18554910Swollman break; 185625944Sjoerg case STATE_STOPPED: 185725944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 18584910Swollman break; 185925944Sjoerg case STATE_STOPPING: 186025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18614910Swollman break; 186225944Sjoerg case STATE_OPENED: 186325944Sjoerg (cp->tld)(sp); 186425944Sjoerg /* fall through */ 186525944Sjoerg case STATE_REQ_SENT: 186625944Sjoerg case STATE_ACK_RCVD: 186725944Sjoerg case STATE_ACK_SENT: 186825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 186978064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 187078064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 187125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18724910Swollman break; 18734910Swollman } 18744910Swollman} 18754910Swollman 187625944Sjoergstatic void 187725944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 187825944Sjoerg{ 187925944Sjoerg STDDCL; 188025944Sjoerg int s; 188125944Sjoerg 188225944Sjoerg s = splimp(); 188325944Sjoerg if (debug) 188440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 188540008Sjoerg SPP_ARGS(ifp), cp->name, 188625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 188725944Sjoerg sp->rst_counter[cp->protoidx]); 188825944Sjoerg 188925944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 189025944Sjoerg /* TO- event */ 189125944Sjoerg switch (sp->state[cp->protoidx]) { 189225944Sjoerg case STATE_CLOSING: 189341881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 189425944Sjoerg (cp->tlf)(sp); 189525944Sjoerg break; 189625944Sjoerg case STATE_STOPPING: 189741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 189825944Sjoerg (cp->tlf)(sp); 189925944Sjoerg break; 190025944Sjoerg case STATE_REQ_SENT: 190125944Sjoerg case STATE_ACK_RCVD: 190225944Sjoerg case STATE_ACK_SENT: 190341881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 190425944Sjoerg (cp->tlf)(sp); 190525944Sjoerg break; 190625944Sjoerg } 190725944Sjoerg else 190825944Sjoerg /* TO+ event */ 190925944Sjoerg switch (sp->state[cp->protoidx]) { 191025944Sjoerg case STATE_CLOSING: 191125944Sjoerg case STATE_STOPPING: 191278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 191378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 191470199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 191542064Sphk sp->ch[cp->protoidx]); 191625944Sjoerg break; 191725944Sjoerg case STATE_REQ_SENT: 191825944Sjoerg case STATE_ACK_RCVD: 191925944Sjoerg (cp->scr)(sp); 192025944Sjoerg /* sppp_cp_change_state() will restart the timer */ 192125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 192225944Sjoerg break; 192325944Sjoerg case STATE_ACK_SENT: 192425944Sjoerg (cp->scr)(sp); 192542064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 192642064Sphk sp->ch[cp->protoidx]); 192725944Sjoerg break; 192825944Sjoerg } 192925944Sjoerg 193025944Sjoerg splx(s); 193125944Sjoerg} 193225944Sjoerg 193311189Sjkh/* 193425944Sjoerg * Change the state of a control protocol in the state automaton. 193525944Sjoerg * Takes care of starting/stopping the restart timer. 193611189Sjkh */ 193725944Sjoergvoid 193825944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 193925944Sjoerg{ 194025944Sjoerg sp->state[cp->protoidx] = newstate; 194125944Sjoerg 194240008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 194325944Sjoerg switch (newstate) { 194425944Sjoerg case STATE_INITIAL: 194525944Sjoerg case STATE_STARTING: 194625944Sjoerg case STATE_CLOSED: 194725944Sjoerg case STATE_STOPPED: 194825944Sjoerg case STATE_OPENED: 194925944Sjoerg break; 195025944Sjoerg case STATE_CLOSING: 195125944Sjoerg case STATE_STOPPING: 195225944Sjoerg case STATE_REQ_SENT: 195325944Sjoerg case STATE_ACK_RCVD: 195425944Sjoerg case STATE_ACK_SENT: 195570199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 195642064Sphk sp->ch[cp->protoidx]); 195725944Sjoerg break; 195825944Sjoerg } 195925944Sjoerg} 196070199Sjhay 196170199Sjhay/* 196225944Sjoerg *--------------------------------------------------------------------------* 196325944Sjoerg * * 196425944Sjoerg * The LCP implementation. * 196525944Sjoerg * * 196625944Sjoerg *--------------------------------------------------------------------------* 196725944Sjoerg */ 196825944Sjoergstatic void 196925944Sjoergsppp_lcp_init(struct sppp *sp) 197025944Sjoerg{ 197125944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 197225944Sjoerg sp->lcp.magic = 0; 197325944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 197425944Sjoerg sp->fail_counter[IDX_LCP] = 0; 197578064Sume sp->pp_seq[IDX_LCP] = 0; 197678064Sume sp->pp_rseq[IDX_LCP] = 0; 197725944Sjoerg sp->lcp.protos = 0; 197825944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 197930300Sjoerg 198044145Sphk /* Note that these values are relevant for all control protocols */ 198144145Sphk sp->lcp.timeout = 3 * hz; 198225944Sjoerg sp->lcp.max_terminate = 2; 198325944Sjoerg sp->lcp.max_configure = 10; 198425944Sjoerg sp->lcp.max_failure = 10; 198542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 198630300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 198740008Sjoerg#endif 198825944Sjoerg} 198925944Sjoerg 199025944Sjoergstatic void 199125944Sjoergsppp_lcp_up(struct sppp *sp) 199225944Sjoerg{ 199325944Sjoerg STDDCL; 199425944Sjoerg 199570199Sjhay sp->pp_alivecnt = 0; 199670199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 199770199Sjhay sp->lcp.magic = 0; 199870199Sjhay sp->lcp.protos = 0; 199970199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 200025944Sjoerg /* 200175321Sjoerg * If we are authenticator, negotiate LCP_AUTH 200275321Sjoerg */ 200375321Sjoerg if (sp->hisauth.proto != 0) 200475321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 200575321Sjoerg else 200675321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 200775321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 200875321Sjoerg /* 200930300Sjoerg * If this interface is passive or dial-on-demand, and we are 201030300Sjoerg * still in Initial state, it means we've got an incoming 201130300Sjoerg * call. Activate the interface. 201225944Sjoerg */ 201325944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 201425944Sjoerg if (debug) 201525944Sjoerg log(LOG_DEBUG, 201640008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 201725944Sjoerg ifp->if_flags |= IFF_RUNNING; 201830300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 201930300Sjoerg if (debug) 202069211Sphk log(-1, "(incoming call)\n"); 202130300Sjoerg sp->pp_flags |= PP_CALLIN; 202230300Sjoerg lcp.Open(sp); 202330300Sjoerg } else if (debug) 202469211Sphk log(-1, "\n"); 202525944Sjoerg } 202625944Sjoerg 202725944Sjoerg sppp_up_event(&lcp, sp); 202825944Sjoerg} 202925944Sjoerg 203025944Sjoergstatic void 203125944Sjoergsppp_lcp_down(struct sppp *sp) 203225944Sjoerg{ 203325944Sjoerg STDDCL; 203425944Sjoerg 203525944Sjoerg sppp_down_event(&lcp, sp); 203625944Sjoerg 203725944Sjoerg /* 203825944Sjoerg * If this is neither a dial-on-demand nor a passive 203925944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 204025944Sjoerg * administrator can force a redial by another ``ifconfig 204125944Sjoerg * up''. XXX For leased line operation, should we immediately 204225944Sjoerg * try to reopen the connection here? 204325944Sjoerg */ 204425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 204525944Sjoerg log(LOG_INFO, 204642066Sphk SPP_FMT "Down event, taking interface down.\n", 204740008Sjoerg SPP_ARGS(ifp)); 204825944Sjoerg if_down(ifp); 204925944Sjoerg } else { 205025944Sjoerg if (debug) 205125944Sjoerg log(LOG_DEBUG, 205240008Sjoerg SPP_FMT "Down event (carrier loss)\n", 205340008Sjoerg SPP_ARGS(ifp)); 205470199Sjhay sp->pp_flags &= ~PP_CALLIN; 205570199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 205670199Sjhay lcp.Close(sp); 205770199Sjhay ifp->if_flags &= ~IFF_RUNNING; 205825944Sjoerg } 205925944Sjoerg} 206025944Sjoerg 206125944Sjoergstatic void 206225944Sjoergsppp_lcp_open(struct sppp *sp) 206325944Sjoerg{ 206425944Sjoerg sppp_open_event(&lcp, sp); 206525944Sjoerg} 206625944Sjoerg 206725944Sjoergstatic void 206825944Sjoergsppp_lcp_close(struct sppp *sp) 206925944Sjoerg{ 207025944Sjoerg sppp_close_event(&lcp, sp); 207125944Sjoerg} 207225944Sjoerg 207325944Sjoergstatic void 207425944Sjoergsppp_lcp_TO(void *cookie) 207525944Sjoerg{ 207625944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 207725944Sjoerg} 207825944Sjoerg 207925944Sjoerg/* 208025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 208125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 208225944Sjoerg * caused action scn. (The return value is used to make the state 208325944Sjoerg * transition decision in the state automaton.) 208425944Sjoerg */ 208512820Sphkstatic int 208625944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 20874910Swollman{ 208825944Sjoerg STDDCL; 208911189Sjkh u_char *buf, *r, *p; 209025944Sjoerg int origlen, rlen; 209125944Sjoerg u_long nmagic; 209230300Sjoerg u_short authproto; 20934910Swollman 209411189Sjkh len -= 4; 209525944Sjoerg origlen = len; 209611189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 209711189Sjkh if (! buf) 209811189Sjkh return (0); 20994910Swollman 210025706Sjoerg if (debug) 210140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 210240008Sjoerg SPP_ARGS(ifp)); 210325706Sjoerg 210425944Sjoerg /* pass 1: check for things that need to be rejected */ 210511189Sjkh p = (void*) (h+1); 210611189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 210725944Sjoerg if (debug) 210869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 210911189Sjkh switch (*p) { 211011189Sjkh case LCP_OPT_MAGIC: 211125944Sjoerg /* Magic number. */ 211270199Sjhay if (len >= 6 && p[1] == 6) 211370199Sjhay continue; 211470199Sjhay if (debug) 211570199Sjhay log(-1, "[invalid] "); 211670199Sjhay break; 211725944Sjoerg case LCP_OPT_ASYNC_MAP: 211825944Sjoerg /* Async control character map. */ 211970199Sjhay if (len >= 6 && p[1] == 6) 212025944Sjoerg continue; 212125944Sjoerg if (debug) 212269211Sphk log(-1, "[invalid] "); 212325944Sjoerg break; 212425944Sjoerg case LCP_OPT_MRU: 212525944Sjoerg /* Maximum receive unit. */ 212625944Sjoerg if (len >= 4 && p[1] == 4) 212725944Sjoerg continue; 212825944Sjoerg if (debug) 212969211Sphk log(-1, "[invalid] "); 213025944Sjoerg break; 213130300Sjoerg case LCP_OPT_AUTH_PROTO: 213230300Sjoerg if (len < 4) { 213330300Sjoerg if (debug) 213469211Sphk log(-1, "[invalid] "); 213530300Sjoerg break; 213630300Sjoerg } 213730300Sjoerg authproto = (p[2] << 8) + p[3]; 213830300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 213930300Sjoerg if (debug) 214069211Sphk log(-1, "[invalid chap len] "); 214130300Sjoerg break; 214230300Sjoerg } 214330300Sjoerg if (sp->myauth.proto == 0) { 214430300Sjoerg /* we are not configured to do auth */ 214530300Sjoerg if (debug) 214669211Sphk log(-1, "[not configured] "); 214730300Sjoerg break; 214830300Sjoerg } 214930300Sjoerg /* 215030300Sjoerg * Remote want us to authenticate, remember this, 215130300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 215230300Sjoerg * up. 215330300Sjoerg */ 215430300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 215530300Sjoerg continue; 215625944Sjoerg default: 215725944Sjoerg /* Others not supported. */ 215825944Sjoerg if (debug) 215969211Sphk log(-1, "[rej] "); 216025944Sjoerg break; 216125944Sjoerg } 216225944Sjoerg /* Add the option to rejected list. */ 216325944Sjoerg bcopy (p, r, p[1]); 216425944Sjoerg r += p[1]; 216525944Sjoerg rlen += p[1]; 216625944Sjoerg } 216725944Sjoerg if (rlen) { 216825944Sjoerg if (debug) 216969211Sphk log(-1, " send conf-rej\n"); 217025944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 217125944Sjoerg return 0; 217225944Sjoerg } else if (debug) 217369211Sphk log(-1, "\n"); 217425944Sjoerg 217525944Sjoerg /* 217625944Sjoerg * pass 2: check for option values that are unacceptable and 217725944Sjoerg * thus require to be nak'ed. 217825944Sjoerg */ 217925944Sjoerg if (debug) 218040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 218140008Sjoerg SPP_ARGS(ifp)); 218225944Sjoerg 218325944Sjoerg p = (void*) (h+1); 218425944Sjoerg len = origlen; 218525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 218625944Sjoerg if (debug) 218769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 218825944Sjoerg switch (*p) { 218925944Sjoerg case LCP_OPT_MAGIC: 219011189Sjkh /* Magic number -- extract. */ 219125944Sjoerg nmagic = (u_long)p[2] << 24 | 219225944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 219325944Sjoerg if (nmagic != sp->lcp.magic) { 219470199Sjhay sp->pp_loopcnt = 0; 219525706Sjoerg if (debug) 219669211Sphk log(-1, "0x%lx ", nmagic); 219711189Sjkh continue; 219811189Sjkh } 219970199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 220069211Sphk log(-1, "[glitch] "); 220125944Sjoerg ++sp->pp_loopcnt; 220225944Sjoerg /* 220325944Sjoerg * We negate our magic here, and NAK it. If 220425944Sjoerg * we see it later in an NAK packet, we 220525944Sjoerg * suggest a new one. 220625944Sjoerg */ 220725944Sjoerg nmagic = ~sp->lcp.magic; 220825944Sjoerg /* Gonna NAK it. */ 220925944Sjoerg p[2] = nmagic >> 24; 221025944Sjoerg p[3] = nmagic >> 16; 221125944Sjoerg p[4] = nmagic >> 8; 221225944Sjoerg p[5] = nmagic; 221311189Sjkh break; 221425944Sjoerg 221511189Sjkh case LCP_OPT_ASYNC_MAP: 221611189Sjkh /* Async control character map -- check to be zero. */ 221725944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 221825706Sjoerg if (debug) 221969211Sphk log(-1, "[empty] "); 222011189Sjkh continue; 222125706Sjoerg } 222225706Sjoerg if (debug) 222369211Sphk log(-1, "[non-empty] "); 222425944Sjoerg /* suggest a zero one */ 222525944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 222611189Sjkh break; 222725944Sjoerg 222811189Sjkh case LCP_OPT_MRU: 222925944Sjoerg /* 223025944Sjoerg * Maximum receive unit. Always agreeable, 223125944Sjoerg * but ignored by now. 223225944Sjoerg */ 223325944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 223425706Sjoerg if (debug) 223569211Sphk log(-1, "%lu ", sp->lcp.their_mru); 223611189Sjkh continue; 223730300Sjoerg 223830300Sjoerg case LCP_OPT_AUTH_PROTO: 223930300Sjoerg authproto = (p[2] << 8) + p[3]; 224030300Sjoerg if (sp->myauth.proto != authproto) { 224130300Sjoerg /* not agreed, nak */ 224230300Sjoerg if (debug) 224369211Sphk log(-1, "[mine %s != his %s] ", 224430300Sjoerg sppp_proto_name(sp->hisauth.proto), 224530300Sjoerg sppp_proto_name(authproto)); 224630300Sjoerg p[2] = sp->myauth.proto >> 8; 224730300Sjoerg p[3] = sp->myauth.proto; 224830300Sjoerg break; 224930300Sjoerg } 225030300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 225130300Sjoerg if (debug) 225269211Sphk log(-1, "[chap not MD5] "); 225339981Sjoerg p[4] = CHAP_MD5; 225430300Sjoerg break; 225530300Sjoerg } 225630300Sjoerg continue; 225711189Sjkh } 225825944Sjoerg /* Add the option to nak'ed list. */ 225925706Sjoerg bcopy (p, r, p[1]); 226025706Sjoerg r += p[1]; 226111189Sjkh rlen += p[1]; 226212436Speter } 226325706Sjoerg if (rlen) { 226470199Sjhay /* 226570199Sjhay * Local and remote magics equal -- loopback? 226670199Sjhay */ 226770199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 226870199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 226970199Sjhay printf (SPP_FMT "loopback\n", 227070199Sjhay SPP_ARGS(ifp)); 227170199Sjhay if (ifp->if_flags & IFF_UP) { 227270199Sjhay if_down(ifp); 227370199Sjhay sppp_qflush(&sp->pp_cpq); 227470199Sjhay /* XXX ? */ 227570199Sjhay lcp.Down(sp); 227670199Sjhay lcp.Up(sp); 227770199Sjhay } 227870199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 227928036Sjoerg if (debug) 228069211Sphk log(-1, " max_failure (%d) exceeded, " 228128036Sjoerg "send conf-rej\n", 228228036Sjoerg sp->lcp.max_failure); 228328036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 228428036Sjoerg } else { 228528036Sjoerg if (debug) 228669211Sphk log(-1, " send conf-nak\n"); 228728036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 228828036Sjoerg } 228925944Sjoerg } else { 229025944Sjoerg if (debug) 229169211Sphk log(-1, " send conf-ack\n"); 229228036Sjoerg sp->fail_counter[IDX_LCP] = 0; 229325944Sjoerg sp->pp_loopcnt = 0; 229425944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 229525944Sjoerg h->ident, origlen, h+1); 229625944Sjoerg } 229725944Sjoerg 229811189Sjkh free (buf, M_TEMP); 229911189Sjkh return (rlen == 0); 23004910Swollman} 23014910Swollman 230225944Sjoerg/* 230325944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 230425944Sjoerg * negotiation. 230525944Sjoerg */ 230612820Sphkstatic void 230725944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 23084910Swollman{ 230925944Sjoerg STDDCL; 231025944Sjoerg u_char *buf, *p; 23114910Swollman 231225944Sjoerg len -= 4; 231325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 231425944Sjoerg if (!buf) 23154910Swollman return; 231625944Sjoerg 231725944Sjoerg if (debug) 231840008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 231940008Sjoerg SPP_ARGS(ifp)); 232025944Sjoerg 232125944Sjoerg p = (void*) (h+1); 232225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 232325944Sjoerg if (debug) 232469211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 232525944Sjoerg switch (*p) { 232625944Sjoerg case LCP_OPT_MAGIC: 232725944Sjoerg /* Magic number -- can't use it, use 0 */ 232825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 232925944Sjoerg sp->lcp.magic = 0; 233025944Sjoerg break; 233125944Sjoerg case LCP_OPT_MRU: 233225944Sjoerg /* 233325944Sjoerg * Should not be rejected anyway, since we only 233425944Sjoerg * negotiate a MRU if explicitly requested by 233525944Sjoerg * peer. 233625944Sjoerg */ 233725944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 233825944Sjoerg break; 233930300Sjoerg case LCP_OPT_AUTH_PROTO: 234030300Sjoerg /* 234130300Sjoerg * Peer doesn't want to authenticate himself, 234230300Sjoerg * deny unless this is a dialout call, and 234330300Sjoerg * AUTHFLAG_NOCALLOUT is set. 234430300Sjoerg */ 234530300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 234630300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 234730300Sjoerg if (debug) 234869211Sphk log(-1, "[don't insist on auth " 234930300Sjoerg "for callout]"); 235030300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 235130300Sjoerg break; 235230300Sjoerg } 235330300Sjoerg if (debug) 235469211Sphk log(-1, "[access denied]\n"); 235530300Sjoerg lcp.Close(sp); 235630300Sjoerg break; 235725944Sjoerg } 23584910Swollman } 235925944Sjoerg if (debug) 236069211Sphk log(-1, "\n"); 236125944Sjoerg free (buf, M_TEMP); 236225944Sjoerg return; 236325944Sjoerg} 236425944Sjoerg 236525944Sjoerg/* 236625944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 236725944Sjoerg * negotiation. 236825944Sjoerg */ 236925944Sjoergstatic void 237025944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 237125944Sjoerg{ 237225944Sjoerg STDDCL; 237325944Sjoerg u_char *buf, *p; 237425944Sjoerg u_long magic; 237525944Sjoerg 237625944Sjoerg len -= 4; 237725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 237825944Sjoerg if (!buf) 237925944Sjoerg return; 238025944Sjoerg 238125944Sjoerg if (debug) 238240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 238340008Sjoerg SPP_ARGS(ifp)); 238425944Sjoerg 238525944Sjoerg p = (void*) (h+1); 238625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 238725706Sjoerg if (debug) 238869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 238925944Sjoerg switch (*p) { 239025944Sjoerg case LCP_OPT_MAGIC: 239125944Sjoerg /* Magic number -- renegotiate */ 239225944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 239325944Sjoerg len >= 6 && p[1] == 6) { 239425944Sjoerg magic = (u_long)p[2] << 24 | 239525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 239625944Sjoerg /* 239725944Sjoerg * If the remote magic is our negated one, 239825944Sjoerg * this looks like a loopback problem. 239925944Sjoerg * Suggest a new magic to make sure. 240025944Sjoerg */ 240125944Sjoerg if (magic == ~sp->lcp.magic) { 240225944Sjoerg if (debug) 240369211Sphk log(-1, "magic glitch "); 240442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 240535064Sphk sp->lcp.magic = random(); 240640008Sjoerg#else 240740008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 240840008Sjoerg#endif 240925944Sjoerg } else { 241025944Sjoerg sp->lcp.magic = magic; 241125944Sjoerg if (debug) 241269211Sphk log(-1, "%lu ", magic); 241325944Sjoerg } 241425944Sjoerg } 241525944Sjoerg break; 241625944Sjoerg case LCP_OPT_MRU: 241725944Sjoerg /* 241825944Sjoerg * Peer wants to advise us to negotiate an MRU. 241925944Sjoerg * Agree on it if it's reasonable, or use 242025944Sjoerg * default otherwise. 242125944Sjoerg */ 242225944Sjoerg if (len >= 4 && p[1] == 4) { 242325944Sjoerg u_int mru = p[2] * 256 + p[3]; 242425944Sjoerg if (debug) 242569211Sphk log(-1, "%d ", mru); 242625944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 242725944Sjoerg mru = PP_MTU; 242825944Sjoerg sp->lcp.mru = mru; 242925944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 243025944Sjoerg } 243125944Sjoerg break; 243230300Sjoerg case LCP_OPT_AUTH_PROTO: 243330300Sjoerg /* 243430300Sjoerg * Peer doesn't like our authentication method, 243530300Sjoerg * deny. 243630300Sjoerg */ 243730300Sjoerg if (debug) 243869211Sphk log(-1, "[access denied]\n"); 243930300Sjoerg lcp.Close(sp); 244030300Sjoerg break; 24414910Swollman } 244225944Sjoerg } 244325944Sjoerg if (debug) 244469211Sphk log(-1, "\n"); 244525944Sjoerg free (buf, M_TEMP); 244625944Sjoerg return; 244725944Sjoerg} 244811189Sjkh 244925944Sjoergstatic void 245025944Sjoergsppp_lcp_tlu(struct sppp *sp) 245125944Sjoerg{ 245242066Sphk STDDCL; 245325944Sjoerg int i; 245425944Sjoerg u_long mask; 245525944Sjoerg 245625944Sjoerg /* XXX ? */ 245725944Sjoerg if (! (ifp->if_flags & IFF_UP) && 245825944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 245925944Sjoerg /* Coming out of loopback mode. */ 246025944Sjoerg if_up(ifp); 246140008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 246225944Sjoerg } 246325944Sjoerg 246425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 246525944Sjoerg if ((cps[i])->flags & CP_QUAL) 246625944Sjoerg (cps[i])->Open(sp); 246725944Sjoerg 246830300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 246930300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 247025944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 247125944Sjoerg else 247225944Sjoerg sp->pp_phase = PHASE_NETWORK; 247325944Sjoerg 247442066Sphk if (debug) 247542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 247642066Sphk sppp_phase_name(sp->pp_phase)); 247725944Sjoerg 247830300Sjoerg /* 247930300Sjoerg * Open all authentication protocols. This is even required 248030300Sjoerg * if we already proceeded to network phase, since it might be 248130300Sjoerg * that remote wants us to authenticate, so we might have to 248230300Sjoerg * send a PAP request. Undesired authentication protocols 248330300Sjoerg * don't do anything when they get an Open event. 248430300Sjoerg */ 248530300Sjoerg for (i = 0; i < IDX_COUNT; i++) 248630300Sjoerg if ((cps[i])->flags & CP_AUTH) 248730300Sjoerg (cps[i])->Open(sp); 248830300Sjoerg 248930300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 249025944Sjoerg /* Notify all NCPs. */ 249125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 249225944Sjoerg if ((cps[i])->flags & CP_NCP) 249325944Sjoerg (cps[i])->Open(sp); 249425944Sjoerg } 249525944Sjoerg 249625944Sjoerg /* Send Up events to all started protos. */ 249725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 249825944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 249925944Sjoerg (cps[i])->Up(sp); 250025944Sjoerg 250142104Sphk /* notify low-level driver of state change */ 250242104Sphk if (sp->pp_chg) 250342104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 250442104Sphk 250525944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 250625944Sjoerg /* if no NCP is starting, close down */ 250730300Sjoerg sppp_lcp_check_and_close(sp); 250825944Sjoerg} 250925944Sjoerg 251025944Sjoergstatic void 251125944Sjoergsppp_lcp_tld(struct sppp *sp) 251225944Sjoerg{ 251342066Sphk STDDCL; 251425944Sjoerg int i; 251525944Sjoerg u_long mask; 251625944Sjoerg 251725944Sjoerg sp->pp_phase = PHASE_TERMINATE; 251825944Sjoerg 251942066Sphk if (debug) 252042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 252142066Sphk sppp_phase_name(sp->pp_phase)); 252225944Sjoerg 252325944Sjoerg /* 252425944Sjoerg * Take upper layers down. We send the Down event first and 252525944Sjoerg * the Close second to prevent the upper layers from sending 252625944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 252725944Sjoerg * describes it. 252825944Sjoerg */ 252925944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 253025944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 253125944Sjoerg (cps[i])->Down(sp); 253225944Sjoerg (cps[i])->Close(sp); 253325944Sjoerg } 253425944Sjoerg} 253525944Sjoerg 253625944Sjoergstatic void 253725944Sjoergsppp_lcp_tls(struct sppp *sp) 253825944Sjoerg{ 253942066Sphk STDDCL; 254025944Sjoerg 254125944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 254225944Sjoerg 254342066Sphk if (debug) 254442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 254542066Sphk sppp_phase_name(sp->pp_phase)); 254625944Sjoerg 254725944Sjoerg /* Notify lower layer if desired. */ 254825944Sjoerg if (sp->pp_tls) 254925944Sjoerg (sp->pp_tls)(sp); 255041881Sphk else 255141881Sphk (sp->pp_up)(sp); 255225944Sjoerg} 255325944Sjoerg 255425944Sjoergstatic void 255525944Sjoergsppp_lcp_tlf(struct sppp *sp) 255625944Sjoerg{ 255742066Sphk STDDCL; 255825944Sjoerg 255925944Sjoerg sp->pp_phase = PHASE_DEAD; 256042066Sphk if (debug) 256142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 256242066Sphk sppp_phase_name(sp->pp_phase)); 256325944Sjoerg 256425944Sjoerg /* Notify lower layer if desired. */ 256525944Sjoerg if (sp->pp_tlf) 256625944Sjoerg (sp->pp_tlf)(sp); 256741881Sphk else 256841881Sphk (sp->pp_down)(sp); 256925944Sjoerg} 257025944Sjoerg 257125944Sjoergstatic void 257225944Sjoergsppp_lcp_scr(struct sppp *sp) 257325944Sjoerg{ 257430300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 257525944Sjoerg int i = 0; 257630300Sjoerg u_short authproto; 257725944Sjoerg 257825944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 257925944Sjoerg if (! sp->lcp.magic) 258042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 258135064Sphk sp->lcp.magic = random(); 258240008Sjoerg#else 258340008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 258440008Sjoerg#endif 258525944Sjoerg opt[i++] = LCP_OPT_MAGIC; 258625944Sjoerg opt[i++] = 6; 258725944Sjoerg opt[i++] = sp->lcp.magic >> 24; 258825944Sjoerg opt[i++] = sp->lcp.magic >> 16; 258925944Sjoerg opt[i++] = sp->lcp.magic >> 8; 259025944Sjoerg opt[i++] = sp->lcp.magic; 259125944Sjoerg } 259225944Sjoerg 259325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 259425944Sjoerg opt[i++] = LCP_OPT_MRU; 259525944Sjoerg opt[i++] = 4; 259625944Sjoerg opt[i++] = sp->lcp.mru >> 8; 259725944Sjoerg opt[i++] = sp->lcp.mru; 259825944Sjoerg } 259925944Sjoerg 260030300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 260130300Sjoerg authproto = sp->hisauth.proto; 260230300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 260330300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 260430300Sjoerg opt[i++] = authproto >> 8; 260530300Sjoerg opt[i++] = authproto; 260630300Sjoerg if (authproto == PPP_CHAP) 260730300Sjoerg opt[i++] = CHAP_MD5; 260830300Sjoerg } 260930300Sjoerg 261078064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 261125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 261225944Sjoerg} 261325944Sjoerg 261425944Sjoerg/* 261530300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 261630300Sjoerg */ 261730300Sjoergstatic int 261830300Sjoergsppp_ncp_check(struct sppp *sp) 261930300Sjoerg{ 262030300Sjoerg int i, mask; 262130300Sjoerg 262230300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 262330300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 262430300Sjoerg return 1; 262530300Sjoerg return 0; 262630300Sjoerg} 262730300Sjoerg 262830300Sjoerg/* 262925944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 263025944Sjoerg * Called by the NCPs during their tlf action handling. 263125944Sjoerg */ 263225944Sjoergstatic void 263330300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 263425944Sjoerg{ 263525944Sjoerg 263630300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 263730300Sjoerg /* don't bother, we are already going down */ 263830300Sjoerg return; 263930300Sjoerg 264030300Sjoerg if (sppp_ncp_check(sp)) 264130300Sjoerg return; 264230300Sjoerg 264325944Sjoerg lcp.Close(sp); 264425944Sjoerg} 264570199Sjhay 264670199Sjhay/* 264725944Sjoerg *--------------------------------------------------------------------------* 264825944Sjoerg * * 264925944Sjoerg * The IPCP implementation. * 265025944Sjoerg * * 265125944Sjoerg *--------------------------------------------------------------------------* 265225944Sjoerg */ 265325944Sjoerg 265425944Sjoergstatic void 265525944Sjoergsppp_ipcp_init(struct sppp *sp) 265625944Sjoerg{ 265725944Sjoerg sp->ipcp.opts = 0; 265825944Sjoerg sp->ipcp.flags = 0; 265925944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 266025944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 266178064Sume sp->pp_seq[IDX_IPCP] = 0; 266278064Sume sp->pp_rseq[IDX_IPCP] = 0; 266342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 266429681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 266540008Sjoerg#endif 266625944Sjoerg} 266725944Sjoerg 266825944Sjoergstatic void 266925944Sjoergsppp_ipcp_up(struct sppp *sp) 267025944Sjoerg{ 267125944Sjoerg sppp_up_event(&ipcp, sp); 267225944Sjoerg} 267325944Sjoerg 267425944Sjoergstatic void 267525944Sjoergsppp_ipcp_down(struct sppp *sp) 267625944Sjoerg{ 267725944Sjoerg sppp_down_event(&ipcp, sp); 267825944Sjoerg} 267925944Sjoerg 268025944Sjoergstatic void 268125944Sjoergsppp_ipcp_open(struct sppp *sp) 268225944Sjoerg{ 268325944Sjoerg STDDCL; 268425944Sjoerg u_long myaddr, hisaddr; 268525944Sjoerg 268642104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 268742104Sphk 268830300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 268925944Sjoerg /* 269025944Sjoerg * If we don't have his address, this probably means our 269125944Sjoerg * interface doesn't want to talk IP at all. (This could 269225944Sjoerg * be the case if somebody wants to speak only IPX, for 269325944Sjoerg * example.) Don't open IPCP in this case. 269425944Sjoerg */ 269525944Sjoerg if (hisaddr == 0L) { 269625944Sjoerg /* XXX this message should go away */ 269725944Sjoerg if (debug) 269840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 269940008Sjoerg SPP_ARGS(ifp)); 270025944Sjoerg return; 270125944Sjoerg } 270225944Sjoerg 270325944Sjoerg if (myaddr == 0L) { 270425944Sjoerg /* 270525944Sjoerg * I don't have an assigned address, so i need to 270625944Sjoerg * negotiate my address. 270725944Sjoerg */ 270825944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 270925944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 271042104Sphk } else 271142104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 271225944Sjoerg sppp_open_event(&ipcp, sp); 271325944Sjoerg} 271425944Sjoerg 271525944Sjoergstatic void 271625944Sjoergsppp_ipcp_close(struct sppp *sp) 271725944Sjoerg{ 271825944Sjoerg sppp_close_event(&ipcp, sp); 271925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 272025944Sjoerg /* 272125944Sjoerg * My address was dynamic, clear it again. 272225944Sjoerg */ 272325944Sjoerg sppp_set_ip_addr(sp, 0L); 272425944Sjoerg} 272525944Sjoerg 272625944Sjoergstatic void 272725944Sjoergsppp_ipcp_TO(void *cookie) 272825944Sjoerg{ 272925944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 273025944Sjoerg} 273125944Sjoerg 273225944Sjoerg/* 273325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 273425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 273525944Sjoerg * caused action scn. (The return value is used to make the state 273625944Sjoerg * transition decision in the state automaton.) 273725944Sjoerg */ 273825944Sjoergstatic int 273925944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 274025944Sjoerg{ 274125944Sjoerg u_char *buf, *r, *p; 274225944Sjoerg struct ifnet *ifp = &sp->pp_if; 274325944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 274425944Sjoerg u_long hisaddr, desiredaddr; 274542104Sphk int gotmyaddr = 0; 274625944Sjoerg 274725944Sjoerg len -= 4; 274825944Sjoerg origlen = len; 274925944Sjoerg /* 275025944Sjoerg * Make sure to allocate a buf that can at least hold a 275125944Sjoerg * conf-nak with an `address' option. We might need it below. 275225944Sjoerg */ 275325944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 275425944Sjoerg if (! buf) 275525944Sjoerg return (0); 275625944Sjoerg 275725944Sjoerg /* pass 1: see if we can recognize them */ 275825944Sjoerg if (debug) 275940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 276040008Sjoerg SPP_ARGS(ifp)); 276125944Sjoerg p = (void*) (h+1); 276225944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 276325944Sjoerg if (debug) 276469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 276525944Sjoerg switch (*p) { 276625944Sjoerg case IPCP_OPT_ADDRESS: 276725944Sjoerg if (len >= 6 && p[1] == 6) { 276825944Sjoerg /* correctly formed address option */ 276925944Sjoerg continue; 277025944Sjoerg } 277125706Sjoerg if (debug) 277269211Sphk log(-1, "[invalid] "); 277311189Sjkh break; 277425944Sjoerg default: 277525944Sjoerg /* Others not supported. */ 277625944Sjoerg if (debug) 277769211Sphk log(-1, "[rej] "); 27784910Swollman break; 27794910Swollman } 278025944Sjoerg /* Add the option to rejected list. */ 278125944Sjoerg bcopy (p, r, p[1]); 278225944Sjoerg r += p[1]; 278325944Sjoerg rlen += p[1]; 278425944Sjoerg } 278525944Sjoerg if (rlen) { 278625944Sjoerg if (debug) 278769211Sphk log(-1, " send conf-rej\n"); 278825944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 278925944Sjoerg return 0; 279025944Sjoerg } else if (debug) 279169211Sphk log(-1, "\n"); 279225944Sjoerg 279325944Sjoerg /* pass 2: parse option values */ 279430300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 279525944Sjoerg if (debug) 279640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 279740008Sjoerg SPP_ARGS(ifp)); 279825944Sjoerg p = (void*) (h+1); 279925944Sjoerg len = origlen; 280025944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 280125944Sjoerg if (debug) 280269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 280325944Sjoerg switch (*p) { 280425944Sjoerg case IPCP_OPT_ADDRESS: 280542104Sphk /* This is the address he wants in his end */ 280625944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 280725944Sjoerg p[4] << 8 | p[5]; 280833928Sphk if (desiredaddr == hisaddr || 280942104Sphk (hisaddr == 1 && desiredaddr != 0)) { 281025944Sjoerg /* 281125944Sjoerg * Peer's address is same as our value, 281270199Sjhay * or we have set it to 0.0.0.1 to 281333928Sphk * indicate that we do not really care, 281425944Sjoerg * this is agreeable. Gonna conf-ack 281525944Sjoerg * it. 281625944Sjoerg */ 281725944Sjoerg if (debug) 281869211Sphk log(-1, "%s [ack] ", 281942104Sphk sppp_dotted_quad(hisaddr)); 282025944Sjoerg /* record that we've seen it already */ 282125944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 282225944Sjoerg continue; 282325944Sjoerg } 282425944Sjoerg /* 282525944Sjoerg * The address wasn't agreeable. This is either 282625944Sjoerg * he sent us 0.0.0.0, asking to assign him an 282725944Sjoerg * address, or he send us another address not 282825944Sjoerg * matching our value. Either case, we gonna 282925944Sjoerg * conf-nak it with our value. 283042104Sphk * XXX: we should "rej" if hisaddr == 0 283125944Sjoerg */ 283225944Sjoerg if (debug) { 283325944Sjoerg if (desiredaddr == 0) 283469211Sphk log(-1, "[addr requested] "); 283525944Sjoerg else 283669211Sphk log(-1, "%s [not agreed] ", 283742104Sphk sppp_dotted_quad(desiredaddr)); 283825944Sjoerg 283925944Sjoerg } 284044235Sphk p[2] = hisaddr >> 24; 284144235Sphk p[3] = hisaddr >> 16; 284244235Sphk p[4] = hisaddr >> 8; 284344235Sphk p[5] = hisaddr; 284411189Sjkh break; 284525706Sjoerg } 284625944Sjoerg /* Add the option to nak'ed list. */ 284725944Sjoerg bcopy (p, r, p[1]); 284825944Sjoerg r += p[1]; 284925944Sjoerg rlen += p[1]; 285025944Sjoerg } 285125944Sjoerg 285225944Sjoerg /* 285325944Sjoerg * If we are about to conf-ack the request, but haven't seen 285425944Sjoerg * his address so far, gonna conf-nak it instead, with the 285525944Sjoerg * `address' option present and our idea of his address being 285625944Sjoerg * filled in there, to request negotiation of both addresses. 285725944Sjoerg * 285825944Sjoerg * XXX This can result in an endless req - nak loop if peer 285925944Sjoerg * doesn't want to send us his address. Q: What should we do 286025944Sjoerg * about it? XXX A: implement the max-failure counter. 286125944Sjoerg */ 286242104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 286325944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 286425944Sjoerg buf[1] = 6; 286525944Sjoerg buf[2] = hisaddr >> 24; 286625944Sjoerg buf[3] = hisaddr >> 16; 286725944Sjoerg buf[4] = hisaddr >> 8; 286825944Sjoerg buf[5] = hisaddr; 286925944Sjoerg rlen = 6; 287025706Sjoerg if (debug) 287169211Sphk log(-1, "still need hisaddr "); 287225944Sjoerg } 287325944Sjoerg 287425944Sjoerg if (rlen) { 287525706Sjoerg if (debug) 287669211Sphk log(-1, " send conf-nak\n"); 287725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 287825944Sjoerg } else { 287925706Sjoerg if (debug) 288069211Sphk log(-1, " send conf-ack\n"); 288125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 288225944Sjoerg h->ident, origlen, h+1); 288325944Sjoerg } 288425944Sjoerg 288525944Sjoerg free (buf, M_TEMP); 288625944Sjoerg return (rlen == 0); 288725944Sjoerg} 288825944Sjoerg 288925944Sjoerg/* 289025944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 289125944Sjoerg * negotiation. 289225944Sjoerg */ 289325944Sjoergstatic void 289425944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 289525944Sjoerg{ 289625944Sjoerg u_char *buf, *p; 289725944Sjoerg struct ifnet *ifp = &sp->pp_if; 289825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 289925944Sjoerg 290025944Sjoerg len -= 4; 290125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 290225944Sjoerg if (!buf) 290325944Sjoerg return; 290425944Sjoerg 290525944Sjoerg if (debug) 290640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 290740008Sjoerg SPP_ARGS(ifp)); 290825944Sjoerg 290925944Sjoerg p = (void*) (h+1); 291025944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 291125706Sjoerg if (debug) 291269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 291325944Sjoerg switch (*p) { 291425944Sjoerg case IPCP_OPT_ADDRESS: 291525944Sjoerg /* 291625944Sjoerg * Peer doesn't grok address option. This is 291725944Sjoerg * bad. XXX Should we better give up here? 291842104Sphk * XXX We could try old "addresses" option... 291925944Sjoerg */ 292025944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 292125944Sjoerg break; 292225944Sjoerg } 29234910Swollman } 292425944Sjoerg if (debug) 292569211Sphk log(-1, "\n"); 292625944Sjoerg free (buf, M_TEMP); 292725944Sjoerg return; 29284910Swollman} 29294910Swollman 293025944Sjoerg/* 293125944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 293225944Sjoerg * negotiation. 293325944Sjoerg */ 293412820Sphkstatic void 293525944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 29364910Swollman{ 293725944Sjoerg u_char *buf, *p; 293825944Sjoerg struct ifnet *ifp = &sp->pp_if; 293925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 294025944Sjoerg u_long wantaddr; 29414910Swollman 294225944Sjoerg len -= 4; 294325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 294425944Sjoerg if (!buf) 294525944Sjoerg return; 294625944Sjoerg 294725944Sjoerg if (debug) 294840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 294940008Sjoerg SPP_ARGS(ifp)); 295025944Sjoerg 295125944Sjoerg p = (void*) (h+1); 295225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 295325944Sjoerg if (debug) 295469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 295525944Sjoerg switch (*p) { 295625944Sjoerg case IPCP_OPT_ADDRESS: 295725944Sjoerg /* 295825944Sjoerg * Peer doesn't like our local IP address. See 295925944Sjoerg * if we can do something for him. We'll drop 296025944Sjoerg * him our address then. 296125944Sjoerg */ 296225944Sjoerg if (len >= 6 && p[1] == 6) { 296325944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 296425944Sjoerg p[4] << 8 | p[5]; 296525944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 296625944Sjoerg if (debug) 296769211Sphk log(-1, "[wantaddr %s] ", 296830300Sjoerg sppp_dotted_quad(wantaddr)); 296925944Sjoerg /* 297025944Sjoerg * When doing dynamic address assignment, 297125944Sjoerg * we accept his offer. Otherwise, we 297225944Sjoerg * ignore it and thus continue to negotiate 297325944Sjoerg * our already existing value. 297442104Sphk * XXX: Bogus, if he said no once, he'll 297542104Sphk * just say no again, might as well die. 297625944Sjoerg */ 297725944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 297825944Sjoerg sppp_set_ip_addr(sp, wantaddr); 297925944Sjoerg if (debug) 298069211Sphk log(-1, "[agree] "); 298142104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 298225944Sjoerg } 298325944Sjoerg } 298425944Sjoerg break; 298525944Sjoerg } 298625944Sjoerg } 298725944Sjoerg if (debug) 298869211Sphk log(-1, "\n"); 298925944Sjoerg free (buf, M_TEMP); 299025944Sjoerg return; 29914910Swollman} 29924910Swollman 299312820Sphkstatic void 299425944Sjoergsppp_ipcp_tlu(struct sppp *sp) 29954910Swollman{ 299642104Sphk /* we are up - notify isdn daemon */ 299742104Sphk if (sp->pp_con) 299842104Sphk sp->pp_con(sp); 29994910Swollman} 30004910Swollman 300125944Sjoergstatic void 300225944Sjoergsppp_ipcp_tld(struct sppp *sp) 300325944Sjoerg{ 300425944Sjoerg} 300525944Sjoerg 300625944Sjoergstatic void 300725944Sjoergsppp_ipcp_tls(struct sppp *sp) 300825944Sjoerg{ 300925944Sjoerg /* indicate to LCP that it must stay alive */ 301025944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 301125944Sjoerg} 301225944Sjoerg 301325944Sjoergstatic void 301425944Sjoergsppp_ipcp_tlf(struct sppp *sp) 301525944Sjoerg{ 301625944Sjoerg /* we no longer need LCP */ 301725944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 301830300Sjoerg sppp_lcp_check_and_close(sp); 301925944Sjoerg} 302025944Sjoerg 302125944Sjoergstatic void 302225944Sjoergsppp_ipcp_scr(struct sppp *sp) 302325944Sjoerg{ 302425944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 302525944Sjoerg u_long ouraddr; 302625944Sjoerg int i = 0; 302725944Sjoerg 302825944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 302930300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 303025944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 303125944Sjoerg opt[i++] = 6; 303225944Sjoerg opt[i++] = ouraddr >> 24; 303325944Sjoerg opt[i++] = ouraddr >> 16; 303425944Sjoerg opt[i++] = ouraddr >> 8; 303525944Sjoerg opt[i++] = ouraddr; 303625944Sjoerg } 303725944Sjoerg 303878064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 303925944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 304025944Sjoerg} 304125944Sjoerg 304270199Sjhay/* 304330300Sjoerg *--------------------------------------------------------------------------* 304430300Sjoerg * * 304578064Sume * The IPv6CP implementation. * 304678064Sume * * 304778064Sume *--------------------------------------------------------------------------* 304878064Sume */ 304978064Sume 305078064Sume#ifdef INET6 305178064Sumestatic void 305278064Sumesppp_ipv6cp_init(struct sppp *sp) 305378064Sume{ 305478064Sume sp->ipv6cp.opts = 0; 305578064Sume sp->ipv6cp.flags = 0; 305678064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 305778064Sume sp->fail_counter[IDX_IPV6CP] = 0; 305878064Sume sp->pp_seq[IDX_IPV6CP] = 0; 305978064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 306078064Sume#if defined(__NetBSD__) 306178064Sume callout_init(&sp->ch[IDX_IPV6CP]); 306278064Sume#endif 306378064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 306478064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 306578064Sume#endif 306678064Sume} 306778064Sume 306878064Sumestatic void 306978064Sumesppp_ipv6cp_up(struct sppp *sp) 307078064Sume{ 307178064Sume sppp_up_event(&ipv6cp, sp); 307278064Sume} 307378064Sume 307478064Sumestatic void 307578064Sumesppp_ipv6cp_down(struct sppp *sp) 307678064Sume{ 307778064Sume sppp_down_event(&ipv6cp, sp); 307878064Sume} 307978064Sume 308078064Sumestatic void 308178064Sumesppp_ipv6cp_open(struct sppp *sp) 308278064Sume{ 308378064Sume STDDCL; 308478064Sume struct in6_addr myaddr, hisaddr; 308578064Sume 308678064Sume#ifdef IPV6CP_MYIFID_DYN 308778064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 308878064Sume#else 308978064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 309078064Sume#endif 309178064Sume 309278064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 309378064Sume /* 309478064Sume * If we don't have our address, this probably means our 309578064Sume * interface doesn't want to talk IPv6 at all. (This could 309678064Sume * be the case if somebody wants to speak only IPX, for 309778064Sume * example.) Don't open IPv6CP in this case. 309878064Sume */ 309978064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 310078064Sume /* XXX this message should go away */ 310178064Sume if (debug) 310278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 310378064Sume SPP_ARGS(ifp)); 310478064Sume return; 310578064Sume } 310678064Sume 310778064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 310878064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 310978064Sume sppp_open_event(&ipv6cp, sp); 311078064Sume} 311178064Sume 311278064Sumestatic void 311378064Sumesppp_ipv6cp_close(struct sppp *sp) 311478064Sume{ 311578064Sume sppp_close_event(&ipv6cp, sp); 311678064Sume} 311778064Sume 311878064Sumestatic void 311978064Sumesppp_ipv6cp_TO(void *cookie) 312078064Sume{ 312178064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 312278064Sume} 312378064Sume 312478064Sume/* 312578064Sume * Analyze a configure request. Return true if it was agreeable, and 312678064Sume * caused action sca, false if it has been rejected or nak'ed, and 312778064Sume * caused action scn. (The return value is used to make the state 312878064Sume * transition decision in the state automaton.) 312978064Sume */ 313078064Sumestatic int 313178064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 313278064Sume{ 313378064Sume u_char *buf, *r, *p; 313478064Sume struct ifnet *ifp = &sp->pp_if; 313578064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 313678064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 313778064Sume int ifidcount; 313878064Sume int type; 313978064Sume int collision, nohisaddr; 314078064Sume 314178064Sume len -= 4; 314278064Sume origlen = len; 314378064Sume /* 314478064Sume * Make sure to allocate a buf that can at least hold a 314578064Sume * conf-nak with an `address' option. We might need it below. 314678064Sume */ 314778064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 314878064Sume if (! buf) 314978064Sume return (0); 315078064Sume 315178064Sume /* pass 1: see if we can recognize them */ 315278064Sume if (debug) 315378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 315478064Sume SPP_ARGS(ifp)); 315578064Sume p = (void*) (h+1); 315678064Sume ifidcount = 0; 315778064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 315878064Sume if (debug) 315978176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 316078064Sume switch (*p) { 316178064Sume case IPV6CP_OPT_IFID: 316278064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 316378064Sume /* correctly formed address option */ 316478064Sume ifidcount++; 316578064Sume continue; 316678064Sume } 316778064Sume if (debug) 316878176Sume log(-1, " [invalid]"); 316978064Sume break; 317078064Sume#ifdef notyet 317178064Sume case IPV6CP_OPT_COMPRESSION: 317278064Sume if (len >= 4 && p[1] >= 4) { 317378064Sume /* correctly formed compress option */ 317478064Sume continue; 317578064Sume } 317678064Sume if (debug) 317778176Sume log(-1, " [invalid]"); 317878064Sume break; 317978064Sume#endif 318078064Sume default: 318178064Sume /* Others not supported. */ 318278064Sume if (debug) 318378176Sume log(-1, " [rej]"); 318478064Sume break; 318578064Sume } 318678064Sume /* Add the option to rejected list. */ 318778064Sume bcopy (p, r, p[1]); 318878064Sume r += p[1]; 318978064Sume rlen += p[1]; 319078064Sume } 319178064Sume if (rlen) { 319278064Sume if (debug) 319378176Sume log(-1, " send conf-rej\n"); 319478064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 319578064Sume goto end; 319678064Sume } else if (debug) 319778176Sume log(-1, "\n"); 319878064Sume 319978064Sume /* pass 2: parse option values */ 320078064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 320178064Sume if (debug) 320278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 320378064Sume SPP_ARGS(ifp)); 320478064Sume p = (void*) (h+1); 320578064Sume len = origlen; 320678064Sume type = CONF_ACK; 320778064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 320878064Sume if (debug) 320978176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 321078064Sume switch (*p) { 321178064Sume#ifdef notyet 321278064Sume case IPV6CP_OPT_COMPRESSION: 321378064Sume continue; 321478064Sume#endif 321578064Sume case IPV6CP_OPT_IFID: 321678064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 321778064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 321878064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 321978064Sume &myaddr.s6_addr[8], 8) == 0); 322078064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 322178064Sume 322278064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 322378064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 322478064Sume 322578064Sume if (!collision && !nohisaddr) { 322678064Sume /* no collision, hisaddr known - Conf-Ack */ 322778064Sume type = CONF_ACK; 322878064Sume 322978064Sume if (debug) { 323078176Sume log(-1, " %s [%s]", 323178064Sume ip6_sprintf(&desiredaddr), 323278064Sume sppp_cp_type_name(type)); 323378064Sume } 323478064Sume continue; 323578064Sume } 323678064Sume 323778064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 323878064Sume if (collision && nohisaddr) { 323978064Sume /* collision, hisaddr unknown - Conf-Rej */ 324078064Sume type = CONF_REJ; 324178064Sume bzero(&p[2], 8); 324278064Sume } else { 324378064Sume /* 324478064Sume * - no collision, hisaddr unknown, or 324578064Sume * - collision, hisaddr known 324678064Sume * Conf-Nak, suggest hisaddr 324778064Sume */ 324878064Sume type = CONF_NAK; 324978064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 325078064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 325178064Sume } 325278064Sume if (debug) 325378176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 325478064Sume sppp_cp_type_name(type)); 325578064Sume break; 325678064Sume } 325778064Sume /* Add the option to nak'ed list. */ 325878064Sume bcopy (p, r, p[1]); 325978064Sume r += p[1]; 326078064Sume rlen += p[1]; 326178064Sume } 326278064Sume 326378064Sume if (rlen == 0 && type == CONF_ACK) { 326478064Sume if (debug) 326578176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 326678064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 326778064Sume } else { 326878064Sume#ifdef DIAGNOSTIC 326978064Sume if (type == CONF_ACK) 327078064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 327178064Sume#endif 327278064Sume 327378064Sume if (debug) { 327478176Sume log(-1, " send %s suggest %s\n", 327578064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 327678064Sume } 327778064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 327878064Sume } 327978064Sume 328078064Sume end: 328178064Sume free (buf, M_TEMP); 328278064Sume return (rlen == 0); 328378064Sume} 328478064Sume 328578064Sume/* 328678064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 328778064Sume * negotiation. 328878064Sume */ 328978064Sumestatic void 329078064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 329178064Sume{ 329278064Sume u_char *buf, *p; 329378064Sume struct ifnet *ifp = &sp->pp_if; 329478064Sume int debug = ifp->if_flags & IFF_DEBUG; 329578064Sume 329678064Sume len -= 4; 329778064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 329878064Sume if (!buf) 329978064Sume return; 330078064Sume 330178064Sume if (debug) 330278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 330378064Sume SPP_ARGS(ifp)); 330478064Sume 330578064Sume p = (void*) (h+1); 330678064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 330778064Sume if (debug) 330878176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 330978064Sume switch (*p) { 331078064Sume case IPV6CP_OPT_IFID: 331178064Sume /* 331278064Sume * Peer doesn't grok address option. This is 331378064Sume * bad. XXX Should we better give up here? 331478064Sume */ 331578064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 331678064Sume break; 331778064Sume#ifdef notyet 331878064Sume case IPV6CP_OPT_COMPRESS: 331978064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 332078064Sume break; 332178064Sume#endif 332278064Sume } 332378064Sume } 332478064Sume if (debug) 332578176Sume log(-1, "\n"); 332678064Sume free (buf, M_TEMP); 332778064Sume return; 332878064Sume} 332978064Sume 333078064Sume/* 333178064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 333278064Sume * negotiation. 333378064Sume */ 333478064Sumestatic void 333578064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 333678064Sume{ 333778064Sume u_char *buf, *p; 333878064Sume struct ifnet *ifp = &sp->pp_if; 333978064Sume int debug = ifp->if_flags & IFF_DEBUG; 334078064Sume struct in6_addr suggestaddr; 334178064Sume 334278064Sume len -= 4; 334378064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 334478064Sume if (!buf) 334578064Sume return; 334678064Sume 334778064Sume if (debug) 334878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 334978064Sume SPP_ARGS(ifp)); 335078064Sume 335178064Sume p = (void*) (h+1); 335278064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 335378064Sume if (debug) 335478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 335578064Sume switch (*p) { 335678064Sume case IPV6CP_OPT_IFID: 335778064Sume /* 335878064Sume * Peer doesn't like our local ifid. See 335978064Sume * if we can do something for him. We'll drop 336078064Sume * him our address then. 336178064Sume */ 336278064Sume if (len < 10 || p[1] != 10) 336378064Sume break; 336478064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 336578064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 336678064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 336778064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 336878064Sume 336978064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 337078064Sume if (debug) 337178176Sume log(-1, " [suggestaddr %s]", 337278064Sume ip6_sprintf(&suggestaddr)); 337378064Sume#ifdef IPV6CP_MYIFID_DYN 337478064Sume /* 337578064Sume * When doing dynamic address assignment, 337678064Sume * we accept his offer. 337778064Sume */ 337878064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 337978064Sume struct in6_addr lastsuggest; 338078064Sume /* 338178064Sume * If <suggested myaddr from peer> equals to 338278064Sume * <hisaddr we have suggested last time>, 338378064Sume * we have a collision. generate new random 338478064Sume * ifid. 338578064Sume */ 338678064Sume sppp_suggest_ip6_addr(&lastsuggest); 338778064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 338878064Sume lastsuggest)) { 338978064Sume if (debug) 339078176Sume log(-1, " [random]"); 339178064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 339278064Sume } 339378064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 339478064Sume if (debug) 339578176Sume log(-1, " [agree]"); 339678064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 339778064Sume } 339878064Sume#else 339978064Sume /* 340078064Sume * Since we do not do dynamic address assignment, 340178064Sume * we ignore it and thus continue to negotiate 340278064Sume * our already existing value. This can possibly 340378064Sume * go into infinite request-reject loop. 340478064Sume * 340578064Sume * This is not likely because we normally use 340678064Sume * ifid based on MAC-address. 340778064Sume * If you have no ethernet card on the node, too bad. 340878064Sume * XXX should we use fail_counter? 340978064Sume */ 341078064Sume#endif 341178064Sume break; 341278064Sume#ifdef notyet 341378064Sume case IPV6CP_OPT_COMPRESS: 341478064Sume /* 341578064Sume * Peer wants different compression parameters. 341678064Sume */ 341778064Sume break; 341878064Sume#endif 341978064Sume } 342078064Sume } 342178064Sume if (debug) 342278176Sume log(-1, "\n"); 342378064Sume free (buf, M_TEMP); 342478064Sume return; 342578064Sume} 342678064Sumestatic void 342778064Sumesppp_ipv6cp_tlu(struct sppp *sp) 342878064Sume{ 342978064Sume /* we are up - notify isdn daemon */ 343078064Sume if (sp->pp_con) 343178064Sume sp->pp_con(sp); 343278064Sume} 343378064Sume 343478064Sumestatic void 343578064Sumesppp_ipv6cp_tld(struct sppp *sp) 343678064Sume{ 343778064Sume} 343878064Sume 343978064Sumestatic void 344078064Sumesppp_ipv6cp_tls(struct sppp *sp) 344178064Sume{ 344278064Sume /* indicate to LCP that it must stay alive */ 344378064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 344478064Sume} 344578064Sume 344678064Sumestatic void 344778064Sumesppp_ipv6cp_tlf(struct sppp *sp) 344878064Sume{ 344978064Sume 345078064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 345178064Sume /* we no longer need LCP */ 345278064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 345378064Sume sppp_lcp_check_and_close(sp); 345478064Sume#endif 345578064Sume} 345678064Sume 345778064Sumestatic void 345878064Sumesppp_ipv6cp_scr(struct sppp *sp) 345978064Sume{ 346078064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 346178064Sume struct in6_addr ouraddr; 346278064Sume int i = 0; 346378064Sume 346478064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 346578064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 346678064Sume opt[i++] = IPV6CP_OPT_IFID; 346778064Sume opt[i++] = 10; 346878064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 346978064Sume i += 8; 347078064Sume } 347178064Sume 347278064Sume#ifdef notyet 347378064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 347478064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 347578064Sume opt[i++] = 4; 347678064Sume opt[i++] = 0; /* TBD */ 347778064Sume opt[i++] = 0; /* TBD */ 347878064Sume /* variable length data may follow */ 347978064Sume } 348078064Sume#endif 348178064Sume 348278064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 348378064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 348478064Sume} 348578064Sume#else /*INET6*/ 348678064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 348778064Sume{ 348878064Sume} 348978064Sume 349078064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 349178064Sume{ 349278064Sume} 349378064Sume 349478064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 349578064Sume{ 349678064Sume} 349778064Sume 349878064Sume 349978064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 350078064Sume{ 350178064Sume} 350278064Sume 350378064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 350478064Sume{ 350578064Sume} 350678064Sume 350778064Sumestatic void sppp_ipv6cp_TO(void *sp) 350878064Sume{ 350978064Sume} 351078064Sume 351178064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 351278064Sume{ 351378064Sume return 0; 351478064Sume} 351578064Sume 351678064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 351778064Sume{ 351878064Sume} 351978064Sume 352078064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 352178064Sume{ 352278064Sume} 352378064Sume 352478064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 352578064Sume{ 352678064Sume} 352778064Sume 352878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 352978064Sume{ 353078064Sume} 353178064Sume 353278064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 353378064Sume{ 353478064Sume} 353578064Sume 353678064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 353778064Sume{ 353878064Sume} 353978064Sume 354078064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 354178064Sume{ 354278064Sume} 354378064Sume#endif /*INET6*/ 354478064Sume 354578064Sume/* 354678064Sume *--------------------------------------------------------------------------* 354778064Sume * * 354830300Sjoerg * The CHAP implementation. * 354930300Sjoerg * * 355030300Sjoerg *--------------------------------------------------------------------------* 355130300Sjoerg */ 355230300Sjoerg 355330300Sjoerg/* 355430300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 355530300Sjoerg * the control protocols do, since they do have Open and Close events, but 355630300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 355730300Sjoerg * authentication protocols may be different in both directions (this makes 355830300Sjoerg * sense, think of a machine that never accepts incoming calls but only 355930300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 356030300Sjoerg * 356130300Sjoerg * Our state machine for the local authentication protocol (we are requesting 356230300Sjoerg * the peer to authenticate) looks like: 356330300Sjoerg * 356430300Sjoerg * RCA- 356530300Sjoerg * +--------------------------------------------+ 356630300Sjoerg * V scn,tld| 356730300Sjoerg * +--------+ Close +---------+ RCA+ 356830300Sjoerg * | |<----------------------------------| |------+ 356930300Sjoerg * +--->| Closed | TO* | Opened | sca | 357030300Sjoerg * | | |-----+ +-------| |<-----+ 357130300Sjoerg * | +--------+ irc | | +---------+ 357230300Sjoerg * | ^ | | ^ 357330300Sjoerg * | | | | | 357430300Sjoerg * | | | | | 357530300Sjoerg * | TO-| | | | 357630300Sjoerg * | |tld TO+ V | | 357730300Sjoerg * | | +------->+ | | 357830300Sjoerg * | | | | | | 357930300Sjoerg * | +--------+ V | | 358030300Sjoerg * | | |<----+<--------------------+ | 358130300Sjoerg * | | Req- | scr | 358230300Sjoerg * | | Sent | | 358330300Sjoerg * | | | | 358430300Sjoerg * | +--------+ | 358530300Sjoerg * | RCA- | | RCA+ | 358630300Sjoerg * +------+ +------------------------------------------+ 358730300Sjoerg * scn,tld sca,irc,ict,tlu 358830300Sjoerg * 358930300Sjoerg * 359030300Sjoerg * with: 359130300Sjoerg * 359230300Sjoerg * Open: LCP reached authentication phase 359330300Sjoerg * Close: LCP reached terminate phase 359430300Sjoerg * 359530300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 359630300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 359730300Sjoerg * TO+: timeout with restart counter >= 0 359830300Sjoerg * TO-: timeout with restart counter < 0 359930300Sjoerg * TO*: reschedule timeout for CHAP 360030300Sjoerg * 360130300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 360230300Sjoerg * sca: send ack packet (pap-ack, chap-success) 360330300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 360430300Sjoerg * ict: initialize re-challenge timer (CHAP only) 360530300Sjoerg * 360630300Sjoerg * tlu: this-layer-up, LCP reaches network phase 360730300Sjoerg * tld: this-layer-down, LCP enters terminate phase 360830300Sjoerg * 360930300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 361030300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 361130300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 361230300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 361330300Sjoerg * causing LCP to enter terminate phase. 361430300Sjoerg * 361530300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 361630300Sjoerg * expected to send one based on the successful negotiation of PAP as 361730300Sjoerg * the authentication protocol during the LCP option negotiation. 361830300Sjoerg * 361930300Sjoerg * Incoming authentication protocol requests (remote requests 362030300Sjoerg * authentication, we are peer) don't employ a state machine at all, 362130300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 362230300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 362330300Sjoerg * still in authentication phase (thereby violating the standard that 362430300Sjoerg * demands that these NCP packets are to be discarded), so we keep 362530300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 362630300Sjoerg * phase network once we've seen a positive acknowledge for the 362730300Sjoerg * authentication. 362830300Sjoerg */ 362930300Sjoerg 363030300Sjoerg/* 363130300Sjoerg * Handle incoming CHAP packets. 363230300Sjoerg */ 363330300Sjoergvoid 363430300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 363530300Sjoerg{ 363630300Sjoerg STDDCL; 363730300Sjoerg struct lcp_header *h; 363830300Sjoerg int len, x; 363930300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 364030300Sjoerg int value_len, name_len; 364130300Sjoerg MD5_CTX ctx; 364230300Sjoerg 364330300Sjoerg len = m->m_pkthdr.len; 364430300Sjoerg if (len < 4) { 364530300Sjoerg if (debug) 364630300Sjoerg log(LOG_DEBUG, 364740008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 364840008Sjoerg SPP_ARGS(ifp), len); 364930300Sjoerg return; 365030300Sjoerg } 365130300Sjoerg h = mtod (m, struct lcp_header*); 365230300Sjoerg if (len > ntohs (h->len)) 365330300Sjoerg len = ntohs (h->len); 365430300Sjoerg 365530300Sjoerg switch (h->type) { 365630300Sjoerg /* challenge, failure and success are his authproto */ 365730300Sjoerg case CHAP_CHALLENGE: 365830300Sjoerg value = 1 + (u_char*)(h+1); 365930300Sjoerg value_len = value[-1]; 366030300Sjoerg name = value + value_len; 366130300Sjoerg name_len = len - value_len - 5; 366230300Sjoerg if (name_len < 0) { 366330300Sjoerg if (debug) { 366430300Sjoerg log(LOG_DEBUG, 366540008Sjoerg SPP_FMT "chap corrupted challenge " 366630300Sjoerg "<%s id=0x%x len=%d", 366740008Sjoerg SPP_ARGS(ifp), 366830300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 366930300Sjoerg h->ident, ntohs(h->len)); 367044145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 367169211Sphk log(-1, ">\n"); 367230300Sjoerg } 367330300Sjoerg break; 367430300Sjoerg } 367570199Sjhay 367630300Sjoerg if (debug) { 367730300Sjoerg log(LOG_DEBUG, 367840008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 367940008Sjoerg SPP_ARGS(ifp), 368030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 368130300Sjoerg ntohs(h->len)); 368230300Sjoerg sppp_print_string((char*) name, name_len); 368369211Sphk log(-1, " value-size=%d value=", value_len); 368430300Sjoerg sppp_print_bytes(value, value_len); 368569211Sphk log(-1, ">\n"); 368630300Sjoerg } 368730300Sjoerg 368830300Sjoerg /* Compute reply value. */ 368930300Sjoerg MD5Init(&ctx); 369030300Sjoerg MD5Update(&ctx, &h->ident, 1); 369130300Sjoerg MD5Update(&ctx, sp->myauth.secret, 369230300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 369330300Sjoerg MD5Update(&ctx, value, value_len); 369430300Sjoerg MD5Final(digest, &ctx); 369530300Sjoerg dsize = sizeof digest; 369630300Sjoerg 369730300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 369830300Sjoerg sizeof dsize, (const char *)&dsize, 369930300Sjoerg sizeof digest, digest, 370040008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 370130300Sjoerg sp->myauth.name, 370230300Sjoerg 0); 370330300Sjoerg break; 370430300Sjoerg 370530300Sjoerg case CHAP_SUCCESS: 370630300Sjoerg if (debug) { 370740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 370840008Sjoerg SPP_ARGS(ifp)); 370930300Sjoerg if (len > 4) { 371069211Sphk log(-1, ": "); 371130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 371230300Sjoerg } 371369211Sphk log(-1, "\n"); 371430300Sjoerg } 371530300Sjoerg x = splimp(); 371630300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 371730300Sjoerg if (sp->myauth.proto == PPP_CHAP && 371832169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 371930300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 372030300Sjoerg /* 372130300Sjoerg * We are authenticator for CHAP but didn't 372230300Sjoerg * complete yet. Leave it to tlu to proceed 372330300Sjoerg * to network phase. 372430300Sjoerg */ 372530300Sjoerg splx(x); 372630300Sjoerg break; 372730300Sjoerg } 372830300Sjoerg splx(x); 372930300Sjoerg sppp_phase_network(sp); 373030300Sjoerg break; 373130300Sjoerg 373230300Sjoerg case CHAP_FAILURE: 373330300Sjoerg if (debug) { 373440008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 373540008Sjoerg SPP_ARGS(ifp)); 373630300Sjoerg if (len > 4) { 373769211Sphk log(-1, ": "); 373830300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 373930300Sjoerg } 374069211Sphk log(-1, "\n"); 374130300Sjoerg } else 374240008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 374340008Sjoerg SPP_ARGS(ifp)); 374430300Sjoerg /* await LCP shutdown by authenticator */ 374530300Sjoerg break; 374630300Sjoerg 374730300Sjoerg /* response is my authproto */ 374830300Sjoerg case CHAP_RESPONSE: 374930300Sjoerg value = 1 + (u_char*)(h+1); 375030300Sjoerg value_len = value[-1]; 375130300Sjoerg name = value + value_len; 375230300Sjoerg name_len = len - value_len - 5; 375330300Sjoerg if (name_len < 0) { 375430300Sjoerg if (debug) { 375530300Sjoerg log(LOG_DEBUG, 375640008Sjoerg SPP_FMT "chap corrupted response " 375730300Sjoerg "<%s id=0x%x len=%d", 375840008Sjoerg SPP_ARGS(ifp), 375930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 376030300Sjoerg h->ident, ntohs(h->len)); 376144145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 376269211Sphk log(-1, ">\n"); 376330300Sjoerg } 376430300Sjoerg break; 376530300Sjoerg } 376630300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 376730300Sjoerg if (debug) 376830300Sjoerg log(LOG_DEBUG, 376940008Sjoerg SPP_FMT "chap dropping response for old ID " 377030300Sjoerg "(got %d, expected %d)\n", 377140008Sjoerg SPP_ARGS(ifp), 377230300Sjoerg h->ident, sp->confid[IDX_CHAP]); 377330300Sjoerg break; 377430300Sjoerg } 377530300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 377630300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 377740008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 377840008Sjoerg SPP_ARGS(ifp)); 377930300Sjoerg sppp_print_string(name, name_len); 378069211Sphk log(-1, " != expected "); 378130300Sjoerg sppp_print_string(sp->hisauth.name, 378230300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 378369211Sphk log(-1, "\n"); 378470199Sjhay } 378530300Sjoerg if (debug) { 378640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 378730300Sjoerg "<%s id=0x%x len=%d name=", 378840008Sjoerg SPP_ARGS(ifp), 378930300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 379030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 379130300Sjoerg h->ident, ntohs (h->len)); 379230300Sjoerg sppp_print_string((char*)name, name_len); 379369211Sphk log(-1, " value-size=%d value=", value_len); 379430300Sjoerg sppp_print_bytes(value, value_len); 379569211Sphk log(-1, ">\n"); 379630300Sjoerg } 379730300Sjoerg if (value_len != AUTHKEYLEN) { 379830300Sjoerg if (debug) 379930300Sjoerg log(LOG_DEBUG, 380040008Sjoerg SPP_FMT "chap bad hash value length: " 380130300Sjoerg "%d bytes, should be %d\n", 380240008Sjoerg SPP_ARGS(ifp), value_len, 380330300Sjoerg AUTHKEYLEN); 380430300Sjoerg break; 380530300Sjoerg } 380630300Sjoerg 380730300Sjoerg MD5Init(&ctx); 380830300Sjoerg MD5Update(&ctx, &h->ident, 1); 380930300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 381030300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 381130300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 381230300Sjoerg MD5Final(digest, &ctx); 381330300Sjoerg 381430300Sjoerg#define FAILMSG "Failed..." 381530300Sjoerg#define SUCCMSG "Welcome!" 381630300Sjoerg 381730300Sjoerg if (value_len != sizeof digest || 381830300Sjoerg bcmp(digest, value, value_len) != 0) { 381930300Sjoerg /* action scn, tld */ 382030300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 382130300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 382230300Sjoerg 0); 382330300Sjoerg chap.tld(sp); 382430300Sjoerg break; 382530300Sjoerg } 382630300Sjoerg /* action sca, perhaps tlu */ 382730300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 382830300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 382930300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 383030300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 383130300Sjoerg 0); 383230300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 383330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 383430300Sjoerg chap.tlu(sp); 383530300Sjoerg } 383630300Sjoerg break; 383730300Sjoerg 383830300Sjoerg default: 383930300Sjoerg /* Unknown CHAP packet type -- ignore. */ 384030300Sjoerg if (debug) { 384140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 384230300Sjoerg "<0x%x id=0x%xh len=%d", 384340008Sjoerg SPP_ARGS(ifp), 384430300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 384530300Sjoerg h->type, h->ident, ntohs(h->len)); 384644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 384769211Sphk log(-1, ">\n"); 384830300Sjoerg } 384930300Sjoerg break; 385030300Sjoerg 385130300Sjoerg } 385230300Sjoerg} 385330300Sjoerg 385430300Sjoergstatic void 385530300Sjoergsppp_chap_init(struct sppp *sp) 385630300Sjoerg{ 385730300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 385830300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 385930300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 386078064Sume sp->pp_seq[IDX_CHAP] = 0; 386178064Sume sp->pp_rseq[IDX_CHAP] = 0; 386242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 386330300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 386440008Sjoerg#endif 386530300Sjoerg} 386630300Sjoerg 386730300Sjoergstatic void 386830300Sjoergsppp_chap_open(struct sppp *sp) 386930300Sjoerg{ 387030300Sjoerg if (sp->myauth.proto == PPP_CHAP && 387130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 387230300Sjoerg /* we are authenticator for CHAP, start it */ 387330300Sjoerg chap.scr(sp); 387430300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 387530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 387630300Sjoerg } 387730300Sjoerg /* nothing to be done if we are peer, await a challenge */ 387830300Sjoerg} 387930300Sjoerg 388030300Sjoergstatic void 388130300Sjoergsppp_chap_close(struct sppp *sp) 388230300Sjoerg{ 388330300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 388430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 388530300Sjoerg} 388630300Sjoerg 388730300Sjoergstatic void 388830300Sjoergsppp_chap_TO(void *cookie) 388930300Sjoerg{ 389030300Sjoerg struct sppp *sp = (struct sppp *)cookie; 389130300Sjoerg STDDCL; 389230300Sjoerg int s; 389330300Sjoerg 389430300Sjoerg s = splimp(); 389530300Sjoerg if (debug) 389640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 389740008Sjoerg SPP_ARGS(ifp), 389830300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 389930300Sjoerg sp->rst_counter[IDX_CHAP]); 390030300Sjoerg 390130300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 390230300Sjoerg /* TO- event */ 390330300Sjoerg switch (sp->state[IDX_CHAP]) { 390430300Sjoerg case STATE_REQ_SENT: 390530300Sjoerg chap.tld(sp); 390630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 390730300Sjoerg break; 390830300Sjoerg } 390930300Sjoerg else 391030300Sjoerg /* TO+ (or TO*) event */ 391130300Sjoerg switch (sp->state[IDX_CHAP]) { 391230300Sjoerg case STATE_OPENED: 391330300Sjoerg /* TO* event */ 391430300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 391530300Sjoerg /* fall through */ 391630300Sjoerg case STATE_REQ_SENT: 391730300Sjoerg chap.scr(sp); 391830300Sjoerg /* sppp_cp_change_state() will restart the timer */ 391930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 392030300Sjoerg break; 392130300Sjoerg } 392230300Sjoerg 392330300Sjoerg splx(s); 392430300Sjoerg} 392530300Sjoerg 392630300Sjoergstatic void 392730300Sjoergsppp_chap_tlu(struct sppp *sp) 392830300Sjoerg{ 392930300Sjoerg STDDCL; 393030300Sjoerg int i, x; 393130300Sjoerg 393240010Sjoerg i = 0; 393330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 393430300Sjoerg 393530300Sjoerg /* 393630300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 393730300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 393830300Sjoerg * initial challenge-response exchange has taken place. 393930300Sjoerg * Provide for an option to avoid rechallenges. 394030300Sjoerg */ 394130300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 394230300Sjoerg /* 394330300Sjoerg * Compute the re-challenge timeout. This will yield 394430300Sjoerg * a number between 300 and 810 seconds. 394530300Sjoerg */ 394630300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 394742064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 394830300Sjoerg } 394930300Sjoerg 395030300Sjoerg if (debug) { 395130300Sjoerg log(LOG_DEBUG, 395240008Sjoerg SPP_FMT "chap %s, ", 395340008Sjoerg SPP_ARGS(ifp), 395430300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 395530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 395669211Sphk log(-1, "next re-challenge in %d seconds\n", i); 395730300Sjoerg else 395869211Sphk log(-1, "re-challenging supressed\n"); 395930300Sjoerg } 396030300Sjoerg 396130300Sjoerg x = splimp(); 396230300Sjoerg /* indicate to LCP that we need to be closed down */ 396330300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 396430300Sjoerg 396530300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 396630300Sjoerg /* 396730300Sjoerg * Remote is authenticator, but his auth proto didn't 396830300Sjoerg * complete yet. Defer the transition to network 396930300Sjoerg * phase. 397030300Sjoerg */ 397130300Sjoerg splx(x); 397230300Sjoerg return; 397330300Sjoerg } 397430300Sjoerg splx(x); 397530300Sjoerg 397630300Sjoerg /* 397730300Sjoerg * If we are already in phase network, we are done here. This 397830300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 397930300Sjoerg */ 398030300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 398130300Sjoerg sppp_phase_network(sp); 398230300Sjoerg} 398330300Sjoerg 398430300Sjoergstatic void 398530300Sjoergsppp_chap_tld(struct sppp *sp) 398630300Sjoerg{ 398730300Sjoerg STDDCL; 398830300Sjoerg 398930300Sjoerg if (debug) 399040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 399140008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 399230300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 399330300Sjoerg 399430300Sjoerg lcp.Close(sp); 399530300Sjoerg} 399630300Sjoerg 399730300Sjoergstatic void 399830300Sjoergsppp_chap_scr(struct sppp *sp) 399930300Sjoerg{ 400030300Sjoerg u_long *ch, seed; 400130300Sjoerg u_char clen; 400230300Sjoerg 400330300Sjoerg /* Compute random challenge. */ 400430300Sjoerg ch = (u_long *)sp->myauth.challenge; 400542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 400635064Sphk read_random(&seed, sizeof seed); 400740008Sjoerg#else 400842104Sphk { 400942104Sphk struct timeval tv; 401040008Sjoerg microtime(&tv); 401140008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 401242104Sphk } 401340008Sjoerg#endif 401430300Sjoerg ch[0] = seed ^ random(); 401530300Sjoerg ch[1] = seed ^ random(); 401630300Sjoerg ch[2] = seed ^ random(); 401730300Sjoerg ch[3] = seed ^ random(); 401830300Sjoerg clen = AUTHKEYLEN; 401930300Sjoerg 402078064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 402130300Sjoerg 402230300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 402330300Sjoerg sizeof clen, (const char *)&clen, 402440008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 402540008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 402630300Sjoerg sp->myauth.name, 402730300Sjoerg 0); 402830300Sjoerg} 402970199Sjhay 403070199Sjhay/* 403130300Sjoerg *--------------------------------------------------------------------------* 403230300Sjoerg * * 403330300Sjoerg * The PAP implementation. * 403430300Sjoerg * * 403530300Sjoerg *--------------------------------------------------------------------------* 403630300Sjoerg */ 403730300Sjoerg/* 403830300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 403930300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 404030300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 404130300Sjoerg * retry counter is expired). 404230300Sjoerg */ 404330300Sjoerg 404430300Sjoerg/* 404530300Sjoerg * Handle incoming PAP packets. */ 404630300Sjoergstatic void 404730300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 404830300Sjoerg{ 404930300Sjoerg STDDCL; 405030300Sjoerg struct lcp_header *h; 405130300Sjoerg int len, x; 405230300Sjoerg u_char *name, *passwd, mlen; 405330300Sjoerg int name_len, passwd_len; 405430300Sjoerg 405530300Sjoerg len = m->m_pkthdr.len; 405630300Sjoerg if (len < 5) { 405730300Sjoerg if (debug) 405830300Sjoerg log(LOG_DEBUG, 405940008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 406040008Sjoerg SPP_ARGS(ifp), len); 406130300Sjoerg return; 406230300Sjoerg } 406330300Sjoerg h = mtod (m, struct lcp_header*); 406430300Sjoerg if (len > ntohs (h->len)) 406530300Sjoerg len = ntohs (h->len); 406630300Sjoerg switch (h->type) { 406730300Sjoerg /* PAP request is my authproto */ 406830300Sjoerg case PAP_REQ: 406930300Sjoerg name = 1 + (u_char*)(h+1); 407030300Sjoerg name_len = name[-1]; 407130300Sjoerg passwd = name + name_len + 1; 407230300Sjoerg if (name_len > len - 6 || 407330300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 407430300Sjoerg if (debug) { 407540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 407630300Sjoerg "<%s id=0x%x len=%d", 407740008Sjoerg SPP_ARGS(ifp), 407830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 407930300Sjoerg h->ident, ntohs(h->len)); 408044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 408169211Sphk log(-1, ">\n"); 408230300Sjoerg } 408330300Sjoerg break; 408430300Sjoerg } 408530300Sjoerg if (debug) { 408640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 408730300Sjoerg "<%s id=0x%x len=%d name=", 408840008Sjoerg SPP_ARGS(ifp), 408930300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 409030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 409130300Sjoerg h->ident, ntohs(h->len)); 409230300Sjoerg sppp_print_string((char*)name, name_len); 409369211Sphk log(-1, " passwd="); 409430300Sjoerg sppp_print_string((char*)passwd, passwd_len); 409569211Sphk log(-1, ">\n"); 409630300Sjoerg } 409774774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 409874774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 409930300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 410030300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 410130300Sjoerg /* action scn, tld */ 410230300Sjoerg mlen = sizeof(FAILMSG) - 1; 410330300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 410430300Sjoerg sizeof mlen, (const char *)&mlen, 410530300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 410630300Sjoerg 0); 410730300Sjoerg pap.tld(sp); 410830300Sjoerg break; 410930300Sjoerg } 411030300Sjoerg /* action sca, perhaps tlu */ 411130300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 411230300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 411330300Sjoerg mlen = sizeof(SUCCMSG) - 1; 411430300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 411530300Sjoerg sizeof mlen, (const char *)&mlen, 411630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 411730300Sjoerg 0); 411830300Sjoerg } 411930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 412030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 412130300Sjoerg pap.tlu(sp); 412230300Sjoerg } 412330300Sjoerg break; 412430300Sjoerg 412530300Sjoerg /* ack and nak are his authproto */ 412630300Sjoerg case PAP_ACK: 412740008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 412830300Sjoerg if (debug) { 412940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 413040008Sjoerg SPP_ARGS(ifp)); 413130300Sjoerg name_len = *((char *)h); 413230300Sjoerg if (len > 5 && name_len) { 413369211Sphk log(-1, ": "); 413430300Sjoerg sppp_print_string((char*)(h+1), name_len); 413530300Sjoerg } 413669211Sphk log(-1, "\n"); 413730300Sjoerg } 413830300Sjoerg x = splimp(); 413930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 414030300Sjoerg if (sp->myauth.proto == PPP_PAP && 414132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 414230300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 414330300Sjoerg /* 414430300Sjoerg * We are authenticator for PAP but didn't 414530300Sjoerg * complete yet. Leave it to tlu to proceed 414630300Sjoerg * to network phase. 414730300Sjoerg */ 414830300Sjoerg splx(x); 414930300Sjoerg break; 415030300Sjoerg } 415130300Sjoerg splx(x); 415230300Sjoerg sppp_phase_network(sp); 415330300Sjoerg break; 415430300Sjoerg 415530300Sjoerg case PAP_NAK: 415640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 415730300Sjoerg if (debug) { 415840008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 415940008Sjoerg SPP_ARGS(ifp)); 416030300Sjoerg name_len = *((char *)h); 416130300Sjoerg if (len > 5 && name_len) { 416269211Sphk log(-1, ": "); 416330300Sjoerg sppp_print_string((char*)(h+1), name_len); 416430300Sjoerg } 416569211Sphk log(-1, "\n"); 416630300Sjoerg } else 416740008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 416840008Sjoerg SPP_ARGS(ifp)); 416930300Sjoerg /* await LCP shutdown by authenticator */ 417030300Sjoerg break; 417130300Sjoerg 417230300Sjoerg default: 417330300Sjoerg /* Unknown PAP packet type -- ignore. */ 417430300Sjoerg if (debug) { 417540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 417630300Sjoerg "<0x%x id=0x%x len=%d", 417740008Sjoerg SPP_ARGS(ifp), 417830300Sjoerg h->type, h->ident, ntohs(h->len)); 417944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 418069211Sphk log(-1, ">\n"); 418130300Sjoerg } 418230300Sjoerg break; 418330300Sjoerg 418430300Sjoerg } 418530300Sjoerg} 418630300Sjoerg 418730300Sjoergstatic void 418830300Sjoergsppp_pap_init(struct sppp *sp) 418930300Sjoerg{ 419030300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 419130300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 419230300Sjoerg sp->fail_counter[IDX_PAP] = 0; 419378064Sume sp->pp_seq[IDX_PAP] = 0; 419478064Sume sp->pp_rseq[IDX_PAP] = 0; 419542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 419630300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 419730300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 419840008Sjoerg#endif 419930300Sjoerg} 420030300Sjoerg 420130300Sjoergstatic void 420230300Sjoergsppp_pap_open(struct sppp *sp) 420330300Sjoerg{ 420430300Sjoerg if (sp->hisauth.proto == PPP_PAP && 420530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 420630300Sjoerg /* we are authenticator for PAP, start our timer */ 420730300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 420830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 420930300Sjoerg } 421030300Sjoerg if (sp->myauth.proto == PPP_PAP) { 421130300Sjoerg /* we are peer, send a request, and start a timer */ 421230300Sjoerg pap.scr(sp); 421342064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 421442064Sphk sp->pap_my_to_ch); 421530300Sjoerg } 421630300Sjoerg} 421730300Sjoerg 421830300Sjoergstatic void 421930300Sjoergsppp_pap_close(struct sppp *sp) 422030300Sjoerg{ 422130300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 422230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 422330300Sjoerg} 422430300Sjoerg 422530300Sjoerg/* 422630300Sjoerg * That's the timeout routine if we are authenticator. Since the 422730300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 422830300Sjoerg */ 422930300Sjoergstatic void 423030300Sjoergsppp_pap_TO(void *cookie) 423130300Sjoerg{ 423230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 423330300Sjoerg STDDCL; 423430300Sjoerg int s; 423530300Sjoerg 423630300Sjoerg s = splimp(); 423730300Sjoerg if (debug) 423840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 423940008Sjoerg SPP_ARGS(ifp), 424030300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 424130300Sjoerg sp->rst_counter[IDX_PAP]); 424230300Sjoerg 424330300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 424430300Sjoerg /* TO- event */ 424530300Sjoerg switch (sp->state[IDX_PAP]) { 424630300Sjoerg case STATE_REQ_SENT: 424730300Sjoerg pap.tld(sp); 424830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 424930300Sjoerg break; 425030300Sjoerg } 425130300Sjoerg else 425230300Sjoerg /* TO+ event, not very much we could do */ 425330300Sjoerg switch (sp->state[IDX_PAP]) { 425430300Sjoerg case STATE_REQ_SENT: 425530300Sjoerg /* sppp_cp_change_state() will restart the timer */ 425630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 425730300Sjoerg break; 425830300Sjoerg } 425930300Sjoerg 426030300Sjoerg splx(s); 426130300Sjoerg} 426230300Sjoerg 426330300Sjoerg/* 426430300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 426530300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 426630300Sjoerg * XXX We should impose a max counter. 426730300Sjoerg */ 426830300Sjoergstatic void 426930300Sjoergsppp_pap_my_TO(void *cookie) 427030300Sjoerg{ 427130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 427230300Sjoerg STDDCL; 427330300Sjoerg 427430300Sjoerg if (debug) 427540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 427640008Sjoerg SPP_ARGS(ifp)); 427730300Sjoerg 427830300Sjoerg pap.scr(sp); 427930300Sjoerg} 428030300Sjoerg 428130300Sjoergstatic void 428230300Sjoergsppp_pap_tlu(struct sppp *sp) 428330300Sjoerg{ 428430300Sjoerg STDDCL; 428530300Sjoerg int x; 428630300Sjoerg 428730300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 428830300Sjoerg 428930300Sjoerg if (debug) 429040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 429140008Sjoerg SPP_ARGS(ifp), pap.name); 429230300Sjoerg 429330300Sjoerg x = splimp(); 429430300Sjoerg /* indicate to LCP that we need to be closed down */ 429530300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 429630300Sjoerg 429730300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 429830300Sjoerg /* 429930300Sjoerg * Remote is authenticator, but his auth proto didn't 430030300Sjoerg * complete yet. Defer the transition to network 430130300Sjoerg * phase. 430230300Sjoerg */ 430330300Sjoerg splx(x); 430430300Sjoerg return; 430530300Sjoerg } 430630300Sjoerg splx(x); 430730300Sjoerg sppp_phase_network(sp); 430830300Sjoerg} 430930300Sjoerg 431030300Sjoergstatic void 431130300Sjoergsppp_pap_tld(struct sppp *sp) 431230300Sjoerg{ 431330300Sjoerg STDDCL; 431430300Sjoerg 431530300Sjoerg if (debug) 431640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 431740008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 431840008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 431930300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 432030300Sjoerg 432130300Sjoerg lcp.Close(sp); 432230300Sjoerg} 432330300Sjoerg 432430300Sjoergstatic void 432530300Sjoergsppp_pap_scr(struct sppp *sp) 432630300Sjoerg{ 432730300Sjoerg u_char idlen, pwdlen; 432830300Sjoerg 432978064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 433030300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 433130300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 433230300Sjoerg 433330300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 433430300Sjoerg sizeof idlen, (const char *)&idlen, 433540008Sjoerg (size_t)idlen, sp->myauth.name, 433630300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 433740008Sjoerg (size_t)pwdlen, sp->myauth.secret, 433830300Sjoerg 0); 433930300Sjoerg} 434070199Sjhay 434170199Sjhay/* 434225944Sjoerg * Random miscellaneous functions. 434325944Sjoerg */ 434425944Sjoerg 43454910Swollman/* 434630300Sjoerg * Send a PAP or CHAP proto packet. 434730300Sjoerg * 434830300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 434940008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 435030300Sjoerg * mlen == 0. 435142104Sphk * NOTE: never declare variadic functions with types subject to type 435242104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 435342104Sphk * on the architecture you are on... 435430300Sjoerg */ 435530300Sjoerg 435630300Sjoergstatic void 435742104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 435842104Sphk unsigned int type, unsigned int id, 435930300Sjoerg ...) 436030300Sjoerg{ 436130300Sjoerg STDDCL; 436230300Sjoerg struct ppp_header *h; 436330300Sjoerg struct lcp_header *lh; 436430300Sjoerg struct mbuf *m; 436530300Sjoerg u_char *p; 436630300Sjoerg int len; 436742104Sphk unsigned int mlen; 436830300Sjoerg const char *msg; 436930300Sjoerg va_list ap; 437030300Sjoerg 437130300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 437230300Sjoerg if (! m) 437330300Sjoerg return; 437430300Sjoerg m->m_pkthdr.rcvif = 0; 437530300Sjoerg 437630300Sjoerg h = mtod (m, struct ppp_header*); 437730300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 437830300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 437930300Sjoerg h->protocol = htons(cp->proto); 438030300Sjoerg 438130300Sjoerg lh = (struct lcp_header*)(h + 1); 438230300Sjoerg lh->type = type; 438330300Sjoerg lh->ident = id; 438430300Sjoerg p = (u_char*) (lh+1); 438530300Sjoerg 438630300Sjoerg va_start(ap, id); 438730300Sjoerg len = 0; 438830300Sjoerg 438942104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 439030300Sjoerg msg = va_arg(ap, const char *); 439130300Sjoerg len += mlen; 439230300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 439330300Sjoerg va_end(ap); 439430300Sjoerg m_freem(m); 439530300Sjoerg return; 439630300Sjoerg } 439730300Sjoerg 439830300Sjoerg bcopy(msg, p, mlen); 439930300Sjoerg p += mlen; 440030300Sjoerg } 440130300Sjoerg va_end(ap); 440230300Sjoerg 440330300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 440430300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 440530300Sjoerg 440630300Sjoerg if (debug) { 440740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 440840008Sjoerg SPP_ARGS(ifp), cp->name, 440930300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 441030300Sjoerg lh->ident, ntohs(lh->len)); 441144145Sphk sppp_print_bytes((u_char*) (lh+1), len); 441269211Sphk log(-1, ">\n"); 441330300Sjoerg } 441469152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 441569152Sjlemon ifp->if_oerrors++; 441630300Sjoerg} 441730300Sjoerg 441830300Sjoerg/* 441925944Sjoerg * Flush interface queue. 44204910Swollman */ 442112820Sphkstatic void 442225944Sjoergsppp_qflush(struct ifqueue *ifq) 44234910Swollman{ 442425944Sjoerg struct mbuf *m, *n; 44254910Swollman 442625944Sjoerg n = ifq->ifq_head; 442725944Sjoerg while ((m = n)) { 442825944Sjoerg n = m->m_act; 442925944Sjoerg m_freem (m); 443011189Sjkh } 443125944Sjoerg ifq->ifq_head = 0; 443225944Sjoerg ifq->ifq_tail = 0; 443325944Sjoerg ifq->ifq_len = 0; 443425944Sjoerg} 443525944Sjoerg 443625944Sjoerg/* 443725944Sjoerg * Send keepalive packets, every 10 seconds. 443825944Sjoerg */ 443925944Sjoergstatic void 444025944Sjoergsppp_keepalive(void *dummy) 444125944Sjoerg{ 444225944Sjoerg struct sppp *sp; 444325944Sjoerg int s; 444425944Sjoerg 444525944Sjoerg s = splimp(); 444625944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 444725944Sjoerg struct ifnet *ifp = &sp->pp_if; 444825944Sjoerg 444925944Sjoerg /* Keepalive mode disabled or channel down? */ 445025944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 445125944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 445225944Sjoerg continue; 445325944Sjoerg 445425944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 445545152Sphk if (sp->pp_mode != IFF_CISCO && 445625944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 445725944Sjoerg continue; 445825944Sjoerg 445925944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 446025944Sjoerg /* No keepalive packets got. Stop the interface. */ 446140008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 446225944Sjoerg if_down (ifp); 446326018Sjoerg sppp_qflush (&sp->pp_cpq); 446445152Sphk if (sp->pp_mode != IFF_CISCO) { 446525944Sjoerg /* XXX */ 446625944Sjoerg /* Shut down the PPP link. */ 446725944Sjoerg lcp.Down(sp); 446825944Sjoerg /* Initiate negotiation. XXX */ 446925944Sjoerg lcp.Up(sp); 447025944Sjoerg } 44714910Swollman } 447225944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 447325944Sjoerg ++sp->pp_alivecnt; 447445152Sphk if (sp->pp_mode == IFF_CISCO) 447578064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 447678064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 447725944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 447825944Sjoerg long nmagic = htonl (sp->lcp.magic); 447978064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 448025944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 448125944Sjoerg sp->lcp.echoid, 4, &nmagic); 448225944Sjoerg } 44834910Swollman } 448425944Sjoerg splx(s); 448542064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 44864910Swollman} 44874910Swollman 448825944Sjoerg/* 448925944Sjoerg * Get both IP addresses. 449025944Sjoerg */ 449125944Sjoergstatic void 449230300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 449325944Sjoerg{ 449425944Sjoerg struct ifnet *ifp = &sp->pp_if; 449525944Sjoerg struct ifaddr *ifa; 449630300Sjoerg struct sockaddr_in *si, *sm; 449725944Sjoerg u_long ssrc, ddst; 449825944Sjoerg 449940010Sjoerg sm = NULL; 450025944Sjoerg ssrc = ddst = 0L; 450125944Sjoerg /* 450225944Sjoerg * Pick the first AF_INET address from the list, 450325944Sjoerg * aliases don't make any sense on a p2p link anyway. 450425944Sjoerg */ 450542065Sphk si = 0; 450642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 450742065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 450842104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 450971959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 451040008Sjoerg ifa; 451171959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 451242104Sphk#else 451342104Sphk for (ifa = ifp->if_addrlist; 451442104Sphk ifa; 451542104Sphk ifa = ifa->ifa_next) 451640008Sjoerg#endif 451725944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 451825944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 451930300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 452025944Sjoerg if (si) 452125944Sjoerg break; 452225944Sjoerg } 452325944Sjoerg if (ifa) { 452430300Sjoerg if (si && si->sin_addr.s_addr) { 452525944Sjoerg ssrc = si->sin_addr.s_addr; 452630300Sjoerg if (srcmask) 452730300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 452830300Sjoerg } 452925944Sjoerg 453025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 453125944Sjoerg if (si && si->sin_addr.s_addr) 453225944Sjoerg ddst = si->sin_addr.s_addr; 453325944Sjoerg } 453425944Sjoerg 453525944Sjoerg if (dst) *dst = ntohl(ddst); 453625944Sjoerg if (src) *src = ntohl(ssrc); 453725944Sjoerg} 453825944Sjoerg 453925944Sjoerg/* 454025944Sjoerg * Set my IP address. Must be called at splimp. 454125944Sjoerg */ 454225944Sjoergstatic void 454325944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 454425944Sjoerg{ 454542104Sphk STDDCL; 454625944Sjoerg struct ifaddr *ifa; 454725944Sjoerg struct sockaddr_in *si; 454825944Sjoerg 454925944Sjoerg /* 455025944Sjoerg * Pick the first AF_INET address from the list, 455125944Sjoerg * aliases don't make any sense on a p2p link anyway. 455225944Sjoerg */ 455342065Sphk si = 0; 455442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 455542065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 455642104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 455771959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 455840008Sjoerg ifa; 455971959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 456042104Sphk#else 456142104Sphk for (ifa = ifp->if_addrlist; 456242104Sphk ifa; 456342104Sphk ifa = ifa->ifa_next) 456440008Sjoerg#endif 456540008Sjoerg { 456640008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 456740008Sjoerg { 456825944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 456925944Sjoerg if (si) 457025944Sjoerg break; 457125944Sjoerg } 457240008Sjoerg } 457340008Sjoerg 457425944Sjoerg if (ifa && si) 457542104Sphk { 457642104Sphk int error; 457742104Sphk#if __NetBSD_Version__ >= 103080000 457842104Sphk struct sockaddr_in new_sin = *si; 457942104Sphk 458042104Sphk new_sin.sin_addr.s_addr = htonl(src); 458142104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 458242104Sphk if(debug && error) 458342104Sphk { 458442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 458542104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 458642104Sphk } 458742104Sphk#else 458842104Sphk /* delete old route */ 458942104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 459042104Sphk if(debug && error) 459142104Sphk { 459242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 459342104Sphk SPP_ARGS(ifp), error); 459442104Sphk } 459542104Sphk 459642104Sphk /* set new address */ 459725944Sjoerg si->sin_addr.s_addr = htonl(src); 459825944Sjoerg 459942104Sphk /* add new route */ 460070199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 460142104Sphk if (debug && error) 460242104Sphk { 460342104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 460442104Sphk SPP_ARGS(ifp), error); 460542104Sphk } 460642104Sphk#endif 460742104Sphk } 460878064Sume} 460978064Sume 461078064Sume#ifdef INET6 461178064Sume/* 461278064Sume * Get both IPv6 addresses. 461378064Sume */ 461478064Sumestatic void 461578064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 461678064Sume struct in6_addr *srcmask) 461778064Sume{ 461878064Sume struct ifnet *ifp = &sp->pp_if; 461978064Sume struct ifaddr *ifa; 462078064Sume struct sockaddr_in6 *si, *sm; 462178064Sume struct in6_addr ssrc, ddst; 462278064Sume 462378064Sume sm = NULL; 462478064Sume bzero(&ssrc, sizeof(ssrc)); 462578064Sume bzero(&ddst, sizeof(ddst)); 462678064Sume /* 462778064Sume * Pick the first link-local AF_INET6 address from the list, 462878064Sume * aliases don't make any sense on a p2p link anyway. 462978064Sume */ 463078064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 463178064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 463278064Sume ifa; 463378064Sume ifa = ifa->ifa_link.tqe_next) 463478064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 463578064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 463678064Sume ifa; 463778064Sume ifa = ifa->ifa_list.tqe_next) 463878064Sume#else 463978064Sume for (ifa = ifp->if_addrlist, si = 0; 464078064Sume ifa; 464178064Sume ifa = ifa->ifa_next) 464278064Sume#endif 464378064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 464478064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 464578064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 464678064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 464778064Sume break; 464878064Sume } 464978064Sume if (ifa) { 465078064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 465178064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 465278064Sume if (srcmask) { 465378064Sume bcopy(&sm->sin6_addr, srcmask, 465478064Sume sizeof(*srcmask)); 465578064Sume } 465678064Sume } 465778064Sume 465878064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 465978064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 466078064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 466178064Sume } 466278064Sume 466378064Sume if (dst) 466478064Sume bcopy(&ddst, dst, sizeof(*dst)); 466578064Sume if (src) 466678064Sume bcopy(&ssrc, src, sizeof(*src)); 466770199Sjhay} 466842104Sphk 466978064Sume#ifdef IPV6CP_MYIFID_DYN 467078064Sume/* 467178064Sume * Generate random ifid. 467278064Sume */ 467378064Sumestatic void 467478064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 467578064Sume{ 467678064Sume /* TBD */ 467778064Sume} 467878064Sume 467978064Sume/* 468078064Sume * Set my IPv6 address. Must be called at splimp. 468178064Sume */ 468278064Sumestatic void 468378064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 468478064Sume{ 468578064Sume STDDCL; 468678064Sume struct ifaddr *ifa; 468778064Sume struct sockaddr_in6 *sin6; 468878064Sume 468978064Sume /* 469078064Sume * Pick the first link-local AF_INET6 address from the list, 469178064Sume * aliases don't make any sense on a p2p link anyway. 469278064Sume */ 469378064Sume 469478064Sume sin6 = NULL; 469578064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 469678064Sume for (ifa = ifp->if_addrhead.tqh_first; 469778064Sume ifa; 469878064Sume ifa = ifa->ifa_link.tqe_next) 469978064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 470078064Sume for (ifa = ifp->if_addrlist.tqh_first; 470178064Sume ifa; 470278064Sume ifa = ifa->ifa_list.tqe_next) 470378064Sume#else 470478064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 470578064Sume#endif 470678064Sume { 470778064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 470878064Sume { 470978064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 471078064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 471178064Sume break; 471278064Sume } 471378064Sume } 471478064Sume 471578064Sume if (ifa && sin6) 471678064Sume { 471778064Sume int error; 471878064Sume struct sockaddr_in6 new_sin6 = *sin6; 471978064Sume 472078064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 472178064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 472278064Sume if (debug && error) 472378064Sume { 472478064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 472578064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 472678064Sume } 472778064Sume } 472878064Sume} 472978064Sume#endif 473078064Sume 473178064Sume/* 473278064Sume * Suggest a candidate address to be used by peer. 473378064Sume */ 473478064Sumestatic void 473578064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 473678064Sume{ 473778064Sume struct in6_addr myaddr; 473878064Sume struct timeval tv; 473978064Sume 474078064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 474178064Sume 474278064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 474378064Sume microtime(&tv); 474478064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 474578064Sume myaddr.s6_addr[14] ^= 0xff; 474678064Sume myaddr.s6_addr[15] ^= 0xff; 474778064Sume } else { 474878064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 474978064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 475078064Sume } 475178064Sume if (suggest) 475278064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 475378064Sume} 475478064Sume#endif /*INET6*/ 475578064Sume 475630300Sjoergstatic int 475738343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 475830300Sjoerg{ 475938343Sbde u_long subcmd; 476030300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 476130300Sjoerg struct spppreq spr; 476230300Sjoerg 476330300Sjoerg /* 476430300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 476530300Sjoerg * Check the cmd word first before attempting to fetch all the 476630300Sjoerg * data. 476730300Sjoerg */ 476830300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 476930300Sjoerg return EFAULT; 477030300Sjoerg 477130300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 477230300Sjoerg return EFAULT; 477330300Sjoerg 477430300Sjoerg switch (subcmd) { 477530300Sjoerg case SPPPIOGDEFS: 477630300Sjoerg if (cmd != SIOCGIFGENERIC) 477730300Sjoerg return EINVAL; 477830300Sjoerg /* 477930300Sjoerg * We copy over the entire current state, but clean 478030300Sjoerg * out some of the stuff we don't wanna pass up. 478130300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 478230300Sjoerg * called by any user. No need to ever get PAP or 478330300Sjoerg * CHAP secrets back to userland anyway. 478430300Sjoerg */ 478530300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 478630300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 478730300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 478830300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 478930300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 479030300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 479130300Sjoerg 479230300Sjoerg case SPPPIOSDEFS: 479330300Sjoerg if (cmd != SIOCSIFGENERIC) 479430300Sjoerg return EINVAL; 479530300Sjoerg /* 479630300Sjoerg * We have a very specific idea of which fields we allow 479730300Sjoerg * being passed back from userland, so to not clobber our 479830300Sjoerg * current state. For one, we only allow setting 479930300Sjoerg * anything if LCP is in dead phase. Once the LCP 480030300Sjoerg * negotiations started, the authentication settings must 480130300Sjoerg * not be changed again. (The administrator can force an 480230300Sjoerg * ifconfig down in order to get LCP back into dead 480330300Sjoerg * phase.) 480430300Sjoerg * 480530300Sjoerg * Also, we only allow for authentication parameters to be 480630300Sjoerg * specified. 480730300Sjoerg * 480830300Sjoerg * XXX Should allow to set or clear pp_flags. 480930300Sjoerg * 481030300Sjoerg * Finally, if the respective authentication protocol to 481130300Sjoerg * be used is set differently than 0, but the secret is 481230300Sjoerg * passed as all zeros, we don't trash the existing secret. 481330300Sjoerg * This allows an administrator to change the system name 481430300Sjoerg * only without clobbering the secret (which he didn't get 481530300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 481630300Sjoerg * secrets are cleared if the authentication protocol is 481730300Sjoerg * reset to 0. 481830300Sjoerg */ 481930300Sjoerg if (sp->pp_phase != PHASE_DEAD) 482030300Sjoerg return EBUSY; 482130300Sjoerg 482230300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 482330300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 482430300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 482530300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 482630300Sjoerg return EINVAL; 482730300Sjoerg 482830300Sjoerg if (spr.defs.myauth.proto == 0) 482930300Sjoerg /* resetting myauth */ 483030300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 483130300Sjoerg else { 483230300Sjoerg /* setting/changing myauth */ 483330300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 483430300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 483530300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 483630300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 483730300Sjoerg AUTHKEYLEN); 483830300Sjoerg } 483930300Sjoerg if (spr.defs.hisauth.proto == 0) 484030300Sjoerg /* resetting hisauth */ 484130300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 484230300Sjoerg else { 484330300Sjoerg /* setting/changing hisauth */ 484430300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 484530300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 484630300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 484730300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 484830300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 484930300Sjoerg AUTHKEYLEN); 485030300Sjoerg } 485130300Sjoerg break; 485230300Sjoerg 485330300Sjoerg default: 485430300Sjoerg return EINVAL; 485530300Sjoerg } 485630300Sjoerg 485730300Sjoerg return 0; 485830300Sjoerg} 485930300Sjoerg 486030300Sjoergstatic void 486130300Sjoergsppp_phase_network(struct sppp *sp) 486230300Sjoerg{ 486342066Sphk STDDCL; 486430300Sjoerg int i; 486530300Sjoerg u_long mask; 486630300Sjoerg 486730300Sjoerg sp->pp_phase = PHASE_NETWORK; 486830300Sjoerg 486942066Sphk if (debug) 487042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 487142066Sphk sppp_phase_name(sp->pp_phase)); 487230300Sjoerg 487330300Sjoerg /* Notify NCPs now. */ 487430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 487530300Sjoerg if ((cps[i])->flags & CP_NCP) 487630300Sjoerg (cps[i])->Open(sp); 487730300Sjoerg 487830300Sjoerg /* Send Up events to all NCPs. */ 487930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 488030300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 488130300Sjoerg (cps[i])->Up(sp); 488230300Sjoerg 488330300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 488430300Sjoerg sppp_lcp_check_and_close(sp); 488530300Sjoerg} 488630300Sjoerg 488770199Sjhay 488825706Sjoergstatic const char * 488925944Sjoergsppp_cp_type_name(u_char type) 48904910Swollman{ 489130300Sjoerg static char buf[12]; 48924910Swollman switch (type) { 489330300Sjoerg case CONF_REQ: return "conf-req"; 489430300Sjoerg case CONF_ACK: return "conf-ack"; 489530300Sjoerg case CONF_NAK: return "conf-nak"; 489630300Sjoerg case CONF_REJ: return "conf-rej"; 489730300Sjoerg case TERM_REQ: return "term-req"; 489830300Sjoerg case TERM_ACK: return "term-ack"; 489930300Sjoerg case CODE_REJ: return "code-rej"; 490030300Sjoerg case PROTO_REJ: return "proto-rej"; 490130300Sjoerg case ECHO_REQ: return "echo-req"; 490230300Sjoerg case ECHO_REPLY: return "echo-reply"; 490330300Sjoerg case DISC_REQ: return "discard-req"; 49044910Swollman } 490544145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 490630300Sjoerg return buf; 49074910Swollman} 49084910Swollman 490925706Sjoergstatic const char * 491030300Sjoergsppp_auth_type_name(u_short proto, u_char type) 491130300Sjoerg{ 491230300Sjoerg static char buf[12]; 491330300Sjoerg switch (proto) { 491430300Sjoerg case PPP_CHAP: 491530300Sjoerg switch (type) { 491630300Sjoerg case CHAP_CHALLENGE: return "challenge"; 491730300Sjoerg case CHAP_RESPONSE: return "response"; 491830300Sjoerg case CHAP_SUCCESS: return "success"; 491930300Sjoerg case CHAP_FAILURE: return "failure"; 492030300Sjoerg } 492130300Sjoerg case PPP_PAP: 492230300Sjoerg switch (type) { 492330300Sjoerg case PAP_REQ: return "req"; 492430300Sjoerg case PAP_ACK: return "ack"; 492530300Sjoerg case PAP_NAK: return "nak"; 492630300Sjoerg } 492730300Sjoerg } 492844145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 492930300Sjoerg return buf; 493030300Sjoerg} 493130300Sjoerg 493230300Sjoergstatic const char * 493325944Sjoergsppp_lcp_opt_name(u_char opt) 49344910Swollman{ 493530300Sjoerg static char buf[12]; 493625944Sjoerg switch (opt) { 493730300Sjoerg case LCP_OPT_MRU: return "mru"; 493830300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 493930300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 494030300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 494130300Sjoerg case LCP_OPT_MAGIC: return "magic"; 494230300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 494330300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 49444910Swollman } 494544145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 494630300Sjoerg return buf; 49474910Swollman} 49484910Swollman 494925944Sjoergstatic const char * 495025944Sjoergsppp_ipcp_opt_name(u_char opt) 495125944Sjoerg{ 495230300Sjoerg static char buf[12]; 495325944Sjoerg switch (opt) { 495430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 495530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 495630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 495725944Sjoerg } 495844145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 495930300Sjoerg return buf; 496025944Sjoerg} 496125944Sjoerg 496278064Sume#ifdef INET6 496325944Sjoergstatic const char * 496478064Sumesppp_ipv6cp_opt_name(u_char opt) 496578064Sume{ 496678064Sume static char buf[12]; 496778064Sume switch (opt) { 496878064Sume case IPV6CP_OPT_IFID: return "ifid"; 496978064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 497078064Sume } 497178064Sume sprintf (buf, "0x%x", opt); 497278064Sume return buf; 497378064Sume} 497478064Sume#endif 497578064Sume 497678064Sumestatic const char * 497725944Sjoergsppp_state_name(int state) 497825944Sjoerg{ 497925944Sjoerg switch (state) { 498025944Sjoerg case STATE_INITIAL: return "initial"; 498125944Sjoerg case STATE_STARTING: return "starting"; 498225944Sjoerg case STATE_CLOSED: return "closed"; 498325944Sjoerg case STATE_STOPPED: return "stopped"; 498425944Sjoerg case STATE_CLOSING: return "closing"; 498525944Sjoerg case STATE_STOPPING: return "stopping"; 498625944Sjoerg case STATE_REQ_SENT: return "req-sent"; 498725944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 498825944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 498925944Sjoerg case STATE_OPENED: return "opened"; 499025944Sjoerg } 499125944Sjoerg return "illegal"; 499225944Sjoerg} 499325944Sjoerg 499425944Sjoergstatic const char * 499525944Sjoergsppp_phase_name(enum ppp_phase phase) 499625944Sjoerg{ 499725944Sjoerg switch (phase) { 499825944Sjoerg case PHASE_DEAD: return "dead"; 499925944Sjoerg case PHASE_ESTABLISH: return "establish"; 500025944Sjoerg case PHASE_TERMINATE: return "terminate"; 500125944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 500225944Sjoerg case PHASE_NETWORK: return "network"; 500325944Sjoerg } 500425944Sjoerg return "illegal"; 500525944Sjoerg} 500625944Sjoerg 500725944Sjoergstatic const char * 500825944Sjoergsppp_proto_name(u_short proto) 500925944Sjoerg{ 501025944Sjoerg static char buf[12]; 501125944Sjoerg switch (proto) { 501225944Sjoerg case PPP_LCP: return "lcp"; 501325944Sjoerg case PPP_IPCP: return "ipcp"; 501430300Sjoerg case PPP_PAP: return "pap"; 501530300Sjoerg case PPP_CHAP: return "chap"; 501678064Sume case PPP_IPV6CP: return "ipv6cp"; 501725944Sjoerg } 501844145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 501925944Sjoerg return buf; 502025944Sjoerg} 502125944Sjoerg 502212820Sphkstatic void 502330300Sjoergsppp_print_bytes(const u_char *p, u_short len) 50244910Swollman{ 502544145Sphk if (len) 502669211Sphk log(-1, " %*D", len, p, "-"); 50274910Swollman} 502825944Sjoerg 502930300Sjoergstatic void 503030300Sjoergsppp_print_string(const char *p, u_short len) 503130300Sjoerg{ 503230300Sjoerg u_char c; 503330300Sjoerg 503430300Sjoerg while (len-- > 0) { 503530300Sjoerg c = *p++; 503630300Sjoerg /* 503730300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 503830300Sjoerg * using only them, but we don't rely on it. */ 503930300Sjoerg if (c < ' ' || c > '~') 504069211Sphk log(-1, "\\x%x", c); 504130300Sjoerg else 504269211Sphk log(-1, "%c", c); 504330300Sjoerg } 504430300Sjoerg} 504530300Sjoerg 504630300Sjoergstatic const char * 504730300Sjoergsppp_dotted_quad(u_long addr) 504830300Sjoerg{ 504930300Sjoerg static char s[16]; 505030300Sjoerg sprintf(s, "%d.%d.%d.%d", 505140008Sjoerg (int)((addr >> 24) & 0xff), 505240008Sjoerg (int)((addr >> 16) & 0xff), 505340008Sjoerg (int)((addr >> 8) & 0xff), 505438372Sbde (int)(addr & 0xff)); 505530300Sjoerg return s; 505630300Sjoerg} 505730300Sjoerg 505830300Sjoergstatic int 505930300Sjoergsppp_strnlen(u_char *p, int max) 506030300Sjoerg{ 506130300Sjoerg int len; 506230300Sjoerg 506330300Sjoerg for (len = 0; len < max && *p; ++p) 506430300Sjoerg ++len; 506530300Sjoerg return len; 506630300Sjoerg} 506730300Sjoerg 506830300Sjoerg/* a dummy, used to drop uninteresting events */ 506930300Sjoergstatic void 507030300Sjoergsppp_null(struct sppp *unused) 507130300Sjoerg{ 507230300Sjoerg /* do just nothing */ 507330300Sjoerg} 5074