if_spppsubr.c revision 74703
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 74703 2001-03-23 19:51:12Z joerg $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2940008Sjoerg#endif 3031742Seivind 3140008Sjoerg#ifdef NetBSD1_3 3240008Sjoerg# if NetBSD1_3 > 6 3340008Sjoerg# include "opt_inet.h" 3454263Sshin# include "opt_inet6.h" 3540008Sjoerg# include "opt_iso.h" 3640008Sjoerg# endif 3740008Sjoerg#endif 3840008Sjoerg 394952Sbde#include <sys/systm.h> 404952Sbde#include <sys/kernel.h> 4170199Sjhay#include <sys/module.h> 4224204Sbde#include <sys/sockio.h> 434910Swollman#include <sys/socket.h> 4425706Sjoerg#include <sys/syslog.h> 4542104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4659604Sobrien#include <sys/random.h> 4742104Sphk#endif 4829024Sbde#include <sys/malloc.h> 494910Swollman#include <sys/mbuf.h> 5040008Sjoerg 5140008Sjoerg#if defined (__OpenBSD__) 5240008Sjoerg#include <sys/md5k.h> 5340008Sjoerg#else 5430300Sjoerg#include <sys/md5.h> 5540008Sjoerg#endif 564910Swollman 574910Swollman#include <net/if.h> 584910Swollman#include <net/netisr.h> 594910Swollman#include <net/if_types.h> 6042104Sphk#include <net/route.h> 614910Swollman 6240008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6340008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6440008Sjoerg#endif 6542104Sphk 6630300Sjoerg#include <machine/stdarg.h> 6730300Sjoerg 684910Swollman#ifdef INET 694910Swollman#include <netinet/in.h> 704910Swollman#include <netinet/in_systm.h> 714910Swollman#include <netinet/in_var.h> 724910Swollman#include <netinet/ip.h> 734910Swollman#include <netinet/tcp.h> 7440008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7540008Sjoerg# include <netinet/if_ether.h> 7640008Sjoerg# else 7740008Sjoerg# include <net/ethertypes.h> 7840008Sjoerg# endif 7932350Seivind#else 8040008Sjoerg# error Huh? sppp without INET? 814910Swollman#endif 824910Swollman 8311819Sjulian#ifdef IPX 8411819Sjulian#include <netipx/ipx.h> 8511819Sjulian#include <netipx/ipx_if.h> 8611819Sjulian#endif 8711819Sjulian 884910Swollman#ifdef NS 894910Swollman#include <netns/ns.h> 904910Swollman#include <netns/ns_if.h> 914910Swollman#endif 924910Swollman 934910Swollman#include <net/if_sppp.h> 944910Swollman 9542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9642064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9742064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 9842104Sphk# define IOCTL_CMD_T u_long 9940008Sjoerg#else 10042064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10142064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10242104Sphk# define IOCTL_CMD_T int 10340008Sjoerg#endif 10442104Sphk 1054910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1064910Swollman 10725944Sjoerg/* 10825944Sjoerg * Interface flags that can be set in an ifconfig command. 10925944Sjoerg * 11025955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11125944Sjoerg * as being administrative openable, but won't be opened to begin 11225944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11325944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11425955Sjoerg * 11525955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11625955Sjoerg * arrive to be sent. 11730300Sjoerg * 11830300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11930300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12030300Sjoerg * like 12130300Sjoerg * 12230300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12330300Sjoerg * 12430300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12530300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12625944Sjoerg */ 12725944Sjoerg 12825955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12925955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13045152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13125944Sjoerg 13230300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13330300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13430300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13530300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13630300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13730300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 13830300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 13930300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14030300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14130300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1424910Swollman 14325944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 14425944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 14525944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 14625944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 14725944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 14825944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 14925944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15025944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15125944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15225944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15325944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1544910Swollman 15530300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 15630300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 15730300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 15830300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 15930300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16030300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16130300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16230300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1634910Swollman 16425944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 16525944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 16625944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1674910Swollman 16830300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 16930300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17030300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1714910Swollman 17230300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17330300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 17430300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 17530300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 17630300Sjoerg 17730300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 17830300Sjoerg 17930300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18030300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18130300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18230300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18330300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 18430300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 18530300Sjoerg 18625944Sjoerg/* states are named and numbered according to RFC 1661 */ 18725944Sjoerg#define STATE_INITIAL 0 18825944Sjoerg#define STATE_STARTING 1 18925944Sjoerg#define STATE_CLOSED 2 19025944Sjoerg#define STATE_STOPPED 3 19125944Sjoerg#define STATE_CLOSING 4 19225944Sjoerg#define STATE_STOPPING 5 19325944Sjoerg#define STATE_REQ_SENT 6 19425944Sjoerg#define STATE_ACK_RCVD 7 19525944Sjoerg#define STATE_ACK_SENT 8 19625944Sjoerg#define STATE_OPENED 9 19725944Sjoerg 1984910Swollmanstruct ppp_header { 19911189Sjkh u_char address; 20011189Sjkh u_char control; 20111189Sjkh u_short protocol; 2024910Swollman}; 2034910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2044910Swollman 2054910Swollmanstruct lcp_header { 20611189Sjkh u_char type; 20711189Sjkh u_char ident; 20811189Sjkh u_short len; 2094910Swollman}; 2104910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2114910Swollman 2124910Swollmanstruct cisco_packet { 21311189Sjkh u_long type; 21411189Sjkh u_long par1; 21511189Sjkh u_long par2; 21611189Sjkh u_short rel; 21711189Sjkh u_short time0; 21811189Sjkh u_short time1; 2194910Swollman}; 2204910Swollman#define CISCO_PACKET_LEN 18 2214910Swollman 22225944Sjoerg/* 22325944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 22425944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 22525944Sjoerg * case you can't make sense out of these abbreviation; it will also 22625944Sjoerg * explain the semantics related to the various events and actions. 22725944Sjoerg */ 22825944Sjoergstruct cp { 22925944Sjoerg u_short proto; /* PPP control protocol number */ 23025944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23125944Sjoerg u_char flags; 23225944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23325944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 23425944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 23525944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 23625944Sjoerg const char *name; /* name of this control protocol */ 23725944Sjoerg /* event handlers */ 23825944Sjoerg void (*Up)(struct sppp *sp); 23925944Sjoerg void (*Down)(struct sppp *sp); 24025944Sjoerg void (*Open)(struct sppp *sp); 24125944Sjoerg void (*Close)(struct sppp *sp); 24225944Sjoerg void (*TO)(void *sp); 24325944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 24425944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 24525944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 24625944Sjoerg /* actions */ 24725944Sjoerg void (*tlu)(struct sppp *sp); 24825944Sjoerg void (*tld)(struct sppp *sp); 24925944Sjoerg void (*tls)(struct sppp *sp); 25025944Sjoerg void (*tlf)(struct sppp *sp); 25125944Sjoerg void (*scr)(struct sppp *sp); 25225944Sjoerg}; 25325944Sjoerg 25412820Sphkstatic struct sppp *spppq; 25542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 25630300Sjoergstatic struct callout_handle keepalive_ch; 25740008Sjoerg#endif 2584910Swollman 25942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26040008Sjoerg#define SPP_FMT "%s%d: " 26140008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26240008Sjoerg#else 26340008Sjoerg#define SPP_FMT "%s: " 26440008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 26540008Sjoerg#endif 26640008Sjoerg 2674910Swollman/* 2684910Swollman * The following disgusting hack gets around the problem that IP TOS 2694910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2704910Swollman * priority queue. To decide if traffic is interactive, we check that 2714910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27230300Sjoerg * 27330300Sjoerg * XXX is this really still necessary? - joerg - 2744910Swollman */ 27511189Sjkhstatic u_short interactive_ports[8] = { 2764910Swollman 0, 513, 0, 0, 2774910Swollman 0, 21, 0, 23, 2784910Swollman}; 2794910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2804910Swollman 28125944Sjoerg/* almost every function needs these */ 28225944Sjoerg#define STDDCL \ 28325944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 28425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 28511189Sjkh 28630300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 28725944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2884910Swollman 28925944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 29025944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29125944Sjoerg 29225944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29325944Sjoerg struct mbuf *m); 29425944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 29525944Sjoerg u_char ident, u_short len, void *data); 29642104Sphk/* static void sppp_cp_timeout(void *arg); */ 29725944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 29825944Sjoerg int newstate); 29930300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30042104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30130300Sjoerg ...); 30225944Sjoerg 30325944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 30425944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 30525944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 30625944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 30725944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 30825944Sjoerg 30930300Sjoergstatic void sppp_null(struct sppp *sp); 31030300Sjoerg 31125944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31225944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31325944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31425944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 31525944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 31625944Sjoergstatic void sppp_lcp_TO(void *sp); 31725944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31825944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31925944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32025944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32225944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32325944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32425944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 32530300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 32630300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 32725944Sjoerg 32825944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 32925944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33025944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33125944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33225944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33325944Sjoergstatic void sppp_ipcp_TO(void *sp); 33425944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33525944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33625944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33725944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 33925944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34025944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34125944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34225944Sjoerg 34330300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 34430300Sjoergstatic void sppp_pap_init(struct sppp *sp); 34530300Sjoergstatic void sppp_pap_open(struct sppp *sp); 34630300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34730300Sjoergstatic void sppp_pap_TO(void *sp); 34830300Sjoergstatic void sppp_pap_my_TO(void *sp); 34930300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 35030300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 35130300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 35230300Sjoerg 35330300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 35430300Sjoergstatic void sppp_chap_init(struct sppp *sp); 35530300Sjoergstatic void sppp_chap_open(struct sppp *sp); 35630300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35730300Sjoergstatic void sppp_chap_TO(void *sp); 35830300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35930300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 36030300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 36130300Sjoerg 36230300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 36325944Sjoergstatic const char *sppp_cp_type_name(u_char type); 36430300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 36530300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 36625944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36725944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 36825944Sjoergstatic const char *sppp_proto_name(u_short proto); 36930300Sjoergstatic const char *sppp_state_name(int state); 37038343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37130300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37230300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 37330300Sjoerg u_long *srcmask); 37425944Sjoergstatic void sppp_keepalive(void *dummy); 37530300Sjoergstatic void sppp_phase_network(struct sppp *sp); 37630300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 37730300Sjoergstatic void sppp_print_string(const char *p, u_short len); 37825944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 37925944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 38025944Sjoerg 38125944Sjoerg/* our control protocol descriptors */ 38233181Seivindstatic const struct cp lcp = { 38325944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 38425944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 38525944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 38625944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 38725944Sjoerg sppp_lcp_scr 38825944Sjoerg}; 38925944Sjoerg 39033181Seivindstatic const struct cp ipcp = { 39125944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 39225944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 39325944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 39425944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 39525944Sjoerg sppp_ipcp_scr 39625944Sjoerg}; 39725944Sjoerg 39833181Seivindstatic const struct cp pap = { 39930300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 40030300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 40130300Sjoerg sppp_pap_TO, 0, 0, 0, 40230300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 40330300Sjoerg sppp_pap_scr 40430300Sjoerg}; 40530300Sjoerg 40633181Seivindstatic const struct cp chap = { 40730300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 40830300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 40930300Sjoerg sppp_chap_TO, 0, 0, 0, 41030300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 41130300Sjoerg sppp_chap_scr 41230300Sjoerg}; 41330300Sjoerg 41433181Seivindstatic const struct cp *cps[IDX_COUNT] = { 41525944Sjoerg &lcp, /* IDX_LCP */ 41625944Sjoerg &ipcp, /* IDX_IPCP */ 41730300Sjoerg &pap, /* IDX_PAP */ 41830300Sjoerg &chap, /* IDX_CHAP */ 41925944Sjoerg}; 42025944Sjoerg 42170199Sjhaystatic int 42270199Sjhaysppp_modevent(module_t mod, int type, void *unused) 42370199Sjhay{ 42470199Sjhay switch (type) { 42570199Sjhay case MOD_LOAD: 42670199Sjhay break; 42770199Sjhay case MOD_UNLOAD: 42870199Sjhay return EACCES; 42970199Sjhay break; 43070199Sjhay default: 43170199Sjhay break; 43270199Sjhay } 43370199Sjhay return 0; 43470199Sjhay} 43570199Sjhaystatic moduledata_t spppmod = { 43670199Sjhay "sppp", 43770199Sjhay sppp_modevent, 43870199Sjhay 0 43970199Sjhay}; 44070199SjhayMODULE_VERSION(sppp, 1); 44170199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 44225944Sjoerg 44370199Sjhay/* 44425944Sjoerg * Exported functions, comprising our interface to the lower layer. 4454910Swollman */ 4464910Swollman 4474910Swollman/* 4484910Swollman * Process the received packet. 4494910Swollman */ 45025706Sjoergvoid 45125706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4524910Swollman{ 4534910Swollman struct ppp_header *h; 4544910Swollman struct ifqueue *inq = 0; 45525944Sjoerg struct sppp *sp = (struct sppp *)ifp; 45625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 4574910Swollman 4584910Swollman if (ifp->if_flags & IFF_UP) 4594910Swollman /* Count received bytes, add FCS and one flag */ 4604910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 4614910Swollman 4624910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 4634910Swollman /* Too small packet, drop it. */ 46425944Sjoerg if (debug) 46525706Sjoerg log(LOG_DEBUG, 46640008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 46740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 46825944Sjoerg drop: 46925944Sjoerg ++ifp->if_ierrors; 47025944Sjoerg ++ifp->if_iqdrops; 4714910Swollman m_freem (m); 4724910Swollman return; 4734910Swollman } 4744910Swollman 4754910Swollman /* Get PPP header. */ 4764910Swollman h = mtod (m, struct ppp_header*); 4774910Swollman m_adj (m, PPP_HEADER_LEN); 4784910Swollman 4794910Swollman switch (h->address) { 4804910Swollman case PPP_ALLSTATIONS: 4814910Swollman if (h->control != PPP_UI) 4824910Swollman goto invalid; 48345152Sphk if (sp->pp_mode == IFF_CISCO) { 48425944Sjoerg if (debug) 48525706Sjoerg log(LOG_DEBUG, 48640008Sjoerg SPP_FMT "PPP packet in Cisco mode " 48725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 48840008Sjoerg SPP_ARGS(ifp), 48925706Sjoerg h->address, h->control, ntohs(h->protocol)); 49011189Sjkh goto drop; 49111189Sjkh } 4924910Swollman switch (ntohs (h->protocol)) { 4934910Swollman default: 49425944Sjoerg if (debug) 49525706Sjoerg log(LOG_DEBUG, 49644145Sphk SPP_FMT "rejecting protocol " 49725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 49840008Sjoerg SPP_ARGS(ifp), 49925706Sjoerg h->address, h->control, ntohs(h->protocol)); 50044145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 50144145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 50244145Sphk ++sp->pp_seq, m->m_pkthdr.len + 2, 50344145Sphk &h->protocol); 5044910Swollman ++ifp->if_noproto; 5054910Swollman goto drop; 5064910Swollman case PPP_LCP: 50730300Sjoerg sppp_cp_input(&lcp, sp, m); 5084910Swollman m_freem (m); 5094910Swollman return; 51030300Sjoerg case PPP_PAP: 51130300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 51230300Sjoerg sppp_pap_input(sp, m); 51330300Sjoerg m_freem (m); 51430300Sjoerg return; 51530300Sjoerg case PPP_CHAP: 51630300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 51730300Sjoerg sppp_chap_input(sp, m); 51830300Sjoerg m_freem (m); 51930300Sjoerg return; 5204910Swollman#ifdef INET 5214910Swollman case PPP_IPCP: 52225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 52330300Sjoerg sppp_cp_input(&ipcp, sp, m); 5244910Swollman m_freem (m); 5254910Swollman return; 5264910Swollman case PPP_IP: 52725944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5284910Swollman schednetisr (NETISR_IP); 5294910Swollman inq = &ipintrq; 5304910Swollman } 5314910Swollman break; 5324910Swollman#endif 53312495Speter#ifdef IPX 53412495Speter case PPP_IPX: 53512495Speter /* IPX IPXCP not implemented yet */ 53625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 53712495Speter schednetisr (NETISR_IPX); 53812495Speter inq = &ipxintrq; 53912495Speter } 54012495Speter break; 54112495Speter#endif 5424910Swollman#ifdef NS 5434910Swollman case PPP_XNS: 5444910Swollman /* XNS IDPCP not implemented yet */ 54525944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5464910Swollman schednetisr (NETISR_NS); 5474910Swollman inq = &nsintrq; 5484910Swollman } 5494910Swollman break; 5504910Swollman#endif 5514910Swollman } 5524910Swollman break; 5534910Swollman case CISCO_MULTICAST: 5544910Swollman case CISCO_UNICAST: 5554910Swollman /* Don't check the control field here (RFC 1547). */ 55645152Sphk if (sp->pp_mode != IFF_CISCO) { 55725944Sjoerg if (debug) 55825706Sjoerg log(LOG_DEBUG, 55940008Sjoerg SPP_FMT "Cisco packet in PPP mode " 56025706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 56140008Sjoerg SPP_ARGS(ifp), 56225706Sjoerg h->address, h->control, ntohs(h->protocol)); 56311189Sjkh goto drop; 56411189Sjkh } 5654910Swollman switch (ntohs (h->protocol)) { 5664910Swollman default: 5674910Swollman ++ifp->if_noproto; 5684910Swollman goto invalid; 5694910Swollman case CISCO_KEEPALIVE: 5704910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5714910Swollman m_freem (m); 5724910Swollman return; 5734910Swollman#ifdef INET 5744910Swollman case ETHERTYPE_IP: 5754910Swollman schednetisr (NETISR_IP); 5764910Swollman inq = &ipintrq; 5774910Swollman break; 5784910Swollman#endif 57954263Sshin#ifdef INET6 58054263Sshin case ETHERTYPE_IPV6: 58154263Sshin schednetisr (NETISR_IPV6); 58254263Sshin inq = &ip6intrq; 58354263Sshin break; 58454263Sshin#endif 58512495Speter#ifdef IPX 58612495Speter case ETHERTYPE_IPX: 58712495Speter schednetisr (NETISR_IPX); 58812495Speter inq = &ipxintrq; 58912495Speter break; 59012495Speter#endif 5914910Swollman#ifdef NS 5924910Swollman case ETHERTYPE_NS: 5934910Swollman schednetisr (NETISR_NS); 5944910Swollman inq = &nsintrq; 5954910Swollman break; 5964910Swollman#endif 5974910Swollman } 5984910Swollman break; 59925944Sjoerg default: /* Invalid PPP packet. */ 60025944Sjoerg invalid: 60125944Sjoerg if (debug) 60225944Sjoerg log(LOG_DEBUG, 60340008Sjoerg SPP_FMT "invalid input packet " 60425944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 60540008Sjoerg SPP_ARGS(ifp), 60625944Sjoerg h->address, h->control, ntohs(h->protocol)); 60725944Sjoerg goto drop; 6084910Swollman } 6094910Swollman 6104910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 6114910Swollman goto drop; 6124910Swollman 6134910Swollman /* Check queue. */ 61469152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 61525944Sjoerg if (debug) 61640008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 61740008Sjoerg SPP_ARGS(ifp)); 6184910Swollman goto drop; 6194910Swollman } 6204910Swollman} 6214910Swollman 6224910Swollman/* 6234910Swollman * Enqueue transmit packet. 6244910Swollman */ 62512820Sphkstatic int 62625706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 62725706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6284910Swollman{ 6294910Swollman struct sppp *sp = (struct sppp*) ifp; 6304910Swollman struct ppp_header *h; 6314910Swollman struct ifqueue *ifq; 63225955Sjoerg int s, rv = 0; 63342066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6344910Swollman 63525944Sjoerg s = splimp(); 63625944Sjoerg 63725944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 63825944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 6394910Swollman m_freem (m); 6404910Swollman splx (s); 6414910Swollman return (ENETDOWN); 6424910Swollman } 6434910Swollman 64425944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 64525944Sjoerg /* 64625944Sjoerg * Interface is not yet running, but auto-dial. Need 64725944Sjoerg * to start LCP for it. 64825944Sjoerg */ 64925944Sjoerg ifp->if_flags |= IFF_RUNNING; 65025944Sjoerg splx(s); 65125944Sjoerg lcp.Open(sp); 65225944Sjoerg s = splimp(); 65325944Sjoerg } 65425944Sjoerg 6554910Swollman ifq = &ifp->if_snd; 6564910Swollman#ifdef INET 65712436Speter if (dst->sa_family == AF_INET) { 65840008Sjoerg /* XXX Check mbuf length here? */ 65912436Speter struct ip *ip = mtod (m, struct ip*); 66012436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6614910Swollman 66242104Sphk /* 66342104Sphk * When using dynamic local IP address assignment by using 66442104Sphk * 0.0.0.0 as a local address, the first TCP session will 66542104Sphk * not connect because the local TCP checksum is computed 66642104Sphk * using 0.0.0.0 which will later become our real IP address 66742104Sphk * so the TCP checksum computed at the remote end will 66842104Sphk * become invalid. So we 66942104Sphk * - don't let packets with src ip addr 0 thru 67042104Sphk * - we flag TCP packets with src ip 0 as an error 67170199Sjhay */ 67242104Sphk 67342104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 67442104Sphk { 67542104Sphk m_freem(m); 67642104Sphk splx(s); 67742104Sphk if(ip->ip_p == IPPROTO_TCP) 67842104Sphk return(EADDRNOTAVAIL); 67942104Sphk else 68042104Sphk return(0); 68142104Sphk } 68270199Sjhay 68342104Sphk /* 68442104Sphk * Put low delay, telnet, rlogin and ftp control packets 68542104Sphk * in front of the queue. 68642104Sphk */ 68769152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 68841686Sphk ; 68941686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 69012436Speter ifq = &sp->pp_fastq; 69141686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 69241686Sphk ; 69341686Sphk else if (ip->ip_p != IPPROTO_TCP) 69441686Sphk ; 69541686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 69641686Sphk ifq = &sp->pp_fastq; 69741686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 69841686Sphk ifq = &sp->pp_fastq; 6994910Swollman } 7004910Swollman#endif 7014910Swollman 7024910Swollman /* 7034910Swollman * Prepend general data packet PPP header. For now, IP only. 7044910Swollman */ 7054910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 7064910Swollman if (! m) { 70742066Sphk if (debug) 70840008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 70940008Sjoerg SPP_ARGS(ifp)); 71025944Sjoerg ++ifp->if_oerrors; 7114910Swollman splx (s); 7124910Swollman return (ENOBUFS); 7134910Swollman } 71440008Sjoerg /* 71540008Sjoerg * May want to check size of packet 71640008Sjoerg * (albeit due to the implementation it's always enough) 71740008Sjoerg */ 7184910Swollman h = mtod (m, struct ppp_header*); 71945152Sphk if (sp->pp_mode == IFF_CISCO) { 72028088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7214910Swollman h->control = 0; 7224910Swollman } else { 7234910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7244910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7254910Swollman } 7264910Swollman 7274910Swollman switch (dst->sa_family) { 7284910Swollman#ifdef INET 7294910Swollman case AF_INET: /* Internet Protocol */ 73045152Sphk if (sp->pp_mode == IFF_CISCO) 73111189Sjkh h->protocol = htons (ETHERTYPE_IP); 73211189Sjkh else { 73325955Sjoerg /* 73425955Sjoerg * Don't choke with an ENETDOWN early. It's 73525955Sjoerg * possible that we just started dialing out, 73625955Sjoerg * so don't drop the packet immediately. If 73725955Sjoerg * we notice that we run out of buffer space 73825955Sjoerg * below, we will however remember that we are 73925955Sjoerg * not ready to carry IP packets, and return 74025955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 74125955Sjoerg */ 74225955Sjoerg h->protocol = htons(PPP_IP); 74325955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 74425955Sjoerg rv = ENETDOWN; 74511189Sjkh } 7464910Swollman break; 7474910Swollman#endif 74854263Sshin#ifdef INET6 74954263Sshin case AF_INET6: /* Internet Protocol */ 75054263Sshin if (sp->pp_mode == IFF_CISCO) 75154263Sshin h->protocol = htons (ETHERTYPE_IPV6); 75254263Sshin else { 75354263Sshin goto nosupport; 75454263Sshin } 75554263Sshin break; 75654263Sshin#endif 7574910Swollman#ifdef NS 7584910Swollman case AF_NS: /* Xerox NS Protocol */ 75945152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 7604910Swollman ETHERTYPE_NS : PPP_XNS); 7614910Swollman break; 7624910Swollman#endif 76311819Sjulian#ifdef IPX 76412495Speter case AF_IPX: /* Novell IPX Protocol */ 76545152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 76612495Speter ETHERTYPE_IPX : PPP_IPX); 76711819Sjulian break; 76811819Sjulian#endif 76912820Sphknosupport: 7704910Swollman default: 7714910Swollman m_freem (m); 77225944Sjoerg ++ifp->if_oerrors; 7734910Swollman splx (s); 7744910Swollman return (EAFNOSUPPORT); 7754910Swollman } 7764910Swollman 7774910Swollman /* 7784910Swollman * Queue message on interface, and start output if interface 77969152Sjlemon * not yet active. Also adjust output byte count. 78069152Sjlemon * The packet length includes header, FCS and 1 flag, 78169152Sjlemon * according to RFC 1333. 7824910Swollman */ 78369152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 78425944Sjoerg ++ifp->if_oerrors; 78525955Sjoerg return (rv? rv: ENOBUFS); 7864910Swollman } 7874910Swollman return (0); 7884910Swollman} 7894910Swollman 79025706Sjoergvoid 79125706Sjoergsppp_attach(struct ifnet *ifp) 7924910Swollman{ 7934910Swollman struct sppp *sp = (struct sppp*) ifp; 7944910Swollman 7954910Swollman /* Initialize keepalive handler. */ 7964910Swollman if (! spppq) 79742064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 7984910Swollman 7994910Swollman /* Insert new entry into the keepalive list. */ 8004910Swollman sp->pp_next = spppq; 8014910Swollman spppq = sp; 8024910Swollman 80342064Sphk sp->pp_if.if_mtu = PP_MTU; 80442064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8054910Swollman sp->pp_if.if_type = IFT_PPP; 8064910Swollman sp->pp_if.if_output = sppp_output; 80742104Sphk#if 0 80842064Sphk sp->pp_flags = PP_KEEPALIVE; 80942104Sphk#endif 81070199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 81170199Sjhay sp->pp_fastq.ifq_maxlen = 32; 81270199Sjhay sp->pp_cpq.ifq_maxlen = 20; 8134910Swollman sp->pp_loopcnt = 0; 8144910Swollman sp->pp_alivecnt = 0; 81511189Sjkh sp->pp_seq = 0; 8164910Swollman sp->pp_rseq = 0; 81725944Sjoerg sp->pp_phase = PHASE_DEAD; 81825944Sjoerg sp->pp_up = lcp.Up; 81925944Sjoerg sp->pp_down = lcp.Down; 82069152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 82169152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 82225944Sjoerg 82325944Sjoerg sppp_lcp_init(sp); 82425944Sjoerg sppp_ipcp_init(sp); 82530300Sjoerg sppp_pap_init(sp); 82630300Sjoerg sppp_chap_init(sp); 8274910Swollman} 8284910Swollman 82930300Sjoergvoid 83025706Sjoergsppp_detach(struct ifnet *ifp) 8314910Swollman{ 8324910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 83325944Sjoerg int i; 8344910Swollman 8354910Swollman /* Remove the entry from the keepalive list. */ 8364910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 8374910Swollman if (p == sp) { 8384910Swollman *q = p->pp_next; 8394910Swollman break; 8404910Swollman } 8414910Swollman 8424910Swollman /* Stop keepalive handler. */ 8434910Swollman if (! spppq) 84440008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 84525944Sjoerg 84625944Sjoerg for (i = 0; i < IDX_COUNT; i++) 84740008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 84840008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 84969152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 85069152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 8514910Swollman} 8524910Swollman 8534910Swollman/* 8544910Swollman * Flush the interface output queue. 8554910Swollman */ 85625706Sjoergvoid 85725706Sjoergsppp_flush(struct ifnet *ifp) 8584910Swollman{ 8594910Swollman struct sppp *sp = (struct sppp*) ifp; 8604910Swollman 86125944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 86225944Sjoerg sppp_qflush (&sp->pp_fastq); 86326018Sjoerg sppp_qflush (&sp->pp_cpq); 8644910Swollman} 8654910Swollman 8664910Swollman/* 86711189Sjkh * Check if the output queue is empty. 86811189Sjkh */ 86912820Sphkint 87025706Sjoergsppp_isempty(struct ifnet *ifp) 87111189Sjkh{ 87211189Sjkh struct sppp *sp = (struct sppp*) ifp; 87325944Sjoerg int empty, s; 87411189Sjkh 87525944Sjoerg s = splimp(); 87626018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 87726018Sjoerg !sp->pp_if.if_snd.ifq_head; 87825944Sjoerg splx(s); 87911189Sjkh return (empty); 88011189Sjkh} 88111189Sjkh 88211189Sjkh/* 8834910Swollman * Get next packet to send. 8844910Swollman */ 88525706Sjoergstruct mbuf * 88625706Sjoergsppp_dequeue(struct ifnet *ifp) 8874910Swollman{ 8884910Swollman struct sppp *sp = (struct sppp*) ifp; 8894910Swollman struct mbuf *m; 89025944Sjoerg int s; 8914910Swollman 89225944Sjoerg s = splimp(); 89326018Sjoerg /* 89430300Sjoerg * Process only the control protocol queue until we have at 89530300Sjoerg * least one NCP open. 89626018Sjoerg * 89726018Sjoerg * Do always serve all three queues in Cisco mode. 89826018Sjoerg */ 89926018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 90026018Sjoerg if (m == NULL && 90145152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 90226018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 90326018Sjoerg if (m == NULL) 90426018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 90526018Sjoerg } 90626018Sjoerg splx(s); 90726018Sjoerg return m; 9084910Swollman} 9094910Swollman 9104910Swollman/* 91130300Sjoerg * Pick the next packet, do not remove it from the queue. 91230300Sjoerg */ 91330300Sjoergstruct mbuf * 91430300Sjoergsppp_pick(struct ifnet *ifp) 91530300Sjoerg{ 91630300Sjoerg struct sppp *sp = (struct sppp*)ifp; 91730300Sjoerg struct mbuf *m; 91830300Sjoerg int s; 91930300Sjoerg 92030300Sjoerg s= splimp (); 92130300Sjoerg 92230300Sjoerg m = sp->pp_cpq.ifq_head; 92330300Sjoerg if (m == NULL && 92445152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 92530300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 92630300Sjoerg m = sp->pp_if.if_snd.ifq_head; 92730300Sjoerg splx (s); 92830300Sjoerg return (m); 92930300Sjoerg} 93030300Sjoerg 93130300Sjoerg/* 93225944Sjoerg * Process an ioctl request. Called on low priority level. 9334910Swollman */ 93425944Sjoergint 93542104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 9364910Swollman{ 93725944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 93825944Sjoerg struct sppp *sp = (struct sppp*) ifp; 93930300Sjoerg int s, rv, going_up, going_down, newmode; 9404910Swollman 94125944Sjoerg s = splimp(); 94230300Sjoerg rv = 0; 94325944Sjoerg switch (cmd) { 94425944Sjoerg case SIOCAIFADDR: 94525944Sjoerg case SIOCSIFDSTADDR: 94625944Sjoerg break; 9474910Swollman 94825944Sjoerg case SIOCSIFADDR: 94925944Sjoerg if_up(ifp); 95025944Sjoerg /* fall through... */ 95111189Sjkh 95225944Sjoerg case SIOCSIFFLAGS: 95325944Sjoerg going_up = ifp->if_flags & IFF_UP && 95425944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 95525944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 95625944Sjoerg ifp->if_flags & IFF_RUNNING; 95745152Sphk 95845152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 95945152Sphk if (!newmode) 96045152Sphk newmode = ifp->if_flags & IFF_AUTO; 96145152Sphk if (!newmode) 96245152Sphk newmode = ifp->if_flags & IFF_CISCO; 96345152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 96445152Sphk ifp->if_flags |= newmode; 96545152Sphk 96645152Sphk if (newmode != sp->pp_mode) { 96745152Sphk going_down = 1; 96845152Sphk if (!going_up) 96945152Sphk going_up = ifp->if_flags & IFF_RUNNING; 9704910Swollman } 9714910Swollman 97245152Sphk if (going_down) { 97370199Sjhay if (sp->pp_mode != IFF_CISCO) 97445152Sphk lcp.Close(sp); 97545152Sphk else if (sp->pp_tlf) 97645152Sphk (sp->pp_tlf)(sp); 97726018Sjoerg sppp_flush(ifp); 97825944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 97945152Sphk sp->pp_mode = newmode; 98026018Sjoerg } 9814910Swollman 98245152Sphk if (going_up) { 98370199Sjhay if (sp->pp_mode != IFF_CISCO) 98445152Sphk lcp.Close(sp); 98545152Sphk sp->pp_mode = newmode; 98645152Sphk if (sp->pp_mode == 0) { 98745152Sphk ifp->if_flags |= IFF_RUNNING; 98845152Sphk lcp.Open(sp); 98945152Sphk } 99045152Sphk if (sp->pp_mode == IFF_CISCO) { 99145152Sphk if (sp->pp_tls) 99245152Sphk (sp->pp_tls)(sp); 99345152Sphk ifp->if_flags |= IFF_RUNNING; 99445152Sphk } 99545152Sphk } 99645152Sphk 9974910Swollman break; 99811189Sjkh 99925944Sjoerg#ifdef SIOCSIFMTU 100025944Sjoerg#ifndef ifr_mtu 100125944Sjoerg#define ifr_mtu ifr_metric 100225944Sjoerg#endif 100325944Sjoerg case SIOCSIFMTU: 100425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 100525944Sjoerg return (EINVAL); 100625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10074910Swollman break; 100825944Sjoerg#endif 100925944Sjoerg#ifdef SLIOCSETMTU 101025944Sjoerg case SLIOCSETMTU: 101125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 101225944Sjoerg return (EINVAL); 101325944Sjoerg ifp->if_mtu = *(short*)data; 10144910Swollman break; 101525944Sjoerg#endif 101625944Sjoerg#ifdef SIOCGIFMTU 101725944Sjoerg case SIOCGIFMTU: 101825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 101911189Sjkh break; 102025944Sjoerg#endif 102125944Sjoerg#ifdef SLIOCGETMTU 102225944Sjoerg case SLIOCGETMTU: 102325944Sjoerg *(short*)data = ifp->if_mtu; 10244910Swollman break; 102525944Sjoerg#endif 102625944Sjoerg case SIOCADDMULTI: 102725944Sjoerg case SIOCDELMULTI: 10284910Swollman break; 102911189Sjkh 103030300Sjoerg case SIOCGIFGENERIC: 103130300Sjoerg case SIOCSIFGENERIC: 103230300Sjoerg rv = sppp_params(sp, cmd, data); 103330300Sjoerg break; 103430300Sjoerg 103525944Sjoerg default: 103630300Sjoerg rv = ENOTTY; 10374910Swollman } 103825944Sjoerg splx(s); 103930300Sjoerg return rv; 10404910Swollman} 10414910Swollman 104270199Sjhay/* 104325944Sjoerg * Cisco framing implementation. 104425944Sjoerg */ 104525944Sjoerg 10464910Swollman/* 10474910Swollman * Handle incoming Cisco keepalive protocol packets. 10484910Swollman */ 104930300Sjoergstatic void 105025706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 10514910Swollman{ 105225944Sjoerg STDDCL; 10534910Swollman struct cisco_packet *h; 105430300Sjoerg u_long me, mymask; 10554910Swollman 105627929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 105725706Sjoerg if (debug) 105825706Sjoerg log(LOG_DEBUG, 105940008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 106040008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 10614910Swollman return; 10624910Swollman } 10634910Swollman h = mtod (m, struct cisco_packet*); 106425706Sjoerg if (debug) 106525706Sjoerg log(LOG_DEBUG, 106640008Sjoerg SPP_FMT "cisco input: %d bytes " 106725706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 106840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 106940008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 107040008Sjoerg (u_int)h->time0, (u_int)h->time1); 10714910Swollman switch (ntohl (h->type)) { 10724910Swollman default: 107325706Sjoerg if (debug) 107469211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 107540008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 10764910Swollman break; 10774910Swollman case CISCO_ADDR_REPLY: 10784910Swollman /* Reply on address request, ignore */ 10794910Swollman break; 10804910Swollman case CISCO_KEEPALIVE_REQ: 10814910Swollman sp->pp_alivecnt = 0; 10824910Swollman sp->pp_rseq = ntohl (h->par1); 10834910Swollman if (sp->pp_seq == sp->pp_rseq) { 10844910Swollman /* Local and remote sequence numbers are equal. 10854910Swollman * Probably, the line is in loopback mode. */ 108611189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 108740008Sjoerg printf (SPP_FMT "loopback\n", 108840008Sjoerg SPP_ARGS(ifp)); 108911189Sjkh sp->pp_loopcnt = 0; 109011189Sjkh if (ifp->if_flags & IFF_UP) { 109111189Sjkh if_down (ifp); 109226018Sjoerg sppp_qflush (&sp->pp_cpq); 109311189Sjkh } 109411189Sjkh } 10954910Swollman ++sp->pp_loopcnt; 10964910Swollman 10974910Swollman /* Generate new local sequence number */ 109842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 109935064Sphk sp->pp_seq = random(); 110040008Sjoerg#else 110140008Sjoerg sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 110240008Sjoerg#endif 110311189Sjkh break; 110411189Sjkh } 110530300Sjoerg sp->pp_loopcnt = 0; 110611189Sjkh if (! (ifp->if_flags & IFF_UP) && 110711189Sjkh (ifp->if_flags & IFF_RUNNING)) { 110830300Sjoerg if_up(ifp); 110940008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 111011189Sjkh } 11114910Swollman break; 11124910Swollman case CISCO_ADDR_REQ: 111330300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 111430300Sjoerg if (me != 0L) 111530300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11164910Swollman break; 11174910Swollman } 11184910Swollman} 11194910Swollman 11204910Swollman/* 112125944Sjoerg * Send Cisco keepalive packet. 11224910Swollman */ 112312820Sphkstatic void 112425944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 112525944Sjoerg{ 112625944Sjoerg STDDCL; 112725944Sjoerg struct ppp_header *h; 112825944Sjoerg struct cisco_packet *ch; 112925944Sjoerg struct mbuf *m; 113042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113135029Sphk struct timeval tv; 113240008Sjoerg#else 113340008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 113440008Sjoerg#endif 113525944Sjoerg 113642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113736119Sphk getmicrouptime(&tv); 113840008Sjoerg#endif 113970199Sjhay 114025944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 114125944Sjoerg if (! m) 114225944Sjoerg return; 114325944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 114425944Sjoerg m->m_pkthdr.rcvif = 0; 114525944Sjoerg 114625944Sjoerg h = mtod (m, struct ppp_header*); 114725944Sjoerg h->address = CISCO_MULTICAST; 114825944Sjoerg h->control = 0; 114925944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 115025944Sjoerg 115125944Sjoerg ch = (struct cisco_packet*) (h + 1); 115225944Sjoerg ch->type = htonl (type); 115325944Sjoerg ch->par1 = htonl (par1); 115425944Sjoerg ch->par2 = htonl (par2); 115525944Sjoerg ch->rel = -1; 115640008Sjoerg 115742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 115835029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 115935029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 116040008Sjoerg#else 116140008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 116240008Sjoerg ch->time1 = htons ((u_short) t); 116340008Sjoerg#endif 116425944Sjoerg 116525944Sjoerg if (debug) 116625944Sjoerg log(LOG_DEBUG, 116740008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 116840008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 116940008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 117025944Sjoerg 117169152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 117269152Sjlemon ifp->if_oerrors++; 117325944Sjoerg} 117425944Sjoerg 117570199Sjhay/* 117625944Sjoerg * PPP protocol implementation. 117725944Sjoerg */ 117825944Sjoerg 117925944Sjoerg/* 118025944Sjoerg * Send PPP control protocol packet. 118125944Sjoerg */ 118225944Sjoergstatic void 118325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 118425706Sjoerg u_char ident, u_short len, void *data) 11854910Swollman{ 118625944Sjoerg STDDCL; 11874910Swollman struct ppp_header *h; 11884910Swollman struct lcp_header *lh; 11894910Swollman struct mbuf *m; 11904910Swollman 11914910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 11924910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 11934910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 11944910Swollman if (! m) 11954910Swollman return; 11964910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 11974910Swollman m->m_pkthdr.rcvif = 0; 11984910Swollman 11994910Swollman h = mtod (m, struct ppp_header*); 12004910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12014910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12024910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12034910Swollman 12044910Swollman lh = (struct lcp_header*) (h + 1); 12054910Swollman lh->type = type; 12064910Swollman lh->ident = ident; 12074910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12084910Swollman if (len) 12094910Swollman bcopy (data, lh+1, len); 12104910Swollman 121125706Sjoerg if (debug) { 121240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 121340008Sjoerg SPP_ARGS(ifp), 121425944Sjoerg sppp_proto_name(proto), 121525944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 121625944Sjoerg ntohs (lh->len)); 121744145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 121869211Sphk log(-1, ">\n"); 12194910Swollman } 122069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 122169152Sjlemon ifp->if_oerrors++; 12224910Swollman} 12234910Swollman 12244910Swollman/* 122525944Sjoerg * Handle incoming PPP control protocol packets. 12264910Swollman */ 122712820Sphkstatic void 122825944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 12294910Swollman{ 123025944Sjoerg STDDCL; 123125944Sjoerg struct lcp_header *h; 123225944Sjoerg int len = m->m_pkthdr.len; 123325944Sjoerg int rv; 123425944Sjoerg u_char *p; 12354910Swollman 123625944Sjoerg if (len < 4) { 123725944Sjoerg if (debug) 123825944Sjoerg log(LOG_DEBUG, 123940008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 124040008Sjoerg SPP_ARGS(ifp), cp->name, len); 12414910Swollman return; 124225944Sjoerg } 124325944Sjoerg h = mtod (m, struct lcp_header*); 124425944Sjoerg if (debug) { 124525944Sjoerg log(LOG_DEBUG, 124640008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 124740008Sjoerg SPP_ARGS(ifp), cp->name, 124825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 124925944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 125044145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 125169211Sphk log(-1, ">\n"); 125225944Sjoerg } 125325944Sjoerg if (len > ntohs (h->len)) 125425944Sjoerg len = ntohs (h->len); 125530300Sjoerg p = (u_char *)(h + 1); 125625944Sjoerg switch (h->type) { 125725944Sjoerg case CONF_REQ: 125825944Sjoerg if (len < 4) { 125925944Sjoerg if (debug) 126069211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 126140008Sjoerg SPP_ARGS(ifp), cp->name, 126225944Sjoerg len); 126325944Sjoerg ++ifp->if_ierrors; 126425944Sjoerg break; 126525944Sjoerg } 126630300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 126730300Sjoerg switch (sp->state[cp->protoidx]) { 126830300Sjoerg case STATE_CLOSING: 126930300Sjoerg case STATE_STOPPING: 127030300Sjoerg return; 127130300Sjoerg case STATE_CLOSED: 127230300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 127330300Sjoerg 0, 0); 127430300Sjoerg return; 127530300Sjoerg } 127625944Sjoerg rv = (cp->RCR)(sp, h, len); 127725944Sjoerg switch (sp->state[cp->protoidx]) { 127825944Sjoerg case STATE_OPENED: 127925944Sjoerg (cp->tld)(sp); 128025944Sjoerg (cp->scr)(sp); 128125944Sjoerg /* fall through... */ 128225944Sjoerg case STATE_ACK_SENT: 128325944Sjoerg case STATE_REQ_SENT: 128470199Sjhay /* 128570199Sjhay * sppp_cp_change_state() have the side effect of 128670199Sjhay * restarting the timeouts. We want to avoid that 128770199Sjhay * if the state don't change, otherwise we won't 128870199Sjhay * ever timeout and resend a configuration request 128970199Sjhay * that got lost. 129070199Sjhay */ 129170199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 129270199Sjhay STATE_REQ_SENT)) 129370199Sjhay break; 129425944Sjoerg sppp_cp_change_state(cp, sp, rv? 129525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 129625944Sjoerg break; 129725944Sjoerg case STATE_STOPPED: 129825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 129925944Sjoerg (cp->scr)(sp); 130025944Sjoerg sppp_cp_change_state(cp, sp, rv? 130125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 130225944Sjoerg break; 130325944Sjoerg case STATE_ACK_RCVD: 130425944Sjoerg if (rv) { 130525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 130625944Sjoerg if (debug) 130740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 130840008Sjoerg SPP_ARGS(ifp), 130926077Sjoerg cp->name); 131025944Sjoerg (cp->tlu)(sp); 131125944Sjoerg } else 131225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 131325944Sjoerg break; 131425944Sjoerg default: 131540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 131640008Sjoerg SPP_ARGS(ifp), cp->name, 131725944Sjoerg sppp_cp_type_name(h->type), 131825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 131925944Sjoerg ++ifp->if_ierrors; 132025944Sjoerg } 132125944Sjoerg break; 132225944Sjoerg case CONF_ACK: 132325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 132425944Sjoerg if (debug) 132569211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 132640008Sjoerg SPP_ARGS(ifp), cp->name, 132725944Sjoerg h->ident, sp->confid[cp->protoidx]); 132825944Sjoerg ++ifp->if_ierrors; 132925944Sjoerg break; 133025944Sjoerg } 133125944Sjoerg switch (sp->state[cp->protoidx]) { 133225944Sjoerg case STATE_CLOSED: 133325944Sjoerg case STATE_STOPPED: 133425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 133525944Sjoerg break; 133625944Sjoerg case STATE_CLOSING: 133725944Sjoerg case STATE_STOPPING: 133825944Sjoerg break; 133925944Sjoerg case STATE_REQ_SENT: 134025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 134125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 134225944Sjoerg break; 134325944Sjoerg case STATE_OPENED: 134425944Sjoerg (cp->tld)(sp); 134525944Sjoerg /* fall through */ 134625944Sjoerg case STATE_ACK_RCVD: 134725944Sjoerg (cp->scr)(sp); 134825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 134925944Sjoerg break; 135025944Sjoerg case STATE_ACK_SENT: 135125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 135225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 135325944Sjoerg if (debug) 135440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 135540008Sjoerg SPP_ARGS(ifp), cp->name); 135625944Sjoerg (cp->tlu)(sp); 135725944Sjoerg break; 135825944Sjoerg default: 135940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 136040008Sjoerg SPP_ARGS(ifp), cp->name, 136125944Sjoerg sppp_cp_type_name(h->type), 136225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 136325944Sjoerg ++ifp->if_ierrors; 136425944Sjoerg } 136525944Sjoerg break; 136625944Sjoerg case CONF_NAK: 136725944Sjoerg case CONF_REJ: 136825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 136925944Sjoerg if (debug) 137069211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 137140008Sjoerg SPP_ARGS(ifp), cp->name, 137225944Sjoerg h->ident, sp->confid[cp->protoidx]); 137325944Sjoerg ++ifp->if_ierrors; 137425944Sjoerg break; 137525944Sjoerg } 137625944Sjoerg if (h->type == CONF_NAK) 137725944Sjoerg (cp->RCN_nak)(sp, h, len); 137825944Sjoerg else /* CONF_REJ */ 137925944Sjoerg (cp->RCN_rej)(sp, h, len); 13804910Swollman 138125944Sjoerg switch (sp->state[cp->protoidx]) { 138225944Sjoerg case STATE_CLOSED: 138325944Sjoerg case STATE_STOPPED: 138425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 138525944Sjoerg break; 138625944Sjoerg case STATE_REQ_SENT: 138725944Sjoerg case STATE_ACK_SENT: 138825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 138970199Sjhay /* 139070199Sjhay * Slow things down a bit if we think we might be 139170199Sjhay * in loopback. Depend on the timeout to send the 139270199Sjhay * next configuration request. 139370199Sjhay */ 139470199Sjhay if (sp->pp_loopcnt) 139570199Sjhay break; 139625944Sjoerg (cp->scr)(sp); 139725944Sjoerg break; 139825944Sjoerg case STATE_OPENED: 139925944Sjoerg (cp->tld)(sp); 140025944Sjoerg /* fall through */ 140125944Sjoerg case STATE_ACK_RCVD: 140252633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 140325944Sjoerg (cp->scr)(sp); 140425944Sjoerg break; 140525944Sjoerg case STATE_CLOSING: 140625944Sjoerg case STATE_STOPPING: 140725944Sjoerg break; 140825944Sjoerg default: 140940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 141040008Sjoerg SPP_ARGS(ifp), cp->name, 141125944Sjoerg sppp_cp_type_name(h->type), 141225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 141325944Sjoerg ++ifp->if_ierrors; 141425944Sjoerg } 141525944Sjoerg break; 14164910Swollman 141725944Sjoerg case TERM_REQ: 141825944Sjoerg switch (sp->state[cp->protoidx]) { 141925944Sjoerg case STATE_ACK_RCVD: 142025944Sjoerg case STATE_ACK_SENT: 142125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142225944Sjoerg /* fall through */ 142325944Sjoerg case STATE_CLOSED: 142425944Sjoerg case STATE_STOPPED: 142525944Sjoerg case STATE_CLOSING: 142625944Sjoerg case STATE_STOPPING: 142725944Sjoerg case STATE_REQ_SENT: 142825944Sjoerg sta: 142925944Sjoerg /* Send Terminate-Ack packet. */ 143025944Sjoerg if (debug) 143140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 143240008Sjoerg SPP_ARGS(ifp), cp->name); 143325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 143425944Sjoerg break; 143525944Sjoerg case STATE_OPENED: 143625944Sjoerg (cp->tld)(sp); 143725944Sjoerg sp->rst_counter[cp->protoidx] = 0; 143825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 143925944Sjoerg goto sta; 144025944Sjoerg break; 144125944Sjoerg default: 144240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 144340008Sjoerg SPP_ARGS(ifp), cp->name, 144425944Sjoerg sppp_cp_type_name(h->type), 144525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144625944Sjoerg ++ifp->if_ierrors; 144725944Sjoerg } 144825944Sjoerg break; 144925944Sjoerg case TERM_ACK: 145025944Sjoerg switch (sp->state[cp->protoidx]) { 145125944Sjoerg case STATE_CLOSED: 145225944Sjoerg case STATE_STOPPED: 145325944Sjoerg case STATE_REQ_SENT: 145425944Sjoerg case STATE_ACK_SENT: 145525944Sjoerg break; 145625944Sjoerg case STATE_CLOSING: 145741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 145825944Sjoerg (cp->tlf)(sp); 145925944Sjoerg break; 146025944Sjoerg case STATE_STOPPING: 146141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 146225944Sjoerg (cp->tlf)(sp); 146325944Sjoerg break; 146425944Sjoerg case STATE_ACK_RCVD: 146525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 146625944Sjoerg break; 146725944Sjoerg case STATE_OPENED: 146825944Sjoerg (cp->tld)(sp); 146925944Sjoerg (cp->scr)(sp); 147025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 147125944Sjoerg break; 147225944Sjoerg default: 147340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 147440008Sjoerg SPP_ARGS(ifp), cp->name, 147525944Sjoerg sppp_cp_type_name(h->type), 147625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 147725944Sjoerg ++ifp->if_ierrors; 147825944Sjoerg } 147925944Sjoerg break; 148025944Sjoerg case CODE_REJ: 148125944Sjoerg case PROTO_REJ: 148225944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 148330300Sjoerg log(LOG_INFO, 148440008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 148530300Sjoerg "danger will robinson\n", 148640008Sjoerg SPP_ARGS(ifp), cp->name, 148730300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 148825944Sjoerg switch (sp->state[cp->protoidx]) { 148925944Sjoerg case STATE_CLOSED: 149025944Sjoerg case STATE_STOPPED: 149125944Sjoerg case STATE_REQ_SENT: 149225944Sjoerg case STATE_ACK_SENT: 149325944Sjoerg case STATE_CLOSING: 149425944Sjoerg case STATE_STOPPING: 149525944Sjoerg case STATE_OPENED: 149625944Sjoerg break; 149725944Sjoerg case STATE_ACK_RCVD: 149825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 149925944Sjoerg break; 150025944Sjoerg default: 150140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 150240008Sjoerg SPP_ARGS(ifp), cp->name, 150325944Sjoerg sppp_cp_type_name(h->type), 150425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 150525944Sjoerg ++ifp->if_ierrors; 150625944Sjoerg } 150725944Sjoerg break; 150825944Sjoerg case DISC_REQ: 150925944Sjoerg if (cp->proto != PPP_LCP) 151025944Sjoerg goto illegal; 151125944Sjoerg /* Discard the packet. */ 151225944Sjoerg break; 151325944Sjoerg case ECHO_REQ: 151425944Sjoerg if (cp->proto != PPP_LCP) 151525944Sjoerg goto illegal; 151625944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 151725944Sjoerg if (debug) 151869211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 151940008Sjoerg SPP_ARGS(ifp)); 152025944Sjoerg ++ifp->if_ierrors; 152125944Sjoerg break; 152225944Sjoerg } 152325944Sjoerg if (len < 8) { 152425944Sjoerg if (debug) 152569211Sphk log(-1, SPP_FMT "invalid lcp echo request " 152625944Sjoerg "packet length: %d bytes\n", 152740008Sjoerg SPP_ARGS(ifp), len); 152825944Sjoerg break; 152925944Sjoerg } 153044145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 153144145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 153225944Sjoerg /* Line loopback mode detected. */ 153340008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 153470199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 153525944Sjoerg if_down (ifp); 153626018Sjoerg sppp_qflush (&sp->pp_cpq); 15374910Swollman 153825944Sjoerg /* Shut down the PPP link. */ 153925944Sjoerg /* XXX */ 154025944Sjoerg lcp.Down(sp); 154125944Sjoerg lcp.Up(sp); 154225944Sjoerg break; 154325944Sjoerg } 154425944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 154525944Sjoerg if (debug) 154669211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 154740008Sjoerg SPP_ARGS(ifp)); 154825944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 154925944Sjoerg break; 155025944Sjoerg case ECHO_REPLY: 155125944Sjoerg if (cp->proto != PPP_LCP) 155225944Sjoerg goto illegal; 155325944Sjoerg if (h->ident != sp->lcp.echoid) { 155425944Sjoerg ++ifp->if_ierrors; 155525944Sjoerg break; 155625944Sjoerg } 155725944Sjoerg if (len < 8) { 155825944Sjoerg if (debug) 155969211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 156025944Sjoerg "packet length: %d bytes\n", 156140008Sjoerg SPP_ARGS(ifp), len); 156225944Sjoerg break; 156325944Sjoerg } 156425944Sjoerg if (debug) 156569211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 156640008Sjoerg SPP_ARGS(ifp)); 156744145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 156844145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 156925944Sjoerg sp->pp_alivecnt = 0; 157025944Sjoerg break; 157125944Sjoerg default: 157225944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 157325944Sjoerg illegal: 157425944Sjoerg if (debug) 157569211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 157640008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 157725944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 157825944Sjoerg m->m_pkthdr.len, h); 157925944Sjoerg ++ifp->if_ierrors; 158025944Sjoerg } 15814910Swollman} 15824910Swollman 158325944Sjoerg 15844910Swollman/* 158525944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 158625944Sjoerg * Basically, the state transition handling in the automaton. 15874910Swollman */ 158825944Sjoergstatic void 158925944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 15904910Swollman{ 159125944Sjoerg STDDCL; 15924910Swollman 159325944Sjoerg if (debug) 159440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 159540008Sjoerg SPP_ARGS(ifp), cp->name, 159625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 159725944Sjoerg 159825944Sjoerg switch (sp->state[cp->protoidx]) { 159925944Sjoerg case STATE_INITIAL: 160025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 160125944Sjoerg break; 160225944Sjoerg case STATE_STARTING: 160325944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 160425944Sjoerg (cp->scr)(sp); 160525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 160625944Sjoerg break; 16074910Swollman default: 160840008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 160940008Sjoerg SPP_ARGS(ifp), cp->name, 161025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 161125944Sjoerg } 161225944Sjoerg} 16134910Swollman 161425944Sjoergstatic void 161525944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 161625944Sjoerg{ 161725944Sjoerg STDDCL; 161825944Sjoerg 161925944Sjoerg if (debug) 162040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 162140008Sjoerg SPP_ARGS(ifp), cp->name, 162225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 162325944Sjoerg 162425944Sjoerg switch (sp->state[cp->protoidx]) { 162525944Sjoerg case STATE_CLOSED: 162625944Sjoerg case STATE_CLOSING: 162725944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 16284910Swollman break; 162925944Sjoerg case STATE_STOPPED: 163041881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 163125944Sjoerg (cp->tls)(sp); 163241881Sphk break; 163325944Sjoerg case STATE_STOPPING: 163425944Sjoerg case STATE_REQ_SENT: 163525944Sjoerg case STATE_ACK_RCVD: 163625944Sjoerg case STATE_ACK_SENT: 163725944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 163825944Sjoerg break; 163925944Sjoerg case STATE_OPENED: 164025944Sjoerg (cp->tld)(sp); 164125944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 164225944Sjoerg break; 164325944Sjoerg default: 164440008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 164540008Sjoerg SPP_ARGS(ifp), cp->name, 164625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164725944Sjoerg } 164825944Sjoerg} 16494910Swollman 165011189Sjkh 165125944Sjoergstatic void 165225944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 165325944Sjoerg{ 165425944Sjoerg STDDCL; 165525944Sjoerg 165625944Sjoerg if (debug) 165740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 165840008Sjoerg SPP_ARGS(ifp), cp->name, 165925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166025944Sjoerg 166125944Sjoerg switch (sp->state[cp->protoidx]) { 166225944Sjoerg case STATE_INITIAL: 166341881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 166425944Sjoerg (cp->tls)(sp); 16654910Swollman break; 166625944Sjoerg case STATE_STARTING: 166725944Sjoerg break; 166825944Sjoerg case STATE_CLOSED: 166925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 167025944Sjoerg (cp->scr)(sp); 167125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 167225944Sjoerg break; 167325944Sjoerg case STATE_STOPPED: 167474703Sjoerg /* 167574703Sjoerg * Try escaping stopped state. This seems to bite 167674703Sjoerg * people occasionally, in particular for IPCP, 167774703Sjoerg * presumably following previous IPCP negotiation 167874703Sjoerg * aborts. Somehow, we must have missed a Down event 167974703Sjoerg * which would have caused a transition into starting 168074703Sjoerg * state, so as a bandaid we force the Down event now. 168174703Sjoerg * This effectively implements (something like the) 168274703Sjoerg * `restart' option mentioned in the state transition 168374703Sjoerg * table of RFC 1661. 168474703Sjoerg */ 168574703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 168674703Sjoerg (cp->tls)(sp); 168774703Sjoerg break; 168825944Sjoerg case STATE_STOPPING: 168925944Sjoerg case STATE_REQ_SENT: 169025944Sjoerg case STATE_ACK_RCVD: 169125944Sjoerg case STATE_ACK_SENT: 169225944Sjoerg case STATE_OPENED: 169325944Sjoerg break; 169425944Sjoerg case STATE_CLOSING: 169525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 169625944Sjoerg break; 169725944Sjoerg } 169825944Sjoerg} 16994910Swollman 170025944Sjoerg 170125944Sjoergstatic void 170225944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 170325944Sjoerg{ 170425944Sjoerg STDDCL; 170525944Sjoerg 170625944Sjoerg if (debug) 170740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 170840008Sjoerg SPP_ARGS(ifp), cp->name, 170925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 171025944Sjoerg 171125944Sjoerg switch (sp->state[cp->protoidx]) { 171225944Sjoerg case STATE_INITIAL: 171325944Sjoerg case STATE_CLOSED: 171425944Sjoerg case STATE_CLOSING: 17154910Swollman break; 171625944Sjoerg case STATE_STARTING: 171741881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 171825944Sjoerg (cp->tlf)(sp); 17194910Swollman break; 172025944Sjoerg case STATE_STOPPED: 172125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 17224910Swollman break; 172325944Sjoerg case STATE_STOPPING: 172425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 17254910Swollman break; 172625944Sjoerg case STATE_OPENED: 172725944Sjoerg (cp->tld)(sp); 172825944Sjoerg /* fall through */ 172925944Sjoerg case STATE_REQ_SENT: 173025944Sjoerg case STATE_ACK_RCVD: 173125944Sjoerg case STATE_ACK_SENT: 173225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 173325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 173425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 17354910Swollman break; 17364910Swollman } 17374910Swollman} 17384910Swollman 173925944Sjoergstatic void 174025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 174125944Sjoerg{ 174225944Sjoerg STDDCL; 174325944Sjoerg int s; 174425944Sjoerg 174525944Sjoerg s = splimp(); 174625944Sjoerg if (debug) 174740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 174840008Sjoerg SPP_ARGS(ifp), cp->name, 174925944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 175025944Sjoerg sp->rst_counter[cp->protoidx]); 175125944Sjoerg 175225944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 175325944Sjoerg /* TO- event */ 175425944Sjoerg switch (sp->state[cp->protoidx]) { 175525944Sjoerg case STATE_CLOSING: 175641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 175725944Sjoerg (cp->tlf)(sp); 175825944Sjoerg break; 175925944Sjoerg case STATE_STOPPING: 176041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 176125944Sjoerg (cp->tlf)(sp); 176225944Sjoerg break; 176325944Sjoerg case STATE_REQ_SENT: 176425944Sjoerg case STATE_ACK_RCVD: 176525944Sjoerg case STATE_ACK_SENT: 176641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 176725944Sjoerg (cp->tlf)(sp); 176825944Sjoerg break; 176925944Sjoerg } 177025944Sjoerg else 177125944Sjoerg /* TO+ event */ 177225944Sjoerg switch (sp->state[cp->protoidx]) { 177325944Sjoerg case STATE_CLOSING: 177425944Sjoerg case STATE_STOPPING: 177525944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 177625944Sjoerg 0, 0); 177770199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 177842064Sphk sp->ch[cp->protoidx]); 177925944Sjoerg break; 178025944Sjoerg case STATE_REQ_SENT: 178125944Sjoerg case STATE_ACK_RCVD: 178225944Sjoerg (cp->scr)(sp); 178325944Sjoerg /* sppp_cp_change_state() will restart the timer */ 178425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 178525944Sjoerg break; 178625944Sjoerg case STATE_ACK_SENT: 178725944Sjoerg (cp->scr)(sp); 178842064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 178942064Sphk sp->ch[cp->protoidx]); 179025944Sjoerg break; 179125944Sjoerg } 179225944Sjoerg 179325944Sjoerg splx(s); 179425944Sjoerg} 179525944Sjoerg 179611189Sjkh/* 179725944Sjoerg * Change the state of a control protocol in the state automaton. 179825944Sjoerg * Takes care of starting/stopping the restart timer. 179911189Sjkh */ 180025944Sjoergvoid 180125944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 180225944Sjoerg{ 180325944Sjoerg sp->state[cp->protoidx] = newstate; 180425944Sjoerg 180540008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 180625944Sjoerg switch (newstate) { 180725944Sjoerg case STATE_INITIAL: 180825944Sjoerg case STATE_STARTING: 180925944Sjoerg case STATE_CLOSED: 181025944Sjoerg case STATE_STOPPED: 181125944Sjoerg case STATE_OPENED: 181225944Sjoerg break; 181325944Sjoerg case STATE_CLOSING: 181425944Sjoerg case STATE_STOPPING: 181525944Sjoerg case STATE_REQ_SENT: 181625944Sjoerg case STATE_ACK_RCVD: 181725944Sjoerg case STATE_ACK_SENT: 181870199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 181942064Sphk sp->ch[cp->protoidx]); 182025944Sjoerg break; 182125944Sjoerg } 182225944Sjoerg} 182370199Sjhay 182470199Sjhay/* 182525944Sjoerg *--------------------------------------------------------------------------* 182625944Sjoerg * * 182725944Sjoerg * The LCP implementation. * 182825944Sjoerg * * 182925944Sjoerg *--------------------------------------------------------------------------* 183025944Sjoerg */ 183125944Sjoergstatic void 183225944Sjoergsppp_lcp_init(struct sppp *sp) 183325944Sjoerg{ 183425944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 183525944Sjoerg sp->lcp.magic = 0; 183625944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 183725944Sjoerg sp->fail_counter[IDX_LCP] = 0; 183825944Sjoerg sp->lcp.protos = 0; 183925944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 184030300Sjoerg 184144145Sphk /* Note that these values are relevant for all control protocols */ 184244145Sphk sp->lcp.timeout = 3 * hz; 184325944Sjoerg sp->lcp.max_terminate = 2; 184425944Sjoerg sp->lcp.max_configure = 10; 184525944Sjoerg sp->lcp.max_failure = 10; 184642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 184730300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 184840008Sjoerg#endif 184925944Sjoerg} 185025944Sjoerg 185125944Sjoergstatic void 185225944Sjoergsppp_lcp_up(struct sppp *sp) 185325944Sjoerg{ 185425944Sjoerg STDDCL; 185525944Sjoerg 185670199Sjhay sp->pp_alivecnt = 0; 185770199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 185870199Sjhay sp->lcp.magic = 0; 185970199Sjhay sp->lcp.protos = 0; 186070199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 186125944Sjoerg /* 186230300Sjoerg * If this interface is passive or dial-on-demand, and we are 186330300Sjoerg * still in Initial state, it means we've got an incoming 186430300Sjoerg * call. Activate the interface. 186525944Sjoerg */ 186625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 186725944Sjoerg if (debug) 186825944Sjoerg log(LOG_DEBUG, 186940008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 187025944Sjoerg ifp->if_flags |= IFF_RUNNING; 187130300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 187230300Sjoerg if (debug) 187369211Sphk log(-1, "(incoming call)\n"); 187430300Sjoerg sp->pp_flags |= PP_CALLIN; 187530300Sjoerg lcp.Open(sp); 187630300Sjoerg } else if (debug) 187769211Sphk log(-1, "\n"); 187825944Sjoerg } 187925944Sjoerg 188025944Sjoerg sppp_up_event(&lcp, sp); 188125944Sjoerg} 188225944Sjoerg 188325944Sjoergstatic void 188425944Sjoergsppp_lcp_down(struct sppp *sp) 188525944Sjoerg{ 188625944Sjoerg STDDCL; 188725944Sjoerg 188825944Sjoerg sppp_down_event(&lcp, sp); 188925944Sjoerg 189025944Sjoerg /* 189125944Sjoerg * If this is neither a dial-on-demand nor a passive 189225944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 189325944Sjoerg * administrator can force a redial by another ``ifconfig 189425944Sjoerg * up''. XXX For leased line operation, should we immediately 189525944Sjoerg * try to reopen the connection here? 189625944Sjoerg */ 189725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 189825944Sjoerg log(LOG_INFO, 189942066Sphk SPP_FMT "Down event, taking interface down.\n", 190040008Sjoerg SPP_ARGS(ifp)); 190125944Sjoerg if_down(ifp); 190225944Sjoerg } else { 190325944Sjoerg if (debug) 190425944Sjoerg log(LOG_DEBUG, 190540008Sjoerg SPP_FMT "Down event (carrier loss)\n", 190640008Sjoerg SPP_ARGS(ifp)); 190770199Sjhay sp->pp_flags &= ~PP_CALLIN; 190870199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 190970199Sjhay lcp.Close(sp); 191070199Sjhay ifp->if_flags &= ~IFF_RUNNING; 191125944Sjoerg } 191225944Sjoerg} 191325944Sjoerg 191425944Sjoergstatic void 191525944Sjoergsppp_lcp_open(struct sppp *sp) 191625944Sjoerg{ 191730300Sjoerg /* 191830300Sjoerg * If we are authenticator, negotiate LCP_AUTH 191930300Sjoerg */ 192030300Sjoerg if (sp->hisauth.proto != 0) 192130300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 192230300Sjoerg else 192330300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 192430300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 192525944Sjoerg sppp_open_event(&lcp, sp); 192625944Sjoerg} 192725944Sjoerg 192825944Sjoergstatic void 192925944Sjoergsppp_lcp_close(struct sppp *sp) 193025944Sjoerg{ 193125944Sjoerg sppp_close_event(&lcp, sp); 193225944Sjoerg} 193325944Sjoerg 193425944Sjoergstatic void 193525944Sjoergsppp_lcp_TO(void *cookie) 193625944Sjoerg{ 193725944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 193825944Sjoerg} 193925944Sjoerg 194025944Sjoerg/* 194125944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 194225944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 194325944Sjoerg * caused action scn. (The return value is used to make the state 194425944Sjoerg * transition decision in the state automaton.) 194525944Sjoerg */ 194612820Sphkstatic int 194725944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 19484910Swollman{ 194925944Sjoerg STDDCL; 195011189Sjkh u_char *buf, *r, *p; 195125944Sjoerg int origlen, rlen; 195225944Sjoerg u_long nmagic; 195330300Sjoerg u_short authproto; 19544910Swollman 195511189Sjkh len -= 4; 195625944Sjoerg origlen = len; 195711189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 195811189Sjkh if (! buf) 195911189Sjkh return (0); 19604910Swollman 196125706Sjoerg if (debug) 196240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 196340008Sjoerg SPP_ARGS(ifp)); 196425706Sjoerg 196525944Sjoerg /* pass 1: check for things that need to be rejected */ 196611189Sjkh p = (void*) (h+1); 196711189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 196825944Sjoerg if (debug) 196969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 197011189Sjkh switch (*p) { 197111189Sjkh case LCP_OPT_MAGIC: 197225944Sjoerg /* Magic number. */ 197370199Sjhay if (len >= 6 && p[1] == 6) 197470199Sjhay continue; 197570199Sjhay if (debug) 197670199Sjhay log(-1, "[invalid] "); 197770199Sjhay break; 197825944Sjoerg case LCP_OPT_ASYNC_MAP: 197925944Sjoerg /* Async control character map. */ 198070199Sjhay if (len >= 6 && p[1] == 6) 198125944Sjoerg continue; 198225944Sjoerg if (debug) 198369211Sphk log(-1, "[invalid] "); 198425944Sjoerg break; 198525944Sjoerg case LCP_OPT_MRU: 198625944Sjoerg /* Maximum receive unit. */ 198725944Sjoerg if (len >= 4 && p[1] == 4) 198825944Sjoerg continue; 198925944Sjoerg if (debug) 199069211Sphk log(-1, "[invalid] "); 199125944Sjoerg break; 199230300Sjoerg case LCP_OPT_AUTH_PROTO: 199330300Sjoerg if (len < 4) { 199430300Sjoerg if (debug) 199569211Sphk log(-1, "[invalid] "); 199630300Sjoerg break; 199730300Sjoerg } 199830300Sjoerg authproto = (p[2] << 8) + p[3]; 199930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 200030300Sjoerg if (debug) 200169211Sphk log(-1, "[invalid chap len] "); 200230300Sjoerg break; 200330300Sjoerg } 200430300Sjoerg if (sp->myauth.proto == 0) { 200530300Sjoerg /* we are not configured to do auth */ 200630300Sjoerg if (debug) 200769211Sphk log(-1, "[not configured] "); 200830300Sjoerg break; 200930300Sjoerg } 201030300Sjoerg /* 201130300Sjoerg * Remote want us to authenticate, remember this, 201230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 201330300Sjoerg * up. 201430300Sjoerg */ 201530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 201630300Sjoerg continue; 201725944Sjoerg default: 201825944Sjoerg /* Others not supported. */ 201925944Sjoerg if (debug) 202069211Sphk log(-1, "[rej] "); 202125944Sjoerg break; 202225944Sjoerg } 202325944Sjoerg /* Add the option to rejected list. */ 202425944Sjoerg bcopy (p, r, p[1]); 202525944Sjoerg r += p[1]; 202625944Sjoerg rlen += p[1]; 202725944Sjoerg } 202825944Sjoerg if (rlen) { 202925944Sjoerg if (debug) 203069211Sphk log(-1, " send conf-rej\n"); 203125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 203225944Sjoerg return 0; 203325944Sjoerg } else if (debug) 203469211Sphk log(-1, "\n"); 203525944Sjoerg 203625944Sjoerg /* 203725944Sjoerg * pass 2: check for option values that are unacceptable and 203825944Sjoerg * thus require to be nak'ed. 203925944Sjoerg */ 204025944Sjoerg if (debug) 204140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 204240008Sjoerg SPP_ARGS(ifp)); 204325944Sjoerg 204425944Sjoerg p = (void*) (h+1); 204525944Sjoerg len = origlen; 204625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 204725944Sjoerg if (debug) 204869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 204925944Sjoerg switch (*p) { 205025944Sjoerg case LCP_OPT_MAGIC: 205111189Sjkh /* Magic number -- extract. */ 205225944Sjoerg nmagic = (u_long)p[2] << 24 | 205325944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 205425944Sjoerg if (nmagic != sp->lcp.magic) { 205570199Sjhay sp->pp_loopcnt = 0; 205625706Sjoerg if (debug) 205769211Sphk log(-1, "0x%lx ", nmagic); 205811189Sjkh continue; 205911189Sjkh } 206070199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 206169211Sphk log(-1, "[glitch] "); 206225944Sjoerg ++sp->pp_loopcnt; 206325944Sjoerg /* 206425944Sjoerg * We negate our magic here, and NAK it. If 206525944Sjoerg * we see it later in an NAK packet, we 206625944Sjoerg * suggest a new one. 206725944Sjoerg */ 206825944Sjoerg nmagic = ~sp->lcp.magic; 206925944Sjoerg /* Gonna NAK it. */ 207025944Sjoerg p[2] = nmagic >> 24; 207125944Sjoerg p[3] = nmagic >> 16; 207225944Sjoerg p[4] = nmagic >> 8; 207325944Sjoerg p[5] = nmagic; 207411189Sjkh break; 207525944Sjoerg 207611189Sjkh case LCP_OPT_ASYNC_MAP: 207711189Sjkh /* Async control character map -- check to be zero. */ 207825944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 207925706Sjoerg if (debug) 208069211Sphk log(-1, "[empty] "); 208111189Sjkh continue; 208225706Sjoerg } 208325706Sjoerg if (debug) 208469211Sphk log(-1, "[non-empty] "); 208525944Sjoerg /* suggest a zero one */ 208625944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 208711189Sjkh break; 208825944Sjoerg 208911189Sjkh case LCP_OPT_MRU: 209025944Sjoerg /* 209125944Sjoerg * Maximum receive unit. Always agreeable, 209225944Sjoerg * but ignored by now. 209325944Sjoerg */ 209425944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 209525706Sjoerg if (debug) 209669211Sphk log(-1, "%lu ", sp->lcp.their_mru); 209711189Sjkh continue; 209830300Sjoerg 209930300Sjoerg case LCP_OPT_AUTH_PROTO: 210030300Sjoerg authproto = (p[2] << 8) + p[3]; 210130300Sjoerg if (sp->myauth.proto != authproto) { 210230300Sjoerg /* not agreed, nak */ 210330300Sjoerg if (debug) 210469211Sphk log(-1, "[mine %s != his %s] ", 210530300Sjoerg sppp_proto_name(sp->hisauth.proto), 210630300Sjoerg sppp_proto_name(authproto)); 210730300Sjoerg p[2] = sp->myauth.proto >> 8; 210830300Sjoerg p[3] = sp->myauth.proto; 210930300Sjoerg break; 211030300Sjoerg } 211130300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 211230300Sjoerg if (debug) 211369211Sphk log(-1, "[chap not MD5] "); 211439981Sjoerg p[4] = CHAP_MD5; 211530300Sjoerg break; 211630300Sjoerg } 211730300Sjoerg continue; 211811189Sjkh } 211925944Sjoerg /* Add the option to nak'ed list. */ 212025706Sjoerg bcopy (p, r, p[1]); 212125706Sjoerg r += p[1]; 212211189Sjkh rlen += p[1]; 212312436Speter } 212425706Sjoerg if (rlen) { 212570199Sjhay /* 212670199Sjhay * Local and remote magics equal -- loopback? 212770199Sjhay */ 212870199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 212970199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 213070199Sjhay printf (SPP_FMT "loopback\n", 213170199Sjhay SPP_ARGS(ifp)); 213270199Sjhay if (ifp->if_flags & IFF_UP) { 213370199Sjhay if_down(ifp); 213470199Sjhay sppp_qflush(&sp->pp_cpq); 213570199Sjhay /* XXX ? */ 213670199Sjhay lcp.Down(sp); 213770199Sjhay lcp.Up(sp); 213870199Sjhay } 213970199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 214028036Sjoerg if (debug) 214169211Sphk log(-1, " max_failure (%d) exceeded, " 214228036Sjoerg "send conf-rej\n", 214328036Sjoerg sp->lcp.max_failure); 214428036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 214528036Sjoerg } else { 214628036Sjoerg if (debug) 214769211Sphk log(-1, " send conf-nak\n"); 214828036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 214928036Sjoerg } 215025944Sjoerg } else { 215125944Sjoerg if (debug) 215269211Sphk log(-1, " send conf-ack\n"); 215328036Sjoerg sp->fail_counter[IDX_LCP] = 0; 215425944Sjoerg sp->pp_loopcnt = 0; 215525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 215625944Sjoerg h->ident, origlen, h+1); 215725944Sjoerg } 215825944Sjoerg 215911189Sjkh free (buf, M_TEMP); 216011189Sjkh return (rlen == 0); 21614910Swollman} 21624910Swollman 216325944Sjoerg/* 216425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 216525944Sjoerg * negotiation. 216625944Sjoerg */ 216712820Sphkstatic void 216825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 21694910Swollman{ 217025944Sjoerg STDDCL; 217125944Sjoerg u_char *buf, *p; 21724910Swollman 217325944Sjoerg len -= 4; 217425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 217525944Sjoerg if (!buf) 21764910Swollman return; 217725944Sjoerg 217825944Sjoerg if (debug) 217940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 218040008Sjoerg SPP_ARGS(ifp)); 218125944Sjoerg 218225944Sjoerg p = (void*) (h+1); 218325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 218425944Sjoerg if (debug) 218569211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 218625944Sjoerg switch (*p) { 218725944Sjoerg case LCP_OPT_MAGIC: 218825944Sjoerg /* Magic number -- can't use it, use 0 */ 218925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 219025944Sjoerg sp->lcp.magic = 0; 219125944Sjoerg break; 219225944Sjoerg case LCP_OPT_MRU: 219325944Sjoerg /* 219425944Sjoerg * Should not be rejected anyway, since we only 219525944Sjoerg * negotiate a MRU if explicitly requested by 219625944Sjoerg * peer. 219725944Sjoerg */ 219825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 219925944Sjoerg break; 220030300Sjoerg case LCP_OPT_AUTH_PROTO: 220130300Sjoerg /* 220230300Sjoerg * Peer doesn't want to authenticate himself, 220330300Sjoerg * deny unless this is a dialout call, and 220430300Sjoerg * AUTHFLAG_NOCALLOUT is set. 220530300Sjoerg */ 220630300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 220730300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 220830300Sjoerg if (debug) 220969211Sphk log(-1, "[don't insist on auth " 221030300Sjoerg "for callout]"); 221130300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 221230300Sjoerg break; 221330300Sjoerg } 221430300Sjoerg if (debug) 221569211Sphk log(-1, "[access denied]\n"); 221630300Sjoerg lcp.Close(sp); 221730300Sjoerg break; 221825944Sjoerg } 22194910Swollman } 222025944Sjoerg if (debug) 222169211Sphk log(-1, "\n"); 222225944Sjoerg free (buf, M_TEMP); 222325944Sjoerg return; 222425944Sjoerg} 222525944Sjoerg 222625944Sjoerg/* 222725944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 222825944Sjoerg * negotiation. 222925944Sjoerg */ 223025944Sjoergstatic void 223125944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 223225944Sjoerg{ 223325944Sjoerg STDDCL; 223425944Sjoerg u_char *buf, *p; 223525944Sjoerg u_long magic; 223625944Sjoerg 223725944Sjoerg len -= 4; 223825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 223925944Sjoerg if (!buf) 224025944Sjoerg return; 224125944Sjoerg 224225944Sjoerg if (debug) 224340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 224440008Sjoerg SPP_ARGS(ifp)); 224525944Sjoerg 224625944Sjoerg p = (void*) (h+1); 224725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 224825706Sjoerg if (debug) 224969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 225025944Sjoerg switch (*p) { 225125944Sjoerg case LCP_OPT_MAGIC: 225225944Sjoerg /* Magic number -- renegotiate */ 225325944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 225425944Sjoerg len >= 6 && p[1] == 6) { 225525944Sjoerg magic = (u_long)p[2] << 24 | 225625944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 225725944Sjoerg /* 225825944Sjoerg * If the remote magic is our negated one, 225925944Sjoerg * this looks like a loopback problem. 226025944Sjoerg * Suggest a new magic to make sure. 226125944Sjoerg */ 226225944Sjoerg if (magic == ~sp->lcp.magic) { 226325944Sjoerg if (debug) 226469211Sphk log(-1, "magic glitch "); 226542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 226635064Sphk sp->lcp.magic = random(); 226740008Sjoerg#else 226840008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 226940008Sjoerg#endif 227025944Sjoerg } else { 227125944Sjoerg sp->lcp.magic = magic; 227225944Sjoerg if (debug) 227369211Sphk log(-1, "%lu ", magic); 227425944Sjoerg } 227525944Sjoerg } 227625944Sjoerg break; 227725944Sjoerg case LCP_OPT_MRU: 227825944Sjoerg /* 227925944Sjoerg * Peer wants to advise us to negotiate an MRU. 228025944Sjoerg * Agree on it if it's reasonable, or use 228125944Sjoerg * default otherwise. 228225944Sjoerg */ 228325944Sjoerg if (len >= 4 && p[1] == 4) { 228425944Sjoerg u_int mru = p[2] * 256 + p[3]; 228525944Sjoerg if (debug) 228669211Sphk log(-1, "%d ", mru); 228725944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 228825944Sjoerg mru = PP_MTU; 228925944Sjoerg sp->lcp.mru = mru; 229025944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 229125944Sjoerg } 229225944Sjoerg break; 229330300Sjoerg case LCP_OPT_AUTH_PROTO: 229430300Sjoerg /* 229530300Sjoerg * Peer doesn't like our authentication method, 229630300Sjoerg * deny. 229730300Sjoerg */ 229830300Sjoerg if (debug) 229969211Sphk log(-1, "[access denied]\n"); 230030300Sjoerg lcp.Close(sp); 230130300Sjoerg break; 23024910Swollman } 230325944Sjoerg } 230425944Sjoerg if (debug) 230569211Sphk log(-1, "\n"); 230625944Sjoerg free (buf, M_TEMP); 230725944Sjoerg return; 230825944Sjoerg} 230911189Sjkh 231025944Sjoergstatic void 231125944Sjoergsppp_lcp_tlu(struct sppp *sp) 231225944Sjoerg{ 231342066Sphk STDDCL; 231425944Sjoerg int i; 231525944Sjoerg u_long mask; 231625944Sjoerg 231725944Sjoerg /* XXX ? */ 231825944Sjoerg if (! (ifp->if_flags & IFF_UP) && 231925944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 232025944Sjoerg /* Coming out of loopback mode. */ 232125944Sjoerg if_up(ifp); 232240008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 232325944Sjoerg } 232425944Sjoerg 232525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 232625944Sjoerg if ((cps[i])->flags & CP_QUAL) 232725944Sjoerg (cps[i])->Open(sp); 232825944Sjoerg 232930300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 233030300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 233125944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 233225944Sjoerg else 233325944Sjoerg sp->pp_phase = PHASE_NETWORK; 233425944Sjoerg 233542066Sphk if (debug) 233642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 233742066Sphk sppp_phase_name(sp->pp_phase)); 233825944Sjoerg 233930300Sjoerg /* 234030300Sjoerg * Open all authentication protocols. This is even required 234130300Sjoerg * if we already proceeded to network phase, since it might be 234230300Sjoerg * that remote wants us to authenticate, so we might have to 234330300Sjoerg * send a PAP request. Undesired authentication protocols 234430300Sjoerg * don't do anything when they get an Open event. 234530300Sjoerg */ 234630300Sjoerg for (i = 0; i < IDX_COUNT; i++) 234730300Sjoerg if ((cps[i])->flags & CP_AUTH) 234830300Sjoerg (cps[i])->Open(sp); 234930300Sjoerg 235030300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 235125944Sjoerg /* Notify all NCPs. */ 235225944Sjoerg for (i = 0; i < IDX_COUNT; i++) 235325944Sjoerg if ((cps[i])->flags & CP_NCP) 235425944Sjoerg (cps[i])->Open(sp); 235525944Sjoerg } 235625944Sjoerg 235725944Sjoerg /* Send Up events to all started protos. */ 235825944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 235925944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 236025944Sjoerg (cps[i])->Up(sp); 236125944Sjoerg 236242104Sphk /* notify low-level driver of state change */ 236342104Sphk if (sp->pp_chg) 236442104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 236542104Sphk 236625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 236725944Sjoerg /* if no NCP is starting, close down */ 236830300Sjoerg sppp_lcp_check_and_close(sp); 236925944Sjoerg} 237025944Sjoerg 237125944Sjoergstatic void 237225944Sjoergsppp_lcp_tld(struct sppp *sp) 237325944Sjoerg{ 237442066Sphk STDDCL; 237525944Sjoerg int i; 237625944Sjoerg u_long mask; 237725944Sjoerg 237825944Sjoerg sp->pp_phase = PHASE_TERMINATE; 237925944Sjoerg 238042066Sphk if (debug) 238142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 238242066Sphk sppp_phase_name(sp->pp_phase)); 238325944Sjoerg 238425944Sjoerg /* 238525944Sjoerg * Take upper layers down. We send the Down event first and 238625944Sjoerg * the Close second to prevent the upper layers from sending 238725944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 238825944Sjoerg * describes it. 238925944Sjoerg */ 239025944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 239125944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 239225944Sjoerg (cps[i])->Down(sp); 239325944Sjoerg (cps[i])->Close(sp); 239425944Sjoerg } 239525944Sjoerg} 239625944Sjoerg 239725944Sjoergstatic void 239825944Sjoergsppp_lcp_tls(struct sppp *sp) 239925944Sjoerg{ 240042066Sphk STDDCL; 240125944Sjoerg 240225944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 240325944Sjoerg 240442066Sphk if (debug) 240542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 240642066Sphk sppp_phase_name(sp->pp_phase)); 240725944Sjoerg 240825944Sjoerg /* Notify lower layer if desired. */ 240925944Sjoerg if (sp->pp_tls) 241025944Sjoerg (sp->pp_tls)(sp); 241141881Sphk else 241241881Sphk (sp->pp_up)(sp); 241325944Sjoerg} 241425944Sjoerg 241525944Sjoergstatic void 241625944Sjoergsppp_lcp_tlf(struct sppp *sp) 241725944Sjoerg{ 241842066Sphk STDDCL; 241925944Sjoerg 242025944Sjoerg sp->pp_phase = PHASE_DEAD; 242142066Sphk if (debug) 242242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 242342066Sphk sppp_phase_name(sp->pp_phase)); 242425944Sjoerg 242525944Sjoerg /* Notify lower layer if desired. */ 242625944Sjoerg if (sp->pp_tlf) 242725944Sjoerg (sp->pp_tlf)(sp); 242841881Sphk else 242941881Sphk (sp->pp_down)(sp); 243025944Sjoerg} 243125944Sjoerg 243225944Sjoergstatic void 243325944Sjoergsppp_lcp_scr(struct sppp *sp) 243425944Sjoerg{ 243530300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 243625944Sjoerg int i = 0; 243730300Sjoerg u_short authproto; 243825944Sjoerg 243925944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 244025944Sjoerg if (! sp->lcp.magic) 244142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 244235064Sphk sp->lcp.magic = random(); 244340008Sjoerg#else 244440008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 244540008Sjoerg#endif 244625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 244725944Sjoerg opt[i++] = 6; 244825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 244925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 245025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 245125944Sjoerg opt[i++] = sp->lcp.magic; 245225944Sjoerg } 245325944Sjoerg 245425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 245525944Sjoerg opt[i++] = LCP_OPT_MRU; 245625944Sjoerg opt[i++] = 4; 245725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 245825944Sjoerg opt[i++] = sp->lcp.mru; 245925944Sjoerg } 246025944Sjoerg 246130300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 246230300Sjoerg authproto = sp->hisauth.proto; 246330300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 246430300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 246530300Sjoerg opt[i++] = authproto >> 8; 246630300Sjoerg opt[i++] = authproto; 246730300Sjoerg if (authproto == PPP_CHAP) 246830300Sjoerg opt[i++] = CHAP_MD5; 246930300Sjoerg } 247030300Sjoerg 247125944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 247225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 247325944Sjoerg} 247425944Sjoerg 247525944Sjoerg/* 247630300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 247730300Sjoerg */ 247830300Sjoergstatic int 247930300Sjoergsppp_ncp_check(struct sppp *sp) 248030300Sjoerg{ 248130300Sjoerg int i, mask; 248230300Sjoerg 248330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 248430300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 248530300Sjoerg return 1; 248630300Sjoerg return 0; 248730300Sjoerg} 248830300Sjoerg 248930300Sjoerg/* 249025944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 249125944Sjoerg * Called by the NCPs during their tlf action handling. 249225944Sjoerg */ 249325944Sjoergstatic void 249430300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 249525944Sjoerg{ 249625944Sjoerg 249730300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 249830300Sjoerg /* don't bother, we are already going down */ 249930300Sjoerg return; 250030300Sjoerg 250130300Sjoerg if (sppp_ncp_check(sp)) 250230300Sjoerg return; 250330300Sjoerg 250425944Sjoerg lcp.Close(sp); 250525944Sjoerg} 250670199Sjhay 250770199Sjhay/* 250825944Sjoerg *--------------------------------------------------------------------------* 250925944Sjoerg * * 251025944Sjoerg * The IPCP implementation. * 251125944Sjoerg * * 251225944Sjoerg *--------------------------------------------------------------------------* 251325944Sjoerg */ 251425944Sjoerg 251525944Sjoergstatic void 251625944Sjoergsppp_ipcp_init(struct sppp *sp) 251725944Sjoerg{ 251825944Sjoerg sp->ipcp.opts = 0; 251925944Sjoerg sp->ipcp.flags = 0; 252025944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 252125944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 252242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 252329681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 252440008Sjoerg#endif 252525944Sjoerg} 252625944Sjoerg 252725944Sjoergstatic void 252825944Sjoergsppp_ipcp_up(struct sppp *sp) 252925944Sjoerg{ 253025944Sjoerg sppp_up_event(&ipcp, sp); 253125944Sjoerg} 253225944Sjoerg 253325944Sjoergstatic void 253425944Sjoergsppp_ipcp_down(struct sppp *sp) 253525944Sjoerg{ 253625944Sjoerg sppp_down_event(&ipcp, sp); 253725944Sjoerg} 253825944Sjoerg 253925944Sjoergstatic void 254025944Sjoergsppp_ipcp_open(struct sppp *sp) 254125944Sjoerg{ 254225944Sjoerg STDDCL; 254325944Sjoerg u_long myaddr, hisaddr; 254425944Sjoerg 254542104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 254642104Sphk 254730300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 254825944Sjoerg /* 254925944Sjoerg * If we don't have his address, this probably means our 255025944Sjoerg * interface doesn't want to talk IP at all. (This could 255125944Sjoerg * be the case if somebody wants to speak only IPX, for 255225944Sjoerg * example.) Don't open IPCP in this case. 255325944Sjoerg */ 255425944Sjoerg if (hisaddr == 0L) { 255525944Sjoerg /* XXX this message should go away */ 255625944Sjoerg if (debug) 255740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 255840008Sjoerg SPP_ARGS(ifp)); 255925944Sjoerg return; 256025944Sjoerg } 256125944Sjoerg 256225944Sjoerg if (myaddr == 0L) { 256325944Sjoerg /* 256425944Sjoerg * I don't have an assigned address, so i need to 256525944Sjoerg * negotiate my address. 256625944Sjoerg */ 256725944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 256825944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 256942104Sphk } else 257042104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 257125944Sjoerg sppp_open_event(&ipcp, sp); 257225944Sjoerg} 257325944Sjoerg 257425944Sjoergstatic void 257525944Sjoergsppp_ipcp_close(struct sppp *sp) 257625944Sjoerg{ 257725944Sjoerg sppp_close_event(&ipcp, sp); 257825944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 257925944Sjoerg /* 258025944Sjoerg * My address was dynamic, clear it again. 258125944Sjoerg */ 258225944Sjoerg sppp_set_ip_addr(sp, 0L); 258325944Sjoerg} 258425944Sjoerg 258525944Sjoergstatic void 258625944Sjoergsppp_ipcp_TO(void *cookie) 258725944Sjoerg{ 258825944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 258925944Sjoerg} 259025944Sjoerg 259125944Sjoerg/* 259225944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 259325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 259425944Sjoerg * caused action scn. (The return value is used to make the state 259525944Sjoerg * transition decision in the state automaton.) 259625944Sjoerg */ 259725944Sjoergstatic int 259825944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 259925944Sjoerg{ 260025944Sjoerg u_char *buf, *r, *p; 260125944Sjoerg struct ifnet *ifp = &sp->pp_if; 260225944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 260325944Sjoerg u_long hisaddr, desiredaddr; 260442104Sphk int gotmyaddr = 0; 260525944Sjoerg 260625944Sjoerg len -= 4; 260725944Sjoerg origlen = len; 260825944Sjoerg /* 260925944Sjoerg * Make sure to allocate a buf that can at least hold a 261025944Sjoerg * conf-nak with an `address' option. We might need it below. 261125944Sjoerg */ 261225944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 261325944Sjoerg if (! buf) 261425944Sjoerg return (0); 261525944Sjoerg 261625944Sjoerg /* pass 1: see if we can recognize them */ 261725944Sjoerg if (debug) 261840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 261940008Sjoerg SPP_ARGS(ifp)); 262025944Sjoerg p = (void*) (h+1); 262125944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 262225944Sjoerg if (debug) 262369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 262425944Sjoerg switch (*p) { 262525944Sjoerg case IPCP_OPT_ADDRESS: 262625944Sjoerg if (len >= 6 && p[1] == 6) { 262725944Sjoerg /* correctly formed address option */ 262825944Sjoerg continue; 262925944Sjoerg } 263025706Sjoerg if (debug) 263169211Sphk log(-1, "[invalid] "); 263211189Sjkh break; 263325944Sjoerg default: 263425944Sjoerg /* Others not supported. */ 263525944Sjoerg if (debug) 263669211Sphk log(-1, "[rej] "); 26374910Swollman break; 26384910Swollman } 263925944Sjoerg /* Add the option to rejected list. */ 264025944Sjoerg bcopy (p, r, p[1]); 264125944Sjoerg r += p[1]; 264225944Sjoerg rlen += p[1]; 264325944Sjoerg } 264425944Sjoerg if (rlen) { 264525944Sjoerg if (debug) 264669211Sphk log(-1, " send conf-rej\n"); 264725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 264825944Sjoerg return 0; 264925944Sjoerg } else if (debug) 265069211Sphk log(-1, "\n"); 265125944Sjoerg 265225944Sjoerg /* pass 2: parse option values */ 265330300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 265425944Sjoerg if (debug) 265540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 265640008Sjoerg SPP_ARGS(ifp)); 265725944Sjoerg p = (void*) (h+1); 265825944Sjoerg len = origlen; 265925944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 266025944Sjoerg if (debug) 266169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 266225944Sjoerg switch (*p) { 266325944Sjoerg case IPCP_OPT_ADDRESS: 266442104Sphk /* This is the address he wants in his end */ 266525944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 266625944Sjoerg p[4] << 8 | p[5]; 266733928Sphk if (desiredaddr == hisaddr || 266842104Sphk (hisaddr == 1 && desiredaddr != 0)) { 266925944Sjoerg /* 267025944Sjoerg * Peer's address is same as our value, 267170199Sjhay * or we have set it to 0.0.0.1 to 267233928Sphk * indicate that we do not really care, 267325944Sjoerg * this is agreeable. Gonna conf-ack 267425944Sjoerg * it. 267525944Sjoerg */ 267625944Sjoerg if (debug) 267769211Sphk log(-1, "%s [ack] ", 267842104Sphk sppp_dotted_quad(hisaddr)); 267925944Sjoerg /* record that we've seen it already */ 268025944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 268125944Sjoerg continue; 268225944Sjoerg } 268325944Sjoerg /* 268425944Sjoerg * The address wasn't agreeable. This is either 268525944Sjoerg * he sent us 0.0.0.0, asking to assign him an 268625944Sjoerg * address, or he send us another address not 268725944Sjoerg * matching our value. Either case, we gonna 268825944Sjoerg * conf-nak it with our value. 268942104Sphk * XXX: we should "rej" if hisaddr == 0 269025944Sjoerg */ 269125944Sjoerg if (debug) { 269225944Sjoerg if (desiredaddr == 0) 269369211Sphk log(-1, "[addr requested] "); 269425944Sjoerg else 269569211Sphk log(-1, "%s [not agreed] ", 269642104Sphk sppp_dotted_quad(desiredaddr)); 269725944Sjoerg 269825944Sjoerg } 269944235Sphk p[2] = hisaddr >> 24; 270044235Sphk p[3] = hisaddr >> 16; 270144235Sphk p[4] = hisaddr >> 8; 270244235Sphk p[5] = hisaddr; 270311189Sjkh break; 270425706Sjoerg } 270525944Sjoerg /* Add the option to nak'ed list. */ 270625944Sjoerg bcopy (p, r, p[1]); 270725944Sjoerg r += p[1]; 270825944Sjoerg rlen += p[1]; 270925944Sjoerg } 271025944Sjoerg 271125944Sjoerg /* 271225944Sjoerg * If we are about to conf-ack the request, but haven't seen 271325944Sjoerg * his address so far, gonna conf-nak it instead, with the 271425944Sjoerg * `address' option present and our idea of his address being 271525944Sjoerg * filled in there, to request negotiation of both addresses. 271625944Sjoerg * 271725944Sjoerg * XXX This can result in an endless req - nak loop if peer 271825944Sjoerg * doesn't want to send us his address. Q: What should we do 271925944Sjoerg * about it? XXX A: implement the max-failure counter. 272025944Sjoerg */ 272142104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 272225944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 272325944Sjoerg buf[1] = 6; 272425944Sjoerg buf[2] = hisaddr >> 24; 272525944Sjoerg buf[3] = hisaddr >> 16; 272625944Sjoerg buf[4] = hisaddr >> 8; 272725944Sjoerg buf[5] = hisaddr; 272825944Sjoerg rlen = 6; 272925706Sjoerg if (debug) 273069211Sphk log(-1, "still need hisaddr "); 273125944Sjoerg } 273225944Sjoerg 273325944Sjoerg if (rlen) { 273425706Sjoerg if (debug) 273569211Sphk log(-1, " send conf-nak\n"); 273625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 273725944Sjoerg } else { 273825706Sjoerg if (debug) 273969211Sphk log(-1, " send conf-ack\n"); 274025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 274125944Sjoerg h->ident, origlen, h+1); 274225944Sjoerg } 274325944Sjoerg 274425944Sjoerg free (buf, M_TEMP); 274525944Sjoerg return (rlen == 0); 274625944Sjoerg} 274725944Sjoerg 274825944Sjoerg/* 274925944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 275025944Sjoerg * negotiation. 275125944Sjoerg */ 275225944Sjoergstatic void 275325944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 275425944Sjoerg{ 275525944Sjoerg u_char *buf, *p; 275625944Sjoerg struct ifnet *ifp = &sp->pp_if; 275725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 275825944Sjoerg 275925944Sjoerg len -= 4; 276025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 276125944Sjoerg if (!buf) 276225944Sjoerg return; 276325944Sjoerg 276425944Sjoerg if (debug) 276540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 276640008Sjoerg SPP_ARGS(ifp)); 276725944Sjoerg 276825944Sjoerg p = (void*) (h+1); 276925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 277025706Sjoerg if (debug) 277169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 277225944Sjoerg switch (*p) { 277325944Sjoerg case IPCP_OPT_ADDRESS: 277425944Sjoerg /* 277525944Sjoerg * Peer doesn't grok address option. This is 277625944Sjoerg * bad. XXX Should we better give up here? 277742104Sphk * XXX We could try old "addresses" option... 277825944Sjoerg */ 277925944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 278025944Sjoerg break; 278125944Sjoerg } 27824910Swollman } 278325944Sjoerg if (debug) 278469211Sphk log(-1, "\n"); 278525944Sjoerg free (buf, M_TEMP); 278625944Sjoerg return; 27874910Swollman} 27884910Swollman 278925944Sjoerg/* 279025944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 279125944Sjoerg * negotiation. 279225944Sjoerg */ 279312820Sphkstatic void 279425944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 27954910Swollman{ 279625944Sjoerg u_char *buf, *p; 279725944Sjoerg struct ifnet *ifp = &sp->pp_if; 279825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 279925944Sjoerg u_long wantaddr; 28004910Swollman 280125944Sjoerg len -= 4; 280225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 280325944Sjoerg if (!buf) 280425944Sjoerg return; 280525944Sjoerg 280625944Sjoerg if (debug) 280740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 280840008Sjoerg SPP_ARGS(ifp)); 280925944Sjoerg 281025944Sjoerg p = (void*) (h+1); 281125944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 281225944Sjoerg if (debug) 281369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 281425944Sjoerg switch (*p) { 281525944Sjoerg case IPCP_OPT_ADDRESS: 281625944Sjoerg /* 281725944Sjoerg * Peer doesn't like our local IP address. See 281825944Sjoerg * if we can do something for him. We'll drop 281925944Sjoerg * him our address then. 282025944Sjoerg */ 282125944Sjoerg if (len >= 6 && p[1] == 6) { 282225944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 282325944Sjoerg p[4] << 8 | p[5]; 282425944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 282525944Sjoerg if (debug) 282669211Sphk log(-1, "[wantaddr %s] ", 282730300Sjoerg sppp_dotted_quad(wantaddr)); 282825944Sjoerg /* 282925944Sjoerg * When doing dynamic address assignment, 283025944Sjoerg * we accept his offer. Otherwise, we 283125944Sjoerg * ignore it and thus continue to negotiate 283225944Sjoerg * our already existing value. 283342104Sphk * XXX: Bogus, if he said no once, he'll 283442104Sphk * just say no again, might as well die. 283525944Sjoerg */ 283625944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 283725944Sjoerg sppp_set_ip_addr(sp, wantaddr); 283825944Sjoerg if (debug) 283969211Sphk log(-1, "[agree] "); 284042104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 284125944Sjoerg } 284225944Sjoerg } 284325944Sjoerg break; 284425944Sjoerg } 284525944Sjoerg } 284625944Sjoerg if (debug) 284769211Sphk log(-1, "\n"); 284825944Sjoerg free (buf, M_TEMP); 284925944Sjoerg return; 28504910Swollman} 28514910Swollman 285212820Sphkstatic void 285325944Sjoergsppp_ipcp_tlu(struct sppp *sp) 28544910Swollman{ 285542104Sphk /* we are up - notify isdn daemon */ 285642104Sphk if (sp->pp_con) 285742104Sphk sp->pp_con(sp); 28584910Swollman} 28594910Swollman 286025944Sjoergstatic void 286125944Sjoergsppp_ipcp_tld(struct sppp *sp) 286225944Sjoerg{ 286325944Sjoerg} 286425944Sjoerg 286525944Sjoergstatic void 286625944Sjoergsppp_ipcp_tls(struct sppp *sp) 286725944Sjoerg{ 286825944Sjoerg /* indicate to LCP that it must stay alive */ 286925944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 287025944Sjoerg} 287125944Sjoerg 287225944Sjoergstatic void 287325944Sjoergsppp_ipcp_tlf(struct sppp *sp) 287425944Sjoerg{ 287525944Sjoerg /* we no longer need LCP */ 287625944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 287730300Sjoerg sppp_lcp_check_and_close(sp); 287825944Sjoerg} 287925944Sjoerg 288025944Sjoergstatic void 288125944Sjoergsppp_ipcp_scr(struct sppp *sp) 288225944Sjoerg{ 288325944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 288425944Sjoerg u_long ouraddr; 288525944Sjoerg int i = 0; 288625944Sjoerg 288725944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 288830300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 288925944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 289025944Sjoerg opt[i++] = 6; 289125944Sjoerg opt[i++] = ouraddr >> 24; 289225944Sjoerg opt[i++] = ouraddr >> 16; 289325944Sjoerg opt[i++] = ouraddr >> 8; 289425944Sjoerg opt[i++] = ouraddr; 289525944Sjoerg } 289625944Sjoerg 289725944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 289825944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 289925944Sjoerg} 290025944Sjoerg 290170199Sjhay/* 290230300Sjoerg *--------------------------------------------------------------------------* 290330300Sjoerg * * 290430300Sjoerg * The CHAP implementation. * 290530300Sjoerg * * 290630300Sjoerg *--------------------------------------------------------------------------* 290730300Sjoerg */ 290830300Sjoerg 290930300Sjoerg/* 291030300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 291130300Sjoerg * the control protocols do, since they do have Open and Close events, but 291230300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 291330300Sjoerg * authentication protocols may be different in both directions (this makes 291430300Sjoerg * sense, think of a machine that never accepts incoming calls but only 291530300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 291630300Sjoerg * 291730300Sjoerg * Our state machine for the local authentication protocol (we are requesting 291830300Sjoerg * the peer to authenticate) looks like: 291930300Sjoerg * 292030300Sjoerg * RCA- 292130300Sjoerg * +--------------------------------------------+ 292230300Sjoerg * V scn,tld| 292330300Sjoerg * +--------+ Close +---------+ RCA+ 292430300Sjoerg * | |<----------------------------------| |------+ 292530300Sjoerg * +--->| Closed | TO* | Opened | sca | 292630300Sjoerg * | | |-----+ +-------| |<-----+ 292730300Sjoerg * | +--------+ irc | | +---------+ 292830300Sjoerg * | ^ | | ^ 292930300Sjoerg * | | | | | 293030300Sjoerg * | | | | | 293130300Sjoerg * | TO-| | | | 293230300Sjoerg * | |tld TO+ V | | 293330300Sjoerg * | | +------->+ | | 293430300Sjoerg * | | | | | | 293530300Sjoerg * | +--------+ V | | 293630300Sjoerg * | | |<----+<--------------------+ | 293730300Sjoerg * | | Req- | scr | 293830300Sjoerg * | | Sent | | 293930300Sjoerg * | | | | 294030300Sjoerg * | +--------+ | 294130300Sjoerg * | RCA- | | RCA+ | 294230300Sjoerg * +------+ +------------------------------------------+ 294330300Sjoerg * scn,tld sca,irc,ict,tlu 294430300Sjoerg * 294530300Sjoerg * 294630300Sjoerg * with: 294730300Sjoerg * 294830300Sjoerg * Open: LCP reached authentication phase 294930300Sjoerg * Close: LCP reached terminate phase 295030300Sjoerg * 295130300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 295230300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 295330300Sjoerg * TO+: timeout with restart counter >= 0 295430300Sjoerg * TO-: timeout with restart counter < 0 295530300Sjoerg * TO*: reschedule timeout for CHAP 295630300Sjoerg * 295730300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 295830300Sjoerg * sca: send ack packet (pap-ack, chap-success) 295930300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 296030300Sjoerg * ict: initialize re-challenge timer (CHAP only) 296130300Sjoerg * 296230300Sjoerg * tlu: this-layer-up, LCP reaches network phase 296330300Sjoerg * tld: this-layer-down, LCP enters terminate phase 296430300Sjoerg * 296530300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 296630300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 296730300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 296830300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 296930300Sjoerg * causing LCP to enter terminate phase. 297030300Sjoerg * 297130300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 297230300Sjoerg * expected to send one based on the successful negotiation of PAP as 297330300Sjoerg * the authentication protocol during the LCP option negotiation. 297430300Sjoerg * 297530300Sjoerg * Incoming authentication protocol requests (remote requests 297630300Sjoerg * authentication, we are peer) don't employ a state machine at all, 297730300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 297830300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 297930300Sjoerg * still in authentication phase (thereby violating the standard that 298030300Sjoerg * demands that these NCP packets are to be discarded), so we keep 298130300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 298230300Sjoerg * phase network once we've seen a positive acknowledge for the 298330300Sjoerg * authentication. 298430300Sjoerg */ 298530300Sjoerg 298630300Sjoerg/* 298730300Sjoerg * Handle incoming CHAP packets. 298830300Sjoerg */ 298930300Sjoergvoid 299030300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 299130300Sjoerg{ 299230300Sjoerg STDDCL; 299330300Sjoerg struct lcp_header *h; 299430300Sjoerg int len, x; 299530300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 299630300Sjoerg int value_len, name_len; 299730300Sjoerg MD5_CTX ctx; 299830300Sjoerg 299930300Sjoerg len = m->m_pkthdr.len; 300030300Sjoerg if (len < 4) { 300130300Sjoerg if (debug) 300230300Sjoerg log(LOG_DEBUG, 300340008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 300440008Sjoerg SPP_ARGS(ifp), len); 300530300Sjoerg return; 300630300Sjoerg } 300730300Sjoerg h = mtod (m, struct lcp_header*); 300830300Sjoerg if (len > ntohs (h->len)) 300930300Sjoerg len = ntohs (h->len); 301030300Sjoerg 301130300Sjoerg switch (h->type) { 301230300Sjoerg /* challenge, failure and success are his authproto */ 301330300Sjoerg case CHAP_CHALLENGE: 301430300Sjoerg value = 1 + (u_char*)(h+1); 301530300Sjoerg value_len = value[-1]; 301630300Sjoerg name = value + value_len; 301730300Sjoerg name_len = len - value_len - 5; 301830300Sjoerg if (name_len < 0) { 301930300Sjoerg if (debug) { 302030300Sjoerg log(LOG_DEBUG, 302140008Sjoerg SPP_FMT "chap corrupted challenge " 302230300Sjoerg "<%s id=0x%x len=%d", 302340008Sjoerg SPP_ARGS(ifp), 302430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 302530300Sjoerg h->ident, ntohs(h->len)); 302644145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 302769211Sphk log(-1, ">\n"); 302830300Sjoerg } 302930300Sjoerg break; 303030300Sjoerg } 303170199Sjhay 303230300Sjoerg if (debug) { 303330300Sjoerg log(LOG_DEBUG, 303440008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 303540008Sjoerg SPP_ARGS(ifp), 303630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 303730300Sjoerg ntohs(h->len)); 303830300Sjoerg sppp_print_string((char*) name, name_len); 303969211Sphk log(-1, " value-size=%d value=", value_len); 304030300Sjoerg sppp_print_bytes(value, value_len); 304169211Sphk log(-1, ">\n"); 304230300Sjoerg } 304330300Sjoerg 304430300Sjoerg /* Compute reply value. */ 304530300Sjoerg MD5Init(&ctx); 304630300Sjoerg MD5Update(&ctx, &h->ident, 1); 304730300Sjoerg MD5Update(&ctx, sp->myauth.secret, 304830300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 304930300Sjoerg MD5Update(&ctx, value, value_len); 305030300Sjoerg MD5Final(digest, &ctx); 305130300Sjoerg dsize = sizeof digest; 305230300Sjoerg 305330300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 305430300Sjoerg sizeof dsize, (const char *)&dsize, 305530300Sjoerg sizeof digest, digest, 305640008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 305730300Sjoerg sp->myauth.name, 305830300Sjoerg 0); 305930300Sjoerg break; 306030300Sjoerg 306130300Sjoerg case CHAP_SUCCESS: 306230300Sjoerg if (debug) { 306340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 306440008Sjoerg SPP_ARGS(ifp)); 306530300Sjoerg if (len > 4) { 306669211Sphk log(-1, ": "); 306730300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 306830300Sjoerg } 306969211Sphk log(-1, "\n"); 307030300Sjoerg } 307130300Sjoerg x = splimp(); 307230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 307330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 307432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 307530300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 307630300Sjoerg /* 307730300Sjoerg * We are authenticator for CHAP but didn't 307830300Sjoerg * complete yet. Leave it to tlu to proceed 307930300Sjoerg * to network phase. 308030300Sjoerg */ 308130300Sjoerg splx(x); 308230300Sjoerg break; 308330300Sjoerg } 308430300Sjoerg splx(x); 308530300Sjoerg sppp_phase_network(sp); 308630300Sjoerg break; 308730300Sjoerg 308830300Sjoerg case CHAP_FAILURE: 308930300Sjoerg if (debug) { 309040008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 309140008Sjoerg SPP_ARGS(ifp)); 309230300Sjoerg if (len > 4) { 309369211Sphk log(-1, ": "); 309430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 309530300Sjoerg } 309669211Sphk log(-1, "\n"); 309730300Sjoerg } else 309840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 309940008Sjoerg SPP_ARGS(ifp)); 310030300Sjoerg /* await LCP shutdown by authenticator */ 310130300Sjoerg break; 310230300Sjoerg 310330300Sjoerg /* response is my authproto */ 310430300Sjoerg case CHAP_RESPONSE: 310530300Sjoerg value = 1 + (u_char*)(h+1); 310630300Sjoerg value_len = value[-1]; 310730300Sjoerg name = value + value_len; 310830300Sjoerg name_len = len - value_len - 5; 310930300Sjoerg if (name_len < 0) { 311030300Sjoerg if (debug) { 311130300Sjoerg log(LOG_DEBUG, 311240008Sjoerg SPP_FMT "chap corrupted response " 311330300Sjoerg "<%s id=0x%x len=%d", 311440008Sjoerg SPP_ARGS(ifp), 311530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 311630300Sjoerg h->ident, ntohs(h->len)); 311744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 311869211Sphk log(-1, ">\n"); 311930300Sjoerg } 312030300Sjoerg break; 312130300Sjoerg } 312230300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 312330300Sjoerg if (debug) 312430300Sjoerg log(LOG_DEBUG, 312540008Sjoerg SPP_FMT "chap dropping response for old ID " 312630300Sjoerg "(got %d, expected %d)\n", 312740008Sjoerg SPP_ARGS(ifp), 312830300Sjoerg h->ident, sp->confid[IDX_CHAP]); 312930300Sjoerg break; 313030300Sjoerg } 313130300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 313230300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 313340008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 313440008Sjoerg SPP_ARGS(ifp)); 313530300Sjoerg sppp_print_string(name, name_len); 313669211Sphk log(-1, " != expected "); 313730300Sjoerg sppp_print_string(sp->hisauth.name, 313830300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 313969211Sphk log(-1, "\n"); 314070199Sjhay } 314130300Sjoerg if (debug) { 314240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 314330300Sjoerg "<%s id=0x%x len=%d name=", 314440008Sjoerg SPP_ARGS(ifp), 314530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 314630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 314730300Sjoerg h->ident, ntohs (h->len)); 314830300Sjoerg sppp_print_string((char*)name, name_len); 314969211Sphk log(-1, " value-size=%d value=", value_len); 315030300Sjoerg sppp_print_bytes(value, value_len); 315169211Sphk log(-1, ">\n"); 315230300Sjoerg } 315330300Sjoerg if (value_len != AUTHKEYLEN) { 315430300Sjoerg if (debug) 315530300Sjoerg log(LOG_DEBUG, 315640008Sjoerg SPP_FMT "chap bad hash value length: " 315730300Sjoerg "%d bytes, should be %d\n", 315840008Sjoerg SPP_ARGS(ifp), value_len, 315930300Sjoerg AUTHKEYLEN); 316030300Sjoerg break; 316130300Sjoerg } 316230300Sjoerg 316330300Sjoerg MD5Init(&ctx); 316430300Sjoerg MD5Update(&ctx, &h->ident, 1); 316530300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 316630300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 316730300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 316830300Sjoerg MD5Final(digest, &ctx); 316930300Sjoerg 317030300Sjoerg#define FAILMSG "Failed..." 317130300Sjoerg#define SUCCMSG "Welcome!" 317230300Sjoerg 317330300Sjoerg if (value_len != sizeof digest || 317430300Sjoerg bcmp(digest, value, value_len) != 0) { 317530300Sjoerg /* action scn, tld */ 317630300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 317730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 317830300Sjoerg 0); 317930300Sjoerg chap.tld(sp); 318030300Sjoerg break; 318130300Sjoerg } 318230300Sjoerg /* action sca, perhaps tlu */ 318330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 318430300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 318530300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 318630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 318730300Sjoerg 0); 318830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 318930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 319030300Sjoerg chap.tlu(sp); 319130300Sjoerg } 319230300Sjoerg break; 319330300Sjoerg 319430300Sjoerg default: 319530300Sjoerg /* Unknown CHAP packet type -- ignore. */ 319630300Sjoerg if (debug) { 319740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 319830300Sjoerg "<0x%x id=0x%xh len=%d", 319940008Sjoerg SPP_ARGS(ifp), 320030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 320130300Sjoerg h->type, h->ident, ntohs(h->len)); 320244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 320369211Sphk log(-1, ">\n"); 320430300Sjoerg } 320530300Sjoerg break; 320630300Sjoerg 320730300Sjoerg } 320830300Sjoerg} 320930300Sjoerg 321030300Sjoergstatic void 321130300Sjoergsppp_chap_init(struct sppp *sp) 321230300Sjoerg{ 321330300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 321430300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 321530300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 321642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 321730300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 321840008Sjoerg#endif 321930300Sjoerg} 322030300Sjoerg 322130300Sjoergstatic void 322230300Sjoergsppp_chap_open(struct sppp *sp) 322330300Sjoerg{ 322430300Sjoerg if (sp->myauth.proto == PPP_CHAP && 322530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 322630300Sjoerg /* we are authenticator for CHAP, start it */ 322730300Sjoerg chap.scr(sp); 322830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 322930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 323030300Sjoerg } 323130300Sjoerg /* nothing to be done if we are peer, await a challenge */ 323230300Sjoerg} 323330300Sjoerg 323430300Sjoergstatic void 323530300Sjoergsppp_chap_close(struct sppp *sp) 323630300Sjoerg{ 323730300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 323830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 323930300Sjoerg} 324030300Sjoerg 324130300Sjoergstatic void 324230300Sjoergsppp_chap_TO(void *cookie) 324330300Sjoerg{ 324430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 324530300Sjoerg STDDCL; 324630300Sjoerg int s; 324730300Sjoerg 324830300Sjoerg s = splimp(); 324930300Sjoerg if (debug) 325040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 325140008Sjoerg SPP_ARGS(ifp), 325230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 325330300Sjoerg sp->rst_counter[IDX_CHAP]); 325430300Sjoerg 325530300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 325630300Sjoerg /* TO- event */ 325730300Sjoerg switch (sp->state[IDX_CHAP]) { 325830300Sjoerg case STATE_REQ_SENT: 325930300Sjoerg chap.tld(sp); 326030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 326130300Sjoerg break; 326230300Sjoerg } 326330300Sjoerg else 326430300Sjoerg /* TO+ (or TO*) event */ 326530300Sjoerg switch (sp->state[IDX_CHAP]) { 326630300Sjoerg case STATE_OPENED: 326730300Sjoerg /* TO* event */ 326830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 326930300Sjoerg /* fall through */ 327030300Sjoerg case STATE_REQ_SENT: 327130300Sjoerg chap.scr(sp); 327230300Sjoerg /* sppp_cp_change_state() will restart the timer */ 327330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 327430300Sjoerg break; 327530300Sjoerg } 327630300Sjoerg 327730300Sjoerg splx(s); 327830300Sjoerg} 327930300Sjoerg 328030300Sjoergstatic void 328130300Sjoergsppp_chap_tlu(struct sppp *sp) 328230300Sjoerg{ 328330300Sjoerg STDDCL; 328430300Sjoerg int i, x; 328530300Sjoerg 328640010Sjoerg i = 0; 328730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 328830300Sjoerg 328930300Sjoerg /* 329030300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 329130300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 329230300Sjoerg * initial challenge-response exchange has taken place. 329330300Sjoerg * Provide for an option to avoid rechallenges. 329430300Sjoerg */ 329530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 329630300Sjoerg /* 329730300Sjoerg * Compute the re-challenge timeout. This will yield 329830300Sjoerg * a number between 300 and 810 seconds. 329930300Sjoerg */ 330030300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 330142064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 330230300Sjoerg } 330330300Sjoerg 330430300Sjoerg if (debug) { 330530300Sjoerg log(LOG_DEBUG, 330640008Sjoerg SPP_FMT "chap %s, ", 330740008Sjoerg SPP_ARGS(ifp), 330830300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 330930300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 331069211Sphk log(-1, "next re-challenge in %d seconds\n", i); 331130300Sjoerg else 331269211Sphk log(-1, "re-challenging supressed\n"); 331330300Sjoerg } 331430300Sjoerg 331530300Sjoerg x = splimp(); 331630300Sjoerg /* indicate to LCP that we need to be closed down */ 331730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 331830300Sjoerg 331930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 332030300Sjoerg /* 332130300Sjoerg * Remote is authenticator, but his auth proto didn't 332230300Sjoerg * complete yet. Defer the transition to network 332330300Sjoerg * phase. 332430300Sjoerg */ 332530300Sjoerg splx(x); 332630300Sjoerg return; 332730300Sjoerg } 332830300Sjoerg splx(x); 332930300Sjoerg 333030300Sjoerg /* 333130300Sjoerg * If we are already in phase network, we are done here. This 333230300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 333330300Sjoerg */ 333430300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 333530300Sjoerg sppp_phase_network(sp); 333630300Sjoerg} 333730300Sjoerg 333830300Sjoergstatic void 333930300Sjoergsppp_chap_tld(struct sppp *sp) 334030300Sjoerg{ 334130300Sjoerg STDDCL; 334230300Sjoerg 334330300Sjoerg if (debug) 334440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 334540008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 334630300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 334730300Sjoerg 334830300Sjoerg lcp.Close(sp); 334930300Sjoerg} 335030300Sjoerg 335130300Sjoergstatic void 335230300Sjoergsppp_chap_scr(struct sppp *sp) 335330300Sjoerg{ 335430300Sjoerg u_long *ch, seed; 335530300Sjoerg u_char clen; 335630300Sjoerg 335730300Sjoerg /* Compute random challenge. */ 335830300Sjoerg ch = (u_long *)sp->myauth.challenge; 335942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 336035064Sphk read_random(&seed, sizeof seed); 336140008Sjoerg#else 336242104Sphk { 336342104Sphk struct timeval tv; 336440008Sjoerg microtime(&tv); 336540008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 336642104Sphk } 336740008Sjoerg#endif 336830300Sjoerg ch[0] = seed ^ random(); 336930300Sjoerg ch[1] = seed ^ random(); 337030300Sjoerg ch[2] = seed ^ random(); 337130300Sjoerg ch[3] = seed ^ random(); 337230300Sjoerg clen = AUTHKEYLEN; 337330300Sjoerg 337430300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 337530300Sjoerg 337630300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 337730300Sjoerg sizeof clen, (const char *)&clen, 337840008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 337940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 338030300Sjoerg sp->myauth.name, 338130300Sjoerg 0); 338230300Sjoerg} 338370199Sjhay 338470199Sjhay/* 338530300Sjoerg *--------------------------------------------------------------------------* 338630300Sjoerg * * 338730300Sjoerg * The PAP implementation. * 338830300Sjoerg * * 338930300Sjoerg *--------------------------------------------------------------------------* 339030300Sjoerg */ 339130300Sjoerg/* 339230300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 339330300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 339430300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 339530300Sjoerg * retry counter is expired). 339630300Sjoerg */ 339730300Sjoerg 339830300Sjoerg/* 339930300Sjoerg * Handle incoming PAP packets. */ 340030300Sjoergstatic void 340130300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 340230300Sjoerg{ 340330300Sjoerg STDDCL; 340430300Sjoerg struct lcp_header *h; 340530300Sjoerg int len, x; 340630300Sjoerg u_char *name, *passwd, mlen; 340730300Sjoerg int name_len, passwd_len; 340830300Sjoerg 340930300Sjoerg len = m->m_pkthdr.len; 341030300Sjoerg if (len < 5) { 341130300Sjoerg if (debug) 341230300Sjoerg log(LOG_DEBUG, 341340008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 341440008Sjoerg SPP_ARGS(ifp), len); 341530300Sjoerg return; 341630300Sjoerg } 341730300Sjoerg h = mtod (m, struct lcp_header*); 341830300Sjoerg if (len > ntohs (h->len)) 341930300Sjoerg len = ntohs (h->len); 342030300Sjoerg switch (h->type) { 342130300Sjoerg /* PAP request is my authproto */ 342230300Sjoerg case PAP_REQ: 342330300Sjoerg name = 1 + (u_char*)(h+1); 342430300Sjoerg name_len = name[-1]; 342530300Sjoerg passwd = name + name_len + 1; 342630300Sjoerg if (name_len > len - 6 || 342730300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 342830300Sjoerg if (debug) { 342940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 343030300Sjoerg "<%s id=0x%x len=%d", 343140008Sjoerg SPP_ARGS(ifp), 343230300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 343330300Sjoerg h->ident, ntohs(h->len)); 343444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 343569211Sphk log(-1, ">\n"); 343630300Sjoerg } 343730300Sjoerg break; 343830300Sjoerg } 343930300Sjoerg if (debug) { 344040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 344130300Sjoerg "<%s id=0x%x len=%d name=", 344240008Sjoerg SPP_ARGS(ifp), 344330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 344430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 344530300Sjoerg h->ident, ntohs(h->len)); 344630300Sjoerg sppp_print_string((char*)name, name_len); 344769211Sphk log(-1, " passwd="); 344830300Sjoerg sppp_print_string((char*)passwd, passwd_len); 344969211Sphk log(-1, ">\n"); 345030300Sjoerg } 345130300Sjoerg if (name_len > AUTHNAMELEN || 345230300Sjoerg passwd_len > AUTHKEYLEN || 345330300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 345430300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 345530300Sjoerg /* action scn, tld */ 345630300Sjoerg mlen = sizeof(FAILMSG) - 1; 345730300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 345830300Sjoerg sizeof mlen, (const char *)&mlen, 345930300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 346030300Sjoerg 0); 346130300Sjoerg pap.tld(sp); 346230300Sjoerg break; 346330300Sjoerg } 346430300Sjoerg /* action sca, perhaps tlu */ 346530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 346630300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 346730300Sjoerg mlen = sizeof(SUCCMSG) - 1; 346830300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 346930300Sjoerg sizeof mlen, (const char *)&mlen, 347030300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 347130300Sjoerg 0); 347230300Sjoerg } 347330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 347430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 347530300Sjoerg pap.tlu(sp); 347630300Sjoerg } 347730300Sjoerg break; 347830300Sjoerg 347930300Sjoerg /* ack and nak are his authproto */ 348030300Sjoerg case PAP_ACK: 348140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 348230300Sjoerg if (debug) { 348340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 348440008Sjoerg SPP_ARGS(ifp)); 348530300Sjoerg name_len = *((char *)h); 348630300Sjoerg if (len > 5 && name_len) { 348769211Sphk log(-1, ": "); 348830300Sjoerg sppp_print_string((char*)(h+1), name_len); 348930300Sjoerg } 349069211Sphk log(-1, "\n"); 349130300Sjoerg } 349230300Sjoerg x = splimp(); 349330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 349430300Sjoerg if (sp->myauth.proto == PPP_PAP && 349532169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 349630300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 349730300Sjoerg /* 349830300Sjoerg * We are authenticator for PAP but didn't 349930300Sjoerg * complete yet. Leave it to tlu to proceed 350030300Sjoerg * to network phase. 350130300Sjoerg */ 350230300Sjoerg splx(x); 350330300Sjoerg break; 350430300Sjoerg } 350530300Sjoerg splx(x); 350630300Sjoerg sppp_phase_network(sp); 350730300Sjoerg break; 350830300Sjoerg 350930300Sjoerg case PAP_NAK: 351040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 351130300Sjoerg if (debug) { 351240008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 351340008Sjoerg SPP_ARGS(ifp)); 351430300Sjoerg name_len = *((char *)h); 351530300Sjoerg if (len > 5 && name_len) { 351669211Sphk log(-1, ": "); 351730300Sjoerg sppp_print_string((char*)(h+1), name_len); 351830300Sjoerg } 351969211Sphk log(-1, "\n"); 352030300Sjoerg } else 352140008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 352240008Sjoerg SPP_ARGS(ifp)); 352330300Sjoerg /* await LCP shutdown by authenticator */ 352430300Sjoerg break; 352530300Sjoerg 352630300Sjoerg default: 352730300Sjoerg /* Unknown PAP packet type -- ignore. */ 352830300Sjoerg if (debug) { 352940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 353030300Sjoerg "<0x%x id=0x%x len=%d", 353140008Sjoerg SPP_ARGS(ifp), 353230300Sjoerg h->type, h->ident, ntohs(h->len)); 353344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 353469211Sphk log(-1, ">\n"); 353530300Sjoerg } 353630300Sjoerg break; 353730300Sjoerg 353830300Sjoerg } 353930300Sjoerg} 354030300Sjoerg 354130300Sjoergstatic void 354230300Sjoergsppp_pap_init(struct sppp *sp) 354330300Sjoerg{ 354430300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 354530300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 354630300Sjoerg sp->fail_counter[IDX_PAP] = 0; 354742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 354830300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 354930300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 355040008Sjoerg#endif 355130300Sjoerg} 355230300Sjoerg 355330300Sjoergstatic void 355430300Sjoergsppp_pap_open(struct sppp *sp) 355530300Sjoerg{ 355630300Sjoerg if (sp->hisauth.proto == PPP_PAP && 355730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 355830300Sjoerg /* we are authenticator for PAP, start our timer */ 355930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 356030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 356130300Sjoerg } 356230300Sjoerg if (sp->myauth.proto == PPP_PAP) { 356330300Sjoerg /* we are peer, send a request, and start a timer */ 356430300Sjoerg pap.scr(sp); 356542064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 356642064Sphk sp->pap_my_to_ch); 356730300Sjoerg } 356830300Sjoerg} 356930300Sjoerg 357030300Sjoergstatic void 357130300Sjoergsppp_pap_close(struct sppp *sp) 357230300Sjoerg{ 357330300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 357430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 357530300Sjoerg} 357630300Sjoerg 357730300Sjoerg/* 357830300Sjoerg * That's the timeout routine if we are authenticator. Since the 357930300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 358030300Sjoerg */ 358130300Sjoergstatic void 358230300Sjoergsppp_pap_TO(void *cookie) 358330300Sjoerg{ 358430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 358530300Sjoerg STDDCL; 358630300Sjoerg int s; 358730300Sjoerg 358830300Sjoerg s = splimp(); 358930300Sjoerg if (debug) 359040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 359140008Sjoerg SPP_ARGS(ifp), 359230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 359330300Sjoerg sp->rst_counter[IDX_PAP]); 359430300Sjoerg 359530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 359630300Sjoerg /* TO- event */ 359730300Sjoerg switch (sp->state[IDX_PAP]) { 359830300Sjoerg case STATE_REQ_SENT: 359930300Sjoerg pap.tld(sp); 360030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 360130300Sjoerg break; 360230300Sjoerg } 360330300Sjoerg else 360430300Sjoerg /* TO+ event, not very much we could do */ 360530300Sjoerg switch (sp->state[IDX_PAP]) { 360630300Sjoerg case STATE_REQ_SENT: 360730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 360830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 360930300Sjoerg break; 361030300Sjoerg } 361130300Sjoerg 361230300Sjoerg splx(s); 361330300Sjoerg} 361430300Sjoerg 361530300Sjoerg/* 361630300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 361730300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 361830300Sjoerg * XXX We should impose a max counter. 361930300Sjoerg */ 362030300Sjoergstatic void 362130300Sjoergsppp_pap_my_TO(void *cookie) 362230300Sjoerg{ 362330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 362430300Sjoerg STDDCL; 362530300Sjoerg 362630300Sjoerg if (debug) 362740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 362840008Sjoerg SPP_ARGS(ifp)); 362930300Sjoerg 363030300Sjoerg pap.scr(sp); 363130300Sjoerg} 363230300Sjoerg 363330300Sjoergstatic void 363430300Sjoergsppp_pap_tlu(struct sppp *sp) 363530300Sjoerg{ 363630300Sjoerg STDDCL; 363730300Sjoerg int x; 363830300Sjoerg 363930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 364030300Sjoerg 364130300Sjoerg if (debug) 364240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 364340008Sjoerg SPP_ARGS(ifp), pap.name); 364430300Sjoerg 364530300Sjoerg x = splimp(); 364630300Sjoerg /* indicate to LCP that we need to be closed down */ 364730300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 364830300Sjoerg 364930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 365030300Sjoerg /* 365130300Sjoerg * Remote is authenticator, but his auth proto didn't 365230300Sjoerg * complete yet. Defer the transition to network 365330300Sjoerg * phase. 365430300Sjoerg */ 365530300Sjoerg splx(x); 365630300Sjoerg return; 365730300Sjoerg } 365830300Sjoerg splx(x); 365930300Sjoerg sppp_phase_network(sp); 366030300Sjoerg} 366130300Sjoerg 366230300Sjoergstatic void 366330300Sjoergsppp_pap_tld(struct sppp *sp) 366430300Sjoerg{ 366530300Sjoerg STDDCL; 366630300Sjoerg 366730300Sjoerg if (debug) 366840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 366940008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 367040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 367130300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 367230300Sjoerg 367330300Sjoerg lcp.Close(sp); 367430300Sjoerg} 367530300Sjoerg 367630300Sjoergstatic void 367730300Sjoergsppp_pap_scr(struct sppp *sp) 367830300Sjoerg{ 367930300Sjoerg u_char idlen, pwdlen; 368030300Sjoerg 368130300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 368230300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 368330300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 368430300Sjoerg 368530300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 368630300Sjoerg sizeof idlen, (const char *)&idlen, 368740008Sjoerg (size_t)idlen, sp->myauth.name, 368830300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 368940008Sjoerg (size_t)pwdlen, sp->myauth.secret, 369030300Sjoerg 0); 369130300Sjoerg} 369270199Sjhay 369370199Sjhay/* 369425944Sjoerg * Random miscellaneous functions. 369525944Sjoerg */ 369625944Sjoerg 36974910Swollman/* 369830300Sjoerg * Send a PAP or CHAP proto packet. 369930300Sjoerg * 370030300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 370140008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 370230300Sjoerg * mlen == 0. 370342104Sphk * NOTE: never declare variadic functions with types subject to type 370442104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 370542104Sphk * on the architecture you are on... 370630300Sjoerg */ 370730300Sjoerg 370830300Sjoergstatic void 370942104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 371042104Sphk unsigned int type, unsigned int id, 371130300Sjoerg ...) 371230300Sjoerg{ 371330300Sjoerg STDDCL; 371430300Sjoerg struct ppp_header *h; 371530300Sjoerg struct lcp_header *lh; 371630300Sjoerg struct mbuf *m; 371730300Sjoerg u_char *p; 371830300Sjoerg int len; 371942104Sphk unsigned int mlen; 372030300Sjoerg const char *msg; 372130300Sjoerg va_list ap; 372230300Sjoerg 372330300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 372430300Sjoerg if (! m) 372530300Sjoerg return; 372630300Sjoerg m->m_pkthdr.rcvif = 0; 372730300Sjoerg 372830300Sjoerg h = mtod (m, struct ppp_header*); 372930300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 373030300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 373130300Sjoerg h->protocol = htons(cp->proto); 373230300Sjoerg 373330300Sjoerg lh = (struct lcp_header*)(h + 1); 373430300Sjoerg lh->type = type; 373530300Sjoerg lh->ident = id; 373630300Sjoerg p = (u_char*) (lh+1); 373730300Sjoerg 373830300Sjoerg va_start(ap, id); 373930300Sjoerg len = 0; 374030300Sjoerg 374142104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 374230300Sjoerg msg = va_arg(ap, const char *); 374330300Sjoerg len += mlen; 374430300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 374530300Sjoerg va_end(ap); 374630300Sjoerg m_freem(m); 374730300Sjoerg return; 374830300Sjoerg } 374930300Sjoerg 375030300Sjoerg bcopy(msg, p, mlen); 375130300Sjoerg p += mlen; 375230300Sjoerg } 375330300Sjoerg va_end(ap); 375430300Sjoerg 375530300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 375630300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 375730300Sjoerg 375830300Sjoerg if (debug) { 375940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 376040008Sjoerg SPP_ARGS(ifp), cp->name, 376130300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 376230300Sjoerg lh->ident, ntohs(lh->len)); 376344145Sphk sppp_print_bytes((u_char*) (lh+1), len); 376469211Sphk log(-1, ">\n"); 376530300Sjoerg } 376669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 376769152Sjlemon ifp->if_oerrors++; 376830300Sjoerg} 376930300Sjoerg 377030300Sjoerg/* 377125944Sjoerg * Flush interface queue. 37724910Swollman */ 377312820Sphkstatic void 377425944Sjoergsppp_qflush(struct ifqueue *ifq) 37754910Swollman{ 377625944Sjoerg struct mbuf *m, *n; 37774910Swollman 377825944Sjoerg n = ifq->ifq_head; 377925944Sjoerg while ((m = n)) { 378025944Sjoerg n = m->m_act; 378125944Sjoerg m_freem (m); 378211189Sjkh } 378325944Sjoerg ifq->ifq_head = 0; 378425944Sjoerg ifq->ifq_tail = 0; 378525944Sjoerg ifq->ifq_len = 0; 378625944Sjoerg} 378725944Sjoerg 378825944Sjoerg/* 378925944Sjoerg * Send keepalive packets, every 10 seconds. 379025944Sjoerg */ 379125944Sjoergstatic void 379225944Sjoergsppp_keepalive(void *dummy) 379325944Sjoerg{ 379425944Sjoerg struct sppp *sp; 379525944Sjoerg int s; 379625944Sjoerg 379725944Sjoerg s = splimp(); 379825944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 379925944Sjoerg struct ifnet *ifp = &sp->pp_if; 380025944Sjoerg 380125944Sjoerg /* Keepalive mode disabled or channel down? */ 380225944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 380325944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 380425944Sjoerg continue; 380525944Sjoerg 380625944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 380745152Sphk if (sp->pp_mode != IFF_CISCO && 380825944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 380925944Sjoerg continue; 381025944Sjoerg 381125944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 381225944Sjoerg /* No keepalive packets got. Stop the interface. */ 381340008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 381425944Sjoerg if_down (ifp); 381526018Sjoerg sppp_qflush (&sp->pp_cpq); 381645152Sphk if (sp->pp_mode != IFF_CISCO) { 381725944Sjoerg /* XXX */ 381825944Sjoerg /* Shut down the PPP link. */ 381925944Sjoerg lcp.Down(sp); 382025944Sjoerg /* Initiate negotiation. XXX */ 382125944Sjoerg lcp.Up(sp); 382225944Sjoerg } 38234910Swollman } 382425944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 382525944Sjoerg ++sp->pp_alivecnt; 382645152Sphk if (sp->pp_mode == IFF_CISCO) 382725944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 382825944Sjoerg sp->pp_rseq); 382925944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 383025944Sjoerg long nmagic = htonl (sp->lcp.magic); 383125944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 383225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 383325944Sjoerg sp->lcp.echoid, 4, &nmagic); 383425944Sjoerg } 38354910Swollman } 383625944Sjoerg splx(s); 383742064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 38384910Swollman} 38394910Swollman 384025944Sjoerg/* 384125944Sjoerg * Get both IP addresses. 384225944Sjoerg */ 384325944Sjoergstatic void 384430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 384525944Sjoerg{ 384625944Sjoerg struct ifnet *ifp = &sp->pp_if; 384725944Sjoerg struct ifaddr *ifa; 384830300Sjoerg struct sockaddr_in *si, *sm; 384925944Sjoerg u_long ssrc, ddst; 385025944Sjoerg 385140010Sjoerg sm = NULL; 385225944Sjoerg ssrc = ddst = 0L; 385325944Sjoerg /* 385425944Sjoerg * Pick the first AF_INET address from the list, 385525944Sjoerg * aliases don't make any sense on a p2p link anyway. 385625944Sjoerg */ 385742065Sphk si = 0; 385842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 385942065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 386042104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 386171959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 386240008Sjoerg ifa; 386371959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 386442104Sphk#else 386542104Sphk for (ifa = ifp->if_addrlist; 386642104Sphk ifa; 386742104Sphk ifa = ifa->ifa_next) 386840008Sjoerg#endif 386925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 387025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 387130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 387225944Sjoerg if (si) 387325944Sjoerg break; 387425944Sjoerg } 387525944Sjoerg if (ifa) { 387630300Sjoerg if (si && si->sin_addr.s_addr) { 387725944Sjoerg ssrc = si->sin_addr.s_addr; 387830300Sjoerg if (srcmask) 387930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 388030300Sjoerg } 388125944Sjoerg 388225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 388325944Sjoerg if (si && si->sin_addr.s_addr) 388425944Sjoerg ddst = si->sin_addr.s_addr; 388525944Sjoerg } 388625944Sjoerg 388725944Sjoerg if (dst) *dst = ntohl(ddst); 388825944Sjoerg if (src) *src = ntohl(ssrc); 388925944Sjoerg} 389025944Sjoerg 389125944Sjoerg/* 389225944Sjoerg * Set my IP address. Must be called at splimp. 389325944Sjoerg */ 389425944Sjoergstatic void 389525944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 389625944Sjoerg{ 389742104Sphk STDDCL; 389825944Sjoerg struct ifaddr *ifa; 389925944Sjoerg struct sockaddr_in *si; 390025944Sjoerg 390125944Sjoerg /* 390225944Sjoerg * Pick the first AF_INET address from the list, 390325944Sjoerg * aliases don't make any sense on a p2p link anyway. 390425944Sjoerg */ 390542065Sphk si = 0; 390642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 390742065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 390842104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 390971959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 391040008Sjoerg ifa; 391171959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 391242104Sphk#else 391342104Sphk for (ifa = ifp->if_addrlist; 391442104Sphk ifa; 391542104Sphk ifa = ifa->ifa_next) 391640008Sjoerg#endif 391740008Sjoerg { 391840008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 391940008Sjoerg { 392025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 392125944Sjoerg if (si) 392225944Sjoerg break; 392325944Sjoerg } 392440008Sjoerg } 392540008Sjoerg 392625944Sjoerg if (ifa && si) 392742104Sphk { 392842104Sphk int error; 392942104Sphk#if __NetBSD_Version__ >= 103080000 393042104Sphk struct sockaddr_in new_sin = *si; 393142104Sphk 393242104Sphk new_sin.sin_addr.s_addr = htonl(src); 393342104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 393442104Sphk if(debug && error) 393542104Sphk { 393642104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 393742104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 393842104Sphk } 393942104Sphk#else 394042104Sphk /* delete old route */ 394142104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 394242104Sphk if(debug && error) 394342104Sphk { 394442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 394542104Sphk SPP_ARGS(ifp), error); 394642104Sphk } 394742104Sphk 394842104Sphk /* set new address */ 394925944Sjoerg si->sin_addr.s_addr = htonl(src); 395025944Sjoerg 395142104Sphk /* add new route */ 395270199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 395342104Sphk if (debug && error) 395442104Sphk { 395542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 395642104Sphk SPP_ARGS(ifp), error); 395742104Sphk } 395842104Sphk#endif 395942104Sphk } 396070199Sjhay} 396142104Sphk 396230300Sjoergstatic int 396338343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 396430300Sjoerg{ 396538343Sbde u_long subcmd; 396630300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 396730300Sjoerg struct spppreq spr; 396830300Sjoerg 396930300Sjoerg /* 397030300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 397130300Sjoerg * Check the cmd word first before attempting to fetch all the 397230300Sjoerg * data. 397330300Sjoerg */ 397430300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 397530300Sjoerg return EFAULT; 397630300Sjoerg 397730300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 397830300Sjoerg return EFAULT; 397930300Sjoerg 398030300Sjoerg switch (subcmd) { 398130300Sjoerg case SPPPIOGDEFS: 398230300Sjoerg if (cmd != SIOCGIFGENERIC) 398330300Sjoerg return EINVAL; 398430300Sjoerg /* 398530300Sjoerg * We copy over the entire current state, but clean 398630300Sjoerg * out some of the stuff we don't wanna pass up. 398730300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 398830300Sjoerg * called by any user. No need to ever get PAP or 398930300Sjoerg * CHAP secrets back to userland anyway. 399030300Sjoerg */ 399130300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 399230300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 399330300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 399430300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 399530300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 399630300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 399730300Sjoerg 399830300Sjoerg case SPPPIOSDEFS: 399930300Sjoerg if (cmd != SIOCSIFGENERIC) 400030300Sjoerg return EINVAL; 400130300Sjoerg /* 400230300Sjoerg * We have a very specific idea of which fields we allow 400330300Sjoerg * being passed back from userland, so to not clobber our 400430300Sjoerg * current state. For one, we only allow setting 400530300Sjoerg * anything if LCP is in dead phase. Once the LCP 400630300Sjoerg * negotiations started, the authentication settings must 400730300Sjoerg * not be changed again. (The administrator can force an 400830300Sjoerg * ifconfig down in order to get LCP back into dead 400930300Sjoerg * phase.) 401030300Sjoerg * 401130300Sjoerg * Also, we only allow for authentication parameters to be 401230300Sjoerg * specified. 401330300Sjoerg * 401430300Sjoerg * XXX Should allow to set or clear pp_flags. 401530300Sjoerg * 401630300Sjoerg * Finally, if the respective authentication protocol to 401730300Sjoerg * be used is set differently than 0, but the secret is 401830300Sjoerg * passed as all zeros, we don't trash the existing secret. 401930300Sjoerg * This allows an administrator to change the system name 402030300Sjoerg * only without clobbering the secret (which he didn't get 402130300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 402230300Sjoerg * secrets are cleared if the authentication protocol is 402330300Sjoerg * reset to 0. 402430300Sjoerg */ 402530300Sjoerg if (sp->pp_phase != PHASE_DEAD) 402630300Sjoerg return EBUSY; 402730300Sjoerg 402830300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 402930300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 403030300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 403130300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 403230300Sjoerg return EINVAL; 403330300Sjoerg 403430300Sjoerg if (spr.defs.myauth.proto == 0) 403530300Sjoerg /* resetting myauth */ 403630300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 403730300Sjoerg else { 403830300Sjoerg /* setting/changing myauth */ 403930300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 404030300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 404130300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 404230300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 404330300Sjoerg AUTHKEYLEN); 404430300Sjoerg } 404530300Sjoerg if (spr.defs.hisauth.proto == 0) 404630300Sjoerg /* resetting hisauth */ 404730300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 404830300Sjoerg else { 404930300Sjoerg /* setting/changing hisauth */ 405030300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 405130300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 405230300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 405330300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 405430300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 405530300Sjoerg AUTHKEYLEN); 405630300Sjoerg } 405730300Sjoerg break; 405830300Sjoerg 405930300Sjoerg default: 406030300Sjoerg return EINVAL; 406130300Sjoerg } 406230300Sjoerg 406330300Sjoerg return 0; 406430300Sjoerg} 406530300Sjoerg 406630300Sjoergstatic void 406730300Sjoergsppp_phase_network(struct sppp *sp) 406830300Sjoerg{ 406942066Sphk STDDCL; 407030300Sjoerg int i; 407130300Sjoerg u_long mask; 407230300Sjoerg 407330300Sjoerg sp->pp_phase = PHASE_NETWORK; 407430300Sjoerg 407542066Sphk if (debug) 407642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 407742066Sphk sppp_phase_name(sp->pp_phase)); 407830300Sjoerg 407930300Sjoerg /* Notify NCPs now. */ 408030300Sjoerg for (i = 0; i < IDX_COUNT; i++) 408130300Sjoerg if ((cps[i])->flags & CP_NCP) 408230300Sjoerg (cps[i])->Open(sp); 408330300Sjoerg 408430300Sjoerg /* Send Up events to all NCPs. */ 408530300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 408630300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 408730300Sjoerg (cps[i])->Up(sp); 408830300Sjoerg 408930300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 409030300Sjoerg sppp_lcp_check_and_close(sp); 409130300Sjoerg} 409230300Sjoerg 409370199Sjhay 409425706Sjoergstatic const char * 409525944Sjoergsppp_cp_type_name(u_char type) 40964910Swollman{ 409730300Sjoerg static char buf[12]; 40984910Swollman switch (type) { 409930300Sjoerg case CONF_REQ: return "conf-req"; 410030300Sjoerg case CONF_ACK: return "conf-ack"; 410130300Sjoerg case CONF_NAK: return "conf-nak"; 410230300Sjoerg case CONF_REJ: return "conf-rej"; 410330300Sjoerg case TERM_REQ: return "term-req"; 410430300Sjoerg case TERM_ACK: return "term-ack"; 410530300Sjoerg case CODE_REJ: return "code-rej"; 410630300Sjoerg case PROTO_REJ: return "proto-rej"; 410730300Sjoerg case ECHO_REQ: return "echo-req"; 410830300Sjoerg case ECHO_REPLY: return "echo-reply"; 410930300Sjoerg case DISC_REQ: return "discard-req"; 41104910Swollman } 411144145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 411230300Sjoerg return buf; 41134910Swollman} 41144910Swollman 411525706Sjoergstatic const char * 411630300Sjoergsppp_auth_type_name(u_short proto, u_char type) 411730300Sjoerg{ 411830300Sjoerg static char buf[12]; 411930300Sjoerg switch (proto) { 412030300Sjoerg case PPP_CHAP: 412130300Sjoerg switch (type) { 412230300Sjoerg case CHAP_CHALLENGE: return "challenge"; 412330300Sjoerg case CHAP_RESPONSE: return "response"; 412430300Sjoerg case CHAP_SUCCESS: return "success"; 412530300Sjoerg case CHAP_FAILURE: return "failure"; 412630300Sjoerg } 412730300Sjoerg case PPP_PAP: 412830300Sjoerg switch (type) { 412930300Sjoerg case PAP_REQ: return "req"; 413030300Sjoerg case PAP_ACK: return "ack"; 413130300Sjoerg case PAP_NAK: return "nak"; 413230300Sjoerg } 413330300Sjoerg } 413444145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 413530300Sjoerg return buf; 413630300Sjoerg} 413730300Sjoerg 413830300Sjoergstatic const char * 413925944Sjoergsppp_lcp_opt_name(u_char opt) 41404910Swollman{ 414130300Sjoerg static char buf[12]; 414225944Sjoerg switch (opt) { 414330300Sjoerg case LCP_OPT_MRU: return "mru"; 414430300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 414530300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 414630300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 414730300Sjoerg case LCP_OPT_MAGIC: return "magic"; 414830300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 414930300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 41504910Swollman } 415144145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 415230300Sjoerg return buf; 41534910Swollman} 41544910Swollman 415525944Sjoergstatic const char * 415625944Sjoergsppp_ipcp_opt_name(u_char opt) 415725944Sjoerg{ 415830300Sjoerg static char buf[12]; 415925944Sjoerg switch (opt) { 416030300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 416130300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 416230300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 416325944Sjoerg } 416444145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 416530300Sjoerg return buf; 416625944Sjoerg} 416725944Sjoerg 416825944Sjoergstatic const char * 416925944Sjoergsppp_state_name(int state) 417025944Sjoerg{ 417125944Sjoerg switch (state) { 417225944Sjoerg case STATE_INITIAL: return "initial"; 417325944Sjoerg case STATE_STARTING: return "starting"; 417425944Sjoerg case STATE_CLOSED: return "closed"; 417525944Sjoerg case STATE_STOPPED: return "stopped"; 417625944Sjoerg case STATE_CLOSING: return "closing"; 417725944Sjoerg case STATE_STOPPING: return "stopping"; 417825944Sjoerg case STATE_REQ_SENT: return "req-sent"; 417925944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 418025944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 418125944Sjoerg case STATE_OPENED: return "opened"; 418225944Sjoerg } 418325944Sjoerg return "illegal"; 418425944Sjoerg} 418525944Sjoerg 418625944Sjoergstatic const char * 418725944Sjoergsppp_phase_name(enum ppp_phase phase) 418825944Sjoerg{ 418925944Sjoerg switch (phase) { 419025944Sjoerg case PHASE_DEAD: return "dead"; 419125944Sjoerg case PHASE_ESTABLISH: return "establish"; 419225944Sjoerg case PHASE_TERMINATE: return "terminate"; 419325944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 419425944Sjoerg case PHASE_NETWORK: return "network"; 419525944Sjoerg } 419625944Sjoerg return "illegal"; 419725944Sjoerg} 419825944Sjoerg 419925944Sjoergstatic const char * 420025944Sjoergsppp_proto_name(u_short proto) 420125944Sjoerg{ 420225944Sjoerg static char buf[12]; 420325944Sjoerg switch (proto) { 420425944Sjoerg case PPP_LCP: return "lcp"; 420525944Sjoerg case PPP_IPCP: return "ipcp"; 420630300Sjoerg case PPP_PAP: return "pap"; 420730300Sjoerg case PPP_CHAP: return "chap"; 420825944Sjoerg } 420944145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 421025944Sjoerg return buf; 421125944Sjoerg} 421225944Sjoerg 421312820Sphkstatic void 421430300Sjoergsppp_print_bytes(const u_char *p, u_short len) 42154910Swollman{ 421644145Sphk if (len) 421769211Sphk log(-1, " %*D", len, p, "-"); 42184910Swollman} 421925944Sjoerg 422030300Sjoergstatic void 422130300Sjoergsppp_print_string(const char *p, u_short len) 422230300Sjoerg{ 422330300Sjoerg u_char c; 422430300Sjoerg 422530300Sjoerg while (len-- > 0) { 422630300Sjoerg c = *p++; 422730300Sjoerg /* 422830300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 422930300Sjoerg * using only them, but we don't rely on it. */ 423030300Sjoerg if (c < ' ' || c > '~') 423169211Sphk log(-1, "\\x%x", c); 423230300Sjoerg else 423369211Sphk log(-1, "%c", c); 423430300Sjoerg } 423530300Sjoerg} 423630300Sjoerg 423730300Sjoergstatic const char * 423830300Sjoergsppp_dotted_quad(u_long addr) 423930300Sjoerg{ 424030300Sjoerg static char s[16]; 424130300Sjoerg sprintf(s, "%d.%d.%d.%d", 424240008Sjoerg (int)((addr >> 24) & 0xff), 424340008Sjoerg (int)((addr >> 16) & 0xff), 424440008Sjoerg (int)((addr >> 8) & 0xff), 424538372Sbde (int)(addr & 0xff)); 424630300Sjoerg return s; 424730300Sjoerg} 424830300Sjoerg 424930300Sjoergstatic int 425030300Sjoergsppp_strnlen(u_char *p, int max) 425130300Sjoerg{ 425230300Sjoerg int len; 425330300Sjoerg 425430300Sjoerg for (len = 0; len < max && *p; ++p) 425530300Sjoerg ++len; 425630300Sjoerg return len; 425730300Sjoerg} 425830300Sjoerg 425930300Sjoerg/* a dummy, used to drop uninteresting events */ 426030300Sjoergstatic void 426130300Sjoergsppp_null(struct sppp *unused) 426230300Sjoerg{ 426330300Sjoerg /* do just nothing */ 426430300Sjoerg} 4265