if_spppsubr.c revision 69152
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 69152 2000-11-25 07:35:38Z jlemon $ 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> 4124204Sbde#include <sys/sockio.h> 424910Swollman#include <sys/socket.h> 4325706Sjoerg#include <sys/syslog.h> 4442104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4559604Sobrien#include <sys/random.h> 4642104Sphk#endif 4729024Sbde#include <sys/malloc.h> 484910Swollman#include <sys/mbuf.h> 4940008Sjoerg 5040008Sjoerg#if defined (__OpenBSD__) 5140008Sjoerg#include <sys/md5k.h> 5240008Sjoerg#else 5330300Sjoerg#include <sys/md5.h> 5440008Sjoerg#endif 554910Swollman 564910Swollman#include <net/if.h> 574910Swollman#include <net/netisr.h> 584910Swollman#include <net/if_types.h> 5942104Sphk#include <net/route.h> 604910Swollman 6140008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6240008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6340008Sjoerg#endif 6442104Sphk 6530300Sjoerg#include <machine/stdarg.h> 6630300Sjoerg 674910Swollman#ifdef INET 684910Swollman#include <netinet/in.h> 694910Swollman#include <netinet/in_systm.h> 704910Swollman#include <netinet/in_var.h> 714910Swollman#include <netinet/ip.h> 724910Swollman#include <netinet/tcp.h> 7340008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7440008Sjoerg# include <netinet/if_ether.h> 7540008Sjoerg# else 7640008Sjoerg# include <net/ethertypes.h> 7740008Sjoerg# endif 7832350Seivind#else 7940008Sjoerg# error Huh? sppp without INET? 804910Swollman#endif 814910Swollman 8211819Sjulian#ifdef IPX 8311819Sjulian#include <netipx/ipx.h> 8411819Sjulian#include <netipx/ipx_if.h> 8511819Sjulian#endif 8611819Sjulian 874910Swollman#ifdef NS 884910Swollman#include <netns/ns.h> 894910Swollman#include <netns/ns_if.h> 904910Swollman#endif 914910Swollman 924910Swollman#include <net/if_sppp.h> 934910Swollman 9442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9542064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9642064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 9742104Sphk# define IOCTL_CMD_T u_long 9840008Sjoerg#else 9942064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10042064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10142104Sphk# define IOCTL_CMD_T int 10240008Sjoerg#endif 10342104Sphk 1044910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1054910Swollman 10625944Sjoerg/* 10725944Sjoerg * Interface flags that can be set in an ifconfig command. 10825944Sjoerg * 10925955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11025944Sjoerg * as being administrative openable, but won't be opened to begin 11125944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11225944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11325955Sjoerg * 11425955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11525955Sjoerg * arrive to be sent. 11630300Sjoerg * 11730300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 11830300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 11930300Sjoerg * like 12030300Sjoerg * 12130300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12230300Sjoerg * 12330300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12430300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12525944Sjoerg */ 12625944Sjoerg 12725955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 12825955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 12945152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13025944Sjoerg 13130300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13230300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13330300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13430300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13530300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13630300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 13730300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 13830300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 13930300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14030300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1414910Swollman 14225944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 14325944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 14425944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 14525944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 14625944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 14725944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 14825944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 14925944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15025944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15125944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15225944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1534910Swollman 15430300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 15530300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 15630300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 15730300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 15830300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 15930300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16030300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16130300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1624910Swollman 16325944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 16425944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 16525944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1664910Swollman 16730300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 16830300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 16930300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1704910Swollman 17130300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17230300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 17330300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 17430300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 17530300Sjoerg 17630300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 17730300Sjoerg 17830300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 17930300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18030300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18130300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18230300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 18330300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 18430300Sjoerg 18525944Sjoerg/* states are named and numbered according to RFC 1661 */ 18625944Sjoerg#define STATE_INITIAL 0 18725944Sjoerg#define STATE_STARTING 1 18825944Sjoerg#define STATE_CLOSED 2 18925944Sjoerg#define STATE_STOPPED 3 19025944Sjoerg#define STATE_CLOSING 4 19125944Sjoerg#define STATE_STOPPING 5 19225944Sjoerg#define STATE_REQ_SENT 6 19325944Sjoerg#define STATE_ACK_RCVD 7 19425944Sjoerg#define STATE_ACK_SENT 8 19525944Sjoerg#define STATE_OPENED 9 19625944Sjoerg 1974910Swollmanstruct ppp_header { 19811189Sjkh u_char address; 19911189Sjkh u_char control; 20011189Sjkh u_short protocol; 2014910Swollman}; 2024910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2034910Swollman 2044910Swollmanstruct lcp_header { 20511189Sjkh u_char type; 20611189Sjkh u_char ident; 20711189Sjkh u_short len; 2084910Swollman}; 2094910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2104910Swollman 2114910Swollmanstruct cisco_packet { 21211189Sjkh u_long type; 21311189Sjkh u_long par1; 21411189Sjkh u_long par2; 21511189Sjkh u_short rel; 21611189Sjkh u_short time0; 21711189Sjkh u_short time1; 2184910Swollman}; 2194910Swollman#define CISCO_PACKET_LEN 18 2204910Swollman 22125944Sjoerg/* 22225944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 22325944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 22425944Sjoerg * case you can't make sense out of these abbreviation; it will also 22525944Sjoerg * explain the semantics related to the various events and actions. 22625944Sjoerg */ 22725944Sjoergstruct cp { 22825944Sjoerg u_short proto; /* PPP control protocol number */ 22925944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23025944Sjoerg u_char flags; 23125944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23225944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 23325944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 23425944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 23525944Sjoerg const char *name; /* name of this control protocol */ 23625944Sjoerg /* event handlers */ 23725944Sjoerg void (*Up)(struct sppp *sp); 23825944Sjoerg void (*Down)(struct sppp *sp); 23925944Sjoerg void (*Open)(struct sppp *sp); 24025944Sjoerg void (*Close)(struct sppp *sp); 24125944Sjoerg void (*TO)(void *sp); 24225944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 24325944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 24425944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 24525944Sjoerg /* actions */ 24625944Sjoerg void (*tlu)(struct sppp *sp); 24725944Sjoerg void (*tld)(struct sppp *sp); 24825944Sjoerg void (*tls)(struct sppp *sp); 24925944Sjoerg void (*tlf)(struct sppp *sp); 25025944Sjoerg void (*scr)(struct sppp *sp); 25125944Sjoerg}; 25225944Sjoerg 25312820Sphkstatic struct sppp *spppq; 25442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 25530300Sjoergstatic struct callout_handle keepalive_ch; 25640008Sjoerg#endif 2574910Swollman 25842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 25940008Sjoerg#define SPP_FMT "%s%d: " 26040008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26140008Sjoerg#else 26240008Sjoerg#define SPP_FMT "%s: " 26340008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 26440008Sjoerg#endif 26540008Sjoerg 2664910Swollman/* 2674910Swollman * The following disgusting hack gets around the problem that IP TOS 2684910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2694910Swollman * priority queue. To decide if traffic is interactive, we check that 2704910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27130300Sjoerg * 27230300Sjoerg * XXX is this really still necessary? - joerg - 2734910Swollman */ 27411189Sjkhstatic u_short interactive_ports[8] = { 2754910Swollman 0, 513, 0, 0, 2764910Swollman 0, 21, 0, 23, 2774910Swollman}; 2784910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2794910Swollman 28025944Sjoerg/* almost every function needs these */ 28125944Sjoerg#define STDDCL \ 28225944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 28325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 28411189Sjkh 28530300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 28625944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2874910Swollman 28825944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 28925944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29025944Sjoerg 29125944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29225944Sjoerg struct mbuf *m); 29325944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 29425944Sjoerg u_char ident, u_short len, void *data); 29542104Sphk/* static void sppp_cp_timeout(void *arg); */ 29625944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 29725944Sjoerg int newstate); 29830300Sjoergstatic void sppp_auth_send(const struct cp *cp, 29942104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30030300Sjoerg ...); 30125944Sjoerg 30225944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 30325944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 30425944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 30525944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 30625944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 30725944Sjoerg 30830300Sjoergstatic void sppp_null(struct sppp *sp); 30930300Sjoerg 31025944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31125944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31225944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 31325944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 31425944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 31525944Sjoergstatic void sppp_lcp_TO(void *sp); 31625944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 31725944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 31825944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 31925944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32225944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 32325944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 32430300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 32530300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 32625944Sjoerg 32725944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 32825944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 32925944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33025944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33125944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33225944Sjoergstatic void sppp_ipcp_TO(void *sp); 33325944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33425944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33525944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33625944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 33925944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34025944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34125944Sjoerg 34230300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 34330300Sjoergstatic void sppp_pap_init(struct sppp *sp); 34430300Sjoergstatic void sppp_pap_open(struct sppp *sp); 34530300Sjoergstatic void sppp_pap_close(struct sppp *sp); 34630300Sjoergstatic void sppp_pap_TO(void *sp); 34730300Sjoergstatic void sppp_pap_my_TO(void *sp); 34830300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 34930300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 35030300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 35130300Sjoerg 35230300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 35330300Sjoergstatic void sppp_chap_init(struct sppp *sp); 35430300Sjoergstatic void sppp_chap_open(struct sppp *sp); 35530300Sjoergstatic void sppp_chap_close(struct sppp *sp); 35630300Sjoergstatic void sppp_chap_TO(void *sp); 35730300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 35830300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 35930300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 36030300Sjoerg 36130300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 36225944Sjoergstatic const char *sppp_cp_type_name(u_char type); 36330300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 36430300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 36525944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 36625944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 36725944Sjoergstatic const char *sppp_proto_name(u_short proto); 36830300Sjoergstatic const char *sppp_state_name(int state); 36938343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37030300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37130300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 37230300Sjoerg u_long *srcmask); 37325944Sjoergstatic void sppp_keepalive(void *dummy); 37430300Sjoergstatic void sppp_phase_network(struct sppp *sp); 37530300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 37630300Sjoergstatic void sppp_print_string(const char *p, u_short len); 37725944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 37825944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 37925944Sjoerg 38025944Sjoerg/* our control protocol descriptors */ 38133181Seivindstatic const struct cp lcp = { 38225944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 38325944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 38425944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 38525944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 38625944Sjoerg sppp_lcp_scr 38725944Sjoerg}; 38825944Sjoerg 38933181Seivindstatic const struct cp ipcp = { 39025944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 39125944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 39225944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 39325944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 39425944Sjoerg sppp_ipcp_scr 39525944Sjoerg}; 39625944Sjoerg 39733181Seivindstatic const struct cp pap = { 39830300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 39930300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 40030300Sjoerg sppp_pap_TO, 0, 0, 0, 40130300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 40230300Sjoerg sppp_pap_scr 40330300Sjoerg}; 40430300Sjoerg 40533181Seivindstatic const struct cp chap = { 40630300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 40730300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 40830300Sjoerg sppp_chap_TO, 0, 0, 0, 40930300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 41030300Sjoerg sppp_chap_scr 41130300Sjoerg}; 41230300Sjoerg 41333181Seivindstatic const struct cp *cps[IDX_COUNT] = { 41425944Sjoerg &lcp, /* IDX_LCP */ 41525944Sjoerg &ipcp, /* IDX_IPCP */ 41630300Sjoerg &pap, /* IDX_PAP */ 41730300Sjoerg &chap, /* IDX_CHAP */ 41825944Sjoerg}; 41925944Sjoerg 42025944Sjoerg 42125944Sjoerg/* 42225944Sjoerg * Exported functions, comprising our interface to the lower layer. 4234910Swollman */ 4244910Swollman 4254910Swollman/* 4264910Swollman * Process the received packet. 4274910Swollman */ 42825706Sjoergvoid 42925706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4304910Swollman{ 4314910Swollman struct ppp_header *h; 4324910Swollman struct ifqueue *inq = 0; 43311189Sjkh int s; 43425944Sjoerg struct sppp *sp = (struct sppp *)ifp; 43525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 4364910Swollman 4374910Swollman if (ifp->if_flags & IFF_UP) 4384910Swollman /* Count received bytes, add FCS and one flag */ 4394910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 4404910Swollman 4414910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 4424910Swollman /* Too small packet, drop it. */ 44325944Sjoerg if (debug) 44425706Sjoerg log(LOG_DEBUG, 44540008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 44640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 44725944Sjoerg drop: 44825944Sjoerg ++ifp->if_ierrors; 44925944Sjoerg ++ifp->if_iqdrops; 4504910Swollman m_freem (m); 4514910Swollman return; 4524910Swollman } 4534910Swollman 4544910Swollman /* Get PPP header. */ 4554910Swollman h = mtod (m, struct ppp_header*); 4564910Swollman m_adj (m, PPP_HEADER_LEN); 4574910Swollman 4584910Swollman switch (h->address) { 4594910Swollman case PPP_ALLSTATIONS: 4604910Swollman if (h->control != PPP_UI) 4614910Swollman goto invalid; 46245152Sphk if (sp->pp_mode == IFF_CISCO) { 46325944Sjoerg if (debug) 46425706Sjoerg log(LOG_DEBUG, 46540008Sjoerg SPP_FMT "PPP packet in Cisco mode " 46625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 46740008Sjoerg SPP_ARGS(ifp), 46825706Sjoerg h->address, h->control, ntohs(h->protocol)); 46911189Sjkh goto drop; 47011189Sjkh } 4714910Swollman switch (ntohs (h->protocol)) { 4724910Swollman default: 47325944Sjoerg if (debug) 47425706Sjoerg log(LOG_DEBUG, 47544145Sphk SPP_FMT "rejecting protocol " 47625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 47740008Sjoerg SPP_ARGS(ifp), 47825706Sjoerg h->address, h->control, ntohs(h->protocol)); 47944145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 48044145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 48144145Sphk ++sp->pp_seq, m->m_pkthdr.len + 2, 48244145Sphk &h->protocol); 4834910Swollman ++ifp->if_noproto; 4844910Swollman goto drop; 4854910Swollman case PPP_LCP: 48630300Sjoerg sppp_cp_input(&lcp, sp, m); 4874910Swollman m_freem (m); 4884910Swollman return; 48930300Sjoerg case PPP_PAP: 49030300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49130300Sjoerg sppp_pap_input(sp, m); 49230300Sjoerg m_freem (m); 49330300Sjoerg return; 49430300Sjoerg case PPP_CHAP: 49530300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49630300Sjoerg sppp_chap_input(sp, m); 49730300Sjoerg m_freem (m); 49830300Sjoerg return; 4994910Swollman#ifdef INET 5004910Swollman case PPP_IPCP: 50125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 50230300Sjoerg sppp_cp_input(&ipcp, sp, m); 5034910Swollman m_freem (m); 5044910Swollman return; 5054910Swollman case PPP_IP: 50625944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5074910Swollman schednetisr (NETISR_IP); 5084910Swollman inq = &ipintrq; 5094910Swollman } 5104910Swollman break; 5114910Swollman#endif 51212495Speter#ifdef IPX 51312495Speter case PPP_IPX: 51412495Speter /* IPX IPXCP not implemented yet */ 51525944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 51612495Speter schednetisr (NETISR_IPX); 51712495Speter inq = &ipxintrq; 51812495Speter } 51912495Speter break; 52012495Speter#endif 5214910Swollman#ifdef NS 5224910Swollman case PPP_XNS: 5234910Swollman /* XNS IDPCP not implemented yet */ 52425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5254910Swollman schednetisr (NETISR_NS); 5264910Swollman inq = &nsintrq; 5274910Swollman } 5284910Swollman break; 5294910Swollman#endif 5304910Swollman } 5314910Swollman break; 5324910Swollman case CISCO_MULTICAST: 5334910Swollman case CISCO_UNICAST: 5344910Swollman /* Don't check the control field here (RFC 1547). */ 53545152Sphk if (sp->pp_mode != IFF_CISCO) { 53625944Sjoerg if (debug) 53725706Sjoerg log(LOG_DEBUG, 53840008Sjoerg SPP_FMT "Cisco packet in PPP mode " 53925706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54040008Sjoerg SPP_ARGS(ifp), 54125706Sjoerg h->address, h->control, ntohs(h->protocol)); 54211189Sjkh goto drop; 54311189Sjkh } 5444910Swollman switch (ntohs (h->protocol)) { 5454910Swollman default: 5464910Swollman ++ifp->if_noproto; 5474910Swollman goto invalid; 5484910Swollman case CISCO_KEEPALIVE: 5494910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5504910Swollman m_freem (m); 5514910Swollman return; 5524910Swollman#ifdef INET 5534910Swollman case ETHERTYPE_IP: 5544910Swollman schednetisr (NETISR_IP); 5554910Swollman inq = &ipintrq; 5564910Swollman break; 5574910Swollman#endif 55854263Sshin#ifdef INET6 55954263Sshin case ETHERTYPE_IPV6: 56054263Sshin schednetisr (NETISR_IPV6); 56154263Sshin inq = &ip6intrq; 56254263Sshin break; 56354263Sshin#endif 56412495Speter#ifdef IPX 56512495Speter case ETHERTYPE_IPX: 56612495Speter schednetisr (NETISR_IPX); 56712495Speter inq = &ipxintrq; 56812495Speter break; 56912495Speter#endif 5704910Swollman#ifdef NS 5714910Swollman case ETHERTYPE_NS: 5724910Swollman schednetisr (NETISR_NS); 5734910Swollman inq = &nsintrq; 5744910Swollman break; 5754910Swollman#endif 5764910Swollman } 5774910Swollman break; 57825944Sjoerg default: /* Invalid PPP packet. */ 57925944Sjoerg invalid: 58025944Sjoerg if (debug) 58125944Sjoerg log(LOG_DEBUG, 58240008Sjoerg SPP_FMT "invalid input packet " 58325944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 58440008Sjoerg SPP_ARGS(ifp), 58525944Sjoerg h->address, h->control, ntohs(h->protocol)); 58625944Sjoerg goto drop; 5874910Swollman } 5884910Swollman 5894910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 5904910Swollman goto drop; 5914910Swollman 5924910Swollman /* Check queue. */ 59369152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 59425944Sjoerg if (debug) 59540008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 59640008Sjoerg SPP_ARGS(ifp)); 5974910Swollman goto drop; 5984910Swollman } 5994910Swollman} 6004910Swollman 6014910Swollman/* 6024910Swollman * Enqueue transmit packet. 6034910Swollman */ 60412820Sphkstatic int 60525706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 60625706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6074910Swollman{ 6084910Swollman struct sppp *sp = (struct sppp*) ifp; 6094910Swollman struct ppp_header *h; 6104910Swollman struct ifqueue *ifq; 61125955Sjoerg int s, rv = 0; 61242066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6134910Swollman 61425944Sjoerg s = splimp(); 61525944Sjoerg 61625944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 61725944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 6184910Swollman m_freem (m); 6194910Swollman splx (s); 6204910Swollman return (ENETDOWN); 6214910Swollman } 6224910Swollman 62325944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 62425944Sjoerg /* 62525944Sjoerg * Interface is not yet running, but auto-dial. Need 62625944Sjoerg * to start LCP for it. 62725944Sjoerg */ 62825944Sjoerg ifp->if_flags |= IFF_RUNNING; 62925944Sjoerg splx(s); 63025944Sjoerg lcp.Open(sp); 63125944Sjoerg s = splimp(); 63225944Sjoerg } 63325944Sjoerg 6344910Swollman ifq = &ifp->if_snd; 6354910Swollman#ifdef INET 63612436Speter if (dst->sa_family == AF_INET) { 63740008Sjoerg /* XXX Check mbuf length here? */ 63812436Speter struct ip *ip = mtod (m, struct ip*); 63912436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6404910Swollman 64142104Sphk /* 64242104Sphk * When using dynamic local IP address assignment by using 64342104Sphk * 0.0.0.0 as a local address, the first TCP session will 64442104Sphk * not connect because the local TCP checksum is computed 64542104Sphk * using 0.0.0.0 which will later become our real IP address 64642104Sphk * so the TCP checksum computed at the remote end will 64742104Sphk * become invalid. So we 64842104Sphk * - don't let packets with src ip addr 0 thru 64942104Sphk * - we flag TCP packets with src ip 0 as an error 65042104Sphk */ 65142104Sphk 65242104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 65342104Sphk { 65442104Sphk m_freem(m); 65542104Sphk splx(s); 65642104Sphk if(ip->ip_p == IPPROTO_TCP) 65742104Sphk return(EADDRNOTAVAIL); 65842104Sphk else 65942104Sphk return(0); 66042104Sphk } 66142104Sphk 66242104Sphk /* 66342104Sphk * Put low delay, telnet, rlogin and ftp control packets 66442104Sphk * in front of the queue. 66542104Sphk */ 66669152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 66741686Sphk ; 66841686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 66912436Speter ifq = &sp->pp_fastq; 67041686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 67141686Sphk ; 67241686Sphk else if (ip->ip_p != IPPROTO_TCP) 67341686Sphk ; 67441686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 67541686Sphk ifq = &sp->pp_fastq; 67641686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 67741686Sphk ifq = &sp->pp_fastq; 6784910Swollman } 6794910Swollman#endif 6804910Swollman 6814910Swollman /* 6824910Swollman * Prepend general data packet PPP header. For now, IP only. 6834910Swollman */ 6844910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 6854910Swollman if (! m) { 68642066Sphk if (debug) 68740008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 68840008Sjoerg SPP_ARGS(ifp)); 68925944Sjoerg ++ifp->if_oerrors; 6904910Swollman splx (s); 6914910Swollman return (ENOBUFS); 6924910Swollman } 69340008Sjoerg /* 69440008Sjoerg * May want to check size of packet 69540008Sjoerg * (albeit due to the implementation it's always enough) 69640008Sjoerg */ 6974910Swollman h = mtod (m, struct ppp_header*); 69845152Sphk if (sp->pp_mode == IFF_CISCO) { 69928088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7004910Swollman h->control = 0; 7014910Swollman } else { 7024910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7034910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7044910Swollman } 7054910Swollman 7064910Swollman switch (dst->sa_family) { 7074910Swollman#ifdef INET 7084910Swollman case AF_INET: /* Internet Protocol */ 70945152Sphk if (sp->pp_mode == IFF_CISCO) 71011189Sjkh h->protocol = htons (ETHERTYPE_IP); 71111189Sjkh else { 71225955Sjoerg /* 71325955Sjoerg * Don't choke with an ENETDOWN early. It's 71425955Sjoerg * possible that we just started dialing out, 71525955Sjoerg * so don't drop the packet immediately. If 71625955Sjoerg * we notice that we run out of buffer space 71725955Sjoerg * below, we will however remember that we are 71825955Sjoerg * not ready to carry IP packets, and return 71925955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 72025955Sjoerg */ 72125955Sjoerg h->protocol = htons(PPP_IP); 72225955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 72325955Sjoerg rv = ENETDOWN; 72411189Sjkh } 7254910Swollman break; 7264910Swollman#endif 72754263Sshin#ifdef INET6 72854263Sshin case AF_INET6: /* Internet Protocol */ 72954263Sshin if (sp->pp_mode == IFF_CISCO) 73054263Sshin h->protocol = htons (ETHERTYPE_IPV6); 73154263Sshin else { 73254263Sshin goto nosupport; 73354263Sshin } 73454263Sshin break; 73554263Sshin#endif 7364910Swollman#ifdef NS 7374910Swollman case AF_NS: /* Xerox NS Protocol */ 73845152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 7394910Swollman ETHERTYPE_NS : PPP_XNS); 7404910Swollman break; 7414910Swollman#endif 74211819Sjulian#ifdef IPX 74312495Speter case AF_IPX: /* Novell IPX Protocol */ 74445152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 74512495Speter ETHERTYPE_IPX : PPP_IPX); 74611819Sjulian break; 74711819Sjulian#endif 74812820Sphknosupport: 7494910Swollman default: 7504910Swollman m_freem (m); 75125944Sjoerg ++ifp->if_oerrors; 7524910Swollman splx (s); 7534910Swollman return (EAFNOSUPPORT); 7544910Swollman } 7554910Swollman 7564910Swollman /* 7574910Swollman * Queue message on interface, and start output if interface 75869152Sjlemon * not yet active. Also adjust output byte count. 75969152Sjlemon * The packet length includes header, FCS and 1 flag, 76069152Sjlemon * according to RFC 1333. 7614910Swollman */ 76269152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 76325944Sjoerg ++ifp->if_oerrors; 76425955Sjoerg return (rv? rv: ENOBUFS); 7654910Swollman } 7664910Swollman return (0); 7674910Swollman} 7684910Swollman 76925706Sjoergvoid 77025706Sjoergsppp_attach(struct ifnet *ifp) 7714910Swollman{ 7724910Swollman struct sppp *sp = (struct sppp*) ifp; 7734910Swollman 7744910Swollman /* Initialize keepalive handler. */ 7754910Swollman if (! spppq) 77642064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 7774910Swollman 7784910Swollman /* Insert new entry into the keepalive list. */ 7794910Swollman sp->pp_next = spppq; 7804910Swollman spppq = sp; 7814910Swollman 78242064Sphk sp->pp_if.if_mtu = PP_MTU; 78342064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 7844910Swollman sp->pp_if.if_type = IFT_PPP; 7854910Swollman sp->pp_if.if_output = sppp_output; 78642104Sphk#if 0 78742064Sphk sp->pp_flags = PP_KEEPALIVE; 78842104Sphk#endif 7894910Swollman sp->pp_fastq.ifq_maxlen = 32; 79026018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 7914910Swollman sp->pp_loopcnt = 0; 7924910Swollman sp->pp_alivecnt = 0; 79311189Sjkh sp->pp_seq = 0; 7944910Swollman sp->pp_rseq = 0; 79525944Sjoerg sp->pp_phase = PHASE_DEAD; 79625944Sjoerg sp->pp_up = lcp.Up; 79725944Sjoerg sp->pp_down = lcp.Down; 79869152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 79969152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 80025944Sjoerg 80125944Sjoerg sppp_lcp_init(sp); 80225944Sjoerg sppp_ipcp_init(sp); 80330300Sjoerg sppp_pap_init(sp); 80430300Sjoerg sppp_chap_init(sp); 8054910Swollman} 8064910Swollman 80730300Sjoergvoid 80825706Sjoergsppp_detach(struct ifnet *ifp) 8094910Swollman{ 8104910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 81125944Sjoerg int i; 8124910Swollman 8134910Swollman /* Remove the entry from the keepalive list. */ 8144910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 8154910Swollman if (p == sp) { 8164910Swollman *q = p->pp_next; 8174910Swollman break; 8184910Swollman } 8194910Swollman 8204910Swollman /* Stop keepalive handler. */ 8214910Swollman if (! spppq) 82240008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 82325944Sjoerg 82425944Sjoerg for (i = 0; i < IDX_COUNT; i++) 82540008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 82640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 82769152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 82869152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 8294910Swollman} 8304910Swollman 8314910Swollman/* 8324910Swollman * Flush the interface output queue. 8334910Swollman */ 83425706Sjoergvoid 83525706Sjoergsppp_flush(struct ifnet *ifp) 8364910Swollman{ 8374910Swollman struct sppp *sp = (struct sppp*) ifp; 8384910Swollman 83925944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 84025944Sjoerg sppp_qflush (&sp->pp_fastq); 84126018Sjoerg sppp_qflush (&sp->pp_cpq); 8424910Swollman} 8434910Swollman 8444910Swollman/* 84511189Sjkh * Check if the output queue is empty. 84611189Sjkh */ 84712820Sphkint 84825706Sjoergsppp_isempty(struct ifnet *ifp) 84911189Sjkh{ 85011189Sjkh struct sppp *sp = (struct sppp*) ifp; 85125944Sjoerg int empty, s; 85211189Sjkh 85325944Sjoerg s = splimp(); 85426018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 85526018Sjoerg !sp->pp_if.if_snd.ifq_head; 85625944Sjoerg splx(s); 85711189Sjkh return (empty); 85811189Sjkh} 85911189Sjkh 86011189Sjkh/* 8614910Swollman * Get next packet to send. 8624910Swollman */ 86325706Sjoergstruct mbuf * 86425706Sjoergsppp_dequeue(struct ifnet *ifp) 8654910Swollman{ 8664910Swollman struct sppp *sp = (struct sppp*) ifp; 8674910Swollman struct mbuf *m; 86825944Sjoerg int s; 8694910Swollman 87025944Sjoerg s = splimp(); 87126018Sjoerg /* 87230300Sjoerg * Process only the control protocol queue until we have at 87330300Sjoerg * least one NCP open. 87426018Sjoerg * 87526018Sjoerg * Do always serve all three queues in Cisco mode. 87626018Sjoerg */ 87726018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 87826018Sjoerg if (m == NULL && 87945152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 88026018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 88126018Sjoerg if (m == NULL) 88226018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 88326018Sjoerg } 88426018Sjoerg splx(s); 88526018Sjoerg return m; 8864910Swollman} 8874910Swollman 8884910Swollman/* 88930300Sjoerg * Pick the next packet, do not remove it from the queue. 89030300Sjoerg */ 89130300Sjoergstruct mbuf * 89230300Sjoergsppp_pick(struct ifnet *ifp) 89330300Sjoerg{ 89430300Sjoerg struct sppp *sp = (struct sppp*)ifp; 89530300Sjoerg struct mbuf *m; 89630300Sjoerg int s; 89730300Sjoerg 89830300Sjoerg s= splimp (); 89930300Sjoerg 90030300Sjoerg m = sp->pp_cpq.ifq_head; 90130300Sjoerg if (m == NULL && 90245152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 90330300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 90430300Sjoerg m = sp->pp_if.if_snd.ifq_head; 90530300Sjoerg splx (s); 90630300Sjoerg return (m); 90730300Sjoerg} 90830300Sjoerg 90930300Sjoerg/* 91025944Sjoerg * Process an ioctl request. Called on low priority level. 9114910Swollman */ 91225944Sjoergint 91342104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 9144910Swollman{ 91525944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 91625944Sjoerg struct sppp *sp = (struct sppp*) ifp; 91730300Sjoerg int s, rv, going_up, going_down, newmode; 9184910Swollman 91925944Sjoerg s = splimp(); 92030300Sjoerg rv = 0; 92125944Sjoerg switch (cmd) { 92225944Sjoerg case SIOCAIFADDR: 92325944Sjoerg case SIOCSIFDSTADDR: 92425944Sjoerg break; 9254910Swollman 92625944Sjoerg case SIOCSIFADDR: 92725944Sjoerg if_up(ifp); 92825944Sjoerg /* fall through... */ 92911189Sjkh 93025944Sjoerg case SIOCSIFFLAGS: 93125944Sjoerg going_up = ifp->if_flags & IFF_UP && 93225944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 93325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 93425944Sjoerg ifp->if_flags & IFF_RUNNING; 93545152Sphk 93645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 93745152Sphk if (!newmode) 93845152Sphk newmode = ifp->if_flags & IFF_AUTO; 93945152Sphk if (!newmode) 94045152Sphk newmode = ifp->if_flags & IFF_CISCO; 94145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 94245152Sphk ifp->if_flags |= newmode; 94345152Sphk 94445152Sphk if (newmode != sp->pp_mode) { 94545152Sphk going_down = 1; 94645152Sphk if (!going_up) 94745152Sphk going_up = ifp->if_flags & IFF_RUNNING; 9484910Swollman } 9494910Swollman 95045152Sphk if (going_down) { 95145152Sphk if (sp->pp_mode != IFF_CISCO) 95245152Sphk lcp.Close(sp); 95345152Sphk else if (sp->pp_tlf) 95445152Sphk (sp->pp_tlf)(sp); 95526018Sjoerg sppp_flush(ifp); 95625944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 95745152Sphk sp->pp_mode = newmode; 95826018Sjoerg } 9594910Swollman 96045152Sphk if (going_up) { 96145152Sphk if (sp->pp_mode != IFF_CISCO) 96245152Sphk lcp.Close(sp); 96345152Sphk sp->pp_mode = newmode; 96445152Sphk if (sp->pp_mode == 0) { 96545152Sphk ifp->if_flags |= IFF_RUNNING; 96645152Sphk lcp.Open(sp); 96745152Sphk } 96845152Sphk if (sp->pp_mode == IFF_CISCO) { 96945152Sphk if (sp->pp_tls) 97045152Sphk (sp->pp_tls)(sp); 97145152Sphk ifp->if_flags |= IFF_RUNNING; 97245152Sphk } 97345152Sphk } 97445152Sphk 9754910Swollman break; 97611189Sjkh 97725944Sjoerg#ifdef SIOCSIFMTU 97825944Sjoerg#ifndef ifr_mtu 97925944Sjoerg#define ifr_mtu ifr_metric 98025944Sjoerg#endif 98125944Sjoerg case SIOCSIFMTU: 98225944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 98325944Sjoerg return (EINVAL); 98425944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 9854910Swollman break; 98625944Sjoerg#endif 98725944Sjoerg#ifdef SLIOCSETMTU 98825944Sjoerg case SLIOCSETMTU: 98925944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 99025944Sjoerg return (EINVAL); 99125944Sjoerg ifp->if_mtu = *(short*)data; 9924910Swollman break; 99325944Sjoerg#endif 99425944Sjoerg#ifdef SIOCGIFMTU 99525944Sjoerg case SIOCGIFMTU: 99625944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 99711189Sjkh break; 99825944Sjoerg#endif 99925944Sjoerg#ifdef SLIOCGETMTU 100025944Sjoerg case SLIOCGETMTU: 100125944Sjoerg *(short*)data = ifp->if_mtu; 10024910Swollman break; 100325944Sjoerg#endif 100425944Sjoerg case SIOCADDMULTI: 100525944Sjoerg case SIOCDELMULTI: 10064910Swollman break; 100711189Sjkh 100830300Sjoerg case SIOCGIFGENERIC: 100930300Sjoerg case SIOCSIFGENERIC: 101030300Sjoerg rv = sppp_params(sp, cmd, data); 101130300Sjoerg break; 101230300Sjoerg 101325944Sjoerg default: 101430300Sjoerg rv = ENOTTY; 10154910Swollman } 101625944Sjoerg splx(s); 101730300Sjoerg return rv; 10184910Swollman} 10194910Swollman 102025944Sjoerg 102125944Sjoerg/* 102225944Sjoerg * Cisco framing implementation. 102325944Sjoerg */ 102425944Sjoerg 10254910Swollman/* 10264910Swollman * Handle incoming Cisco keepalive protocol packets. 10274910Swollman */ 102830300Sjoergstatic void 102925706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 10304910Swollman{ 103125944Sjoerg STDDCL; 10324910Swollman struct cisco_packet *h; 103330300Sjoerg u_long me, mymask; 10344910Swollman 103527929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 103625706Sjoerg if (debug) 103725706Sjoerg log(LOG_DEBUG, 103840008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 103940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 10404910Swollman return; 10414910Swollman } 10424910Swollman h = mtod (m, struct cisco_packet*); 104325706Sjoerg if (debug) 104425706Sjoerg log(LOG_DEBUG, 104540008Sjoerg SPP_FMT "cisco input: %d bytes " 104625706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 104740008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 104840008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 104940008Sjoerg (u_int)h->time0, (u_int)h->time1); 10504910Swollman switch (ntohl (h->type)) { 10514910Swollman default: 105225706Sjoerg if (debug) 105340008Sjoerg addlog(SPP_FMT "cisco unknown packet type: 0x%lx\n", 105440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 10554910Swollman break; 10564910Swollman case CISCO_ADDR_REPLY: 10574910Swollman /* Reply on address request, ignore */ 10584910Swollman break; 10594910Swollman case CISCO_KEEPALIVE_REQ: 10604910Swollman sp->pp_alivecnt = 0; 10614910Swollman sp->pp_rseq = ntohl (h->par1); 10624910Swollman if (sp->pp_seq == sp->pp_rseq) { 10634910Swollman /* Local and remote sequence numbers are equal. 10644910Swollman * Probably, the line is in loopback mode. */ 106511189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 106640008Sjoerg printf (SPP_FMT "loopback\n", 106740008Sjoerg SPP_ARGS(ifp)); 106811189Sjkh sp->pp_loopcnt = 0; 106911189Sjkh if (ifp->if_flags & IFF_UP) { 107011189Sjkh if_down (ifp); 107126018Sjoerg sppp_qflush (&sp->pp_cpq); 107211189Sjkh } 107311189Sjkh } 10744910Swollman ++sp->pp_loopcnt; 10754910Swollman 10764910Swollman /* Generate new local sequence number */ 107742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 107835064Sphk sp->pp_seq = random(); 107940008Sjoerg#else 108040008Sjoerg sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 108140008Sjoerg#endif 108211189Sjkh break; 108311189Sjkh } 108430300Sjoerg sp->pp_loopcnt = 0; 108511189Sjkh if (! (ifp->if_flags & IFF_UP) && 108611189Sjkh (ifp->if_flags & IFF_RUNNING)) { 108730300Sjoerg if_up(ifp); 108840008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 108911189Sjkh } 10904910Swollman break; 10914910Swollman case CISCO_ADDR_REQ: 109230300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 109330300Sjoerg if (me != 0L) 109430300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 10954910Swollman break; 10964910Swollman } 10974910Swollman} 10984910Swollman 10994910Swollman/* 110025944Sjoerg * Send Cisco keepalive packet. 11014910Swollman */ 110212820Sphkstatic void 110325944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 110425944Sjoerg{ 110525944Sjoerg STDDCL; 110625944Sjoerg struct ppp_header *h; 110725944Sjoerg struct cisco_packet *ch; 110825944Sjoerg struct mbuf *m; 110942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 111035029Sphk struct timeval tv; 111140008Sjoerg#else 111240008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 111340008Sjoerg#endif 111425944Sjoerg 111542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 111636119Sphk getmicrouptime(&tv); 111740008Sjoerg#endif 111835029Sphk 111925944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 112025944Sjoerg if (! m) 112125944Sjoerg return; 112225944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 112325944Sjoerg m->m_pkthdr.rcvif = 0; 112425944Sjoerg 112525944Sjoerg h = mtod (m, struct ppp_header*); 112625944Sjoerg h->address = CISCO_MULTICAST; 112725944Sjoerg h->control = 0; 112825944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 112925944Sjoerg 113025944Sjoerg ch = (struct cisco_packet*) (h + 1); 113125944Sjoerg ch->type = htonl (type); 113225944Sjoerg ch->par1 = htonl (par1); 113325944Sjoerg ch->par2 = htonl (par2); 113425944Sjoerg ch->rel = -1; 113540008Sjoerg 113642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113735029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 113835029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 113940008Sjoerg#else 114040008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 114140008Sjoerg ch->time1 = htons ((u_short) t); 114240008Sjoerg#endif 114325944Sjoerg 114425944Sjoerg if (debug) 114525944Sjoerg log(LOG_DEBUG, 114640008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114740008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 114840008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 114925944Sjoerg 115069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 115169152Sjlemon ifp->if_oerrors++; 115225944Sjoerg} 115325944Sjoerg 115425944Sjoerg/* 115525944Sjoerg * PPP protocol implementation. 115625944Sjoerg */ 115725944Sjoerg 115825944Sjoerg/* 115925944Sjoerg * Send PPP control protocol packet. 116025944Sjoerg */ 116125944Sjoergstatic void 116225706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 116325706Sjoerg u_char ident, u_short len, void *data) 11644910Swollman{ 116525944Sjoerg STDDCL; 11664910Swollman struct ppp_header *h; 11674910Swollman struct lcp_header *lh; 11684910Swollman struct mbuf *m; 11694910Swollman 11704910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 11714910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 11724910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 11734910Swollman if (! m) 11744910Swollman return; 11754910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 11764910Swollman m->m_pkthdr.rcvif = 0; 11774910Swollman 11784910Swollman h = mtod (m, struct ppp_header*); 11794910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 11804910Swollman h->control = PPP_UI; /* Unnumbered Info */ 11814910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 11824910Swollman 11834910Swollman lh = (struct lcp_header*) (h + 1); 11844910Swollman lh->type = type; 11854910Swollman lh->ident = ident; 11864910Swollman lh->len = htons (LCP_HEADER_LEN + len); 11874910Swollman if (len) 11884910Swollman bcopy (data, lh+1, len); 11894910Swollman 119025706Sjoerg if (debug) { 119140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 119240008Sjoerg SPP_ARGS(ifp), 119325944Sjoerg sppp_proto_name(proto), 119425944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 119525944Sjoerg ntohs (lh->len)); 119644145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 119725706Sjoerg addlog(">\n"); 11984910Swollman } 119969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 120069152Sjlemon ifp->if_oerrors++; 12014910Swollman} 12024910Swollman 12034910Swollman/* 120425944Sjoerg * Handle incoming PPP control protocol packets. 12054910Swollman */ 120612820Sphkstatic void 120725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 12084910Swollman{ 120925944Sjoerg STDDCL; 121025944Sjoerg struct lcp_header *h; 121125944Sjoerg int len = m->m_pkthdr.len; 121225944Sjoerg int rv; 121325944Sjoerg u_char *p; 12144910Swollman 121525944Sjoerg if (len < 4) { 121625944Sjoerg if (debug) 121725944Sjoerg log(LOG_DEBUG, 121840008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 121940008Sjoerg SPP_ARGS(ifp), cp->name, len); 12204910Swollman return; 122125944Sjoerg } 122225944Sjoerg h = mtod (m, struct lcp_header*); 122325944Sjoerg if (debug) { 122425944Sjoerg log(LOG_DEBUG, 122540008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 122640008Sjoerg SPP_ARGS(ifp), cp->name, 122725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 122825944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 122944145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 123025944Sjoerg addlog(">\n"); 123125944Sjoerg } 123225944Sjoerg if (len > ntohs (h->len)) 123325944Sjoerg len = ntohs (h->len); 123430300Sjoerg p = (u_char *)(h + 1); 123525944Sjoerg switch (h->type) { 123625944Sjoerg case CONF_REQ: 123725944Sjoerg if (len < 4) { 123825944Sjoerg if (debug) 123940008Sjoerg addlog(SPP_FMT "%s invalid conf-req length %d\n", 124040008Sjoerg SPP_ARGS(ifp), cp->name, 124125944Sjoerg len); 124225944Sjoerg ++ifp->if_ierrors; 124325944Sjoerg break; 124425944Sjoerg } 124530300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 124630300Sjoerg switch (sp->state[cp->protoidx]) { 124730300Sjoerg case STATE_CLOSING: 124830300Sjoerg case STATE_STOPPING: 124930300Sjoerg return; 125030300Sjoerg case STATE_CLOSED: 125130300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 125230300Sjoerg 0, 0); 125330300Sjoerg return; 125430300Sjoerg } 125525944Sjoerg rv = (cp->RCR)(sp, h, len); 125625944Sjoerg switch (sp->state[cp->protoidx]) { 125725944Sjoerg case STATE_OPENED: 125825944Sjoerg (cp->tld)(sp); 125925944Sjoerg (cp->scr)(sp); 126025944Sjoerg /* fall through... */ 126125944Sjoerg case STATE_ACK_SENT: 126225944Sjoerg case STATE_REQ_SENT: 126325944Sjoerg sppp_cp_change_state(cp, sp, rv? 126425944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 126525944Sjoerg break; 126625944Sjoerg case STATE_STOPPED: 126725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 126825944Sjoerg (cp->scr)(sp); 126925944Sjoerg sppp_cp_change_state(cp, sp, rv? 127025944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 127125944Sjoerg break; 127225944Sjoerg case STATE_ACK_RCVD: 127325944Sjoerg if (rv) { 127425944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 127525944Sjoerg if (debug) 127640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 127740008Sjoerg SPP_ARGS(ifp), 127826077Sjoerg cp->name); 127925944Sjoerg (cp->tlu)(sp); 128025944Sjoerg } else 128125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 128225944Sjoerg break; 128325944Sjoerg default: 128440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 128540008Sjoerg SPP_ARGS(ifp), cp->name, 128625944Sjoerg sppp_cp_type_name(h->type), 128725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 128825944Sjoerg ++ifp->if_ierrors; 128925944Sjoerg } 129025944Sjoerg break; 129125944Sjoerg case CONF_ACK: 129225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 129325944Sjoerg if (debug) 129440008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 129540008Sjoerg SPP_ARGS(ifp), cp->name, 129625944Sjoerg h->ident, sp->confid[cp->protoidx]); 129725944Sjoerg ++ifp->if_ierrors; 129825944Sjoerg break; 129925944Sjoerg } 130025944Sjoerg switch (sp->state[cp->protoidx]) { 130125944Sjoerg case STATE_CLOSED: 130225944Sjoerg case STATE_STOPPED: 130325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 130425944Sjoerg break; 130525944Sjoerg case STATE_CLOSING: 130625944Sjoerg case STATE_STOPPING: 130725944Sjoerg break; 130825944Sjoerg case STATE_REQ_SENT: 130925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 131025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 131125944Sjoerg break; 131225944Sjoerg case STATE_OPENED: 131325944Sjoerg (cp->tld)(sp); 131425944Sjoerg /* fall through */ 131525944Sjoerg case STATE_ACK_RCVD: 131625944Sjoerg (cp->scr)(sp); 131725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 131825944Sjoerg break; 131925944Sjoerg case STATE_ACK_SENT: 132025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 132125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 132225944Sjoerg if (debug) 132340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 132440008Sjoerg SPP_ARGS(ifp), cp->name); 132525944Sjoerg (cp->tlu)(sp); 132625944Sjoerg break; 132725944Sjoerg default: 132840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 132940008Sjoerg SPP_ARGS(ifp), cp->name, 133025944Sjoerg sppp_cp_type_name(h->type), 133125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 133225944Sjoerg ++ifp->if_ierrors; 133325944Sjoerg } 133425944Sjoerg break; 133525944Sjoerg case CONF_NAK: 133625944Sjoerg case CONF_REJ: 133725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 133825944Sjoerg if (debug) 133940008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 134040008Sjoerg SPP_ARGS(ifp), cp->name, 134125944Sjoerg h->ident, sp->confid[cp->protoidx]); 134225944Sjoerg ++ifp->if_ierrors; 134325944Sjoerg break; 134425944Sjoerg } 134525944Sjoerg if (h->type == CONF_NAK) 134625944Sjoerg (cp->RCN_nak)(sp, h, len); 134725944Sjoerg else /* CONF_REJ */ 134825944Sjoerg (cp->RCN_rej)(sp, h, len); 13494910Swollman 135025944Sjoerg switch (sp->state[cp->protoidx]) { 135125944Sjoerg case STATE_CLOSED: 135225944Sjoerg case STATE_STOPPED: 135325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 135425944Sjoerg break; 135525944Sjoerg case STATE_REQ_SENT: 135625944Sjoerg case STATE_ACK_SENT: 135725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 135825944Sjoerg (cp->scr)(sp); 135925944Sjoerg break; 136025944Sjoerg case STATE_OPENED: 136125944Sjoerg (cp->tld)(sp); 136225944Sjoerg /* fall through */ 136325944Sjoerg case STATE_ACK_RCVD: 136452633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 136525944Sjoerg (cp->scr)(sp); 136625944Sjoerg break; 136725944Sjoerg case STATE_CLOSING: 136825944Sjoerg case STATE_STOPPING: 136925944Sjoerg break; 137025944Sjoerg default: 137140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 137240008Sjoerg SPP_ARGS(ifp), cp->name, 137325944Sjoerg sppp_cp_type_name(h->type), 137425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 137525944Sjoerg ++ifp->if_ierrors; 137625944Sjoerg } 137725944Sjoerg break; 13784910Swollman 137925944Sjoerg case TERM_REQ: 138025944Sjoerg switch (sp->state[cp->protoidx]) { 138125944Sjoerg case STATE_ACK_RCVD: 138225944Sjoerg case STATE_ACK_SENT: 138325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 138425944Sjoerg /* fall through */ 138525944Sjoerg case STATE_CLOSED: 138625944Sjoerg case STATE_STOPPED: 138725944Sjoerg case STATE_CLOSING: 138825944Sjoerg case STATE_STOPPING: 138925944Sjoerg case STATE_REQ_SENT: 139025944Sjoerg sta: 139125944Sjoerg /* Send Terminate-Ack packet. */ 139225944Sjoerg if (debug) 139340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 139440008Sjoerg SPP_ARGS(ifp), cp->name); 139525944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 139625944Sjoerg break; 139725944Sjoerg case STATE_OPENED: 139825944Sjoerg (cp->tld)(sp); 139925944Sjoerg sp->rst_counter[cp->protoidx] = 0; 140025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 140125944Sjoerg goto sta; 140225944Sjoerg break; 140325944Sjoerg default: 140440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 140540008Sjoerg SPP_ARGS(ifp), cp->name, 140625944Sjoerg sppp_cp_type_name(h->type), 140725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 140825944Sjoerg ++ifp->if_ierrors; 140925944Sjoerg } 141025944Sjoerg break; 141125944Sjoerg case TERM_ACK: 141225944Sjoerg switch (sp->state[cp->protoidx]) { 141325944Sjoerg case STATE_CLOSED: 141425944Sjoerg case STATE_STOPPED: 141525944Sjoerg case STATE_REQ_SENT: 141625944Sjoerg case STATE_ACK_SENT: 141725944Sjoerg break; 141825944Sjoerg case STATE_CLOSING: 141941881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 142025944Sjoerg (cp->tlf)(sp); 142125944Sjoerg break; 142225944Sjoerg case STATE_STOPPING: 142341881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 142425944Sjoerg (cp->tlf)(sp); 142525944Sjoerg break; 142625944Sjoerg case STATE_ACK_RCVD: 142725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142825944Sjoerg break; 142925944Sjoerg case STATE_OPENED: 143025944Sjoerg (cp->tld)(sp); 143125944Sjoerg (cp->scr)(sp); 143225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 143325944Sjoerg break; 143425944Sjoerg default: 143540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 143640008Sjoerg SPP_ARGS(ifp), cp->name, 143725944Sjoerg sppp_cp_type_name(h->type), 143825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 143925944Sjoerg ++ifp->if_ierrors; 144025944Sjoerg } 144125944Sjoerg break; 144225944Sjoerg case CODE_REJ: 144325944Sjoerg case PROTO_REJ: 144425944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 144530300Sjoerg log(LOG_INFO, 144640008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 144730300Sjoerg "danger will robinson\n", 144840008Sjoerg SPP_ARGS(ifp), cp->name, 144930300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 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 case STATE_CLOSING: 145625944Sjoerg case STATE_STOPPING: 145725944Sjoerg case STATE_OPENED: 145825944Sjoerg break; 145925944Sjoerg case STATE_ACK_RCVD: 146025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 146125944Sjoerg break; 146225944Sjoerg default: 146340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 146440008Sjoerg SPP_ARGS(ifp), cp->name, 146525944Sjoerg sppp_cp_type_name(h->type), 146625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 146725944Sjoerg ++ifp->if_ierrors; 146825944Sjoerg } 146925944Sjoerg break; 147025944Sjoerg case DISC_REQ: 147125944Sjoerg if (cp->proto != PPP_LCP) 147225944Sjoerg goto illegal; 147325944Sjoerg /* Discard the packet. */ 147425944Sjoerg break; 147525944Sjoerg case ECHO_REQ: 147625944Sjoerg if (cp->proto != PPP_LCP) 147725944Sjoerg goto illegal; 147825944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 147925944Sjoerg if (debug) 148040008Sjoerg addlog(SPP_FMT "lcp echo req but lcp closed\n", 148140008Sjoerg SPP_ARGS(ifp)); 148225944Sjoerg ++ifp->if_ierrors; 148325944Sjoerg break; 148425944Sjoerg } 148525944Sjoerg if (len < 8) { 148625944Sjoerg if (debug) 148740008Sjoerg addlog(SPP_FMT "invalid lcp echo request " 148825944Sjoerg "packet length: %d bytes\n", 148940008Sjoerg SPP_ARGS(ifp), len); 149025944Sjoerg break; 149125944Sjoerg } 149244145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 149344145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 149425944Sjoerg /* Line loopback mode detected. */ 149540008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 149625944Sjoerg if_down (ifp); 149726018Sjoerg sppp_qflush (&sp->pp_cpq); 14984910Swollman 149925944Sjoerg /* Shut down the PPP link. */ 150025944Sjoerg /* XXX */ 150125944Sjoerg lcp.Down(sp); 150225944Sjoerg lcp.Up(sp); 150325944Sjoerg break; 150425944Sjoerg } 150525944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 150625944Sjoerg if (debug) 150740008Sjoerg addlog(SPP_FMT "got lcp echo req, sending echo rep\n", 150840008Sjoerg SPP_ARGS(ifp)); 150925944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 151025944Sjoerg break; 151125944Sjoerg case ECHO_REPLY: 151225944Sjoerg if (cp->proto != PPP_LCP) 151325944Sjoerg goto illegal; 151425944Sjoerg if (h->ident != sp->lcp.echoid) { 151525944Sjoerg ++ifp->if_ierrors; 151625944Sjoerg break; 151725944Sjoerg } 151825944Sjoerg if (len < 8) { 151925944Sjoerg if (debug) 152040008Sjoerg addlog(SPP_FMT "lcp invalid echo reply " 152125944Sjoerg "packet length: %d bytes\n", 152240008Sjoerg SPP_ARGS(ifp), len); 152325944Sjoerg break; 152425944Sjoerg } 152525944Sjoerg if (debug) 152640008Sjoerg addlog(SPP_FMT "lcp got echo rep\n", 152740008Sjoerg SPP_ARGS(ifp)); 152844145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 152944145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 153025944Sjoerg sp->pp_alivecnt = 0; 153125944Sjoerg break; 153225944Sjoerg default: 153325944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 153425944Sjoerg illegal: 153525944Sjoerg if (debug) 153640008Sjoerg addlog(SPP_FMT "%s send code-rej for 0x%x\n", 153740008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 153825944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 153925944Sjoerg m->m_pkthdr.len, h); 154025944Sjoerg ++ifp->if_ierrors; 154125944Sjoerg } 15424910Swollman} 15434910Swollman 154425944Sjoerg 15454910Swollman/* 154625944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 154725944Sjoerg * Basically, the state transition handling in the automaton. 15484910Swollman */ 154925944Sjoergstatic void 155025944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 15514910Swollman{ 155225944Sjoerg STDDCL; 15534910Swollman 155425944Sjoerg if (debug) 155540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 155640008Sjoerg SPP_ARGS(ifp), cp->name, 155725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155825944Sjoerg 155925944Sjoerg switch (sp->state[cp->protoidx]) { 156025944Sjoerg case STATE_INITIAL: 156125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 156225944Sjoerg break; 156325944Sjoerg case STATE_STARTING: 156425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 156525944Sjoerg (cp->scr)(sp); 156625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 156725944Sjoerg break; 15684910Swollman default: 156940008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 157040008Sjoerg SPP_ARGS(ifp), cp->name, 157125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 157225944Sjoerg } 157325944Sjoerg} 15744910Swollman 157525944Sjoergstatic void 157625944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 157725944Sjoerg{ 157825944Sjoerg STDDCL; 157925944Sjoerg 158025944Sjoerg if (debug) 158140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 158240008Sjoerg SPP_ARGS(ifp), cp->name, 158325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158425944Sjoerg 158525944Sjoerg switch (sp->state[cp->protoidx]) { 158625944Sjoerg case STATE_CLOSED: 158725944Sjoerg case STATE_CLOSING: 158825944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 15894910Swollman break; 159025944Sjoerg case STATE_STOPPED: 159141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 159225944Sjoerg (cp->tls)(sp); 159341881Sphk break; 159425944Sjoerg case STATE_STOPPING: 159525944Sjoerg case STATE_REQ_SENT: 159625944Sjoerg case STATE_ACK_RCVD: 159725944Sjoerg case STATE_ACK_SENT: 159825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 159925944Sjoerg break; 160025944Sjoerg case STATE_OPENED: 160125944Sjoerg (cp->tld)(sp); 160225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 160325944Sjoerg break; 160425944Sjoerg default: 160540008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 160640008Sjoerg SPP_ARGS(ifp), cp->name, 160725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160825944Sjoerg } 160925944Sjoerg} 16104910Swollman 161111189Sjkh 161225944Sjoergstatic void 161325944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 161425944Sjoerg{ 161525944Sjoerg STDDCL; 161625944Sjoerg 161725944Sjoerg if (debug) 161840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 161940008Sjoerg SPP_ARGS(ifp), cp->name, 162025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 162125944Sjoerg 162225944Sjoerg switch (sp->state[cp->protoidx]) { 162325944Sjoerg case STATE_INITIAL: 162441881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 162525944Sjoerg (cp->tls)(sp); 16264910Swollman break; 162725944Sjoerg case STATE_STARTING: 162825944Sjoerg break; 162925944Sjoerg case STATE_CLOSED: 163025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 163125944Sjoerg (cp->scr)(sp); 163225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 163325944Sjoerg break; 163425944Sjoerg case STATE_STOPPED: 163525944Sjoerg case STATE_STOPPING: 163625944Sjoerg case STATE_REQ_SENT: 163725944Sjoerg case STATE_ACK_RCVD: 163825944Sjoerg case STATE_ACK_SENT: 163925944Sjoerg case STATE_OPENED: 164025944Sjoerg break; 164125944Sjoerg case STATE_CLOSING: 164225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 164325944Sjoerg break; 164425944Sjoerg } 164525944Sjoerg} 16464910Swollman 164725944Sjoerg 164825944Sjoergstatic void 164925944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 165025944Sjoerg{ 165125944Sjoerg STDDCL; 165225944Sjoerg 165325944Sjoerg if (debug) 165440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 165540008Sjoerg SPP_ARGS(ifp), cp->name, 165625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 165725944Sjoerg 165825944Sjoerg switch (sp->state[cp->protoidx]) { 165925944Sjoerg case STATE_INITIAL: 166025944Sjoerg case STATE_CLOSED: 166125944Sjoerg case STATE_CLOSING: 16624910Swollman break; 166325944Sjoerg case STATE_STARTING: 166441881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 166525944Sjoerg (cp->tlf)(sp); 16664910Swollman break; 166725944Sjoerg case STATE_STOPPED: 166825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 16694910Swollman break; 167025944Sjoerg case STATE_STOPPING: 167125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16724910Swollman break; 167325944Sjoerg case STATE_OPENED: 167425944Sjoerg (cp->tld)(sp); 167525944Sjoerg /* fall through */ 167625944Sjoerg case STATE_REQ_SENT: 167725944Sjoerg case STATE_ACK_RCVD: 167825944Sjoerg case STATE_ACK_SENT: 167925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 168025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 168125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16824910Swollman break; 16834910Swollman } 16844910Swollman} 16854910Swollman 168625944Sjoergstatic void 168725944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 168825944Sjoerg{ 168925944Sjoerg STDDCL; 169025944Sjoerg int s; 169125944Sjoerg 169225944Sjoerg s = splimp(); 169325944Sjoerg if (debug) 169440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 169540008Sjoerg SPP_ARGS(ifp), cp->name, 169625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 169725944Sjoerg sp->rst_counter[cp->protoidx]); 169825944Sjoerg 169925944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 170025944Sjoerg /* TO- event */ 170125944Sjoerg switch (sp->state[cp->protoidx]) { 170225944Sjoerg case STATE_CLOSING: 170341881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 170425944Sjoerg (cp->tlf)(sp); 170525944Sjoerg break; 170625944Sjoerg case STATE_STOPPING: 170741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 170825944Sjoerg (cp->tlf)(sp); 170925944Sjoerg break; 171025944Sjoerg case STATE_REQ_SENT: 171125944Sjoerg case STATE_ACK_RCVD: 171225944Sjoerg case STATE_ACK_SENT: 171341881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 171425944Sjoerg (cp->tlf)(sp); 171525944Sjoerg break; 171625944Sjoerg } 171725944Sjoerg else 171825944Sjoerg /* TO+ event */ 171925944Sjoerg switch (sp->state[cp->protoidx]) { 172025944Sjoerg case STATE_CLOSING: 172125944Sjoerg case STATE_STOPPING: 172225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 172325944Sjoerg 0, 0); 172442064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 172542064Sphk sp->ch[cp->protoidx]); 172625944Sjoerg break; 172725944Sjoerg case STATE_REQ_SENT: 172825944Sjoerg case STATE_ACK_RCVD: 172925944Sjoerg (cp->scr)(sp); 173025944Sjoerg /* sppp_cp_change_state() will restart the timer */ 173125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 173225944Sjoerg break; 173325944Sjoerg case STATE_ACK_SENT: 173425944Sjoerg (cp->scr)(sp); 173542064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 173642064Sphk sp->ch[cp->protoidx]); 173725944Sjoerg break; 173825944Sjoerg } 173925944Sjoerg 174025944Sjoerg splx(s); 174125944Sjoerg} 174225944Sjoerg 174311189Sjkh/* 174425944Sjoerg * Change the state of a control protocol in the state automaton. 174525944Sjoerg * Takes care of starting/stopping the restart timer. 174611189Sjkh */ 174725944Sjoergvoid 174825944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 174925944Sjoerg{ 175025944Sjoerg sp->state[cp->protoidx] = newstate; 175125944Sjoerg 175240008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 175325944Sjoerg switch (newstate) { 175425944Sjoerg case STATE_INITIAL: 175525944Sjoerg case STATE_STARTING: 175625944Sjoerg case STATE_CLOSED: 175725944Sjoerg case STATE_STOPPED: 175825944Sjoerg case STATE_OPENED: 175925944Sjoerg break; 176025944Sjoerg case STATE_CLOSING: 176125944Sjoerg case STATE_STOPPING: 176225944Sjoerg case STATE_REQ_SENT: 176325944Sjoerg case STATE_ACK_RCVD: 176425944Sjoerg case STATE_ACK_SENT: 176542064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 176642064Sphk sp->ch[cp->protoidx]); 176725944Sjoerg break; 176825944Sjoerg } 176925944Sjoerg} 177025944Sjoerg/* 177125944Sjoerg *--------------------------------------------------------------------------* 177225944Sjoerg * * 177325944Sjoerg * The LCP implementation. * 177425944Sjoerg * * 177525944Sjoerg *--------------------------------------------------------------------------* 177625944Sjoerg */ 177725944Sjoergstatic void 177825944Sjoergsppp_lcp_init(struct sppp *sp) 177925944Sjoerg{ 178025944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 178125944Sjoerg sp->lcp.magic = 0; 178225944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 178325944Sjoerg sp->fail_counter[IDX_LCP] = 0; 178425944Sjoerg sp->lcp.protos = 0; 178525944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 178630300Sjoerg 178744145Sphk /* Note that these values are relevant for all control protocols */ 178844145Sphk sp->lcp.timeout = 3 * hz; 178925944Sjoerg sp->lcp.max_terminate = 2; 179025944Sjoerg sp->lcp.max_configure = 10; 179125944Sjoerg sp->lcp.max_failure = 10; 179242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 179330300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 179440008Sjoerg#endif 179525944Sjoerg} 179625944Sjoerg 179725944Sjoergstatic void 179825944Sjoergsppp_lcp_up(struct sppp *sp) 179925944Sjoerg{ 180025944Sjoerg STDDCL; 180125944Sjoerg 180225944Sjoerg /* 180330300Sjoerg * If this interface is passive or dial-on-demand, and we are 180430300Sjoerg * still in Initial state, it means we've got an incoming 180530300Sjoerg * call. Activate the interface. 180625944Sjoerg */ 180725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 180825944Sjoerg if (debug) 180925944Sjoerg log(LOG_DEBUG, 181040008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 181125944Sjoerg ifp->if_flags |= IFF_RUNNING; 181230300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 181330300Sjoerg if (debug) 181430300Sjoerg addlog("(incoming call)\n"); 181530300Sjoerg sp->pp_flags |= PP_CALLIN; 181630300Sjoerg lcp.Open(sp); 181730300Sjoerg } else if (debug) 181830300Sjoerg addlog("\n"); 181925944Sjoerg } 182025944Sjoerg 182125944Sjoerg sppp_up_event(&lcp, sp); 182225944Sjoerg} 182325944Sjoerg 182425944Sjoergstatic void 182525944Sjoergsppp_lcp_down(struct sppp *sp) 182625944Sjoerg{ 182725944Sjoerg STDDCL; 182825944Sjoerg 182925944Sjoerg sppp_down_event(&lcp, sp); 183025944Sjoerg 183125944Sjoerg /* 183225944Sjoerg * If this is neither a dial-on-demand nor a passive 183325944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 183425944Sjoerg * administrator can force a redial by another ``ifconfig 183525944Sjoerg * up''. XXX For leased line operation, should we immediately 183625944Sjoerg * try to reopen the connection here? 183725944Sjoerg */ 183825944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 183925944Sjoerg log(LOG_INFO, 184042066Sphk SPP_FMT "Down event, taking interface down.\n", 184140008Sjoerg SPP_ARGS(ifp)); 184225944Sjoerg if_down(ifp); 184325944Sjoerg } else { 184425944Sjoerg if (debug) 184525944Sjoerg log(LOG_DEBUG, 184640008Sjoerg SPP_FMT "Down event (carrier loss)\n", 184740008Sjoerg SPP_ARGS(ifp)); 184825944Sjoerg } 184930300Sjoerg sp->pp_flags &= ~PP_CALLIN; 185030300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 185130300Sjoerg lcp.Close(sp); 185225944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 185325944Sjoerg} 185425944Sjoerg 185525944Sjoergstatic void 185625944Sjoergsppp_lcp_open(struct sppp *sp) 185725944Sjoerg{ 185830300Sjoerg /* 185930300Sjoerg * If we are authenticator, negotiate LCP_AUTH 186030300Sjoerg */ 186130300Sjoerg if (sp->hisauth.proto != 0) 186230300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 186330300Sjoerg else 186430300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 186530300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 186625944Sjoerg sppp_open_event(&lcp, sp); 186725944Sjoerg} 186825944Sjoerg 186925944Sjoergstatic void 187025944Sjoergsppp_lcp_close(struct sppp *sp) 187125944Sjoerg{ 187225944Sjoerg sppp_close_event(&lcp, sp); 187325944Sjoerg} 187425944Sjoerg 187525944Sjoergstatic void 187625944Sjoergsppp_lcp_TO(void *cookie) 187725944Sjoerg{ 187825944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 187925944Sjoerg} 188025944Sjoerg 188125944Sjoerg/* 188225944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 188325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 188425944Sjoerg * caused action scn. (The return value is used to make the state 188525944Sjoerg * transition decision in the state automaton.) 188625944Sjoerg */ 188712820Sphkstatic int 188825944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 18894910Swollman{ 189025944Sjoerg STDDCL; 189111189Sjkh u_char *buf, *r, *p; 189225944Sjoerg int origlen, rlen; 189325944Sjoerg u_long nmagic; 189430300Sjoerg u_short authproto; 18954910Swollman 189611189Sjkh len -= 4; 189725944Sjoerg origlen = len; 189811189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 189911189Sjkh if (! buf) 190011189Sjkh return (0); 19014910Swollman 190225706Sjoerg if (debug) 190340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 190440008Sjoerg SPP_ARGS(ifp)); 190525706Sjoerg 190625944Sjoerg /* pass 1: check for things that need to be rejected */ 190711189Sjkh p = (void*) (h+1); 190811189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 190925944Sjoerg if (debug) 191025944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 191111189Sjkh switch (*p) { 191211189Sjkh case LCP_OPT_MAGIC: 191325944Sjoerg /* Magic number. */ 191425944Sjoerg /* fall through, both are same length */ 191525944Sjoerg case LCP_OPT_ASYNC_MAP: 191625944Sjoerg /* Async control character map. */ 191725944Sjoerg if (len >= 6 || p[1] == 6) 191825944Sjoerg continue; 191925944Sjoerg if (debug) 192025944Sjoerg addlog("[invalid] "); 192125944Sjoerg break; 192225944Sjoerg case LCP_OPT_MRU: 192325944Sjoerg /* Maximum receive unit. */ 192425944Sjoerg if (len >= 4 && p[1] == 4) 192525944Sjoerg continue; 192625944Sjoerg if (debug) 192725944Sjoerg addlog("[invalid] "); 192825944Sjoerg break; 192930300Sjoerg case LCP_OPT_AUTH_PROTO: 193030300Sjoerg if (len < 4) { 193130300Sjoerg if (debug) 193230300Sjoerg addlog("[invalid] "); 193330300Sjoerg break; 193430300Sjoerg } 193530300Sjoerg authproto = (p[2] << 8) + p[3]; 193630300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 193730300Sjoerg if (debug) 193830300Sjoerg addlog("[invalid chap len] "); 193930300Sjoerg break; 194030300Sjoerg } 194130300Sjoerg if (sp->myauth.proto == 0) { 194230300Sjoerg /* we are not configured to do auth */ 194330300Sjoerg if (debug) 194430300Sjoerg addlog("[not configured] "); 194530300Sjoerg break; 194630300Sjoerg } 194730300Sjoerg /* 194830300Sjoerg * Remote want us to authenticate, remember this, 194930300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 195030300Sjoerg * up. 195130300Sjoerg */ 195230300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 195330300Sjoerg continue; 195425944Sjoerg default: 195525944Sjoerg /* Others not supported. */ 195625944Sjoerg if (debug) 195725944Sjoerg addlog("[rej] "); 195825944Sjoerg break; 195925944Sjoerg } 196025944Sjoerg /* Add the option to rejected list. */ 196125944Sjoerg bcopy (p, r, p[1]); 196225944Sjoerg r += p[1]; 196325944Sjoerg rlen += p[1]; 196425944Sjoerg } 196525944Sjoerg if (rlen) { 196625944Sjoerg if (debug) 196725944Sjoerg addlog(" send conf-rej\n"); 196825944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 196925944Sjoerg return 0; 197025944Sjoerg } else if (debug) 197125944Sjoerg addlog("\n"); 197225944Sjoerg 197325944Sjoerg /* 197425944Sjoerg * pass 2: check for option values that are unacceptable and 197525944Sjoerg * thus require to be nak'ed. 197625944Sjoerg */ 197725944Sjoerg if (debug) 197840008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 197940008Sjoerg SPP_ARGS(ifp)); 198025944Sjoerg 198125944Sjoerg p = (void*) (h+1); 198225944Sjoerg len = origlen; 198325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 198425944Sjoerg if (debug) 198525944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 198625944Sjoerg switch (*p) { 198725944Sjoerg case LCP_OPT_MAGIC: 198811189Sjkh /* Magic number -- extract. */ 198925944Sjoerg nmagic = (u_long)p[2] << 24 | 199025944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 199125944Sjoerg if (nmagic != sp->lcp.magic) { 199225706Sjoerg if (debug) 199338372Sbde addlog("0x%lx ", nmagic); 199411189Sjkh continue; 199511189Sjkh } 199625944Sjoerg /* 199725944Sjoerg * Local and remote magics equal -- loopback? 199825944Sjoerg */ 199925944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 200040008Sjoerg printf (SPP_FMT "loopback\n", 200140008Sjoerg SPP_ARGS(ifp)); 200225944Sjoerg sp->pp_loopcnt = 0; 200325944Sjoerg if (ifp->if_flags & IFF_UP) { 200425944Sjoerg if_down(ifp); 200526018Sjoerg sppp_qflush(&sp->pp_cpq); 200625944Sjoerg /* XXX ? */ 200725944Sjoerg lcp.Down(sp); 200825944Sjoerg lcp.Up(sp); 200925944Sjoerg } 201025944Sjoerg } else if (debug) 201125944Sjoerg addlog("[glitch] "); 201225944Sjoerg ++sp->pp_loopcnt; 201325944Sjoerg /* 201425944Sjoerg * We negate our magic here, and NAK it. If 201525944Sjoerg * we see it later in an NAK packet, we 201625944Sjoerg * suggest a new one. 201725944Sjoerg */ 201825944Sjoerg nmagic = ~sp->lcp.magic; 201925944Sjoerg /* Gonna NAK it. */ 202025944Sjoerg p[2] = nmagic >> 24; 202125944Sjoerg p[3] = nmagic >> 16; 202225944Sjoerg p[4] = nmagic >> 8; 202325944Sjoerg p[5] = nmagic; 202411189Sjkh break; 202525944Sjoerg 202611189Sjkh case LCP_OPT_ASYNC_MAP: 202711189Sjkh /* Async control character map -- check to be zero. */ 202825944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 202925706Sjoerg if (debug) 203025944Sjoerg addlog("[empty] "); 203111189Sjkh continue; 203225706Sjoerg } 203325706Sjoerg if (debug) 203425944Sjoerg addlog("[non-empty] "); 203525944Sjoerg /* suggest a zero one */ 203625944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 203711189Sjkh break; 203825944Sjoerg 203911189Sjkh case LCP_OPT_MRU: 204025944Sjoerg /* 204125944Sjoerg * Maximum receive unit. Always agreeable, 204225944Sjoerg * but ignored by now. 204325944Sjoerg */ 204425944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 204525706Sjoerg if (debug) 204638372Sbde addlog("%lu ", sp->lcp.their_mru); 204711189Sjkh continue; 204830300Sjoerg 204930300Sjoerg case LCP_OPT_AUTH_PROTO: 205030300Sjoerg authproto = (p[2] << 8) + p[3]; 205130300Sjoerg if (sp->myauth.proto != authproto) { 205230300Sjoerg /* not agreed, nak */ 205330300Sjoerg if (debug) 205430300Sjoerg addlog("[mine %s != his %s] ", 205530300Sjoerg sppp_proto_name(sp->hisauth.proto), 205630300Sjoerg sppp_proto_name(authproto)); 205730300Sjoerg p[2] = sp->myauth.proto >> 8; 205830300Sjoerg p[3] = sp->myauth.proto; 205930300Sjoerg break; 206030300Sjoerg } 206130300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 206230300Sjoerg if (debug) 206330300Sjoerg addlog("[chap not MD5] "); 206439981Sjoerg p[4] = CHAP_MD5; 206530300Sjoerg break; 206630300Sjoerg } 206730300Sjoerg continue; 206811189Sjkh } 206925944Sjoerg /* Add the option to nak'ed list. */ 207025706Sjoerg bcopy (p, r, p[1]); 207125706Sjoerg r += p[1]; 207211189Sjkh rlen += p[1]; 207312436Speter } 207425706Sjoerg if (rlen) { 207528036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 207628036Sjoerg if (debug) 207728036Sjoerg addlog(" max_failure (%d) exceeded, " 207828036Sjoerg "send conf-rej\n", 207928036Sjoerg sp->lcp.max_failure); 208028036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 208128036Sjoerg } else { 208228036Sjoerg if (debug) 208328036Sjoerg addlog(" send conf-nak\n"); 208428036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 208528036Sjoerg } 208625944Sjoerg return 0; 208725944Sjoerg } else { 208825944Sjoerg if (debug) 208925944Sjoerg addlog(" send conf-ack\n"); 209028036Sjoerg sp->fail_counter[IDX_LCP] = 0; 209125944Sjoerg sp->pp_loopcnt = 0; 209225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 209325944Sjoerg h->ident, origlen, h+1); 209425944Sjoerg } 209525944Sjoerg 209611189Sjkh free (buf, M_TEMP); 209711189Sjkh return (rlen == 0); 20984910Swollman} 20994910Swollman 210025944Sjoerg/* 210125944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 210225944Sjoerg * negotiation. 210325944Sjoerg */ 210412820Sphkstatic void 210525944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 21064910Swollman{ 210725944Sjoerg STDDCL; 210825944Sjoerg u_char *buf, *p; 21094910Swollman 211025944Sjoerg len -= 4; 211125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 211225944Sjoerg if (!buf) 21134910Swollman return; 211425944Sjoerg 211525944Sjoerg if (debug) 211640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 211740008Sjoerg SPP_ARGS(ifp)); 211825944Sjoerg 211925944Sjoerg p = (void*) (h+1); 212025944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 212125944Sjoerg if (debug) 212225944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 212325944Sjoerg switch (*p) { 212425944Sjoerg case LCP_OPT_MAGIC: 212525944Sjoerg /* Magic number -- can't use it, use 0 */ 212625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 212725944Sjoerg sp->lcp.magic = 0; 212825944Sjoerg break; 212925944Sjoerg case LCP_OPT_MRU: 213025944Sjoerg /* 213125944Sjoerg * Should not be rejected anyway, since we only 213225944Sjoerg * negotiate a MRU if explicitly requested by 213325944Sjoerg * peer. 213425944Sjoerg */ 213525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 213625944Sjoerg break; 213730300Sjoerg case LCP_OPT_AUTH_PROTO: 213830300Sjoerg /* 213930300Sjoerg * Peer doesn't want to authenticate himself, 214030300Sjoerg * deny unless this is a dialout call, and 214130300Sjoerg * AUTHFLAG_NOCALLOUT is set. 214230300Sjoerg */ 214330300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 214430300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 214530300Sjoerg if (debug) 214630300Sjoerg addlog("[don't insist on auth " 214730300Sjoerg "for callout]"); 214830300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 214930300Sjoerg break; 215030300Sjoerg } 215130300Sjoerg if (debug) 215230300Sjoerg addlog("[access denied]\n"); 215330300Sjoerg lcp.Close(sp); 215430300Sjoerg break; 215525944Sjoerg } 21564910Swollman } 215725944Sjoerg if (debug) 215825944Sjoerg addlog("\n"); 215925944Sjoerg free (buf, M_TEMP); 216025944Sjoerg return; 216125944Sjoerg} 216225944Sjoerg 216325944Sjoerg/* 216425944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 216525944Sjoerg * negotiation. 216625944Sjoerg */ 216725944Sjoergstatic void 216825944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 216925944Sjoerg{ 217025944Sjoerg STDDCL; 217125944Sjoerg u_char *buf, *p; 217225944Sjoerg u_long magic; 217325944Sjoerg 217425944Sjoerg len -= 4; 217525944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 217625944Sjoerg if (!buf) 217725944Sjoerg return; 217825944Sjoerg 217925944Sjoerg if (debug) 218040008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 218140008Sjoerg SPP_ARGS(ifp)); 218225944Sjoerg 218325944Sjoerg p = (void*) (h+1); 218425944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 218525706Sjoerg if (debug) 218625944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 218725944Sjoerg switch (*p) { 218825944Sjoerg case LCP_OPT_MAGIC: 218925944Sjoerg /* Magic number -- renegotiate */ 219025944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 219125944Sjoerg len >= 6 && p[1] == 6) { 219225944Sjoerg magic = (u_long)p[2] << 24 | 219325944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 219425944Sjoerg /* 219525944Sjoerg * If the remote magic is our negated one, 219625944Sjoerg * this looks like a loopback problem. 219725944Sjoerg * Suggest a new magic to make sure. 219825944Sjoerg */ 219925944Sjoerg if (magic == ~sp->lcp.magic) { 220025944Sjoerg if (debug) 220125944Sjoerg addlog("magic glitch "); 220242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 220335064Sphk sp->lcp.magic = random(); 220440008Sjoerg#else 220540008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 220640008Sjoerg#endif 220725944Sjoerg } else { 220825944Sjoerg sp->lcp.magic = magic; 220925944Sjoerg if (debug) 221040008Sjoerg addlog("%lu ", magic); 221125944Sjoerg } 221225944Sjoerg } 221325944Sjoerg break; 221425944Sjoerg case LCP_OPT_MRU: 221525944Sjoerg /* 221625944Sjoerg * Peer wants to advise us to negotiate an MRU. 221725944Sjoerg * Agree on it if it's reasonable, or use 221825944Sjoerg * default otherwise. 221925944Sjoerg */ 222025944Sjoerg if (len >= 4 && p[1] == 4) { 222125944Sjoerg u_int mru = p[2] * 256 + p[3]; 222225944Sjoerg if (debug) 222325944Sjoerg addlog("%d ", mru); 222425944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 222525944Sjoerg mru = PP_MTU; 222625944Sjoerg sp->lcp.mru = mru; 222725944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 222825944Sjoerg } 222925944Sjoerg break; 223030300Sjoerg case LCP_OPT_AUTH_PROTO: 223130300Sjoerg /* 223230300Sjoerg * Peer doesn't like our authentication method, 223330300Sjoerg * deny. 223430300Sjoerg */ 223530300Sjoerg if (debug) 223630300Sjoerg addlog("[access denied]\n"); 223730300Sjoerg lcp.Close(sp); 223830300Sjoerg break; 22394910Swollman } 224025944Sjoerg } 224125944Sjoerg if (debug) 224225944Sjoerg addlog("\n"); 224325944Sjoerg free (buf, M_TEMP); 224425944Sjoerg return; 224525944Sjoerg} 224611189Sjkh 224725944Sjoergstatic void 224825944Sjoergsppp_lcp_tlu(struct sppp *sp) 224925944Sjoerg{ 225042066Sphk STDDCL; 225125944Sjoerg int i; 225225944Sjoerg u_long mask; 225325944Sjoerg 225425944Sjoerg /* XXX ? */ 225525944Sjoerg if (! (ifp->if_flags & IFF_UP) && 225625944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 225725944Sjoerg /* Coming out of loopback mode. */ 225825944Sjoerg if_up(ifp); 225940008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 226025944Sjoerg } 226125944Sjoerg 226225944Sjoerg for (i = 0; i < IDX_COUNT; i++) 226325944Sjoerg if ((cps[i])->flags & CP_QUAL) 226425944Sjoerg (cps[i])->Open(sp); 226525944Sjoerg 226630300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 226730300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 226825944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 226925944Sjoerg else 227025944Sjoerg sp->pp_phase = PHASE_NETWORK; 227125944Sjoerg 227242066Sphk if (debug) 227342066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 227442066Sphk sppp_phase_name(sp->pp_phase)); 227525944Sjoerg 227630300Sjoerg /* 227730300Sjoerg * Open all authentication protocols. This is even required 227830300Sjoerg * if we already proceeded to network phase, since it might be 227930300Sjoerg * that remote wants us to authenticate, so we might have to 228030300Sjoerg * send a PAP request. Undesired authentication protocols 228130300Sjoerg * don't do anything when they get an Open event. 228230300Sjoerg */ 228330300Sjoerg for (i = 0; i < IDX_COUNT; i++) 228430300Sjoerg if ((cps[i])->flags & CP_AUTH) 228530300Sjoerg (cps[i])->Open(sp); 228630300Sjoerg 228730300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 228825944Sjoerg /* Notify all NCPs. */ 228925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 229025944Sjoerg if ((cps[i])->flags & CP_NCP) 229125944Sjoerg (cps[i])->Open(sp); 229225944Sjoerg } 229325944Sjoerg 229425944Sjoerg /* Send Up events to all started protos. */ 229525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 229625944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 229725944Sjoerg (cps[i])->Up(sp); 229825944Sjoerg 229942104Sphk /* notify low-level driver of state change */ 230042104Sphk if (sp->pp_chg) 230142104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 230242104Sphk 230325944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 230425944Sjoerg /* if no NCP is starting, close down */ 230530300Sjoerg sppp_lcp_check_and_close(sp); 230625944Sjoerg} 230725944Sjoerg 230825944Sjoergstatic void 230925944Sjoergsppp_lcp_tld(struct sppp *sp) 231025944Sjoerg{ 231142066Sphk STDDCL; 231225944Sjoerg int i; 231325944Sjoerg u_long mask; 231425944Sjoerg 231525944Sjoerg sp->pp_phase = PHASE_TERMINATE; 231625944Sjoerg 231742066Sphk if (debug) 231842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 231942066Sphk sppp_phase_name(sp->pp_phase)); 232025944Sjoerg 232125944Sjoerg /* 232225944Sjoerg * Take upper layers down. We send the Down event first and 232325944Sjoerg * the Close second to prevent the upper layers from sending 232425944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 232525944Sjoerg * describes it. 232625944Sjoerg */ 232725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 232825944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 232925944Sjoerg (cps[i])->Down(sp); 233025944Sjoerg (cps[i])->Close(sp); 233125944Sjoerg } 233225944Sjoerg} 233325944Sjoerg 233425944Sjoergstatic void 233525944Sjoergsppp_lcp_tls(struct sppp *sp) 233625944Sjoerg{ 233742066Sphk STDDCL; 233825944Sjoerg 233925944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 234025944Sjoerg 234142066Sphk if (debug) 234242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 234342066Sphk sppp_phase_name(sp->pp_phase)); 234425944Sjoerg 234525944Sjoerg /* Notify lower layer if desired. */ 234625944Sjoerg if (sp->pp_tls) 234725944Sjoerg (sp->pp_tls)(sp); 234841881Sphk else 234941881Sphk (sp->pp_up)(sp); 235025944Sjoerg} 235125944Sjoerg 235225944Sjoergstatic void 235325944Sjoergsppp_lcp_tlf(struct sppp *sp) 235425944Sjoerg{ 235542066Sphk STDDCL; 235625944Sjoerg 235725944Sjoerg sp->pp_phase = PHASE_DEAD; 235842066Sphk if (debug) 235942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 236042066Sphk sppp_phase_name(sp->pp_phase)); 236125944Sjoerg 236225944Sjoerg /* Notify lower layer if desired. */ 236325944Sjoerg if (sp->pp_tlf) 236425944Sjoerg (sp->pp_tlf)(sp); 236541881Sphk else 236641881Sphk (sp->pp_down)(sp); 236725944Sjoerg} 236825944Sjoerg 236925944Sjoergstatic void 237025944Sjoergsppp_lcp_scr(struct sppp *sp) 237125944Sjoerg{ 237230300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 237325944Sjoerg int i = 0; 237430300Sjoerg u_short authproto; 237525944Sjoerg 237625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 237725944Sjoerg if (! sp->lcp.magic) 237842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 237935064Sphk sp->lcp.magic = random(); 238040008Sjoerg#else 238140008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 238240008Sjoerg#endif 238325944Sjoerg opt[i++] = LCP_OPT_MAGIC; 238425944Sjoerg opt[i++] = 6; 238525944Sjoerg opt[i++] = sp->lcp.magic >> 24; 238625944Sjoerg opt[i++] = sp->lcp.magic >> 16; 238725944Sjoerg opt[i++] = sp->lcp.magic >> 8; 238825944Sjoerg opt[i++] = sp->lcp.magic; 238925944Sjoerg } 239025944Sjoerg 239125944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 239225944Sjoerg opt[i++] = LCP_OPT_MRU; 239325944Sjoerg opt[i++] = 4; 239425944Sjoerg opt[i++] = sp->lcp.mru >> 8; 239525944Sjoerg opt[i++] = sp->lcp.mru; 239625944Sjoerg } 239725944Sjoerg 239830300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 239930300Sjoerg authproto = sp->hisauth.proto; 240030300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 240130300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 240230300Sjoerg opt[i++] = authproto >> 8; 240330300Sjoerg opt[i++] = authproto; 240430300Sjoerg if (authproto == PPP_CHAP) 240530300Sjoerg opt[i++] = CHAP_MD5; 240630300Sjoerg } 240730300Sjoerg 240825944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 240925944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 241025944Sjoerg} 241125944Sjoerg 241225944Sjoerg/* 241330300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 241430300Sjoerg */ 241530300Sjoergstatic int 241630300Sjoergsppp_ncp_check(struct sppp *sp) 241730300Sjoerg{ 241830300Sjoerg int i, mask; 241930300Sjoerg 242030300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 242130300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 242230300Sjoerg return 1; 242330300Sjoerg return 0; 242430300Sjoerg} 242530300Sjoerg 242630300Sjoerg/* 242725944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 242825944Sjoerg * Called by the NCPs during their tlf action handling. 242925944Sjoerg */ 243025944Sjoergstatic void 243130300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 243225944Sjoerg{ 243325944Sjoerg 243430300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 243530300Sjoerg /* don't bother, we are already going down */ 243630300Sjoerg return; 243730300Sjoerg 243830300Sjoerg if (sppp_ncp_check(sp)) 243930300Sjoerg return; 244030300Sjoerg 244125944Sjoerg lcp.Close(sp); 244225944Sjoerg} 244325944Sjoerg/* 244425944Sjoerg *--------------------------------------------------------------------------* 244525944Sjoerg * * 244625944Sjoerg * The IPCP implementation. * 244725944Sjoerg * * 244825944Sjoerg *--------------------------------------------------------------------------* 244925944Sjoerg */ 245025944Sjoerg 245125944Sjoergstatic void 245225944Sjoergsppp_ipcp_init(struct sppp *sp) 245325944Sjoerg{ 245425944Sjoerg sp->ipcp.opts = 0; 245525944Sjoerg sp->ipcp.flags = 0; 245625944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 245725944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 245842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 245929681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 246040008Sjoerg#endif 246125944Sjoerg} 246225944Sjoerg 246325944Sjoergstatic void 246425944Sjoergsppp_ipcp_up(struct sppp *sp) 246525944Sjoerg{ 246625944Sjoerg sppp_up_event(&ipcp, sp); 246725944Sjoerg} 246825944Sjoerg 246925944Sjoergstatic void 247025944Sjoergsppp_ipcp_down(struct sppp *sp) 247125944Sjoerg{ 247225944Sjoerg sppp_down_event(&ipcp, sp); 247325944Sjoerg} 247425944Sjoerg 247525944Sjoergstatic void 247625944Sjoergsppp_ipcp_open(struct sppp *sp) 247725944Sjoerg{ 247825944Sjoerg STDDCL; 247925944Sjoerg u_long myaddr, hisaddr; 248025944Sjoerg 248142104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 248242104Sphk 248330300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 248425944Sjoerg /* 248525944Sjoerg * If we don't have his address, this probably means our 248625944Sjoerg * interface doesn't want to talk IP at all. (This could 248725944Sjoerg * be the case if somebody wants to speak only IPX, for 248825944Sjoerg * example.) Don't open IPCP in this case. 248925944Sjoerg */ 249025944Sjoerg if (hisaddr == 0L) { 249125944Sjoerg /* XXX this message should go away */ 249225944Sjoerg if (debug) 249340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 249440008Sjoerg SPP_ARGS(ifp)); 249525944Sjoerg return; 249625944Sjoerg } 249725944Sjoerg 249825944Sjoerg if (myaddr == 0L) { 249925944Sjoerg /* 250025944Sjoerg * I don't have an assigned address, so i need to 250125944Sjoerg * negotiate my address. 250225944Sjoerg */ 250325944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 250425944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 250542104Sphk } else 250642104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 250725944Sjoerg sppp_open_event(&ipcp, sp); 250825944Sjoerg} 250925944Sjoerg 251025944Sjoergstatic void 251125944Sjoergsppp_ipcp_close(struct sppp *sp) 251225944Sjoerg{ 251325944Sjoerg sppp_close_event(&ipcp, sp); 251425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 251525944Sjoerg /* 251625944Sjoerg * My address was dynamic, clear it again. 251725944Sjoerg */ 251825944Sjoerg sppp_set_ip_addr(sp, 0L); 251925944Sjoerg} 252025944Sjoerg 252125944Sjoergstatic void 252225944Sjoergsppp_ipcp_TO(void *cookie) 252325944Sjoerg{ 252425944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 252525944Sjoerg} 252625944Sjoerg 252725944Sjoerg/* 252825944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 252925944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 253025944Sjoerg * caused action scn. (The return value is used to make the state 253125944Sjoerg * transition decision in the state automaton.) 253225944Sjoerg */ 253325944Sjoergstatic int 253425944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 253525944Sjoerg{ 253625944Sjoerg u_char *buf, *r, *p; 253725944Sjoerg struct ifnet *ifp = &sp->pp_if; 253825944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 253925944Sjoerg u_long hisaddr, desiredaddr; 254042104Sphk int gotmyaddr = 0; 254125944Sjoerg 254225944Sjoerg len -= 4; 254325944Sjoerg origlen = len; 254425944Sjoerg /* 254525944Sjoerg * Make sure to allocate a buf that can at least hold a 254625944Sjoerg * conf-nak with an `address' option. We might need it below. 254725944Sjoerg */ 254825944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 254925944Sjoerg if (! buf) 255025944Sjoerg return (0); 255125944Sjoerg 255225944Sjoerg /* pass 1: see if we can recognize them */ 255325944Sjoerg if (debug) 255440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 255540008Sjoerg SPP_ARGS(ifp)); 255625944Sjoerg p = (void*) (h+1); 255725944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 255825944Sjoerg if (debug) 255925944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 256025944Sjoerg switch (*p) { 256125944Sjoerg case IPCP_OPT_ADDRESS: 256225944Sjoerg if (len >= 6 && p[1] == 6) { 256325944Sjoerg /* correctly formed address option */ 256425944Sjoerg continue; 256525944Sjoerg } 256625706Sjoerg if (debug) 256725944Sjoerg addlog("[invalid] "); 256811189Sjkh break; 256925944Sjoerg default: 257025944Sjoerg /* Others not supported. */ 257125944Sjoerg if (debug) 257225944Sjoerg addlog("[rej] "); 25734910Swollman break; 25744910Swollman } 257525944Sjoerg /* Add the option to rejected list. */ 257625944Sjoerg bcopy (p, r, p[1]); 257725944Sjoerg r += p[1]; 257825944Sjoerg rlen += p[1]; 257925944Sjoerg } 258025944Sjoerg if (rlen) { 258125944Sjoerg if (debug) 258225944Sjoerg addlog(" send conf-rej\n"); 258325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 258425944Sjoerg return 0; 258525944Sjoerg } else if (debug) 258625944Sjoerg addlog("\n"); 258725944Sjoerg 258825944Sjoerg /* pass 2: parse option values */ 258930300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 259025944Sjoerg if (debug) 259140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 259240008Sjoerg SPP_ARGS(ifp)); 259325944Sjoerg p = (void*) (h+1); 259425944Sjoerg len = origlen; 259525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 259625944Sjoerg if (debug) 259725944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 259825944Sjoerg switch (*p) { 259925944Sjoerg case IPCP_OPT_ADDRESS: 260042104Sphk /* This is the address he wants in his end */ 260125944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 260225944Sjoerg p[4] << 8 | p[5]; 260333928Sphk if (desiredaddr == hisaddr || 260442104Sphk (hisaddr == 1 && desiredaddr != 0)) { 260525944Sjoerg /* 260625944Sjoerg * Peer's address is same as our value, 260733928Sphk * or we have set it to 0.0.0.1 to 260833928Sphk * indicate that we do not really care, 260925944Sjoerg * this is agreeable. Gonna conf-ack 261025944Sjoerg * it. 261125944Sjoerg */ 261225944Sjoerg if (debug) 261330300Sjoerg addlog("%s [ack] ", 261442104Sphk sppp_dotted_quad(hisaddr)); 261525944Sjoerg /* record that we've seen it already */ 261625944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 261725944Sjoerg continue; 261825944Sjoerg } 261925944Sjoerg /* 262025944Sjoerg * The address wasn't agreeable. This is either 262125944Sjoerg * he sent us 0.0.0.0, asking to assign him an 262225944Sjoerg * address, or he send us another address not 262325944Sjoerg * matching our value. Either case, we gonna 262425944Sjoerg * conf-nak it with our value. 262542104Sphk * XXX: we should "rej" if hisaddr == 0 262625944Sjoerg */ 262725944Sjoerg if (debug) { 262825944Sjoerg if (desiredaddr == 0) 262925944Sjoerg addlog("[addr requested] "); 263025944Sjoerg else 263130300Sjoerg addlog("%s [not agreed] ", 263242104Sphk sppp_dotted_quad(desiredaddr)); 263325944Sjoerg 263425944Sjoerg } 263544235Sphk p[2] = hisaddr >> 24; 263644235Sphk p[3] = hisaddr >> 16; 263744235Sphk p[4] = hisaddr >> 8; 263844235Sphk p[5] = hisaddr; 263911189Sjkh break; 264025706Sjoerg } 264125944Sjoerg /* Add the option to nak'ed list. */ 264225944Sjoerg bcopy (p, r, p[1]); 264325944Sjoerg r += p[1]; 264425944Sjoerg rlen += p[1]; 264525944Sjoerg } 264625944Sjoerg 264725944Sjoerg /* 264825944Sjoerg * If we are about to conf-ack the request, but haven't seen 264925944Sjoerg * his address so far, gonna conf-nak it instead, with the 265025944Sjoerg * `address' option present and our idea of his address being 265125944Sjoerg * filled in there, to request negotiation of both addresses. 265225944Sjoerg * 265325944Sjoerg * XXX This can result in an endless req - nak loop if peer 265425944Sjoerg * doesn't want to send us his address. Q: What should we do 265525944Sjoerg * about it? XXX A: implement the max-failure counter. 265625944Sjoerg */ 265742104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 265825944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 265925944Sjoerg buf[1] = 6; 266025944Sjoerg buf[2] = hisaddr >> 24; 266125944Sjoerg buf[3] = hisaddr >> 16; 266225944Sjoerg buf[4] = hisaddr >> 8; 266325944Sjoerg buf[5] = hisaddr; 266425944Sjoerg rlen = 6; 266525706Sjoerg if (debug) 266625944Sjoerg addlog("still need hisaddr "); 266725944Sjoerg } 266825944Sjoerg 266925944Sjoerg if (rlen) { 267025706Sjoerg if (debug) 267125944Sjoerg addlog(" send conf-nak\n"); 267225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 267325944Sjoerg } else { 267425706Sjoerg if (debug) 267525944Sjoerg addlog(" send conf-ack\n"); 267625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 267725944Sjoerg h->ident, origlen, h+1); 267825944Sjoerg } 267925944Sjoerg 268025944Sjoerg free (buf, M_TEMP); 268125944Sjoerg return (rlen == 0); 268225944Sjoerg} 268325944Sjoerg 268425944Sjoerg/* 268525944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 268625944Sjoerg * negotiation. 268725944Sjoerg */ 268825944Sjoergstatic void 268925944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 269025944Sjoerg{ 269125944Sjoerg u_char *buf, *p; 269225944Sjoerg struct ifnet *ifp = &sp->pp_if; 269325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 269425944Sjoerg 269525944Sjoerg len -= 4; 269625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 269725944Sjoerg if (!buf) 269825944Sjoerg return; 269925944Sjoerg 270025944Sjoerg if (debug) 270140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 270240008Sjoerg SPP_ARGS(ifp)); 270325944Sjoerg 270425944Sjoerg p = (void*) (h+1); 270525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 270625706Sjoerg if (debug) 270725944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 270825944Sjoerg switch (*p) { 270925944Sjoerg case IPCP_OPT_ADDRESS: 271025944Sjoerg /* 271125944Sjoerg * Peer doesn't grok address option. This is 271225944Sjoerg * bad. XXX Should we better give up here? 271342104Sphk * XXX We could try old "addresses" option... 271425944Sjoerg */ 271525944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 271625944Sjoerg break; 271725944Sjoerg } 27184910Swollman } 271925944Sjoerg if (debug) 272025944Sjoerg addlog("\n"); 272125944Sjoerg free (buf, M_TEMP); 272225944Sjoerg return; 27234910Swollman} 27244910Swollman 272525944Sjoerg/* 272625944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 272725944Sjoerg * negotiation. 272825944Sjoerg */ 272912820Sphkstatic void 273025944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 27314910Swollman{ 273225944Sjoerg u_char *buf, *p; 273325944Sjoerg struct ifnet *ifp = &sp->pp_if; 273425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 273525944Sjoerg u_long wantaddr; 27364910Swollman 273725944Sjoerg len -= 4; 273825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 273925944Sjoerg if (!buf) 274025944Sjoerg return; 274125944Sjoerg 274225944Sjoerg if (debug) 274340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 274440008Sjoerg SPP_ARGS(ifp)); 274525944Sjoerg 274625944Sjoerg p = (void*) (h+1); 274725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 274825944Sjoerg if (debug) 274925944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 275025944Sjoerg switch (*p) { 275125944Sjoerg case IPCP_OPT_ADDRESS: 275225944Sjoerg /* 275325944Sjoerg * Peer doesn't like our local IP address. See 275425944Sjoerg * if we can do something for him. We'll drop 275525944Sjoerg * him our address then. 275625944Sjoerg */ 275725944Sjoerg if (len >= 6 && p[1] == 6) { 275825944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 275925944Sjoerg p[4] << 8 | p[5]; 276025944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 276125944Sjoerg if (debug) 276230300Sjoerg addlog("[wantaddr %s] ", 276330300Sjoerg sppp_dotted_quad(wantaddr)); 276425944Sjoerg /* 276525944Sjoerg * When doing dynamic address assignment, 276625944Sjoerg * we accept his offer. Otherwise, we 276725944Sjoerg * ignore it and thus continue to negotiate 276825944Sjoerg * our already existing value. 276942104Sphk * XXX: Bogus, if he said no once, he'll 277042104Sphk * just say no again, might as well die. 277125944Sjoerg */ 277225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 277325944Sjoerg sppp_set_ip_addr(sp, wantaddr); 277425944Sjoerg if (debug) 277525944Sjoerg addlog("[agree] "); 277642104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 277725944Sjoerg } 277825944Sjoerg } 277925944Sjoerg break; 278025944Sjoerg } 278125944Sjoerg } 278225944Sjoerg if (debug) 278325944Sjoerg addlog("\n"); 278425944Sjoerg free (buf, M_TEMP); 278525944Sjoerg return; 27864910Swollman} 27874910Swollman 278812820Sphkstatic void 278925944Sjoergsppp_ipcp_tlu(struct sppp *sp) 27904910Swollman{ 279142104Sphk /* we are up - notify isdn daemon */ 279242104Sphk if (sp->pp_con) 279342104Sphk sp->pp_con(sp); 27944910Swollman} 27954910Swollman 279625944Sjoergstatic void 279725944Sjoergsppp_ipcp_tld(struct sppp *sp) 279825944Sjoerg{ 279925944Sjoerg} 280025944Sjoerg 280125944Sjoergstatic void 280225944Sjoergsppp_ipcp_tls(struct sppp *sp) 280325944Sjoerg{ 280425944Sjoerg /* indicate to LCP that it must stay alive */ 280525944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 280625944Sjoerg} 280725944Sjoerg 280825944Sjoergstatic void 280925944Sjoergsppp_ipcp_tlf(struct sppp *sp) 281025944Sjoerg{ 281125944Sjoerg /* we no longer need LCP */ 281225944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 281330300Sjoerg sppp_lcp_check_and_close(sp); 281425944Sjoerg} 281525944Sjoerg 281625944Sjoergstatic void 281725944Sjoergsppp_ipcp_scr(struct sppp *sp) 281825944Sjoerg{ 281925944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 282025944Sjoerg u_long ouraddr; 282125944Sjoerg int i = 0; 282225944Sjoerg 282325944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 282430300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 282525944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 282625944Sjoerg opt[i++] = 6; 282725944Sjoerg opt[i++] = ouraddr >> 24; 282825944Sjoerg opt[i++] = ouraddr >> 16; 282925944Sjoerg opt[i++] = ouraddr >> 8; 283025944Sjoerg opt[i++] = ouraddr; 283125944Sjoerg } 283225944Sjoerg 283325944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 283425944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 283525944Sjoerg} 283625944Sjoerg 283725944Sjoerg 283825944Sjoerg/* 283930300Sjoerg *--------------------------------------------------------------------------* 284030300Sjoerg * * 284130300Sjoerg * The CHAP implementation. * 284230300Sjoerg * * 284330300Sjoerg *--------------------------------------------------------------------------* 284430300Sjoerg */ 284530300Sjoerg 284630300Sjoerg/* 284730300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 284830300Sjoerg * the control protocols do, since they do have Open and Close events, but 284930300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 285030300Sjoerg * authentication protocols may be different in both directions (this makes 285130300Sjoerg * sense, think of a machine that never accepts incoming calls but only 285230300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 285330300Sjoerg * 285430300Sjoerg * Our state machine for the local authentication protocol (we are requesting 285530300Sjoerg * the peer to authenticate) looks like: 285630300Sjoerg * 285730300Sjoerg * RCA- 285830300Sjoerg * +--------------------------------------------+ 285930300Sjoerg * V scn,tld| 286030300Sjoerg * +--------+ Close +---------+ RCA+ 286130300Sjoerg * | |<----------------------------------| |------+ 286230300Sjoerg * +--->| Closed | TO* | Opened | sca | 286330300Sjoerg * | | |-----+ +-------| |<-----+ 286430300Sjoerg * | +--------+ irc | | +---------+ 286530300Sjoerg * | ^ | | ^ 286630300Sjoerg * | | | | | 286730300Sjoerg * | | | | | 286830300Sjoerg * | TO-| | | | 286930300Sjoerg * | |tld TO+ V | | 287030300Sjoerg * | | +------->+ | | 287130300Sjoerg * | | | | | | 287230300Sjoerg * | +--------+ V | | 287330300Sjoerg * | | |<----+<--------------------+ | 287430300Sjoerg * | | Req- | scr | 287530300Sjoerg * | | Sent | | 287630300Sjoerg * | | | | 287730300Sjoerg * | +--------+ | 287830300Sjoerg * | RCA- | | RCA+ | 287930300Sjoerg * +------+ +------------------------------------------+ 288030300Sjoerg * scn,tld sca,irc,ict,tlu 288130300Sjoerg * 288230300Sjoerg * 288330300Sjoerg * with: 288430300Sjoerg * 288530300Sjoerg * Open: LCP reached authentication phase 288630300Sjoerg * Close: LCP reached terminate phase 288730300Sjoerg * 288830300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 288930300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 289030300Sjoerg * TO+: timeout with restart counter >= 0 289130300Sjoerg * TO-: timeout with restart counter < 0 289230300Sjoerg * TO*: reschedule timeout for CHAP 289330300Sjoerg * 289430300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 289530300Sjoerg * sca: send ack packet (pap-ack, chap-success) 289630300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 289730300Sjoerg * ict: initialize re-challenge timer (CHAP only) 289830300Sjoerg * 289930300Sjoerg * tlu: this-layer-up, LCP reaches network phase 290030300Sjoerg * tld: this-layer-down, LCP enters terminate phase 290130300Sjoerg * 290230300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 290330300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 290430300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 290530300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 290630300Sjoerg * causing LCP to enter terminate phase. 290730300Sjoerg * 290830300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 290930300Sjoerg * expected to send one based on the successful negotiation of PAP as 291030300Sjoerg * the authentication protocol during the LCP option negotiation. 291130300Sjoerg * 291230300Sjoerg * Incoming authentication protocol requests (remote requests 291330300Sjoerg * authentication, we are peer) don't employ a state machine at all, 291430300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 291530300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 291630300Sjoerg * still in authentication phase (thereby violating the standard that 291730300Sjoerg * demands that these NCP packets are to be discarded), so we keep 291830300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 291930300Sjoerg * phase network once we've seen a positive acknowledge for the 292030300Sjoerg * authentication. 292130300Sjoerg */ 292230300Sjoerg 292330300Sjoerg/* 292430300Sjoerg * Handle incoming CHAP packets. 292530300Sjoerg */ 292630300Sjoergvoid 292730300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 292830300Sjoerg{ 292930300Sjoerg STDDCL; 293030300Sjoerg struct lcp_header *h; 293130300Sjoerg int len, x; 293230300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 293330300Sjoerg int value_len, name_len; 293430300Sjoerg MD5_CTX ctx; 293530300Sjoerg 293630300Sjoerg len = m->m_pkthdr.len; 293730300Sjoerg if (len < 4) { 293830300Sjoerg if (debug) 293930300Sjoerg log(LOG_DEBUG, 294040008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 294140008Sjoerg SPP_ARGS(ifp), len); 294230300Sjoerg return; 294330300Sjoerg } 294430300Sjoerg h = mtod (m, struct lcp_header*); 294530300Sjoerg if (len > ntohs (h->len)) 294630300Sjoerg len = ntohs (h->len); 294730300Sjoerg 294830300Sjoerg switch (h->type) { 294930300Sjoerg /* challenge, failure and success are his authproto */ 295030300Sjoerg case CHAP_CHALLENGE: 295130300Sjoerg value = 1 + (u_char*)(h+1); 295230300Sjoerg value_len = value[-1]; 295330300Sjoerg name = value + value_len; 295430300Sjoerg name_len = len - value_len - 5; 295530300Sjoerg if (name_len < 0) { 295630300Sjoerg if (debug) { 295730300Sjoerg log(LOG_DEBUG, 295840008Sjoerg SPP_FMT "chap corrupted challenge " 295930300Sjoerg "<%s id=0x%x len=%d", 296040008Sjoerg SPP_ARGS(ifp), 296130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 296230300Sjoerg h->ident, ntohs(h->len)); 296344145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 296430300Sjoerg addlog(">\n"); 296530300Sjoerg } 296630300Sjoerg break; 296730300Sjoerg } 296830300Sjoerg 296930300Sjoerg if (debug) { 297030300Sjoerg log(LOG_DEBUG, 297140008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 297240008Sjoerg SPP_ARGS(ifp), 297330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 297430300Sjoerg ntohs(h->len)); 297530300Sjoerg sppp_print_string((char*) name, name_len); 297630300Sjoerg addlog(" value-size=%d value=", value_len); 297730300Sjoerg sppp_print_bytes(value, value_len); 297830300Sjoerg addlog(">\n"); 297930300Sjoerg } 298030300Sjoerg 298130300Sjoerg /* Compute reply value. */ 298230300Sjoerg MD5Init(&ctx); 298330300Sjoerg MD5Update(&ctx, &h->ident, 1); 298430300Sjoerg MD5Update(&ctx, sp->myauth.secret, 298530300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 298630300Sjoerg MD5Update(&ctx, value, value_len); 298730300Sjoerg MD5Final(digest, &ctx); 298830300Sjoerg dsize = sizeof digest; 298930300Sjoerg 299030300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 299130300Sjoerg sizeof dsize, (const char *)&dsize, 299230300Sjoerg sizeof digest, digest, 299340008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 299430300Sjoerg sp->myauth.name, 299530300Sjoerg 0); 299630300Sjoerg break; 299730300Sjoerg 299830300Sjoerg case CHAP_SUCCESS: 299930300Sjoerg if (debug) { 300040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 300140008Sjoerg SPP_ARGS(ifp)); 300230300Sjoerg if (len > 4) { 300330300Sjoerg addlog(": "); 300430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 300530300Sjoerg } 300630300Sjoerg addlog("\n"); 300730300Sjoerg } 300830300Sjoerg x = splimp(); 300930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 301030300Sjoerg if (sp->myauth.proto == PPP_CHAP && 301132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 301230300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 301330300Sjoerg /* 301430300Sjoerg * We are authenticator for CHAP but didn't 301530300Sjoerg * complete yet. Leave it to tlu to proceed 301630300Sjoerg * to network phase. 301730300Sjoerg */ 301830300Sjoerg splx(x); 301930300Sjoerg break; 302030300Sjoerg } 302130300Sjoerg splx(x); 302230300Sjoerg sppp_phase_network(sp); 302330300Sjoerg break; 302430300Sjoerg 302530300Sjoerg case CHAP_FAILURE: 302630300Sjoerg if (debug) { 302740008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 302840008Sjoerg SPP_ARGS(ifp)); 302930300Sjoerg if (len > 4) { 303030300Sjoerg addlog(": "); 303130300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 303230300Sjoerg } 303330300Sjoerg addlog("\n"); 303430300Sjoerg } else 303540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 303640008Sjoerg SPP_ARGS(ifp)); 303730300Sjoerg /* await LCP shutdown by authenticator */ 303830300Sjoerg break; 303930300Sjoerg 304030300Sjoerg /* response is my authproto */ 304130300Sjoerg case CHAP_RESPONSE: 304230300Sjoerg value = 1 + (u_char*)(h+1); 304330300Sjoerg value_len = value[-1]; 304430300Sjoerg name = value + value_len; 304530300Sjoerg name_len = len - value_len - 5; 304630300Sjoerg if (name_len < 0) { 304730300Sjoerg if (debug) { 304830300Sjoerg log(LOG_DEBUG, 304940008Sjoerg SPP_FMT "chap corrupted response " 305030300Sjoerg "<%s id=0x%x len=%d", 305140008Sjoerg SPP_ARGS(ifp), 305230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 305330300Sjoerg h->ident, ntohs(h->len)); 305444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 305530300Sjoerg addlog(">\n"); 305630300Sjoerg } 305730300Sjoerg break; 305830300Sjoerg } 305930300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 306030300Sjoerg if (debug) 306130300Sjoerg log(LOG_DEBUG, 306240008Sjoerg SPP_FMT "chap dropping response for old ID " 306330300Sjoerg "(got %d, expected %d)\n", 306440008Sjoerg SPP_ARGS(ifp), 306530300Sjoerg h->ident, sp->confid[IDX_CHAP]); 306630300Sjoerg break; 306730300Sjoerg } 306830300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 306930300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 307040008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 307140008Sjoerg SPP_ARGS(ifp)); 307230300Sjoerg sppp_print_string(name, name_len); 307330300Sjoerg addlog(" != expected "); 307430300Sjoerg sppp_print_string(sp->hisauth.name, 307530300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 307630300Sjoerg addlog("\n"); 307730300Sjoerg } 307830300Sjoerg if (debug) { 307940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 308030300Sjoerg "<%s id=0x%x len=%d name=", 308140008Sjoerg SPP_ARGS(ifp), 308230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 308330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 308430300Sjoerg h->ident, ntohs (h->len)); 308530300Sjoerg sppp_print_string((char*)name, name_len); 308630300Sjoerg addlog(" value-size=%d value=", value_len); 308730300Sjoerg sppp_print_bytes(value, value_len); 308830300Sjoerg addlog(">\n"); 308930300Sjoerg } 309030300Sjoerg if (value_len != AUTHKEYLEN) { 309130300Sjoerg if (debug) 309230300Sjoerg log(LOG_DEBUG, 309340008Sjoerg SPP_FMT "chap bad hash value length: " 309430300Sjoerg "%d bytes, should be %d\n", 309540008Sjoerg SPP_ARGS(ifp), value_len, 309630300Sjoerg AUTHKEYLEN); 309730300Sjoerg break; 309830300Sjoerg } 309930300Sjoerg 310030300Sjoerg MD5Init(&ctx); 310130300Sjoerg MD5Update(&ctx, &h->ident, 1); 310230300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 310330300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 310430300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 310530300Sjoerg MD5Final(digest, &ctx); 310630300Sjoerg 310730300Sjoerg#define FAILMSG "Failed..." 310830300Sjoerg#define SUCCMSG "Welcome!" 310930300Sjoerg 311030300Sjoerg if (value_len != sizeof digest || 311130300Sjoerg bcmp(digest, value, value_len) != 0) { 311230300Sjoerg /* action scn, tld */ 311330300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 311430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 311530300Sjoerg 0); 311630300Sjoerg chap.tld(sp); 311730300Sjoerg break; 311830300Sjoerg } 311930300Sjoerg /* action sca, perhaps tlu */ 312030300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 312130300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 312230300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 312330300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 312430300Sjoerg 0); 312530300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 312630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 312730300Sjoerg chap.tlu(sp); 312830300Sjoerg } 312930300Sjoerg break; 313030300Sjoerg 313130300Sjoerg default: 313230300Sjoerg /* Unknown CHAP packet type -- ignore. */ 313330300Sjoerg if (debug) { 313440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 313530300Sjoerg "<0x%x id=0x%xh len=%d", 313640008Sjoerg SPP_ARGS(ifp), 313730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 313830300Sjoerg h->type, h->ident, ntohs(h->len)); 313944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 314030300Sjoerg addlog(">\n"); 314130300Sjoerg } 314230300Sjoerg break; 314330300Sjoerg 314430300Sjoerg } 314530300Sjoerg} 314630300Sjoerg 314730300Sjoergstatic void 314830300Sjoergsppp_chap_init(struct sppp *sp) 314930300Sjoerg{ 315030300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 315130300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 315230300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 315342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 315430300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 315540008Sjoerg#endif 315630300Sjoerg} 315730300Sjoerg 315830300Sjoergstatic void 315930300Sjoergsppp_chap_open(struct sppp *sp) 316030300Sjoerg{ 316130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 316230300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 316330300Sjoerg /* we are authenticator for CHAP, start it */ 316430300Sjoerg chap.scr(sp); 316530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 316630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 316730300Sjoerg } 316830300Sjoerg /* nothing to be done if we are peer, await a challenge */ 316930300Sjoerg} 317030300Sjoerg 317130300Sjoergstatic void 317230300Sjoergsppp_chap_close(struct sppp *sp) 317330300Sjoerg{ 317430300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 317530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 317630300Sjoerg} 317730300Sjoerg 317830300Sjoergstatic void 317930300Sjoergsppp_chap_TO(void *cookie) 318030300Sjoerg{ 318130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 318230300Sjoerg STDDCL; 318330300Sjoerg int s; 318430300Sjoerg 318530300Sjoerg s = splimp(); 318630300Sjoerg if (debug) 318740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 318840008Sjoerg SPP_ARGS(ifp), 318930300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 319030300Sjoerg sp->rst_counter[IDX_CHAP]); 319130300Sjoerg 319230300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 319330300Sjoerg /* TO- event */ 319430300Sjoerg switch (sp->state[IDX_CHAP]) { 319530300Sjoerg case STATE_REQ_SENT: 319630300Sjoerg chap.tld(sp); 319730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 319830300Sjoerg break; 319930300Sjoerg } 320030300Sjoerg else 320130300Sjoerg /* TO+ (or TO*) event */ 320230300Sjoerg switch (sp->state[IDX_CHAP]) { 320330300Sjoerg case STATE_OPENED: 320430300Sjoerg /* TO* event */ 320530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 320630300Sjoerg /* fall through */ 320730300Sjoerg case STATE_REQ_SENT: 320830300Sjoerg chap.scr(sp); 320930300Sjoerg /* sppp_cp_change_state() will restart the timer */ 321030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 321130300Sjoerg break; 321230300Sjoerg } 321330300Sjoerg 321430300Sjoerg splx(s); 321530300Sjoerg} 321630300Sjoerg 321730300Sjoergstatic void 321830300Sjoergsppp_chap_tlu(struct sppp *sp) 321930300Sjoerg{ 322030300Sjoerg STDDCL; 322130300Sjoerg int i, x; 322230300Sjoerg 322340010Sjoerg i = 0; 322430300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 322530300Sjoerg 322630300Sjoerg /* 322730300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 322830300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 322930300Sjoerg * initial challenge-response exchange has taken place. 323030300Sjoerg * Provide for an option to avoid rechallenges. 323130300Sjoerg */ 323230300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 323330300Sjoerg /* 323430300Sjoerg * Compute the re-challenge timeout. This will yield 323530300Sjoerg * a number between 300 and 810 seconds. 323630300Sjoerg */ 323730300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 323842064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 323930300Sjoerg } 324030300Sjoerg 324130300Sjoerg if (debug) { 324230300Sjoerg log(LOG_DEBUG, 324340008Sjoerg SPP_FMT "chap %s, ", 324440008Sjoerg SPP_ARGS(ifp), 324530300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 324630300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 324730300Sjoerg addlog("next re-challenge in %d seconds\n", i); 324830300Sjoerg else 324930300Sjoerg addlog("re-challenging supressed\n"); 325030300Sjoerg } 325130300Sjoerg 325230300Sjoerg x = splimp(); 325330300Sjoerg /* indicate to LCP that we need to be closed down */ 325430300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 325530300Sjoerg 325630300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 325730300Sjoerg /* 325830300Sjoerg * Remote is authenticator, but his auth proto didn't 325930300Sjoerg * complete yet. Defer the transition to network 326030300Sjoerg * phase. 326130300Sjoerg */ 326230300Sjoerg splx(x); 326330300Sjoerg return; 326430300Sjoerg } 326530300Sjoerg splx(x); 326630300Sjoerg 326730300Sjoerg /* 326830300Sjoerg * If we are already in phase network, we are done here. This 326930300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 327030300Sjoerg */ 327130300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 327230300Sjoerg sppp_phase_network(sp); 327330300Sjoerg} 327430300Sjoerg 327530300Sjoergstatic void 327630300Sjoergsppp_chap_tld(struct sppp *sp) 327730300Sjoerg{ 327830300Sjoerg STDDCL; 327930300Sjoerg 328030300Sjoerg if (debug) 328140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 328240008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 328330300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 328430300Sjoerg 328530300Sjoerg lcp.Close(sp); 328630300Sjoerg} 328730300Sjoerg 328830300Sjoergstatic void 328930300Sjoergsppp_chap_scr(struct sppp *sp) 329030300Sjoerg{ 329130300Sjoerg u_long *ch, seed; 329230300Sjoerg u_char clen; 329330300Sjoerg 329430300Sjoerg /* Compute random challenge. */ 329530300Sjoerg ch = (u_long *)sp->myauth.challenge; 329642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 329735064Sphk read_random(&seed, sizeof seed); 329840008Sjoerg#else 329942104Sphk { 330042104Sphk struct timeval tv; 330140008Sjoerg microtime(&tv); 330240008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 330342104Sphk } 330440008Sjoerg#endif 330530300Sjoerg ch[0] = seed ^ random(); 330630300Sjoerg ch[1] = seed ^ random(); 330730300Sjoerg ch[2] = seed ^ random(); 330830300Sjoerg ch[3] = seed ^ random(); 330930300Sjoerg clen = AUTHKEYLEN; 331030300Sjoerg 331130300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 331230300Sjoerg 331330300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 331430300Sjoerg sizeof clen, (const char *)&clen, 331540008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 331640008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 331730300Sjoerg sp->myauth.name, 331830300Sjoerg 0); 331930300Sjoerg} 332030300Sjoerg/* 332130300Sjoerg *--------------------------------------------------------------------------* 332230300Sjoerg * * 332330300Sjoerg * The PAP implementation. * 332430300Sjoerg * * 332530300Sjoerg *--------------------------------------------------------------------------* 332630300Sjoerg */ 332730300Sjoerg/* 332830300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 332930300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 333030300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 333130300Sjoerg * retry counter is expired). 333230300Sjoerg */ 333330300Sjoerg 333430300Sjoerg/* 333530300Sjoerg * Handle incoming PAP packets. */ 333630300Sjoergstatic void 333730300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 333830300Sjoerg{ 333930300Sjoerg STDDCL; 334030300Sjoerg struct lcp_header *h; 334130300Sjoerg int len, x; 334230300Sjoerg u_char *name, *passwd, mlen; 334330300Sjoerg int name_len, passwd_len; 334430300Sjoerg 334530300Sjoerg len = m->m_pkthdr.len; 334630300Sjoerg if (len < 5) { 334730300Sjoerg if (debug) 334830300Sjoerg log(LOG_DEBUG, 334940008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 335040008Sjoerg SPP_ARGS(ifp), len); 335130300Sjoerg return; 335230300Sjoerg } 335330300Sjoerg h = mtod (m, struct lcp_header*); 335430300Sjoerg if (len > ntohs (h->len)) 335530300Sjoerg len = ntohs (h->len); 335630300Sjoerg switch (h->type) { 335730300Sjoerg /* PAP request is my authproto */ 335830300Sjoerg case PAP_REQ: 335930300Sjoerg name = 1 + (u_char*)(h+1); 336030300Sjoerg name_len = name[-1]; 336130300Sjoerg passwd = name + name_len + 1; 336230300Sjoerg if (name_len > len - 6 || 336330300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 336430300Sjoerg if (debug) { 336540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 336630300Sjoerg "<%s id=0x%x len=%d", 336740008Sjoerg SPP_ARGS(ifp), 336830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 336930300Sjoerg h->ident, ntohs(h->len)); 337044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 337130300Sjoerg addlog(">\n"); 337230300Sjoerg } 337330300Sjoerg break; 337430300Sjoerg } 337530300Sjoerg if (debug) { 337640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 337730300Sjoerg "<%s id=0x%x len=%d name=", 337840008Sjoerg SPP_ARGS(ifp), 337930300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 338030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 338130300Sjoerg h->ident, ntohs(h->len)); 338230300Sjoerg sppp_print_string((char*)name, name_len); 338330300Sjoerg addlog(" passwd="); 338430300Sjoerg sppp_print_string((char*)passwd, passwd_len); 338530300Sjoerg addlog(">\n"); 338630300Sjoerg } 338730300Sjoerg if (name_len > AUTHNAMELEN || 338830300Sjoerg passwd_len > AUTHKEYLEN || 338930300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 339030300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 339130300Sjoerg /* action scn, tld */ 339230300Sjoerg mlen = sizeof(FAILMSG) - 1; 339330300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 339430300Sjoerg sizeof mlen, (const char *)&mlen, 339530300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 339630300Sjoerg 0); 339730300Sjoerg pap.tld(sp); 339830300Sjoerg break; 339930300Sjoerg } 340030300Sjoerg /* action sca, perhaps tlu */ 340130300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 340230300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 340330300Sjoerg mlen = sizeof(SUCCMSG) - 1; 340430300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 340530300Sjoerg sizeof mlen, (const char *)&mlen, 340630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 340730300Sjoerg 0); 340830300Sjoerg } 340930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 341030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 341130300Sjoerg pap.tlu(sp); 341230300Sjoerg } 341330300Sjoerg break; 341430300Sjoerg 341530300Sjoerg /* ack and nak are his authproto */ 341630300Sjoerg case PAP_ACK: 341740008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 341830300Sjoerg if (debug) { 341940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 342040008Sjoerg SPP_ARGS(ifp)); 342130300Sjoerg name_len = *((char *)h); 342230300Sjoerg if (len > 5 && name_len) { 342330300Sjoerg addlog(": "); 342430300Sjoerg sppp_print_string((char*)(h+1), name_len); 342530300Sjoerg } 342630300Sjoerg addlog("\n"); 342730300Sjoerg } 342830300Sjoerg x = splimp(); 342930300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 343030300Sjoerg if (sp->myauth.proto == PPP_PAP && 343132169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 343230300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 343330300Sjoerg /* 343430300Sjoerg * We are authenticator for PAP but didn't 343530300Sjoerg * complete yet. Leave it to tlu to proceed 343630300Sjoerg * to network phase. 343730300Sjoerg */ 343830300Sjoerg splx(x); 343930300Sjoerg break; 344030300Sjoerg } 344130300Sjoerg splx(x); 344230300Sjoerg sppp_phase_network(sp); 344330300Sjoerg break; 344430300Sjoerg 344530300Sjoerg case PAP_NAK: 344640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 344730300Sjoerg if (debug) { 344840008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 344940008Sjoerg SPP_ARGS(ifp)); 345030300Sjoerg name_len = *((char *)h); 345130300Sjoerg if (len > 5 && name_len) { 345230300Sjoerg addlog(": "); 345330300Sjoerg sppp_print_string((char*)(h+1), name_len); 345430300Sjoerg } 345530300Sjoerg addlog("\n"); 345630300Sjoerg } else 345740008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 345840008Sjoerg SPP_ARGS(ifp)); 345930300Sjoerg /* await LCP shutdown by authenticator */ 346030300Sjoerg break; 346130300Sjoerg 346230300Sjoerg default: 346330300Sjoerg /* Unknown PAP packet type -- ignore. */ 346430300Sjoerg if (debug) { 346540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 346630300Sjoerg "<0x%x id=0x%x len=%d", 346740008Sjoerg SPP_ARGS(ifp), 346830300Sjoerg h->type, h->ident, ntohs(h->len)); 346944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 347030300Sjoerg addlog(">\n"); 347130300Sjoerg } 347230300Sjoerg break; 347330300Sjoerg 347430300Sjoerg } 347530300Sjoerg} 347630300Sjoerg 347730300Sjoergstatic void 347830300Sjoergsppp_pap_init(struct sppp *sp) 347930300Sjoerg{ 348030300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 348130300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 348230300Sjoerg sp->fail_counter[IDX_PAP] = 0; 348342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 348430300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 348530300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 348640008Sjoerg#endif 348730300Sjoerg} 348830300Sjoerg 348930300Sjoergstatic void 349030300Sjoergsppp_pap_open(struct sppp *sp) 349130300Sjoerg{ 349230300Sjoerg if (sp->hisauth.proto == PPP_PAP && 349330300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 349430300Sjoerg /* we are authenticator for PAP, start our timer */ 349530300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 349630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 349730300Sjoerg } 349830300Sjoerg if (sp->myauth.proto == PPP_PAP) { 349930300Sjoerg /* we are peer, send a request, and start a timer */ 350030300Sjoerg pap.scr(sp); 350142064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 350242064Sphk sp->pap_my_to_ch); 350330300Sjoerg } 350430300Sjoerg} 350530300Sjoerg 350630300Sjoergstatic void 350730300Sjoergsppp_pap_close(struct sppp *sp) 350830300Sjoerg{ 350930300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 351030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 351130300Sjoerg} 351230300Sjoerg 351330300Sjoerg/* 351430300Sjoerg * That's the timeout routine if we are authenticator. Since the 351530300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 351630300Sjoerg */ 351730300Sjoergstatic void 351830300Sjoergsppp_pap_TO(void *cookie) 351930300Sjoerg{ 352030300Sjoerg struct sppp *sp = (struct sppp *)cookie; 352130300Sjoerg STDDCL; 352230300Sjoerg int s; 352330300Sjoerg 352430300Sjoerg s = splimp(); 352530300Sjoerg if (debug) 352640008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 352740008Sjoerg SPP_ARGS(ifp), 352830300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 352930300Sjoerg sp->rst_counter[IDX_PAP]); 353030300Sjoerg 353130300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 353230300Sjoerg /* TO- event */ 353330300Sjoerg switch (sp->state[IDX_PAP]) { 353430300Sjoerg case STATE_REQ_SENT: 353530300Sjoerg pap.tld(sp); 353630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 353730300Sjoerg break; 353830300Sjoerg } 353930300Sjoerg else 354030300Sjoerg /* TO+ event, not very much we could do */ 354130300Sjoerg switch (sp->state[IDX_PAP]) { 354230300Sjoerg case STATE_REQ_SENT: 354330300Sjoerg /* sppp_cp_change_state() will restart the timer */ 354430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 354530300Sjoerg break; 354630300Sjoerg } 354730300Sjoerg 354830300Sjoerg splx(s); 354930300Sjoerg} 355030300Sjoerg 355130300Sjoerg/* 355230300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 355330300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 355430300Sjoerg * XXX We should impose a max counter. 355530300Sjoerg */ 355630300Sjoergstatic void 355730300Sjoergsppp_pap_my_TO(void *cookie) 355830300Sjoerg{ 355930300Sjoerg struct sppp *sp = (struct sppp *)cookie; 356030300Sjoerg STDDCL; 356130300Sjoerg 356230300Sjoerg if (debug) 356340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 356440008Sjoerg SPP_ARGS(ifp)); 356530300Sjoerg 356630300Sjoerg pap.scr(sp); 356730300Sjoerg} 356830300Sjoerg 356930300Sjoergstatic void 357030300Sjoergsppp_pap_tlu(struct sppp *sp) 357130300Sjoerg{ 357230300Sjoerg STDDCL; 357330300Sjoerg int x; 357430300Sjoerg 357530300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 357630300Sjoerg 357730300Sjoerg if (debug) 357840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 357940008Sjoerg SPP_ARGS(ifp), pap.name); 358030300Sjoerg 358130300Sjoerg x = splimp(); 358230300Sjoerg /* indicate to LCP that we need to be closed down */ 358330300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 358430300Sjoerg 358530300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 358630300Sjoerg /* 358730300Sjoerg * Remote is authenticator, but his auth proto didn't 358830300Sjoerg * complete yet. Defer the transition to network 358930300Sjoerg * phase. 359030300Sjoerg */ 359130300Sjoerg splx(x); 359230300Sjoerg return; 359330300Sjoerg } 359430300Sjoerg splx(x); 359530300Sjoerg sppp_phase_network(sp); 359630300Sjoerg} 359730300Sjoerg 359830300Sjoergstatic void 359930300Sjoergsppp_pap_tld(struct sppp *sp) 360030300Sjoerg{ 360130300Sjoerg STDDCL; 360230300Sjoerg 360330300Sjoerg if (debug) 360440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 360540008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 360640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 360730300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 360830300Sjoerg 360930300Sjoerg lcp.Close(sp); 361030300Sjoerg} 361130300Sjoerg 361230300Sjoergstatic void 361330300Sjoergsppp_pap_scr(struct sppp *sp) 361430300Sjoerg{ 361530300Sjoerg u_char idlen, pwdlen; 361630300Sjoerg 361730300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 361830300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 361930300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 362030300Sjoerg 362130300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 362230300Sjoerg sizeof idlen, (const char *)&idlen, 362340008Sjoerg (size_t)idlen, sp->myauth.name, 362430300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 362540008Sjoerg (size_t)pwdlen, sp->myauth.secret, 362630300Sjoerg 0); 362730300Sjoerg} 362830300Sjoerg/* 362925944Sjoerg * Random miscellaneous functions. 363025944Sjoerg */ 363125944Sjoerg 36324910Swollman/* 363330300Sjoerg * Send a PAP or CHAP proto packet. 363430300Sjoerg * 363530300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 363640008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 363730300Sjoerg * mlen == 0. 363842104Sphk * NOTE: never declare variadic functions with types subject to type 363942104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 364042104Sphk * on the architecture you are on... 364130300Sjoerg */ 364230300Sjoerg 364330300Sjoergstatic void 364442104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 364542104Sphk unsigned int type, unsigned int id, 364630300Sjoerg ...) 364730300Sjoerg{ 364830300Sjoerg STDDCL; 364930300Sjoerg struct ppp_header *h; 365030300Sjoerg struct lcp_header *lh; 365130300Sjoerg struct mbuf *m; 365230300Sjoerg u_char *p; 365330300Sjoerg int len; 365442104Sphk unsigned int mlen; 365530300Sjoerg const char *msg; 365630300Sjoerg va_list ap; 365730300Sjoerg 365830300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 365930300Sjoerg if (! m) 366030300Sjoerg return; 366130300Sjoerg m->m_pkthdr.rcvif = 0; 366230300Sjoerg 366330300Sjoerg h = mtod (m, struct ppp_header*); 366430300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 366530300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 366630300Sjoerg h->protocol = htons(cp->proto); 366730300Sjoerg 366830300Sjoerg lh = (struct lcp_header*)(h + 1); 366930300Sjoerg lh->type = type; 367030300Sjoerg lh->ident = id; 367130300Sjoerg p = (u_char*) (lh+1); 367230300Sjoerg 367330300Sjoerg va_start(ap, id); 367430300Sjoerg len = 0; 367530300Sjoerg 367642104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 367730300Sjoerg msg = va_arg(ap, const char *); 367830300Sjoerg len += mlen; 367930300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 368030300Sjoerg va_end(ap); 368130300Sjoerg m_freem(m); 368230300Sjoerg return; 368330300Sjoerg } 368430300Sjoerg 368530300Sjoerg bcopy(msg, p, mlen); 368630300Sjoerg p += mlen; 368730300Sjoerg } 368830300Sjoerg va_end(ap); 368930300Sjoerg 369030300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 369130300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 369230300Sjoerg 369330300Sjoerg if (debug) { 369440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 369540008Sjoerg SPP_ARGS(ifp), cp->name, 369630300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 369730300Sjoerg lh->ident, ntohs(lh->len)); 369844145Sphk sppp_print_bytes((u_char*) (lh+1), len); 369930300Sjoerg addlog(">\n"); 370030300Sjoerg } 370169152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 370269152Sjlemon ifp->if_oerrors++; 370330300Sjoerg} 370430300Sjoerg 370530300Sjoerg/* 370625944Sjoerg * Flush interface queue. 37074910Swollman */ 370812820Sphkstatic void 370925944Sjoergsppp_qflush(struct ifqueue *ifq) 37104910Swollman{ 371125944Sjoerg struct mbuf *m, *n; 37124910Swollman 371325944Sjoerg n = ifq->ifq_head; 371425944Sjoerg while ((m = n)) { 371525944Sjoerg n = m->m_act; 371625944Sjoerg m_freem (m); 371711189Sjkh } 371825944Sjoerg ifq->ifq_head = 0; 371925944Sjoerg ifq->ifq_tail = 0; 372025944Sjoerg ifq->ifq_len = 0; 372125944Sjoerg} 372225944Sjoerg 372325944Sjoerg/* 372425944Sjoerg * Send keepalive packets, every 10 seconds. 372525944Sjoerg */ 372625944Sjoergstatic void 372725944Sjoergsppp_keepalive(void *dummy) 372825944Sjoerg{ 372925944Sjoerg struct sppp *sp; 373025944Sjoerg int s; 373125944Sjoerg 373225944Sjoerg s = splimp(); 373325944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 373425944Sjoerg struct ifnet *ifp = &sp->pp_if; 373525944Sjoerg 373625944Sjoerg /* Keepalive mode disabled or channel down? */ 373725944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 373825944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 373925944Sjoerg continue; 374025944Sjoerg 374125944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 374245152Sphk if (sp->pp_mode != IFF_CISCO && 374325944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 374425944Sjoerg continue; 374525944Sjoerg 374625944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 374725944Sjoerg /* No keepalive packets got. Stop the interface. */ 374840008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 374925944Sjoerg if_down (ifp); 375026018Sjoerg sppp_qflush (&sp->pp_cpq); 375145152Sphk if (sp->pp_mode != IFF_CISCO) { 375225944Sjoerg /* XXX */ 375325944Sjoerg /* Shut down the PPP link. */ 375425944Sjoerg lcp.Down(sp); 375525944Sjoerg /* Initiate negotiation. XXX */ 375625944Sjoerg lcp.Up(sp); 375725944Sjoerg } 37584910Swollman } 375925944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 376025944Sjoerg ++sp->pp_alivecnt; 376145152Sphk if (sp->pp_mode == IFF_CISCO) 376225944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 376325944Sjoerg sp->pp_rseq); 376425944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 376525944Sjoerg long nmagic = htonl (sp->lcp.magic); 376625944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 376725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 376825944Sjoerg sp->lcp.echoid, 4, &nmagic); 376925944Sjoerg } 37704910Swollman } 377125944Sjoerg splx(s); 377242064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 37734910Swollman} 37744910Swollman 377525944Sjoerg/* 377625944Sjoerg * Get both IP addresses. 377725944Sjoerg */ 377825944Sjoergstatic void 377930300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 378025944Sjoerg{ 378125944Sjoerg struct ifnet *ifp = &sp->pp_if; 378225944Sjoerg struct ifaddr *ifa; 378330300Sjoerg struct sockaddr_in *si, *sm; 378425944Sjoerg u_long ssrc, ddst; 378525944Sjoerg 378640010Sjoerg sm = NULL; 378725944Sjoerg ssrc = ddst = 0L; 378825944Sjoerg /* 378925944Sjoerg * Pick the first AF_INET address from the list, 379025944Sjoerg * aliases don't make any sense on a p2p link anyway. 379125944Sjoerg */ 379242065Sphk si = 0; 379342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 379442065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 379542104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 379642065Sphk for (ifa = ifp->if_addrlist.tqh_first; 379740008Sjoerg ifa; 379840008Sjoerg ifa = ifa->ifa_list.tqe_next) 379942104Sphk#else 380042104Sphk for (ifa = ifp->if_addrlist; 380142104Sphk ifa; 380242104Sphk ifa = ifa->ifa_next) 380340008Sjoerg#endif 380425944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 380525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 380630300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 380725944Sjoerg if (si) 380825944Sjoerg break; 380925944Sjoerg } 381025944Sjoerg if (ifa) { 381130300Sjoerg if (si && si->sin_addr.s_addr) { 381225944Sjoerg ssrc = si->sin_addr.s_addr; 381330300Sjoerg if (srcmask) 381430300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 381530300Sjoerg } 381625944Sjoerg 381725944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 381825944Sjoerg if (si && si->sin_addr.s_addr) 381925944Sjoerg ddst = si->sin_addr.s_addr; 382025944Sjoerg } 382125944Sjoerg 382225944Sjoerg if (dst) *dst = ntohl(ddst); 382325944Sjoerg if (src) *src = ntohl(ssrc); 382425944Sjoerg} 382525944Sjoerg 382625944Sjoerg/* 382725944Sjoerg * Set my IP address. Must be called at splimp. 382825944Sjoerg */ 382925944Sjoergstatic void 383025944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 383125944Sjoerg{ 383242104Sphk STDDCL; 383325944Sjoerg struct ifaddr *ifa; 383425944Sjoerg struct sockaddr_in *si; 383525944Sjoerg 383625944Sjoerg /* 383725944Sjoerg * Pick the first AF_INET address from the list, 383825944Sjoerg * aliases don't make any sense on a p2p link anyway. 383925944Sjoerg */ 384042065Sphk si = 0; 384142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 384242065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 384342104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 384442065Sphk for (ifa = ifp->if_addrlist.tqh_first; 384540008Sjoerg ifa; 384640008Sjoerg ifa = ifa->ifa_list.tqe_next) 384742104Sphk#else 384842104Sphk for (ifa = ifp->if_addrlist; 384942104Sphk ifa; 385042104Sphk ifa = ifa->ifa_next) 385140008Sjoerg#endif 385240008Sjoerg { 385340008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 385440008Sjoerg { 385525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 385625944Sjoerg if (si) 385725944Sjoerg break; 385825944Sjoerg } 385940008Sjoerg } 386040008Sjoerg 386125944Sjoerg if (ifa && si) 386242104Sphk { 386342104Sphk int error; 386442104Sphk#if __NetBSD_Version__ >= 103080000 386542104Sphk struct sockaddr_in new_sin = *si; 386642104Sphk 386742104Sphk new_sin.sin_addr.s_addr = htonl(src); 386842104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 386942104Sphk if(debug && error) 387042104Sphk { 387142104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 387242104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 387342104Sphk } 387442104Sphk#else 387542104Sphk /* delete old route */ 387642104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 387742104Sphk if(debug && error) 387842104Sphk { 387942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 388042104Sphk SPP_ARGS(ifp), error); 388142104Sphk } 388242104Sphk 388342104Sphk /* set new address */ 388425944Sjoerg si->sin_addr.s_addr = htonl(src); 388525944Sjoerg 388642104Sphk /* add new route */ 388742104Sphk error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 388842104Sphk if (debug && error) 388942104Sphk { 389042104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 389142104Sphk SPP_ARGS(ifp), error); 389242104Sphk } 389342104Sphk#endif 389442104Sphk } 389542104Sphk} 389642104Sphk 389730300Sjoergstatic int 389838343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 389930300Sjoerg{ 390038343Sbde u_long subcmd; 390130300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 390230300Sjoerg struct spppreq spr; 390330300Sjoerg 390430300Sjoerg /* 390530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 390630300Sjoerg * Check the cmd word first before attempting to fetch all the 390730300Sjoerg * data. 390830300Sjoerg */ 390930300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 391030300Sjoerg return EFAULT; 391130300Sjoerg 391230300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 391330300Sjoerg return EFAULT; 391430300Sjoerg 391530300Sjoerg switch (subcmd) { 391630300Sjoerg case SPPPIOGDEFS: 391730300Sjoerg if (cmd != SIOCGIFGENERIC) 391830300Sjoerg return EINVAL; 391930300Sjoerg /* 392030300Sjoerg * We copy over the entire current state, but clean 392130300Sjoerg * out some of the stuff we don't wanna pass up. 392230300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 392330300Sjoerg * called by any user. No need to ever get PAP or 392430300Sjoerg * CHAP secrets back to userland anyway. 392530300Sjoerg */ 392630300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 392730300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 392830300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 392930300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 393030300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 393130300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 393230300Sjoerg 393330300Sjoerg case SPPPIOSDEFS: 393430300Sjoerg if (cmd != SIOCSIFGENERIC) 393530300Sjoerg return EINVAL; 393630300Sjoerg /* 393730300Sjoerg * We have a very specific idea of which fields we allow 393830300Sjoerg * being passed back from userland, so to not clobber our 393930300Sjoerg * current state. For one, we only allow setting 394030300Sjoerg * anything if LCP is in dead phase. Once the LCP 394130300Sjoerg * negotiations started, the authentication settings must 394230300Sjoerg * not be changed again. (The administrator can force an 394330300Sjoerg * ifconfig down in order to get LCP back into dead 394430300Sjoerg * phase.) 394530300Sjoerg * 394630300Sjoerg * Also, we only allow for authentication parameters to be 394730300Sjoerg * specified. 394830300Sjoerg * 394930300Sjoerg * XXX Should allow to set or clear pp_flags. 395030300Sjoerg * 395130300Sjoerg * Finally, if the respective authentication protocol to 395230300Sjoerg * be used is set differently than 0, but the secret is 395330300Sjoerg * passed as all zeros, we don't trash the existing secret. 395430300Sjoerg * This allows an administrator to change the system name 395530300Sjoerg * only without clobbering the secret (which he didn't get 395630300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 395730300Sjoerg * secrets are cleared if the authentication protocol is 395830300Sjoerg * reset to 0. 395930300Sjoerg */ 396030300Sjoerg if (sp->pp_phase != PHASE_DEAD) 396130300Sjoerg return EBUSY; 396230300Sjoerg 396330300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 396430300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 396530300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 396630300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 396730300Sjoerg return EINVAL; 396830300Sjoerg 396930300Sjoerg if (spr.defs.myauth.proto == 0) 397030300Sjoerg /* resetting myauth */ 397130300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 397230300Sjoerg else { 397330300Sjoerg /* setting/changing myauth */ 397430300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 397530300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 397630300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 397730300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 397830300Sjoerg AUTHKEYLEN); 397930300Sjoerg } 398030300Sjoerg if (spr.defs.hisauth.proto == 0) 398130300Sjoerg /* resetting hisauth */ 398230300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 398330300Sjoerg else { 398430300Sjoerg /* setting/changing hisauth */ 398530300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 398630300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 398730300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 398830300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 398930300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 399030300Sjoerg AUTHKEYLEN); 399130300Sjoerg } 399230300Sjoerg break; 399330300Sjoerg 399430300Sjoerg default: 399530300Sjoerg return EINVAL; 399630300Sjoerg } 399730300Sjoerg 399830300Sjoerg return 0; 399930300Sjoerg} 400030300Sjoerg 400130300Sjoergstatic void 400230300Sjoergsppp_phase_network(struct sppp *sp) 400330300Sjoerg{ 400442066Sphk STDDCL; 400530300Sjoerg int i; 400630300Sjoerg u_long mask; 400730300Sjoerg 400830300Sjoerg sp->pp_phase = PHASE_NETWORK; 400930300Sjoerg 401042066Sphk if (debug) 401142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 401242066Sphk sppp_phase_name(sp->pp_phase)); 401330300Sjoerg 401430300Sjoerg /* Notify NCPs now. */ 401530300Sjoerg for (i = 0; i < IDX_COUNT; i++) 401630300Sjoerg if ((cps[i])->flags & CP_NCP) 401730300Sjoerg (cps[i])->Open(sp); 401830300Sjoerg 401930300Sjoerg /* Send Up events to all NCPs. */ 402030300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 402130300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 402230300Sjoerg (cps[i])->Up(sp); 402330300Sjoerg 402430300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 402530300Sjoerg sppp_lcp_check_and_close(sp); 402630300Sjoerg} 402730300Sjoerg 402830300Sjoerg 402925706Sjoergstatic const char * 403025944Sjoergsppp_cp_type_name(u_char type) 40314910Swollman{ 403230300Sjoerg static char buf[12]; 40334910Swollman switch (type) { 403430300Sjoerg case CONF_REQ: return "conf-req"; 403530300Sjoerg case CONF_ACK: return "conf-ack"; 403630300Sjoerg case CONF_NAK: return "conf-nak"; 403730300Sjoerg case CONF_REJ: return "conf-rej"; 403830300Sjoerg case TERM_REQ: return "term-req"; 403930300Sjoerg case TERM_ACK: return "term-ack"; 404030300Sjoerg case CODE_REJ: return "code-rej"; 404130300Sjoerg case PROTO_REJ: return "proto-rej"; 404230300Sjoerg case ECHO_REQ: return "echo-req"; 404330300Sjoerg case ECHO_REPLY: return "echo-reply"; 404430300Sjoerg case DISC_REQ: return "discard-req"; 40454910Swollman } 404644145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 404730300Sjoerg return buf; 40484910Swollman} 40494910Swollman 405025706Sjoergstatic const char * 405130300Sjoergsppp_auth_type_name(u_short proto, u_char type) 405230300Sjoerg{ 405330300Sjoerg static char buf[12]; 405430300Sjoerg switch (proto) { 405530300Sjoerg case PPP_CHAP: 405630300Sjoerg switch (type) { 405730300Sjoerg case CHAP_CHALLENGE: return "challenge"; 405830300Sjoerg case CHAP_RESPONSE: return "response"; 405930300Sjoerg case CHAP_SUCCESS: return "success"; 406030300Sjoerg case CHAP_FAILURE: return "failure"; 406130300Sjoerg } 406230300Sjoerg case PPP_PAP: 406330300Sjoerg switch (type) { 406430300Sjoerg case PAP_REQ: return "req"; 406530300Sjoerg case PAP_ACK: return "ack"; 406630300Sjoerg case PAP_NAK: return "nak"; 406730300Sjoerg } 406830300Sjoerg } 406944145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 407030300Sjoerg return buf; 407130300Sjoerg} 407230300Sjoerg 407330300Sjoergstatic const char * 407425944Sjoergsppp_lcp_opt_name(u_char opt) 40754910Swollman{ 407630300Sjoerg static char buf[12]; 407725944Sjoerg switch (opt) { 407830300Sjoerg case LCP_OPT_MRU: return "mru"; 407930300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 408030300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 408130300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 408230300Sjoerg case LCP_OPT_MAGIC: return "magic"; 408330300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 408430300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 40854910Swollman } 408644145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 408730300Sjoerg return buf; 40884910Swollman} 40894910Swollman 409025944Sjoergstatic const char * 409125944Sjoergsppp_ipcp_opt_name(u_char opt) 409225944Sjoerg{ 409330300Sjoerg static char buf[12]; 409425944Sjoerg switch (opt) { 409530300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 409630300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 409730300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 409825944Sjoerg } 409944145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 410030300Sjoerg return buf; 410125944Sjoerg} 410225944Sjoerg 410325944Sjoergstatic const char * 410425944Sjoergsppp_state_name(int state) 410525944Sjoerg{ 410625944Sjoerg switch (state) { 410725944Sjoerg case STATE_INITIAL: return "initial"; 410825944Sjoerg case STATE_STARTING: return "starting"; 410925944Sjoerg case STATE_CLOSED: return "closed"; 411025944Sjoerg case STATE_STOPPED: return "stopped"; 411125944Sjoerg case STATE_CLOSING: return "closing"; 411225944Sjoerg case STATE_STOPPING: return "stopping"; 411325944Sjoerg case STATE_REQ_SENT: return "req-sent"; 411425944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 411525944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 411625944Sjoerg case STATE_OPENED: return "opened"; 411725944Sjoerg } 411825944Sjoerg return "illegal"; 411925944Sjoerg} 412025944Sjoerg 412125944Sjoergstatic const char * 412225944Sjoergsppp_phase_name(enum ppp_phase phase) 412325944Sjoerg{ 412425944Sjoerg switch (phase) { 412525944Sjoerg case PHASE_DEAD: return "dead"; 412625944Sjoerg case PHASE_ESTABLISH: return "establish"; 412725944Sjoerg case PHASE_TERMINATE: return "terminate"; 412825944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 412925944Sjoerg case PHASE_NETWORK: return "network"; 413025944Sjoerg } 413125944Sjoerg return "illegal"; 413225944Sjoerg} 413325944Sjoerg 413425944Sjoergstatic const char * 413525944Sjoergsppp_proto_name(u_short proto) 413625944Sjoerg{ 413725944Sjoerg static char buf[12]; 413825944Sjoerg switch (proto) { 413925944Sjoerg case PPP_LCP: return "lcp"; 414025944Sjoerg case PPP_IPCP: return "ipcp"; 414130300Sjoerg case PPP_PAP: return "pap"; 414230300Sjoerg case PPP_CHAP: return "chap"; 414325944Sjoerg } 414444145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 414525944Sjoerg return buf; 414625944Sjoerg} 414725944Sjoerg 414812820Sphkstatic void 414930300Sjoergsppp_print_bytes(const u_char *p, u_short len) 41504910Swollman{ 415144145Sphk if (len) 415244145Sphk addlog(" %*D", len, p, "-"); 41534910Swollman} 415425944Sjoerg 415530300Sjoergstatic void 415630300Sjoergsppp_print_string(const char *p, u_short len) 415730300Sjoerg{ 415830300Sjoerg u_char c; 415930300Sjoerg 416030300Sjoerg while (len-- > 0) { 416130300Sjoerg c = *p++; 416230300Sjoerg /* 416330300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 416430300Sjoerg * using only them, but we don't rely on it. */ 416530300Sjoerg if (c < ' ' || c > '~') 416630300Sjoerg addlog("\\x%x", c); 416730300Sjoerg else 416830300Sjoerg addlog("%c", c); 416930300Sjoerg } 417030300Sjoerg} 417130300Sjoerg 417230300Sjoergstatic const char * 417330300Sjoergsppp_dotted_quad(u_long addr) 417430300Sjoerg{ 417530300Sjoerg static char s[16]; 417630300Sjoerg sprintf(s, "%d.%d.%d.%d", 417740008Sjoerg (int)((addr >> 24) & 0xff), 417840008Sjoerg (int)((addr >> 16) & 0xff), 417940008Sjoerg (int)((addr >> 8) & 0xff), 418038372Sbde (int)(addr & 0xff)); 418130300Sjoerg return s; 418230300Sjoerg} 418330300Sjoerg 418430300Sjoergstatic int 418530300Sjoergsppp_strnlen(u_char *p, int max) 418630300Sjoerg{ 418730300Sjoerg int len; 418830300Sjoerg 418930300Sjoerg for (len = 0; len < max && *p; ++p) 419030300Sjoerg ++len; 419130300Sjoerg return len; 419230300Sjoerg} 419330300Sjoerg 419430300Sjoerg/* a dummy, used to drop uninteresting events */ 419530300Sjoergstatic void 419630300Sjoergsppp_null(struct sppp *unused) 419730300Sjoerg{ 419830300Sjoerg /* do just nothing */ 419930300Sjoerg} 4200