if_spppsubr.c revision 88508
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 88508 2001-12-26 22:36:59Z joerg $ 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: 102788503Sjoerg /* set the interface "up" when assigning an IP address */ 102888503Sjoerg ifp->if_flags |= IFF_UP; 102925944Sjoerg /* fall through... */ 103011189Sjkh 103125944Sjoerg case SIOCSIFFLAGS: 103225944Sjoerg going_up = ifp->if_flags & IFF_UP && 103325944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 103425944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 103525944Sjoerg ifp->if_flags & IFF_RUNNING; 103645152Sphk 103745152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 103845152Sphk if (!newmode) 103945152Sphk newmode = ifp->if_flags & IFF_AUTO; 104045152Sphk if (!newmode) 104145152Sphk newmode = ifp->if_flags & IFF_CISCO; 104245152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 104345152Sphk ifp->if_flags |= newmode; 104445152Sphk 104545152Sphk if (newmode != sp->pp_mode) { 104645152Sphk going_down = 1; 104745152Sphk if (!going_up) 104845152Sphk going_up = ifp->if_flags & IFF_RUNNING; 10494910Swollman } 10504910Swollman 105145152Sphk if (going_down) { 105270199Sjhay if (sp->pp_mode != IFF_CISCO) 105345152Sphk lcp.Close(sp); 105445152Sphk else if (sp->pp_tlf) 105545152Sphk (sp->pp_tlf)(sp); 105626018Sjoerg sppp_flush(ifp); 105725944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 105845152Sphk sp->pp_mode = newmode; 105926018Sjoerg } 10604910Swollman 106145152Sphk if (going_up) { 106270199Sjhay if (sp->pp_mode != IFF_CISCO) 106345152Sphk lcp.Close(sp); 106445152Sphk sp->pp_mode = newmode; 106545152Sphk if (sp->pp_mode == 0) { 106645152Sphk ifp->if_flags |= IFF_RUNNING; 106745152Sphk lcp.Open(sp); 106845152Sphk } 106945152Sphk if (sp->pp_mode == IFF_CISCO) { 107045152Sphk if (sp->pp_tls) 107145152Sphk (sp->pp_tls)(sp); 107245152Sphk ifp->if_flags |= IFF_RUNNING; 107345152Sphk } 107445152Sphk } 107545152Sphk 10764910Swollman break; 107711189Sjkh 107825944Sjoerg#ifdef SIOCSIFMTU 107925944Sjoerg#ifndef ifr_mtu 108025944Sjoerg#define ifr_mtu ifr_metric 108125944Sjoerg#endif 108225944Sjoerg case SIOCSIFMTU: 108325944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 108425944Sjoerg return (EINVAL); 108525944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10864910Swollman break; 108725944Sjoerg#endif 108825944Sjoerg#ifdef SLIOCSETMTU 108925944Sjoerg case SLIOCSETMTU: 109025944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 109125944Sjoerg return (EINVAL); 109225944Sjoerg ifp->if_mtu = *(short*)data; 10934910Swollman break; 109425944Sjoerg#endif 109525944Sjoerg#ifdef SIOCGIFMTU 109625944Sjoerg case SIOCGIFMTU: 109725944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 109811189Sjkh break; 109925944Sjoerg#endif 110025944Sjoerg#ifdef SLIOCGETMTU 110125944Sjoerg case SLIOCGETMTU: 110225944Sjoerg *(short*)data = ifp->if_mtu; 11034910Swollman break; 110425944Sjoerg#endif 110525944Sjoerg case SIOCADDMULTI: 110625944Sjoerg case SIOCDELMULTI: 11074910Swollman break; 110811189Sjkh 110930300Sjoerg case SIOCGIFGENERIC: 111030300Sjoerg case SIOCSIFGENERIC: 111130300Sjoerg rv = sppp_params(sp, cmd, data); 111230300Sjoerg break; 111330300Sjoerg 111425944Sjoerg default: 111530300Sjoerg rv = ENOTTY; 11164910Swollman } 111725944Sjoerg splx(s); 111830300Sjoerg return rv; 11194910Swollman} 11204910Swollman 112170199Sjhay/* 112225944Sjoerg * Cisco framing implementation. 112325944Sjoerg */ 112425944Sjoerg 11254910Swollman/* 11264910Swollman * Handle incoming Cisco keepalive protocol packets. 11274910Swollman */ 112830300Sjoergstatic void 112925706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 11304910Swollman{ 113125944Sjoerg STDDCL; 11324910Swollman struct cisco_packet *h; 113330300Sjoerg u_long me, mymask; 11344910Swollman 113527929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 113625706Sjoerg if (debug) 113725706Sjoerg log(LOG_DEBUG, 113840008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 113940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 11404910Swollman return; 11414910Swollman } 11424910Swollman h = mtod (m, struct cisco_packet*); 114325706Sjoerg if (debug) 114425706Sjoerg log(LOG_DEBUG, 114540008Sjoerg SPP_FMT "cisco input: %d bytes " 114625706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 114840008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 114940008Sjoerg (u_int)h->time0, (u_int)h->time1); 11504910Swollman switch (ntohl (h->type)) { 11514910Swollman default: 115225706Sjoerg if (debug) 115369211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 115440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 11554910Swollman break; 11564910Swollman case CISCO_ADDR_REPLY: 11574910Swollman /* Reply on address request, ignore */ 11584910Swollman break; 11594910Swollman case CISCO_KEEPALIVE_REQ: 11604910Swollman sp->pp_alivecnt = 0; 116178064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 116278064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 11634910Swollman /* Local and remote sequence numbers are equal. 11644910Swollman * Probably, the line is in loopback mode. */ 116511189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 116640008Sjoerg printf (SPP_FMT "loopback\n", 116740008Sjoerg SPP_ARGS(ifp)); 116811189Sjkh sp->pp_loopcnt = 0; 116911189Sjkh if (ifp->if_flags & IFF_UP) { 117011189Sjkh if_down (ifp); 117126018Sjoerg sppp_qflush (&sp->pp_cpq); 117211189Sjkh } 117311189Sjkh } 11744910Swollman ++sp->pp_loopcnt; 11754910Swollman 11764910Swollman /* Generate new local sequence number */ 117742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 117878064Sume sp->pp_seq[IDX_LCP] = random(); 117940008Sjoerg#else 118078064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 118140008Sjoerg#endif 118211189Sjkh break; 118311189Sjkh } 118430300Sjoerg sp->pp_loopcnt = 0; 118511189Sjkh if (! (ifp->if_flags & IFF_UP) && 118611189Sjkh (ifp->if_flags & IFF_RUNNING)) { 118730300Sjoerg if_up(ifp); 118840008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 118911189Sjkh } 11904910Swollman break; 11914910Swollman case CISCO_ADDR_REQ: 119230300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 119330300Sjoerg if (me != 0L) 119430300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11954910Swollman break; 11964910Swollman } 11974910Swollman} 11984910Swollman 11994910Swollman/* 120025944Sjoerg * Send Cisco keepalive packet. 12014910Swollman */ 120212820Sphkstatic void 120325944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 120425944Sjoerg{ 120525944Sjoerg STDDCL; 120625944Sjoerg struct ppp_header *h; 120725944Sjoerg struct cisco_packet *ch; 120825944Sjoerg struct mbuf *m; 120942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121035029Sphk struct timeval tv; 121140008Sjoerg#else 121240008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 121340008Sjoerg#endif 121425944Sjoerg 121542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121636119Sphk getmicrouptime(&tv); 121740008Sjoerg#endif 121870199Sjhay 121925944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 122025944Sjoerg if (! m) 122125944Sjoerg return; 122225944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 122325944Sjoerg m->m_pkthdr.rcvif = 0; 122425944Sjoerg 122525944Sjoerg h = mtod (m, struct ppp_header*); 122625944Sjoerg h->address = CISCO_MULTICAST; 122725944Sjoerg h->control = 0; 122825944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 122925944Sjoerg 123025944Sjoerg ch = (struct cisco_packet*) (h + 1); 123125944Sjoerg ch->type = htonl (type); 123225944Sjoerg ch->par1 = htonl (par1); 123325944Sjoerg ch->par2 = htonl (par2); 123425944Sjoerg ch->rel = -1; 123540008Sjoerg 123642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 123735029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 123835029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 123940008Sjoerg#else 124040008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 124140008Sjoerg ch->time1 = htons ((u_short) t); 124240008Sjoerg#endif 124325944Sjoerg 124425944Sjoerg if (debug) 124525944Sjoerg log(LOG_DEBUG, 124640008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 124740008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 124840008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 124925944Sjoerg 125069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 125169152Sjlemon ifp->if_oerrors++; 125225944Sjoerg} 125325944Sjoerg 125470199Sjhay/* 125525944Sjoerg * PPP protocol implementation. 125625944Sjoerg */ 125725944Sjoerg 125825944Sjoerg/* 125925944Sjoerg * Send PPP control protocol packet. 126025944Sjoerg */ 126125944Sjoergstatic void 126225706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 126325706Sjoerg u_char ident, u_short len, void *data) 12644910Swollman{ 126525944Sjoerg STDDCL; 12664910Swollman struct ppp_header *h; 12674910Swollman struct lcp_header *lh; 12684910Swollman struct mbuf *m; 12694910Swollman 12704910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 12714910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 12724910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 12734910Swollman if (! m) 12744910Swollman return; 12754910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 12764910Swollman m->m_pkthdr.rcvif = 0; 12774910Swollman 12784910Swollman h = mtod (m, struct ppp_header*); 12794910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12804910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12814910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12824910Swollman 12834910Swollman lh = (struct lcp_header*) (h + 1); 12844910Swollman lh->type = type; 12854910Swollman lh->ident = ident; 12864910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12874910Swollman if (len) 12884910Swollman bcopy (data, lh+1, len); 12894910Swollman 129025706Sjoerg if (debug) { 129140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 129240008Sjoerg SPP_ARGS(ifp), 129325944Sjoerg sppp_proto_name(proto), 129425944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 129525944Sjoerg ntohs (lh->len)); 129644145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 129769211Sphk log(-1, ">\n"); 12984910Swollman } 129969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 130069152Sjlemon ifp->if_oerrors++; 13014910Swollman} 13024910Swollman 13034910Swollman/* 130425944Sjoerg * Handle incoming PPP control protocol packets. 13054910Swollman */ 130612820Sphkstatic void 130725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13084910Swollman{ 130925944Sjoerg STDDCL; 131025944Sjoerg struct lcp_header *h; 131125944Sjoerg int len = m->m_pkthdr.len; 131225944Sjoerg int rv; 131325944Sjoerg u_char *p; 13144910Swollman 131525944Sjoerg if (len < 4) { 131625944Sjoerg if (debug) 131725944Sjoerg log(LOG_DEBUG, 131840008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 131940008Sjoerg SPP_ARGS(ifp), cp->name, len); 13204910Swollman return; 132125944Sjoerg } 132225944Sjoerg h = mtod (m, struct lcp_header*); 132325944Sjoerg if (debug) { 132425944Sjoerg log(LOG_DEBUG, 132540008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 132640008Sjoerg SPP_ARGS(ifp), cp->name, 132725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 132825944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 132944145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 133069211Sphk log(-1, ">\n"); 133125944Sjoerg } 133225944Sjoerg if (len > ntohs (h->len)) 133325944Sjoerg len = ntohs (h->len); 133430300Sjoerg p = (u_char *)(h + 1); 133525944Sjoerg switch (h->type) { 133625944Sjoerg case CONF_REQ: 133725944Sjoerg if (len < 4) { 133825944Sjoerg if (debug) 133969211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 134040008Sjoerg SPP_ARGS(ifp), cp->name, 134125944Sjoerg len); 134225944Sjoerg ++ifp->if_ierrors; 134325944Sjoerg break; 134425944Sjoerg } 134530300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 134630300Sjoerg switch (sp->state[cp->protoidx]) { 134730300Sjoerg case STATE_CLOSING: 134830300Sjoerg case STATE_STOPPING: 134930300Sjoerg return; 135030300Sjoerg case STATE_CLOSED: 135130300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 135230300Sjoerg 0, 0); 135330300Sjoerg return; 135430300Sjoerg } 135525944Sjoerg rv = (cp->RCR)(sp, h, len); 135625944Sjoerg switch (sp->state[cp->protoidx]) { 135725944Sjoerg case STATE_OPENED: 135825944Sjoerg (cp->tld)(sp); 135925944Sjoerg (cp->scr)(sp); 136025944Sjoerg /* fall through... */ 136125944Sjoerg case STATE_ACK_SENT: 136225944Sjoerg case STATE_REQ_SENT: 136370199Sjhay /* 136470199Sjhay * sppp_cp_change_state() have the side effect of 136570199Sjhay * restarting the timeouts. We want to avoid that 136670199Sjhay * if the state don't change, otherwise we won't 136770199Sjhay * ever timeout and resend a configuration request 136870199Sjhay * that got lost. 136970199Sjhay */ 137070199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 137170199Sjhay STATE_REQ_SENT)) 137270199Sjhay break; 137325944Sjoerg sppp_cp_change_state(cp, sp, rv? 137425944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 137525944Sjoerg break; 137625944Sjoerg case STATE_STOPPED: 137725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 137825944Sjoerg (cp->scr)(sp); 137925944Sjoerg sppp_cp_change_state(cp, sp, rv? 138025944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 138125944Sjoerg break; 138225944Sjoerg case STATE_ACK_RCVD: 138325944Sjoerg if (rv) { 138425944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 138525944Sjoerg if (debug) 138640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 138740008Sjoerg SPP_ARGS(ifp), 138826077Sjoerg cp->name); 138925944Sjoerg (cp->tlu)(sp); 139025944Sjoerg } else 139125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 139225944Sjoerg break; 139325944Sjoerg default: 139440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139540008Sjoerg SPP_ARGS(ifp), cp->name, 139625944Sjoerg sppp_cp_type_name(h->type), 139725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139825944Sjoerg ++ifp->if_ierrors; 139925944Sjoerg } 140025944Sjoerg break; 140125944Sjoerg case CONF_ACK: 140225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 140325944Sjoerg if (debug) 140469211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 140540008Sjoerg SPP_ARGS(ifp), cp->name, 140625944Sjoerg h->ident, sp->confid[cp->protoidx]); 140725944Sjoerg ++ifp->if_ierrors; 140825944Sjoerg break; 140925944Sjoerg } 141025944Sjoerg switch (sp->state[cp->protoidx]) { 141125944Sjoerg case STATE_CLOSED: 141225944Sjoerg case STATE_STOPPED: 141325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 141425944Sjoerg break; 141525944Sjoerg case STATE_CLOSING: 141625944Sjoerg case STATE_STOPPING: 141725944Sjoerg break; 141825944Sjoerg case STATE_REQ_SENT: 141925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 142025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 142125944Sjoerg break; 142225944Sjoerg case STATE_OPENED: 142325944Sjoerg (cp->tld)(sp); 142425944Sjoerg /* fall through */ 142525944Sjoerg case STATE_ACK_RCVD: 142625944Sjoerg (cp->scr)(sp); 142725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142825944Sjoerg break; 142925944Sjoerg case STATE_ACK_SENT: 143025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 143225944Sjoerg if (debug) 143340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 143440008Sjoerg SPP_ARGS(ifp), cp->name); 143525944Sjoerg (cp->tlu)(sp); 143625944Sjoerg break; 143725944Sjoerg default: 143840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 143940008Sjoerg SPP_ARGS(ifp), cp->name, 144025944Sjoerg sppp_cp_type_name(h->type), 144125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144225944Sjoerg ++ifp->if_ierrors; 144325944Sjoerg } 144425944Sjoerg break; 144525944Sjoerg case CONF_NAK: 144625944Sjoerg case CONF_REJ: 144725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 144825944Sjoerg if (debug) 144969211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 145040008Sjoerg SPP_ARGS(ifp), cp->name, 145125944Sjoerg h->ident, sp->confid[cp->protoidx]); 145225944Sjoerg ++ifp->if_ierrors; 145325944Sjoerg break; 145425944Sjoerg } 145525944Sjoerg if (h->type == CONF_NAK) 145625944Sjoerg (cp->RCN_nak)(sp, h, len); 145725944Sjoerg else /* CONF_REJ */ 145825944Sjoerg (cp->RCN_rej)(sp, h, len); 14594910Swollman 146025944Sjoerg switch (sp->state[cp->protoidx]) { 146125944Sjoerg case STATE_CLOSED: 146225944Sjoerg case STATE_STOPPED: 146325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 146425944Sjoerg break; 146525944Sjoerg case STATE_REQ_SENT: 146625944Sjoerg case STATE_ACK_SENT: 146725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 146870199Sjhay /* 146970199Sjhay * Slow things down a bit if we think we might be 147070199Sjhay * in loopback. Depend on the timeout to send the 147170199Sjhay * next configuration request. 147270199Sjhay */ 147370199Sjhay if (sp->pp_loopcnt) 147470199Sjhay break; 147525944Sjoerg (cp->scr)(sp); 147625944Sjoerg break; 147725944Sjoerg case STATE_OPENED: 147825944Sjoerg (cp->tld)(sp); 147925944Sjoerg /* fall through */ 148025944Sjoerg case STATE_ACK_RCVD: 148152633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148225944Sjoerg (cp->scr)(sp); 148325944Sjoerg break; 148425944Sjoerg case STATE_CLOSING: 148525944Sjoerg case STATE_STOPPING: 148625944Sjoerg break; 148725944Sjoerg default: 148840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 148940008Sjoerg SPP_ARGS(ifp), cp->name, 149025944Sjoerg sppp_cp_type_name(h->type), 149125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149225944Sjoerg ++ifp->if_ierrors; 149325944Sjoerg } 149425944Sjoerg break; 14954910Swollman 149625944Sjoerg case TERM_REQ: 149725944Sjoerg switch (sp->state[cp->protoidx]) { 149825944Sjoerg case STATE_ACK_RCVD: 149925944Sjoerg case STATE_ACK_SENT: 150025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 150125944Sjoerg /* fall through */ 150225944Sjoerg case STATE_CLOSED: 150325944Sjoerg case STATE_STOPPED: 150425944Sjoerg case STATE_CLOSING: 150525944Sjoerg case STATE_STOPPING: 150625944Sjoerg case STATE_REQ_SENT: 150725944Sjoerg sta: 150825944Sjoerg /* Send Terminate-Ack packet. */ 150925944Sjoerg if (debug) 151040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 151140008Sjoerg SPP_ARGS(ifp), cp->name); 151225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 151325944Sjoerg break; 151425944Sjoerg case STATE_OPENED: 151525944Sjoerg (cp->tld)(sp); 151625944Sjoerg sp->rst_counter[cp->protoidx] = 0; 151725944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 151825944Sjoerg goto sta; 151925944Sjoerg break; 152025944Sjoerg default: 152140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 152240008Sjoerg SPP_ARGS(ifp), cp->name, 152325944Sjoerg sppp_cp_type_name(h->type), 152425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152525944Sjoerg ++ifp->if_ierrors; 152625944Sjoerg } 152725944Sjoerg break; 152825944Sjoerg case TERM_ACK: 152925944Sjoerg switch (sp->state[cp->protoidx]) { 153025944Sjoerg case STATE_CLOSED: 153125944Sjoerg case STATE_STOPPED: 153225944Sjoerg case STATE_REQ_SENT: 153325944Sjoerg case STATE_ACK_SENT: 153425944Sjoerg break; 153525944Sjoerg case STATE_CLOSING: 153641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 153725944Sjoerg (cp->tlf)(sp); 153825944Sjoerg break; 153925944Sjoerg case STATE_STOPPING: 154041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 154125944Sjoerg (cp->tlf)(sp); 154225944Sjoerg break; 154325944Sjoerg case STATE_ACK_RCVD: 154425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154525944Sjoerg break; 154625944Sjoerg case STATE_OPENED: 154725944Sjoerg (cp->tld)(sp); 154825944Sjoerg (cp->scr)(sp); 154925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 155025944Sjoerg break; 155125944Sjoerg default: 155240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 155340008Sjoerg SPP_ARGS(ifp), cp->name, 155425944Sjoerg sppp_cp_type_name(h->type), 155525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155625944Sjoerg ++ifp->if_ierrors; 155725944Sjoerg } 155825944Sjoerg break; 155925944Sjoerg case CODE_REJ: 156025944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 156130300Sjoerg log(LOG_INFO, 156240008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 156330300Sjoerg "danger will robinson\n", 156440008Sjoerg SPP_ARGS(ifp), cp->name, 156530300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 156625944Sjoerg switch (sp->state[cp->protoidx]) { 156725944Sjoerg case STATE_CLOSED: 156825944Sjoerg case STATE_STOPPED: 156925944Sjoerg case STATE_REQ_SENT: 157025944Sjoerg case STATE_ACK_SENT: 157125944Sjoerg case STATE_CLOSING: 157225944Sjoerg case STATE_STOPPING: 157325944Sjoerg case STATE_OPENED: 157425944Sjoerg break; 157525944Sjoerg case STATE_ACK_RCVD: 157625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 157725944Sjoerg break; 157825944Sjoerg default: 157940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 158040008Sjoerg SPP_ARGS(ifp), cp->name, 158125944Sjoerg sppp_cp_type_name(h->type), 158225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158325944Sjoerg ++ifp->if_ierrors; 158425944Sjoerg } 158525944Sjoerg break; 158680715Sume case PROTO_REJ: 158780715Sume { 158880715Sume int catastrophic; 158980715Sume const struct cp *upper; 159080715Sume int i; 159180715Sume u_int16_t proto; 159280715Sume 159380715Sume catastrophic = 0; 159480715Sume upper = NULL; 159580715Sume proto = ntohs(*((u_int16_t *)p)); 159680715Sume for (i = 0; i < IDX_COUNT; i++) { 159780715Sume if (cps[i]->proto == proto) { 159880715Sume upper = cps[i]; 159980715Sume break; 160080715Sume } 160180715Sume } 160280715Sume if (upper == NULL) 160380715Sume catastrophic++; 160480715Sume 160588508Sjoerg if (catastrophic || debug) 160688508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 160788508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 160888508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 160988508Sjoerg sppp_cp_type_name(h->type), proto, 161088508Sjoerg upper ? upper->name : "unknown", 161188508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 161280715Sume 161380715Sume /* 161480715Sume * if we got RXJ+ against conf-req, the peer does not implement 161580715Sume * this particular protocol type. terminate the protocol. 161680715Sume */ 161780715Sume if (upper && !catastrophic) { 161880715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 161980715Sume upper->Close(sp); 162080715Sume break; 162180715Sume } 162280715Sume } 162380715Sume 162480715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 162580715Sume switch (sp->state[cp->protoidx]) { 162680715Sume case STATE_CLOSED: 162780715Sume case STATE_STOPPED: 162880715Sume case STATE_REQ_SENT: 162980715Sume case STATE_ACK_SENT: 163080715Sume case STATE_CLOSING: 163180715Sume case STATE_STOPPING: 163280715Sume case STATE_OPENED: 163380715Sume break; 163480715Sume case STATE_ACK_RCVD: 163580715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 163680715Sume break; 163780715Sume default: 163880715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 163980715Sume SPP_ARGS(ifp), cp->name, 164080715Sume sppp_cp_type_name(h->type), 164180715Sume sppp_state_name(sp->state[cp->protoidx])); 164280715Sume ++ifp->if_ierrors; 164380715Sume } 164480715Sume break; 164580715Sume } 164625944Sjoerg case DISC_REQ: 164725944Sjoerg if (cp->proto != PPP_LCP) 164825944Sjoerg goto illegal; 164925944Sjoerg /* Discard the packet. */ 165025944Sjoerg break; 165125944Sjoerg case ECHO_REQ: 165225944Sjoerg if (cp->proto != PPP_LCP) 165325944Sjoerg goto illegal; 165425944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 165525944Sjoerg if (debug) 165669211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 165740008Sjoerg SPP_ARGS(ifp)); 165825944Sjoerg ++ifp->if_ierrors; 165925944Sjoerg break; 166025944Sjoerg } 166125944Sjoerg if (len < 8) { 166225944Sjoerg if (debug) 166369211Sphk log(-1, SPP_FMT "invalid lcp echo request " 166425944Sjoerg "packet length: %d bytes\n", 166540008Sjoerg SPP_ARGS(ifp), len); 166625944Sjoerg break; 166725944Sjoerg } 166844145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 166944145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 167025944Sjoerg /* Line loopback mode detected. */ 167140008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 167270199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 167325944Sjoerg if_down (ifp); 167426018Sjoerg sppp_qflush (&sp->pp_cpq); 16754910Swollman 167625944Sjoerg /* Shut down the PPP link. */ 167725944Sjoerg /* XXX */ 167825944Sjoerg lcp.Down(sp); 167925944Sjoerg lcp.Up(sp); 168025944Sjoerg break; 168125944Sjoerg } 168225944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 168325944Sjoerg if (debug) 168469211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 168540008Sjoerg SPP_ARGS(ifp)); 168625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 168725944Sjoerg break; 168825944Sjoerg case ECHO_REPLY: 168925944Sjoerg if (cp->proto != PPP_LCP) 169025944Sjoerg goto illegal; 169125944Sjoerg if (h->ident != sp->lcp.echoid) { 169225944Sjoerg ++ifp->if_ierrors; 169325944Sjoerg break; 169425944Sjoerg } 169525944Sjoerg if (len < 8) { 169625944Sjoerg if (debug) 169769211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 169825944Sjoerg "packet length: %d bytes\n", 169940008Sjoerg SPP_ARGS(ifp), len); 170025944Sjoerg break; 170125944Sjoerg } 170225944Sjoerg if (debug) 170369211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 170440008Sjoerg SPP_ARGS(ifp)); 170544145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 170644145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 170725944Sjoerg sp->pp_alivecnt = 0; 170825944Sjoerg break; 170925944Sjoerg default: 171025944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 171125944Sjoerg illegal: 171225944Sjoerg if (debug) 171369211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 171440008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 171578064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 171678064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 171725944Sjoerg ++ifp->if_ierrors; 171825944Sjoerg } 17194910Swollman} 17204910Swollman 172125944Sjoerg 17224910Swollman/* 172325944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 172425944Sjoerg * Basically, the state transition handling in the automaton. 17254910Swollman */ 172625944Sjoergstatic void 172725944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 17284910Swollman{ 172925944Sjoerg STDDCL; 17304910Swollman 173125944Sjoerg if (debug) 173240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 173340008Sjoerg SPP_ARGS(ifp), cp->name, 173425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 173525944Sjoerg 173625944Sjoerg switch (sp->state[cp->protoidx]) { 173725944Sjoerg case STATE_INITIAL: 173825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 173925944Sjoerg break; 174025944Sjoerg case STATE_STARTING: 174125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 174225944Sjoerg (cp->scr)(sp); 174325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174425944Sjoerg break; 17454910Swollman default: 174640008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 174740008Sjoerg SPP_ARGS(ifp), cp->name, 174825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 174925944Sjoerg } 175025944Sjoerg} 17514910Swollman 175225944Sjoergstatic void 175325944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 175425944Sjoerg{ 175525944Sjoerg STDDCL; 175625944Sjoerg 175725944Sjoerg if (debug) 175840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 175940008Sjoerg SPP_ARGS(ifp), cp->name, 176025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 176125944Sjoerg 176225944Sjoerg switch (sp->state[cp->protoidx]) { 176325944Sjoerg case STATE_CLOSED: 176425944Sjoerg case STATE_CLOSING: 176525944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 17664910Swollman break; 176725944Sjoerg case STATE_STOPPED: 176841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 176925944Sjoerg (cp->tls)(sp); 177041881Sphk break; 177125944Sjoerg case STATE_STOPPING: 177225944Sjoerg case STATE_REQ_SENT: 177325944Sjoerg case STATE_ACK_RCVD: 177425944Sjoerg case STATE_ACK_SENT: 177525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 177625944Sjoerg break; 177725944Sjoerg case STATE_OPENED: 177825944Sjoerg (cp->tld)(sp); 177925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 178025944Sjoerg break; 178125944Sjoerg default: 178240008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 178340008Sjoerg SPP_ARGS(ifp), cp->name, 178425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 178525944Sjoerg } 178625944Sjoerg} 17874910Swollman 178811189Sjkh 178925944Sjoergstatic void 179025944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 179125944Sjoerg{ 179225944Sjoerg STDDCL; 179325944Sjoerg 179425944Sjoerg if (debug) 179540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 179640008Sjoerg SPP_ARGS(ifp), cp->name, 179725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 179825944Sjoerg 179925944Sjoerg switch (sp->state[cp->protoidx]) { 180025944Sjoerg case STATE_INITIAL: 180141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 180225944Sjoerg (cp->tls)(sp); 18034910Swollman break; 180425944Sjoerg case STATE_STARTING: 180525944Sjoerg break; 180625944Sjoerg case STATE_CLOSED: 180725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 180825944Sjoerg (cp->scr)(sp); 180925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 181025944Sjoerg break; 181125944Sjoerg case STATE_STOPPED: 181274703Sjoerg /* 181374703Sjoerg * Try escaping stopped state. This seems to bite 181474703Sjoerg * people occasionally, in particular for IPCP, 181574703Sjoerg * presumably following previous IPCP negotiation 181674703Sjoerg * aborts. Somehow, we must have missed a Down event 181774703Sjoerg * which would have caused a transition into starting 181874703Sjoerg * state, so as a bandaid we force the Down event now. 181974703Sjoerg * This effectively implements (something like the) 182074703Sjoerg * `restart' option mentioned in the state transition 182174703Sjoerg * table of RFC 1661. 182274703Sjoerg */ 182374703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 182474703Sjoerg (cp->tls)(sp); 182574703Sjoerg break; 182625944Sjoerg case STATE_STOPPING: 182725944Sjoerg case STATE_REQ_SENT: 182825944Sjoerg case STATE_ACK_RCVD: 182925944Sjoerg case STATE_ACK_SENT: 183025944Sjoerg case STATE_OPENED: 183125944Sjoerg break; 183225944Sjoerg case STATE_CLOSING: 183325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 183425944Sjoerg break; 183525944Sjoerg } 183625944Sjoerg} 18374910Swollman 183825944Sjoerg 183925944Sjoergstatic void 184025944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 184125944Sjoerg{ 184225944Sjoerg STDDCL; 184325944Sjoerg 184425944Sjoerg if (debug) 184540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 184640008Sjoerg SPP_ARGS(ifp), cp->name, 184725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 184825944Sjoerg 184925944Sjoerg switch (sp->state[cp->protoidx]) { 185025944Sjoerg case STATE_INITIAL: 185125944Sjoerg case STATE_CLOSED: 185225944Sjoerg case STATE_CLOSING: 18534910Swollman break; 185425944Sjoerg case STATE_STARTING: 185541881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 185625944Sjoerg (cp->tlf)(sp); 18574910Swollman break; 185825944Sjoerg case STATE_STOPPED: 185925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 18604910Swollman break; 186125944Sjoerg case STATE_STOPPING: 186225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18634910Swollman break; 186425944Sjoerg case STATE_OPENED: 186525944Sjoerg (cp->tld)(sp); 186625944Sjoerg /* fall through */ 186725944Sjoerg case STATE_REQ_SENT: 186825944Sjoerg case STATE_ACK_RCVD: 186925944Sjoerg case STATE_ACK_SENT: 187025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 187178064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 187278064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 187325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18744910Swollman break; 18754910Swollman } 18764910Swollman} 18774910Swollman 187825944Sjoergstatic void 187925944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 188025944Sjoerg{ 188125944Sjoerg STDDCL; 188225944Sjoerg int s; 188325944Sjoerg 188425944Sjoerg s = splimp(); 188525944Sjoerg if (debug) 188640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 188740008Sjoerg SPP_ARGS(ifp), cp->name, 188825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 188925944Sjoerg sp->rst_counter[cp->protoidx]); 189025944Sjoerg 189125944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 189225944Sjoerg /* TO- event */ 189325944Sjoerg switch (sp->state[cp->protoidx]) { 189425944Sjoerg case STATE_CLOSING: 189541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 189625944Sjoerg (cp->tlf)(sp); 189725944Sjoerg break; 189825944Sjoerg case STATE_STOPPING: 189941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 190025944Sjoerg (cp->tlf)(sp); 190125944Sjoerg break; 190225944Sjoerg case STATE_REQ_SENT: 190325944Sjoerg case STATE_ACK_RCVD: 190425944Sjoerg case STATE_ACK_SENT: 190541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 190625944Sjoerg (cp->tlf)(sp); 190725944Sjoerg break; 190825944Sjoerg } 190925944Sjoerg else 191025944Sjoerg /* TO+ event */ 191125944Sjoerg switch (sp->state[cp->protoidx]) { 191225944Sjoerg case STATE_CLOSING: 191325944Sjoerg case STATE_STOPPING: 191478064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 191578064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 191670199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 191742064Sphk sp->ch[cp->protoidx]); 191825944Sjoerg break; 191925944Sjoerg case STATE_REQ_SENT: 192025944Sjoerg case STATE_ACK_RCVD: 192125944Sjoerg (cp->scr)(sp); 192225944Sjoerg /* sppp_cp_change_state() will restart the timer */ 192325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 192425944Sjoerg break; 192525944Sjoerg case STATE_ACK_SENT: 192625944Sjoerg (cp->scr)(sp); 192742064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 192842064Sphk sp->ch[cp->protoidx]); 192925944Sjoerg break; 193025944Sjoerg } 193125944Sjoerg 193225944Sjoerg splx(s); 193325944Sjoerg} 193425944Sjoerg 193511189Sjkh/* 193625944Sjoerg * Change the state of a control protocol in the state automaton. 193725944Sjoerg * Takes care of starting/stopping the restart timer. 193811189Sjkh */ 193925944Sjoergvoid 194025944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 194125944Sjoerg{ 194225944Sjoerg sp->state[cp->protoidx] = newstate; 194325944Sjoerg 194440008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 194525944Sjoerg switch (newstate) { 194625944Sjoerg case STATE_INITIAL: 194725944Sjoerg case STATE_STARTING: 194825944Sjoerg case STATE_CLOSED: 194925944Sjoerg case STATE_STOPPED: 195025944Sjoerg case STATE_OPENED: 195125944Sjoerg break; 195225944Sjoerg case STATE_CLOSING: 195325944Sjoerg case STATE_STOPPING: 195425944Sjoerg case STATE_REQ_SENT: 195525944Sjoerg case STATE_ACK_RCVD: 195625944Sjoerg case STATE_ACK_SENT: 195770199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 195842064Sphk sp->ch[cp->protoidx]); 195925944Sjoerg break; 196025944Sjoerg } 196125944Sjoerg} 196270199Sjhay 196370199Sjhay/* 196425944Sjoerg *--------------------------------------------------------------------------* 196525944Sjoerg * * 196625944Sjoerg * The LCP implementation. * 196725944Sjoerg * * 196825944Sjoerg *--------------------------------------------------------------------------* 196925944Sjoerg */ 197025944Sjoergstatic void 197125944Sjoergsppp_lcp_init(struct sppp *sp) 197225944Sjoerg{ 197325944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 197425944Sjoerg sp->lcp.magic = 0; 197525944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 197625944Sjoerg sp->fail_counter[IDX_LCP] = 0; 197778064Sume sp->pp_seq[IDX_LCP] = 0; 197878064Sume sp->pp_rseq[IDX_LCP] = 0; 197925944Sjoerg sp->lcp.protos = 0; 198025944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 198130300Sjoerg 198244145Sphk /* Note that these values are relevant for all control protocols */ 198344145Sphk sp->lcp.timeout = 3 * hz; 198425944Sjoerg sp->lcp.max_terminate = 2; 198525944Sjoerg sp->lcp.max_configure = 10; 198625944Sjoerg sp->lcp.max_failure = 10; 198742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 198830300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 198940008Sjoerg#endif 199025944Sjoerg} 199125944Sjoerg 199225944Sjoergstatic void 199325944Sjoergsppp_lcp_up(struct sppp *sp) 199425944Sjoerg{ 199525944Sjoerg STDDCL; 199625944Sjoerg 199770199Sjhay sp->pp_alivecnt = 0; 199870199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 199970199Sjhay sp->lcp.magic = 0; 200070199Sjhay sp->lcp.protos = 0; 200170199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 200225944Sjoerg /* 200375321Sjoerg * If we are authenticator, negotiate LCP_AUTH 200475321Sjoerg */ 200575321Sjoerg if (sp->hisauth.proto != 0) 200675321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 200775321Sjoerg else 200875321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 200975321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 201075321Sjoerg /* 201130300Sjoerg * If this interface is passive or dial-on-demand, and we are 201230300Sjoerg * still in Initial state, it means we've got an incoming 201330300Sjoerg * call. Activate the interface. 201425944Sjoerg */ 201525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 201625944Sjoerg if (debug) 201725944Sjoerg log(LOG_DEBUG, 201840008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 201925944Sjoerg ifp->if_flags |= IFF_RUNNING; 202030300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 202130300Sjoerg if (debug) 202269211Sphk log(-1, "(incoming call)\n"); 202330300Sjoerg sp->pp_flags |= PP_CALLIN; 202430300Sjoerg lcp.Open(sp); 202530300Sjoerg } else if (debug) 202669211Sphk log(-1, "\n"); 202725944Sjoerg } 202825944Sjoerg 202925944Sjoerg sppp_up_event(&lcp, sp); 203025944Sjoerg} 203125944Sjoerg 203225944Sjoergstatic void 203325944Sjoergsppp_lcp_down(struct sppp *sp) 203425944Sjoerg{ 203525944Sjoerg STDDCL; 203625944Sjoerg 203725944Sjoerg sppp_down_event(&lcp, sp); 203825944Sjoerg 203925944Sjoerg /* 204025944Sjoerg * If this is neither a dial-on-demand nor a passive 204125944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 204225944Sjoerg * administrator can force a redial by another ``ifconfig 204325944Sjoerg * up''. XXX For leased line operation, should we immediately 204425944Sjoerg * try to reopen the connection here? 204525944Sjoerg */ 204625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 204725944Sjoerg log(LOG_INFO, 204842066Sphk SPP_FMT "Down event, taking interface down.\n", 204940008Sjoerg SPP_ARGS(ifp)); 205025944Sjoerg if_down(ifp); 205125944Sjoerg } else { 205225944Sjoerg if (debug) 205325944Sjoerg log(LOG_DEBUG, 205440008Sjoerg SPP_FMT "Down event (carrier loss)\n", 205540008Sjoerg SPP_ARGS(ifp)); 205670199Sjhay sp->pp_flags &= ~PP_CALLIN; 205770199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 205870199Sjhay lcp.Close(sp); 205970199Sjhay ifp->if_flags &= ~IFF_RUNNING; 206025944Sjoerg } 206125944Sjoerg} 206225944Sjoerg 206325944Sjoergstatic void 206425944Sjoergsppp_lcp_open(struct sppp *sp) 206525944Sjoerg{ 206625944Sjoerg sppp_open_event(&lcp, sp); 206725944Sjoerg} 206825944Sjoerg 206925944Sjoergstatic void 207025944Sjoergsppp_lcp_close(struct sppp *sp) 207125944Sjoerg{ 207225944Sjoerg sppp_close_event(&lcp, sp); 207325944Sjoerg} 207425944Sjoerg 207525944Sjoergstatic void 207625944Sjoergsppp_lcp_TO(void *cookie) 207725944Sjoerg{ 207825944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 207925944Sjoerg} 208025944Sjoerg 208125944Sjoerg/* 208225944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 208325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 208425944Sjoerg * caused action scn. (The return value is used to make the state 208525944Sjoerg * transition decision in the state automaton.) 208625944Sjoerg */ 208712820Sphkstatic int 208825944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 20894910Swollman{ 209025944Sjoerg STDDCL; 209111189Sjkh u_char *buf, *r, *p; 209225944Sjoerg int origlen, rlen; 209325944Sjoerg u_long nmagic; 209430300Sjoerg u_short authproto; 20954910Swollman 209611189Sjkh len -= 4; 209725944Sjoerg origlen = len; 209811189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 209911189Sjkh if (! buf) 210011189Sjkh return (0); 21014910Swollman 210225706Sjoerg if (debug) 210340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 210440008Sjoerg SPP_ARGS(ifp)); 210525706Sjoerg 210625944Sjoerg /* pass 1: check for things that need to be rejected */ 210711189Sjkh p = (void*) (h+1); 210811189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 210925944Sjoerg if (debug) 211069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 211111189Sjkh switch (*p) { 211211189Sjkh case LCP_OPT_MAGIC: 211325944Sjoerg /* Magic number. */ 211470199Sjhay if (len >= 6 && p[1] == 6) 211570199Sjhay continue; 211670199Sjhay if (debug) 211770199Sjhay log(-1, "[invalid] "); 211870199Sjhay break; 211925944Sjoerg case LCP_OPT_ASYNC_MAP: 212025944Sjoerg /* Async control character map. */ 212170199Sjhay if (len >= 6 && p[1] == 6) 212225944Sjoerg continue; 212325944Sjoerg if (debug) 212469211Sphk log(-1, "[invalid] "); 212525944Sjoerg break; 212625944Sjoerg case LCP_OPT_MRU: 212725944Sjoerg /* Maximum receive unit. */ 212825944Sjoerg if (len >= 4 && p[1] == 4) 212925944Sjoerg continue; 213025944Sjoerg if (debug) 213169211Sphk log(-1, "[invalid] "); 213225944Sjoerg break; 213330300Sjoerg case LCP_OPT_AUTH_PROTO: 213430300Sjoerg if (len < 4) { 213530300Sjoerg if (debug) 213669211Sphk log(-1, "[invalid] "); 213730300Sjoerg break; 213830300Sjoerg } 213930300Sjoerg authproto = (p[2] << 8) + p[3]; 214030300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 214130300Sjoerg if (debug) 214269211Sphk log(-1, "[invalid chap len] "); 214330300Sjoerg break; 214430300Sjoerg } 214530300Sjoerg if (sp->myauth.proto == 0) { 214630300Sjoerg /* we are not configured to do auth */ 214730300Sjoerg if (debug) 214869211Sphk log(-1, "[not configured] "); 214930300Sjoerg break; 215030300Sjoerg } 215130300Sjoerg /* 215230300Sjoerg * Remote want us to authenticate, remember this, 215330300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 215430300Sjoerg * up. 215530300Sjoerg */ 215630300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 215730300Sjoerg continue; 215825944Sjoerg default: 215925944Sjoerg /* Others not supported. */ 216025944Sjoerg if (debug) 216169211Sphk log(-1, "[rej] "); 216225944Sjoerg break; 216325944Sjoerg } 216425944Sjoerg /* Add the option to rejected list. */ 216525944Sjoerg bcopy (p, r, p[1]); 216625944Sjoerg r += p[1]; 216725944Sjoerg rlen += p[1]; 216825944Sjoerg } 216925944Sjoerg if (rlen) { 217025944Sjoerg if (debug) 217169211Sphk log(-1, " send conf-rej\n"); 217225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 217325944Sjoerg return 0; 217425944Sjoerg } else if (debug) 217569211Sphk log(-1, "\n"); 217625944Sjoerg 217725944Sjoerg /* 217825944Sjoerg * pass 2: check for option values that are unacceptable and 217925944Sjoerg * thus require to be nak'ed. 218025944Sjoerg */ 218125944Sjoerg if (debug) 218240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 218340008Sjoerg SPP_ARGS(ifp)); 218425944Sjoerg 218525944Sjoerg p = (void*) (h+1); 218625944Sjoerg len = origlen; 218725944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 218825944Sjoerg if (debug) 218969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 219025944Sjoerg switch (*p) { 219125944Sjoerg case LCP_OPT_MAGIC: 219211189Sjkh /* Magic number -- extract. */ 219325944Sjoerg nmagic = (u_long)p[2] << 24 | 219425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 219525944Sjoerg if (nmagic != sp->lcp.magic) { 219670199Sjhay sp->pp_loopcnt = 0; 219725706Sjoerg if (debug) 219869211Sphk log(-1, "0x%lx ", nmagic); 219911189Sjkh continue; 220011189Sjkh } 220170199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 220269211Sphk log(-1, "[glitch] "); 220325944Sjoerg ++sp->pp_loopcnt; 220425944Sjoerg /* 220525944Sjoerg * We negate our magic here, and NAK it. If 220625944Sjoerg * we see it later in an NAK packet, we 220725944Sjoerg * suggest a new one. 220825944Sjoerg */ 220925944Sjoerg nmagic = ~sp->lcp.magic; 221025944Sjoerg /* Gonna NAK it. */ 221125944Sjoerg p[2] = nmagic >> 24; 221225944Sjoerg p[3] = nmagic >> 16; 221325944Sjoerg p[4] = nmagic >> 8; 221425944Sjoerg p[5] = nmagic; 221511189Sjkh break; 221625944Sjoerg 221711189Sjkh case LCP_OPT_ASYNC_MAP: 221888506Sjoerg /* 221988506Sjoerg * Async control character map -- just ignore it. 222088506Sjoerg * 222188506Sjoerg * Quote from RFC 1662, chapter 6: 222288506Sjoerg * To enable this functionality, synchronous PPP 222388506Sjoerg * implementations MUST always respond to the 222488506Sjoerg * Async-Control-Character-Map Configuration 222588506Sjoerg * Option with the LCP Configure-Ack. However, 222688506Sjoerg * acceptance of the Configuration Option does 222788506Sjoerg * not imply that the synchronous implementation 222888506Sjoerg * will do any ACCM mapping. Instead, all such 222988506Sjoerg * octet mapping will be performed by the 223088506Sjoerg * asynchronous-to-synchronous converter. 223188506Sjoerg */ 223288506Sjoerg continue; 223325944Sjoerg 223411189Sjkh case LCP_OPT_MRU: 223525944Sjoerg /* 223625944Sjoerg * Maximum receive unit. Always agreeable, 223725944Sjoerg * but ignored by now. 223825944Sjoerg */ 223925944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 224025706Sjoerg if (debug) 224169211Sphk log(-1, "%lu ", sp->lcp.their_mru); 224211189Sjkh continue; 224330300Sjoerg 224430300Sjoerg case LCP_OPT_AUTH_PROTO: 224530300Sjoerg authproto = (p[2] << 8) + p[3]; 224630300Sjoerg if (sp->myauth.proto != authproto) { 224730300Sjoerg /* not agreed, nak */ 224830300Sjoerg if (debug) 224969211Sphk log(-1, "[mine %s != his %s] ", 225030300Sjoerg sppp_proto_name(sp->hisauth.proto), 225130300Sjoerg sppp_proto_name(authproto)); 225230300Sjoerg p[2] = sp->myauth.proto >> 8; 225330300Sjoerg p[3] = sp->myauth.proto; 225430300Sjoerg break; 225530300Sjoerg } 225630300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 225730300Sjoerg if (debug) 225869211Sphk log(-1, "[chap not MD5] "); 225939981Sjoerg p[4] = CHAP_MD5; 226030300Sjoerg break; 226130300Sjoerg } 226230300Sjoerg continue; 226311189Sjkh } 226425944Sjoerg /* Add the option to nak'ed list. */ 226525706Sjoerg bcopy (p, r, p[1]); 226625706Sjoerg r += p[1]; 226711189Sjkh rlen += p[1]; 226812436Speter } 226925706Sjoerg if (rlen) { 227070199Sjhay /* 227170199Sjhay * Local and remote magics equal -- loopback? 227270199Sjhay */ 227370199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 227470199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 227570199Sjhay printf (SPP_FMT "loopback\n", 227670199Sjhay SPP_ARGS(ifp)); 227770199Sjhay if (ifp->if_flags & IFF_UP) { 227870199Sjhay if_down(ifp); 227970199Sjhay sppp_qflush(&sp->pp_cpq); 228070199Sjhay /* XXX ? */ 228170199Sjhay lcp.Down(sp); 228270199Sjhay lcp.Up(sp); 228370199Sjhay } 228470199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 228528036Sjoerg if (debug) 228669211Sphk log(-1, " max_failure (%d) exceeded, " 228728036Sjoerg "send conf-rej\n", 228828036Sjoerg sp->lcp.max_failure); 228928036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 229028036Sjoerg } else { 229128036Sjoerg if (debug) 229269211Sphk log(-1, " send conf-nak\n"); 229328036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 229428036Sjoerg } 229525944Sjoerg } else { 229625944Sjoerg if (debug) 229769211Sphk log(-1, " send conf-ack\n"); 229828036Sjoerg sp->fail_counter[IDX_LCP] = 0; 229925944Sjoerg sp->pp_loopcnt = 0; 230025944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 230125944Sjoerg h->ident, origlen, h+1); 230225944Sjoerg } 230325944Sjoerg 230411189Sjkh free (buf, M_TEMP); 230511189Sjkh return (rlen == 0); 23064910Swollman} 23074910Swollman 230825944Sjoerg/* 230925944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 231025944Sjoerg * negotiation. 231125944Sjoerg */ 231212820Sphkstatic void 231325944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 23144910Swollman{ 231525944Sjoerg STDDCL; 231625944Sjoerg u_char *buf, *p; 23174910Swollman 231825944Sjoerg len -= 4; 231925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 232025944Sjoerg if (!buf) 23214910Swollman return; 232225944Sjoerg 232325944Sjoerg if (debug) 232440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 232540008Sjoerg SPP_ARGS(ifp)); 232625944Sjoerg 232725944Sjoerg p = (void*) (h+1); 232825944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 232925944Sjoerg if (debug) 233069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 233125944Sjoerg switch (*p) { 233225944Sjoerg case LCP_OPT_MAGIC: 233325944Sjoerg /* Magic number -- can't use it, use 0 */ 233425944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 233525944Sjoerg sp->lcp.magic = 0; 233625944Sjoerg break; 233725944Sjoerg case LCP_OPT_MRU: 233825944Sjoerg /* 233925944Sjoerg * Should not be rejected anyway, since we only 234025944Sjoerg * negotiate a MRU if explicitly requested by 234125944Sjoerg * peer. 234225944Sjoerg */ 234325944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 234425944Sjoerg break; 234530300Sjoerg case LCP_OPT_AUTH_PROTO: 234630300Sjoerg /* 234730300Sjoerg * Peer doesn't want to authenticate himself, 234830300Sjoerg * deny unless this is a dialout call, and 234930300Sjoerg * AUTHFLAG_NOCALLOUT is set. 235030300Sjoerg */ 235130300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 235230300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 235330300Sjoerg if (debug) 235469211Sphk log(-1, "[don't insist on auth " 235530300Sjoerg "for callout]"); 235630300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 235730300Sjoerg break; 235830300Sjoerg } 235930300Sjoerg if (debug) 236069211Sphk log(-1, "[access denied]\n"); 236130300Sjoerg lcp.Close(sp); 236230300Sjoerg break; 236325944Sjoerg } 23644910Swollman } 236525944Sjoerg if (debug) 236669211Sphk log(-1, "\n"); 236725944Sjoerg free (buf, M_TEMP); 236825944Sjoerg return; 236925944Sjoerg} 237025944Sjoerg 237125944Sjoerg/* 237225944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 237325944Sjoerg * negotiation. 237425944Sjoerg */ 237525944Sjoergstatic void 237625944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 237725944Sjoerg{ 237825944Sjoerg STDDCL; 237925944Sjoerg u_char *buf, *p; 238025944Sjoerg u_long magic; 238125944Sjoerg 238225944Sjoerg len -= 4; 238325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 238425944Sjoerg if (!buf) 238525944Sjoerg return; 238625944Sjoerg 238725944Sjoerg if (debug) 238840008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 238940008Sjoerg SPP_ARGS(ifp)); 239025944Sjoerg 239125944Sjoerg p = (void*) (h+1); 239225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 239325706Sjoerg if (debug) 239469211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 239525944Sjoerg switch (*p) { 239625944Sjoerg case LCP_OPT_MAGIC: 239725944Sjoerg /* Magic number -- renegotiate */ 239825944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 239925944Sjoerg len >= 6 && p[1] == 6) { 240025944Sjoerg magic = (u_long)p[2] << 24 | 240125944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 240225944Sjoerg /* 240325944Sjoerg * If the remote magic is our negated one, 240425944Sjoerg * this looks like a loopback problem. 240525944Sjoerg * Suggest a new magic to make sure. 240625944Sjoerg */ 240725944Sjoerg if (magic == ~sp->lcp.magic) { 240825944Sjoerg if (debug) 240969211Sphk log(-1, "magic glitch "); 241042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 241135064Sphk sp->lcp.magic = random(); 241240008Sjoerg#else 241340008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 241440008Sjoerg#endif 241525944Sjoerg } else { 241625944Sjoerg sp->lcp.magic = magic; 241725944Sjoerg if (debug) 241869211Sphk log(-1, "%lu ", magic); 241925944Sjoerg } 242025944Sjoerg } 242125944Sjoerg break; 242225944Sjoerg case LCP_OPT_MRU: 242325944Sjoerg /* 242425944Sjoerg * Peer wants to advise us to negotiate an MRU. 242525944Sjoerg * Agree on it if it's reasonable, or use 242625944Sjoerg * default otherwise. 242725944Sjoerg */ 242825944Sjoerg if (len >= 4 && p[1] == 4) { 242925944Sjoerg u_int mru = p[2] * 256 + p[3]; 243025944Sjoerg if (debug) 243169211Sphk log(-1, "%d ", mru); 243225944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 243325944Sjoerg mru = PP_MTU; 243425944Sjoerg sp->lcp.mru = mru; 243525944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 243625944Sjoerg } 243725944Sjoerg break; 243830300Sjoerg case LCP_OPT_AUTH_PROTO: 243930300Sjoerg /* 244030300Sjoerg * Peer doesn't like our authentication method, 244130300Sjoerg * deny. 244230300Sjoerg */ 244330300Sjoerg if (debug) 244469211Sphk log(-1, "[access denied]\n"); 244530300Sjoerg lcp.Close(sp); 244630300Sjoerg break; 24474910Swollman } 244825944Sjoerg } 244925944Sjoerg if (debug) 245069211Sphk log(-1, "\n"); 245125944Sjoerg free (buf, M_TEMP); 245225944Sjoerg return; 245325944Sjoerg} 245411189Sjkh 245525944Sjoergstatic void 245625944Sjoergsppp_lcp_tlu(struct sppp *sp) 245725944Sjoerg{ 245842066Sphk STDDCL; 245925944Sjoerg int i; 246025944Sjoerg u_long mask; 246125944Sjoerg 246225944Sjoerg /* XXX ? */ 246325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 246425944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 246525944Sjoerg /* Coming out of loopback mode. */ 246625944Sjoerg if_up(ifp); 246740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 246825944Sjoerg } 246925944Sjoerg 247025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 247125944Sjoerg if ((cps[i])->flags & CP_QUAL) 247225944Sjoerg (cps[i])->Open(sp); 247325944Sjoerg 247430300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 247530300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 247625944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 247725944Sjoerg else 247825944Sjoerg sp->pp_phase = PHASE_NETWORK; 247925944Sjoerg 248042066Sphk if (debug) 248142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 248242066Sphk sppp_phase_name(sp->pp_phase)); 248325944Sjoerg 248430300Sjoerg /* 248530300Sjoerg * Open all authentication protocols. This is even required 248630300Sjoerg * if we already proceeded to network phase, since it might be 248730300Sjoerg * that remote wants us to authenticate, so we might have to 248830300Sjoerg * send a PAP request. Undesired authentication protocols 248930300Sjoerg * don't do anything when they get an Open event. 249030300Sjoerg */ 249130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 249230300Sjoerg if ((cps[i])->flags & CP_AUTH) 249330300Sjoerg (cps[i])->Open(sp); 249430300Sjoerg 249530300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 249625944Sjoerg /* Notify all NCPs. */ 249725944Sjoerg for (i = 0; i < IDX_COUNT; i++) 249825944Sjoerg if ((cps[i])->flags & CP_NCP) 249925944Sjoerg (cps[i])->Open(sp); 250025944Sjoerg } 250125944Sjoerg 250225944Sjoerg /* Send Up events to all started protos. */ 250325944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 250425944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 250525944Sjoerg (cps[i])->Up(sp); 250625944Sjoerg 250742104Sphk /* notify low-level driver of state change */ 250842104Sphk if (sp->pp_chg) 250942104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 251042104Sphk 251125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 251225944Sjoerg /* if no NCP is starting, close down */ 251330300Sjoerg sppp_lcp_check_and_close(sp); 251425944Sjoerg} 251525944Sjoerg 251625944Sjoergstatic void 251725944Sjoergsppp_lcp_tld(struct sppp *sp) 251825944Sjoerg{ 251942066Sphk STDDCL; 252025944Sjoerg int i; 252125944Sjoerg u_long mask; 252225944Sjoerg 252325944Sjoerg sp->pp_phase = PHASE_TERMINATE; 252425944Sjoerg 252542066Sphk if (debug) 252642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 252742066Sphk sppp_phase_name(sp->pp_phase)); 252825944Sjoerg 252925944Sjoerg /* 253025944Sjoerg * Take upper layers down. We send the Down event first and 253125944Sjoerg * the Close second to prevent the upper layers from sending 253225944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 253325944Sjoerg * describes it. 253425944Sjoerg */ 253525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 253625944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 253725944Sjoerg (cps[i])->Down(sp); 253825944Sjoerg (cps[i])->Close(sp); 253925944Sjoerg } 254025944Sjoerg} 254125944Sjoerg 254225944Sjoergstatic void 254325944Sjoergsppp_lcp_tls(struct sppp *sp) 254425944Sjoerg{ 254542066Sphk STDDCL; 254625944Sjoerg 254725944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 254825944Sjoerg 254942066Sphk if (debug) 255042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 255142066Sphk sppp_phase_name(sp->pp_phase)); 255225944Sjoerg 255325944Sjoerg /* Notify lower layer if desired. */ 255425944Sjoerg if (sp->pp_tls) 255525944Sjoerg (sp->pp_tls)(sp); 255641881Sphk else 255741881Sphk (sp->pp_up)(sp); 255825944Sjoerg} 255925944Sjoerg 256025944Sjoergstatic void 256125944Sjoergsppp_lcp_tlf(struct sppp *sp) 256225944Sjoerg{ 256342066Sphk STDDCL; 256425944Sjoerg 256525944Sjoerg sp->pp_phase = PHASE_DEAD; 256642066Sphk if (debug) 256742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 256842066Sphk sppp_phase_name(sp->pp_phase)); 256925944Sjoerg 257025944Sjoerg /* Notify lower layer if desired. */ 257125944Sjoerg if (sp->pp_tlf) 257225944Sjoerg (sp->pp_tlf)(sp); 257341881Sphk else 257441881Sphk (sp->pp_down)(sp); 257525944Sjoerg} 257625944Sjoerg 257725944Sjoergstatic void 257825944Sjoergsppp_lcp_scr(struct sppp *sp) 257925944Sjoerg{ 258030300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 258125944Sjoerg int i = 0; 258230300Sjoerg u_short authproto; 258325944Sjoerg 258425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 258525944Sjoerg if (! sp->lcp.magic) 258642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 258735064Sphk sp->lcp.magic = random(); 258840008Sjoerg#else 258940008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 259040008Sjoerg#endif 259125944Sjoerg opt[i++] = LCP_OPT_MAGIC; 259225944Sjoerg opt[i++] = 6; 259325944Sjoerg opt[i++] = sp->lcp.magic >> 24; 259425944Sjoerg opt[i++] = sp->lcp.magic >> 16; 259525944Sjoerg opt[i++] = sp->lcp.magic >> 8; 259625944Sjoerg opt[i++] = sp->lcp.magic; 259725944Sjoerg } 259825944Sjoerg 259925944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 260025944Sjoerg opt[i++] = LCP_OPT_MRU; 260125944Sjoerg opt[i++] = 4; 260225944Sjoerg opt[i++] = sp->lcp.mru >> 8; 260325944Sjoerg opt[i++] = sp->lcp.mru; 260425944Sjoerg } 260525944Sjoerg 260630300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 260730300Sjoerg authproto = sp->hisauth.proto; 260830300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 260930300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 261030300Sjoerg opt[i++] = authproto >> 8; 261130300Sjoerg opt[i++] = authproto; 261230300Sjoerg if (authproto == PPP_CHAP) 261330300Sjoerg opt[i++] = CHAP_MD5; 261430300Sjoerg } 261530300Sjoerg 261678064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 261725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 261825944Sjoerg} 261925944Sjoerg 262025944Sjoerg/* 262130300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 262230300Sjoerg */ 262330300Sjoergstatic int 262430300Sjoergsppp_ncp_check(struct sppp *sp) 262530300Sjoerg{ 262630300Sjoerg int i, mask; 262730300Sjoerg 262830300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 262930300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 263030300Sjoerg return 1; 263130300Sjoerg return 0; 263230300Sjoerg} 263330300Sjoerg 263430300Sjoerg/* 263525944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 263625944Sjoerg * Called by the NCPs during their tlf action handling. 263725944Sjoerg */ 263825944Sjoergstatic void 263930300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 264025944Sjoerg{ 264125944Sjoerg 264230300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 264330300Sjoerg /* don't bother, we are already going down */ 264430300Sjoerg return; 264530300Sjoerg 264630300Sjoerg if (sppp_ncp_check(sp)) 264730300Sjoerg return; 264830300Sjoerg 264925944Sjoerg lcp.Close(sp); 265025944Sjoerg} 265170199Sjhay 265270199Sjhay/* 265325944Sjoerg *--------------------------------------------------------------------------* 265425944Sjoerg * * 265525944Sjoerg * The IPCP implementation. * 265625944Sjoerg * * 265725944Sjoerg *--------------------------------------------------------------------------* 265825944Sjoerg */ 265925944Sjoerg 266025944Sjoergstatic void 266125944Sjoergsppp_ipcp_init(struct sppp *sp) 266225944Sjoerg{ 266325944Sjoerg sp->ipcp.opts = 0; 266425944Sjoerg sp->ipcp.flags = 0; 266525944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 266625944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 266778064Sume sp->pp_seq[IDX_IPCP] = 0; 266878064Sume sp->pp_rseq[IDX_IPCP] = 0; 266942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 267029681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 267140008Sjoerg#endif 267225944Sjoerg} 267325944Sjoerg 267425944Sjoergstatic void 267525944Sjoergsppp_ipcp_up(struct sppp *sp) 267625944Sjoerg{ 267725944Sjoerg sppp_up_event(&ipcp, sp); 267825944Sjoerg} 267925944Sjoerg 268025944Sjoergstatic void 268125944Sjoergsppp_ipcp_down(struct sppp *sp) 268225944Sjoerg{ 268325944Sjoerg sppp_down_event(&ipcp, sp); 268425944Sjoerg} 268525944Sjoerg 268625944Sjoergstatic void 268725944Sjoergsppp_ipcp_open(struct sppp *sp) 268825944Sjoerg{ 268925944Sjoerg STDDCL; 269025944Sjoerg u_long myaddr, hisaddr; 269125944Sjoerg 269242104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 269342104Sphk 269430300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 269525944Sjoerg /* 269625944Sjoerg * If we don't have his address, this probably means our 269725944Sjoerg * interface doesn't want to talk IP at all. (This could 269825944Sjoerg * be the case if somebody wants to speak only IPX, for 269925944Sjoerg * example.) Don't open IPCP in this case. 270025944Sjoerg */ 270125944Sjoerg if (hisaddr == 0L) { 270225944Sjoerg /* XXX this message should go away */ 270325944Sjoerg if (debug) 270440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 270540008Sjoerg SPP_ARGS(ifp)); 270625944Sjoerg return; 270725944Sjoerg } 270825944Sjoerg 270925944Sjoerg if (myaddr == 0L) { 271025944Sjoerg /* 271125944Sjoerg * I don't have an assigned address, so i need to 271225944Sjoerg * negotiate my address. 271325944Sjoerg */ 271425944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 271525944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 271642104Sphk } else 271742104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 271825944Sjoerg sppp_open_event(&ipcp, sp); 271925944Sjoerg} 272025944Sjoerg 272125944Sjoergstatic void 272225944Sjoergsppp_ipcp_close(struct sppp *sp) 272325944Sjoerg{ 272425944Sjoerg sppp_close_event(&ipcp, sp); 272525944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 272625944Sjoerg /* 272725944Sjoerg * My address was dynamic, clear it again. 272825944Sjoerg */ 272925944Sjoerg sppp_set_ip_addr(sp, 0L); 273025944Sjoerg} 273125944Sjoerg 273225944Sjoergstatic void 273325944Sjoergsppp_ipcp_TO(void *cookie) 273425944Sjoerg{ 273525944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 273625944Sjoerg} 273725944Sjoerg 273825944Sjoerg/* 273925944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 274025944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 274125944Sjoerg * caused action scn. (The return value is used to make the state 274225944Sjoerg * transition decision in the state automaton.) 274325944Sjoerg */ 274425944Sjoergstatic int 274525944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 274625944Sjoerg{ 274725944Sjoerg u_char *buf, *r, *p; 274825944Sjoerg struct ifnet *ifp = &sp->pp_if; 274925944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 275025944Sjoerg u_long hisaddr, desiredaddr; 275142104Sphk int gotmyaddr = 0; 275225944Sjoerg 275325944Sjoerg len -= 4; 275425944Sjoerg origlen = len; 275525944Sjoerg /* 275625944Sjoerg * Make sure to allocate a buf that can at least hold a 275725944Sjoerg * conf-nak with an `address' option. We might need it below. 275825944Sjoerg */ 275925944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 276025944Sjoerg if (! buf) 276125944Sjoerg return (0); 276225944Sjoerg 276325944Sjoerg /* pass 1: see if we can recognize them */ 276425944Sjoerg if (debug) 276540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 276640008Sjoerg SPP_ARGS(ifp)); 276725944Sjoerg p = (void*) (h+1); 276825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 276925944Sjoerg if (debug) 277069211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 277125944Sjoerg switch (*p) { 277225944Sjoerg case IPCP_OPT_ADDRESS: 277325944Sjoerg if (len >= 6 && p[1] == 6) { 277425944Sjoerg /* correctly formed address option */ 277525944Sjoerg continue; 277625944Sjoerg } 277725706Sjoerg if (debug) 277869211Sphk log(-1, "[invalid] "); 277911189Sjkh break; 278025944Sjoerg default: 278125944Sjoerg /* Others not supported. */ 278225944Sjoerg if (debug) 278369211Sphk log(-1, "[rej] "); 27844910Swollman break; 27854910Swollman } 278625944Sjoerg /* Add the option to rejected list. */ 278725944Sjoerg bcopy (p, r, p[1]); 278825944Sjoerg r += p[1]; 278925944Sjoerg rlen += p[1]; 279025944Sjoerg } 279125944Sjoerg if (rlen) { 279225944Sjoerg if (debug) 279369211Sphk log(-1, " send conf-rej\n"); 279425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 279525944Sjoerg return 0; 279625944Sjoerg } else if (debug) 279769211Sphk log(-1, "\n"); 279825944Sjoerg 279925944Sjoerg /* pass 2: parse option values */ 280030300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 280125944Sjoerg if (debug) 280240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 280340008Sjoerg SPP_ARGS(ifp)); 280425944Sjoerg p = (void*) (h+1); 280525944Sjoerg len = origlen; 280625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 280725944Sjoerg if (debug) 280869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 280925944Sjoerg switch (*p) { 281025944Sjoerg case IPCP_OPT_ADDRESS: 281142104Sphk /* This is the address he wants in his end */ 281225944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 281325944Sjoerg p[4] << 8 | p[5]; 281433928Sphk if (desiredaddr == hisaddr || 281542104Sphk (hisaddr == 1 && desiredaddr != 0)) { 281625944Sjoerg /* 281725944Sjoerg * Peer's address is same as our value, 281870199Sjhay * or we have set it to 0.0.0.1 to 281933928Sphk * indicate that we do not really care, 282025944Sjoerg * this is agreeable. Gonna conf-ack 282125944Sjoerg * it. 282225944Sjoerg */ 282325944Sjoerg if (debug) 282469211Sphk log(-1, "%s [ack] ", 282542104Sphk sppp_dotted_quad(hisaddr)); 282625944Sjoerg /* record that we've seen it already */ 282725944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 282825944Sjoerg continue; 282925944Sjoerg } 283025944Sjoerg /* 283125944Sjoerg * The address wasn't agreeable. This is either 283225944Sjoerg * he sent us 0.0.0.0, asking to assign him an 283325944Sjoerg * address, or he send us another address not 283425944Sjoerg * matching our value. Either case, we gonna 283525944Sjoerg * conf-nak it with our value. 283642104Sphk * XXX: we should "rej" if hisaddr == 0 283725944Sjoerg */ 283825944Sjoerg if (debug) { 283925944Sjoerg if (desiredaddr == 0) 284069211Sphk log(-1, "[addr requested] "); 284125944Sjoerg else 284269211Sphk log(-1, "%s [not agreed] ", 284342104Sphk sppp_dotted_quad(desiredaddr)); 284425944Sjoerg 284525944Sjoerg } 284644235Sphk p[2] = hisaddr >> 24; 284744235Sphk p[3] = hisaddr >> 16; 284844235Sphk p[4] = hisaddr >> 8; 284944235Sphk p[5] = hisaddr; 285011189Sjkh break; 285125706Sjoerg } 285225944Sjoerg /* Add the option to nak'ed list. */ 285325944Sjoerg bcopy (p, r, p[1]); 285425944Sjoerg r += p[1]; 285525944Sjoerg rlen += p[1]; 285625944Sjoerg } 285725944Sjoerg 285825944Sjoerg /* 285925944Sjoerg * If we are about to conf-ack the request, but haven't seen 286025944Sjoerg * his address so far, gonna conf-nak it instead, with the 286125944Sjoerg * `address' option present and our idea of his address being 286225944Sjoerg * filled in there, to request negotiation of both addresses. 286325944Sjoerg * 286425944Sjoerg * XXX This can result in an endless req - nak loop if peer 286525944Sjoerg * doesn't want to send us his address. Q: What should we do 286625944Sjoerg * about it? XXX A: implement the max-failure counter. 286725944Sjoerg */ 286842104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 286925944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 287025944Sjoerg buf[1] = 6; 287125944Sjoerg buf[2] = hisaddr >> 24; 287225944Sjoerg buf[3] = hisaddr >> 16; 287325944Sjoerg buf[4] = hisaddr >> 8; 287425944Sjoerg buf[5] = hisaddr; 287525944Sjoerg rlen = 6; 287625706Sjoerg if (debug) 287769211Sphk log(-1, "still need hisaddr "); 287825944Sjoerg } 287925944Sjoerg 288025944Sjoerg if (rlen) { 288125706Sjoerg if (debug) 288269211Sphk log(-1, " send conf-nak\n"); 288325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 288425944Sjoerg } else { 288525706Sjoerg if (debug) 288669211Sphk log(-1, " send conf-ack\n"); 288725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 288825944Sjoerg h->ident, origlen, h+1); 288925944Sjoerg } 289025944Sjoerg 289125944Sjoerg free (buf, M_TEMP); 289225944Sjoerg return (rlen == 0); 289325944Sjoerg} 289425944Sjoerg 289525944Sjoerg/* 289625944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 289725944Sjoerg * negotiation. 289825944Sjoerg */ 289925944Sjoergstatic void 290025944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 290125944Sjoerg{ 290225944Sjoerg u_char *buf, *p; 290325944Sjoerg struct ifnet *ifp = &sp->pp_if; 290425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 290525944Sjoerg 290625944Sjoerg len -= 4; 290725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 290825944Sjoerg if (!buf) 290925944Sjoerg return; 291025944Sjoerg 291125944Sjoerg if (debug) 291240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 291340008Sjoerg SPP_ARGS(ifp)); 291425944Sjoerg 291525944Sjoerg p = (void*) (h+1); 291625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 291725706Sjoerg if (debug) 291869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 291925944Sjoerg switch (*p) { 292025944Sjoerg case IPCP_OPT_ADDRESS: 292125944Sjoerg /* 292225944Sjoerg * Peer doesn't grok address option. This is 292325944Sjoerg * bad. XXX Should we better give up here? 292442104Sphk * XXX We could try old "addresses" option... 292525944Sjoerg */ 292625944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 292725944Sjoerg break; 292825944Sjoerg } 29294910Swollman } 293025944Sjoerg if (debug) 293169211Sphk log(-1, "\n"); 293225944Sjoerg free (buf, M_TEMP); 293325944Sjoerg return; 29344910Swollman} 29354910Swollman 293625944Sjoerg/* 293725944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 293825944Sjoerg * negotiation. 293925944Sjoerg */ 294012820Sphkstatic void 294125944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 29424910Swollman{ 294325944Sjoerg u_char *buf, *p; 294425944Sjoerg struct ifnet *ifp = &sp->pp_if; 294525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 294625944Sjoerg u_long wantaddr; 29474910Swollman 294825944Sjoerg len -= 4; 294925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 295025944Sjoerg if (!buf) 295125944Sjoerg return; 295225944Sjoerg 295325944Sjoerg if (debug) 295440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 295540008Sjoerg SPP_ARGS(ifp)); 295625944Sjoerg 295725944Sjoerg p = (void*) (h+1); 295825944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 295925944Sjoerg if (debug) 296069211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 296125944Sjoerg switch (*p) { 296225944Sjoerg case IPCP_OPT_ADDRESS: 296325944Sjoerg /* 296425944Sjoerg * Peer doesn't like our local IP address. See 296525944Sjoerg * if we can do something for him. We'll drop 296625944Sjoerg * him our address then. 296725944Sjoerg */ 296825944Sjoerg if (len >= 6 && p[1] == 6) { 296925944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 297025944Sjoerg p[4] << 8 | p[5]; 297125944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 297225944Sjoerg if (debug) 297369211Sphk log(-1, "[wantaddr %s] ", 297430300Sjoerg sppp_dotted_quad(wantaddr)); 297525944Sjoerg /* 297625944Sjoerg * When doing dynamic address assignment, 297725944Sjoerg * we accept his offer. Otherwise, we 297825944Sjoerg * ignore it and thus continue to negotiate 297925944Sjoerg * our already existing value. 298042104Sphk * XXX: Bogus, if he said no once, he'll 298142104Sphk * just say no again, might as well die. 298225944Sjoerg */ 298325944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 298425944Sjoerg sppp_set_ip_addr(sp, wantaddr); 298525944Sjoerg if (debug) 298669211Sphk log(-1, "[agree] "); 298742104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 298825944Sjoerg } 298925944Sjoerg } 299025944Sjoerg break; 299125944Sjoerg } 299225944Sjoerg } 299325944Sjoerg if (debug) 299469211Sphk log(-1, "\n"); 299525944Sjoerg free (buf, M_TEMP); 299625944Sjoerg return; 29974910Swollman} 29984910Swollman 299912820Sphkstatic void 300025944Sjoergsppp_ipcp_tlu(struct sppp *sp) 30014910Swollman{ 300242104Sphk /* we are up - notify isdn daemon */ 300342104Sphk if (sp->pp_con) 300442104Sphk sp->pp_con(sp); 30054910Swollman} 30064910Swollman 300725944Sjoergstatic void 300825944Sjoergsppp_ipcp_tld(struct sppp *sp) 300925944Sjoerg{ 301025944Sjoerg} 301125944Sjoerg 301225944Sjoergstatic void 301325944Sjoergsppp_ipcp_tls(struct sppp *sp) 301425944Sjoerg{ 301525944Sjoerg /* indicate to LCP that it must stay alive */ 301625944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 301725944Sjoerg} 301825944Sjoerg 301925944Sjoergstatic void 302025944Sjoergsppp_ipcp_tlf(struct sppp *sp) 302125944Sjoerg{ 302225944Sjoerg /* we no longer need LCP */ 302325944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 302430300Sjoerg sppp_lcp_check_and_close(sp); 302525944Sjoerg} 302625944Sjoerg 302725944Sjoergstatic void 302825944Sjoergsppp_ipcp_scr(struct sppp *sp) 302925944Sjoerg{ 303025944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 303125944Sjoerg u_long ouraddr; 303225944Sjoerg int i = 0; 303325944Sjoerg 303425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 303530300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 303625944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 303725944Sjoerg opt[i++] = 6; 303825944Sjoerg opt[i++] = ouraddr >> 24; 303925944Sjoerg opt[i++] = ouraddr >> 16; 304025944Sjoerg opt[i++] = ouraddr >> 8; 304125944Sjoerg opt[i++] = ouraddr; 304225944Sjoerg } 304325944Sjoerg 304478064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 304525944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 304625944Sjoerg} 304725944Sjoerg 304870199Sjhay/* 304930300Sjoerg *--------------------------------------------------------------------------* 305030300Sjoerg * * 305178064Sume * The IPv6CP implementation. * 305278064Sume * * 305378064Sume *--------------------------------------------------------------------------* 305478064Sume */ 305578064Sume 305678064Sume#ifdef INET6 305778064Sumestatic void 305878064Sumesppp_ipv6cp_init(struct sppp *sp) 305978064Sume{ 306078064Sume sp->ipv6cp.opts = 0; 306178064Sume sp->ipv6cp.flags = 0; 306278064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 306378064Sume sp->fail_counter[IDX_IPV6CP] = 0; 306478064Sume sp->pp_seq[IDX_IPV6CP] = 0; 306578064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 306678064Sume#if defined(__NetBSD__) 306778064Sume callout_init(&sp->ch[IDX_IPV6CP]); 306878064Sume#endif 306978064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 307078064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 307178064Sume#endif 307278064Sume} 307378064Sume 307478064Sumestatic void 307578064Sumesppp_ipv6cp_up(struct sppp *sp) 307678064Sume{ 307778064Sume sppp_up_event(&ipv6cp, sp); 307878064Sume} 307978064Sume 308078064Sumestatic void 308178064Sumesppp_ipv6cp_down(struct sppp *sp) 308278064Sume{ 308378064Sume sppp_down_event(&ipv6cp, sp); 308478064Sume} 308578064Sume 308678064Sumestatic void 308778064Sumesppp_ipv6cp_open(struct sppp *sp) 308878064Sume{ 308978064Sume STDDCL; 309078064Sume struct in6_addr myaddr, hisaddr; 309178064Sume 309278064Sume#ifdef IPV6CP_MYIFID_DYN 309378064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 309478064Sume#else 309578064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 309678064Sume#endif 309778064Sume 309878064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 309978064Sume /* 310078064Sume * If we don't have our address, this probably means our 310178064Sume * interface doesn't want to talk IPv6 at all. (This could 310278064Sume * be the case if somebody wants to speak only IPX, for 310378064Sume * example.) Don't open IPv6CP in this case. 310478064Sume */ 310578064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 310678064Sume /* XXX this message should go away */ 310778064Sume if (debug) 310878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 310978064Sume SPP_ARGS(ifp)); 311078064Sume return; 311178064Sume } 311278064Sume 311378064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 311478064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 311578064Sume sppp_open_event(&ipv6cp, sp); 311678064Sume} 311778064Sume 311878064Sumestatic void 311978064Sumesppp_ipv6cp_close(struct sppp *sp) 312078064Sume{ 312178064Sume sppp_close_event(&ipv6cp, sp); 312278064Sume} 312378064Sume 312478064Sumestatic void 312578064Sumesppp_ipv6cp_TO(void *cookie) 312678064Sume{ 312778064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 312878064Sume} 312978064Sume 313078064Sume/* 313178064Sume * Analyze a configure request. Return true if it was agreeable, and 313278064Sume * caused action sca, false if it has been rejected or nak'ed, and 313378064Sume * caused action scn. (The return value is used to make the state 313478064Sume * transition decision in the state automaton.) 313578064Sume */ 313678064Sumestatic int 313778064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 313878064Sume{ 313978064Sume u_char *buf, *r, *p; 314078064Sume struct ifnet *ifp = &sp->pp_if; 314178064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 314278064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 314378064Sume int ifidcount; 314478064Sume int type; 314578064Sume int collision, nohisaddr; 314678064Sume 314778064Sume len -= 4; 314878064Sume origlen = len; 314978064Sume /* 315078064Sume * Make sure to allocate a buf that can at least hold a 315178064Sume * conf-nak with an `address' option. We might need it below. 315278064Sume */ 315378064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 315478064Sume if (! buf) 315578064Sume return (0); 315678064Sume 315778064Sume /* pass 1: see if we can recognize them */ 315878064Sume if (debug) 315978064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 316078064Sume SPP_ARGS(ifp)); 316178064Sume p = (void*) (h+1); 316278064Sume ifidcount = 0; 316378064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 316478064Sume if (debug) 316578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 316678064Sume switch (*p) { 316778064Sume case IPV6CP_OPT_IFID: 316878064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 316978064Sume /* correctly formed address option */ 317078064Sume ifidcount++; 317178064Sume continue; 317278064Sume } 317378064Sume if (debug) 317478176Sume log(-1, " [invalid]"); 317578064Sume break; 317678064Sume#ifdef notyet 317778064Sume case IPV6CP_OPT_COMPRESSION: 317878064Sume if (len >= 4 && p[1] >= 4) { 317978064Sume /* correctly formed compress option */ 318078064Sume continue; 318178064Sume } 318278064Sume if (debug) 318378176Sume log(-1, " [invalid]"); 318478064Sume break; 318578064Sume#endif 318678064Sume default: 318778064Sume /* Others not supported. */ 318878064Sume if (debug) 318978176Sume log(-1, " [rej]"); 319078064Sume break; 319178064Sume } 319278064Sume /* Add the option to rejected list. */ 319378064Sume bcopy (p, r, p[1]); 319478064Sume r += p[1]; 319578064Sume rlen += p[1]; 319678064Sume } 319778064Sume if (rlen) { 319878064Sume if (debug) 319978176Sume log(-1, " send conf-rej\n"); 320078064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 320178064Sume goto end; 320278064Sume } else if (debug) 320378176Sume log(-1, "\n"); 320478064Sume 320578064Sume /* pass 2: parse option values */ 320678064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 320778064Sume if (debug) 320878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 320978064Sume SPP_ARGS(ifp)); 321078064Sume p = (void*) (h+1); 321178064Sume len = origlen; 321278064Sume type = CONF_ACK; 321378064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 321478064Sume if (debug) 321578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 321678064Sume switch (*p) { 321778064Sume#ifdef notyet 321878064Sume case IPV6CP_OPT_COMPRESSION: 321978064Sume continue; 322078064Sume#endif 322178064Sume case IPV6CP_OPT_IFID: 322278064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 322378064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 322478064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 322578064Sume &myaddr.s6_addr[8], 8) == 0); 322678064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 322778064Sume 322878064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 322978064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 323078064Sume 323178064Sume if (!collision && !nohisaddr) { 323278064Sume /* no collision, hisaddr known - Conf-Ack */ 323378064Sume type = CONF_ACK; 323478064Sume 323578064Sume if (debug) { 323678176Sume log(-1, " %s [%s]", 323778064Sume ip6_sprintf(&desiredaddr), 323878064Sume sppp_cp_type_name(type)); 323978064Sume } 324078064Sume continue; 324178064Sume } 324278064Sume 324378064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 324478064Sume if (collision && nohisaddr) { 324578064Sume /* collision, hisaddr unknown - Conf-Rej */ 324678064Sume type = CONF_REJ; 324778064Sume bzero(&p[2], 8); 324878064Sume } else { 324978064Sume /* 325078064Sume * - no collision, hisaddr unknown, or 325178064Sume * - collision, hisaddr known 325278064Sume * Conf-Nak, suggest hisaddr 325378064Sume */ 325478064Sume type = CONF_NAK; 325578064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 325678064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 325778064Sume } 325878064Sume if (debug) 325978176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 326078064Sume sppp_cp_type_name(type)); 326178064Sume break; 326278064Sume } 326378064Sume /* Add the option to nak'ed list. */ 326478064Sume bcopy (p, r, p[1]); 326578064Sume r += p[1]; 326678064Sume rlen += p[1]; 326778064Sume } 326878064Sume 326978064Sume if (rlen == 0 && type == CONF_ACK) { 327078064Sume if (debug) 327178176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 327278064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 327378064Sume } else { 327478064Sume#ifdef DIAGNOSTIC 327578064Sume if (type == CONF_ACK) 327678064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 327778064Sume#endif 327878064Sume 327978064Sume if (debug) { 328078176Sume log(-1, " send %s suggest %s\n", 328178064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 328278064Sume } 328378064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 328478064Sume } 328578064Sume 328678064Sume end: 328778064Sume free (buf, M_TEMP); 328878064Sume return (rlen == 0); 328978064Sume} 329078064Sume 329178064Sume/* 329278064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 329378064Sume * negotiation. 329478064Sume */ 329578064Sumestatic void 329678064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 329778064Sume{ 329878064Sume u_char *buf, *p; 329978064Sume struct ifnet *ifp = &sp->pp_if; 330078064Sume int debug = ifp->if_flags & IFF_DEBUG; 330178064Sume 330278064Sume len -= 4; 330378064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 330478064Sume if (!buf) 330578064Sume return; 330678064Sume 330778064Sume if (debug) 330878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 330978064Sume SPP_ARGS(ifp)); 331078064Sume 331178064Sume p = (void*) (h+1); 331278064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 331378064Sume if (debug) 331478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 331578064Sume switch (*p) { 331678064Sume case IPV6CP_OPT_IFID: 331778064Sume /* 331878064Sume * Peer doesn't grok address option. This is 331978064Sume * bad. XXX Should we better give up here? 332078064Sume */ 332178064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 332278064Sume break; 332378064Sume#ifdef notyet 332478064Sume case IPV6CP_OPT_COMPRESS: 332578064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 332678064Sume break; 332778064Sume#endif 332878064Sume } 332978064Sume } 333078064Sume if (debug) 333178176Sume log(-1, "\n"); 333278064Sume free (buf, M_TEMP); 333378064Sume return; 333478064Sume} 333578064Sume 333678064Sume/* 333778064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 333878064Sume * negotiation. 333978064Sume */ 334078064Sumestatic void 334178064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 334278064Sume{ 334378064Sume u_char *buf, *p; 334478064Sume struct ifnet *ifp = &sp->pp_if; 334578064Sume int debug = ifp->if_flags & IFF_DEBUG; 334678064Sume struct in6_addr suggestaddr; 334778064Sume 334878064Sume len -= 4; 334978064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 335078064Sume if (!buf) 335178064Sume return; 335278064Sume 335378064Sume if (debug) 335478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 335578064Sume SPP_ARGS(ifp)); 335678064Sume 335778064Sume p = (void*) (h+1); 335878064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 335978064Sume if (debug) 336078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 336178064Sume switch (*p) { 336278064Sume case IPV6CP_OPT_IFID: 336378064Sume /* 336478064Sume * Peer doesn't like our local ifid. See 336578064Sume * if we can do something for him. We'll drop 336678064Sume * him our address then. 336778064Sume */ 336878064Sume if (len < 10 || p[1] != 10) 336978064Sume break; 337078064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 337178064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 337278064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 337378064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 337478064Sume 337578064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 337678064Sume if (debug) 337778176Sume log(-1, " [suggestaddr %s]", 337878064Sume ip6_sprintf(&suggestaddr)); 337978064Sume#ifdef IPV6CP_MYIFID_DYN 338078064Sume /* 338178064Sume * When doing dynamic address assignment, 338278064Sume * we accept his offer. 338378064Sume */ 338478064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 338578064Sume struct in6_addr lastsuggest; 338678064Sume /* 338778064Sume * If <suggested myaddr from peer> equals to 338878064Sume * <hisaddr we have suggested last time>, 338978064Sume * we have a collision. generate new random 339078064Sume * ifid. 339178064Sume */ 339278064Sume sppp_suggest_ip6_addr(&lastsuggest); 339378064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 339478064Sume lastsuggest)) { 339578064Sume if (debug) 339678176Sume log(-1, " [random]"); 339778064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 339878064Sume } 339978064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 340078064Sume if (debug) 340178176Sume log(-1, " [agree]"); 340278064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 340378064Sume } 340478064Sume#else 340578064Sume /* 340678064Sume * Since we do not do dynamic address assignment, 340778064Sume * we ignore it and thus continue to negotiate 340878064Sume * our already existing value. This can possibly 340978064Sume * go into infinite request-reject loop. 341078064Sume * 341178064Sume * This is not likely because we normally use 341278064Sume * ifid based on MAC-address. 341378064Sume * If you have no ethernet card on the node, too bad. 341478064Sume * XXX should we use fail_counter? 341578064Sume */ 341678064Sume#endif 341778064Sume break; 341878064Sume#ifdef notyet 341978064Sume case IPV6CP_OPT_COMPRESS: 342078064Sume /* 342178064Sume * Peer wants different compression parameters. 342278064Sume */ 342378064Sume break; 342478064Sume#endif 342578064Sume } 342678064Sume } 342778064Sume if (debug) 342878176Sume log(-1, "\n"); 342978064Sume free (buf, M_TEMP); 343078064Sume return; 343178064Sume} 343278064Sumestatic void 343378064Sumesppp_ipv6cp_tlu(struct sppp *sp) 343478064Sume{ 343578064Sume /* we are up - notify isdn daemon */ 343678064Sume if (sp->pp_con) 343778064Sume sp->pp_con(sp); 343878064Sume} 343978064Sume 344078064Sumestatic void 344178064Sumesppp_ipv6cp_tld(struct sppp *sp) 344278064Sume{ 344378064Sume} 344478064Sume 344578064Sumestatic void 344678064Sumesppp_ipv6cp_tls(struct sppp *sp) 344778064Sume{ 344878064Sume /* indicate to LCP that it must stay alive */ 344978064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 345078064Sume} 345178064Sume 345278064Sumestatic void 345378064Sumesppp_ipv6cp_tlf(struct sppp *sp) 345478064Sume{ 345578064Sume 345678064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 345778064Sume /* we no longer need LCP */ 345878064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 345978064Sume sppp_lcp_check_and_close(sp); 346078064Sume#endif 346178064Sume} 346278064Sume 346378064Sumestatic void 346478064Sumesppp_ipv6cp_scr(struct sppp *sp) 346578064Sume{ 346678064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 346778064Sume struct in6_addr ouraddr; 346878064Sume int i = 0; 346978064Sume 347078064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 347178064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 347278064Sume opt[i++] = IPV6CP_OPT_IFID; 347378064Sume opt[i++] = 10; 347478064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 347578064Sume i += 8; 347678064Sume } 347778064Sume 347878064Sume#ifdef notyet 347978064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 348078064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 348178064Sume opt[i++] = 4; 348278064Sume opt[i++] = 0; /* TBD */ 348378064Sume opt[i++] = 0; /* TBD */ 348478064Sume /* variable length data may follow */ 348578064Sume } 348678064Sume#endif 348778064Sume 348878064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 348978064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 349078064Sume} 349178064Sume#else /*INET6*/ 349278064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 349378064Sume{ 349478064Sume} 349578064Sume 349678064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 349778064Sume{ 349878064Sume} 349978064Sume 350078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 350178064Sume{ 350278064Sume} 350378064Sume 350478064Sume 350578064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 350678064Sume{ 350778064Sume} 350878064Sume 350978064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 351078064Sume{ 351178064Sume} 351278064Sume 351378064Sumestatic void sppp_ipv6cp_TO(void *sp) 351478064Sume{ 351578064Sume} 351678064Sume 351778064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 351878064Sume{ 351978064Sume return 0; 352078064Sume} 352178064Sume 352278064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 352378064Sume{ 352478064Sume} 352578064Sume 352678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 352778064Sume{ 352878064Sume} 352978064Sume 353078064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 353178064Sume{ 353278064Sume} 353378064Sume 353478064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 353578064Sume{ 353678064Sume} 353778064Sume 353878064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 353978064Sume{ 354078064Sume} 354178064Sume 354278064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 354378064Sume{ 354478064Sume} 354578064Sume 354678064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 354778064Sume{ 354878064Sume} 354978064Sume#endif /*INET6*/ 355078064Sume 355178064Sume/* 355278064Sume *--------------------------------------------------------------------------* 355378064Sume * * 355430300Sjoerg * The CHAP implementation. * 355530300Sjoerg * * 355630300Sjoerg *--------------------------------------------------------------------------* 355730300Sjoerg */ 355830300Sjoerg 355930300Sjoerg/* 356030300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 356130300Sjoerg * the control protocols do, since they do have Open and Close events, but 356230300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 356330300Sjoerg * authentication protocols may be different in both directions (this makes 356430300Sjoerg * sense, think of a machine that never accepts incoming calls but only 356530300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 356630300Sjoerg * 356730300Sjoerg * Our state machine for the local authentication protocol (we are requesting 356830300Sjoerg * the peer to authenticate) looks like: 356930300Sjoerg * 357030300Sjoerg * RCA- 357130300Sjoerg * +--------------------------------------------+ 357230300Sjoerg * V scn,tld| 357330300Sjoerg * +--------+ Close +---------+ RCA+ 357430300Sjoerg * | |<----------------------------------| |------+ 357530300Sjoerg * +--->| Closed | TO* | Opened | sca | 357630300Sjoerg * | | |-----+ +-------| |<-----+ 357730300Sjoerg * | +--------+ irc | | +---------+ 357830300Sjoerg * | ^ | | ^ 357930300Sjoerg * | | | | | 358030300Sjoerg * | | | | | 358130300Sjoerg * | TO-| | | | 358230300Sjoerg * | |tld TO+ V | | 358330300Sjoerg * | | +------->+ | | 358430300Sjoerg * | | | | | | 358530300Sjoerg * | +--------+ V | | 358630300Sjoerg * | | |<----+<--------------------+ | 358730300Sjoerg * | | Req- | scr | 358830300Sjoerg * | | Sent | | 358930300Sjoerg * | | | | 359030300Sjoerg * | +--------+ | 359130300Sjoerg * | RCA- | | RCA+ | 359230300Sjoerg * +------+ +------------------------------------------+ 359330300Sjoerg * scn,tld sca,irc,ict,tlu 359430300Sjoerg * 359530300Sjoerg * 359630300Sjoerg * with: 359730300Sjoerg * 359830300Sjoerg * Open: LCP reached authentication phase 359930300Sjoerg * Close: LCP reached terminate phase 360030300Sjoerg * 360130300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 360230300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 360330300Sjoerg * TO+: timeout with restart counter >= 0 360430300Sjoerg * TO-: timeout with restart counter < 0 360530300Sjoerg * TO*: reschedule timeout for CHAP 360630300Sjoerg * 360730300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 360830300Sjoerg * sca: send ack packet (pap-ack, chap-success) 360930300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 361030300Sjoerg * ict: initialize re-challenge timer (CHAP only) 361130300Sjoerg * 361230300Sjoerg * tlu: this-layer-up, LCP reaches network phase 361330300Sjoerg * tld: this-layer-down, LCP enters terminate phase 361430300Sjoerg * 361530300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 361630300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 361730300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 361830300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 361930300Sjoerg * causing LCP to enter terminate phase. 362030300Sjoerg * 362130300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 362230300Sjoerg * expected to send one based on the successful negotiation of PAP as 362330300Sjoerg * the authentication protocol during the LCP option negotiation. 362430300Sjoerg * 362530300Sjoerg * Incoming authentication protocol requests (remote requests 362630300Sjoerg * authentication, we are peer) don't employ a state machine at all, 362730300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 362830300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 362930300Sjoerg * still in authentication phase (thereby violating the standard that 363030300Sjoerg * demands that these NCP packets are to be discarded), so we keep 363130300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 363230300Sjoerg * phase network once we've seen a positive acknowledge for the 363330300Sjoerg * authentication. 363430300Sjoerg */ 363530300Sjoerg 363630300Sjoerg/* 363730300Sjoerg * Handle incoming CHAP packets. 363830300Sjoerg */ 363930300Sjoergvoid 364030300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 364130300Sjoerg{ 364230300Sjoerg STDDCL; 364330300Sjoerg struct lcp_header *h; 364430300Sjoerg int len, x; 364530300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 364630300Sjoerg int value_len, name_len; 364730300Sjoerg MD5_CTX ctx; 364830300Sjoerg 364930300Sjoerg len = m->m_pkthdr.len; 365030300Sjoerg if (len < 4) { 365130300Sjoerg if (debug) 365230300Sjoerg log(LOG_DEBUG, 365340008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 365440008Sjoerg SPP_ARGS(ifp), len); 365530300Sjoerg return; 365630300Sjoerg } 365730300Sjoerg h = mtod (m, struct lcp_header*); 365830300Sjoerg if (len > ntohs (h->len)) 365930300Sjoerg len = ntohs (h->len); 366030300Sjoerg 366130300Sjoerg switch (h->type) { 366230300Sjoerg /* challenge, failure and success are his authproto */ 366330300Sjoerg case CHAP_CHALLENGE: 366430300Sjoerg value = 1 + (u_char*)(h+1); 366530300Sjoerg value_len = value[-1]; 366630300Sjoerg name = value + value_len; 366730300Sjoerg name_len = len - value_len - 5; 366830300Sjoerg if (name_len < 0) { 366930300Sjoerg if (debug) { 367030300Sjoerg log(LOG_DEBUG, 367140008Sjoerg SPP_FMT "chap corrupted challenge " 367230300Sjoerg "<%s id=0x%x len=%d", 367340008Sjoerg SPP_ARGS(ifp), 367430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 367530300Sjoerg h->ident, ntohs(h->len)); 367644145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 367769211Sphk log(-1, ">\n"); 367830300Sjoerg } 367930300Sjoerg break; 368030300Sjoerg } 368170199Sjhay 368230300Sjoerg if (debug) { 368330300Sjoerg log(LOG_DEBUG, 368440008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 368540008Sjoerg SPP_ARGS(ifp), 368630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 368730300Sjoerg ntohs(h->len)); 368830300Sjoerg sppp_print_string((char*) name, name_len); 368969211Sphk log(-1, " value-size=%d value=", value_len); 369030300Sjoerg sppp_print_bytes(value, value_len); 369169211Sphk log(-1, ">\n"); 369230300Sjoerg } 369330300Sjoerg 369430300Sjoerg /* Compute reply value. */ 369530300Sjoerg MD5Init(&ctx); 369630300Sjoerg MD5Update(&ctx, &h->ident, 1); 369730300Sjoerg MD5Update(&ctx, sp->myauth.secret, 369830300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 369930300Sjoerg MD5Update(&ctx, value, value_len); 370030300Sjoerg MD5Final(digest, &ctx); 370130300Sjoerg dsize = sizeof digest; 370230300Sjoerg 370330300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 370430300Sjoerg sizeof dsize, (const char *)&dsize, 370530300Sjoerg sizeof digest, digest, 370640008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 370730300Sjoerg sp->myauth.name, 370830300Sjoerg 0); 370930300Sjoerg break; 371030300Sjoerg 371130300Sjoerg case CHAP_SUCCESS: 371230300Sjoerg if (debug) { 371340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 371440008Sjoerg SPP_ARGS(ifp)); 371530300Sjoerg if (len > 4) { 371669211Sphk log(-1, ": "); 371730300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 371830300Sjoerg } 371969211Sphk log(-1, "\n"); 372030300Sjoerg } 372130300Sjoerg x = splimp(); 372230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 372330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 372432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 372530300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 372630300Sjoerg /* 372730300Sjoerg * We are authenticator for CHAP but didn't 372830300Sjoerg * complete yet. Leave it to tlu to proceed 372930300Sjoerg * to network phase. 373030300Sjoerg */ 373130300Sjoerg splx(x); 373230300Sjoerg break; 373330300Sjoerg } 373430300Sjoerg splx(x); 373530300Sjoerg sppp_phase_network(sp); 373630300Sjoerg break; 373730300Sjoerg 373830300Sjoerg case CHAP_FAILURE: 373930300Sjoerg if (debug) { 374040008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 374140008Sjoerg SPP_ARGS(ifp)); 374230300Sjoerg if (len > 4) { 374369211Sphk log(-1, ": "); 374430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 374530300Sjoerg } 374669211Sphk log(-1, "\n"); 374730300Sjoerg } else 374840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 374940008Sjoerg SPP_ARGS(ifp)); 375030300Sjoerg /* await LCP shutdown by authenticator */ 375130300Sjoerg break; 375230300Sjoerg 375330300Sjoerg /* response is my authproto */ 375430300Sjoerg case CHAP_RESPONSE: 375530300Sjoerg value = 1 + (u_char*)(h+1); 375630300Sjoerg value_len = value[-1]; 375730300Sjoerg name = value + value_len; 375830300Sjoerg name_len = len - value_len - 5; 375930300Sjoerg if (name_len < 0) { 376030300Sjoerg if (debug) { 376130300Sjoerg log(LOG_DEBUG, 376240008Sjoerg SPP_FMT "chap corrupted response " 376330300Sjoerg "<%s id=0x%x len=%d", 376440008Sjoerg SPP_ARGS(ifp), 376530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 376630300Sjoerg h->ident, ntohs(h->len)); 376744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 376869211Sphk log(-1, ">\n"); 376930300Sjoerg } 377030300Sjoerg break; 377130300Sjoerg } 377230300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 377330300Sjoerg if (debug) 377430300Sjoerg log(LOG_DEBUG, 377540008Sjoerg SPP_FMT "chap dropping response for old ID " 377630300Sjoerg "(got %d, expected %d)\n", 377740008Sjoerg SPP_ARGS(ifp), 377830300Sjoerg h->ident, sp->confid[IDX_CHAP]); 377930300Sjoerg break; 378030300Sjoerg } 378130300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 378230300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 378340008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 378440008Sjoerg SPP_ARGS(ifp)); 378530300Sjoerg sppp_print_string(name, name_len); 378669211Sphk log(-1, " != expected "); 378730300Sjoerg sppp_print_string(sp->hisauth.name, 378830300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 378969211Sphk log(-1, "\n"); 379070199Sjhay } 379130300Sjoerg if (debug) { 379240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 379330300Sjoerg "<%s id=0x%x len=%d name=", 379440008Sjoerg SPP_ARGS(ifp), 379530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 379630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 379730300Sjoerg h->ident, ntohs (h->len)); 379830300Sjoerg sppp_print_string((char*)name, name_len); 379969211Sphk log(-1, " value-size=%d value=", value_len); 380030300Sjoerg sppp_print_bytes(value, value_len); 380169211Sphk log(-1, ">\n"); 380230300Sjoerg } 380330300Sjoerg if (value_len != AUTHKEYLEN) { 380430300Sjoerg if (debug) 380530300Sjoerg log(LOG_DEBUG, 380640008Sjoerg SPP_FMT "chap bad hash value length: " 380730300Sjoerg "%d bytes, should be %d\n", 380840008Sjoerg SPP_ARGS(ifp), value_len, 380930300Sjoerg AUTHKEYLEN); 381030300Sjoerg break; 381130300Sjoerg } 381230300Sjoerg 381330300Sjoerg MD5Init(&ctx); 381430300Sjoerg MD5Update(&ctx, &h->ident, 1); 381530300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 381630300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 381730300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 381830300Sjoerg MD5Final(digest, &ctx); 381930300Sjoerg 382030300Sjoerg#define FAILMSG "Failed..." 382130300Sjoerg#define SUCCMSG "Welcome!" 382230300Sjoerg 382330300Sjoerg if (value_len != sizeof digest || 382430300Sjoerg bcmp(digest, value, value_len) != 0) { 382530300Sjoerg /* action scn, tld */ 382630300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 382730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 382830300Sjoerg 0); 382930300Sjoerg chap.tld(sp); 383030300Sjoerg break; 383130300Sjoerg } 383230300Sjoerg /* action sca, perhaps tlu */ 383330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 383430300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 383530300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 383630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 383730300Sjoerg 0); 383830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 383930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 384030300Sjoerg chap.tlu(sp); 384130300Sjoerg } 384230300Sjoerg break; 384330300Sjoerg 384430300Sjoerg default: 384530300Sjoerg /* Unknown CHAP packet type -- ignore. */ 384630300Sjoerg if (debug) { 384740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 384830300Sjoerg "<0x%x id=0x%xh len=%d", 384940008Sjoerg SPP_ARGS(ifp), 385030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 385130300Sjoerg h->type, h->ident, ntohs(h->len)); 385244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 385369211Sphk log(-1, ">\n"); 385430300Sjoerg } 385530300Sjoerg break; 385630300Sjoerg 385730300Sjoerg } 385830300Sjoerg} 385930300Sjoerg 386030300Sjoergstatic void 386130300Sjoergsppp_chap_init(struct sppp *sp) 386230300Sjoerg{ 386330300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 386430300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 386530300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 386678064Sume sp->pp_seq[IDX_CHAP] = 0; 386778064Sume sp->pp_rseq[IDX_CHAP] = 0; 386842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 386930300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 387040008Sjoerg#endif 387130300Sjoerg} 387230300Sjoerg 387330300Sjoergstatic void 387430300Sjoergsppp_chap_open(struct sppp *sp) 387530300Sjoerg{ 387630300Sjoerg if (sp->myauth.proto == PPP_CHAP && 387730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 387830300Sjoerg /* we are authenticator for CHAP, start it */ 387930300Sjoerg chap.scr(sp); 388030300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 388130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 388230300Sjoerg } 388330300Sjoerg /* nothing to be done if we are peer, await a challenge */ 388430300Sjoerg} 388530300Sjoerg 388630300Sjoergstatic void 388730300Sjoergsppp_chap_close(struct sppp *sp) 388830300Sjoerg{ 388930300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 389030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 389130300Sjoerg} 389230300Sjoerg 389330300Sjoergstatic void 389430300Sjoergsppp_chap_TO(void *cookie) 389530300Sjoerg{ 389630300Sjoerg struct sppp *sp = (struct sppp *)cookie; 389730300Sjoerg STDDCL; 389830300Sjoerg int s; 389930300Sjoerg 390030300Sjoerg s = splimp(); 390130300Sjoerg if (debug) 390240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 390340008Sjoerg SPP_ARGS(ifp), 390430300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 390530300Sjoerg sp->rst_counter[IDX_CHAP]); 390630300Sjoerg 390730300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 390830300Sjoerg /* TO- event */ 390930300Sjoerg switch (sp->state[IDX_CHAP]) { 391030300Sjoerg case STATE_REQ_SENT: 391130300Sjoerg chap.tld(sp); 391230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 391330300Sjoerg break; 391430300Sjoerg } 391530300Sjoerg else 391630300Sjoerg /* TO+ (or TO*) event */ 391730300Sjoerg switch (sp->state[IDX_CHAP]) { 391830300Sjoerg case STATE_OPENED: 391930300Sjoerg /* TO* event */ 392030300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 392130300Sjoerg /* fall through */ 392230300Sjoerg case STATE_REQ_SENT: 392330300Sjoerg chap.scr(sp); 392430300Sjoerg /* sppp_cp_change_state() will restart the timer */ 392530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 392630300Sjoerg break; 392730300Sjoerg } 392830300Sjoerg 392930300Sjoerg splx(s); 393030300Sjoerg} 393130300Sjoerg 393230300Sjoergstatic void 393330300Sjoergsppp_chap_tlu(struct sppp *sp) 393430300Sjoerg{ 393530300Sjoerg STDDCL; 393630300Sjoerg int i, x; 393730300Sjoerg 393840010Sjoerg i = 0; 393930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 394030300Sjoerg 394130300Sjoerg /* 394230300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 394330300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 394430300Sjoerg * initial challenge-response exchange has taken place. 394530300Sjoerg * Provide for an option to avoid rechallenges. 394630300Sjoerg */ 394730300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 394830300Sjoerg /* 394930300Sjoerg * Compute the re-challenge timeout. This will yield 395030300Sjoerg * a number between 300 and 810 seconds. 395130300Sjoerg */ 395230300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 395342064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 395430300Sjoerg } 395530300Sjoerg 395630300Sjoerg if (debug) { 395730300Sjoerg log(LOG_DEBUG, 395840008Sjoerg SPP_FMT "chap %s, ", 395940008Sjoerg SPP_ARGS(ifp), 396030300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 396130300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 396269211Sphk log(-1, "next re-challenge in %d seconds\n", i); 396330300Sjoerg else 396469211Sphk log(-1, "re-challenging supressed\n"); 396530300Sjoerg } 396630300Sjoerg 396730300Sjoerg x = splimp(); 396830300Sjoerg /* indicate to LCP that we need to be closed down */ 396930300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 397030300Sjoerg 397130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 397230300Sjoerg /* 397330300Sjoerg * Remote is authenticator, but his auth proto didn't 397430300Sjoerg * complete yet. Defer the transition to network 397530300Sjoerg * phase. 397630300Sjoerg */ 397730300Sjoerg splx(x); 397830300Sjoerg return; 397930300Sjoerg } 398030300Sjoerg splx(x); 398130300Sjoerg 398230300Sjoerg /* 398330300Sjoerg * If we are already in phase network, we are done here. This 398430300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 398530300Sjoerg */ 398630300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 398730300Sjoerg sppp_phase_network(sp); 398830300Sjoerg} 398930300Sjoerg 399030300Sjoergstatic void 399130300Sjoergsppp_chap_tld(struct sppp *sp) 399230300Sjoerg{ 399330300Sjoerg STDDCL; 399430300Sjoerg 399530300Sjoerg if (debug) 399640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 399740008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 399830300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 399930300Sjoerg 400030300Sjoerg lcp.Close(sp); 400130300Sjoerg} 400230300Sjoerg 400330300Sjoergstatic void 400430300Sjoergsppp_chap_scr(struct sppp *sp) 400530300Sjoerg{ 400630300Sjoerg u_long *ch, seed; 400730300Sjoerg u_char clen; 400830300Sjoerg 400930300Sjoerg /* Compute random challenge. */ 401030300Sjoerg ch = (u_long *)sp->myauth.challenge; 401142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 401235064Sphk read_random(&seed, sizeof seed); 401340008Sjoerg#else 401442104Sphk { 401542104Sphk struct timeval tv; 401640008Sjoerg microtime(&tv); 401740008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 401842104Sphk } 401940008Sjoerg#endif 402030300Sjoerg ch[0] = seed ^ random(); 402130300Sjoerg ch[1] = seed ^ random(); 402230300Sjoerg ch[2] = seed ^ random(); 402330300Sjoerg ch[3] = seed ^ random(); 402430300Sjoerg clen = AUTHKEYLEN; 402530300Sjoerg 402678064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 402730300Sjoerg 402830300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 402930300Sjoerg sizeof clen, (const char *)&clen, 403040008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 403140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 403230300Sjoerg sp->myauth.name, 403330300Sjoerg 0); 403430300Sjoerg} 403570199Sjhay 403670199Sjhay/* 403730300Sjoerg *--------------------------------------------------------------------------* 403830300Sjoerg * * 403930300Sjoerg * The PAP implementation. * 404030300Sjoerg * * 404130300Sjoerg *--------------------------------------------------------------------------* 404230300Sjoerg */ 404330300Sjoerg/* 404430300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 404530300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 404630300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 404730300Sjoerg * retry counter is expired). 404830300Sjoerg */ 404930300Sjoerg 405030300Sjoerg/* 405130300Sjoerg * Handle incoming PAP packets. */ 405230300Sjoergstatic void 405330300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 405430300Sjoerg{ 405530300Sjoerg STDDCL; 405630300Sjoerg struct lcp_header *h; 405730300Sjoerg int len, x; 405830300Sjoerg u_char *name, *passwd, mlen; 405930300Sjoerg int name_len, passwd_len; 406030300Sjoerg 406130300Sjoerg len = m->m_pkthdr.len; 406230300Sjoerg if (len < 5) { 406330300Sjoerg if (debug) 406430300Sjoerg log(LOG_DEBUG, 406540008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 406640008Sjoerg SPP_ARGS(ifp), len); 406730300Sjoerg return; 406830300Sjoerg } 406930300Sjoerg h = mtod (m, struct lcp_header*); 407030300Sjoerg if (len > ntohs (h->len)) 407130300Sjoerg len = ntohs (h->len); 407230300Sjoerg switch (h->type) { 407330300Sjoerg /* PAP request is my authproto */ 407430300Sjoerg case PAP_REQ: 407530300Sjoerg name = 1 + (u_char*)(h+1); 407630300Sjoerg name_len = name[-1]; 407730300Sjoerg passwd = name + name_len + 1; 407830300Sjoerg if (name_len > len - 6 || 407930300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 408030300Sjoerg if (debug) { 408140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 408230300Sjoerg "<%s id=0x%x len=%d", 408340008Sjoerg SPP_ARGS(ifp), 408430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 408530300Sjoerg h->ident, ntohs(h->len)); 408644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 408769211Sphk log(-1, ">\n"); 408830300Sjoerg } 408930300Sjoerg break; 409030300Sjoerg } 409130300Sjoerg if (debug) { 409240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 409330300Sjoerg "<%s id=0x%x len=%d name=", 409440008Sjoerg SPP_ARGS(ifp), 409530300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 409630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 409730300Sjoerg h->ident, ntohs(h->len)); 409830300Sjoerg sppp_print_string((char*)name, name_len); 409969211Sphk log(-1, " passwd="); 410030300Sjoerg sppp_print_string((char*)passwd, passwd_len); 410169211Sphk log(-1, ">\n"); 410230300Sjoerg } 410374774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 410474774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 410530300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 410630300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 410730300Sjoerg /* action scn, tld */ 410830300Sjoerg mlen = sizeof(FAILMSG) - 1; 410930300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 411030300Sjoerg sizeof mlen, (const char *)&mlen, 411130300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 411230300Sjoerg 0); 411330300Sjoerg pap.tld(sp); 411430300Sjoerg break; 411530300Sjoerg } 411630300Sjoerg /* action sca, perhaps tlu */ 411730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 411830300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 411930300Sjoerg mlen = sizeof(SUCCMSG) - 1; 412030300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 412130300Sjoerg sizeof mlen, (const char *)&mlen, 412230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 412330300Sjoerg 0); 412430300Sjoerg } 412530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 412630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 412730300Sjoerg pap.tlu(sp); 412830300Sjoerg } 412930300Sjoerg break; 413030300Sjoerg 413130300Sjoerg /* ack and nak are his authproto */ 413230300Sjoerg case PAP_ACK: 413340008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 413430300Sjoerg if (debug) { 413540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 413640008Sjoerg SPP_ARGS(ifp)); 413730300Sjoerg name_len = *((char *)h); 413830300Sjoerg if (len > 5 && name_len) { 413969211Sphk log(-1, ": "); 414030300Sjoerg sppp_print_string((char*)(h+1), name_len); 414130300Sjoerg } 414269211Sphk log(-1, "\n"); 414330300Sjoerg } 414430300Sjoerg x = splimp(); 414530300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 414630300Sjoerg if (sp->myauth.proto == PPP_PAP && 414732169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 414830300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 414930300Sjoerg /* 415030300Sjoerg * We are authenticator for PAP but didn't 415130300Sjoerg * complete yet. Leave it to tlu to proceed 415230300Sjoerg * to network phase. 415330300Sjoerg */ 415430300Sjoerg splx(x); 415530300Sjoerg break; 415630300Sjoerg } 415730300Sjoerg splx(x); 415830300Sjoerg sppp_phase_network(sp); 415930300Sjoerg break; 416030300Sjoerg 416130300Sjoerg case PAP_NAK: 416240008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 416330300Sjoerg if (debug) { 416440008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 416540008Sjoerg SPP_ARGS(ifp)); 416630300Sjoerg name_len = *((char *)h); 416730300Sjoerg if (len > 5 && name_len) { 416869211Sphk log(-1, ": "); 416930300Sjoerg sppp_print_string((char*)(h+1), name_len); 417030300Sjoerg } 417169211Sphk log(-1, "\n"); 417230300Sjoerg } else 417340008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 417440008Sjoerg SPP_ARGS(ifp)); 417530300Sjoerg /* await LCP shutdown by authenticator */ 417630300Sjoerg break; 417730300Sjoerg 417830300Sjoerg default: 417930300Sjoerg /* Unknown PAP packet type -- ignore. */ 418030300Sjoerg if (debug) { 418140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 418230300Sjoerg "<0x%x id=0x%x len=%d", 418340008Sjoerg SPP_ARGS(ifp), 418430300Sjoerg h->type, h->ident, ntohs(h->len)); 418544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 418669211Sphk log(-1, ">\n"); 418730300Sjoerg } 418830300Sjoerg break; 418930300Sjoerg 419030300Sjoerg } 419130300Sjoerg} 419230300Sjoerg 419330300Sjoergstatic void 419430300Sjoergsppp_pap_init(struct sppp *sp) 419530300Sjoerg{ 419630300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 419730300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 419830300Sjoerg sp->fail_counter[IDX_PAP] = 0; 419978064Sume sp->pp_seq[IDX_PAP] = 0; 420078064Sume sp->pp_rseq[IDX_PAP] = 0; 420142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 420230300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 420330300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 420440008Sjoerg#endif 420530300Sjoerg} 420630300Sjoerg 420730300Sjoergstatic void 420830300Sjoergsppp_pap_open(struct sppp *sp) 420930300Sjoerg{ 421030300Sjoerg if (sp->hisauth.proto == PPP_PAP && 421130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 421230300Sjoerg /* we are authenticator for PAP, start our timer */ 421330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 421430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 421530300Sjoerg } 421630300Sjoerg if (sp->myauth.proto == PPP_PAP) { 421730300Sjoerg /* we are peer, send a request, and start a timer */ 421830300Sjoerg pap.scr(sp); 421942064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 422042064Sphk sp->pap_my_to_ch); 422130300Sjoerg } 422230300Sjoerg} 422330300Sjoerg 422430300Sjoergstatic void 422530300Sjoergsppp_pap_close(struct sppp *sp) 422630300Sjoerg{ 422730300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 422830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 422930300Sjoerg} 423030300Sjoerg 423130300Sjoerg/* 423230300Sjoerg * That's the timeout routine if we are authenticator. Since the 423330300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 423430300Sjoerg */ 423530300Sjoergstatic void 423630300Sjoergsppp_pap_TO(void *cookie) 423730300Sjoerg{ 423830300Sjoerg struct sppp *sp = (struct sppp *)cookie; 423930300Sjoerg STDDCL; 424030300Sjoerg int s; 424130300Sjoerg 424230300Sjoerg s = splimp(); 424330300Sjoerg if (debug) 424440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 424540008Sjoerg SPP_ARGS(ifp), 424630300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 424730300Sjoerg sp->rst_counter[IDX_PAP]); 424830300Sjoerg 424930300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 425030300Sjoerg /* TO- event */ 425130300Sjoerg switch (sp->state[IDX_PAP]) { 425230300Sjoerg case STATE_REQ_SENT: 425330300Sjoerg pap.tld(sp); 425430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 425530300Sjoerg break; 425630300Sjoerg } 425730300Sjoerg else 425830300Sjoerg /* TO+ event, not very much we could do */ 425930300Sjoerg switch (sp->state[IDX_PAP]) { 426030300Sjoerg case STATE_REQ_SENT: 426130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 426230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 426330300Sjoerg break; 426430300Sjoerg } 426530300Sjoerg 426630300Sjoerg splx(s); 426730300Sjoerg} 426830300Sjoerg 426930300Sjoerg/* 427030300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 427130300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 427230300Sjoerg * XXX We should impose a max counter. 427330300Sjoerg */ 427430300Sjoergstatic void 427530300Sjoergsppp_pap_my_TO(void *cookie) 427630300Sjoerg{ 427730300Sjoerg struct sppp *sp = (struct sppp *)cookie; 427830300Sjoerg STDDCL; 427930300Sjoerg 428030300Sjoerg if (debug) 428140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 428240008Sjoerg SPP_ARGS(ifp)); 428330300Sjoerg 428430300Sjoerg pap.scr(sp); 428530300Sjoerg} 428630300Sjoerg 428730300Sjoergstatic void 428830300Sjoergsppp_pap_tlu(struct sppp *sp) 428930300Sjoerg{ 429030300Sjoerg STDDCL; 429130300Sjoerg int x; 429230300Sjoerg 429330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 429430300Sjoerg 429530300Sjoerg if (debug) 429640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 429740008Sjoerg SPP_ARGS(ifp), pap.name); 429830300Sjoerg 429930300Sjoerg x = splimp(); 430030300Sjoerg /* indicate to LCP that we need to be closed down */ 430130300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 430230300Sjoerg 430330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 430430300Sjoerg /* 430530300Sjoerg * Remote is authenticator, but his auth proto didn't 430630300Sjoerg * complete yet. Defer the transition to network 430730300Sjoerg * phase. 430830300Sjoerg */ 430930300Sjoerg splx(x); 431030300Sjoerg return; 431130300Sjoerg } 431230300Sjoerg splx(x); 431330300Sjoerg sppp_phase_network(sp); 431430300Sjoerg} 431530300Sjoerg 431630300Sjoergstatic void 431730300Sjoergsppp_pap_tld(struct sppp *sp) 431830300Sjoerg{ 431930300Sjoerg STDDCL; 432030300Sjoerg 432130300Sjoerg if (debug) 432240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 432340008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 432440008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 432530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 432630300Sjoerg 432730300Sjoerg lcp.Close(sp); 432830300Sjoerg} 432930300Sjoerg 433030300Sjoergstatic void 433130300Sjoergsppp_pap_scr(struct sppp *sp) 433230300Sjoerg{ 433330300Sjoerg u_char idlen, pwdlen; 433430300Sjoerg 433578064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 433630300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 433730300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 433830300Sjoerg 433930300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 434030300Sjoerg sizeof idlen, (const char *)&idlen, 434140008Sjoerg (size_t)idlen, sp->myauth.name, 434230300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 434340008Sjoerg (size_t)pwdlen, sp->myauth.secret, 434430300Sjoerg 0); 434530300Sjoerg} 434670199Sjhay 434770199Sjhay/* 434825944Sjoerg * Random miscellaneous functions. 434925944Sjoerg */ 435025944Sjoerg 43514910Swollman/* 435230300Sjoerg * Send a PAP or CHAP proto packet. 435330300Sjoerg * 435430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 435540008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 435630300Sjoerg * mlen == 0. 435742104Sphk * NOTE: never declare variadic functions with types subject to type 435842104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 435942104Sphk * on the architecture you are on... 436030300Sjoerg */ 436130300Sjoerg 436230300Sjoergstatic void 436342104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 436442104Sphk unsigned int type, unsigned int id, 436530300Sjoerg ...) 436630300Sjoerg{ 436730300Sjoerg STDDCL; 436830300Sjoerg struct ppp_header *h; 436930300Sjoerg struct lcp_header *lh; 437030300Sjoerg struct mbuf *m; 437130300Sjoerg u_char *p; 437230300Sjoerg int len; 437342104Sphk unsigned int mlen; 437430300Sjoerg const char *msg; 437530300Sjoerg va_list ap; 437630300Sjoerg 437730300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 437830300Sjoerg if (! m) 437930300Sjoerg return; 438030300Sjoerg m->m_pkthdr.rcvif = 0; 438130300Sjoerg 438230300Sjoerg h = mtod (m, struct ppp_header*); 438330300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 438430300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 438530300Sjoerg h->protocol = htons(cp->proto); 438630300Sjoerg 438730300Sjoerg lh = (struct lcp_header*)(h + 1); 438830300Sjoerg lh->type = type; 438930300Sjoerg lh->ident = id; 439030300Sjoerg p = (u_char*) (lh+1); 439130300Sjoerg 439230300Sjoerg va_start(ap, id); 439330300Sjoerg len = 0; 439430300Sjoerg 439542104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 439630300Sjoerg msg = va_arg(ap, const char *); 439730300Sjoerg len += mlen; 439830300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 439930300Sjoerg va_end(ap); 440030300Sjoerg m_freem(m); 440130300Sjoerg return; 440230300Sjoerg } 440330300Sjoerg 440430300Sjoerg bcopy(msg, p, mlen); 440530300Sjoerg p += mlen; 440630300Sjoerg } 440730300Sjoerg va_end(ap); 440830300Sjoerg 440930300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 441030300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 441130300Sjoerg 441230300Sjoerg if (debug) { 441340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 441440008Sjoerg SPP_ARGS(ifp), cp->name, 441530300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 441630300Sjoerg lh->ident, ntohs(lh->len)); 441744145Sphk sppp_print_bytes((u_char*) (lh+1), len); 441869211Sphk log(-1, ">\n"); 441930300Sjoerg } 442069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 442169152Sjlemon ifp->if_oerrors++; 442230300Sjoerg} 442330300Sjoerg 442430300Sjoerg/* 442525944Sjoerg * Flush interface queue. 44264910Swollman */ 442712820Sphkstatic void 442825944Sjoergsppp_qflush(struct ifqueue *ifq) 44294910Swollman{ 443025944Sjoerg struct mbuf *m, *n; 44314910Swollman 443225944Sjoerg n = ifq->ifq_head; 443325944Sjoerg while ((m = n)) { 443425944Sjoerg n = m->m_act; 443525944Sjoerg m_freem (m); 443611189Sjkh } 443725944Sjoerg ifq->ifq_head = 0; 443825944Sjoerg ifq->ifq_tail = 0; 443925944Sjoerg ifq->ifq_len = 0; 444025944Sjoerg} 444125944Sjoerg 444225944Sjoerg/* 444325944Sjoerg * Send keepalive packets, every 10 seconds. 444425944Sjoerg */ 444525944Sjoergstatic void 444625944Sjoergsppp_keepalive(void *dummy) 444725944Sjoerg{ 444825944Sjoerg struct sppp *sp; 444925944Sjoerg int s; 445025944Sjoerg 445125944Sjoerg s = splimp(); 445225944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 445325944Sjoerg struct ifnet *ifp = &sp->pp_if; 445425944Sjoerg 445525944Sjoerg /* Keepalive mode disabled or channel down? */ 445625944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 445725944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 445825944Sjoerg continue; 445925944Sjoerg 446025944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 446145152Sphk if (sp->pp_mode != IFF_CISCO && 446225944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 446325944Sjoerg continue; 446425944Sjoerg 446525944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 446625944Sjoerg /* No keepalive packets got. Stop the interface. */ 446740008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 446825944Sjoerg if_down (ifp); 446926018Sjoerg sppp_qflush (&sp->pp_cpq); 447045152Sphk if (sp->pp_mode != IFF_CISCO) { 447125944Sjoerg /* XXX */ 447225944Sjoerg /* Shut down the PPP link. */ 447325944Sjoerg lcp.Down(sp); 447425944Sjoerg /* Initiate negotiation. XXX */ 447525944Sjoerg lcp.Up(sp); 447625944Sjoerg } 44774910Swollman } 447825944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 447925944Sjoerg ++sp->pp_alivecnt; 448045152Sphk if (sp->pp_mode == IFF_CISCO) 448178064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 448278064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 448325944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 448425944Sjoerg long nmagic = htonl (sp->lcp.magic); 448578064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 448625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 448725944Sjoerg sp->lcp.echoid, 4, &nmagic); 448825944Sjoerg } 44894910Swollman } 449025944Sjoerg splx(s); 449142064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 44924910Swollman} 44934910Swollman 449425944Sjoerg/* 449525944Sjoerg * Get both IP addresses. 449625944Sjoerg */ 449725944Sjoergstatic void 449830300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 449925944Sjoerg{ 450025944Sjoerg struct ifnet *ifp = &sp->pp_if; 450125944Sjoerg struct ifaddr *ifa; 450230300Sjoerg struct sockaddr_in *si, *sm; 450325944Sjoerg u_long ssrc, ddst; 450425944Sjoerg 450540010Sjoerg sm = NULL; 450625944Sjoerg ssrc = ddst = 0L; 450725944Sjoerg /* 450825944Sjoerg * Pick the first AF_INET address from the list, 450925944Sjoerg * aliases don't make any sense on a p2p link anyway. 451025944Sjoerg */ 451142065Sphk si = 0; 451242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 451342065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 451442104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 451571959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 451640008Sjoerg ifa; 451771959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 451842104Sphk#else 451942104Sphk for (ifa = ifp->if_addrlist; 452042104Sphk ifa; 452142104Sphk ifa = ifa->ifa_next) 452240008Sjoerg#endif 452325944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 452425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 452530300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 452625944Sjoerg if (si) 452725944Sjoerg break; 452825944Sjoerg } 452925944Sjoerg if (ifa) { 453030300Sjoerg if (si && si->sin_addr.s_addr) { 453125944Sjoerg ssrc = si->sin_addr.s_addr; 453230300Sjoerg if (srcmask) 453330300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 453430300Sjoerg } 453525944Sjoerg 453625944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 453725944Sjoerg if (si && si->sin_addr.s_addr) 453825944Sjoerg ddst = si->sin_addr.s_addr; 453925944Sjoerg } 454025944Sjoerg 454125944Sjoerg if (dst) *dst = ntohl(ddst); 454225944Sjoerg if (src) *src = ntohl(ssrc); 454325944Sjoerg} 454425944Sjoerg 454525944Sjoerg/* 454625944Sjoerg * Set my IP address. Must be called at splimp. 454725944Sjoerg */ 454825944Sjoergstatic void 454925944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 455025944Sjoerg{ 455142104Sphk STDDCL; 455225944Sjoerg struct ifaddr *ifa; 455325944Sjoerg struct sockaddr_in *si; 455484318Sjlemon struct in_ifaddr *ia; 455525944Sjoerg 455625944Sjoerg /* 455725944Sjoerg * Pick the first AF_INET address from the list, 455825944Sjoerg * aliases don't make any sense on a p2p link anyway. 455925944Sjoerg */ 456042065Sphk si = 0; 456142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 456242065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 456342104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 456471959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 456540008Sjoerg ifa; 456671959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 456742104Sphk#else 456842104Sphk for (ifa = ifp->if_addrlist; 456942104Sphk ifa; 457042104Sphk ifa = ifa->ifa_next) 457140008Sjoerg#endif 457240008Sjoerg { 457340008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 457440008Sjoerg { 457525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 457625944Sjoerg if (si) 457725944Sjoerg break; 457825944Sjoerg } 457940008Sjoerg } 458040008Sjoerg 458125944Sjoerg if (ifa && si) 458242104Sphk { 458342104Sphk int error; 458442104Sphk#if __NetBSD_Version__ >= 103080000 458542104Sphk struct sockaddr_in new_sin = *si; 458642104Sphk 458742104Sphk new_sin.sin_addr.s_addr = htonl(src); 458842104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 458942104Sphk if(debug && error) 459042104Sphk { 459142104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 459242104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 459342104Sphk } 459442104Sphk#else 459542104Sphk /* delete old route */ 459642104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 459742104Sphk if(debug && error) 459842104Sphk { 459942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 460042104Sphk SPP_ARGS(ifp), error); 460142104Sphk } 460242104Sphk 460342104Sphk /* set new address */ 460425944Sjoerg si->sin_addr.s_addr = htonl(src); 460584318Sjlemon ia = ifatoia(ifa); 460684318Sjlemon LIST_REMOVE(ia, ia_hash); 460784318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 460825944Sjoerg 460942104Sphk /* add new route */ 461070199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 461142104Sphk if (debug && error) 461242104Sphk { 461342104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 461442104Sphk SPP_ARGS(ifp), error); 461542104Sphk } 461642104Sphk#endif 461742104Sphk } 461878064Sume} 461978064Sume 462078064Sume#ifdef INET6 462178064Sume/* 462278064Sume * Get both IPv6 addresses. 462378064Sume */ 462478064Sumestatic void 462578064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 462678064Sume struct in6_addr *srcmask) 462778064Sume{ 462878064Sume struct ifnet *ifp = &sp->pp_if; 462978064Sume struct ifaddr *ifa; 463078064Sume struct sockaddr_in6 *si, *sm; 463178064Sume struct in6_addr ssrc, ddst; 463278064Sume 463378064Sume sm = NULL; 463478064Sume bzero(&ssrc, sizeof(ssrc)); 463578064Sume bzero(&ddst, sizeof(ddst)); 463678064Sume /* 463778064Sume * Pick the first link-local AF_INET6 address from the list, 463878064Sume * aliases don't make any sense on a p2p link anyway. 463978064Sume */ 464078064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 464178064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 464278064Sume ifa; 464378064Sume ifa = ifa->ifa_link.tqe_next) 464478064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 464578064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 464678064Sume ifa; 464778064Sume ifa = ifa->ifa_list.tqe_next) 464878064Sume#else 464978064Sume for (ifa = ifp->if_addrlist, si = 0; 465078064Sume ifa; 465178064Sume ifa = ifa->ifa_next) 465278064Sume#endif 465378064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 465478064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 465578064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 465678064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 465778064Sume break; 465878064Sume } 465978064Sume if (ifa) { 466078064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 466178064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 466278064Sume if (srcmask) { 466378064Sume bcopy(&sm->sin6_addr, srcmask, 466478064Sume sizeof(*srcmask)); 466578064Sume } 466678064Sume } 466778064Sume 466878064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 466978064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 467078064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 467178064Sume } 467278064Sume 467378064Sume if (dst) 467478064Sume bcopy(&ddst, dst, sizeof(*dst)); 467578064Sume if (src) 467678064Sume bcopy(&ssrc, src, sizeof(*src)); 467770199Sjhay} 467842104Sphk 467978064Sume#ifdef IPV6CP_MYIFID_DYN 468078064Sume/* 468178064Sume * Generate random ifid. 468278064Sume */ 468378064Sumestatic void 468478064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 468578064Sume{ 468678064Sume /* TBD */ 468778064Sume} 468878064Sume 468978064Sume/* 469078064Sume * Set my IPv6 address. Must be called at splimp. 469178064Sume */ 469278064Sumestatic void 469378064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 469478064Sume{ 469578064Sume STDDCL; 469678064Sume struct ifaddr *ifa; 469778064Sume struct sockaddr_in6 *sin6; 469878064Sume 469978064Sume /* 470078064Sume * Pick the first link-local AF_INET6 address from the list, 470178064Sume * aliases don't make any sense on a p2p link anyway. 470278064Sume */ 470378064Sume 470478064Sume sin6 = NULL; 470578064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 470678064Sume for (ifa = ifp->if_addrhead.tqh_first; 470778064Sume ifa; 470878064Sume ifa = ifa->ifa_link.tqe_next) 470978064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 471078064Sume for (ifa = ifp->if_addrlist.tqh_first; 471178064Sume ifa; 471278064Sume ifa = ifa->ifa_list.tqe_next) 471378064Sume#else 471478064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 471578064Sume#endif 471678064Sume { 471778064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 471878064Sume { 471978064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 472078064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 472178064Sume break; 472278064Sume } 472378064Sume } 472478064Sume 472578064Sume if (ifa && sin6) 472678064Sume { 472778064Sume int error; 472878064Sume struct sockaddr_in6 new_sin6 = *sin6; 472978064Sume 473078064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 473178064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 473278064Sume if (debug && error) 473378064Sume { 473478064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 473578064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 473678064Sume } 473778064Sume } 473878064Sume} 473978064Sume#endif 474078064Sume 474178064Sume/* 474278064Sume * Suggest a candidate address to be used by peer. 474378064Sume */ 474478064Sumestatic void 474578064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 474678064Sume{ 474778064Sume struct in6_addr myaddr; 474878064Sume struct timeval tv; 474978064Sume 475078064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 475178064Sume 475278064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 475378064Sume microtime(&tv); 475478064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 475578064Sume myaddr.s6_addr[14] ^= 0xff; 475678064Sume myaddr.s6_addr[15] ^= 0xff; 475778064Sume } else { 475878064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 475978064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 476078064Sume } 476178064Sume if (suggest) 476278064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 476378064Sume} 476478064Sume#endif /*INET6*/ 476578064Sume 476630300Sjoergstatic int 476738343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 476830300Sjoerg{ 476938343Sbde u_long subcmd; 477030300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 477130300Sjoerg struct spppreq spr; 477230300Sjoerg 477330300Sjoerg /* 477430300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 477530300Sjoerg * Check the cmd word first before attempting to fetch all the 477630300Sjoerg * data. 477730300Sjoerg */ 477830300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 477930300Sjoerg return EFAULT; 478030300Sjoerg 478130300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 478230300Sjoerg return EFAULT; 478330300Sjoerg 478430300Sjoerg switch (subcmd) { 478530300Sjoerg case SPPPIOGDEFS: 478630300Sjoerg if (cmd != SIOCGIFGENERIC) 478730300Sjoerg return EINVAL; 478830300Sjoerg /* 478930300Sjoerg * We copy over the entire current state, but clean 479030300Sjoerg * out some of the stuff we don't wanna pass up. 479130300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 479230300Sjoerg * called by any user. No need to ever get PAP or 479330300Sjoerg * CHAP secrets back to userland anyway. 479430300Sjoerg */ 479530300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 479630300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 479730300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 479830300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 479930300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 480030300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 480130300Sjoerg 480230300Sjoerg case SPPPIOSDEFS: 480330300Sjoerg if (cmd != SIOCSIFGENERIC) 480430300Sjoerg return EINVAL; 480530300Sjoerg /* 480630300Sjoerg * We have a very specific idea of which fields we allow 480730300Sjoerg * being passed back from userland, so to not clobber our 480830300Sjoerg * current state. For one, we only allow setting 480930300Sjoerg * anything if LCP is in dead phase. Once the LCP 481030300Sjoerg * negotiations started, the authentication settings must 481130300Sjoerg * not be changed again. (The administrator can force an 481230300Sjoerg * ifconfig down in order to get LCP back into dead 481330300Sjoerg * phase.) 481430300Sjoerg * 481530300Sjoerg * Also, we only allow for authentication parameters to be 481630300Sjoerg * specified. 481730300Sjoerg * 481830300Sjoerg * XXX Should allow to set or clear pp_flags. 481930300Sjoerg * 482030300Sjoerg * Finally, if the respective authentication protocol to 482130300Sjoerg * be used is set differently than 0, but the secret is 482230300Sjoerg * passed as all zeros, we don't trash the existing secret. 482330300Sjoerg * This allows an administrator to change the system name 482430300Sjoerg * only without clobbering the secret (which he didn't get 482530300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 482630300Sjoerg * secrets are cleared if the authentication protocol is 482730300Sjoerg * reset to 0. 482830300Sjoerg */ 482930300Sjoerg if (sp->pp_phase != PHASE_DEAD) 483030300Sjoerg return EBUSY; 483130300Sjoerg 483230300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 483330300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 483430300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 483530300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 483630300Sjoerg return EINVAL; 483730300Sjoerg 483830300Sjoerg if (spr.defs.myauth.proto == 0) 483930300Sjoerg /* resetting myauth */ 484030300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 484130300Sjoerg else { 484230300Sjoerg /* setting/changing myauth */ 484330300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 484430300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 484530300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 484630300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 484730300Sjoerg AUTHKEYLEN); 484830300Sjoerg } 484930300Sjoerg if (spr.defs.hisauth.proto == 0) 485030300Sjoerg /* resetting hisauth */ 485130300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 485230300Sjoerg else { 485330300Sjoerg /* setting/changing hisauth */ 485430300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 485530300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 485630300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 485730300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 485830300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 485930300Sjoerg AUTHKEYLEN); 486030300Sjoerg } 486130300Sjoerg break; 486230300Sjoerg 486330300Sjoerg default: 486430300Sjoerg return EINVAL; 486530300Sjoerg } 486630300Sjoerg 486730300Sjoerg return 0; 486830300Sjoerg} 486930300Sjoerg 487030300Sjoergstatic void 487130300Sjoergsppp_phase_network(struct sppp *sp) 487230300Sjoerg{ 487342066Sphk STDDCL; 487430300Sjoerg int i; 487530300Sjoerg u_long mask; 487630300Sjoerg 487730300Sjoerg sp->pp_phase = PHASE_NETWORK; 487830300Sjoerg 487942066Sphk if (debug) 488042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 488142066Sphk sppp_phase_name(sp->pp_phase)); 488230300Sjoerg 488330300Sjoerg /* Notify NCPs now. */ 488430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 488530300Sjoerg if ((cps[i])->flags & CP_NCP) 488630300Sjoerg (cps[i])->Open(sp); 488730300Sjoerg 488830300Sjoerg /* Send Up events to all NCPs. */ 488930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 489030300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 489130300Sjoerg (cps[i])->Up(sp); 489230300Sjoerg 489330300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 489430300Sjoerg sppp_lcp_check_and_close(sp); 489530300Sjoerg} 489630300Sjoerg 489770199Sjhay 489825706Sjoergstatic const char * 489925944Sjoergsppp_cp_type_name(u_char type) 49004910Swollman{ 490130300Sjoerg static char buf[12]; 49024910Swollman switch (type) { 490330300Sjoerg case CONF_REQ: return "conf-req"; 490430300Sjoerg case CONF_ACK: return "conf-ack"; 490530300Sjoerg case CONF_NAK: return "conf-nak"; 490630300Sjoerg case CONF_REJ: return "conf-rej"; 490730300Sjoerg case TERM_REQ: return "term-req"; 490830300Sjoerg case TERM_ACK: return "term-ack"; 490930300Sjoerg case CODE_REJ: return "code-rej"; 491030300Sjoerg case PROTO_REJ: return "proto-rej"; 491130300Sjoerg case ECHO_REQ: return "echo-req"; 491230300Sjoerg case ECHO_REPLY: return "echo-reply"; 491330300Sjoerg case DISC_REQ: return "discard-req"; 49144910Swollman } 491544145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 491630300Sjoerg return buf; 49174910Swollman} 49184910Swollman 491925706Sjoergstatic const char * 492030300Sjoergsppp_auth_type_name(u_short proto, u_char type) 492130300Sjoerg{ 492230300Sjoerg static char buf[12]; 492330300Sjoerg switch (proto) { 492430300Sjoerg case PPP_CHAP: 492530300Sjoerg switch (type) { 492630300Sjoerg case CHAP_CHALLENGE: return "challenge"; 492730300Sjoerg case CHAP_RESPONSE: return "response"; 492830300Sjoerg case CHAP_SUCCESS: return "success"; 492930300Sjoerg case CHAP_FAILURE: return "failure"; 493030300Sjoerg } 493130300Sjoerg case PPP_PAP: 493230300Sjoerg switch (type) { 493330300Sjoerg case PAP_REQ: return "req"; 493430300Sjoerg case PAP_ACK: return "ack"; 493530300Sjoerg case PAP_NAK: return "nak"; 493630300Sjoerg } 493730300Sjoerg } 493844145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 493930300Sjoerg return buf; 494030300Sjoerg} 494130300Sjoerg 494230300Sjoergstatic const char * 494325944Sjoergsppp_lcp_opt_name(u_char opt) 49444910Swollman{ 494530300Sjoerg static char buf[12]; 494625944Sjoerg switch (opt) { 494730300Sjoerg case LCP_OPT_MRU: return "mru"; 494830300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 494930300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 495030300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 495130300Sjoerg case LCP_OPT_MAGIC: return "magic"; 495230300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 495330300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 49544910Swollman } 495544145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 495630300Sjoerg return buf; 49574910Swollman} 49584910Swollman 495925944Sjoergstatic const char * 496025944Sjoergsppp_ipcp_opt_name(u_char opt) 496125944Sjoerg{ 496230300Sjoerg static char buf[12]; 496325944Sjoerg switch (opt) { 496430300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 496530300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 496630300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 496725944Sjoerg } 496844145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 496930300Sjoerg return buf; 497025944Sjoerg} 497125944Sjoerg 497278064Sume#ifdef INET6 497325944Sjoergstatic const char * 497478064Sumesppp_ipv6cp_opt_name(u_char opt) 497578064Sume{ 497678064Sume static char buf[12]; 497778064Sume switch (opt) { 497878064Sume case IPV6CP_OPT_IFID: return "ifid"; 497978064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 498078064Sume } 498178064Sume sprintf (buf, "0x%x", opt); 498278064Sume return buf; 498378064Sume} 498478064Sume#endif 498578064Sume 498678064Sumestatic const char * 498725944Sjoergsppp_state_name(int state) 498825944Sjoerg{ 498925944Sjoerg switch (state) { 499025944Sjoerg case STATE_INITIAL: return "initial"; 499125944Sjoerg case STATE_STARTING: return "starting"; 499225944Sjoerg case STATE_CLOSED: return "closed"; 499325944Sjoerg case STATE_STOPPED: return "stopped"; 499425944Sjoerg case STATE_CLOSING: return "closing"; 499525944Sjoerg case STATE_STOPPING: return "stopping"; 499625944Sjoerg case STATE_REQ_SENT: return "req-sent"; 499725944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 499825944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 499925944Sjoerg case STATE_OPENED: return "opened"; 500025944Sjoerg } 500125944Sjoerg return "illegal"; 500225944Sjoerg} 500325944Sjoerg 500425944Sjoergstatic const char * 500525944Sjoergsppp_phase_name(enum ppp_phase phase) 500625944Sjoerg{ 500725944Sjoerg switch (phase) { 500825944Sjoerg case PHASE_DEAD: return "dead"; 500925944Sjoerg case PHASE_ESTABLISH: return "establish"; 501025944Sjoerg case PHASE_TERMINATE: return "terminate"; 501125944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 501225944Sjoerg case PHASE_NETWORK: return "network"; 501325944Sjoerg } 501425944Sjoerg return "illegal"; 501525944Sjoerg} 501625944Sjoerg 501725944Sjoergstatic const char * 501825944Sjoergsppp_proto_name(u_short proto) 501925944Sjoerg{ 502025944Sjoerg static char buf[12]; 502125944Sjoerg switch (proto) { 502225944Sjoerg case PPP_LCP: return "lcp"; 502325944Sjoerg case PPP_IPCP: return "ipcp"; 502430300Sjoerg case PPP_PAP: return "pap"; 502530300Sjoerg case PPP_CHAP: return "chap"; 502678064Sume case PPP_IPV6CP: return "ipv6cp"; 502725944Sjoerg } 502844145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 502925944Sjoerg return buf; 503025944Sjoerg} 503125944Sjoerg 503212820Sphkstatic void 503330300Sjoergsppp_print_bytes(const u_char *p, u_short len) 50344910Swollman{ 503544145Sphk if (len) 503669211Sphk log(-1, " %*D", len, p, "-"); 50374910Swollman} 503825944Sjoerg 503930300Sjoergstatic void 504030300Sjoergsppp_print_string(const char *p, u_short len) 504130300Sjoerg{ 504230300Sjoerg u_char c; 504330300Sjoerg 504430300Sjoerg while (len-- > 0) { 504530300Sjoerg c = *p++; 504630300Sjoerg /* 504730300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 504830300Sjoerg * using only them, but we don't rely on it. */ 504930300Sjoerg if (c < ' ' || c > '~') 505069211Sphk log(-1, "\\x%x", c); 505130300Sjoerg else 505269211Sphk log(-1, "%c", c); 505330300Sjoerg } 505430300Sjoerg} 505530300Sjoerg 505630300Sjoergstatic const char * 505730300Sjoergsppp_dotted_quad(u_long addr) 505830300Sjoerg{ 505930300Sjoerg static char s[16]; 506030300Sjoerg sprintf(s, "%d.%d.%d.%d", 506140008Sjoerg (int)((addr >> 24) & 0xff), 506240008Sjoerg (int)((addr >> 16) & 0xff), 506340008Sjoerg (int)((addr >> 8) & 0xff), 506438372Sbde (int)(addr & 0xff)); 506530300Sjoerg return s; 506630300Sjoerg} 506730300Sjoerg 506830300Sjoergstatic int 506930300Sjoergsppp_strnlen(u_char *p, int max) 507030300Sjoerg{ 507130300Sjoerg int len; 507230300Sjoerg 507330300Sjoerg for (len = 0; len < max && *p; ++p) 507430300Sjoerg ++len; 507530300Sjoerg return len; 507630300Sjoerg} 507730300Sjoerg 507830300Sjoerg/* a dummy, used to drop uninteresting events */ 507930300Sjoergstatic void 508030300Sjoergsppp_null(struct sppp *unused) 508130300Sjoerg{ 508230300Sjoerg /* do just nothing */ 508330300Sjoerg} 5084