if_spppsubr.c revision 78064
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 78064 2001-06-11 12:39:29Z ume $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2940008Sjoerg#endif 3031742Seivind 3140008Sjoerg#ifdef NetBSD1_3 3240008Sjoerg# if NetBSD1_3 > 6 3340008Sjoerg# include "opt_inet.h" 3454263Sshin# include "opt_inet6.h" 3540008Sjoerg# include "opt_iso.h" 3640008Sjoerg# endif 3740008Sjoerg#endif 3840008Sjoerg 394952Sbde#include <sys/systm.h> 404952Sbde#include <sys/kernel.h> 4170199Sjhay#include <sys/module.h> 4224204Sbde#include <sys/sockio.h> 434910Swollman#include <sys/socket.h> 4425706Sjoerg#include <sys/syslog.h> 4542104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4659604Sobrien#include <sys/random.h> 4742104Sphk#endif 4829024Sbde#include <sys/malloc.h> 494910Swollman#include <sys/mbuf.h> 5040008Sjoerg 5140008Sjoerg#if defined (__OpenBSD__) 5240008Sjoerg#include <sys/md5k.h> 5340008Sjoerg#else 5430300Sjoerg#include <sys/md5.h> 5540008Sjoerg#endif 564910Swollman 574910Swollman#include <net/if.h> 584910Swollman#include <net/netisr.h> 594910Swollman#include <net/if_types.h> 6042104Sphk#include <net/route.h> 614910Swollman 6240008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6340008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6440008Sjoerg#endif 6542104Sphk 6630300Sjoerg#include <machine/stdarg.h> 6730300Sjoerg 684910Swollman#ifdef INET 694910Swollman#include <netinet/in.h> 704910Swollman#include <netinet/in_systm.h> 714910Swollman#include <netinet/in_var.h> 724910Swollman#include <netinet/ip.h> 734910Swollman#include <netinet/tcp.h> 7440008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7540008Sjoerg# include <netinet/if_ether.h> 7640008Sjoerg# else 7740008Sjoerg# include <net/ethertypes.h> 7840008Sjoerg# endif 7932350Seivind#else 8040008Sjoerg# error Huh? sppp without INET? 814910Swollman#endif 824910Swollman 8311819Sjulian#ifdef IPX 8411819Sjulian#include <netipx/ipx.h> 8511819Sjulian#include <netipx/ipx_if.h> 8611819Sjulian#endif 8711819Sjulian 884910Swollman#ifdef NS 894910Swollman#include <netns/ns.h> 904910Swollman#include <netns/ns_if.h> 914910Swollman#endif 924910Swollman 934910Swollman#include <net/if_sppp.h> 944910Swollman 9542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9642064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9742064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 9842104Sphk# define IOCTL_CMD_T u_long 9940008Sjoerg#else 10042064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10142064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10242104Sphk# define IOCTL_CMD_T int 10340008Sjoerg#endif 10442104Sphk 1054910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1064910Swollman 10725944Sjoerg/* 10825944Sjoerg * Interface flags that can be set in an ifconfig command. 10925944Sjoerg * 11025955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11125944Sjoerg * as being administrative openable, but won't be opened to begin 11225944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11325944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11425955Sjoerg * 11525955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11625955Sjoerg * arrive to be sent. 11730300Sjoerg * 11830300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11930300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12030300Sjoerg * like 12130300Sjoerg * 12230300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12330300Sjoerg * 12430300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12530300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12625944Sjoerg */ 12725944Sjoerg 12825955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12925955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13045152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13125944Sjoerg 13230300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13330300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13430300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13530300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13630300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13730300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 13878064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 13930300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14030300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14130300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14230300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 14378064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1444910Swollman 14525944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 14625944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 14725944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 14825944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 14925944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 15025944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 15125944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15225944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15325944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15425944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15525944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1564910Swollman 15730300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 15830300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 15930300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 16030300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 16130300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16230300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16330300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16430300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1654910Swollman 16625944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 16725944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 16825944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1694910Swollman 17078064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 17178064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 17278064Sume 17330300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 17430300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17530300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1764910Swollman 17730300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17830300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 17930300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18030300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18130300Sjoerg 18230300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18330300Sjoerg 18430300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18530300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18630300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18730300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18830300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 18930300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19030300Sjoerg 19125944Sjoerg/* states are named and numbered according to RFC 1661 */ 19225944Sjoerg#define STATE_INITIAL 0 19325944Sjoerg#define STATE_STARTING 1 19425944Sjoerg#define STATE_CLOSED 2 19525944Sjoerg#define STATE_STOPPED 3 19625944Sjoerg#define STATE_CLOSING 4 19725944Sjoerg#define STATE_STOPPING 5 19825944Sjoerg#define STATE_REQ_SENT 6 19925944Sjoerg#define STATE_ACK_RCVD 7 20025944Sjoerg#define STATE_ACK_SENT 8 20125944Sjoerg#define STATE_OPENED 9 20225944Sjoerg 2034910Swollmanstruct ppp_header { 20411189Sjkh u_char address; 20511189Sjkh u_char control; 20611189Sjkh u_short protocol; 2074910Swollman}; 2084910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2094910Swollman 2104910Swollmanstruct lcp_header { 21111189Sjkh u_char type; 21211189Sjkh u_char ident; 21311189Sjkh u_short len; 2144910Swollman}; 2154910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2164910Swollman 2174910Swollmanstruct cisco_packet { 21811189Sjkh u_long type; 21911189Sjkh u_long par1; 22011189Sjkh u_long par2; 22111189Sjkh u_short rel; 22211189Sjkh u_short time0; 22311189Sjkh u_short time1; 2244910Swollman}; 2254910Swollman#define CISCO_PACKET_LEN 18 2264910Swollman 22725944Sjoerg/* 22825944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 22925944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23025944Sjoerg * case you can't make sense out of these abbreviation; it will also 23125944Sjoerg * explain the semantics related to the various events and actions. 23225944Sjoerg */ 23325944Sjoergstruct cp { 23425944Sjoerg u_short proto; /* PPP control protocol number */ 23525944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23625944Sjoerg u_char flags; 23725944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23825944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 23925944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24025944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24125944Sjoerg const char *name; /* name of this control protocol */ 24225944Sjoerg /* event handlers */ 24325944Sjoerg void (*Up)(struct sppp *sp); 24425944Sjoerg void (*Down)(struct sppp *sp); 24525944Sjoerg void (*Open)(struct sppp *sp); 24625944Sjoerg void (*Close)(struct sppp *sp); 24725944Sjoerg void (*TO)(void *sp); 24825944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 24925944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25025944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25125944Sjoerg /* actions */ 25225944Sjoerg void (*tlu)(struct sppp *sp); 25325944Sjoerg void (*tld)(struct sppp *sp); 25425944Sjoerg void (*tls)(struct sppp *sp); 25525944Sjoerg void (*tlf)(struct sppp *sp); 25625944Sjoerg void (*scr)(struct sppp *sp); 25725944Sjoerg}; 25825944Sjoerg 25912820Sphkstatic struct sppp *spppq; 26042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26130300Sjoergstatic struct callout_handle keepalive_ch; 26240008Sjoerg#endif 2634910Swollman 26442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26540008Sjoerg#define SPP_FMT "%s%d: " 26640008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26740008Sjoerg#else 26840008Sjoerg#define SPP_FMT "%s: " 26940008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27040008Sjoerg#endif 27140008Sjoerg 2724910Swollman/* 2734910Swollman * The following disgusting hack gets around the problem that IP TOS 2744910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2754910Swollman * priority queue. To decide if traffic is interactive, we check that 2764910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27730300Sjoerg * 27830300Sjoerg * XXX is this really still necessary? - joerg - 2794910Swollman */ 28011189Sjkhstatic u_short interactive_ports[8] = { 2814910Swollman 0, 513, 0, 0, 2824910Swollman 0, 21, 0, 23, 2834910Swollman}; 2844910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2854910Swollman 28625944Sjoerg/* almost every function needs these */ 28725944Sjoerg#define STDDCL \ 28825944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 28925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29011189Sjkh 29130300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 29225944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2934910Swollman 29425944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 29525944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29625944Sjoerg 29725944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29825944Sjoerg struct mbuf *m); 29925944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30025944Sjoerg u_char ident, u_short len, void *data); 30142104Sphk/* static void sppp_cp_timeout(void *arg); */ 30225944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 30325944Sjoerg int newstate); 30430300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30542104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30630300Sjoerg ...); 30725944Sjoerg 30825944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 30925944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31025944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31125944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 31225944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 31325944Sjoerg 31430300Sjoergstatic void sppp_null(struct sppp *sp); 31530300Sjoerg 31625944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31725944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31825944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31925944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_TO(void *sp); 32225944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32325944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 32425944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32525944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32625944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33030300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33130300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 33225944Sjoerg 33325944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 33425944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33525944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33625944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_TO(void *sp); 33925944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34025944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34125944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34225944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 34325944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34725944Sjoerg 34878064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 34978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 35078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 35178064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 35278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 35378064Sumestatic void sppp_ipv6cp_TO(void *sp); 35478064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 35578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 35678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 35778064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 35878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 35978064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 36078064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 36178064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 36278064Sume 36330300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 36430300Sjoergstatic void sppp_pap_init(struct sppp *sp); 36530300Sjoergstatic void sppp_pap_open(struct sppp *sp); 36630300Sjoergstatic void sppp_pap_close(struct sppp *sp); 36730300Sjoergstatic void sppp_pap_TO(void *sp); 36830300Sjoergstatic void sppp_pap_my_TO(void *sp); 36930300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 37030300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 37130300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 37230300Sjoerg 37330300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 37430300Sjoergstatic void sppp_chap_init(struct sppp *sp); 37530300Sjoergstatic void sppp_chap_open(struct sppp *sp); 37630300Sjoergstatic void sppp_chap_close(struct sppp *sp); 37730300Sjoergstatic void sppp_chap_TO(void *sp); 37830300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 37930300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 38030300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 38130300Sjoerg 38230300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 38325944Sjoergstatic const char *sppp_cp_type_name(u_char type); 38430300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 38530300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 38678064Sume#ifdef INET6 38778064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 38878064Sume#endif 38925944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 39025944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 39125944Sjoergstatic const char *sppp_proto_name(u_short proto); 39230300Sjoergstatic const char *sppp_state_name(int state); 39338343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 39430300Sjoergstatic int sppp_strnlen(u_char *p, int max); 39530300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 39630300Sjoerg u_long *srcmask); 39725944Sjoergstatic void sppp_keepalive(void *dummy); 39830300Sjoergstatic void sppp_phase_network(struct sppp *sp); 39930300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 40030300Sjoergstatic void sppp_print_string(const char *p, u_short len); 40125944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 40225944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 40378064Sume#ifdef INET6 40478064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 40578064Sume struct in6_addr *dst, struct in6_addr *srcmask); 40678064Sume#ifdef IPV6CP_MYIFID_DYN 40778064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40878064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 40978064Sume#endif 41078064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 41178064Sume#endif 41225944Sjoerg 41325944Sjoerg/* our control protocol descriptors */ 41433181Seivindstatic const struct cp lcp = { 41525944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 41625944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 41725944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 41825944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 41925944Sjoerg sppp_lcp_scr 42025944Sjoerg}; 42125944Sjoerg 42233181Seivindstatic const struct cp ipcp = { 42325944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 42425944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 42525944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 42625944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 42725944Sjoerg sppp_ipcp_scr 42825944Sjoerg}; 42925944Sjoerg 43078064Sumestatic const struct cp ipv6cp = { 43178064Sume PPP_IPV6CP, IDX_IPV6CP, 43278064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 43378064Sume CP_NCP, 43478064Sume#else 43578064Sume 0, 43678064Sume#endif 43778064Sume "ipv6cp", 43878064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 43978064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 44078064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 44178064Sume sppp_ipv6cp_scr 44278064Sume}; 44378064Sume 44433181Seivindstatic const struct cp pap = { 44530300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 44630300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 44730300Sjoerg sppp_pap_TO, 0, 0, 0, 44830300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 44930300Sjoerg sppp_pap_scr 45030300Sjoerg}; 45130300Sjoerg 45233181Seivindstatic const struct cp chap = { 45330300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 45430300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 45530300Sjoerg sppp_chap_TO, 0, 0, 0, 45630300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 45730300Sjoerg sppp_chap_scr 45830300Sjoerg}; 45930300Sjoerg 46033181Seivindstatic const struct cp *cps[IDX_COUNT] = { 46125944Sjoerg &lcp, /* IDX_LCP */ 46225944Sjoerg &ipcp, /* IDX_IPCP */ 46378064Sume &ipv6cp, /* IDX_IPV6CP */ 46430300Sjoerg &pap, /* IDX_PAP */ 46530300Sjoerg &chap, /* IDX_CHAP */ 46625944Sjoerg}; 46725944Sjoerg 46870199Sjhaystatic int 46970199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47070199Sjhay{ 47170199Sjhay switch (type) { 47270199Sjhay case MOD_LOAD: 47370199Sjhay break; 47470199Sjhay case MOD_UNLOAD: 47570199Sjhay return EACCES; 47670199Sjhay break; 47770199Sjhay default: 47870199Sjhay break; 47970199Sjhay } 48070199Sjhay return 0; 48170199Sjhay} 48270199Sjhaystatic moduledata_t spppmod = { 48370199Sjhay "sppp", 48470199Sjhay sppp_modevent, 48570199Sjhay 0 48670199Sjhay}; 48770199SjhayMODULE_VERSION(sppp, 1); 48870199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 48925944Sjoerg 49070199Sjhay/* 49125944Sjoerg * Exported functions, comprising our interface to the lower layer. 4924910Swollman */ 4934910Swollman 4944910Swollman/* 4954910Swollman * Process the received packet. 4964910Swollman */ 49725706Sjoergvoid 49825706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4994910Swollman{ 5004910Swollman struct ppp_header *h; 5014910Swollman struct ifqueue *inq = 0; 50225944Sjoerg struct sppp *sp = (struct sppp *)ifp; 50325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5044910Swollman 5054910Swollman if (ifp->if_flags & IFF_UP) 5064910Swollman /* Count received bytes, add FCS and one flag */ 5074910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5084910Swollman 5094910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5104910Swollman /* Too small packet, drop it. */ 51125944Sjoerg if (debug) 51225706Sjoerg log(LOG_DEBUG, 51340008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 51440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 51525944Sjoerg drop: 51625944Sjoerg ++ifp->if_ierrors; 51725944Sjoerg ++ifp->if_iqdrops; 5184910Swollman m_freem (m); 5194910Swollman return; 5204910Swollman } 5214910Swollman 5224910Swollman /* Get PPP header. */ 5234910Swollman h = mtod (m, struct ppp_header*); 5244910Swollman m_adj (m, PPP_HEADER_LEN); 5254910Swollman 5264910Swollman switch (h->address) { 5274910Swollman case PPP_ALLSTATIONS: 5284910Swollman if (h->control != PPP_UI) 5294910Swollman goto invalid; 53045152Sphk if (sp->pp_mode == IFF_CISCO) { 53125944Sjoerg if (debug) 53225706Sjoerg log(LOG_DEBUG, 53340008Sjoerg SPP_FMT "PPP packet in Cisco mode " 53425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 53540008Sjoerg SPP_ARGS(ifp), 53625706Sjoerg h->address, h->control, ntohs(h->protocol)); 53711189Sjkh goto drop; 53811189Sjkh } 5394910Swollman switch (ntohs (h->protocol)) { 5404910Swollman default: 54125944Sjoerg if (debug) 54225706Sjoerg log(LOG_DEBUG, 54344145Sphk SPP_FMT "rejecting protocol " 54425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54540008Sjoerg SPP_ARGS(ifp), 54625706Sjoerg h->address, h->control, ntohs(h->protocol)); 54744145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 54844145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 54978064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 55044145Sphk &h->protocol); 5514910Swollman ++ifp->if_noproto; 5524910Swollman goto drop; 5534910Swollman case PPP_LCP: 55430300Sjoerg sppp_cp_input(&lcp, sp, m); 5554910Swollman m_freem (m); 5564910Swollman return; 55730300Sjoerg case PPP_PAP: 55830300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 55930300Sjoerg sppp_pap_input(sp, m); 56030300Sjoerg m_freem (m); 56130300Sjoerg return; 56230300Sjoerg case PPP_CHAP: 56330300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 56430300Sjoerg sppp_chap_input(sp, m); 56530300Sjoerg m_freem (m); 56630300Sjoerg return; 5674910Swollman#ifdef INET 5684910Swollman case PPP_IPCP: 56925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 57030300Sjoerg sppp_cp_input(&ipcp, sp, m); 5714910Swollman m_freem (m); 5724910Swollman return; 5734910Swollman case PPP_IP: 57425944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5754910Swollman schednetisr (NETISR_IP); 5764910Swollman inq = &ipintrq; 5774910Swollman } 5784910Swollman break; 5794910Swollman#endif 58078064Sume#ifdef INET6 58178064Sume case PPP_IPV6CP: 58278064Sume if (sp->pp_phase == PHASE_NETWORK) 58378064Sume sppp_cp_input(&ipv6cp, sp, m); 58478064Sume m_freem (m); 58578064Sume return; 58678064Sume 58778064Sume case PPP_IPV6: 58878064Sume if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 58978064Sume schednetisr (NETISR_IPV6); 59078064Sume inq = &ip6intrq; 59178064Sume } 59278064Sume break; 59378064Sume#endif 59412495Speter#ifdef IPX 59512495Speter case PPP_IPX: 59612495Speter /* IPX IPXCP not implemented yet */ 59725944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 59812495Speter schednetisr (NETISR_IPX); 59912495Speter inq = &ipxintrq; 60012495Speter } 60112495Speter break; 60212495Speter#endif 6034910Swollman#ifdef NS 6044910Swollman case PPP_XNS: 6054910Swollman /* XNS IDPCP not implemented yet */ 60625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6074910Swollman schednetisr (NETISR_NS); 6084910Swollman inq = &nsintrq; 6094910Swollman } 6104910Swollman break; 6114910Swollman#endif 6124910Swollman } 6134910Swollman break; 6144910Swollman case CISCO_MULTICAST: 6154910Swollman case CISCO_UNICAST: 6164910Swollman /* Don't check the control field here (RFC 1547). */ 61745152Sphk if (sp->pp_mode != IFF_CISCO) { 61825944Sjoerg if (debug) 61925706Sjoerg log(LOG_DEBUG, 62040008Sjoerg SPP_FMT "Cisco packet in PPP mode " 62125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 62240008Sjoerg SPP_ARGS(ifp), 62325706Sjoerg h->address, h->control, ntohs(h->protocol)); 62411189Sjkh goto drop; 62511189Sjkh } 6264910Swollman switch (ntohs (h->protocol)) { 6274910Swollman default: 6284910Swollman ++ifp->if_noproto; 6294910Swollman goto invalid; 6304910Swollman case CISCO_KEEPALIVE: 6314910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 6324910Swollman m_freem (m); 6334910Swollman return; 6344910Swollman#ifdef INET 6354910Swollman case ETHERTYPE_IP: 6364910Swollman schednetisr (NETISR_IP); 6374910Swollman inq = &ipintrq; 6384910Swollman break; 6394910Swollman#endif 64054263Sshin#ifdef INET6 64154263Sshin case ETHERTYPE_IPV6: 64254263Sshin schednetisr (NETISR_IPV6); 64354263Sshin inq = &ip6intrq; 64454263Sshin break; 64554263Sshin#endif 64612495Speter#ifdef IPX 64712495Speter case ETHERTYPE_IPX: 64812495Speter schednetisr (NETISR_IPX); 64912495Speter inq = &ipxintrq; 65012495Speter break; 65112495Speter#endif 6524910Swollman#ifdef NS 6534910Swollman case ETHERTYPE_NS: 6544910Swollman schednetisr (NETISR_NS); 6554910Swollman inq = &nsintrq; 6564910Swollman break; 6574910Swollman#endif 6584910Swollman } 6594910Swollman break; 66025944Sjoerg default: /* Invalid PPP packet. */ 66125944Sjoerg invalid: 66225944Sjoerg if (debug) 66325944Sjoerg log(LOG_DEBUG, 66440008Sjoerg SPP_FMT "invalid input packet " 66525944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 66640008Sjoerg SPP_ARGS(ifp), 66725944Sjoerg h->address, h->control, ntohs(h->protocol)); 66825944Sjoerg goto drop; 6694910Swollman } 6704910Swollman 6714910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 6724910Swollman goto drop; 6734910Swollman 6744910Swollman /* Check queue. */ 67569152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 67625944Sjoerg if (debug) 67740008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 67840008Sjoerg SPP_ARGS(ifp)); 6794910Swollman goto drop; 6804910Swollman } 6814910Swollman} 6824910Swollman 6834910Swollman/* 6844910Swollman * Enqueue transmit packet. 6854910Swollman */ 68612820Sphkstatic int 68725706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 68825706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6894910Swollman{ 6904910Swollman struct sppp *sp = (struct sppp*) ifp; 6914910Swollman struct ppp_header *h; 69278064Sume struct ifqueue *ifq = NULL; 69325955Sjoerg int s, rv = 0; 69442066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6954910Swollman 69625944Sjoerg s = splimp(); 69725944Sjoerg 69825944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 69925944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 7004910Swollman m_freem (m); 7014910Swollman splx (s); 7024910Swollman return (ENETDOWN); 7034910Swollman } 7044910Swollman 70525944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 70625944Sjoerg /* 70725944Sjoerg * Interface is not yet running, but auto-dial. Need 70825944Sjoerg * to start LCP for it. 70925944Sjoerg */ 71025944Sjoerg ifp->if_flags |= IFF_RUNNING; 71125944Sjoerg splx(s); 71225944Sjoerg lcp.Open(sp); 71325944Sjoerg s = splimp(); 71425944Sjoerg } 71525944Sjoerg 7164910Swollman#ifdef INET 71712436Speter if (dst->sa_family == AF_INET) { 71840008Sjoerg /* XXX Check mbuf length here? */ 71912436Speter struct ip *ip = mtod (m, struct ip*); 72012436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 7214910Swollman 72242104Sphk /* 72342104Sphk * When using dynamic local IP address assignment by using 72442104Sphk * 0.0.0.0 as a local address, the first TCP session will 72542104Sphk * not connect because the local TCP checksum is computed 72642104Sphk * using 0.0.0.0 which will later become our real IP address 72742104Sphk * so the TCP checksum computed at the remote end will 72842104Sphk * become invalid. So we 72942104Sphk * - don't let packets with src ip addr 0 thru 73042104Sphk * - we flag TCP packets with src ip 0 as an error 73170199Sjhay */ 73242104Sphk 73342104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 73442104Sphk { 73542104Sphk m_freem(m); 73642104Sphk splx(s); 73742104Sphk if(ip->ip_p == IPPROTO_TCP) 73842104Sphk return(EADDRNOTAVAIL); 73942104Sphk else 74042104Sphk return(0); 74142104Sphk } 74270199Sjhay 74342104Sphk /* 74442104Sphk * Put low delay, telnet, rlogin and ftp control packets 74542104Sphk * in front of the queue. 74642104Sphk */ 74769152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 74841686Sphk ; 74941686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 75012436Speter ifq = &sp->pp_fastq; 75141686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 75241686Sphk ; 75341686Sphk else if (ip->ip_p != IPPROTO_TCP) 75441686Sphk ; 75541686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 75641686Sphk ifq = &sp->pp_fastq; 75741686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 75841686Sphk ifq = &sp->pp_fastq; 7594910Swollman } 7604910Swollman#endif 7614910Swollman 76278064Sume#ifdef INET6 76378064Sume if (dst->sa_family == AF_INET6) { 76478064Sume /* XXX do something tricky here? */ 76578064Sume } 76678064Sume#endif 76778064Sume 7684910Swollman /* 7694910Swollman * Prepend general data packet PPP header. For now, IP only. 7704910Swollman */ 7714910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 7724910Swollman if (! m) { 77342066Sphk if (debug) 77440008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 77540008Sjoerg SPP_ARGS(ifp)); 77625944Sjoerg ++ifp->if_oerrors; 7774910Swollman splx (s); 7784910Swollman return (ENOBUFS); 7794910Swollman } 78040008Sjoerg /* 78140008Sjoerg * May want to check size of packet 78240008Sjoerg * (albeit due to the implementation it's always enough) 78340008Sjoerg */ 7844910Swollman h = mtod (m, struct ppp_header*); 78545152Sphk if (sp->pp_mode == IFF_CISCO) { 78628088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7874910Swollman h->control = 0; 7884910Swollman } else { 7894910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7904910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7914910Swollman } 7924910Swollman 7934910Swollman switch (dst->sa_family) { 7944910Swollman#ifdef INET 7954910Swollman case AF_INET: /* Internet Protocol */ 79645152Sphk if (sp->pp_mode == IFF_CISCO) 79711189Sjkh h->protocol = htons (ETHERTYPE_IP); 79811189Sjkh else { 79925955Sjoerg /* 80025955Sjoerg * Don't choke with an ENETDOWN early. It's 80125955Sjoerg * possible that we just started dialing out, 80225955Sjoerg * so don't drop the packet immediately. If 80325955Sjoerg * we notice that we run out of buffer space 80425955Sjoerg * below, we will however remember that we are 80525955Sjoerg * not ready to carry IP packets, and return 80625955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 80725955Sjoerg */ 80825955Sjoerg h->protocol = htons(PPP_IP); 80925955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 81025955Sjoerg rv = ENETDOWN; 81111189Sjkh } 8124910Swollman break; 8134910Swollman#endif 81454263Sshin#ifdef INET6 81554263Sshin case AF_INET6: /* Internet Protocol */ 81654263Sshin if (sp->pp_mode == IFF_CISCO) 81754263Sshin h->protocol = htons (ETHERTYPE_IPV6); 81854263Sshin else { 81978064Sume /* 82078064Sume * Don't choke with an ENETDOWN early. It's 82178064Sume * possible that we just started dialing out, 82278064Sume * so don't drop the packet immediately. If 82378064Sume * we notice that we run out of buffer space 82478064Sume * below, we will however remember that we are 82578064Sume * not ready to carry IP packets, and return 82678064Sume * ENETDOWN, as opposed to ENOBUFS. 82778064Sume */ 82878064Sume h->protocol = htons(PPP_IPV6); 82978064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 83078064Sume rv = ENETDOWN; 83154263Sshin } 83254263Sshin break; 83354263Sshin#endif 8344910Swollman#ifdef NS 8354910Swollman case AF_NS: /* Xerox NS Protocol */ 83645152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 8374910Swollman ETHERTYPE_NS : PPP_XNS); 8384910Swollman break; 8394910Swollman#endif 84011819Sjulian#ifdef IPX 84112495Speter case AF_IPX: /* Novell IPX Protocol */ 84245152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 84312495Speter ETHERTYPE_IPX : PPP_IPX); 84411819Sjulian break; 84511819Sjulian#endif 84612820Sphknosupport: 8474910Swollman default: 8484910Swollman m_freem (m); 84925944Sjoerg ++ifp->if_oerrors; 8504910Swollman splx (s); 8514910Swollman return (EAFNOSUPPORT); 8524910Swollman } 8534910Swollman 8544910Swollman /* 8554910Swollman * Queue message on interface, and start output if interface 85669152Sjlemon * not yet active. Also adjust output byte count. 85769152Sjlemon * The packet length includes header, FCS and 1 flag, 85869152Sjlemon * according to RFC 1333. 8594910Swollman */ 86069152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 86125944Sjoerg ++ifp->if_oerrors; 86225955Sjoerg return (rv? rv: ENOBUFS); 8634910Swollman } 8644910Swollman return (0); 8654910Swollman} 8664910Swollman 86725706Sjoergvoid 86825706Sjoergsppp_attach(struct ifnet *ifp) 8694910Swollman{ 8704910Swollman struct sppp *sp = (struct sppp*) ifp; 8714910Swollman 8724910Swollman /* Initialize keepalive handler. */ 8734910Swollman if (! spppq) 87442064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 8754910Swollman 8764910Swollman /* Insert new entry into the keepalive list. */ 8774910Swollman sp->pp_next = spppq; 8784910Swollman spppq = sp; 8794910Swollman 88042064Sphk sp->pp_if.if_mtu = PP_MTU; 88142064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8824910Swollman sp->pp_if.if_type = IFT_PPP; 8834910Swollman sp->pp_if.if_output = sppp_output; 88442104Sphk#if 0 88542064Sphk sp->pp_flags = PP_KEEPALIVE; 88642104Sphk#endif 88770199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 88870199Sjhay sp->pp_fastq.ifq_maxlen = 32; 88970199Sjhay sp->pp_cpq.ifq_maxlen = 20; 8904910Swollman sp->pp_loopcnt = 0; 8914910Swollman sp->pp_alivecnt = 0; 89278064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 89378064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 89425944Sjoerg sp->pp_phase = PHASE_DEAD; 89525944Sjoerg sp->pp_up = lcp.Up; 89625944Sjoerg sp->pp_down = lcp.Down; 89769152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 89869152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 89925944Sjoerg 90025944Sjoerg sppp_lcp_init(sp); 90125944Sjoerg sppp_ipcp_init(sp); 90278064Sume sppp_ipv6cp_init(sp); 90330300Sjoerg sppp_pap_init(sp); 90430300Sjoerg sppp_chap_init(sp); 9054910Swollman} 9064910Swollman 90730300Sjoergvoid 90825706Sjoergsppp_detach(struct ifnet *ifp) 9094910Swollman{ 9104910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 91125944Sjoerg int i; 9124910Swollman 9134910Swollman /* Remove the entry from the keepalive list. */ 9144910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 9154910Swollman if (p == sp) { 9164910Swollman *q = p->pp_next; 9174910Swollman break; 9184910Swollman } 9194910Swollman 9204910Swollman /* Stop keepalive handler. */ 9214910Swollman if (! spppq) 92240008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 92325944Sjoerg 92425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 92540008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 92640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 92769152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 92869152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 9294910Swollman} 9304910Swollman 9314910Swollman/* 9324910Swollman * Flush the interface output queue. 9334910Swollman */ 93425706Sjoergvoid 93525706Sjoergsppp_flush(struct ifnet *ifp) 9364910Swollman{ 9374910Swollman struct sppp *sp = (struct sppp*) ifp; 9384910Swollman 93925944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 94025944Sjoerg sppp_qflush (&sp->pp_fastq); 94126018Sjoerg sppp_qflush (&sp->pp_cpq); 9424910Swollman} 9434910Swollman 9444910Swollman/* 94511189Sjkh * Check if the output queue is empty. 94611189Sjkh */ 94712820Sphkint 94825706Sjoergsppp_isempty(struct ifnet *ifp) 94911189Sjkh{ 95011189Sjkh struct sppp *sp = (struct sppp*) ifp; 95125944Sjoerg int empty, s; 95211189Sjkh 95325944Sjoerg s = splimp(); 95426018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 95526018Sjoerg !sp->pp_if.if_snd.ifq_head; 95625944Sjoerg splx(s); 95711189Sjkh return (empty); 95811189Sjkh} 95911189Sjkh 96011189Sjkh/* 9614910Swollman * Get next packet to send. 9624910Swollman */ 96325706Sjoergstruct mbuf * 96425706Sjoergsppp_dequeue(struct ifnet *ifp) 9654910Swollman{ 9664910Swollman struct sppp *sp = (struct sppp*) ifp; 9674910Swollman struct mbuf *m; 96825944Sjoerg int s; 9694910Swollman 97025944Sjoerg s = splimp(); 97126018Sjoerg /* 97230300Sjoerg * Process only the control protocol queue until we have at 97330300Sjoerg * least one NCP open. 97426018Sjoerg * 97526018Sjoerg * Do always serve all three queues in Cisco mode. 97626018Sjoerg */ 97726018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 97826018Sjoerg if (m == NULL && 97945152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 98026018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 98126018Sjoerg if (m == NULL) 98226018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 98326018Sjoerg } 98426018Sjoerg splx(s); 98526018Sjoerg return m; 9864910Swollman} 9874910Swollman 9884910Swollman/* 98930300Sjoerg * Pick the next packet, do not remove it from the queue. 99030300Sjoerg */ 99130300Sjoergstruct mbuf * 99230300Sjoergsppp_pick(struct ifnet *ifp) 99330300Sjoerg{ 99430300Sjoerg struct sppp *sp = (struct sppp*)ifp; 99530300Sjoerg struct mbuf *m; 99630300Sjoerg int s; 99730300Sjoerg 99830300Sjoerg s= splimp (); 99930300Sjoerg 100030300Sjoerg m = sp->pp_cpq.ifq_head; 100130300Sjoerg if (m == NULL && 100245152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 100330300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 100430300Sjoerg m = sp->pp_if.if_snd.ifq_head; 100530300Sjoerg splx (s); 100630300Sjoerg return (m); 100730300Sjoerg} 100830300Sjoerg 100930300Sjoerg/* 101025944Sjoerg * Process an ioctl request. Called on low priority level. 10114910Swollman */ 101225944Sjoergint 101342104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 10144910Swollman{ 101525944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 101625944Sjoerg struct sppp *sp = (struct sppp*) ifp; 101730300Sjoerg int s, rv, going_up, going_down, newmode; 10184910Swollman 101925944Sjoerg s = splimp(); 102030300Sjoerg rv = 0; 102125944Sjoerg switch (cmd) { 102225944Sjoerg case SIOCAIFADDR: 102325944Sjoerg case SIOCSIFDSTADDR: 102425944Sjoerg break; 10254910Swollman 102625944Sjoerg case SIOCSIFADDR: 102725944Sjoerg if_up(ifp); 102825944Sjoerg /* fall through... */ 102911189Sjkh 103025944Sjoerg case SIOCSIFFLAGS: 103125944Sjoerg going_up = ifp->if_flags & IFF_UP && 103225944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 103325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 103425944Sjoerg ifp->if_flags & IFF_RUNNING; 103545152Sphk 103645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 103745152Sphk if (!newmode) 103845152Sphk newmode = ifp->if_flags & IFF_AUTO; 103945152Sphk if (!newmode) 104045152Sphk newmode = ifp->if_flags & IFF_CISCO; 104145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 104245152Sphk ifp->if_flags |= newmode; 104345152Sphk 104445152Sphk if (newmode != sp->pp_mode) { 104545152Sphk going_down = 1; 104645152Sphk if (!going_up) 104745152Sphk going_up = ifp->if_flags & IFF_RUNNING; 10484910Swollman } 10494910Swollman 105045152Sphk if (going_down) { 105170199Sjhay if (sp->pp_mode != IFF_CISCO) 105245152Sphk lcp.Close(sp); 105345152Sphk else if (sp->pp_tlf) 105445152Sphk (sp->pp_tlf)(sp); 105526018Sjoerg sppp_flush(ifp); 105625944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 105745152Sphk sp->pp_mode = newmode; 105826018Sjoerg } 10594910Swollman 106045152Sphk if (going_up) { 106170199Sjhay if (sp->pp_mode != IFF_CISCO) 106245152Sphk lcp.Close(sp); 106345152Sphk sp->pp_mode = newmode; 106445152Sphk if (sp->pp_mode == 0) { 106545152Sphk ifp->if_flags |= IFF_RUNNING; 106645152Sphk lcp.Open(sp); 106745152Sphk } 106845152Sphk if (sp->pp_mode == IFF_CISCO) { 106945152Sphk if (sp->pp_tls) 107045152Sphk (sp->pp_tls)(sp); 107145152Sphk ifp->if_flags |= IFF_RUNNING; 107245152Sphk } 107345152Sphk } 107445152Sphk 10754910Swollman break; 107611189Sjkh 107725944Sjoerg#ifdef SIOCSIFMTU 107825944Sjoerg#ifndef ifr_mtu 107925944Sjoerg#define ifr_mtu ifr_metric 108025944Sjoerg#endif 108125944Sjoerg case SIOCSIFMTU: 108225944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 108325944Sjoerg return (EINVAL); 108425944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10854910Swollman break; 108625944Sjoerg#endif 108725944Sjoerg#ifdef SLIOCSETMTU 108825944Sjoerg case SLIOCSETMTU: 108925944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 109025944Sjoerg return (EINVAL); 109125944Sjoerg ifp->if_mtu = *(short*)data; 10924910Swollman break; 109325944Sjoerg#endif 109425944Sjoerg#ifdef SIOCGIFMTU 109525944Sjoerg case SIOCGIFMTU: 109625944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 109711189Sjkh break; 109825944Sjoerg#endif 109925944Sjoerg#ifdef SLIOCGETMTU 110025944Sjoerg case SLIOCGETMTU: 110125944Sjoerg *(short*)data = ifp->if_mtu; 11024910Swollman break; 110325944Sjoerg#endif 110425944Sjoerg case SIOCADDMULTI: 110525944Sjoerg case SIOCDELMULTI: 11064910Swollman break; 110711189Sjkh 110830300Sjoerg case SIOCGIFGENERIC: 110930300Sjoerg case SIOCSIFGENERIC: 111030300Sjoerg rv = sppp_params(sp, cmd, data); 111130300Sjoerg break; 111230300Sjoerg 111325944Sjoerg default: 111430300Sjoerg rv = ENOTTY; 11154910Swollman } 111625944Sjoerg splx(s); 111730300Sjoerg return rv; 11184910Swollman} 11194910Swollman 112070199Sjhay/* 112125944Sjoerg * Cisco framing implementation. 112225944Sjoerg */ 112325944Sjoerg 11244910Swollman/* 11254910Swollman * Handle incoming Cisco keepalive protocol packets. 11264910Swollman */ 112730300Sjoergstatic void 112825706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 11294910Swollman{ 113025944Sjoerg STDDCL; 11314910Swollman struct cisco_packet *h; 113230300Sjoerg u_long me, mymask; 11334910Swollman 113427929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 113525706Sjoerg if (debug) 113625706Sjoerg log(LOG_DEBUG, 113740008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 113840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 11394910Swollman return; 11404910Swollman } 11414910Swollman h = mtod (m, struct cisco_packet*); 114225706Sjoerg if (debug) 114325706Sjoerg log(LOG_DEBUG, 114440008Sjoerg SPP_FMT "cisco input: %d bytes " 114525706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 114740008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 114840008Sjoerg (u_int)h->time0, (u_int)h->time1); 11494910Swollman switch (ntohl (h->type)) { 11504910Swollman default: 115125706Sjoerg if (debug) 115269211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 115340008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 11544910Swollman break; 11554910Swollman case CISCO_ADDR_REPLY: 11564910Swollman /* Reply on address request, ignore */ 11574910Swollman break; 11584910Swollman case CISCO_KEEPALIVE_REQ: 11594910Swollman sp->pp_alivecnt = 0; 116078064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 116178064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 11624910Swollman /* Local and remote sequence numbers are equal. 11634910Swollman * Probably, the line is in loopback mode. */ 116411189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 116540008Sjoerg printf (SPP_FMT "loopback\n", 116640008Sjoerg SPP_ARGS(ifp)); 116711189Sjkh sp->pp_loopcnt = 0; 116811189Sjkh if (ifp->if_flags & IFF_UP) { 116911189Sjkh if_down (ifp); 117026018Sjoerg sppp_qflush (&sp->pp_cpq); 117111189Sjkh } 117211189Sjkh } 11734910Swollman ++sp->pp_loopcnt; 11744910Swollman 11754910Swollman /* Generate new local sequence number */ 117642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 117778064Sume sp->pp_seq[IDX_LCP] = random(); 117840008Sjoerg#else 117978064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 118040008Sjoerg#endif 118111189Sjkh break; 118211189Sjkh } 118330300Sjoerg sp->pp_loopcnt = 0; 118411189Sjkh if (! (ifp->if_flags & IFF_UP) && 118511189Sjkh (ifp->if_flags & IFF_RUNNING)) { 118630300Sjoerg if_up(ifp); 118740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 118811189Sjkh } 11894910Swollman break; 11904910Swollman case CISCO_ADDR_REQ: 119130300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 119230300Sjoerg if (me != 0L) 119330300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11944910Swollman break; 11954910Swollman } 11964910Swollman} 11974910Swollman 11984910Swollman/* 119925944Sjoerg * Send Cisco keepalive packet. 12004910Swollman */ 120112820Sphkstatic void 120225944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 120325944Sjoerg{ 120425944Sjoerg STDDCL; 120525944Sjoerg struct ppp_header *h; 120625944Sjoerg struct cisco_packet *ch; 120725944Sjoerg struct mbuf *m; 120842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 120935029Sphk struct timeval tv; 121040008Sjoerg#else 121140008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 121240008Sjoerg#endif 121325944Sjoerg 121442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 121536119Sphk getmicrouptime(&tv); 121640008Sjoerg#endif 121770199Sjhay 121825944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 121925944Sjoerg if (! m) 122025944Sjoerg return; 122125944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 122225944Sjoerg m->m_pkthdr.rcvif = 0; 122325944Sjoerg 122425944Sjoerg h = mtod (m, struct ppp_header*); 122525944Sjoerg h->address = CISCO_MULTICAST; 122625944Sjoerg h->control = 0; 122725944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 122825944Sjoerg 122925944Sjoerg ch = (struct cisco_packet*) (h + 1); 123025944Sjoerg ch->type = htonl (type); 123125944Sjoerg ch->par1 = htonl (par1); 123225944Sjoerg ch->par2 = htonl (par2); 123325944Sjoerg ch->rel = -1; 123440008Sjoerg 123542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 123635029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 123735029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 123840008Sjoerg#else 123940008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 124040008Sjoerg ch->time1 = htons ((u_short) t); 124140008Sjoerg#endif 124225944Sjoerg 124325944Sjoerg if (debug) 124425944Sjoerg log(LOG_DEBUG, 124540008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 124640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 124740008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 124825944Sjoerg 124969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 125069152Sjlemon ifp->if_oerrors++; 125125944Sjoerg} 125225944Sjoerg 125370199Sjhay/* 125425944Sjoerg * PPP protocol implementation. 125525944Sjoerg */ 125625944Sjoerg 125725944Sjoerg/* 125825944Sjoerg * Send PPP control protocol packet. 125925944Sjoerg */ 126025944Sjoergstatic void 126125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 126225706Sjoerg u_char ident, u_short len, void *data) 12634910Swollman{ 126425944Sjoerg STDDCL; 12654910Swollman struct ppp_header *h; 12664910Swollman struct lcp_header *lh; 12674910Swollman struct mbuf *m; 12684910Swollman 12694910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 12704910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 12714910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 12724910Swollman if (! m) 12734910Swollman return; 12744910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 12754910Swollman m->m_pkthdr.rcvif = 0; 12764910Swollman 12774910Swollman h = mtod (m, struct ppp_header*); 12784910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12794910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12804910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12814910Swollman 12824910Swollman lh = (struct lcp_header*) (h + 1); 12834910Swollman lh->type = type; 12844910Swollman lh->ident = ident; 12854910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12864910Swollman if (len) 12874910Swollman bcopy (data, lh+1, len); 12884910Swollman 128925706Sjoerg if (debug) { 129040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 129140008Sjoerg SPP_ARGS(ifp), 129225944Sjoerg sppp_proto_name(proto), 129325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 129425944Sjoerg ntohs (lh->len)); 129544145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 129669211Sphk log(-1, ">\n"); 12974910Swollman } 129869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 129969152Sjlemon ifp->if_oerrors++; 13004910Swollman} 13014910Swollman 13024910Swollman/* 130325944Sjoerg * Handle incoming PPP control protocol packets. 13044910Swollman */ 130512820Sphkstatic void 130625944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13074910Swollman{ 130825944Sjoerg STDDCL; 130925944Sjoerg struct lcp_header *h; 131025944Sjoerg int len = m->m_pkthdr.len; 131125944Sjoerg int rv; 131225944Sjoerg u_char *p; 13134910Swollman 131425944Sjoerg if (len < 4) { 131525944Sjoerg if (debug) 131625944Sjoerg log(LOG_DEBUG, 131740008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 131840008Sjoerg SPP_ARGS(ifp), cp->name, len); 13194910Swollman return; 132025944Sjoerg } 132125944Sjoerg h = mtod (m, struct lcp_header*); 132225944Sjoerg if (debug) { 132325944Sjoerg log(LOG_DEBUG, 132440008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 132540008Sjoerg SPP_ARGS(ifp), cp->name, 132625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 132725944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 132844145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 132969211Sphk log(-1, ">\n"); 133025944Sjoerg } 133125944Sjoerg if (len > ntohs (h->len)) 133225944Sjoerg len = ntohs (h->len); 133330300Sjoerg p = (u_char *)(h + 1); 133425944Sjoerg switch (h->type) { 133525944Sjoerg case CONF_REQ: 133625944Sjoerg if (len < 4) { 133725944Sjoerg if (debug) 133869211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 133940008Sjoerg SPP_ARGS(ifp), cp->name, 134025944Sjoerg len); 134125944Sjoerg ++ifp->if_ierrors; 134225944Sjoerg break; 134325944Sjoerg } 134430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 134530300Sjoerg switch (sp->state[cp->protoidx]) { 134630300Sjoerg case STATE_CLOSING: 134730300Sjoerg case STATE_STOPPING: 134830300Sjoerg return; 134930300Sjoerg case STATE_CLOSED: 135030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 135130300Sjoerg 0, 0); 135230300Sjoerg return; 135330300Sjoerg } 135425944Sjoerg rv = (cp->RCR)(sp, h, len); 135525944Sjoerg switch (sp->state[cp->protoidx]) { 135625944Sjoerg case STATE_OPENED: 135725944Sjoerg (cp->tld)(sp); 135825944Sjoerg (cp->scr)(sp); 135925944Sjoerg /* fall through... */ 136025944Sjoerg case STATE_ACK_SENT: 136125944Sjoerg case STATE_REQ_SENT: 136270199Sjhay /* 136370199Sjhay * sppp_cp_change_state() have the side effect of 136470199Sjhay * restarting the timeouts. We want to avoid that 136570199Sjhay * if the state don't change, otherwise we won't 136670199Sjhay * ever timeout and resend a configuration request 136770199Sjhay * that got lost. 136870199Sjhay */ 136970199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 137070199Sjhay STATE_REQ_SENT)) 137170199Sjhay break; 137225944Sjoerg sppp_cp_change_state(cp, sp, rv? 137325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 137425944Sjoerg break; 137525944Sjoerg case STATE_STOPPED: 137625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 137725944Sjoerg (cp->scr)(sp); 137825944Sjoerg sppp_cp_change_state(cp, sp, rv? 137925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 138025944Sjoerg break; 138125944Sjoerg case STATE_ACK_RCVD: 138225944Sjoerg if (rv) { 138325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 138425944Sjoerg if (debug) 138540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 138640008Sjoerg SPP_ARGS(ifp), 138726077Sjoerg cp->name); 138825944Sjoerg (cp->tlu)(sp); 138925944Sjoerg } else 139025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 139125944Sjoerg break; 139225944Sjoerg default: 139340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139440008Sjoerg SPP_ARGS(ifp), cp->name, 139525944Sjoerg sppp_cp_type_name(h->type), 139625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139725944Sjoerg ++ifp->if_ierrors; 139825944Sjoerg } 139925944Sjoerg break; 140025944Sjoerg case CONF_ACK: 140125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 140225944Sjoerg if (debug) 140369211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 140440008Sjoerg SPP_ARGS(ifp), cp->name, 140525944Sjoerg h->ident, sp->confid[cp->protoidx]); 140625944Sjoerg ++ifp->if_ierrors; 140725944Sjoerg break; 140825944Sjoerg } 140925944Sjoerg switch (sp->state[cp->protoidx]) { 141025944Sjoerg case STATE_CLOSED: 141125944Sjoerg case STATE_STOPPED: 141225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 141325944Sjoerg break; 141425944Sjoerg case STATE_CLOSING: 141525944Sjoerg case STATE_STOPPING: 141625944Sjoerg break; 141725944Sjoerg case STATE_REQ_SENT: 141825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 141925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 142025944Sjoerg break; 142125944Sjoerg case STATE_OPENED: 142225944Sjoerg (cp->tld)(sp); 142325944Sjoerg /* fall through */ 142425944Sjoerg case STATE_ACK_RCVD: 142525944Sjoerg (cp->scr)(sp); 142625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142725944Sjoerg break; 142825944Sjoerg case STATE_ACK_SENT: 142925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 143125944Sjoerg if (debug) 143240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 143340008Sjoerg SPP_ARGS(ifp), cp->name); 143425944Sjoerg (cp->tlu)(sp); 143525944Sjoerg break; 143625944Sjoerg default: 143740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 143840008Sjoerg SPP_ARGS(ifp), cp->name, 143925944Sjoerg sppp_cp_type_name(h->type), 144025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144125944Sjoerg ++ifp->if_ierrors; 144225944Sjoerg } 144325944Sjoerg break; 144425944Sjoerg case CONF_NAK: 144525944Sjoerg case CONF_REJ: 144625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 144725944Sjoerg if (debug) 144869211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 144940008Sjoerg SPP_ARGS(ifp), cp->name, 145025944Sjoerg h->ident, sp->confid[cp->protoidx]); 145125944Sjoerg ++ifp->if_ierrors; 145225944Sjoerg break; 145325944Sjoerg } 145425944Sjoerg if (h->type == CONF_NAK) 145525944Sjoerg (cp->RCN_nak)(sp, h, len); 145625944Sjoerg else /* CONF_REJ */ 145725944Sjoerg (cp->RCN_rej)(sp, h, len); 14584910Swollman 145925944Sjoerg switch (sp->state[cp->protoidx]) { 146025944Sjoerg case STATE_CLOSED: 146125944Sjoerg case STATE_STOPPED: 146225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 146325944Sjoerg break; 146425944Sjoerg case STATE_REQ_SENT: 146525944Sjoerg case STATE_ACK_SENT: 146625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 146770199Sjhay /* 146870199Sjhay * Slow things down a bit if we think we might be 146970199Sjhay * in loopback. Depend on the timeout to send the 147070199Sjhay * next configuration request. 147170199Sjhay */ 147270199Sjhay if (sp->pp_loopcnt) 147370199Sjhay break; 147425944Sjoerg (cp->scr)(sp); 147525944Sjoerg break; 147625944Sjoerg case STATE_OPENED: 147725944Sjoerg (cp->tld)(sp); 147825944Sjoerg /* fall through */ 147925944Sjoerg case STATE_ACK_RCVD: 148052633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148125944Sjoerg (cp->scr)(sp); 148225944Sjoerg break; 148325944Sjoerg case STATE_CLOSING: 148425944Sjoerg case STATE_STOPPING: 148525944Sjoerg break; 148625944Sjoerg default: 148740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 148840008Sjoerg SPP_ARGS(ifp), cp->name, 148925944Sjoerg sppp_cp_type_name(h->type), 149025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 149125944Sjoerg ++ifp->if_ierrors; 149225944Sjoerg } 149325944Sjoerg break; 14944910Swollman 149525944Sjoerg case TERM_REQ: 149625944Sjoerg switch (sp->state[cp->protoidx]) { 149725944Sjoerg case STATE_ACK_RCVD: 149825944Sjoerg case STATE_ACK_SENT: 149925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 150025944Sjoerg /* fall through */ 150125944Sjoerg case STATE_CLOSED: 150225944Sjoerg case STATE_STOPPED: 150325944Sjoerg case STATE_CLOSING: 150425944Sjoerg case STATE_STOPPING: 150525944Sjoerg case STATE_REQ_SENT: 150625944Sjoerg sta: 150725944Sjoerg /* Send Terminate-Ack packet. */ 150825944Sjoerg if (debug) 150940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 151040008Sjoerg SPP_ARGS(ifp), cp->name); 151125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 151225944Sjoerg break; 151325944Sjoerg case STATE_OPENED: 151425944Sjoerg (cp->tld)(sp); 151525944Sjoerg sp->rst_counter[cp->protoidx] = 0; 151625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 151725944Sjoerg goto sta; 151825944Sjoerg break; 151925944Sjoerg default: 152040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 152140008Sjoerg SPP_ARGS(ifp), cp->name, 152225944Sjoerg sppp_cp_type_name(h->type), 152325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152425944Sjoerg ++ifp->if_ierrors; 152525944Sjoerg } 152625944Sjoerg break; 152725944Sjoerg case TERM_ACK: 152825944Sjoerg switch (sp->state[cp->protoidx]) { 152925944Sjoerg case STATE_CLOSED: 153025944Sjoerg case STATE_STOPPED: 153125944Sjoerg case STATE_REQ_SENT: 153225944Sjoerg case STATE_ACK_SENT: 153325944Sjoerg break; 153425944Sjoerg case STATE_CLOSING: 153541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 153625944Sjoerg (cp->tlf)(sp); 153725944Sjoerg break; 153825944Sjoerg case STATE_STOPPING: 153941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 154025944Sjoerg (cp->tlf)(sp); 154125944Sjoerg break; 154225944Sjoerg case STATE_ACK_RCVD: 154325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154425944Sjoerg break; 154525944Sjoerg case STATE_OPENED: 154625944Sjoerg (cp->tld)(sp); 154725944Sjoerg (cp->scr)(sp); 154825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 154925944Sjoerg break; 155025944Sjoerg default: 155140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 155240008Sjoerg SPP_ARGS(ifp), cp->name, 155325944Sjoerg sppp_cp_type_name(h->type), 155425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155525944Sjoerg ++ifp->if_ierrors; 155625944Sjoerg } 155725944Sjoerg break; 155825944Sjoerg case CODE_REJ: 155925944Sjoerg case PROTO_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; 158625944Sjoerg case DISC_REQ: 158725944Sjoerg if (cp->proto != PPP_LCP) 158825944Sjoerg goto illegal; 158925944Sjoerg /* Discard the packet. */ 159025944Sjoerg break; 159125944Sjoerg case ECHO_REQ: 159225944Sjoerg if (cp->proto != PPP_LCP) 159325944Sjoerg goto illegal; 159425944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 159525944Sjoerg if (debug) 159669211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 159740008Sjoerg SPP_ARGS(ifp)); 159825944Sjoerg ++ifp->if_ierrors; 159925944Sjoerg break; 160025944Sjoerg } 160125944Sjoerg if (len < 8) { 160225944Sjoerg if (debug) 160369211Sphk log(-1, SPP_FMT "invalid lcp echo request " 160425944Sjoerg "packet length: %d bytes\n", 160540008Sjoerg SPP_ARGS(ifp), len); 160625944Sjoerg break; 160725944Sjoerg } 160844145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 160944145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 161025944Sjoerg /* Line loopback mode detected. */ 161140008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 161270199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 161325944Sjoerg if_down (ifp); 161426018Sjoerg sppp_qflush (&sp->pp_cpq); 16154910Swollman 161625944Sjoerg /* Shut down the PPP link. */ 161725944Sjoerg /* XXX */ 161825944Sjoerg lcp.Down(sp); 161925944Sjoerg lcp.Up(sp); 162025944Sjoerg break; 162125944Sjoerg } 162225944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 162325944Sjoerg if (debug) 162469211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 162540008Sjoerg SPP_ARGS(ifp)); 162625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 162725944Sjoerg break; 162825944Sjoerg case ECHO_REPLY: 162925944Sjoerg if (cp->proto != PPP_LCP) 163025944Sjoerg goto illegal; 163125944Sjoerg if (h->ident != sp->lcp.echoid) { 163225944Sjoerg ++ifp->if_ierrors; 163325944Sjoerg break; 163425944Sjoerg } 163525944Sjoerg if (len < 8) { 163625944Sjoerg if (debug) 163769211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 163825944Sjoerg "packet length: %d bytes\n", 163940008Sjoerg SPP_ARGS(ifp), len); 164025944Sjoerg break; 164125944Sjoerg } 164225944Sjoerg if (debug) 164369211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 164440008Sjoerg SPP_ARGS(ifp)); 164544145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 164644145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 164725944Sjoerg sp->pp_alivecnt = 0; 164825944Sjoerg break; 164925944Sjoerg default: 165025944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 165125944Sjoerg illegal: 165225944Sjoerg if (debug) 165369211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 165440008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 165578064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 165678064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 165725944Sjoerg ++ifp->if_ierrors; 165825944Sjoerg } 16594910Swollman} 16604910Swollman 166125944Sjoerg 16624910Swollman/* 166325944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 166425944Sjoerg * Basically, the state transition handling in the automaton. 16654910Swollman */ 166625944Sjoergstatic void 166725944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 16684910Swollman{ 166925944Sjoerg STDDCL; 16704910Swollman 167125944Sjoerg if (debug) 167240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 167340008Sjoerg SPP_ARGS(ifp), cp->name, 167425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 167525944Sjoerg 167625944Sjoerg switch (sp->state[cp->protoidx]) { 167725944Sjoerg case STATE_INITIAL: 167825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 167925944Sjoerg break; 168025944Sjoerg case STATE_STARTING: 168125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 168225944Sjoerg (cp->scr)(sp); 168325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 168425944Sjoerg break; 16854910Swollman default: 168640008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 168740008Sjoerg SPP_ARGS(ifp), cp->name, 168825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 168925944Sjoerg } 169025944Sjoerg} 16914910Swollman 169225944Sjoergstatic void 169325944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 169425944Sjoerg{ 169525944Sjoerg STDDCL; 169625944Sjoerg 169725944Sjoerg if (debug) 169840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 169940008Sjoerg SPP_ARGS(ifp), cp->name, 170025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 170125944Sjoerg 170225944Sjoerg switch (sp->state[cp->protoidx]) { 170325944Sjoerg case STATE_CLOSED: 170425944Sjoerg case STATE_CLOSING: 170525944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 17064910Swollman break; 170725944Sjoerg case STATE_STOPPED: 170841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 170925944Sjoerg (cp->tls)(sp); 171041881Sphk break; 171125944Sjoerg case STATE_STOPPING: 171225944Sjoerg case STATE_REQ_SENT: 171325944Sjoerg case STATE_ACK_RCVD: 171425944Sjoerg case STATE_ACK_SENT: 171525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 171625944Sjoerg break; 171725944Sjoerg case STATE_OPENED: 171825944Sjoerg (cp->tld)(sp); 171925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 172025944Sjoerg break; 172125944Sjoerg default: 172240008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 172340008Sjoerg SPP_ARGS(ifp), cp->name, 172425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172525944Sjoerg } 172625944Sjoerg} 17274910Swollman 172811189Sjkh 172925944Sjoergstatic void 173025944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 173125944Sjoerg{ 173225944Sjoerg STDDCL; 173325944Sjoerg 173425944Sjoerg if (debug) 173540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 173640008Sjoerg SPP_ARGS(ifp), cp->name, 173725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 173825944Sjoerg 173925944Sjoerg switch (sp->state[cp->protoidx]) { 174025944Sjoerg case STATE_INITIAL: 174141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 174225944Sjoerg (cp->tls)(sp); 17434910Swollman break; 174425944Sjoerg case STATE_STARTING: 174525944Sjoerg break; 174625944Sjoerg case STATE_CLOSED: 174725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 174825944Sjoerg (cp->scr)(sp); 174925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 175025944Sjoerg break; 175125944Sjoerg case STATE_STOPPED: 175274703Sjoerg /* 175374703Sjoerg * Try escaping stopped state. This seems to bite 175474703Sjoerg * people occasionally, in particular for IPCP, 175574703Sjoerg * presumably following previous IPCP negotiation 175674703Sjoerg * aborts. Somehow, we must have missed a Down event 175774703Sjoerg * which would have caused a transition into starting 175874703Sjoerg * state, so as a bandaid we force the Down event now. 175974703Sjoerg * This effectively implements (something like the) 176074703Sjoerg * `restart' option mentioned in the state transition 176174703Sjoerg * table of RFC 1661. 176274703Sjoerg */ 176374703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 176474703Sjoerg (cp->tls)(sp); 176574703Sjoerg break; 176625944Sjoerg case STATE_STOPPING: 176725944Sjoerg case STATE_REQ_SENT: 176825944Sjoerg case STATE_ACK_RCVD: 176925944Sjoerg case STATE_ACK_SENT: 177025944Sjoerg case STATE_OPENED: 177125944Sjoerg break; 177225944Sjoerg case STATE_CLOSING: 177325944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 177425944Sjoerg break; 177525944Sjoerg } 177625944Sjoerg} 17774910Swollman 177825944Sjoerg 177925944Sjoergstatic void 178025944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 178125944Sjoerg{ 178225944Sjoerg STDDCL; 178325944Sjoerg 178425944Sjoerg if (debug) 178540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 178640008Sjoerg SPP_ARGS(ifp), cp->name, 178725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 178825944Sjoerg 178925944Sjoerg switch (sp->state[cp->protoidx]) { 179025944Sjoerg case STATE_INITIAL: 179125944Sjoerg case STATE_CLOSED: 179225944Sjoerg case STATE_CLOSING: 17934910Swollman break; 179425944Sjoerg case STATE_STARTING: 179541881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 179625944Sjoerg (cp->tlf)(sp); 17974910Swollman break; 179825944Sjoerg case STATE_STOPPED: 179925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 18004910Swollman break; 180125944Sjoerg case STATE_STOPPING: 180225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18034910Swollman break; 180425944Sjoerg case STATE_OPENED: 180525944Sjoerg (cp->tld)(sp); 180625944Sjoerg /* fall through */ 180725944Sjoerg case STATE_REQ_SENT: 180825944Sjoerg case STATE_ACK_RCVD: 180925944Sjoerg case STATE_ACK_SENT: 181025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 181178064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 181278064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 181325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 18144910Swollman break; 18154910Swollman } 18164910Swollman} 18174910Swollman 181825944Sjoergstatic void 181925944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 182025944Sjoerg{ 182125944Sjoerg STDDCL; 182225944Sjoerg int s; 182325944Sjoerg 182425944Sjoerg s = splimp(); 182525944Sjoerg if (debug) 182640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 182740008Sjoerg SPP_ARGS(ifp), cp->name, 182825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 182925944Sjoerg sp->rst_counter[cp->protoidx]); 183025944Sjoerg 183125944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 183225944Sjoerg /* TO- event */ 183325944Sjoerg switch (sp->state[cp->protoidx]) { 183425944Sjoerg case STATE_CLOSING: 183541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 183625944Sjoerg (cp->tlf)(sp); 183725944Sjoerg break; 183825944Sjoerg case STATE_STOPPING: 183941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 184025944Sjoerg (cp->tlf)(sp); 184125944Sjoerg break; 184225944Sjoerg case STATE_REQ_SENT: 184325944Sjoerg case STATE_ACK_RCVD: 184425944Sjoerg case STATE_ACK_SENT: 184541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 184625944Sjoerg (cp->tlf)(sp); 184725944Sjoerg break; 184825944Sjoerg } 184925944Sjoerg else 185025944Sjoerg /* TO+ event */ 185125944Sjoerg switch (sp->state[cp->protoidx]) { 185225944Sjoerg case STATE_CLOSING: 185325944Sjoerg case STATE_STOPPING: 185478064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 185578064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 185670199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 185742064Sphk sp->ch[cp->protoidx]); 185825944Sjoerg break; 185925944Sjoerg case STATE_REQ_SENT: 186025944Sjoerg case STATE_ACK_RCVD: 186125944Sjoerg (cp->scr)(sp); 186225944Sjoerg /* sppp_cp_change_state() will restart the timer */ 186325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 186425944Sjoerg break; 186525944Sjoerg case STATE_ACK_SENT: 186625944Sjoerg (cp->scr)(sp); 186742064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 186842064Sphk sp->ch[cp->protoidx]); 186925944Sjoerg break; 187025944Sjoerg } 187125944Sjoerg 187225944Sjoerg splx(s); 187325944Sjoerg} 187425944Sjoerg 187511189Sjkh/* 187625944Sjoerg * Change the state of a control protocol in the state automaton. 187725944Sjoerg * Takes care of starting/stopping the restart timer. 187811189Sjkh */ 187925944Sjoergvoid 188025944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 188125944Sjoerg{ 188225944Sjoerg sp->state[cp->protoidx] = newstate; 188325944Sjoerg 188440008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 188525944Sjoerg switch (newstate) { 188625944Sjoerg case STATE_INITIAL: 188725944Sjoerg case STATE_STARTING: 188825944Sjoerg case STATE_CLOSED: 188925944Sjoerg case STATE_STOPPED: 189025944Sjoerg case STATE_OPENED: 189125944Sjoerg break; 189225944Sjoerg case STATE_CLOSING: 189325944Sjoerg case STATE_STOPPING: 189425944Sjoerg case STATE_REQ_SENT: 189525944Sjoerg case STATE_ACK_RCVD: 189625944Sjoerg case STATE_ACK_SENT: 189770199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 189842064Sphk sp->ch[cp->protoidx]); 189925944Sjoerg break; 190025944Sjoerg } 190125944Sjoerg} 190270199Sjhay 190370199Sjhay/* 190425944Sjoerg *--------------------------------------------------------------------------* 190525944Sjoerg * * 190625944Sjoerg * The LCP implementation. * 190725944Sjoerg * * 190825944Sjoerg *--------------------------------------------------------------------------* 190925944Sjoerg */ 191025944Sjoergstatic void 191125944Sjoergsppp_lcp_init(struct sppp *sp) 191225944Sjoerg{ 191325944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 191425944Sjoerg sp->lcp.magic = 0; 191525944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 191625944Sjoerg sp->fail_counter[IDX_LCP] = 0; 191778064Sume sp->pp_seq[IDX_LCP] = 0; 191878064Sume sp->pp_rseq[IDX_LCP] = 0; 191925944Sjoerg sp->lcp.protos = 0; 192025944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 192130300Sjoerg 192244145Sphk /* Note that these values are relevant for all control protocols */ 192344145Sphk sp->lcp.timeout = 3 * hz; 192425944Sjoerg sp->lcp.max_terminate = 2; 192525944Sjoerg sp->lcp.max_configure = 10; 192625944Sjoerg sp->lcp.max_failure = 10; 192742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 192830300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 192940008Sjoerg#endif 193025944Sjoerg} 193125944Sjoerg 193225944Sjoergstatic void 193325944Sjoergsppp_lcp_up(struct sppp *sp) 193425944Sjoerg{ 193525944Sjoerg STDDCL; 193625944Sjoerg 193770199Sjhay sp->pp_alivecnt = 0; 193870199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 193970199Sjhay sp->lcp.magic = 0; 194070199Sjhay sp->lcp.protos = 0; 194170199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 194225944Sjoerg /* 194375321Sjoerg * If we are authenticator, negotiate LCP_AUTH 194475321Sjoerg */ 194575321Sjoerg if (sp->hisauth.proto != 0) 194675321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 194775321Sjoerg else 194875321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 194975321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 195075321Sjoerg /* 195130300Sjoerg * If this interface is passive or dial-on-demand, and we are 195230300Sjoerg * still in Initial state, it means we've got an incoming 195330300Sjoerg * call. Activate the interface. 195425944Sjoerg */ 195525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 195625944Sjoerg if (debug) 195725944Sjoerg log(LOG_DEBUG, 195840008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 195925944Sjoerg ifp->if_flags |= IFF_RUNNING; 196030300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 196130300Sjoerg if (debug) 196269211Sphk log(-1, "(incoming call)\n"); 196330300Sjoerg sp->pp_flags |= PP_CALLIN; 196430300Sjoerg lcp.Open(sp); 196530300Sjoerg } else if (debug) 196669211Sphk log(-1, "\n"); 196725944Sjoerg } 196825944Sjoerg 196925944Sjoerg sppp_up_event(&lcp, sp); 197025944Sjoerg} 197125944Sjoerg 197225944Sjoergstatic void 197325944Sjoergsppp_lcp_down(struct sppp *sp) 197425944Sjoerg{ 197525944Sjoerg STDDCL; 197625944Sjoerg 197725944Sjoerg sppp_down_event(&lcp, sp); 197825944Sjoerg 197925944Sjoerg /* 198025944Sjoerg * If this is neither a dial-on-demand nor a passive 198125944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 198225944Sjoerg * administrator can force a redial by another ``ifconfig 198325944Sjoerg * up''. XXX For leased line operation, should we immediately 198425944Sjoerg * try to reopen the connection here? 198525944Sjoerg */ 198625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 198725944Sjoerg log(LOG_INFO, 198842066Sphk SPP_FMT "Down event, taking interface down.\n", 198940008Sjoerg SPP_ARGS(ifp)); 199025944Sjoerg if_down(ifp); 199125944Sjoerg } else { 199225944Sjoerg if (debug) 199325944Sjoerg log(LOG_DEBUG, 199440008Sjoerg SPP_FMT "Down event (carrier loss)\n", 199540008Sjoerg SPP_ARGS(ifp)); 199670199Sjhay sp->pp_flags &= ~PP_CALLIN; 199770199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 199870199Sjhay lcp.Close(sp); 199970199Sjhay ifp->if_flags &= ~IFF_RUNNING; 200025944Sjoerg } 200125944Sjoerg} 200225944Sjoerg 200325944Sjoergstatic void 200425944Sjoergsppp_lcp_open(struct sppp *sp) 200525944Sjoerg{ 200625944Sjoerg sppp_open_event(&lcp, sp); 200725944Sjoerg} 200825944Sjoerg 200925944Sjoergstatic void 201025944Sjoergsppp_lcp_close(struct sppp *sp) 201125944Sjoerg{ 201225944Sjoerg sppp_close_event(&lcp, sp); 201325944Sjoerg} 201425944Sjoerg 201525944Sjoergstatic void 201625944Sjoergsppp_lcp_TO(void *cookie) 201725944Sjoerg{ 201825944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 201925944Sjoerg} 202025944Sjoerg 202125944Sjoerg/* 202225944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 202325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 202425944Sjoerg * caused action scn. (The return value is used to make the state 202525944Sjoerg * transition decision in the state automaton.) 202625944Sjoerg */ 202712820Sphkstatic int 202825944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 20294910Swollman{ 203025944Sjoerg STDDCL; 203111189Sjkh u_char *buf, *r, *p; 203225944Sjoerg int origlen, rlen; 203325944Sjoerg u_long nmagic; 203430300Sjoerg u_short authproto; 20354910Swollman 203611189Sjkh len -= 4; 203725944Sjoerg origlen = len; 203811189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 203911189Sjkh if (! buf) 204011189Sjkh return (0); 20414910Swollman 204225706Sjoerg if (debug) 204340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 204440008Sjoerg SPP_ARGS(ifp)); 204525706Sjoerg 204625944Sjoerg /* pass 1: check for things that need to be rejected */ 204711189Sjkh p = (void*) (h+1); 204811189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 204925944Sjoerg if (debug) 205069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 205111189Sjkh switch (*p) { 205211189Sjkh case LCP_OPT_MAGIC: 205325944Sjoerg /* Magic number. */ 205470199Sjhay if (len >= 6 && p[1] == 6) 205570199Sjhay continue; 205670199Sjhay if (debug) 205770199Sjhay log(-1, "[invalid] "); 205870199Sjhay break; 205925944Sjoerg case LCP_OPT_ASYNC_MAP: 206025944Sjoerg /* Async control character map. */ 206170199Sjhay if (len >= 6 && p[1] == 6) 206225944Sjoerg continue; 206325944Sjoerg if (debug) 206469211Sphk log(-1, "[invalid] "); 206525944Sjoerg break; 206625944Sjoerg case LCP_OPT_MRU: 206725944Sjoerg /* Maximum receive unit. */ 206825944Sjoerg if (len >= 4 && p[1] == 4) 206925944Sjoerg continue; 207025944Sjoerg if (debug) 207169211Sphk log(-1, "[invalid] "); 207225944Sjoerg break; 207330300Sjoerg case LCP_OPT_AUTH_PROTO: 207430300Sjoerg if (len < 4) { 207530300Sjoerg if (debug) 207669211Sphk log(-1, "[invalid] "); 207730300Sjoerg break; 207830300Sjoerg } 207930300Sjoerg authproto = (p[2] << 8) + p[3]; 208030300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 208130300Sjoerg if (debug) 208269211Sphk log(-1, "[invalid chap len] "); 208330300Sjoerg break; 208430300Sjoerg } 208530300Sjoerg if (sp->myauth.proto == 0) { 208630300Sjoerg /* we are not configured to do auth */ 208730300Sjoerg if (debug) 208869211Sphk log(-1, "[not configured] "); 208930300Sjoerg break; 209030300Sjoerg } 209130300Sjoerg /* 209230300Sjoerg * Remote want us to authenticate, remember this, 209330300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 209430300Sjoerg * up. 209530300Sjoerg */ 209630300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 209730300Sjoerg continue; 209825944Sjoerg default: 209925944Sjoerg /* Others not supported. */ 210025944Sjoerg if (debug) 210169211Sphk log(-1, "[rej] "); 210225944Sjoerg break; 210325944Sjoerg } 210425944Sjoerg /* Add the option to rejected list. */ 210525944Sjoerg bcopy (p, r, p[1]); 210625944Sjoerg r += p[1]; 210725944Sjoerg rlen += p[1]; 210825944Sjoerg } 210925944Sjoerg if (rlen) { 211025944Sjoerg if (debug) 211169211Sphk log(-1, " send conf-rej\n"); 211225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 211325944Sjoerg return 0; 211425944Sjoerg } else if (debug) 211569211Sphk log(-1, "\n"); 211625944Sjoerg 211725944Sjoerg /* 211825944Sjoerg * pass 2: check for option values that are unacceptable and 211925944Sjoerg * thus require to be nak'ed. 212025944Sjoerg */ 212125944Sjoerg if (debug) 212240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 212340008Sjoerg SPP_ARGS(ifp)); 212425944Sjoerg 212525944Sjoerg p = (void*) (h+1); 212625944Sjoerg len = origlen; 212725944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 212825944Sjoerg if (debug) 212969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 213025944Sjoerg switch (*p) { 213125944Sjoerg case LCP_OPT_MAGIC: 213211189Sjkh /* Magic number -- extract. */ 213325944Sjoerg nmagic = (u_long)p[2] << 24 | 213425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 213525944Sjoerg if (nmagic != sp->lcp.magic) { 213670199Sjhay sp->pp_loopcnt = 0; 213725706Sjoerg if (debug) 213869211Sphk log(-1, "0x%lx ", nmagic); 213911189Sjkh continue; 214011189Sjkh } 214170199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 214269211Sphk log(-1, "[glitch] "); 214325944Sjoerg ++sp->pp_loopcnt; 214425944Sjoerg /* 214525944Sjoerg * We negate our magic here, and NAK it. If 214625944Sjoerg * we see it later in an NAK packet, we 214725944Sjoerg * suggest a new one. 214825944Sjoerg */ 214925944Sjoerg nmagic = ~sp->lcp.magic; 215025944Sjoerg /* Gonna NAK it. */ 215125944Sjoerg p[2] = nmagic >> 24; 215225944Sjoerg p[3] = nmagic >> 16; 215325944Sjoerg p[4] = nmagic >> 8; 215425944Sjoerg p[5] = nmagic; 215511189Sjkh break; 215625944Sjoerg 215711189Sjkh case LCP_OPT_ASYNC_MAP: 215811189Sjkh /* Async control character map -- check to be zero. */ 215925944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 216025706Sjoerg if (debug) 216169211Sphk log(-1, "[empty] "); 216211189Sjkh continue; 216325706Sjoerg } 216425706Sjoerg if (debug) 216569211Sphk log(-1, "[non-empty] "); 216625944Sjoerg /* suggest a zero one */ 216725944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 216811189Sjkh break; 216925944Sjoerg 217011189Sjkh case LCP_OPT_MRU: 217125944Sjoerg /* 217225944Sjoerg * Maximum receive unit. Always agreeable, 217325944Sjoerg * but ignored by now. 217425944Sjoerg */ 217525944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 217625706Sjoerg if (debug) 217769211Sphk log(-1, "%lu ", sp->lcp.their_mru); 217811189Sjkh continue; 217930300Sjoerg 218030300Sjoerg case LCP_OPT_AUTH_PROTO: 218130300Sjoerg authproto = (p[2] << 8) + p[3]; 218230300Sjoerg if (sp->myauth.proto != authproto) { 218330300Sjoerg /* not agreed, nak */ 218430300Sjoerg if (debug) 218569211Sphk log(-1, "[mine %s != his %s] ", 218630300Sjoerg sppp_proto_name(sp->hisauth.proto), 218730300Sjoerg sppp_proto_name(authproto)); 218830300Sjoerg p[2] = sp->myauth.proto >> 8; 218930300Sjoerg p[3] = sp->myauth.proto; 219030300Sjoerg break; 219130300Sjoerg } 219230300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 219330300Sjoerg if (debug) 219469211Sphk log(-1, "[chap not MD5] "); 219539981Sjoerg p[4] = CHAP_MD5; 219630300Sjoerg break; 219730300Sjoerg } 219830300Sjoerg continue; 219911189Sjkh } 220025944Sjoerg /* Add the option to nak'ed list. */ 220125706Sjoerg bcopy (p, r, p[1]); 220225706Sjoerg r += p[1]; 220311189Sjkh rlen += p[1]; 220412436Speter } 220525706Sjoerg if (rlen) { 220670199Sjhay /* 220770199Sjhay * Local and remote magics equal -- loopback? 220870199Sjhay */ 220970199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 221070199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 221170199Sjhay printf (SPP_FMT "loopback\n", 221270199Sjhay SPP_ARGS(ifp)); 221370199Sjhay if (ifp->if_flags & IFF_UP) { 221470199Sjhay if_down(ifp); 221570199Sjhay sppp_qflush(&sp->pp_cpq); 221670199Sjhay /* XXX ? */ 221770199Sjhay lcp.Down(sp); 221870199Sjhay lcp.Up(sp); 221970199Sjhay } 222070199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 222128036Sjoerg if (debug) 222269211Sphk log(-1, " max_failure (%d) exceeded, " 222328036Sjoerg "send conf-rej\n", 222428036Sjoerg sp->lcp.max_failure); 222528036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 222628036Sjoerg } else { 222728036Sjoerg if (debug) 222869211Sphk log(-1, " send conf-nak\n"); 222928036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 223028036Sjoerg } 223125944Sjoerg } else { 223225944Sjoerg if (debug) 223369211Sphk log(-1, " send conf-ack\n"); 223428036Sjoerg sp->fail_counter[IDX_LCP] = 0; 223525944Sjoerg sp->pp_loopcnt = 0; 223625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 223725944Sjoerg h->ident, origlen, h+1); 223825944Sjoerg } 223925944Sjoerg 224011189Sjkh free (buf, M_TEMP); 224111189Sjkh return (rlen == 0); 22424910Swollman} 22434910Swollman 224425944Sjoerg/* 224525944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 224625944Sjoerg * negotiation. 224725944Sjoerg */ 224812820Sphkstatic void 224925944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 22504910Swollman{ 225125944Sjoerg STDDCL; 225225944Sjoerg u_char *buf, *p; 22534910Swollman 225425944Sjoerg len -= 4; 225525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 225625944Sjoerg if (!buf) 22574910Swollman return; 225825944Sjoerg 225925944Sjoerg if (debug) 226040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 226140008Sjoerg SPP_ARGS(ifp)); 226225944Sjoerg 226325944Sjoerg p = (void*) (h+1); 226425944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 226525944Sjoerg if (debug) 226669211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 226725944Sjoerg switch (*p) { 226825944Sjoerg case LCP_OPT_MAGIC: 226925944Sjoerg /* Magic number -- can't use it, use 0 */ 227025944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 227125944Sjoerg sp->lcp.magic = 0; 227225944Sjoerg break; 227325944Sjoerg case LCP_OPT_MRU: 227425944Sjoerg /* 227525944Sjoerg * Should not be rejected anyway, since we only 227625944Sjoerg * negotiate a MRU if explicitly requested by 227725944Sjoerg * peer. 227825944Sjoerg */ 227925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 228025944Sjoerg break; 228130300Sjoerg case LCP_OPT_AUTH_PROTO: 228230300Sjoerg /* 228330300Sjoerg * Peer doesn't want to authenticate himself, 228430300Sjoerg * deny unless this is a dialout call, and 228530300Sjoerg * AUTHFLAG_NOCALLOUT is set. 228630300Sjoerg */ 228730300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 228830300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 228930300Sjoerg if (debug) 229069211Sphk log(-1, "[don't insist on auth " 229130300Sjoerg "for callout]"); 229230300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 229330300Sjoerg break; 229430300Sjoerg } 229530300Sjoerg if (debug) 229669211Sphk log(-1, "[access denied]\n"); 229730300Sjoerg lcp.Close(sp); 229830300Sjoerg break; 229925944Sjoerg } 23004910Swollman } 230125944Sjoerg if (debug) 230269211Sphk log(-1, "\n"); 230325944Sjoerg free (buf, M_TEMP); 230425944Sjoerg return; 230525944Sjoerg} 230625944Sjoerg 230725944Sjoerg/* 230825944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 230925944Sjoerg * negotiation. 231025944Sjoerg */ 231125944Sjoergstatic void 231225944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 231325944Sjoerg{ 231425944Sjoerg STDDCL; 231525944Sjoerg u_char *buf, *p; 231625944Sjoerg u_long magic; 231725944Sjoerg 231825944Sjoerg len -= 4; 231925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 232025944Sjoerg if (!buf) 232125944Sjoerg return; 232225944Sjoerg 232325944Sjoerg if (debug) 232440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 232540008Sjoerg SPP_ARGS(ifp)); 232625944Sjoerg 232725944Sjoerg p = (void*) (h+1); 232825944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 232925706Sjoerg if (debug) 233069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 233125944Sjoerg switch (*p) { 233225944Sjoerg case LCP_OPT_MAGIC: 233325944Sjoerg /* Magic number -- renegotiate */ 233425944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 233525944Sjoerg len >= 6 && p[1] == 6) { 233625944Sjoerg magic = (u_long)p[2] << 24 | 233725944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 233825944Sjoerg /* 233925944Sjoerg * If the remote magic is our negated one, 234025944Sjoerg * this looks like a loopback problem. 234125944Sjoerg * Suggest a new magic to make sure. 234225944Sjoerg */ 234325944Sjoerg if (magic == ~sp->lcp.magic) { 234425944Sjoerg if (debug) 234569211Sphk log(-1, "magic glitch "); 234642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 234735064Sphk sp->lcp.magic = random(); 234840008Sjoerg#else 234940008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 235040008Sjoerg#endif 235125944Sjoerg } else { 235225944Sjoerg sp->lcp.magic = magic; 235325944Sjoerg if (debug) 235469211Sphk log(-1, "%lu ", magic); 235525944Sjoerg } 235625944Sjoerg } 235725944Sjoerg break; 235825944Sjoerg case LCP_OPT_MRU: 235925944Sjoerg /* 236025944Sjoerg * Peer wants to advise us to negotiate an MRU. 236125944Sjoerg * Agree on it if it's reasonable, or use 236225944Sjoerg * default otherwise. 236325944Sjoerg */ 236425944Sjoerg if (len >= 4 && p[1] == 4) { 236525944Sjoerg u_int mru = p[2] * 256 + p[3]; 236625944Sjoerg if (debug) 236769211Sphk log(-1, "%d ", mru); 236825944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 236925944Sjoerg mru = PP_MTU; 237025944Sjoerg sp->lcp.mru = mru; 237125944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 237225944Sjoerg } 237325944Sjoerg break; 237430300Sjoerg case LCP_OPT_AUTH_PROTO: 237530300Sjoerg /* 237630300Sjoerg * Peer doesn't like our authentication method, 237730300Sjoerg * deny. 237830300Sjoerg */ 237930300Sjoerg if (debug) 238069211Sphk log(-1, "[access denied]\n"); 238130300Sjoerg lcp.Close(sp); 238230300Sjoerg break; 23834910Swollman } 238425944Sjoerg } 238525944Sjoerg if (debug) 238669211Sphk log(-1, "\n"); 238725944Sjoerg free (buf, M_TEMP); 238825944Sjoerg return; 238925944Sjoerg} 239011189Sjkh 239125944Sjoergstatic void 239225944Sjoergsppp_lcp_tlu(struct sppp *sp) 239325944Sjoerg{ 239442066Sphk STDDCL; 239525944Sjoerg int i; 239625944Sjoerg u_long mask; 239725944Sjoerg 239825944Sjoerg /* XXX ? */ 239925944Sjoerg if (! (ifp->if_flags & IFF_UP) && 240025944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 240125944Sjoerg /* Coming out of loopback mode. */ 240225944Sjoerg if_up(ifp); 240340008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 240425944Sjoerg } 240525944Sjoerg 240625944Sjoerg for (i = 0; i < IDX_COUNT; i++) 240725944Sjoerg if ((cps[i])->flags & CP_QUAL) 240825944Sjoerg (cps[i])->Open(sp); 240925944Sjoerg 241030300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 241130300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 241225944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 241325944Sjoerg else 241425944Sjoerg sp->pp_phase = PHASE_NETWORK; 241525944Sjoerg 241642066Sphk if (debug) 241742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 241842066Sphk sppp_phase_name(sp->pp_phase)); 241925944Sjoerg 242030300Sjoerg /* 242130300Sjoerg * Open all authentication protocols. This is even required 242230300Sjoerg * if we already proceeded to network phase, since it might be 242330300Sjoerg * that remote wants us to authenticate, so we might have to 242430300Sjoerg * send a PAP request. Undesired authentication protocols 242530300Sjoerg * don't do anything when they get an Open event. 242630300Sjoerg */ 242730300Sjoerg for (i = 0; i < IDX_COUNT; i++) 242830300Sjoerg if ((cps[i])->flags & CP_AUTH) 242930300Sjoerg (cps[i])->Open(sp); 243030300Sjoerg 243130300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 243225944Sjoerg /* Notify all NCPs. */ 243325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 243425944Sjoerg if ((cps[i])->flags & CP_NCP) 243525944Sjoerg (cps[i])->Open(sp); 243625944Sjoerg } 243725944Sjoerg 243825944Sjoerg /* Send Up events to all started protos. */ 243925944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 244025944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 244125944Sjoerg (cps[i])->Up(sp); 244225944Sjoerg 244342104Sphk /* notify low-level driver of state change */ 244442104Sphk if (sp->pp_chg) 244542104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 244642104Sphk 244725944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 244825944Sjoerg /* if no NCP is starting, close down */ 244930300Sjoerg sppp_lcp_check_and_close(sp); 245025944Sjoerg} 245125944Sjoerg 245225944Sjoergstatic void 245325944Sjoergsppp_lcp_tld(struct sppp *sp) 245425944Sjoerg{ 245542066Sphk STDDCL; 245625944Sjoerg int i; 245725944Sjoerg u_long mask; 245825944Sjoerg 245925944Sjoerg sp->pp_phase = PHASE_TERMINATE; 246025944Sjoerg 246142066Sphk if (debug) 246242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 246342066Sphk sppp_phase_name(sp->pp_phase)); 246425944Sjoerg 246525944Sjoerg /* 246625944Sjoerg * Take upper layers down. We send the Down event first and 246725944Sjoerg * the Close second to prevent the upper layers from sending 246825944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 246925944Sjoerg * describes it. 247025944Sjoerg */ 247125944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 247225944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 247325944Sjoerg (cps[i])->Down(sp); 247425944Sjoerg (cps[i])->Close(sp); 247525944Sjoerg } 247625944Sjoerg} 247725944Sjoerg 247825944Sjoergstatic void 247925944Sjoergsppp_lcp_tls(struct sppp *sp) 248025944Sjoerg{ 248142066Sphk STDDCL; 248225944Sjoerg 248325944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 248425944Sjoerg 248542066Sphk if (debug) 248642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 248742066Sphk sppp_phase_name(sp->pp_phase)); 248825944Sjoerg 248925944Sjoerg /* Notify lower layer if desired. */ 249025944Sjoerg if (sp->pp_tls) 249125944Sjoerg (sp->pp_tls)(sp); 249241881Sphk else 249341881Sphk (sp->pp_up)(sp); 249425944Sjoerg} 249525944Sjoerg 249625944Sjoergstatic void 249725944Sjoergsppp_lcp_tlf(struct sppp *sp) 249825944Sjoerg{ 249942066Sphk STDDCL; 250025944Sjoerg 250125944Sjoerg sp->pp_phase = PHASE_DEAD; 250242066Sphk if (debug) 250342066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 250442066Sphk sppp_phase_name(sp->pp_phase)); 250525944Sjoerg 250625944Sjoerg /* Notify lower layer if desired. */ 250725944Sjoerg if (sp->pp_tlf) 250825944Sjoerg (sp->pp_tlf)(sp); 250941881Sphk else 251041881Sphk (sp->pp_down)(sp); 251125944Sjoerg} 251225944Sjoerg 251325944Sjoergstatic void 251425944Sjoergsppp_lcp_scr(struct sppp *sp) 251525944Sjoerg{ 251630300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 251725944Sjoerg int i = 0; 251830300Sjoerg u_short authproto; 251925944Sjoerg 252025944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 252125944Sjoerg if (! sp->lcp.magic) 252242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 252335064Sphk sp->lcp.magic = random(); 252440008Sjoerg#else 252540008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 252640008Sjoerg#endif 252725944Sjoerg opt[i++] = LCP_OPT_MAGIC; 252825944Sjoerg opt[i++] = 6; 252925944Sjoerg opt[i++] = sp->lcp.magic >> 24; 253025944Sjoerg opt[i++] = sp->lcp.magic >> 16; 253125944Sjoerg opt[i++] = sp->lcp.magic >> 8; 253225944Sjoerg opt[i++] = sp->lcp.magic; 253325944Sjoerg } 253425944Sjoerg 253525944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 253625944Sjoerg opt[i++] = LCP_OPT_MRU; 253725944Sjoerg opt[i++] = 4; 253825944Sjoerg opt[i++] = sp->lcp.mru >> 8; 253925944Sjoerg opt[i++] = sp->lcp.mru; 254025944Sjoerg } 254125944Sjoerg 254230300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 254330300Sjoerg authproto = sp->hisauth.proto; 254430300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 254530300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 254630300Sjoerg opt[i++] = authproto >> 8; 254730300Sjoerg opt[i++] = authproto; 254830300Sjoerg if (authproto == PPP_CHAP) 254930300Sjoerg opt[i++] = CHAP_MD5; 255030300Sjoerg } 255130300Sjoerg 255278064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 255325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 255425944Sjoerg} 255525944Sjoerg 255625944Sjoerg/* 255730300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 255830300Sjoerg */ 255930300Sjoergstatic int 256030300Sjoergsppp_ncp_check(struct sppp *sp) 256130300Sjoerg{ 256230300Sjoerg int i, mask; 256330300Sjoerg 256430300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 256530300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 256630300Sjoerg return 1; 256730300Sjoerg return 0; 256830300Sjoerg} 256930300Sjoerg 257030300Sjoerg/* 257125944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 257225944Sjoerg * Called by the NCPs during their tlf action handling. 257325944Sjoerg */ 257425944Sjoergstatic void 257530300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 257625944Sjoerg{ 257725944Sjoerg 257830300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 257930300Sjoerg /* don't bother, we are already going down */ 258030300Sjoerg return; 258130300Sjoerg 258230300Sjoerg if (sppp_ncp_check(sp)) 258330300Sjoerg return; 258430300Sjoerg 258525944Sjoerg lcp.Close(sp); 258625944Sjoerg} 258770199Sjhay 258870199Sjhay/* 258925944Sjoerg *--------------------------------------------------------------------------* 259025944Sjoerg * * 259125944Sjoerg * The IPCP implementation. * 259225944Sjoerg * * 259325944Sjoerg *--------------------------------------------------------------------------* 259425944Sjoerg */ 259525944Sjoerg 259625944Sjoergstatic void 259725944Sjoergsppp_ipcp_init(struct sppp *sp) 259825944Sjoerg{ 259925944Sjoerg sp->ipcp.opts = 0; 260025944Sjoerg sp->ipcp.flags = 0; 260125944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 260225944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 260378064Sume sp->pp_seq[IDX_IPCP] = 0; 260478064Sume sp->pp_rseq[IDX_IPCP] = 0; 260542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 260629681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 260740008Sjoerg#endif 260825944Sjoerg} 260925944Sjoerg 261025944Sjoergstatic void 261125944Sjoergsppp_ipcp_up(struct sppp *sp) 261225944Sjoerg{ 261325944Sjoerg sppp_up_event(&ipcp, sp); 261425944Sjoerg} 261525944Sjoerg 261625944Sjoergstatic void 261725944Sjoergsppp_ipcp_down(struct sppp *sp) 261825944Sjoerg{ 261925944Sjoerg sppp_down_event(&ipcp, sp); 262025944Sjoerg} 262125944Sjoerg 262225944Sjoergstatic void 262325944Sjoergsppp_ipcp_open(struct sppp *sp) 262425944Sjoerg{ 262525944Sjoerg STDDCL; 262625944Sjoerg u_long myaddr, hisaddr; 262725944Sjoerg 262842104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 262942104Sphk 263030300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 263125944Sjoerg /* 263225944Sjoerg * If we don't have his address, this probably means our 263325944Sjoerg * interface doesn't want to talk IP at all. (This could 263425944Sjoerg * be the case if somebody wants to speak only IPX, for 263525944Sjoerg * example.) Don't open IPCP in this case. 263625944Sjoerg */ 263725944Sjoerg if (hisaddr == 0L) { 263825944Sjoerg /* XXX this message should go away */ 263925944Sjoerg if (debug) 264040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 264140008Sjoerg SPP_ARGS(ifp)); 264225944Sjoerg return; 264325944Sjoerg } 264425944Sjoerg 264525944Sjoerg if (myaddr == 0L) { 264625944Sjoerg /* 264725944Sjoerg * I don't have an assigned address, so i need to 264825944Sjoerg * negotiate my address. 264925944Sjoerg */ 265025944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 265125944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 265242104Sphk } else 265342104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 265425944Sjoerg sppp_open_event(&ipcp, sp); 265525944Sjoerg} 265625944Sjoerg 265725944Sjoergstatic void 265825944Sjoergsppp_ipcp_close(struct sppp *sp) 265925944Sjoerg{ 266025944Sjoerg sppp_close_event(&ipcp, sp); 266125944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 266225944Sjoerg /* 266325944Sjoerg * My address was dynamic, clear it again. 266425944Sjoerg */ 266525944Sjoerg sppp_set_ip_addr(sp, 0L); 266625944Sjoerg} 266725944Sjoerg 266825944Sjoergstatic void 266925944Sjoergsppp_ipcp_TO(void *cookie) 267025944Sjoerg{ 267125944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 267225944Sjoerg} 267325944Sjoerg 267425944Sjoerg/* 267525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 267625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 267725944Sjoerg * caused action scn. (The return value is used to make the state 267825944Sjoerg * transition decision in the state automaton.) 267925944Sjoerg */ 268025944Sjoergstatic int 268125944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 268225944Sjoerg{ 268325944Sjoerg u_char *buf, *r, *p; 268425944Sjoerg struct ifnet *ifp = &sp->pp_if; 268525944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 268625944Sjoerg u_long hisaddr, desiredaddr; 268742104Sphk int gotmyaddr = 0; 268825944Sjoerg 268925944Sjoerg len -= 4; 269025944Sjoerg origlen = len; 269125944Sjoerg /* 269225944Sjoerg * Make sure to allocate a buf that can at least hold a 269325944Sjoerg * conf-nak with an `address' option. We might need it below. 269425944Sjoerg */ 269525944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 269625944Sjoerg if (! buf) 269725944Sjoerg return (0); 269825944Sjoerg 269925944Sjoerg /* pass 1: see if we can recognize them */ 270025944Sjoerg if (debug) 270140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 270240008Sjoerg SPP_ARGS(ifp)); 270325944Sjoerg p = (void*) (h+1); 270425944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 270525944Sjoerg if (debug) 270669211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 270725944Sjoerg switch (*p) { 270825944Sjoerg case IPCP_OPT_ADDRESS: 270925944Sjoerg if (len >= 6 && p[1] == 6) { 271025944Sjoerg /* correctly formed address option */ 271125944Sjoerg continue; 271225944Sjoerg } 271325706Sjoerg if (debug) 271469211Sphk log(-1, "[invalid] "); 271511189Sjkh break; 271625944Sjoerg default: 271725944Sjoerg /* Others not supported. */ 271825944Sjoerg if (debug) 271969211Sphk log(-1, "[rej] "); 27204910Swollman break; 27214910Swollman } 272225944Sjoerg /* Add the option to rejected list. */ 272325944Sjoerg bcopy (p, r, p[1]); 272425944Sjoerg r += p[1]; 272525944Sjoerg rlen += p[1]; 272625944Sjoerg } 272725944Sjoerg if (rlen) { 272825944Sjoerg if (debug) 272969211Sphk log(-1, " send conf-rej\n"); 273025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 273125944Sjoerg return 0; 273225944Sjoerg } else if (debug) 273369211Sphk log(-1, "\n"); 273425944Sjoerg 273525944Sjoerg /* pass 2: parse option values */ 273630300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 273725944Sjoerg if (debug) 273840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 273940008Sjoerg SPP_ARGS(ifp)); 274025944Sjoerg p = (void*) (h+1); 274125944Sjoerg len = origlen; 274225944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 274325944Sjoerg if (debug) 274469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 274525944Sjoerg switch (*p) { 274625944Sjoerg case IPCP_OPT_ADDRESS: 274742104Sphk /* This is the address he wants in his end */ 274825944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 274925944Sjoerg p[4] << 8 | p[5]; 275033928Sphk if (desiredaddr == hisaddr || 275142104Sphk (hisaddr == 1 && desiredaddr != 0)) { 275225944Sjoerg /* 275325944Sjoerg * Peer's address is same as our value, 275470199Sjhay * or we have set it to 0.0.0.1 to 275533928Sphk * indicate that we do not really care, 275625944Sjoerg * this is agreeable. Gonna conf-ack 275725944Sjoerg * it. 275825944Sjoerg */ 275925944Sjoerg if (debug) 276069211Sphk log(-1, "%s [ack] ", 276142104Sphk sppp_dotted_quad(hisaddr)); 276225944Sjoerg /* record that we've seen it already */ 276325944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 276425944Sjoerg continue; 276525944Sjoerg } 276625944Sjoerg /* 276725944Sjoerg * The address wasn't agreeable. This is either 276825944Sjoerg * he sent us 0.0.0.0, asking to assign him an 276925944Sjoerg * address, or he send us another address not 277025944Sjoerg * matching our value. Either case, we gonna 277125944Sjoerg * conf-nak it with our value. 277242104Sphk * XXX: we should "rej" if hisaddr == 0 277325944Sjoerg */ 277425944Sjoerg if (debug) { 277525944Sjoerg if (desiredaddr == 0) 277669211Sphk log(-1, "[addr requested] "); 277725944Sjoerg else 277869211Sphk log(-1, "%s [not agreed] ", 277942104Sphk sppp_dotted_quad(desiredaddr)); 278025944Sjoerg 278125944Sjoerg } 278244235Sphk p[2] = hisaddr >> 24; 278344235Sphk p[3] = hisaddr >> 16; 278444235Sphk p[4] = hisaddr >> 8; 278544235Sphk p[5] = hisaddr; 278611189Sjkh break; 278725706Sjoerg } 278825944Sjoerg /* Add the option to nak'ed list. */ 278925944Sjoerg bcopy (p, r, p[1]); 279025944Sjoerg r += p[1]; 279125944Sjoerg rlen += p[1]; 279225944Sjoerg } 279325944Sjoerg 279425944Sjoerg /* 279525944Sjoerg * If we are about to conf-ack the request, but haven't seen 279625944Sjoerg * his address so far, gonna conf-nak it instead, with the 279725944Sjoerg * `address' option present and our idea of his address being 279825944Sjoerg * filled in there, to request negotiation of both addresses. 279925944Sjoerg * 280025944Sjoerg * XXX This can result in an endless req - nak loop if peer 280125944Sjoerg * doesn't want to send us his address. Q: What should we do 280225944Sjoerg * about it? XXX A: implement the max-failure counter. 280325944Sjoerg */ 280442104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 280525944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 280625944Sjoerg buf[1] = 6; 280725944Sjoerg buf[2] = hisaddr >> 24; 280825944Sjoerg buf[3] = hisaddr >> 16; 280925944Sjoerg buf[4] = hisaddr >> 8; 281025944Sjoerg buf[5] = hisaddr; 281125944Sjoerg rlen = 6; 281225706Sjoerg if (debug) 281369211Sphk log(-1, "still need hisaddr "); 281425944Sjoerg } 281525944Sjoerg 281625944Sjoerg if (rlen) { 281725706Sjoerg if (debug) 281869211Sphk log(-1, " send conf-nak\n"); 281925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 282025944Sjoerg } else { 282125706Sjoerg if (debug) 282269211Sphk log(-1, " send conf-ack\n"); 282325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 282425944Sjoerg h->ident, origlen, h+1); 282525944Sjoerg } 282625944Sjoerg 282725944Sjoerg free (buf, M_TEMP); 282825944Sjoerg return (rlen == 0); 282925944Sjoerg} 283025944Sjoerg 283125944Sjoerg/* 283225944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 283325944Sjoerg * negotiation. 283425944Sjoerg */ 283525944Sjoergstatic void 283625944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 283725944Sjoerg{ 283825944Sjoerg u_char *buf, *p; 283925944Sjoerg struct ifnet *ifp = &sp->pp_if; 284025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 284125944Sjoerg 284225944Sjoerg len -= 4; 284325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 284425944Sjoerg if (!buf) 284525944Sjoerg return; 284625944Sjoerg 284725944Sjoerg if (debug) 284840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 284940008Sjoerg SPP_ARGS(ifp)); 285025944Sjoerg 285125944Sjoerg p = (void*) (h+1); 285225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 285325706Sjoerg if (debug) 285469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 285525944Sjoerg switch (*p) { 285625944Sjoerg case IPCP_OPT_ADDRESS: 285725944Sjoerg /* 285825944Sjoerg * Peer doesn't grok address option. This is 285925944Sjoerg * bad. XXX Should we better give up here? 286042104Sphk * XXX We could try old "addresses" option... 286125944Sjoerg */ 286225944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 286325944Sjoerg break; 286425944Sjoerg } 28654910Swollman } 286625944Sjoerg if (debug) 286769211Sphk log(-1, "\n"); 286825944Sjoerg free (buf, M_TEMP); 286925944Sjoerg return; 28704910Swollman} 28714910Swollman 287225944Sjoerg/* 287325944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 287425944Sjoerg * negotiation. 287525944Sjoerg */ 287612820Sphkstatic void 287725944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 28784910Swollman{ 287925944Sjoerg u_char *buf, *p; 288025944Sjoerg struct ifnet *ifp = &sp->pp_if; 288125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 288225944Sjoerg u_long wantaddr; 28834910Swollman 288425944Sjoerg len -= 4; 288525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 288625944Sjoerg if (!buf) 288725944Sjoerg return; 288825944Sjoerg 288925944Sjoerg if (debug) 289040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 289140008Sjoerg SPP_ARGS(ifp)); 289225944Sjoerg 289325944Sjoerg p = (void*) (h+1); 289425944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 289525944Sjoerg if (debug) 289669211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 289725944Sjoerg switch (*p) { 289825944Sjoerg case IPCP_OPT_ADDRESS: 289925944Sjoerg /* 290025944Sjoerg * Peer doesn't like our local IP address. See 290125944Sjoerg * if we can do something for him. We'll drop 290225944Sjoerg * him our address then. 290325944Sjoerg */ 290425944Sjoerg if (len >= 6 && p[1] == 6) { 290525944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 290625944Sjoerg p[4] << 8 | p[5]; 290725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 290825944Sjoerg if (debug) 290969211Sphk log(-1, "[wantaddr %s] ", 291030300Sjoerg sppp_dotted_quad(wantaddr)); 291125944Sjoerg /* 291225944Sjoerg * When doing dynamic address assignment, 291325944Sjoerg * we accept his offer. Otherwise, we 291425944Sjoerg * ignore it and thus continue to negotiate 291525944Sjoerg * our already existing value. 291642104Sphk * XXX: Bogus, if he said no once, he'll 291742104Sphk * just say no again, might as well die. 291825944Sjoerg */ 291925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 292025944Sjoerg sppp_set_ip_addr(sp, wantaddr); 292125944Sjoerg if (debug) 292269211Sphk log(-1, "[agree] "); 292342104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 292425944Sjoerg } 292525944Sjoerg } 292625944Sjoerg break; 292725944Sjoerg } 292825944Sjoerg } 292925944Sjoerg if (debug) 293069211Sphk log(-1, "\n"); 293125944Sjoerg free (buf, M_TEMP); 293225944Sjoerg return; 29334910Swollman} 29344910Swollman 293512820Sphkstatic void 293625944Sjoergsppp_ipcp_tlu(struct sppp *sp) 29374910Swollman{ 293842104Sphk /* we are up - notify isdn daemon */ 293942104Sphk if (sp->pp_con) 294042104Sphk sp->pp_con(sp); 29414910Swollman} 29424910Swollman 294325944Sjoergstatic void 294425944Sjoergsppp_ipcp_tld(struct sppp *sp) 294525944Sjoerg{ 294625944Sjoerg} 294725944Sjoerg 294825944Sjoergstatic void 294925944Sjoergsppp_ipcp_tls(struct sppp *sp) 295025944Sjoerg{ 295125944Sjoerg /* indicate to LCP that it must stay alive */ 295225944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 295325944Sjoerg} 295425944Sjoerg 295525944Sjoergstatic void 295625944Sjoergsppp_ipcp_tlf(struct sppp *sp) 295725944Sjoerg{ 295825944Sjoerg /* we no longer need LCP */ 295925944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 296030300Sjoerg sppp_lcp_check_and_close(sp); 296125944Sjoerg} 296225944Sjoerg 296325944Sjoergstatic void 296425944Sjoergsppp_ipcp_scr(struct sppp *sp) 296525944Sjoerg{ 296625944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 296725944Sjoerg u_long ouraddr; 296825944Sjoerg int i = 0; 296925944Sjoerg 297025944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 297130300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 297225944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 297325944Sjoerg opt[i++] = 6; 297425944Sjoerg opt[i++] = ouraddr >> 24; 297525944Sjoerg opt[i++] = ouraddr >> 16; 297625944Sjoerg opt[i++] = ouraddr >> 8; 297725944Sjoerg opt[i++] = ouraddr; 297825944Sjoerg } 297925944Sjoerg 298078064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 298125944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 298225944Sjoerg} 298325944Sjoerg 298470199Sjhay/* 298530300Sjoerg *--------------------------------------------------------------------------* 298630300Sjoerg * * 298778064Sume * The IPv6CP implementation. * 298878064Sume * * 298978064Sume *--------------------------------------------------------------------------* 299078064Sume */ 299178064Sume 299278064Sume#ifdef INET6 299378064Sumestatic void 299478064Sumesppp_ipv6cp_init(struct sppp *sp) 299578064Sume{ 299678064Sume sp->ipv6cp.opts = 0; 299778064Sume sp->ipv6cp.flags = 0; 299878064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 299978064Sume sp->fail_counter[IDX_IPV6CP] = 0; 300078064Sume sp->pp_seq[IDX_IPV6CP] = 0; 300178064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 300278064Sume#if defined(__NetBSD__) 300378064Sume callout_init(&sp->ch[IDX_IPV6CP]); 300478064Sume#endif 300578064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 300678064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 300778064Sume#endif 300878064Sume} 300978064Sume 301078064Sumestatic void 301178064Sumesppp_ipv6cp_up(struct sppp *sp) 301278064Sume{ 301378064Sume sppp_up_event(&ipv6cp, sp); 301478064Sume} 301578064Sume 301678064Sumestatic void 301778064Sumesppp_ipv6cp_down(struct sppp *sp) 301878064Sume{ 301978064Sume sppp_down_event(&ipv6cp, sp); 302078064Sume} 302178064Sume 302278064Sumestatic void 302378064Sumesppp_ipv6cp_open(struct sppp *sp) 302478064Sume{ 302578064Sume STDDCL; 302678064Sume struct in6_addr myaddr, hisaddr; 302778064Sume 302878064Sume#ifdef IPV6CP_MYIFID_DYN 302978064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 303078064Sume#else 303178064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 303278064Sume#endif 303378064Sume 303478064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 303578064Sume /* 303678064Sume * If we don't have our address, this probably means our 303778064Sume * interface doesn't want to talk IPv6 at all. (This could 303878064Sume * be the case if somebody wants to speak only IPX, for 303978064Sume * example.) Don't open IPv6CP in this case. 304078064Sume */ 304178064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 304278064Sume /* XXX this message should go away */ 304378064Sume if (debug) 304478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 304578064Sume SPP_ARGS(ifp)); 304678064Sume return; 304778064Sume } 304878064Sume 304978064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 305078064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 305178064Sume sppp_open_event(&ipv6cp, sp); 305278064Sume} 305378064Sume 305478064Sumestatic void 305578064Sumesppp_ipv6cp_close(struct sppp *sp) 305678064Sume{ 305778064Sume sppp_close_event(&ipv6cp, sp); 305878064Sume} 305978064Sume 306078064Sumestatic void 306178064Sumesppp_ipv6cp_TO(void *cookie) 306278064Sume{ 306378064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 306478064Sume} 306578064Sume 306678064Sume/* 306778064Sume * Analyze a configure request. Return true if it was agreeable, and 306878064Sume * caused action sca, false if it has been rejected or nak'ed, and 306978064Sume * caused action scn. (The return value is used to make the state 307078064Sume * transition decision in the state automaton.) 307178064Sume */ 307278064Sumestatic int 307378064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 307478064Sume{ 307578064Sume u_char *buf, *r, *p; 307678064Sume struct ifnet *ifp = &sp->pp_if; 307778064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 307878064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 307978064Sume int ifidcount; 308078064Sume int type; 308178064Sume int collision, nohisaddr; 308278064Sume 308378064Sume len -= 4; 308478064Sume origlen = len; 308578064Sume /* 308678064Sume * Make sure to allocate a buf that can at least hold a 308778064Sume * conf-nak with an `address' option. We might need it below. 308878064Sume */ 308978064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 309078064Sume if (! buf) 309178064Sume return (0); 309278064Sume 309378064Sume /* pass 1: see if we can recognize them */ 309478064Sume if (debug) 309578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 309678064Sume SPP_ARGS(ifp)); 309778064Sume p = (void*) (h+1); 309878064Sume ifidcount = 0; 309978064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 310078064Sume if (debug) 310178064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 310278064Sume switch (*p) { 310378064Sume case IPV6CP_OPT_IFID: 310478064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 310578064Sume /* correctly formed address option */ 310678064Sume ifidcount++; 310778064Sume continue; 310878064Sume } 310978064Sume if (debug) 311078064Sume addlog(" [invalid]"); 311178064Sume break; 311278064Sume#ifdef notyet 311378064Sume case IPV6CP_OPT_COMPRESSION: 311478064Sume if (len >= 4 && p[1] >= 4) { 311578064Sume /* correctly formed compress option */ 311678064Sume continue; 311778064Sume } 311878064Sume if (debug) 311978064Sume addlog(" [invalid]"); 312078064Sume break; 312178064Sume#endif 312278064Sume default: 312378064Sume /* Others not supported. */ 312478064Sume if (debug) 312578064Sume addlog(" [rej]"); 312678064Sume break; 312778064Sume } 312878064Sume /* Add the option to rejected list. */ 312978064Sume bcopy (p, r, p[1]); 313078064Sume r += p[1]; 313178064Sume rlen += p[1]; 313278064Sume } 313378064Sume if (rlen) { 313478064Sume if (debug) 313578064Sume addlog(" send conf-rej\n"); 313678064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 313778064Sume goto end; 313878064Sume } else if (debug) 313978064Sume addlog("\n"); 314078064Sume 314178064Sume /* pass 2: parse option values */ 314278064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 314378064Sume if (debug) 314478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 314578064Sume SPP_ARGS(ifp)); 314678064Sume p = (void*) (h+1); 314778064Sume len = origlen; 314878064Sume type = CONF_ACK; 314978064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 315078064Sume if (debug) 315178064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 315278064Sume switch (*p) { 315378064Sume#ifdef notyet 315478064Sume case IPV6CP_OPT_COMPRESSION: 315578064Sume continue; 315678064Sume#endif 315778064Sume case IPV6CP_OPT_IFID: 315878064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 315978064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 316078064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 316178064Sume &myaddr.s6_addr[8], 8) == 0); 316278064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 316378064Sume 316478064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 316578064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 316678064Sume 316778064Sume if (!collision && !nohisaddr) { 316878064Sume /* no collision, hisaddr known - Conf-Ack */ 316978064Sume type = CONF_ACK; 317078064Sume 317178064Sume if (debug) { 317278064Sume addlog(" %s [%s]", 317378064Sume ip6_sprintf(&desiredaddr), 317478064Sume sppp_cp_type_name(type)); 317578064Sume } 317678064Sume continue; 317778064Sume } 317878064Sume 317978064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 318078064Sume if (collision && nohisaddr) { 318178064Sume /* collision, hisaddr unknown - Conf-Rej */ 318278064Sume type = CONF_REJ; 318378064Sume bzero(&p[2], 8); 318478064Sume } else { 318578064Sume /* 318678064Sume * - no collision, hisaddr unknown, or 318778064Sume * - collision, hisaddr known 318878064Sume * Conf-Nak, suggest hisaddr 318978064Sume */ 319078064Sume type = CONF_NAK; 319178064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 319278064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 319378064Sume } 319478064Sume if (debug) 319578064Sume addlog(" %s [%s]", ip6_sprintf(&desiredaddr), 319678064Sume sppp_cp_type_name(type)); 319778064Sume break; 319878064Sume } 319978064Sume /* Add the option to nak'ed list. */ 320078064Sume bcopy (p, r, p[1]); 320178064Sume r += p[1]; 320278064Sume rlen += p[1]; 320378064Sume } 320478064Sume 320578064Sume if (rlen == 0 && type == CONF_ACK) { 320678064Sume if (debug) 320778064Sume addlog(" send %s\n", sppp_cp_type_name(type)); 320878064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 320978064Sume } else { 321078064Sume#ifdef DIAGNOSTIC 321178064Sume if (type == CONF_ACK) 321278064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 321378064Sume#endif 321478064Sume 321578064Sume if (debug) { 321678064Sume addlog(" send %s suggest %s\n", 321778064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 321878064Sume } 321978064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 322078064Sume } 322178064Sume 322278064Sume end: 322378064Sume free (buf, M_TEMP); 322478064Sume return (rlen == 0); 322578064Sume} 322678064Sume 322778064Sume/* 322878064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 322978064Sume * negotiation. 323078064Sume */ 323178064Sumestatic void 323278064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 323378064Sume{ 323478064Sume u_char *buf, *p; 323578064Sume struct ifnet *ifp = &sp->pp_if; 323678064Sume int debug = ifp->if_flags & IFF_DEBUG; 323778064Sume 323878064Sume len -= 4; 323978064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 324078064Sume if (!buf) 324178064Sume return; 324278064Sume 324378064Sume if (debug) 324478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 324578064Sume SPP_ARGS(ifp)); 324678064Sume 324778064Sume p = (void*) (h+1); 324878064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 324978064Sume if (debug) 325078064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 325178064Sume switch (*p) { 325278064Sume case IPV6CP_OPT_IFID: 325378064Sume /* 325478064Sume * Peer doesn't grok address option. This is 325578064Sume * bad. XXX Should we better give up here? 325678064Sume */ 325778064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 325878064Sume break; 325978064Sume#ifdef notyet 326078064Sume case IPV6CP_OPT_COMPRESS: 326178064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 326278064Sume break; 326378064Sume#endif 326478064Sume } 326578064Sume } 326678064Sume if (debug) 326778064Sume addlog("\n"); 326878064Sume free (buf, M_TEMP); 326978064Sume return; 327078064Sume} 327178064Sume 327278064Sume/* 327378064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 327478064Sume * negotiation. 327578064Sume */ 327678064Sumestatic void 327778064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 327878064Sume{ 327978064Sume u_char *buf, *p; 328078064Sume struct ifnet *ifp = &sp->pp_if; 328178064Sume int debug = ifp->if_flags & IFF_DEBUG; 328278064Sume struct in6_addr suggestaddr; 328378064Sume 328478064Sume len -= 4; 328578064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 328678064Sume if (!buf) 328778064Sume return; 328878064Sume 328978064Sume if (debug) 329078064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 329178064Sume SPP_ARGS(ifp)); 329278064Sume 329378064Sume p = (void*) (h+1); 329478064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 329578064Sume if (debug) 329678064Sume addlog(" %s", sppp_ipv6cp_opt_name(*p)); 329778064Sume switch (*p) { 329878064Sume case IPV6CP_OPT_IFID: 329978064Sume /* 330078064Sume * Peer doesn't like our local ifid. See 330178064Sume * if we can do something for him. We'll drop 330278064Sume * him our address then. 330378064Sume */ 330478064Sume if (len < 10 || p[1] != 10) 330578064Sume break; 330678064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 330778064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 330878064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 330978064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 331078064Sume 331178064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 331278064Sume if (debug) 331378064Sume addlog(" [suggestaddr %s]", 331478064Sume ip6_sprintf(&suggestaddr)); 331578064Sume#ifdef IPV6CP_MYIFID_DYN 331678064Sume /* 331778064Sume * When doing dynamic address assignment, 331878064Sume * we accept his offer. 331978064Sume */ 332078064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 332178064Sume struct in6_addr lastsuggest; 332278064Sume /* 332378064Sume * If <suggested myaddr from peer> equals to 332478064Sume * <hisaddr we have suggested last time>, 332578064Sume * we have a collision. generate new random 332678064Sume * ifid. 332778064Sume */ 332878064Sume sppp_suggest_ip6_addr(&lastsuggest); 332978064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 333078064Sume lastsuggest)) { 333178064Sume if (debug) 333278064Sume addlog(" [random]"); 333378064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 333478064Sume } 333578064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 333678064Sume if (debug) 333778064Sume addlog(" [agree]"); 333878064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 333978064Sume } 334078064Sume#else 334178064Sume /* 334278064Sume * Since we do not do dynamic address assignment, 334378064Sume * we ignore it and thus continue to negotiate 334478064Sume * our already existing value. This can possibly 334578064Sume * go into infinite request-reject loop. 334678064Sume * 334778064Sume * This is not likely because we normally use 334878064Sume * ifid based on MAC-address. 334978064Sume * If you have no ethernet card on the node, too bad. 335078064Sume * XXX should we use fail_counter? 335178064Sume */ 335278064Sume#endif 335378064Sume break; 335478064Sume#ifdef notyet 335578064Sume case IPV6CP_OPT_COMPRESS: 335678064Sume /* 335778064Sume * Peer wants different compression parameters. 335878064Sume */ 335978064Sume break; 336078064Sume#endif 336178064Sume } 336278064Sume } 336378064Sume if (debug) 336478064Sume addlog("\n"); 336578064Sume free (buf, M_TEMP); 336678064Sume return; 336778064Sume} 336878064Sumestatic void 336978064Sumesppp_ipv6cp_tlu(struct sppp *sp) 337078064Sume{ 337178064Sume /* we are up - notify isdn daemon */ 337278064Sume if (sp->pp_con) 337378064Sume sp->pp_con(sp); 337478064Sume} 337578064Sume 337678064Sumestatic void 337778064Sumesppp_ipv6cp_tld(struct sppp *sp) 337878064Sume{ 337978064Sume} 338078064Sume 338178064Sumestatic void 338278064Sumesppp_ipv6cp_tls(struct sppp *sp) 338378064Sume{ 338478064Sume /* indicate to LCP that it must stay alive */ 338578064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 338678064Sume} 338778064Sume 338878064Sumestatic void 338978064Sumesppp_ipv6cp_tlf(struct sppp *sp) 339078064Sume{ 339178064Sume 339278064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 339378064Sume /* we no longer need LCP */ 339478064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 339578064Sume sppp_lcp_check_and_close(sp); 339678064Sume#endif 339778064Sume} 339878064Sume 339978064Sumestatic void 340078064Sumesppp_ipv6cp_scr(struct sppp *sp) 340178064Sume{ 340278064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 340378064Sume struct in6_addr ouraddr; 340478064Sume int i = 0; 340578064Sume 340678064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 340778064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 340878064Sume opt[i++] = IPV6CP_OPT_IFID; 340978064Sume opt[i++] = 10; 341078064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 341178064Sume i += 8; 341278064Sume } 341378064Sume 341478064Sume#ifdef notyet 341578064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 341678064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 341778064Sume opt[i++] = 4; 341878064Sume opt[i++] = 0; /* TBD */ 341978064Sume opt[i++] = 0; /* TBD */ 342078064Sume /* variable length data may follow */ 342178064Sume } 342278064Sume#endif 342378064Sume 342478064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 342578064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 342678064Sume} 342778064Sume#else /*INET6*/ 342878064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 342978064Sume{ 343078064Sume} 343178064Sume 343278064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 343378064Sume{ 343478064Sume} 343578064Sume 343678064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 343778064Sume{ 343878064Sume} 343978064Sume 344078064Sume 344178064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 344278064Sume{ 344378064Sume} 344478064Sume 344578064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 344678064Sume{ 344778064Sume} 344878064Sume 344978064Sumestatic void sppp_ipv6cp_TO(void *sp) 345078064Sume{ 345178064Sume} 345278064Sume 345378064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 345478064Sume{ 345578064Sume return 0; 345678064Sume} 345778064Sume 345878064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 345978064Sume{ 346078064Sume} 346178064Sume 346278064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 346378064Sume{ 346478064Sume} 346578064Sume 346678064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 346778064Sume{ 346878064Sume} 346978064Sume 347078064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 347178064Sume{ 347278064Sume} 347378064Sume 347478064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 347578064Sume{ 347678064Sume} 347778064Sume 347878064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 347978064Sume{ 348078064Sume} 348178064Sume 348278064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 348378064Sume{ 348478064Sume} 348578064Sume#endif /*INET6*/ 348678064Sume 348778064Sume/* 348878064Sume *--------------------------------------------------------------------------* 348978064Sume * * 349030300Sjoerg * The CHAP implementation. * 349130300Sjoerg * * 349230300Sjoerg *--------------------------------------------------------------------------* 349330300Sjoerg */ 349430300Sjoerg 349530300Sjoerg/* 349630300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 349730300Sjoerg * the control protocols do, since they do have Open and Close events, but 349830300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 349930300Sjoerg * authentication protocols may be different in both directions (this makes 350030300Sjoerg * sense, think of a machine that never accepts incoming calls but only 350130300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 350230300Sjoerg * 350330300Sjoerg * Our state machine for the local authentication protocol (we are requesting 350430300Sjoerg * the peer to authenticate) looks like: 350530300Sjoerg * 350630300Sjoerg * RCA- 350730300Sjoerg * +--------------------------------------------+ 350830300Sjoerg * V scn,tld| 350930300Sjoerg * +--------+ Close +---------+ RCA+ 351030300Sjoerg * | |<----------------------------------| |------+ 351130300Sjoerg * +--->| Closed | TO* | Opened | sca | 351230300Sjoerg * | | |-----+ +-------| |<-----+ 351330300Sjoerg * | +--------+ irc | | +---------+ 351430300Sjoerg * | ^ | | ^ 351530300Sjoerg * | | | | | 351630300Sjoerg * | | | | | 351730300Sjoerg * | TO-| | | | 351830300Sjoerg * | |tld TO+ V | | 351930300Sjoerg * | | +------->+ | | 352030300Sjoerg * | | | | | | 352130300Sjoerg * | +--------+ V | | 352230300Sjoerg * | | |<----+<--------------------+ | 352330300Sjoerg * | | Req- | scr | 352430300Sjoerg * | | Sent | | 352530300Sjoerg * | | | | 352630300Sjoerg * | +--------+ | 352730300Sjoerg * | RCA- | | RCA+ | 352830300Sjoerg * +------+ +------------------------------------------+ 352930300Sjoerg * scn,tld sca,irc,ict,tlu 353030300Sjoerg * 353130300Sjoerg * 353230300Sjoerg * with: 353330300Sjoerg * 353430300Sjoerg * Open: LCP reached authentication phase 353530300Sjoerg * Close: LCP reached terminate phase 353630300Sjoerg * 353730300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 353830300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 353930300Sjoerg * TO+: timeout with restart counter >= 0 354030300Sjoerg * TO-: timeout with restart counter < 0 354130300Sjoerg * TO*: reschedule timeout for CHAP 354230300Sjoerg * 354330300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 354430300Sjoerg * sca: send ack packet (pap-ack, chap-success) 354530300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 354630300Sjoerg * ict: initialize re-challenge timer (CHAP only) 354730300Sjoerg * 354830300Sjoerg * tlu: this-layer-up, LCP reaches network phase 354930300Sjoerg * tld: this-layer-down, LCP enters terminate phase 355030300Sjoerg * 355130300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 355230300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 355330300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 355430300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 355530300Sjoerg * causing LCP to enter terminate phase. 355630300Sjoerg * 355730300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 355830300Sjoerg * expected to send one based on the successful negotiation of PAP as 355930300Sjoerg * the authentication protocol during the LCP option negotiation. 356030300Sjoerg * 356130300Sjoerg * Incoming authentication protocol requests (remote requests 356230300Sjoerg * authentication, we are peer) don't employ a state machine at all, 356330300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 356430300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 356530300Sjoerg * still in authentication phase (thereby violating the standard that 356630300Sjoerg * demands that these NCP packets are to be discarded), so we keep 356730300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 356830300Sjoerg * phase network once we've seen a positive acknowledge for the 356930300Sjoerg * authentication. 357030300Sjoerg */ 357130300Sjoerg 357230300Sjoerg/* 357330300Sjoerg * Handle incoming CHAP packets. 357430300Sjoerg */ 357530300Sjoergvoid 357630300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 357730300Sjoerg{ 357830300Sjoerg STDDCL; 357930300Sjoerg struct lcp_header *h; 358030300Sjoerg int len, x; 358130300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 358230300Sjoerg int value_len, name_len; 358330300Sjoerg MD5_CTX ctx; 358430300Sjoerg 358530300Sjoerg len = m->m_pkthdr.len; 358630300Sjoerg if (len < 4) { 358730300Sjoerg if (debug) 358830300Sjoerg log(LOG_DEBUG, 358940008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 359040008Sjoerg SPP_ARGS(ifp), len); 359130300Sjoerg return; 359230300Sjoerg } 359330300Sjoerg h = mtod (m, struct lcp_header*); 359430300Sjoerg if (len > ntohs (h->len)) 359530300Sjoerg len = ntohs (h->len); 359630300Sjoerg 359730300Sjoerg switch (h->type) { 359830300Sjoerg /* challenge, failure and success are his authproto */ 359930300Sjoerg case CHAP_CHALLENGE: 360030300Sjoerg value = 1 + (u_char*)(h+1); 360130300Sjoerg value_len = value[-1]; 360230300Sjoerg name = value + value_len; 360330300Sjoerg name_len = len - value_len - 5; 360430300Sjoerg if (name_len < 0) { 360530300Sjoerg if (debug) { 360630300Sjoerg log(LOG_DEBUG, 360740008Sjoerg SPP_FMT "chap corrupted challenge " 360830300Sjoerg "<%s id=0x%x len=%d", 360940008Sjoerg SPP_ARGS(ifp), 361030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 361130300Sjoerg h->ident, ntohs(h->len)); 361244145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 361369211Sphk log(-1, ">\n"); 361430300Sjoerg } 361530300Sjoerg break; 361630300Sjoerg } 361770199Sjhay 361830300Sjoerg if (debug) { 361930300Sjoerg log(LOG_DEBUG, 362040008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 362140008Sjoerg SPP_ARGS(ifp), 362230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 362330300Sjoerg ntohs(h->len)); 362430300Sjoerg sppp_print_string((char*) name, name_len); 362569211Sphk log(-1, " value-size=%d value=", value_len); 362630300Sjoerg sppp_print_bytes(value, value_len); 362769211Sphk log(-1, ">\n"); 362830300Sjoerg } 362930300Sjoerg 363030300Sjoerg /* Compute reply value. */ 363130300Sjoerg MD5Init(&ctx); 363230300Sjoerg MD5Update(&ctx, &h->ident, 1); 363330300Sjoerg MD5Update(&ctx, sp->myauth.secret, 363430300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 363530300Sjoerg MD5Update(&ctx, value, value_len); 363630300Sjoerg MD5Final(digest, &ctx); 363730300Sjoerg dsize = sizeof digest; 363830300Sjoerg 363930300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 364030300Sjoerg sizeof dsize, (const char *)&dsize, 364130300Sjoerg sizeof digest, digest, 364240008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 364330300Sjoerg sp->myauth.name, 364430300Sjoerg 0); 364530300Sjoerg break; 364630300Sjoerg 364730300Sjoerg case CHAP_SUCCESS: 364830300Sjoerg if (debug) { 364940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 365040008Sjoerg SPP_ARGS(ifp)); 365130300Sjoerg if (len > 4) { 365269211Sphk log(-1, ": "); 365330300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 365430300Sjoerg } 365569211Sphk log(-1, "\n"); 365630300Sjoerg } 365730300Sjoerg x = splimp(); 365830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 365930300Sjoerg if (sp->myauth.proto == PPP_CHAP && 366032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 366130300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 366230300Sjoerg /* 366330300Sjoerg * We are authenticator for CHAP but didn't 366430300Sjoerg * complete yet. Leave it to tlu to proceed 366530300Sjoerg * to network phase. 366630300Sjoerg */ 366730300Sjoerg splx(x); 366830300Sjoerg break; 366930300Sjoerg } 367030300Sjoerg splx(x); 367130300Sjoerg sppp_phase_network(sp); 367230300Sjoerg break; 367330300Sjoerg 367430300Sjoerg case CHAP_FAILURE: 367530300Sjoerg if (debug) { 367640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 367740008Sjoerg SPP_ARGS(ifp)); 367830300Sjoerg if (len > 4) { 367969211Sphk log(-1, ": "); 368030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 368130300Sjoerg } 368269211Sphk log(-1, "\n"); 368330300Sjoerg } else 368440008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 368540008Sjoerg SPP_ARGS(ifp)); 368630300Sjoerg /* await LCP shutdown by authenticator */ 368730300Sjoerg break; 368830300Sjoerg 368930300Sjoerg /* response is my authproto */ 369030300Sjoerg case CHAP_RESPONSE: 369130300Sjoerg value = 1 + (u_char*)(h+1); 369230300Sjoerg value_len = value[-1]; 369330300Sjoerg name = value + value_len; 369430300Sjoerg name_len = len - value_len - 5; 369530300Sjoerg if (name_len < 0) { 369630300Sjoerg if (debug) { 369730300Sjoerg log(LOG_DEBUG, 369840008Sjoerg SPP_FMT "chap corrupted response " 369930300Sjoerg "<%s id=0x%x len=%d", 370040008Sjoerg SPP_ARGS(ifp), 370130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 370230300Sjoerg h->ident, ntohs(h->len)); 370344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 370469211Sphk log(-1, ">\n"); 370530300Sjoerg } 370630300Sjoerg break; 370730300Sjoerg } 370830300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 370930300Sjoerg if (debug) 371030300Sjoerg log(LOG_DEBUG, 371140008Sjoerg SPP_FMT "chap dropping response for old ID " 371230300Sjoerg "(got %d, expected %d)\n", 371340008Sjoerg SPP_ARGS(ifp), 371430300Sjoerg h->ident, sp->confid[IDX_CHAP]); 371530300Sjoerg break; 371630300Sjoerg } 371730300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 371830300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 371940008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 372040008Sjoerg SPP_ARGS(ifp)); 372130300Sjoerg sppp_print_string(name, name_len); 372269211Sphk log(-1, " != expected "); 372330300Sjoerg sppp_print_string(sp->hisauth.name, 372430300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 372569211Sphk log(-1, "\n"); 372670199Sjhay } 372730300Sjoerg if (debug) { 372840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 372930300Sjoerg "<%s id=0x%x len=%d name=", 373040008Sjoerg SPP_ARGS(ifp), 373130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 373230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 373330300Sjoerg h->ident, ntohs (h->len)); 373430300Sjoerg sppp_print_string((char*)name, name_len); 373569211Sphk log(-1, " value-size=%d value=", value_len); 373630300Sjoerg sppp_print_bytes(value, value_len); 373769211Sphk log(-1, ">\n"); 373830300Sjoerg } 373930300Sjoerg if (value_len != AUTHKEYLEN) { 374030300Sjoerg if (debug) 374130300Sjoerg log(LOG_DEBUG, 374240008Sjoerg SPP_FMT "chap bad hash value length: " 374330300Sjoerg "%d bytes, should be %d\n", 374440008Sjoerg SPP_ARGS(ifp), value_len, 374530300Sjoerg AUTHKEYLEN); 374630300Sjoerg break; 374730300Sjoerg } 374830300Sjoerg 374930300Sjoerg MD5Init(&ctx); 375030300Sjoerg MD5Update(&ctx, &h->ident, 1); 375130300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 375230300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 375330300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 375430300Sjoerg MD5Final(digest, &ctx); 375530300Sjoerg 375630300Sjoerg#define FAILMSG "Failed..." 375730300Sjoerg#define SUCCMSG "Welcome!" 375830300Sjoerg 375930300Sjoerg if (value_len != sizeof digest || 376030300Sjoerg bcmp(digest, value, value_len) != 0) { 376130300Sjoerg /* action scn, tld */ 376230300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 376330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 376430300Sjoerg 0); 376530300Sjoerg chap.tld(sp); 376630300Sjoerg break; 376730300Sjoerg } 376830300Sjoerg /* action sca, perhaps tlu */ 376930300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 377030300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 377130300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 377230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 377330300Sjoerg 0); 377430300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 377530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 377630300Sjoerg chap.tlu(sp); 377730300Sjoerg } 377830300Sjoerg break; 377930300Sjoerg 378030300Sjoerg default: 378130300Sjoerg /* Unknown CHAP packet type -- ignore. */ 378230300Sjoerg if (debug) { 378340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 378430300Sjoerg "<0x%x id=0x%xh len=%d", 378540008Sjoerg SPP_ARGS(ifp), 378630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 378730300Sjoerg h->type, h->ident, ntohs(h->len)); 378844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 378969211Sphk log(-1, ">\n"); 379030300Sjoerg } 379130300Sjoerg break; 379230300Sjoerg 379330300Sjoerg } 379430300Sjoerg} 379530300Sjoerg 379630300Sjoergstatic void 379730300Sjoergsppp_chap_init(struct sppp *sp) 379830300Sjoerg{ 379930300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 380030300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 380130300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 380278064Sume sp->pp_seq[IDX_CHAP] = 0; 380378064Sume sp->pp_rseq[IDX_CHAP] = 0; 380442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 380530300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 380640008Sjoerg#endif 380730300Sjoerg} 380830300Sjoerg 380930300Sjoergstatic void 381030300Sjoergsppp_chap_open(struct sppp *sp) 381130300Sjoerg{ 381230300Sjoerg if (sp->myauth.proto == PPP_CHAP && 381330300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 381430300Sjoerg /* we are authenticator for CHAP, start it */ 381530300Sjoerg chap.scr(sp); 381630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 381730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 381830300Sjoerg } 381930300Sjoerg /* nothing to be done if we are peer, await a challenge */ 382030300Sjoerg} 382130300Sjoerg 382230300Sjoergstatic void 382330300Sjoergsppp_chap_close(struct sppp *sp) 382430300Sjoerg{ 382530300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 382630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 382730300Sjoerg} 382830300Sjoerg 382930300Sjoergstatic void 383030300Sjoergsppp_chap_TO(void *cookie) 383130300Sjoerg{ 383230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 383330300Sjoerg STDDCL; 383430300Sjoerg int s; 383530300Sjoerg 383630300Sjoerg s = splimp(); 383730300Sjoerg if (debug) 383840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 383940008Sjoerg SPP_ARGS(ifp), 384030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 384130300Sjoerg sp->rst_counter[IDX_CHAP]); 384230300Sjoerg 384330300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 384430300Sjoerg /* TO- event */ 384530300Sjoerg switch (sp->state[IDX_CHAP]) { 384630300Sjoerg case STATE_REQ_SENT: 384730300Sjoerg chap.tld(sp); 384830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 384930300Sjoerg break; 385030300Sjoerg } 385130300Sjoerg else 385230300Sjoerg /* TO+ (or TO*) event */ 385330300Sjoerg switch (sp->state[IDX_CHAP]) { 385430300Sjoerg case STATE_OPENED: 385530300Sjoerg /* TO* event */ 385630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 385730300Sjoerg /* fall through */ 385830300Sjoerg case STATE_REQ_SENT: 385930300Sjoerg chap.scr(sp); 386030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 386130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 386230300Sjoerg break; 386330300Sjoerg } 386430300Sjoerg 386530300Sjoerg splx(s); 386630300Sjoerg} 386730300Sjoerg 386830300Sjoergstatic void 386930300Sjoergsppp_chap_tlu(struct sppp *sp) 387030300Sjoerg{ 387130300Sjoerg STDDCL; 387230300Sjoerg int i, x; 387330300Sjoerg 387440010Sjoerg i = 0; 387530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 387630300Sjoerg 387730300Sjoerg /* 387830300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 387930300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 388030300Sjoerg * initial challenge-response exchange has taken place. 388130300Sjoerg * Provide for an option to avoid rechallenges. 388230300Sjoerg */ 388330300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 388430300Sjoerg /* 388530300Sjoerg * Compute the re-challenge timeout. This will yield 388630300Sjoerg * a number between 300 and 810 seconds. 388730300Sjoerg */ 388830300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 388942064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 389030300Sjoerg } 389130300Sjoerg 389230300Sjoerg if (debug) { 389330300Sjoerg log(LOG_DEBUG, 389440008Sjoerg SPP_FMT "chap %s, ", 389540008Sjoerg SPP_ARGS(ifp), 389630300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 389730300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 389869211Sphk log(-1, "next re-challenge in %d seconds\n", i); 389930300Sjoerg else 390069211Sphk log(-1, "re-challenging supressed\n"); 390130300Sjoerg } 390230300Sjoerg 390330300Sjoerg x = splimp(); 390430300Sjoerg /* indicate to LCP that we need to be closed down */ 390530300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 390630300Sjoerg 390730300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 390830300Sjoerg /* 390930300Sjoerg * Remote is authenticator, but his auth proto didn't 391030300Sjoerg * complete yet. Defer the transition to network 391130300Sjoerg * phase. 391230300Sjoerg */ 391330300Sjoerg splx(x); 391430300Sjoerg return; 391530300Sjoerg } 391630300Sjoerg splx(x); 391730300Sjoerg 391830300Sjoerg /* 391930300Sjoerg * If we are already in phase network, we are done here. This 392030300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 392130300Sjoerg */ 392230300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 392330300Sjoerg sppp_phase_network(sp); 392430300Sjoerg} 392530300Sjoerg 392630300Sjoergstatic void 392730300Sjoergsppp_chap_tld(struct sppp *sp) 392830300Sjoerg{ 392930300Sjoerg STDDCL; 393030300Sjoerg 393130300Sjoerg if (debug) 393240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 393340008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 393430300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 393530300Sjoerg 393630300Sjoerg lcp.Close(sp); 393730300Sjoerg} 393830300Sjoerg 393930300Sjoergstatic void 394030300Sjoergsppp_chap_scr(struct sppp *sp) 394130300Sjoerg{ 394230300Sjoerg u_long *ch, seed; 394330300Sjoerg u_char clen; 394430300Sjoerg 394530300Sjoerg /* Compute random challenge. */ 394630300Sjoerg ch = (u_long *)sp->myauth.challenge; 394742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 394835064Sphk read_random(&seed, sizeof seed); 394940008Sjoerg#else 395042104Sphk { 395142104Sphk struct timeval tv; 395240008Sjoerg microtime(&tv); 395340008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 395442104Sphk } 395540008Sjoerg#endif 395630300Sjoerg ch[0] = seed ^ random(); 395730300Sjoerg ch[1] = seed ^ random(); 395830300Sjoerg ch[2] = seed ^ random(); 395930300Sjoerg ch[3] = seed ^ random(); 396030300Sjoerg clen = AUTHKEYLEN; 396130300Sjoerg 396278064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 396330300Sjoerg 396430300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 396530300Sjoerg sizeof clen, (const char *)&clen, 396640008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 396740008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 396830300Sjoerg sp->myauth.name, 396930300Sjoerg 0); 397030300Sjoerg} 397170199Sjhay 397270199Sjhay/* 397330300Sjoerg *--------------------------------------------------------------------------* 397430300Sjoerg * * 397530300Sjoerg * The PAP implementation. * 397630300Sjoerg * * 397730300Sjoerg *--------------------------------------------------------------------------* 397830300Sjoerg */ 397930300Sjoerg/* 398030300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 398130300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 398230300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 398330300Sjoerg * retry counter is expired). 398430300Sjoerg */ 398530300Sjoerg 398630300Sjoerg/* 398730300Sjoerg * Handle incoming PAP packets. */ 398830300Sjoergstatic void 398930300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 399030300Sjoerg{ 399130300Sjoerg STDDCL; 399230300Sjoerg struct lcp_header *h; 399330300Sjoerg int len, x; 399430300Sjoerg u_char *name, *passwd, mlen; 399530300Sjoerg int name_len, passwd_len; 399630300Sjoerg 399730300Sjoerg len = m->m_pkthdr.len; 399830300Sjoerg if (len < 5) { 399930300Sjoerg if (debug) 400030300Sjoerg log(LOG_DEBUG, 400140008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 400240008Sjoerg SPP_ARGS(ifp), len); 400330300Sjoerg return; 400430300Sjoerg } 400530300Sjoerg h = mtod (m, struct lcp_header*); 400630300Sjoerg if (len > ntohs (h->len)) 400730300Sjoerg len = ntohs (h->len); 400830300Sjoerg switch (h->type) { 400930300Sjoerg /* PAP request is my authproto */ 401030300Sjoerg case PAP_REQ: 401130300Sjoerg name = 1 + (u_char*)(h+1); 401230300Sjoerg name_len = name[-1]; 401330300Sjoerg passwd = name + name_len + 1; 401430300Sjoerg if (name_len > len - 6 || 401530300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 401630300Sjoerg if (debug) { 401740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 401830300Sjoerg "<%s id=0x%x len=%d", 401940008Sjoerg SPP_ARGS(ifp), 402030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 402130300Sjoerg h->ident, ntohs(h->len)); 402244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 402369211Sphk log(-1, ">\n"); 402430300Sjoerg } 402530300Sjoerg break; 402630300Sjoerg } 402730300Sjoerg if (debug) { 402840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 402930300Sjoerg "<%s id=0x%x len=%d name=", 403040008Sjoerg SPP_ARGS(ifp), 403130300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 403230300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 403330300Sjoerg h->ident, ntohs(h->len)); 403430300Sjoerg sppp_print_string((char*)name, name_len); 403569211Sphk log(-1, " passwd="); 403630300Sjoerg sppp_print_string((char*)passwd, passwd_len); 403769211Sphk log(-1, ">\n"); 403830300Sjoerg } 403974774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 404074774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 404130300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 404230300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 404330300Sjoerg /* action scn, tld */ 404430300Sjoerg mlen = sizeof(FAILMSG) - 1; 404530300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 404630300Sjoerg sizeof mlen, (const char *)&mlen, 404730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 404830300Sjoerg 0); 404930300Sjoerg pap.tld(sp); 405030300Sjoerg break; 405130300Sjoerg } 405230300Sjoerg /* action sca, perhaps tlu */ 405330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 405430300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 405530300Sjoerg mlen = sizeof(SUCCMSG) - 1; 405630300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 405730300Sjoerg sizeof mlen, (const char *)&mlen, 405830300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 405930300Sjoerg 0); 406030300Sjoerg } 406130300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 406230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 406330300Sjoerg pap.tlu(sp); 406430300Sjoerg } 406530300Sjoerg break; 406630300Sjoerg 406730300Sjoerg /* ack and nak are his authproto */ 406830300Sjoerg case PAP_ACK: 406940008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 407030300Sjoerg if (debug) { 407140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 407240008Sjoerg SPP_ARGS(ifp)); 407330300Sjoerg name_len = *((char *)h); 407430300Sjoerg if (len > 5 && name_len) { 407569211Sphk log(-1, ": "); 407630300Sjoerg sppp_print_string((char*)(h+1), name_len); 407730300Sjoerg } 407869211Sphk log(-1, "\n"); 407930300Sjoerg } 408030300Sjoerg x = splimp(); 408130300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 408230300Sjoerg if (sp->myauth.proto == PPP_PAP && 408332169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 408430300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 408530300Sjoerg /* 408630300Sjoerg * We are authenticator for PAP but didn't 408730300Sjoerg * complete yet. Leave it to tlu to proceed 408830300Sjoerg * to network phase. 408930300Sjoerg */ 409030300Sjoerg splx(x); 409130300Sjoerg break; 409230300Sjoerg } 409330300Sjoerg splx(x); 409430300Sjoerg sppp_phase_network(sp); 409530300Sjoerg break; 409630300Sjoerg 409730300Sjoerg case PAP_NAK: 409840008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 409930300Sjoerg if (debug) { 410040008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 410140008Sjoerg SPP_ARGS(ifp)); 410230300Sjoerg name_len = *((char *)h); 410330300Sjoerg if (len > 5 && name_len) { 410469211Sphk log(-1, ": "); 410530300Sjoerg sppp_print_string((char*)(h+1), name_len); 410630300Sjoerg } 410769211Sphk log(-1, "\n"); 410830300Sjoerg } else 410940008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 411040008Sjoerg SPP_ARGS(ifp)); 411130300Sjoerg /* await LCP shutdown by authenticator */ 411230300Sjoerg break; 411330300Sjoerg 411430300Sjoerg default: 411530300Sjoerg /* Unknown PAP packet type -- ignore. */ 411630300Sjoerg if (debug) { 411740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 411830300Sjoerg "<0x%x id=0x%x len=%d", 411940008Sjoerg SPP_ARGS(ifp), 412030300Sjoerg h->type, h->ident, ntohs(h->len)); 412144145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 412269211Sphk log(-1, ">\n"); 412330300Sjoerg } 412430300Sjoerg break; 412530300Sjoerg 412630300Sjoerg } 412730300Sjoerg} 412830300Sjoerg 412930300Sjoergstatic void 413030300Sjoergsppp_pap_init(struct sppp *sp) 413130300Sjoerg{ 413230300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 413330300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 413430300Sjoerg sp->fail_counter[IDX_PAP] = 0; 413578064Sume sp->pp_seq[IDX_PAP] = 0; 413678064Sume sp->pp_rseq[IDX_PAP] = 0; 413742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 413830300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 413930300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 414040008Sjoerg#endif 414130300Sjoerg} 414230300Sjoerg 414330300Sjoergstatic void 414430300Sjoergsppp_pap_open(struct sppp *sp) 414530300Sjoerg{ 414630300Sjoerg if (sp->hisauth.proto == PPP_PAP && 414730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 414830300Sjoerg /* we are authenticator for PAP, start our timer */ 414930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 415030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 415130300Sjoerg } 415230300Sjoerg if (sp->myauth.proto == PPP_PAP) { 415330300Sjoerg /* we are peer, send a request, and start a timer */ 415430300Sjoerg pap.scr(sp); 415542064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 415642064Sphk sp->pap_my_to_ch); 415730300Sjoerg } 415830300Sjoerg} 415930300Sjoerg 416030300Sjoergstatic void 416130300Sjoergsppp_pap_close(struct sppp *sp) 416230300Sjoerg{ 416330300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 416430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 416530300Sjoerg} 416630300Sjoerg 416730300Sjoerg/* 416830300Sjoerg * That's the timeout routine if we are authenticator. Since the 416930300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 417030300Sjoerg */ 417130300Sjoergstatic void 417230300Sjoergsppp_pap_TO(void *cookie) 417330300Sjoerg{ 417430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 417530300Sjoerg STDDCL; 417630300Sjoerg int s; 417730300Sjoerg 417830300Sjoerg s = splimp(); 417930300Sjoerg if (debug) 418040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 418140008Sjoerg SPP_ARGS(ifp), 418230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 418330300Sjoerg sp->rst_counter[IDX_PAP]); 418430300Sjoerg 418530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 418630300Sjoerg /* TO- event */ 418730300Sjoerg switch (sp->state[IDX_PAP]) { 418830300Sjoerg case STATE_REQ_SENT: 418930300Sjoerg pap.tld(sp); 419030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 419130300Sjoerg break; 419230300Sjoerg } 419330300Sjoerg else 419430300Sjoerg /* TO+ event, not very much we could do */ 419530300Sjoerg switch (sp->state[IDX_PAP]) { 419630300Sjoerg case STATE_REQ_SENT: 419730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 419830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 419930300Sjoerg break; 420030300Sjoerg } 420130300Sjoerg 420230300Sjoerg splx(s); 420330300Sjoerg} 420430300Sjoerg 420530300Sjoerg/* 420630300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 420730300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 420830300Sjoerg * XXX We should impose a max counter. 420930300Sjoerg */ 421030300Sjoergstatic void 421130300Sjoergsppp_pap_my_TO(void *cookie) 421230300Sjoerg{ 421330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 421430300Sjoerg STDDCL; 421530300Sjoerg 421630300Sjoerg if (debug) 421740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 421840008Sjoerg SPP_ARGS(ifp)); 421930300Sjoerg 422030300Sjoerg pap.scr(sp); 422130300Sjoerg} 422230300Sjoerg 422330300Sjoergstatic void 422430300Sjoergsppp_pap_tlu(struct sppp *sp) 422530300Sjoerg{ 422630300Sjoerg STDDCL; 422730300Sjoerg int x; 422830300Sjoerg 422930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 423030300Sjoerg 423130300Sjoerg if (debug) 423240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 423340008Sjoerg SPP_ARGS(ifp), pap.name); 423430300Sjoerg 423530300Sjoerg x = splimp(); 423630300Sjoerg /* indicate to LCP that we need to be closed down */ 423730300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 423830300Sjoerg 423930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 424030300Sjoerg /* 424130300Sjoerg * Remote is authenticator, but his auth proto didn't 424230300Sjoerg * complete yet. Defer the transition to network 424330300Sjoerg * phase. 424430300Sjoerg */ 424530300Sjoerg splx(x); 424630300Sjoerg return; 424730300Sjoerg } 424830300Sjoerg splx(x); 424930300Sjoerg sppp_phase_network(sp); 425030300Sjoerg} 425130300Sjoerg 425230300Sjoergstatic void 425330300Sjoergsppp_pap_tld(struct sppp *sp) 425430300Sjoerg{ 425530300Sjoerg STDDCL; 425630300Sjoerg 425730300Sjoerg if (debug) 425840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 425940008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 426040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 426130300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 426230300Sjoerg 426330300Sjoerg lcp.Close(sp); 426430300Sjoerg} 426530300Sjoerg 426630300Sjoergstatic void 426730300Sjoergsppp_pap_scr(struct sppp *sp) 426830300Sjoerg{ 426930300Sjoerg u_char idlen, pwdlen; 427030300Sjoerg 427178064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 427230300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 427330300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 427430300Sjoerg 427530300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 427630300Sjoerg sizeof idlen, (const char *)&idlen, 427740008Sjoerg (size_t)idlen, sp->myauth.name, 427830300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 427940008Sjoerg (size_t)pwdlen, sp->myauth.secret, 428030300Sjoerg 0); 428130300Sjoerg} 428270199Sjhay 428370199Sjhay/* 428425944Sjoerg * Random miscellaneous functions. 428525944Sjoerg */ 428625944Sjoerg 42874910Swollman/* 428830300Sjoerg * Send a PAP or CHAP proto packet. 428930300Sjoerg * 429030300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 429140008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 429230300Sjoerg * mlen == 0. 429342104Sphk * NOTE: never declare variadic functions with types subject to type 429442104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 429542104Sphk * on the architecture you are on... 429630300Sjoerg */ 429730300Sjoerg 429830300Sjoergstatic void 429942104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 430042104Sphk unsigned int type, unsigned int id, 430130300Sjoerg ...) 430230300Sjoerg{ 430330300Sjoerg STDDCL; 430430300Sjoerg struct ppp_header *h; 430530300Sjoerg struct lcp_header *lh; 430630300Sjoerg struct mbuf *m; 430730300Sjoerg u_char *p; 430830300Sjoerg int len; 430942104Sphk unsigned int mlen; 431030300Sjoerg const char *msg; 431130300Sjoerg va_list ap; 431230300Sjoerg 431330300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 431430300Sjoerg if (! m) 431530300Sjoerg return; 431630300Sjoerg m->m_pkthdr.rcvif = 0; 431730300Sjoerg 431830300Sjoerg h = mtod (m, struct ppp_header*); 431930300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 432030300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 432130300Sjoerg h->protocol = htons(cp->proto); 432230300Sjoerg 432330300Sjoerg lh = (struct lcp_header*)(h + 1); 432430300Sjoerg lh->type = type; 432530300Sjoerg lh->ident = id; 432630300Sjoerg p = (u_char*) (lh+1); 432730300Sjoerg 432830300Sjoerg va_start(ap, id); 432930300Sjoerg len = 0; 433030300Sjoerg 433142104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 433230300Sjoerg msg = va_arg(ap, const char *); 433330300Sjoerg len += mlen; 433430300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 433530300Sjoerg va_end(ap); 433630300Sjoerg m_freem(m); 433730300Sjoerg return; 433830300Sjoerg } 433930300Sjoerg 434030300Sjoerg bcopy(msg, p, mlen); 434130300Sjoerg p += mlen; 434230300Sjoerg } 434330300Sjoerg va_end(ap); 434430300Sjoerg 434530300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 434630300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 434730300Sjoerg 434830300Sjoerg if (debug) { 434940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 435040008Sjoerg SPP_ARGS(ifp), cp->name, 435130300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 435230300Sjoerg lh->ident, ntohs(lh->len)); 435344145Sphk sppp_print_bytes((u_char*) (lh+1), len); 435469211Sphk log(-1, ">\n"); 435530300Sjoerg } 435669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 435769152Sjlemon ifp->if_oerrors++; 435830300Sjoerg} 435930300Sjoerg 436030300Sjoerg/* 436125944Sjoerg * Flush interface queue. 43624910Swollman */ 436312820Sphkstatic void 436425944Sjoergsppp_qflush(struct ifqueue *ifq) 43654910Swollman{ 436625944Sjoerg struct mbuf *m, *n; 43674910Swollman 436825944Sjoerg n = ifq->ifq_head; 436925944Sjoerg while ((m = n)) { 437025944Sjoerg n = m->m_act; 437125944Sjoerg m_freem (m); 437211189Sjkh } 437325944Sjoerg ifq->ifq_head = 0; 437425944Sjoerg ifq->ifq_tail = 0; 437525944Sjoerg ifq->ifq_len = 0; 437625944Sjoerg} 437725944Sjoerg 437825944Sjoerg/* 437925944Sjoerg * Send keepalive packets, every 10 seconds. 438025944Sjoerg */ 438125944Sjoergstatic void 438225944Sjoergsppp_keepalive(void *dummy) 438325944Sjoerg{ 438425944Sjoerg struct sppp *sp; 438525944Sjoerg int s; 438625944Sjoerg 438725944Sjoerg s = splimp(); 438825944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 438925944Sjoerg struct ifnet *ifp = &sp->pp_if; 439025944Sjoerg 439125944Sjoerg /* Keepalive mode disabled or channel down? */ 439225944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 439325944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 439425944Sjoerg continue; 439525944Sjoerg 439625944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 439745152Sphk if (sp->pp_mode != IFF_CISCO && 439825944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 439925944Sjoerg continue; 440025944Sjoerg 440125944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 440225944Sjoerg /* No keepalive packets got. Stop the interface. */ 440340008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 440425944Sjoerg if_down (ifp); 440526018Sjoerg sppp_qflush (&sp->pp_cpq); 440645152Sphk if (sp->pp_mode != IFF_CISCO) { 440725944Sjoerg /* XXX */ 440825944Sjoerg /* Shut down the PPP link. */ 440925944Sjoerg lcp.Down(sp); 441025944Sjoerg /* Initiate negotiation. XXX */ 441125944Sjoerg lcp.Up(sp); 441225944Sjoerg } 44134910Swollman } 441425944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 441525944Sjoerg ++sp->pp_alivecnt; 441645152Sphk if (sp->pp_mode == IFF_CISCO) 441778064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 441878064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 441925944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 442025944Sjoerg long nmagic = htonl (sp->lcp.magic); 442178064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 442225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 442325944Sjoerg sp->lcp.echoid, 4, &nmagic); 442425944Sjoerg } 44254910Swollman } 442625944Sjoerg splx(s); 442742064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 44284910Swollman} 44294910Swollman 443025944Sjoerg/* 443125944Sjoerg * Get both IP addresses. 443225944Sjoerg */ 443325944Sjoergstatic void 443430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 443525944Sjoerg{ 443625944Sjoerg struct ifnet *ifp = &sp->pp_if; 443725944Sjoerg struct ifaddr *ifa; 443830300Sjoerg struct sockaddr_in *si, *sm; 443925944Sjoerg u_long ssrc, ddst; 444025944Sjoerg 444140010Sjoerg sm = NULL; 444225944Sjoerg ssrc = ddst = 0L; 444325944Sjoerg /* 444425944Sjoerg * Pick the first AF_INET address from the list, 444525944Sjoerg * aliases don't make any sense on a p2p link anyway. 444625944Sjoerg */ 444742065Sphk si = 0; 444842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 444942065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 445042104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 445171959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 445240008Sjoerg ifa; 445371959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 445442104Sphk#else 445542104Sphk for (ifa = ifp->if_addrlist; 445642104Sphk ifa; 445742104Sphk ifa = ifa->ifa_next) 445840008Sjoerg#endif 445925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 446025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 446130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 446225944Sjoerg if (si) 446325944Sjoerg break; 446425944Sjoerg } 446525944Sjoerg if (ifa) { 446630300Sjoerg if (si && si->sin_addr.s_addr) { 446725944Sjoerg ssrc = si->sin_addr.s_addr; 446830300Sjoerg if (srcmask) 446930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 447030300Sjoerg } 447125944Sjoerg 447225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 447325944Sjoerg if (si && si->sin_addr.s_addr) 447425944Sjoerg ddst = si->sin_addr.s_addr; 447525944Sjoerg } 447625944Sjoerg 447725944Sjoerg if (dst) *dst = ntohl(ddst); 447825944Sjoerg if (src) *src = ntohl(ssrc); 447925944Sjoerg} 448025944Sjoerg 448125944Sjoerg/* 448225944Sjoerg * Set my IP address. Must be called at splimp. 448325944Sjoerg */ 448425944Sjoergstatic void 448525944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 448625944Sjoerg{ 448742104Sphk STDDCL; 448825944Sjoerg struct ifaddr *ifa; 448925944Sjoerg struct sockaddr_in *si; 449025944Sjoerg 449125944Sjoerg /* 449225944Sjoerg * Pick the first AF_INET address from the list, 449325944Sjoerg * aliases don't make any sense on a p2p link anyway. 449425944Sjoerg */ 449542065Sphk si = 0; 449642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 449742065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 449842104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 449971959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 450040008Sjoerg ifa; 450171959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 450242104Sphk#else 450342104Sphk for (ifa = ifp->if_addrlist; 450442104Sphk ifa; 450542104Sphk ifa = ifa->ifa_next) 450640008Sjoerg#endif 450740008Sjoerg { 450840008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 450940008Sjoerg { 451025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 451125944Sjoerg if (si) 451225944Sjoerg break; 451325944Sjoerg } 451440008Sjoerg } 451540008Sjoerg 451625944Sjoerg if (ifa && si) 451742104Sphk { 451842104Sphk int error; 451942104Sphk#if __NetBSD_Version__ >= 103080000 452042104Sphk struct sockaddr_in new_sin = *si; 452142104Sphk 452242104Sphk new_sin.sin_addr.s_addr = htonl(src); 452342104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 452442104Sphk if(debug && error) 452542104Sphk { 452642104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 452742104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 452842104Sphk } 452942104Sphk#else 453042104Sphk /* delete old route */ 453142104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 453242104Sphk if(debug && error) 453342104Sphk { 453442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 453542104Sphk SPP_ARGS(ifp), error); 453642104Sphk } 453742104Sphk 453842104Sphk /* set new address */ 453925944Sjoerg si->sin_addr.s_addr = htonl(src); 454025944Sjoerg 454142104Sphk /* add new route */ 454270199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 454342104Sphk if (debug && error) 454442104Sphk { 454542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 454642104Sphk SPP_ARGS(ifp), error); 454742104Sphk } 454842104Sphk#endif 454942104Sphk } 455078064Sume} 455178064Sume 455278064Sume#ifdef INET6 455378064Sume/* 455478064Sume * Get both IPv6 addresses. 455578064Sume */ 455678064Sumestatic void 455778064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 455878064Sume struct in6_addr *srcmask) 455978064Sume{ 456078064Sume struct ifnet *ifp = &sp->pp_if; 456178064Sume struct ifaddr *ifa; 456278064Sume struct sockaddr_in6 *si, *sm; 456378064Sume struct in6_addr ssrc, ddst; 456478064Sume 456578064Sume sm = NULL; 456678064Sume bzero(&ssrc, sizeof(ssrc)); 456778064Sume bzero(&ddst, sizeof(ddst)); 456878064Sume /* 456978064Sume * Pick the first link-local AF_INET6 address from the list, 457078064Sume * aliases don't make any sense on a p2p link anyway. 457178064Sume */ 457278064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 457378064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 457478064Sume ifa; 457578064Sume ifa = ifa->ifa_link.tqe_next) 457678064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 457778064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 457878064Sume ifa; 457978064Sume ifa = ifa->ifa_list.tqe_next) 458078064Sume#else 458178064Sume for (ifa = ifp->if_addrlist, si = 0; 458278064Sume ifa; 458378064Sume ifa = ifa->ifa_next) 458478064Sume#endif 458578064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 458678064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 458778064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 458878064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 458978064Sume break; 459078064Sume } 459178064Sume if (ifa) { 459278064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 459378064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 459478064Sume if (srcmask) { 459578064Sume bcopy(&sm->sin6_addr, srcmask, 459678064Sume sizeof(*srcmask)); 459778064Sume } 459878064Sume } 459978064Sume 460078064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 460178064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 460278064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 460378064Sume } 460478064Sume 460578064Sume if (dst) 460678064Sume bcopy(&ddst, dst, sizeof(*dst)); 460778064Sume if (src) 460878064Sume bcopy(&ssrc, src, sizeof(*src)); 460970199Sjhay} 461042104Sphk 461178064Sume#ifdef IPV6CP_MYIFID_DYN 461278064Sume/* 461378064Sume * Generate random ifid. 461478064Sume */ 461578064Sumestatic void 461678064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 461778064Sume{ 461878064Sume /* TBD */ 461978064Sume} 462078064Sume 462178064Sume/* 462278064Sume * Set my IPv6 address. Must be called at splimp. 462378064Sume */ 462478064Sumestatic void 462578064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 462678064Sume{ 462778064Sume STDDCL; 462878064Sume struct ifaddr *ifa; 462978064Sume struct sockaddr_in6 *sin6; 463078064Sume 463178064Sume /* 463278064Sume * Pick the first link-local AF_INET6 address from the list, 463378064Sume * aliases don't make any sense on a p2p link anyway. 463478064Sume */ 463578064Sume 463678064Sume sin6 = NULL; 463778064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 463878064Sume for (ifa = ifp->if_addrhead.tqh_first; 463978064Sume ifa; 464078064Sume ifa = ifa->ifa_link.tqe_next) 464178064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 464278064Sume for (ifa = ifp->if_addrlist.tqh_first; 464378064Sume ifa; 464478064Sume ifa = ifa->ifa_list.tqe_next) 464578064Sume#else 464678064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 464778064Sume#endif 464878064Sume { 464978064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 465078064Sume { 465178064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 465278064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 465378064Sume break; 465478064Sume } 465578064Sume } 465678064Sume 465778064Sume if (ifa && sin6) 465878064Sume { 465978064Sume int error; 466078064Sume struct sockaddr_in6 new_sin6 = *sin6; 466178064Sume 466278064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 466378064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 466478064Sume if (debug && error) 466578064Sume { 466678064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 466778064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 466878064Sume } 466978064Sume } 467078064Sume} 467178064Sume#endif 467278064Sume 467378064Sume/* 467478064Sume * Suggest a candidate address to be used by peer. 467578064Sume */ 467678064Sumestatic void 467778064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 467878064Sume{ 467978064Sume struct in6_addr myaddr; 468078064Sume struct timeval tv; 468178064Sume 468278064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 468378064Sume 468478064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 468578064Sume microtime(&tv); 468678064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 468778064Sume myaddr.s6_addr[14] ^= 0xff; 468878064Sume myaddr.s6_addr[15] ^= 0xff; 468978064Sume } else { 469078064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 469178064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 469278064Sume } 469378064Sume if (suggest) 469478064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 469578064Sume} 469678064Sume#endif /*INET6*/ 469778064Sume 469830300Sjoergstatic int 469938343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 470030300Sjoerg{ 470138343Sbde u_long subcmd; 470230300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 470330300Sjoerg struct spppreq spr; 470430300Sjoerg 470530300Sjoerg /* 470630300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 470730300Sjoerg * Check the cmd word first before attempting to fetch all the 470830300Sjoerg * data. 470930300Sjoerg */ 471030300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 471130300Sjoerg return EFAULT; 471230300Sjoerg 471330300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 471430300Sjoerg return EFAULT; 471530300Sjoerg 471630300Sjoerg switch (subcmd) { 471730300Sjoerg case SPPPIOGDEFS: 471830300Sjoerg if (cmd != SIOCGIFGENERIC) 471930300Sjoerg return EINVAL; 472030300Sjoerg /* 472130300Sjoerg * We copy over the entire current state, but clean 472230300Sjoerg * out some of the stuff we don't wanna pass up. 472330300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 472430300Sjoerg * called by any user. No need to ever get PAP or 472530300Sjoerg * CHAP secrets back to userland anyway. 472630300Sjoerg */ 472730300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 472830300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 472930300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 473030300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 473130300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 473230300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 473330300Sjoerg 473430300Sjoerg case SPPPIOSDEFS: 473530300Sjoerg if (cmd != SIOCSIFGENERIC) 473630300Sjoerg return EINVAL; 473730300Sjoerg /* 473830300Sjoerg * We have a very specific idea of which fields we allow 473930300Sjoerg * being passed back from userland, so to not clobber our 474030300Sjoerg * current state. For one, we only allow setting 474130300Sjoerg * anything if LCP is in dead phase. Once the LCP 474230300Sjoerg * negotiations started, the authentication settings must 474330300Sjoerg * not be changed again. (The administrator can force an 474430300Sjoerg * ifconfig down in order to get LCP back into dead 474530300Sjoerg * phase.) 474630300Sjoerg * 474730300Sjoerg * Also, we only allow for authentication parameters to be 474830300Sjoerg * specified. 474930300Sjoerg * 475030300Sjoerg * XXX Should allow to set or clear pp_flags. 475130300Sjoerg * 475230300Sjoerg * Finally, if the respective authentication protocol to 475330300Sjoerg * be used is set differently than 0, but the secret is 475430300Sjoerg * passed as all zeros, we don't trash the existing secret. 475530300Sjoerg * This allows an administrator to change the system name 475630300Sjoerg * only without clobbering the secret (which he didn't get 475730300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 475830300Sjoerg * secrets are cleared if the authentication protocol is 475930300Sjoerg * reset to 0. 476030300Sjoerg */ 476130300Sjoerg if (sp->pp_phase != PHASE_DEAD) 476230300Sjoerg return EBUSY; 476330300Sjoerg 476430300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 476530300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 476630300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 476730300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 476830300Sjoerg return EINVAL; 476930300Sjoerg 477030300Sjoerg if (spr.defs.myauth.proto == 0) 477130300Sjoerg /* resetting myauth */ 477230300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 477330300Sjoerg else { 477430300Sjoerg /* setting/changing myauth */ 477530300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 477630300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 477730300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 477830300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 477930300Sjoerg AUTHKEYLEN); 478030300Sjoerg } 478130300Sjoerg if (spr.defs.hisauth.proto == 0) 478230300Sjoerg /* resetting hisauth */ 478330300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 478430300Sjoerg else { 478530300Sjoerg /* setting/changing hisauth */ 478630300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 478730300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 478830300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 478930300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 479030300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 479130300Sjoerg AUTHKEYLEN); 479230300Sjoerg } 479330300Sjoerg break; 479430300Sjoerg 479530300Sjoerg default: 479630300Sjoerg return EINVAL; 479730300Sjoerg } 479830300Sjoerg 479930300Sjoerg return 0; 480030300Sjoerg} 480130300Sjoerg 480230300Sjoergstatic void 480330300Sjoergsppp_phase_network(struct sppp *sp) 480430300Sjoerg{ 480542066Sphk STDDCL; 480630300Sjoerg int i; 480730300Sjoerg u_long mask; 480830300Sjoerg 480930300Sjoerg sp->pp_phase = PHASE_NETWORK; 481030300Sjoerg 481142066Sphk if (debug) 481242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 481342066Sphk sppp_phase_name(sp->pp_phase)); 481430300Sjoerg 481530300Sjoerg /* Notify NCPs now. */ 481630300Sjoerg for (i = 0; i < IDX_COUNT; i++) 481730300Sjoerg if ((cps[i])->flags & CP_NCP) 481830300Sjoerg (cps[i])->Open(sp); 481930300Sjoerg 482030300Sjoerg /* Send Up events to all NCPs. */ 482130300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 482230300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 482330300Sjoerg (cps[i])->Up(sp); 482430300Sjoerg 482530300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 482630300Sjoerg sppp_lcp_check_and_close(sp); 482730300Sjoerg} 482830300Sjoerg 482970199Sjhay 483025706Sjoergstatic const char * 483125944Sjoergsppp_cp_type_name(u_char type) 48324910Swollman{ 483330300Sjoerg static char buf[12]; 48344910Swollman switch (type) { 483530300Sjoerg case CONF_REQ: return "conf-req"; 483630300Sjoerg case CONF_ACK: return "conf-ack"; 483730300Sjoerg case CONF_NAK: return "conf-nak"; 483830300Sjoerg case CONF_REJ: return "conf-rej"; 483930300Sjoerg case TERM_REQ: return "term-req"; 484030300Sjoerg case TERM_ACK: return "term-ack"; 484130300Sjoerg case CODE_REJ: return "code-rej"; 484230300Sjoerg case PROTO_REJ: return "proto-rej"; 484330300Sjoerg case ECHO_REQ: return "echo-req"; 484430300Sjoerg case ECHO_REPLY: return "echo-reply"; 484530300Sjoerg case DISC_REQ: return "discard-req"; 48464910Swollman } 484744145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 484830300Sjoerg return buf; 48494910Swollman} 48504910Swollman 485125706Sjoergstatic const char * 485230300Sjoergsppp_auth_type_name(u_short proto, u_char type) 485330300Sjoerg{ 485430300Sjoerg static char buf[12]; 485530300Sjoerg switch (proto) { 485630300Sjoerg case PPP_CHAP: 485730300Sjoerg switch (type) { 485830300Sjoerg case CHAP_CHALLENGE: return "challenge"; 485930300Sjoerg case CHAP_RESPONSE: return "response"; 486030300Sjoerg case CHAP_SUCCESS: return "success"; 486130300Sjoerg case CHAP_FAILURE: return "failure"; 486230300Sjoerg } 486330300Sjoerg case PPP_PAP: 486430300Sjoerg switch (type) { 486530300Sjoerg case PAP_REQ: return "req"; 486630300Sjoerg case PAP_ACK: return "ack"; 486730300Sjoerg case PAP_NAK: return "nak"; 486830300Sjoerg } 486930300Sjoerg } 487044145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 487130300Sjoerg return buf; 487230300Sjoerg} 487330300Sjoerg 487430300Sjoergstatic const char * 487525944Sjoergsppp_lcp_opt_name(u_char opt) 48764910Swollman{ 487730300Sjoerg static char buf[12]; 487825944Sjoerg switch (opt) { 487930300Sjoerg case LCP_OPT_MRU: return "mru"; 488030300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 488130300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 488230300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 488330300Sjoerg case LCP_OPT_MAGIC: return "magic"; 488430300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 488530300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 48864910Swollman } 488744145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 488830300Sjoerg return buf; 48894910Swollman} 48904910Swollman 489125944Sjoergstatic const char * 489225944Sjoergsppp_ipcp_opt_name(u_char opt) 489325944Sjoerg{ 489430300Sjoerg static char buf[12]; 489525944Sjoerg switch (opt) { 489630300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 489730300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 489830300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 489925944Sjoerg } 490044145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 490130300Sjoerg return buf; 490225944Sjoerg} 490325944Sjoerg 490478064Sume#ifdef INET6 490525944Sjoergstatic const char * 490678064Sumesppp_ipv6cp_opt_name(u_char opt) 490778064Sume{ 490878064Sume static char buf[12]; 490978064Sume switch (opt) { 491078064Sume case IPV6CP_OPT_IFID: return "ifid"; 491178064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 491278064Sume } 491378064Sume sprintf (buf, "0x%x", opt); 491478064Sume return buf; 491578064Sume} 491678064Sume#endif 491778064Sume 491878064Sumestatic const char * 491925944Sjoergsppp_state_name(int state) 492025944Sjoerg{ 492125944Sjoerg switch (state) { 492225944Sjoerg case STATE_INITIAL: return "initial"; 492325944Sjoerg case STATE_STARTING: return "starting"; 492425944Sjoerg case STATE_CLOSED: return "closed"; 492525944Sjoerg case STATE_STOPPED: return "stopped"; 492625944Sjoerg case STATE_CLOSING: return "closing"; 492725944Sjoerg case STATE_STOPPING: return "stopping"; 492825944Sjoerg case STATE_REQ_SENT: return "req-sent"; 492925944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 493025944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 493125944Sjoerg case STATE_OPENED: return "opened"; 493225944Sjoerg } 493325944Sjoerg return "illegal"; 493425944Sjoerg} 493525944Sjoerg 493625944Sjoergstatic const char * 493725944Sjoergsppp_phase_name(enum ppp_phase phase) 493825944Sjoerg{ 493925944Sjoerg switch (phase) { 494025944Sjoerg case PHASE_DEAD: return "dead"; 494125944Sjoerg case PHASE_ESTABLISH: return "establish"; 494225944Sjoerg case PHASE_TERMINATE: return "terminate"; 494325944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 494425944Sjoerg case PHASE_NETWORK: return "network"; 494525944Sjoerg } 494625944Sjoerg return "illegal"; 494725944Sjoerg} 494825944Sjoerg 494925944Sjoergstatic const char * 495025944Sjoergsppp_proto_name(u_short proto) 495125944Sjoerg{ 495225944Sjoerg static char buf[12]; 495325944Sjoerg switch (proto) { 495425944Sjoerg case PPP_LCP: return "lcp"; 495525944Sjoerg case PPP_IPCP: return "ipcp"; 495630300Sjoerg case PPP_PAP: return "pap"; 495730300Sjoerg case PPP_CHAP: return "chap"; 495878064Sume case PPP_IPV6CP: return "ipv6cp"; 495925944Sjoerg } 496044145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 496125944Sjoerg return buf; 496225944Sjoerg} 496325944Sjoerg 496412820Sphkstatic void 496530300Sjoergsppp_print_bytes(const u_char *p, u_short len) 49664910Swollman{ 496744145Sphk if (len) 496869211Sphk log(-1, " %*D", len, p, "-"); 49694910Swollman} 497025944Sjoerg 497130300Sjoergstatic void 497230300Sjoergsppp_print_string(const char *p, u_short len) 497330300Sjoerg{ 497430300Sjoerg u_char c; 497530300Sjoerg 497630300Sjoerg while (len-- > 0) { 497730300Sjoerg c = *p++; 497830300Sjoerg /* 497930300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 498030300Sjoerg * using only them, but we don't rely on it. */ 498130300Sjoerg if (c < ' ' || c > '~') 498269211Sphk log(-1, "\\x%x", c); 498330300Sjoerg else 498469211Sphk log(-1, "%c", c); 498530300Sjoerg } 498630300Sjoerg} 498730300Sjoerg 498830300Sjoergstatic const char * 498930300Sjoergsppp_dotted_quad(u_long addr) 499030300Sjoerg{ 499130300Sjoerg static char s[16]; 499230300Sjoerg sprintf(s, "%d.%d.%d.%d", 499340008Sjoerg (int)((addr >> 24) & 0xff), 499440008Sjoerg (int)((addr >> 16) & 0xff), 499540008Sjoerg (int)((addr >> 8) & 0xff), 499638372Sbde (int)(addr & 0xff)); 499730300Sjoerg return s; 499830300Sjoerg} 499930300Sjoerg 500030300Sjoergstatic int 500130300Sjoergsppp_strnlen(u_char *p, int max) 500230300Sjoerg{ 500330300Sjoerg int len; 500430300Sjoerg 500530300Sjoerg for (len = 0; len < max && *p; ++p) 500630300Sjoerg ++len; 500730300Sjoerg return len; 500830300Sjoerg} 500930300Sjoerg 501030300Sjoerg/* a dummy, used to drop uninteresting events */ 501130300Sjoergstatic void 501230300Sjoergsppp_null(struct sppp *unused) 501330300Sjoerg{ 501430300Sjoerg /* do just nothing */ 501530300Sjoerg} 5016