if_spppsubr.c revision 52633
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 52633 1999-10-29 17:57:42Z joerg $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2731742Seivind#include "opt_ipx.h" 2840008Sjoerg#endif 2931742Seivind 3040008Sjoerg#ifdef NetBSD1_3 3140008Sjoerg# if NetBSD1_3 > 6 3240008Sjoerg# include "opt_inet.h" 3340008Sjoerg# include "opt_iso.h" 3440008Sjoerg# endif 3540008Sjoerg#endif 3640008Sjoerg 374952Sbde#include <sys/systm.h> 384952Sbde#include <sys/kernel.h> 3924204Sbde#include <sys/sockio.h> 404910Swollman#include <sys/socket.h> 4125706Sjoerg#include <sys/syslog.h> 4242104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4342104Sphk#include <machine/random.h> 4442104Sphk#endif 4529024Sbde#include <sys/malloc.h> 464910Swollman#include <sys/mbuf.h> 4740008Sjoerg 4840008Sjoerg#if defined (__OpenBSD__) 4940008Sjoerg#include <sys/md5k.h> 5040008Sjoerg#else 5130300Sjoerg#include <sys/md5.h> 5240008Sjoerg#endif 534910Swollman 544910Swollman#include <net/if.h> 554910Swollman#include <net/netisr.h> 564910Swollman#include <net/if_types.h> 5742104Sphk#include <net/route.h> 584910Swollman 5942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 6040008Sjoerg#include <machine/random.h> 6140008Sjoerg#endif 6240008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6340008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6440008Sjoerg#endif 6542104Sphk 6630300Sjoerg#include <machine/stdarg.h> 6730300Sjoerg 684910Swollman#ifdef INET 694910Swollman#include <netinet/in.h> 704910Swollman#include <netinet/in_systm.h> 714910Swollman#include <netinet/in_var.h> 724910Swollman#include <netinet/ip.h> 734910Swollman#include <netinet/tcp.h> 7440008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7540008Sjoerg# include <netinet/if_ether.h> 7640008Sjoerg# else 7740008Sjoerg# include <net/ethertypes.h> 7840008Sjoerg# endif 7932350Seivind#else 8040008Sjoerg# error Huh? sppp without INET? 814910Swollman#endif 824910Swollman 8311819Sjulian#ifdef IPX 8411819Sjulian#include <netipx/ipx.h> 8511819Sjulian#include <netipx/ipx_if.h> 8611819Sjulian#endif 8711819Sjulian 884910Swollman#ifdef NS 894910Swollman#include <netns/ns.h> 904910Swollman#include <netns/ns_if.h> 914910Swollman#endif 924910Swollman 934910Swollman#ifdef ISO 944910Swollman#include <netiso/argo_debug.h> 954910Swollman#include <netiso/iso.h> 964910Swollman#include <netiso/iso_var.h> 974910Swollman#include <netiso/iso_snpac.h> 984910Swollman#endif 994910Swollman 1004910Swollman#include <net/if_sppp.h> 1014910Swollman 10242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 10342064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 10442064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 10542104Sphk# define IOCTL_CMD_T u_long 10640008Sjoerg#else 10742064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10842064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10942104Sphk# define IOCTL_CMD_T int 11040008Sjoerg#endif 11142104Sphk 1124910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1134910Swollman 11425944Sjoerg/* 11525944Sjoerg * Interface flags that can be set in an ifconfig command. 11625944Sjoerg * 11725955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11825944Sjoerg * as being administrative openable, but won't be opened to begin 11925944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 12025944Sjoerg * -link1 will cause the administrative open of the LCP layer. 12125955Sjoerg * 12225955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 12325955Sjoerg * arrive to be sent. 12430300Sjoerg * 12530300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 12630300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12730300Sjoerg * like 12830300Sjoerg * 12930300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 13030300Sjoerg * 13130300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 13230300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 13325944Sjoerg */ 13425944Sjoerg 13525955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 13625955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13745152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13825944Sjoerg 13930300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 14030300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 14130300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 14230300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 14330300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 14430300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 14530300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14630300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14730300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14830300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1494910Swollman 15025944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 15125944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 15225944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 15325944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 15425944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 15525944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 15625944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15725944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15825944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15925944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 16025944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1614910Swollman 16230300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 16330300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 16430300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 16530300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 16630300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16730300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16830300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16930300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1704910Swollman 17125944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 17225944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 17325944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1744910Swollman 17530300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 17630300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17730300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1784910Swollman 17930300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 18030300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 18130300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18230300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18330300Sjoerg 18430300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18530300Sjoerg 18630300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18730300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18830300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18930300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 19030300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 19130300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19230300Sjoerg 19325944Sjoerg/* states are named and numbered according to RFC 1661 */ 19425944Sjoerg#define STATE_INITIAL 0 19525944Sjoerg#define STATE_STARTING 1 19625944Sjoerg#define STATE_CLOSED 2 19725944Sjoerg#define STATE_STOPPED 3 19825944Sjoerg#define STATE_CLOSING 4 19925944Sjoerg#define STATE_STOPPING 5 20025944Sjoerg#define STATE_REQ_SENT 6 20125944Sjoerg#define STATE_ACK_RCVD 7 20225944Sjoerg#define STATE_ACK_SENT 8 20325944Sjoerg#define STATE_OPENED 9 20425944Sjoerg 2054910Swollmanstruct ppp_header { 20611189Sjkh u_char address; 20711189Sjkh u_char control; 20811189Sjkh u_short protocol; 2094910Swollman}; 2104910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2114910Swollman 2124910Swollmanstruct lcp_header { 21311189Sjkh u_char type; 21411189Sjkh u_char ident; 21511189Sjkh u_short len; 2164910Swollman}; 2174910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2184910Swollman 2194910Swollmanstruct cisco_packet { 22011189Sjkh u_long type; 22111189Sjkh u_long par1; 22211189Sjkh u_long par2; 22311189Sjkh u_short rel; 22411189Sjkh u_short time0; 22511189Sjkh u_short time1; 2264910Swollman}; 2274910Swollman#define CISCO_PACKET_LEN 18 2284910Swollman 22925944Sjoerg/* 23025944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 23125944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23225944Sjoerg * case you can't make sense out of these abbreviation; it will also 23325944Sjoerg * explain the semantics related to the various events and actions. 23425944Sjoerg */ 23525944Sjoergstruct cp { 23625944Sjoerg u_short proto; /* PPP control protocol number */ 23725944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23825944Sjoerg u_char flags; 23925944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 24025944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 24125944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24225944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24325944Sjoerg const char *name; /* name of this control protocol */ 24425944Sjoerg /* event handlers */ 24525944Sjoerg void (*Up)(struct sppp *sp); 24625944Sjoerg void (*Down)(struct sppp *sp); 24725944Sjoerg void (*Open)(struct sppp *sp); 24825944Sjoerg void (*Close)(struct sppp *sp); 24925944Sjoerg void (*TO)(void *sp); 25025944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 25125944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25225944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25325944Sjoerg /* actions */ 25425944Sjoerg void (*tlu)(struct sppp *sp); 25525944Sjoerg void (*tld)(struct sppp *sp); 25625944Sjoerg void (*tls)(struct sppp *sp); 25725944Sjoerg void (*tlf)(struct sppp *sp); 25825944Sjoerg void (*scr)(struct sppp *sp); 25925944Sjoerg}; 26025944Sjoerg 26112820Sphkstatic struct sppp *spppq; 26242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26330300Sjoergstatic struct callout_handle keepalive_ch; 26440008Sjoerg#endif 2654910Swollman 26642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26740008Sjoerg#define SPP_FMT "%s%d: " 26840008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26940008Sjoerg#else 27040008Sjoerg#define SPP_FMT "%s: " 27140008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27240008Sjoerg#endif 27340008Sjoerg 2744910Swollman/* 2754910Swollman * The following disgusting hack gets around the problem that IP TOS 2764910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2774910Swollman * priority queue. To decide if traffic is interactive, we check that 2784910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27930300Sjoerg * 28030300Sjoerg * XXX is this really still necessary? - joerg - 2814910Swollman */ 28211189Sjkhstatic u_short interactive_ports[8] = { 2834910Swollman 0, 513, 0, 0, 2844910Swollman 0, 21, 0, 23, 2854910Swollman}; 2864910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2874910Swollman 28825944Sjoerg/* almost every function needs these */ 28925944Sjoerg#define STDDCL \ 29025944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 29125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29211189Sjkh 29330300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 29425944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2954910Swollman 29625944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 29725944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29825944Sjoerg 29925944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 30025944Sjoerg struct mbuf *m); 30125944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30225944Sjoerg u_char ident, u_short len, void *data); 30342104Sphk/* static void sppp_cp_timeout(void *arg); */ 30425944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 30525944Sjoerg int newstate); 30630300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30742104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30830300Sjoerg ...); 30925944Sjoerg 31025944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 31125944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31225944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31325944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 31425944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 31525944Sjoerg 31630300Sjoergstatic void sppp_null(struct sppp *sp); 31730300Sjoerg 31825944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31925944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32225944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32325944Sjoergstatic void sppp_lcp_TO(void *sp); 32425944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32525944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 32625944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32725944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 33025944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 33125944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33230300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33330300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 33425944Sjoerg 33525944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 33625944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33925944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 34025944Sjoergstatic void sppp_ipcp_TO(void *sp); 34125944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34225944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34325944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34425944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34725944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34825944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34925944Sjoerg 35030300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 35130300Sjoergstatic void sppp_pap_init(struct sppp *sp); 35230300Sjoergstatic void sppp_pap_open(struct sppp *sp); 35330300Sjoergstatic void sppp_pap_close(struct sppp *sp); 35430300Sjoergstatic void sppp_pap_TO(void *sp); 35530300Sjoergstatic void sppp_pap_my_TO(void *sp); 35630300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 35730300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 35830300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 35930300Sjoerg 36030300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 36130300Sjoergstatic void sppp_chap_init(struct sppp *sp); 36230300Sjoergstatic void sppp_chap_open(struct sppp *sp); 36330300Sjoergstatic void sppp_chap_close(struct sppp *sp); 36430300Sjoergstatic void sppp_chap_TO(void *sp); 36530300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 36630300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 36730300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 36830300Sjoerg 36930300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 37025944Sjoergstatic const char *sppp_cp_type_name(u_char type); 37130300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 37230300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 37325944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 37425944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 37525944Sjoergstatic const char *sppp_proto_name(u_short proto); 37630300Sjoergstatic const char *sppp_state_name(int state); 37738343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37830300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37930300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 38030300Sjoerg u_long *srcmask); 38125944Sjoergstatic void sppp_keepalive(void *dummy); 38230300Sjoergstatic void sppp_phase_network(struct sppp *sp); 38330300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 38430300Sjoergstatic void sppp_print_string(const char *p, u_short len); 38525944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 38625944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 38725944Sjoerg 38825944Sjoerg/* our control protocol descriptors */ 38933181Seivindstatic const struct cp lcp = { 39025944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 39125944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 39225944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 39325944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 39425944Sjoerg sppp_lcp_scr 39525944Sjoerg}; 39625944Sjoerg 39733181Seivindstatic const struct cp ipcp = { 39825944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 39925944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 40025944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 40125944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 40225944Sjoerg sppp_ipcp_scr 40325944Sjoerg}; 40425944Sjoerg 40533181Seivindstatic const struct cp pap = { 40630300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 40730300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 40830300Sjoerg sppp_pap_TO, 0, 0, 0, 40930300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 41030300Sjoerg sppp_pap_scr 41130300Sjoerg}; 41230300Sjoerg 41333181Seivindstatic const struct cp chap = { 41430300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 41530300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 41630300Sjoerg sppp_chap_TO, 0, 0, 0, 41730300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 41830300Sjoerg sppp_chap_scr 41930300Sjoerg}; 42030300Sjoerg 42133181Seivindstatic const struct cp *cps[IDX_COUNT] = { 42225944Sjoerg &lcp, /* IDX_LCP */ 42325944Sjoerg &ipcp, /* IDX_IPCP */ 42430300Sjoerg &pap, /* IDX_PAP */ 42530300Sjoerg &chap, /* IDX_CHAP */ 42625944Sjoerg}; 42725944Sjoerg 42825944Sjoerg 42925944Sjoerg/* 43025944Sjoerg * Exported functions, comprising our interface to the lower layer. 4314910Swollman */ 4324910Swollman 4334910Swollman/* 4344910Swollman * Process the received packet. 4354910Swollman */ 43625706Sjoergvoid 43725706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4384910Swollman{ 4394910Swollman struct ppp_header *h; 4404910Swollman struct ifqueue *inq = 0; 44111189Sjkh int s; 44225944Sjoerg struct sppp *sp = (struct sppp *)ifp; 44325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 4444910Swollman 4454910Swollman if (ifp->if_flags & IFF_UP) 4464910Swollman /* Count received bytes, add FCS and one flag */ 4474910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 4484910Swollman 4494910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 4504910Swollman /* Too small packet, drop it. */ 45125944Sjoerg if (debug) 45225706Sjoerg log(LOG_DEBUG, 45340008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 45440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 45525944Sjoerg drop: 45625944Sjoerg ++ifp->if_ierrors; 45725944Sjoerg ++ifp->if_iqdrops; 4584910Swollman m_freem (m); 4594910Swollman return; 4604910Swollman } 4614910Swollman 4624910Swollman /* Get PPP header. */ 4634910Swollman h = mtod (m, struct ppp_header*); 4644910Swollman m_adj (m, PPP_HEADER_LEN); 4654910Swollman 4664910Swollman switch (h->address) { 4674910Swollman case PPP_ALLSTATIONS: 4684910Swollman if (h->control != PPP_UI) 4694910Swollman goto invalid; 47045152Sphk if (sp->pp_mode == IFF_CISCO) { 47125944Sjoerg if (debug) 47225706Sjoerg log(LOG_DEBUG, 47340008Sjoerg SPP_FMT "PPP packet in Cisco mode " 47425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 47540008Sjoerg SPP_ARGS(ifp), 47625706Sjoerg h->address, h->control, ntohs(h->protocol)); 47711189Sjkh goto drop; 47811189Sjkh } 4794910Swollman switch (ntohs (h->protocol)) { 4804910Swollman default: 48125944Sjoerg if (debug) 48225706Sjoerg log(LOG_DEBUG, 48344145Sphk SPP_FMT "rejecting protocol " 48425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 48540008Sjoerg SPP_ARGS(ifp), 48625706Sjoerg h->address, h->control, ntohs(h->protocol)); 48744145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 48844145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 48944145Sphk ++sp->pp_seq, m->m_pkthdr.len + 2, 49044145Sphk &h->protocol); 4914910Swollman ++ifp->if_noproto; 4924910Swollman goto drop; 4934910Swollman case PPP_LCP: 49430300Sjoerg sppp_cp_input(&lcp, sp, m); 4954910Swollman m_freem (m); 4964910Swollman return; 49730300Sjoerg case PPP_PAP: 49830300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49930300Sjoerg sppp_pap_input(sp, m); 50030300Sjoerg m_freem (m); 50130300Sjoerg return; 50230300Sjoerg case PPP_CHAP: 50330300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 50430300Sjoerg sppp_chap_input(sp, m); 50530300Sjoerg m_freem (m); 50630300Sjoerg return; 5074910Swollman#ifdef INET 5084910Swollman case PPP_IPCP: 50925944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 51030300Sjoerg sppp_cp_input(&ipcp, sp, m); 5114910Swollman m_freem (m); 5124910Swollman return; 5134910Swollman case PPP_IP: 51425944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5154910Swollman schednetisr (NETISR_IP); 5164910Swollman inq = &ipintrq; 5174910Swollman } 5184910Swollman break; 5194910Swollman#endif 52012495Speter#ifdef IPX 52112495Speter case PPP_IPX: 52212495Speter /* IPX IPXCP not implemented yet */ 52325944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 52412495Speter schednetisr (NETISR_IPX); 52512495Speter inq = &ipxintrq; 52612495Speter } 52712495Speter break; 52812495Speter#endif 5294910Swollman#ifdef NS 5304910Swollman case PPP_XNS: 5314910Swollman /* XNS IDPCP not implemented yet */ 53225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5334910Swollman schednetisr (NETISR_NS); 5344910Swollman inq = &nsintrq; 5354910Swollman } 5364910Swollman break; 5374910Swollman#endif 5384910Swollman#ifdef ISO 5394910Swollman case PPP_ISO: 5404910Swollman /* OSI NLCP not implemented yet */ 54125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5424910Swollman schednetisr (NETISR_ISO); 5434910Swollman inq = &clnlintrq; 5444910Swollman } 5454910Swollman break; 5464910Swollman#endif 5474910Swollman } 5484910Swollman break; 5494910Swollman case CISCO_MULTICAST: 5504910Swollman case CISCO_UNICAST: 5514910Swollman /* Don't check the control field here (RFC 1547). */ 55245152Sphk if (sp->pp_mode != IFF_CISCO) { 55325944Sjoerg if (debug) 55425706Sjoerg log(LOG_DEBUG, 55540008Sjoerg SPP_FMT "Cisco packet in PPP mode " 55625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55740008Sjoerg SPP_ARGS(ifp), 55825706Sjoerg h->address, h->control, ntohs(h->protocol)); 55911189Sjkh goto drop; 56011189Sjkh } 5614910Swollman switch (ntohs (h->protocol)) { 5624910Swollman default: 5634910Swollman ++ifp->if_noproto; 5644910Swollman goto invalid; 5654910Swollman case CISCO_KEEPALIVE: 5664910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5674910Swollman m_freem (m); 5684910Swollman return; 5694910Swollman#ifdef INET 5704910Swollman case ETHERTYPE_IP: 5714910Swollman schednetisr (NETISR_IP); 5724910Swollman inq = &ipintrq; 5734910Swollman break; 5744910Swollman#endif 57512495Speter#ifdef IPX 57612495Speter case ETHERTYPE_IPX: 57712495Speter schednetisr (NETISR_IPX); 57812495Speter inq = &ipxintrq; 57912495Speter break; 58012495Speter#endif 5814910Swollman#ifdef NS 5824910Swollman case ETHERTYPE_NS: 5834910Swollman schednetisr (NETISR_NS); 5844910Swollman inq = &nsintrq; 5854910Swollman break; 5864910Swollman#endif 5874910Swollman } 5884910Swollman break; 58925944Sjoerg default: /* Invalid PPP packet. */ 59025944Sjoerg invalid: 59125944Sjoerg if (debug) 59225944Sjoerg log(LOG_DEBUG, 59340008Sjoerg SPP_FMT "invalid input packet " 59425944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 59540008Sjoerg SPP_ARGS(ifp), 59625944Sjoerg h->address, h->control, ntohs(h->protocol)); 59725944Sjoerg goto drop; 5984910Swollman } 5994910Swollman 6004910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 6014910Swollman goto drop; 6024910Swollman 6034910Swollman /* Check queue. */ 60425944Sjoerg s = splimp(); 6054910Swollman if (IF_QFULL (inq)) { 6064910Swollman /* Queue overflow. */ 60725944Sjoerg IF_DROP(inq); 60825944Sjoerg splx(s); 60925944Sjoerg if (debug) 61040008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 61140008Sjoerg SPP_ARGS(ifp)); 6124910Swollman goto drop; 6134910Swollman } 61425944Sjoerg IF_ENQUEUE(inq, m); 61525944Sjoerg splx(s); 6164910Swollman} 6174910Swollman 6184910Swollman/* 6194910Swollman * Enqueue transmit packet. 6204910Swollman */ 62112820Sphkstatic int 62225706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 62325706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6244910Swollman{ 6254910Swollman struct sppp *sp = (struct sppp*) ifp; 6264910Swollman struct ppp_header *h; 6274910Swollman struct ifqueue *ifq; 62825955Sjoerg int s, rv = 0; 62942066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6304910Swollman 63125944Sjoerg s = splimp(); 63225944Sjoerg 63325944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 63425944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 6354910Swollman m_freem (m); 6364910Swollman splx (s); 6374910Swollman return (ENETDOWN); 6384910Swollman } 6394910Swollman 64025944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 64125944Sjoerg /* 64225944Sjoerg * Interface is not yet running, but auto-dial. Need 64325944Sjoerg * to start LCP for it. 64425944Sjoerg */ 64525944Sjoerg ifp->if_flags |= IFF_RUNNING; 64625944Sjoerg splx(s); 64725944Sjoerg lcp.Open(sp); 64825944Sjoerg s = splimp(); 64925944Sjoerg } 65025944Sjoerg 6514910Swollman ifq = &ifp->if_snd; 6524910Swollman#ifdef INET 65312436Speter if (dst->sa_family == AF_INET) { 65440008Sjoerg /* XXX Check mbuf length here? */ 65512436Speter struct ip *ip = mtod (m, struct ip*); 65612436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6574910Swollman 65842104Sphk /* 65942104Sphk * When using dynamic local IP address assignment by using 66042104Sphk * 0.0.0.0 as a local address, the first TCP session will 66142104Sphk * not connect because the local TCP checksum is computed 66242104Sphk * using 0.0.0.0 which will later become our real IP address 66342104Sphk * so the TCP checksum computed at the remote end will 66442104Sphk * become invalid. So we 66542104Sphk * - don't let packets with src ip addr 0 thru 66642104Sphk * - we flag TCP packets with src ip 0 as an error 66742104Sphk */ 66842104Sphk 66942104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 67042104Sphk { 67142104Sphk m_freem(m); 67242104Sphk splx(s); 67342104Sphk if(ip->ip_p == IPPROTO_TCP) 67442104Sphk return(EADDRNOTAVAIL); 67542104Sphk else 67642104Sphk return(0); 67742104Sphk } 67842104Sphk 67942104Sphk /* 68042104Sphk * Put low delay, telnet, rlogin and ftp control packets 68142104Sphk * in front of the queue. 68242104Sphk */ 68341686Sphk if (IF_QFULL (&sp->pp_fastq)) 68441686Sphk ; 68541686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 68612436Speter ifq = &sp->pp_fastq; 68741686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 68841686Sphk ; 68941686Sphk else if (ip->ip_p != IPPROTO_TCP) 69041686Sphk ; 69141686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 69241686Sphk ifq = &sp->pp_fastq; 69341686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 69441686Sphk ifq = &sp->pp_fastq; 6954910Swollman } 6964910Swollman#endif 6974910Swollman 6984910Swollman /* 6994910Swollman * Prepend general data packet PPP header. For now, IP only. 7004910Swollman */ 7014910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 7024910Swollman if (! m) { 70342066Sphk if (debug) 70440008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 70540008Sjoerg SPP_ARGS(ifp)); 70625944Sjoerg ++ifp->if_oerrors; 7074910Swollman splx (s); 7084910Swollman return (ENOBUFS); 7094910Swollman } 71040008Sjoerg /* 71140008Sjoerg * May want to check size of packet 71240008Sjoerg * (albeit due to the implementation it's always enough) 71340008Sjoerg */ 7144910Swollman h = mtod (m, struct ppp_header*); 71545152Sphk if (sp->pp_mode == IFF_CISCO) { 71628088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7174910Swollman h->control = 0; 7184910Swollman } else { 7194910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7204910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7214910Swollman } 7224910Swollman 7234910Swollman switch (dst->sa_family) { 7244910Swollman#ifdef INET 7254910Swollman case AF_INET: /* Internet Protocol */ 72645152Sphk if (sp->pp_mode == IFF_CISCO) 72711189Sjkh h->protocol = htons (ETHERTYPE_IP); 72811189Sjkh else { 72925955Sjoerg /* 73025955Sjoerg * Don't choke with an ENETDOWN early. It's 73125955Sjoerg * possible that we just started dialing out, 73225955Sjoerg * so don't drop the packet immediately. If 73325955Sjoerg * we notice that we run out of buffer space 73425955Sjoerg * below, we will however remember that we are 73525955Sjoerg * not ready to carry IP packets, and return 73625955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 73725955Sjoerg */ 73825955Sjoerg h->protocol = htons(PPP_IP); 73925955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 74025955Sjoerg rv = ENETDOWN; 74111189Sjkh } 7424910Swollman break; 7434910Swollman#endif 7444910Swollman#ifdef NS 7454910Swollman case AF_NS: /* Xerox NS Protocol */ 74645152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 7474910Swollman ETHERTYPE_NS : PPP_XNS); 7484910Swollman break; 7494910Swollman#endif 75011819Sjulian#ifdef IPX 75112495Speter case AF_IPX: /* Novell IPX Protocol */ 75245152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 75312495Speter ETHERTYPE_IPX : PPP_IPX); 75411819Sjulian break; 75511819Sjulian#endif 7564910Swollman#ifdef ISO 7574910Swollman case AF_ISO: /* ISO OSI Protocol */ 75845152Sphk if (sp->pp_mode == IFF_CISCO) 7594910Swollman goto nosupport; 7604910Swollman h->protocol = htons (PPP_ISO); 7614910Swollman break; 76212820Sphknosupport: 7634910Swollman#endif 7644910Swollman default: 7654910Swollman m_freem (m); 76625944Sjoerg ++ifp->if_oerrors; 7674910Swollman splx (s); 7684910Swollman return (EAFNOSUPPORT); 7694910Swollman } 7704910Swollman 7714910Swollman /* 7724910Swollman * Queue message on interface, and start output if interface 7734910Swollman * not yet active. 7744910Swollman */ 7754910Swollman if (IF_QFULL (ifq)) { 7764910Swollman IF_DROP (&ifp->if_snd); 7774910Swollman m_freem (m); 77825944Sjoerg ++ifp->if_oerrors; 7794910Swollman splx (s); 78025955Sjoerg return (rv? rv: ENOBUFS); 7814910Swollman } 7824910Swollman IF_ENQUEUE (ifq, m); 7834910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 7844910Swollman (*ifp->if_start) (ifp); 7854910Swollman 7864910Swollman /* 7874910Swollman * Count output packets and bytes. 7884910Swollman * The packet length includes header, FCS and 1 flag, 7894910Swollman * according to RFC 1333. 7904910Swollman */ 7914910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 7924910Swollman splx (s); 7934910Swollman return (0); 7944910Swollman} 7954910Swollman 79625706Sjoergvoid 79725706Sjoergsppp_attach(struct ifnet *ifp) 7984910Swollman{ 7994910Swollman struct sppp *sp = (struct sppp*) ifp; 8004910Swollman 8014910Swollman /* Initialize keepalive handler. */ 8024910Swollman if (! spppq) 80342064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 8044910Swollman 8054910Swollman /* Insert new entry into the keepalive list. */ 8064910Swollman sp->pp_next = spppq; 8074910Swollman spppq = sp; 8084910Swollman 80942064Sphk sp->pp_if.if_mtu = PP_MTU; 81042064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8114910Swollman sp->pp_if.if_type = IFT_PPP; 8124910Swollman sp->pp_if.if_output = sppp_output; 81342104Sphk#if 0 81442064Sphk sp->pp_flags = PP_KEEPALIVE; 81542104Sphk#endif 8164910Swollman sp->pp_fastq.ifq_maxlen = 32; 81726018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 8184910Swollman sp->pp_loopcnt = 0; 8194910Swollman sp->pp_alivecnt = 0; 82011189Sjkh sp->pp_seq = 0; 8214910Swollman sp->pp_rseq = 0; 82225944Sjoerg sp->pp_phase = PHASE_DEAD; 82325944Sjoerg sp->pp_up = lcp.Up; 82425944Sjoerg sp->pp_down = lcp.Down; 82525944Sjoerg 82625944Sjoerg sppp_lcp_init(sp); 82725944Sjoerg sppp_ipcp_init(sp); 82830300Sjoerg sppp_pap_init(sp); 82930300Sjoerg sppp_chap_init(sp); 8304910Swollman} 8314910Swollman 83230300Sjoergvoid 83325706Sjoergsppp_detach(struct ifnet *ifp) 8344910Swollman{ 8354910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 83625944Sjoerg int i; 8374910Swollman 8384910Swollman /* Remove the entry from the keepalive list. */ 8394910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 8404910Swollman if (p == sp) { 8414910Swollman *q = p->pp_next; 8424910Swollman break; 8434910Swollman } 8444910Swollman 8454910Swollman /* Stop keepalive handler. */ 8464910Swollman if (! spppq) 84740008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 84825944Sjoerg 84925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 85040008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 85140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 8524910Swollman} 8534910Swollman 8544910Swollman/* 8554910Swollman * Flush the interface output queue. 8564910Swollman */ 85725706Sjoergvoid 85825706Sjoergsppp_flush(struct ifnet *ifp) 8594910Swollman{ 8604910Swollman struct sppp *sp = (struct sppp*) ifp; 8614910Swollman 86225944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 86325944Sjoerg sppp_qflush (&sp->pp_fastq); 86426018Sjoerg sppp_qflush (&sp->pp_cpq); 8654910Swollman} 8664910Swollman 8674910Swollman/* 86811189Sjkh * Check if the output queue is empty. 86911189Sjkh */ 87012820Sphkint 87125706Sjoergsppp_isempty(struct ifnet *ifp) 87211189Sjkh{ 87311189Sjkh struct sppp *sp = (struct sppp*) ifp; 87425944Sjoerg int empty, s; 87511189Sjkh 87625944Sjoerg s = splimp(); 87726018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 87826018Sjoerg !sp->pp_if.if_snd.ifq_head; 87925944Sjoerg splx(s); 88011189Sjkh return (empty); 88111189Sjkh} 88211189Sjkh 88311189Sjkh/* 8844910Swollman * Get next packet to send. 8854910Swollman */ 88625706Sjoergstruct mbuf * 88725706Sjoergsppp_dequeue(struct ifnet *ifp) 8884910Swollman{ 8894910Swollman struct sppp *sp = (struct sppp*) ifp; 8904910Swollman struct mbuf *m; 89125944Sjoerg int s; 8924910Swollman 89325944Sjoerg s = splimp(); 89426018Sjoerg /* 89530300Sjoerg * Process only the control protocol queue until we have at 89630300Sjoerg * least one NCP open. 89726018Sjoerg * 89826018Sjoerg * Do always serve all three queues in Cisco mode. 89926018Sjoerg */ 90026018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 90126018Sjoerg if (m == NULL && 90245152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 90326018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 90426018Sjoerg if (m == NULL) 90526018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 90626018Sjoerg } 90726018Sjoerg splx(s); 90826018Sjoerg return m; 9094910Swollman} 9104910Swollman 9114910Swollman/* 91230300Sjoerg * Pick the next packet, do not remove it from the queue. 91330300Sjoerg */ 91430300Sjoergstruct mbuf * 91530300Sjoergsppp_pick(struct ifnet *ifp) 91630300Sjoerg{ 91730300Sjoerg struct sppp *sp = (struct sppp*)ifp; 91830300Sjoerg struct mbuf *m; 91930300Sjoerg int s; 92030300Sjoerg 92130300Sjoerg s= splimp (); 92230300Sjoerg 92330300Sjoerg m = sp->pp_cpq.ifq_head; 92430300Sjoerg if (m == NULL && 92545152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 92630300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 92730300Sjoerg m = sp->pp_if.if_snd.ifq_head; 92830300Sjoerg splx (s); 92930300Sjoerg return (m); 93030300Sjoerg} 93130300Sjoerg 93230300Sjoerg/* 93325944Sjoerg * Process an ioctl request. Called on low priority level. 9344910Swollman */ 93525944Sjoergint 93642104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 9374910Swollman{ 93825944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 93925944Sjoerg struct sppp *sp = (struct sppp*) ifp; 94030300Sjoerg int s, rv, going_up, going_down, newmode; 9414910Swollman 94225944Sjoerg s = splimp(); 94330300Sjoerg rv = 0; 94425944Sjoerg switch (cmd) { 94525944Sjoerg case SIOCAIFADDR: 94625944Sjoerg case SIOCSIFDSTADDR: 94725944Sjoerg break; 9484910Swollman 94925944Sjoerg case SIOCSIFADDR: 95025944Sjoerg if_up(ifp); 95125944Sjoerg /* fall through... */ 95211189Sjkh 95325944Sjoerg case SIOCSIFFLAGS: 95425944Sjoerg going_up = ifp->if_flags & IFF_UP && 95525944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 95625944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 95725944Sjoerg ifp->if_flags & IFF_RUNNING; 95845152Sphk 95945152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 96045152Sphk if (!newmode) 96145152Sphk newmode = ifp->if_flags & IFF_AUTO; 96245152Sphk if (!newmode) 96345152Sphk newmode = ifp->if_flags & IFF_CISCO; 96445152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 96545152Sphk ifp->if_flags |= newmode; 96645152Sphk 96745152Sphk if (newmode != sp->pp_mode) { 96845152Sphk going_down = 1; 96945152Sphk if (!going_up) 97045152Sphk going_up = ifp->if_flags & IFF_RUNNING; 9714910Swollman } 9724910Swollman 97345152Sphk if (going_down) { 97445152Sphk if (sp->pp_mode != IFF_CISCO) 97545152Sphk lcp.Close(sp); 97645152Sphk else if (sp->pp_tlf) 97745152Sphk (sp->pp_tlf)(sp); 97826018Sjoerg sppp_flush(ifp); 97925944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 98045152Sphk sp->pp_mode = newmode; 98126018Sjoerg } 9824910Swollman 98345152Sphk if (going_up) { 98445152Sphk if (sp->pp_mode != IFF_CISCO) 98545152Sphk lcp.Close(sp); 98645152Sphk sp->pp_mode = newmode; 98745152Sphk if (sp->pp_mode == 0) { 98845152Sphk ifp->if_flags |= IFF_RUNNING; 98945152Sphk lcp.Open(sp); 99045152Sphk } 99145152Sphk if (sp->pp_mode == IFF_CISCO) { 99245152Sphk if (sp->pp_tls) 99345152Sphk (sp->pp_tls)(sp); 99445152Sphk ifp->if_flags |= IFF_RUNNING; 99545152Sphk } 99645152Sphk } 99745152Sphk 9984910Swollman break; 99911189Sjkh 100025944Sjoerg#ifdef SIOCSIFMTU 100125944Sjoerg#ifndef ifr_mtu 100225944Sjoerg#define ifr_mtu ifr_metric 100325944Sjoerg#endif 100425944Sjoerg case SIOCSIFMTU: 100525944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 100625944Sjoerg return (EINVAL); 100725944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 10084910Swollman break; 100925944Sjoerg#endif 101025944Sjoerg#ifdef SLIOCSETMTU 101125944Sjoerg case SLIOCSETMTU: 101225944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 101325944Sjoerg return (EINVAL); 101425944Sjoerg ifp->if_mtu = *(short*)data; 10154910Swollman break; 101625944Sjoerg#endif 101725944Sjoerg#ifdef SIOCGIFMTU 101825944Sjoerg case SIOCGIFMTU: 101925944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 102011189Sjkh break; 102125944Sjoerg#endif 102225944Sjoerg#ifdef SLIOCGETMTU 102325944Sjoerg case SLIOCGETMTU: 102425944Sjoerg *(short*)data = ifp->if_mtu; 10254910Swollman break; 102625944Sjoerg#endif 102725944Sjoerg case SIOCADDMULTI: 102825944Sjoerg case SIOCDELMULTI: 10294910Swollman break; 103011189Sjkh 103130300Sjoerg case SIOCGIFGENERIC: 103230300Sjoerg case SIOCSIFGENERIC: 103330300Sjoerg rv = sppp_params(sp, cmd, data); 103430300Sjoerg break; 103530300Sjoerg 103625944Sjoerg default: 103730300Sjoerg rv = ENOTTY; 10384910Swollman } 103925944Sjoerg splx(s); 104030300Sjoerg return rv; 10414910Swollman} 10424910Swollman 104325944Sjoerg 104425944Sjoerg/* 104525944Sjoerg * Cisco framing implementation. 104625944Sjoerg */ 104725944Sjoerg 10484910Swollman/* 10494910Swollman * Handle incoming Cisco keepalive protocol packets. 10504910Swollman */ 105130300Sjoergstatic void 105225706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 10534910Swollman{ 105425944Sjoerg STDDCL; 10554910Swollman struct cisco_packet *h; 105630300Sjoerg u_long me, mymask; 10574910Swollman 105827929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 105925706Sjoerg if (debug) 106025706Sjoerg log(LOG_DEBUG, 106140008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 106240008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 10634910Swollman return; 10644910Swollman } 10654910Swollman h = mtod (m, struct cisco_packet*); 106625706Sjoerg if (debug) 106725706Sjoerg log(LOG_DEBUG, 106840008Sjoerg SPP_FMT "cisco input: %d bytes " 106925706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 107040008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 107140008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 107240008Sjoerg (u_int)h->time0, (u_int)h->time1); 10734910Swollman switch (ntohl (h->type)) { 10744910Swollman default: 107525706Sjoerg if (debug) 107640008Sjoerg addlog(SPP_FMT "cisco unknown packet type: 0x%lx\n", 107740008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 10784910Swollman break; 10794910Swollman case CISCO_ADDR_REPLY: 10804910Swollman /* Reply on address request, ignore */ 10814910Swollman break; 10824910Swollman case CISCO_KEEPALIVE_REQ: 10834910Swollman sp->pp_alivecnt = 0; 10844910Swollman sp->pp_rseq = ntohl (h->par1); 10854910Swollman if (sp->pp_seq == sp->pp_rseq) { 10864910Swollman /* Local and remote sequence numbers are equal. 10874910Swollman * Probably, the line is in loopback mode. */ 108811189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 108940008Sjoerg printf (SPP_FMT "loopback\n", 109040008Sjoerg SPP_ARGS(ifp)); 109111189Sjkh sp->pp_loopcnt = 0; 109211189Sjkh if (ifp->if_flags & IFF_UP) { 109311189Sjkh if_down (ifp); 109426018Sjoerg sppp_qflush (&sp->pp_cpq); 109511189Sjkh } 109611189Sjkh } 10974910Swollman ++sp->pp_loopcnt; 10984910Swollman 10994910Swollman /* Generate new local sequence number */ 110042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 110135064Sphk sp->pp_seq = random(); 110240008Sjoerg#else 110340008Sjoerg sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 110440008Sjoerg#endif 110511189Sjkh break; 110611189Sjkh } 110730300Sjoerg sp->pp_loopcnt = 0; 110811189Sjkh if (! (ifp->if_flags & IFF_UP) && 110911189Sjkh (ifp->if_flags & IFF_RUNNING)) { 111030300Sjoerg if_up(ifp); 111140008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 111211189Sjkh } 11134910Swollman break; 11144910Swollman case CISCO_ADDR_REQ: 111530300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 111630300Sjoerg if (me != 0L) 111730300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 11184910Swollman break; 11194910Swollman } 11204910Swollman} 11214910Swollman 11224910Swollman/* 112325944Sjoerg * Send Cisco keepalive packet. 11244910Swollman */ 112512820Sphkstatic void 112625944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 112725944Sjoerg{ 112825944Sjoerg STDDCL; 112925944Sjoerg struct ppp_header *h; 113025944Sjoerg struct cisco_packet *ch; 113125944Sjoerg struct mbuf *m; 113242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113335029Sphk struct timeval tv; 113440008Sjoerg#else 113540008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 113640008Sjoerg#endif 113725944Sjoerg 113842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113936119Sphk getmicrouptime(&tv); 114040008Sjoerg#endif 114135029Sphk 114225944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 114325944Sjoerg if (! m) 114425944Sjoerg return; 114525944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 114625944Sjoerg m->m_pkthdr.rcvif = 0; 114725944Sjoerg 114825944Sjoerg h = mtod (m, struct ppp_header*); 114925944Sjoerg h->address = CISCO_MULTICAST; 115025944Sjoerg h->control = 0; 115125944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 115225944Sjoerg 115325944Sjoerg ch = (struct cisco_packet*) (h + 1); 115425944Sjoerg ch->type = htonl (type); 115525944Sjoerg ch->par1 = htonl (par1); 115625944Sjoerg ch->par2 = htonl (par2); 115725944Sjoerg ch->rel = -1; 115840008Sjoerg 115942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 116035029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 116135029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 116240008Sjoerg#else 116340008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 116440008Sjoerg ch->time1 = htons ((u_short) t); 116540008Sjoerg#endif 116625944Sjoerg 116725944Sjoerg if (debug) 116825944Sjoerg log(LOG_DEBUG, 116940008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 117040008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 117140008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 117225944Sjoerg 117326018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 117426018Sjoerg IF_DROP (&sp->pp_fastq); 117525944Sjoerg IF_DROP (&ifp->if_snd); 117625944Sjoerg m_freem (m); 117725944Sjoerg } else 117826018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 117925944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 118025944Sjoerg (*ifp->if_start) (ifp); 118125944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 118225944Sjoerg} 118325944Sjoerg 118425944Sjoerg/* 118525944Sjoerg * PPP protocol implementation. 118625944Sjoerg */ 118725944Sjoerg 118825944Sjoerg/* 118925944Sjoerg * Send PPP control protocol packet. 119025944Sjoerg */ 119125944Sjoergstatic void 119225706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 119325706Sjoerg u_char ident, u_short len, void *data) 11944910Swollman{ 119525944Sjoerg STDDCL; 11964910Swollman struct ppp_header *h; 11974910Swollman struct lcp_header *lh; 11984910Swollman struct mbuf *m; 11994910Swollman 12004910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 12014910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 12024910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 12034910Swollman if (! m) 12044910Swollman return; 12054910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 12064910Swollman m->m_pkthdr.rcvif = 0; 12074910Swollman 12084910Swollman h = mtod (m, struct ppp_header*); 12094910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 12104910Swollman h->control = PPP_UI; /* Unnumbered Info */ 12114910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 12124910Swollman 12134910Swollman lh = (struct lcp_header*) (h + 1); 12144910Swollman lh->type = type; 12154910Swollman lh->ident = ident; 12164910Swollman lh->len = htons (LCP_HEADER_LEN + len); 12174910Swollman if (len) 12184910Swollman bcopy (data, lh+1, len); 12194910Swollman 122025706Sjoerg if (debug) { 122140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 122240008Sjoerg SPP_ARGS(ifp), 122325944Sjoerg sppp_proto_name(proto), 122425944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 122525944Sjoerg ntohs (lh->len)); 122644145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 122725706Sjoerg addlog(">\n"); 12284910Swollman } 122926018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 123026018Sjoerg IF_DROP (&sp->pp_fastq); 12314910Swollman IF_DROP (&ifp->if_snd); 12324910Swollman m_freem (m); 123325944Sjoerg ++ifp->if_oerrors; 12344910Swollman } else 123526018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 12364910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 12374910Swollman (*ifp->if_start) (ifp); 12384910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 12394910Swollman} 12404910Swollman 12414910Swollman/* 124225944Sjoerg * Handle incoming PPP control protocol packets. 12434910Swollman */ 124412820Sphkstatic void 124525944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 12464910Swollman{ 124725944Sjoerg STDDCL; 124825944Sjoerg struct lcp_header *h; 124925944Sjoerg int len = m->m_pkthdr.len; 125025944Sjoerg int rv; 125125944Sjoerg u_char *p; 12524910Swollman 125325944Sjoerg if (len < 4) { 125425944Sjoerg if (debug) 125525944Sjoerg log(LOG_DEBUG, 125640008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 125740008Sjoerg SPP_ARGS(ifp), cp->name, len); 12584910Swollman return; 125925944Sjoerg } 126025944Sjoerg h = mtod (m, struct lcp_header*); 126125944Sjoerg if (debug) { 126225944Sjoerg log(LOG_DEBUG, 126340008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 126440008Sjoerg SPP_ARGS(ifp), cp->name, 126525944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 126625944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 126744145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 126825944Sjoerg addlog(">\n"); 126925944Sjoerg } 127025944Sjoerg if (len > ntohs (h->len)) 127125944Sjoerg len = ntohs (h->len); 127230300Sjoerg p = (u_char *)(h + 1); 127325944Sjoerg switch (h->type) { 127425944Sjoerg case CONF_REQ: 127525944Sjoerg if (len < 4) { 127625944Sjoerg if (debug) 127740008Sjoerg addlog(SPP_FMT "%s invalid conf-req length %d\n", 127840008Sjoerg SPP_ARGS(ifp), cp->name, 127925944Sjoerg len); 128025944Sjoerg ++ifp->if_ierrors; 128125944Sjoerg break; 128225944Sjoerg } 128330300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 128430300Sjoerg switch (sp->state[cp->protoidx]) { 128530300Sjoerg case STATE_CLOSING: 128630300Sjoerg case STATE_STOPPING: 128730300Sjoerg return; 128830300Sjoerg case STATE_CLOSED: 128930300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 129030300Sjoerg 0, 0); 129130300Sjoerg return; 129230300Sjoerg } 129325944Sjoerg rv = (cp->RCR)(sp, h, len); 129425944Sjoerg switch (sp->state[cp->protoidx]) { 129525944Sjoerg case STATE_OPENED: 129625944Sjoerg (cp->tld)(sp); 129725944Sjoerg (cp->scr)(sp); 129825944Sjoerg /* fall through... */ 129925944Sjoerg case STATE_ACK_SENT: 130025944Sjoerg case STATE_REQ_SENT: 130125944Sjoerg sppp_cp_change_state(cp, sp, rv? 130225944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 130325944Sjoerg break; 130425944Sjoerg case STATE_STOPPED: 130525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 130625944Sjoerg (cp->scr)(sp); 130725944Sjoerg sppp_cp_change_state(cp, sp, rv? 130825944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 130925944Sjoerg break; 131025944Sjoerg case STATE_ACK_RCVD: 131125944Sjoerg if (rv) { 131225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 131325944Sjoerg if (debug) 131440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 131540008Sjoerg SPP_ARGS(ifp), 131626077Sjoerg cp->name); 131725944Sjoerg (cp->tlu)(sp); 131825944Sjoerg } else 131925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 132025944Sjoerg break; 132125944Sjoerg default: 132240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 132340008Sjoerg SPP_ARGS(ifp), cp->name, 132425944Sjoerg sppp_cp_type_name(h->type), 132525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 132625944Sjoerg ++ifp->if_ierrors; 132725944Sjoerg } 132825944Sjoerg break; 132925944Sjoerg case CONF_ACK: 133025944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 133125944Sjoerg if (debug) 133240008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 133340008Sjoerg SPP_ARGS(ifp), cp->name, 133425944Sjoerg h->ident, sp->confid[cp->protoidx]); 133525944Sjoerg ++ifp->if_ierrors; 133625944Sjoerg break; 133725944Sjoerg } 133825944Sjoerg switch (sp->state[cp->protoidx]) { 133925944Sjoerg case STATE_CLOSED: 134025944Sjoerg case STATE_STOPPED: 134125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 134225944Sjoerg break; 134325944Sjoerg case STATE_CLOSING: 134425944Sjoerg case STATE_STOPPING: 134525944Sjoerg break; 134625944Sjoerg case STATE_REQ_SENT: 134725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 134825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 134925944Sjoerg break; 135025944Sjoerg case STATE_OPENED: 135125944Sjoerg (cp->tld)(sp); 135225944Sjoerg /* fall through */ 135325944Sjoerg case STATE_ACK_RCVD: 135425944Sjoerg (cp->scr)(sp); 135525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 135625944Sjoerg break; 135725944Sjoerg case STATE_ACK_SENT: 135825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 135925944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 136025944Sjoerg if (debug) 136140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 136240008Sjoerg SPP_ARGS(ifp), cp->name); 136325944Sjoerg (cp->tlu)(sp); 136425944Sjoerg break; 136525944Sjoerg default: 136640008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 136740008Sjoerg SPP_ARGS(ifp), cp->name, 136825944Sjoerg sppp_cp_type_name(h->type), 136925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 137025944Sjoerg ++ifp->if_ierrors; 137125944Sjoerg } 137225944Sjoerg break; 137325944Sjoerg case CONF_NAK: 137425944Sjoerg case CONF_REJ: 137525944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 137625944Sjoerg if (debug) 137740008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 137840008Sjoerg SPP_ARGS(ifp), cp->name, 137925944Sjoerg h->ident, sp->confid[cp->protoidx]); 138025944Sjoerg ++ifp->if_ierrors; 138125944Sjoerg break; 138225944Sjoerg } 138325944Sjoerg if (h->type == CONF_NAK) 138425944Sjoerg (cp->RCN_nak)(sp, h, len); 138525944Sjoerg else /* CONF_REJ */ 138625944Sjoerg (cp->RCN_rej)(sp, h, len); 13874910Swollman 138825944Sjoerg switch (sp->state[cp->protoidx]) { 138925944Sjoerg case STATE_CLOSED: 139025944Sjoerg case STATE_STOPPED: 139125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 139225944Sjoerg break; 139325944Sjoerg case STATE_REQ_SENT: 139425944Sjoerg case STATE_ACK_SENT: 139525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 139625944Sjoerg (cp->scr)(sp); 139725944Sjoerg break; 139825944Sjoerg case STATE_OPENED: 139925944Sjoerg (cp->tld)(sp); 140025944Sjoerg /* fall through */ 140125944Sjoerg case STATE_ACK_RCVD: 140252633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 140325944Sjoerg (cp->scr)(sp); 140425944Sjoerg break; 140525944Sjoerg case STATE_CLOSING: 140625944Sjoerg case STATE_STOPPING: 140725944Sjoerg break; 140825944Sjoerg default: 140940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 141040008Sjoerg SPP_ARGS(ifp), cp->name, 141125944Sjoerg sppp_cp_type_name(h->type), 141225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 141325944Sjoerg ++ifp->if_ierrors; 141425944Sjoerg } 141525944Sjoerg break; 14164910Swollman 141725944Sjoerg case TERM_REQ: 141825944Sjoerg switch (sp->state[cp->protoidx]) { 141925944Sjoerg case STATE_ACK_RCVD: 142025944Sjoerg case STATE_ACK_SENT: 142125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 142225944Sjoerg /* fall through */ 142325944Sjoerg case STATE_CLOSED: 142425944Sjoerg case STATE_STOPPED: 142525944Sjoerg case STATE_CLOSING: 142625944Sjoerg case STATE_STOPPING: 142725944Sjoerg case STATE_REQ_SENT: 142825944Sjoerg sta: 142925944Sjoerg /* Send Terminate-Ack packet. */ 143025944Sjoerg if (debug) 143140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 143240008Sjoerg SPP_ARGS(ifp), cp->name); 143325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 143425944Sjoerg break; 143525944Sjoerg case STATE_OPENED: 143625944Sjoerg (cp->tld)(sp); 143725944Sjoerg sp->rst_counter[cp->protoidx] = 0; 143825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 143925944Sjoerg goto sta; 144025944Sjoerg break; 144125944Sjoerg default: 144240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 144340008Sjoerg SPP_ARGS(ifp), cp->name, 144425944Sjoerg sppp_cp_type_name(h->type), 144525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 144625944Sjoerg ++ifp->if_ierrors; 144725944Sjoerg } 144825944Sjoerg break; 144925944Sjoerg case TERM_ACK: 145025944Sjoerg switch (sp->state[cp->protoidx]) { 145125944Sjoerg case STATE_CLOSED: 145225944Sjoerg case STATE_STOPPED: 145325944Sjoerg case STATE_REQ_SENT: 145425944Sjoerg case STATE_ACK_SENT: 145525944Sjoerg break; 145625944Sjoerg case STATE_CLOSING: 145741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 145825944Sjoerg (cp->tlf)(sp); 145925944Sjoerg break; 146025944Sjoerg case STATE_STOPPING: 146141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 146225944Sjoerg (cp->tlf)(sp); 146325944Sjoerg break; 146425944Sjoerg case STATE_ACK_RCVD: 146525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 146625944Sjoerg break; 146725944Sjoerg case STATE_OPENED: 146825944Sjoerg (cp->tld)(sp); 146925944Sjoerg (cp->scr)(sp); 147025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 147125944Sjoerg break; 147225944Sjoerg default: 147340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 147440008Sjoerg SPP_ARGS(ifp), cp->name, 147525944Sjoerg sppp_cp_type_name(h->type), 147625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 147725944Sjoerg ++ifp->if_ierrors; 147825944Sjoerg } 147925944Sjoerg break; 148025944Sjoerg case CODE_REJ: 148125944Sjoerg case PROTO_REJ: 148225944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 148330300Sjoerg log(LOG_INFO, 148440008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 148530300Sjoerg "danger will robinson\n", 148640008Sjoerg SPP_ARGS(ifp), cp->name, 148730300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 148825944Sjoerg switch (sp->state[cp->protoidx]) { 148925944Sjoerg case STATE_CLOSED: 149025944Sjoerg case STATE_STOPPED: 149125944Sjoerg case STATE_REQ_SENT: 149225944Sjoerg case STATE_ACK_SENT: 149325944Sjoerg case STATE_CLOSING: 149425944Sjoerg case STATE_STOPPING: 149525944Sjoerg case STATE_OPENED: 149625944Sjoerg break; 149725944Sjoerg case STATE_ACK_RCVD: 149825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 149925944Sjoerg break; 150025944Sjoerg default: 150140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 150240008Sjoerg SPP_ARGS(ifp), cp->name, 150325944Sjoerg sppp_cp_type_name(h->type), 150425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 150525944Sjoerg ++ifp->if_ierrors; 150625944Sjoerg } 150725944Sjoerg break; 150825944Sjoerg case DISC_REQ: 150925944Sjoerg if (cp->proto != PPP_LCP) 151025944Sjoerg goto illegal; 151125944Sjoerg /* Discard the packet. */ 151225944Sjoerg break; 151325944Sjoerg case ECHO_REQ: 151425944Sjoerg if (cp->proto != PPP_LCP) 151525944Sjoerg goto illegal; 151625944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 151725944Sjoerg if (debug) 151840008Sjoerg addlog(SPP_FMT "lcp echo req but lcp closed\n", 151940008Sjoerg SPP_ARGS(ifp)); 152025944Sjoerg ++ifp->if_ierrors; 152125944Sjoerg break; 152225944Sjoerg } 152325944Sjoerg if (len < 8) { 152425944Sjoerg if (debug) 152540008Sjoerg addlog(SPP_FMT "invalid lcp echo request " 152625944Sjoerg "packet length: %d bytes\n", 152740008Sjoerg SPP_ARGS(ifp), len); 152825944Sjoerg break; 152925944Sjoerg } 153044145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 153144145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 153225944Sjoerg /* Line loopback mode detected. */ 153340008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 153425944Sjoerg if_down (ifp); 153526018Sjoerg sppp_qflush (&sp->pp_cpq); 15364910Swollman 153725944Sjoerg /* Shut down the PPP link. */ 153825944Sjoerg /* XXX */ 153925944Sjoerg lcp.Down(sp); 154025944Sjoerg lcp.Up(sp); 154125944Sjoerg break; 154225944Sjoerg } 154325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 154425944Sjoerg if (debug) 154540008Sjoerg addlog(SPP_FMT "got lcp echo req, sending echo rep\n", 154640008Sjoerg SPP_ARGS(ifp)); 154725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 154825944Sjoerg break; 154925944Sjoerg case ECHO_REPLY: 155025944Sjoerg if (cp->proto != PPP_LCP) 155125944Sjoerg goto illegal; 155225944Sjoerg if (h->ident != sp->lcp.echoid) { 155325944Sjoerg ++ifp->if_ierrors; 155425944Sjoerg break; 155525944Sjoerg } 155625944Sjoerg if (len < 8) { 155725944Sjoerg if (debug) 155840008Sjoerg addlog(SPP_FMT "lcp invalid echo reply " 155925944Sjoerg "packet length: %d bytes\n", 156040008Sjoerg SPP_ARGS(ifp), len); 156125944Sjoerg break; 156225944Sjoerg } 156325944Sjoerg if (debug) 156440008Sjoerg addlog(SPP_FMT "lcp got echo rep\n", 156540008Sjoerg SPP_ARGS(ifp)); 156644145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 156744145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 156825944Sjoerg sp->pp_alivecnt = 0; 156925944Sjoerg break; 157025944Sjoerg default: 157125944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 157225944Sjoerg illegal: 157325944Sjoerg if (debug) 157440008Sjoerg addlog(SPP_FMT "%s send code-rej for 0x%x\n", 157540008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 157625944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 157725944Sjoerg m->m_pkthdr.len, h); 157825944Sjoerg ++ifp->if_ierrors; 157925944Sjoerg } 15804910Swollman} 15814910Swollman 158225944Sjoerg 15834910Swollman/* 158425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 158525944Sjoerg * Basically, the state transition handling in the automaton. 15864910Swollman */ 158725944Sjoergstatic void 158825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 15894910Swollman{ 159025944Sjoerg STDDCL; 15914910Swollman 159225944Sjoerg if (debug) 159340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 159440008Sjoerg SPP_ARGS(ifp), cp->name, 159525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 159625944Sjoerg 159725944Sjoerg switch (sp->state[cp->protoidx]) { 159825944Sjoerg case STATE_INITIAL: 159925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 160025944Sjoerg break; 160125944Sjoerg case STATE_STARTING: 160225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 160325944Sjoerg (cp->scr)(sp); 160425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 160525944Sjoerg break; 16064910Swollman default: 160740008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 160840008Sjoerg SPP_ARGS(ifp), cp->name, 160925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 161025944Sjoerg } 161125944Sjoerg} 16124910Swollman 161325944Sjoergstatic void 161425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 161525944Sjoerg{ 161625944Sjoerg STDDCL; 161725944Sjoerg 161825944Sjoerg if (debug) 161940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 162040008Sjoerg SPP_ARGS(ifp), cp->name, 162125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 162225944Sjoerg 162325944Sjoerg switch (sp->state[cp->protoidx]) { 162425944Sjoerg case STATE_CLOSED: 162525944Sjoerg case STATE_CLOSING: 162625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 16274910Swollman break; 162825944Sjoerg case STATE_STOPPED: 162941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 163025944Sjoerg (cp->tls)(sp); 163141881Sphk break; 163225944Sjoerg case STATE_STOPPING: 163325944Sjoerg case STATE_REQ_SENT: 163425944Sjoerg case STATE_ACK_RCVD: 163525944Sjoerg case STATE_ACK_SENT: 163625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 163725944Sjoerg break; 163825944Sjoerg case STATE_OPENED: 163925944Sjoerg (cp->tld)(sp); 164025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 164125944Sjoerg break; 164225944Sjoerg default: 164340008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 164440008Sjoerg SPP_ARGS(ifp), cp->name, 164525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164625944Sjoerg } 164725944Sjoerg} 16484910Swollman 164911189Sjkh 165025944Sjoergstatic void 165125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 165225944Sjoerg{ 165325944Sjoerg STDDCL; 165425944Sjoerg 165525944Sjoerg if (debug) 165640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 165740008Sjoerg SPP_ARGS(ifp), cp->name, 165825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 165925944Sjoerg 166025944Sjoerg switch (sp->state[cp->protoidx]) { 166125944Sjoerg case STATE_INITIAL: 166241881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 166325944Sjoerg (cp->tls)(sp); 16644910Swollman break; 166525944Sjoerg case STATE_STARTING: 166625944Sjoerg break; 166725944Sjoerg case STATE_CLOSED: 166825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 166925944Sjoerg (cp->scr)(sp); 167025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 167125944Sjoerg break; 167225944Sjoerg case STATE_STOPPED: 167325944Sjoerg case STATE_STOPPING: 167425944Sjoerg case STATE_REQ_SENT: 167525944Sjoerg case STATE_ACK_RCVD: 167625944Sjoerg case STATE_ACK_SENT: 167725944Sjoerg case STATE_OPENED: 167825944Sjoerg break; 167925944Sjoerg case STATE_CLOSING: 168025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 168125944Sjoerg break; 168225944Sjoerg } 168325944Sjoerg} 16844910Swollman 168525944Sjoerg 168625944Sjoergstatic void 168725944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 168825944Sjoerg{ 168925944Sjoerg STDDCL; 169025944Sjoerg 169125944Sjoerg if (debug) 169240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 169340008Sjoerg SPP_ARGS(ifp), cp->name, 169425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169525944Sjoerg 169625944Sjoerg switch (sp->state[cp->protoidx]) { 169725944Sjoerg case STATE_INITIAL: 169825944Sjoerg case STATE_CLOSED: 169925944Sjoerg case STATE_CLOSING: 17004910Swollman break; 170125944Sjoerg case STATE_STARTING: 170241881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 170325944Sjoerg (cp->tlf)(sp); 17044910Swollman break; 170525944Sjoerg case STATE_STOPPED: 170625944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 17074910Swollman break; 170825944Sjoerg case STATE_STOPPING: 170925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 17104910Swollman break; 171125944Sjoerg case STATE_OPENED: 171225944Sjoerg (cp->tld)(sp); 171325944Sjoerg /* fall through */ 171425944Sjoerg case STATE_REQ_SENT: 171525944Sjoerg case STATE_ACK_RCVD: 171625944Sjoerg case STATE_ACK_SENT: 171725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 171825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 171925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 17204910Swollman break; 17214910Swollman } 17224910Swollman} 17234910Swollman 172425944Sjoergstatic void 172525944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 172625944Sjoerg{ 172725944Sjoerg STDDCL; 172825944Sjoerg int s; 172925944Sjoerg 173025944Sjoerg s = splimp(); 173125944Sjoerg if (debug) 173240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 173340008Sjoerg SPP_ARGS(ifp), cp->name, 173425944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 173525944Sjoerg sp->rst_counter[cp->protoidx]); 173625944Sjoerg 173725944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 173825944Sjoerg /* TO- event */ 173925944Sjoerg switch (sp->state[cp->protoidx]) { 174025944Sjoerg case STATE_CLOSING: 174141881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 174225944Sjoerg (cp->tlf)(sp); 174325944Sjoerg break; 174425944Sjoerg case STATE_STOPPING: 174541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 174625944Sjoerg (cp->tlf)(sp); 174725944Sjoerg break; 174825944Sjoerg case STATE_REQ_SENT: 174925944Sjoerg case STATE_ACK_RCVD: 175025944Sjoerg case STATE_ACK_SENT: 175141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 175225944Sjoerg (cp->tlf)(sp); 175325944Sjoerg break; 175425944Sjoerg } 175525944Sjoerg else 175625944Sjoerg /* TO+ event */ 175725944Sjoerg switch (sp->state[cp->protoidx]) { 175825944Sjoerg case STATE_CLOSING: 175925944Sjoerg case STATE_STOPPING: 176025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 176125944Sjoerg 0, 0); 176242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 176342064Sphk sp->ch[cp->protoidx]); 176425944Sjoerg break; 176525944Sjoerg case STATE_REQ_SENT: 176625944Sjoerg case STATE_ACK_RCVD: 176725944Sjoerg (cp->scr)(sp); 176825944Sjoerg /* sppp_cp_change_state() will restart the timer */ 176925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 177025944Sjoerg break; 177125944Sjoerg case STATE_ACK_SENT: 177225944Sjoerg (cp->scr)(sp); 177342064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 177442064Sphk sp->ch[cp->protoidx]); 177525944Sjoerg break; 177625944Sjoerg } 177725944Sjoerg 177825944Sjoerg splx(s); 177925944Sjoerg} 178025944Sjoerg 178111189Sjkh/* 178225944Sjoerg * Change the state of a control protocol in the state automaton. 178325944Sjoerg * Takes care of starting/stopping the restart timer. 178411189Sjkh */ 178525944Sjoergvoid 178625944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 178725944Sjoerg{ 178825944Sjoerg sp->state[cp->protoidx] = newstate; 178925944Sjoerg 179040008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 179125944Sjoerg switch (newstate) { 179225944Sjoerg case STATE_INITIAL: 179325944Sjoerg case STATE_STARTING: 179425944Sjoerg case STATE_CLOSED: 179525944Sjoerg case STATE_STOPPED: 179625944Sjoerg case STATE_OPENED: 179725944Sjoerg break; 179825944Sjoerg case STATE_CLOSING: 179925944Sjoerg case STATE_STOPPING: 180025944Sjoerg case STATE_REQ_SENT: 180125944Sjoerg case STATE_ACK_RCVD: 180225944Sjoerg case STATE_ACK_SENT: 180342064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 180442064Sphk sp->ch[cp->protoidx]); 180525944Sjoerg break; 180625944Sjoerg } 180725944Sjoerg} 180825944Sjoerg/* 180925944Sjoerg *--------------------------------------------------------------------------* 181025944Sjoerg * * 181125944Sjoerg * The LCP implementation. * 181225944Sjoerg * * 181325944Sjoerg *--------------------------------------------------------------------------* 181425944Sjoerg */ 181525944Sjoergstatic void 181625944Sjoergsppp_lcp_init(struct sppp *sp) 181725944Sjoerg{ 181825944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 181925944Sjoerg sp->lcp.magic = 0; 182025944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 182125944Sjoerg sp->fail_counter[IDX_LCP] = 0; 182225944Sjoerg sp->lcp.protos = 0; 182325944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 182430300Sjoerg 182544145Sphk /* Note that these values are relevant for all control protocols */ 182644145Sphk sp->lcp.timeout = 3 * hz; 182725944Sjoerg sp->lcp.max_terminate = 2; 182825944Sjoerg sp->lcp.max_configure = 10; 182925944Sjoerg sp->lcp.max_failure = 10; 183042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 183130300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 183240008Sjoerg#endif 183325944Sjoerg} 183425944Sjoerg 183525944Sjoergstatic void 183625944Sjoergsppp_lcp_up(struct sppp *sp) 183725944Sjoerg{ 183825944Sjoerg STDDCL; 183925944Sjoerg 184025944Sjoerg /* 184130300Sjoerg * If this interface is passive or dial-on-demand, and we are 184230300Sjoerg * still in Initial state, it means we've got an incoming 184330300Sjoerg * call. Activate the interface. 184425944Sjoerg */ 184525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 184625944Sjoerg if (debug) 184725944Sjoerg log(LOG_DEBUG, 184840008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 184925944Sjoerg ifp->if_flags |= IFF_RUNNING; 185030300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 185130300Sjoerg if (debug) 185230300Sjoerg addlog("(incoming call)\n"); 185330300Sjoerg sp->pp_flags |= PP_CALLIN; 185430300Sjoerg lcp.Open(sp); 185530300Sjoerg } else if (debug) 185630300Sjoerg addlog("\n"); 185725944Sjoerg } 185825944Sjoerg 185925944Sjoerg sppp_up_event(&lcp, sp); 186025944Sjoerg} 186125944Sjoerg 186225944Sjoergstatic void 186325944Sjoergsppp_lcp_down(struct sppp *sp) 186425944Sjoerg{ 186525944Sjoerg STDDCL; 186625944Sjoerg 186725944Sjoerg sppp_down_event(&lcp, sp); 186825944Sjoerg 186925944Sjoerg /* 187025944Sjoerg * If this is neither a dial-on-demand nor a passive 187125944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 187225944Sjoerg * administrator can force a redial by another ``ifconfig 187325944Sjoerg * up''. XXX For leased line operation, should we immediately 187425944Sjoerg * try to reopen the connection here? 187525944Sjoerg */ 187625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 187725944Sjoerg log(LOG_INFO, 187842066Sphk SPP_FMT "Down event, taking interface down.\n", 187940008Sjoerg SPP_ARGS(ifp)); 188025944Sjoerg if_down(ifp); 188125944Sjoerg } else { 188225944Sjoerg if (debug) 188325944Sjoerg log(LOG_DEBUG, 188440008Sjoerg SPP_FMT "Down event (carrier loss)\n", 188540008Sjoerg SPP_ARGS(ifp)); 188625944Sjoerg } 188730300Sjoerg sp->pp_flags &= ~PP_CALLIN; 188830300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 188930300Sjoerg lcp.Close(sp); 189025944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 189125944Sjoerg} 189225944Sjoerg 189325944Sjoergstatic void 189425944Sjoergsppp_lcp_open(struct sppp *sp) 189525944Sjoerg{ 189630300Sjoerg /* 189730300Sjoerg * If we are authenticator, negotiate LCP_AUTH 189830300Sjoerg */ 189930300Sjoerg if (sp->hisauth.proto != 0) 190030300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 190130300Sjoerg else 190230300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 190330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 190425944Sjoerg sppp_open_event(&lcp, sp); 190525944Sjoerg} 190625944Sjoerg 190725944Sjoergstatic void 190825944Sjoergsppp_lcp_close(struct sppp *sp) 190925944Sjoerg{ 191025944Sjoerg sppp_close_event(&lcp, sp); 191125944Sjoerg} 191225944Sjoerg 191325944Sjoergstatic void 191425944Sjoergsppp_lcp_TO(void *cookie) 191525944Sjoerg{ 191625944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 191725944Sjoerg} 191825944Sjoerg 191925944Sjoerg/* 192025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 192125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 192225944Sjoerg * caused action scn. (The return value is used to make the state 192325944Sjoerg * transition decision in the state automaton.) 192425944Sjoerg */ 192512820Sphkstatic int 192625944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 19274910Swollman{ 192825944Sjoerg STDDCL; 192911189Sjkh u_char *buf, *r, *p; 193025944Sjoerg int origlen, rlen; 193125944Sjoerg u_long nmagic; 193230300Sjoerg u_short authproto; 19334910Swollman 193411189Sjkh len -= 4; 193525944Sjoerg origlen = len; 193611189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 193711189Sjkh if (! buf) 193811189Sjkh return (0); 19394910Swollman 194025706Sjoerg if (debug) 194140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 194240008Sjoerg SPP_ARGS(ifp)); 194325706Sjoerg 194425944Sjoerg /* pass 1: check for things that need to be rejected */ 194511189Sjkh p = (void*) (h+1); 194611189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 194725944Sjoerg if (debug) 194825944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 194911189Sjkh switch (*p) { 195011189Sjkh case LCP_OPT_MAGIC: 195125944Sjoerg /* Magic number. */ 195225944Sjoerg /* fall through, both are same length */ 195325944Sjoerg case LCP_OPT_ASYNC_MAP: 195425944Sjoerg /* Async control character map. */ 195525944Sjoerg if (len >= 6 || p[1] == 6) 195625944Sjoerg continue; 195725944Sjoerg if (debug) 195825944Sjoerg addlog("[invalid] "); 195925944Sjoerg break; 196025944Sjoerg case LCP_OPT_MRU: 196125944Sjoerg /* Maximum receive unit. */ 196225944Sjoerg if (len >= 4 && p[1] == 4) 196325944Sjoerg continue; 196425944Sjoerg if (debug) 196525944Sjoerg addlog("[invalid] "); 196625944Sjoerg break; 196730300Sjoerg case LCP_OPT_AUTH_PROTO: 196830300Sjoerg if (len < 4) { 196930300Sjoerg if (debug) 197030300Sjoerg addlog("[invalid] "); 197130300Sjoerg break; 197230300Sjoerg } 197330300Sjoerg authproto = (p[2] << 8) + p[3]; 197430300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 197530300Sjoerg if (debug) 197630300Sjoerg addlog("[invalid chap len] "); 197730300Sjoerg break; 197830300Sjoerg } 197930300Sjoerg if (sp->myauth.proto == 0) { 198030300Sjoerg /* we are not configured to do auth */ 198130300Sjoerg if (debug) 198230300Sjoerg addlog("[not configured] "); 198330300Sjoerg break; 198430300Sjoerg } 198530300Sjoerg /* 198630300Sjoerg * Remote want us to authenticate, remember this, 198730300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 198830300Sjoerg * up. 198930300Sjoerg */ 199030300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 199130300Sjoerg continue; 199225944Sjoerg default: 199325944Sjoerg /* Others not supported. */ 199425944Sjoerg if (debug) 199525944Sjoerg addlog("[rej] "); 199625944Sjoerg break; 199725944Sjoerg } 199825944Sjoerg /* Add the option to rejected list. */ 199925944Sjoerg bcopy (p, r, p[1]); 200025944Sjoerg r += p[1]; 200125944Sjoerg rlen += p[1]; 200225944Sjoerg } 200325944Sjoerg if (rlen) { 200425944Sjoerg if (debug) 200525944Sjoerg addlog(" send conf-rej\n"); 200625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 200725944Sjoerg return 0; 200825944Sjoerg } else if (debug) 200925944Sjoerg addlog("\n"); 201025944Sjoerg 201125944Sjoerg /* 201225944Sjoerg * pass 2: check for option values that are unacceptable and 201325944Sjoerg * thus require to be nak'ed. 201425944Sjoerg */ 201525944Sjoerg if (debug) 201640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 201740008Sjoerg SPP_ARGS(ifp)); 201825944Sjoerg 201925944Sjoerg p = (void*) (h+1); 202025944Sjoerg len = origlen; 202125944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 202225944Sjoerg if (debug) 202325944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 202425944Sjoerg switch (*p) { 202525944Sjoerg case LCP_OPT_MAGIC: 202611189Sjkh /* Magic number -- extract. */ 202725944Sjoerg nmagic = (u_long)p[2] << 24 | 202825944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 202925944Sjoerg if (nmagic != sp->lcp.magic) { 203025706Sjoerg if (debug) 203138372Sbde addlog("0x%lx ", nmagic); 203211189Sjkh continue; 203311189Sjkh } 203425944Sjoerg /* 203525944Sjoerg * Local and remote magics equal -- loopback? 203625944Sjoerg */ 203725944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 203840008Sjoerg printf (SPP_FMT "loopback\n", 203940008Sjoerg SPP_ARGS(ifp)); 204025944Sjoerg sp->pp_loopcnt = 0; 204125944Sjoerg if (ifp->if_flags & IFF_UP) { 204225944Sjoerg if_down(ifp); 204326018Sjoerg sppp_qflush(&sp->pp_cpq); 204425944Sjoerg /* XXX ? */ 204525944Sjoerg lcp.Down(sp); 204625944Sjoerg lcp.Up(sp); 204725944Sjoerg } 204825944Sjoerg } else if (debug) 204925944Sjoerg addlog("[glitch] "); 205025944Sjoerg ++sp->pp_loopcnt; 205125944Sjoerg /* 205225944Sjoerg * We negate our magic here, and NAK it. If 205325944Sjoerg * we see it later in an NAK packet, we 205425944Sjoerg * suggest a new one. 205525944Sjoerg */ 205625944Sjoerg nmagic = ~sp->lcp.magic; 205725944Sjoerg /* Gonna NAK it. */ 205825944Sjoerg p[2] = nmagic >> 24; 205925944Sjoerg p[3] = nmagic >> 16; 206025944Sjoerg p[4] = nmagic >> 8; 206125944Sjoerg p[5] = nmagic; 206211189Sjkh break; 206325944Sjoerg 206411189Sjkh case LCP_OPT_ASYNC_MAP: 206511189Sjkh /* Async control character map -- check to be zero. */ 206625944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 206725706Sjoerg if (debug) 206825944Sjoerg addlog("[empty] "); 206911189Sjkh continue; 207025706Sjoerg } 207125706Sjoerg if (debug) 207225944Sjoerg addlog("[non-empty] "); 207325944Sjoerg /* suggest a zero one */ 207425944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 207511189Sjkh break; 207625944Sjoerg 207711189Sjkh case LCP_OPT_MRU: 207825944Sjoerg /* 207925944Sjoerg * Maximum receive unit. Always agreeable, 208025944Sjoerg * but ignored by now. 208125944Sjoerg */ 208225944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 208325706Sjoerg if (debug) 208438372Sbde addlog("%lu ", sp->lcp.their_mru); 208511189Sjkh continue; 208630300Sjoerg 208730300Sjoerg case LCP_OPT_AUTH_PROTO: 208830300Sjoerg authproto = (p[2] << 8) + p[3]; 208930300Sjoerg if (sp->myauth.proto != authproto) { 209030300Sjoerg /* not agreed, nak */ 209130300Sjoerg if (debug) 209230300Sjoerg addlog("[mine %s != his %s] ", 209330300Sjoerg sppp_proto_name(sp->hisauth.proto), 209430300Sjoerg sppp_proto_name(authproto)); 209530300Sjoerg p[2] = sp->myauth.proto >> 8; 209630300Sjoerg p[3] = sp->myauth.proto; 209730300Sjoerg break; 209830300Sjoerg } 209930300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 210030300Sjoerg if (debug) 210130300Sjoerg addlog("[chap not MD5] "); 210239981Sjoerg p[4] = CHAP_MD5; 210330300Sjoerg break; 210430300Sjoerg } 210530300Sjoerg continue; 210611189Sjkh } 210725944Sjoerg /* Add the option to nak'ed list. */ 210825706Sjoerg bcopy (p, r, p[1]); 210925706Sjoerg r += p[1]; 211011189Sjkh rlen += p[1]; 211112436Speter } 211225706Sjoerg if (rlen) { 211328036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 211428036Sjoerg if (debug) 211528036Sjoerg addlog(" max_failure (%d) exceeded, " 211628036Sjoerg "send conf-rej\n", 211728036Sjoerg sp->lcp.max_failure); 211828036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 211928036Sjoerg } else { 212028036Sjoerg if (debug) 212128036Sjoerg addlog(" send conf-nak\n"); 212228036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 212328036Sjoerg } 212425944Sjoerg return 0; 212525944Sjoerg } else { 212625944Sjoerg if (debug) 212725944Sjoerg addlog(" send conf-ack\n"); 212828036Sjoerg sp->fail_counter[IDX_LCP] = 0; 212925944Sjoerg sp->pp_loopcnt = 0; 213025944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 213125944Sjoerg h->ident, origlen, h+1); 213225944Sjoerg } 213325944Sjoerg 213411189Sjkh free (buf, M_TEMP); 213511189Sjkh return (rlen == 0); 21364910Swollman} 21374910Swollman 213825944Sjoerg/* 213925944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 214025944Sjoerg * negotiation. 214125944Sjoerg */ 214212820Sphkstatic void 214325944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 21444910Swollman{ 214525944Sjoerg STDDCL; 214625944Sjoerg u_char *buf, *p; 21474910Swollman 214825944Sjoerg len -= 4; 214925944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 215025944Sjoerg if (!buf) 21514910Swollman return; 215225944Sjoerg 215325944Sjoerg if (debug) 215440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 215540008Sjoerg SPP_ARGS(ifp)); 215625944Sjoerg 215725944Sjoerg p = (void*) (h+1); 215825944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 215925944Sjoerg if (debug) 216025944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 216125944Sjoerg switch (*p) { 216225944Sjoerg case LCP_OPT_MAGIC: 216325944Sjoerg /* Magic number -- can't use it, use 0 */ 216425944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 216525944Sjoerg sp->lcp.magic = 0; 216625944Sjoerg break; 216725944Sjoerg case LCP_OPT_MRU: 216825944Sjoerg /* 216925944Sjoerg * Should not be rejected anyway, since we only 217025944Sjoerg * negotiate a MRU if explicitly requested by 217125944Sjoerg * peer. 217225944Sjoerg */ 217325944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 217425944Sjoerg break; 217530300Sjoerg case LCP_OPT_AUTH_PROTO: 217630300Sjoerg /* 217730300Sjoerg * Peer doesn't want to authenticate himself, 217830300Sjoerg * deny unless this is a dialout call, and 217930300Sjoerg * AUTHFLAG_NOCALLOUT is set. 218030300Sjoerg */ 218130300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 218230300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 218330300Sjoerg if (debug) 218430300Sjoerg addlog("[don't insist on auth " 218530300Sjoerg "for callout]"); 218630300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 218730300Sjoerg break; 218830300Sjoerg } 218930300Sjoerg if (debug) 219030300Sjoerg addlog("[access denied]\n"); 219130300Sjoerg lcp.Close(sp); 219230300Sjoerg break; 219325944Sjoerg } 21944910Swollman } 219525944Sjoerg if (debug) 219625944Sjoerg addlog("\n"); 219725944Sjoerg free (buf, M_TEMP); 219825944Sjoerg return; 219925944Sjoerg} 220025944Sjoerg 220125944Sjoerg/* 220225944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 220325944Sjoerg * negotiation. 220425944Sjoerg */ 220525944Sjoergstatic void 220625944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 220725944Sjoerg{ 220825944Sjoerg STDDCL; 220925944Sjoerg u_char *buf, *p; 221025944Sjoerg u_long magic; 221125944Sjoerg 221225944Sjoerg len -= 4; 221325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 221425944Sjoerg if (!buf) 221525944Sjoerg return; 221625944Sjoerg 221725944Sjoerg if (debug) 221840008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 221940008Sjoerg SPP_ARGS(ifp)); 222025944Sjoerg 222125944Sjoerg p = (void*) (h+1); 222225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 222325706Sjoerg if (debug) 222425944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 222525944Sjoerg switch (*p) { 222625944Sjoerg case LCP_OPT_MAGIC: 222725944Sjoerg /* Magic number -- renegotiate */ 222825944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 222925944Sjoerg len >= 6 && p[1] == 6) { 223025944Sjoerg magic = (u_long)p[2] << 24 | 223125944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 223225944Sjoerg /* 223325944Sjoerg * If the remote magic is our negated one, 223425944Sjoerg * this looks like a loopback problem. 223525944Sjoerg * Suggest a new magic to make sure. 223625944Sjoerg */ 223725944Sjoerg if (magic == ~sp->lcp.magic) { 223825944Sjoerg if (debug) 223925944Sjoerg addlog("magic glitch "); 224042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 224135064Sphk sp->lcp.magic = random(); 224240008Sjoerg#else 224340008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 224440008Sjoerg#endif 224525944Sjoerg } else { 224625944Sjoerg sp->lcp.magic = magic; 224725944Sjoerg if (debug) 224840008Sjoerg addlog("%lu ", magic); 224925944Sjoerg } 225025944Sjoerg } 225125944Sjoerg break; 225225944Sjoerg case LCP_OPT_MRU: 225325944Sjoerg /* 225425944Sjoerg * Peer wants to advise us to negotiate an MRU. 225525944Sjoerg * Agree on it if it's reasonable, or use 225625944Sjoerg * default otherwise. 225725944Sjoerg */ 225825944Sjoerg if (len >= 4 && p[1] == 4) { 225925944Sjoerg u_int mru = p[2] * 256 + p[3]; 226025944Sjoerg if (debug) 226125944Sjoerg addlog("%d ", mru); 226225944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 226325944Sjoerg mru = PP_MTU; 226425944Sjoerg sp->lcp.mru = mru; 226525944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 226625944Sjoerg } 226725944Sjoerg break; 226830300Sjoerg case LCP_OPT_AUTH_PROTO: 226930300Sjoerg /* 227030300Sjoerg * Peer doesn't like our authentication method, 227130300Sjoerg * deny. 227230300Sjoerg */ 227330300Sjoerg if (debug) 227430300Sjoerg addlog("[access denied]\n"); 227530300Sjoerg lcp.Close(sp); 227630300Sjoerg break; 22774910Swollman } 227825944Sjoerg } 227925944Sjoerg if (debug) 228025944Sjoerg addlog("\n"); 228125944Sjoerg free (buf, M_TEMP); 228225944Sjoerg return; 228325944Sjoerg} 228411189Sjkh 228525944Sjoergstatic void 228625944Sjoergsppp_lcp_tlu(struct sppp *sp) 228725944Sjoerg{ 228842066Sphk STDDCL; 228925944Sjoerg int i; 229025944Sjoerg u_long mask; 229125944Sjoerg 229225944Sjoerg /* XXX ? */ 229325944Sjoerg if (! (ifp->if_flags & IFF_UP) && 229425944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 229525944Sjoerg /* Coming out of loopback mode. */ 229625944Sjoerg if_up(ifp); 229740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 229825944Sjoerg } 229925944Sjoerg 230025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 230125944Sjoerg if ((cps[i])->flags & CP_QUAL) 230225944Sjoerg (cps[i])->Open(sp); 230325944Sjoerg 230430300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 230530300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 230625944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 230725944Sjoerg else 230825944Sjoerg sp->pp_phase = PHASE_NETWORK; 230925944Sjoerg 231042066Sphk if (debug) 231142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 231242066Sphk sppp_phase_name(sp->pp_phase)); 231325944Sjoerg 231430300Sjoerg /* 231530300Sjoerg * Open all authentication protocols. This is even required 231630300Sjoerg * if we already proceeded to network phase, since it might be 231730300Sjoerg * that remote wants us to authenticate, so we might have to 231830300Sjoerg * send a PAP request. Undesired authentication protocols 231930300Sjoerg * don't do anything when they get an Open event. 232030300Sjoerg */ 232130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 232230300Sjoerg if ((cps[i])->flags & CP_AUTH) 232330300Sjoerg (cps[i])->Open(sp); 232430300Sjoerg 232530300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 232625944Sjoerg /* Notify all NCPs. */ 232725944Sjoerg for (i = 0; i < IDX_COUNT; i++) 232825944Sjoerg if ((cps[i])->flags & CP_NCP) 232925944Sjoerg (cps[i])->Open(sp); 233025944Sjoerg } 233125944Sjoerg 233225944Sjoerg /* Send Up events to all started protos. */ 233325944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 233425944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 233525944Sjoerg (cps[i])->Up(sp); 233625944Sjoerg 233742104Sphk /* notify low-level driver of state change */ 233842104Sphk if (sp->pp_chg) 233942104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 234042104Sphk 234125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 234225944Sjoerg /* if no NCP is starting, close down */ 234330300Sjoerg sppp_lcp_check_and_close(sp); 234425944Sjoerg} 234525944Sjoerg 234625944Sjoergstatic void 234725944Sjoergsppp_lcp_tld(struct sppp *sp) 234825944Sjoerg{ 234942066Sphk STDDCL; 235025944Sjoerg int i; 235125944Sjoerg u_long mask; 235225944Sjoerg 235325944Sjoerg sp->pp_phase = PHASE_TERMINATE; 235425944Sjoerg 235542066Sphk if (debug) 235642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 235742066Sphk sppp_phase_name(sp->pp_phase)); 235825944Sjoerg 235925944Sjoerg /* 236025944Sjoerg * Take upper layers down. We send the Down event first and 236125944Sjoerg * the Close second to prevent the upper layers from sending 236225944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 236325944Sjoerg * describes it. 236425944Sjoerg */ 236525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 236625944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 236725944Sjoerg (cps[i])->Down(sp); 236825944Sjoerg (cps[i])->Close(sp); 236925944Sjoerg } 237025944Sjoerg} 237125944Sjoerg 237225944Sjoergstatic void 237325944Sjoergsppp_lcp_tls(struct sppp *sp) 237425944Sjoerg{ 237542066Sphk STDDCL; 237625944Sjoerg 237725944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 237825944Sjoerg 237942066Sphk if (debug) 238042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 238142066Sphk sppp_phase_name(sp->pp_phase)); 238225944Sjoerg 238325944Sjoerg /* Notify lower layer if desired. */ 238425944Sjoerg if (sp->pp_tls) 238525944Sjoerg (sp->pp_tls)(sp); 238641881Sphk else 238741881Sphk (sp->pp_up)(sp); 238825944Sjoerg} 238925944Sjoerg 239025944Sjoergstatic void 239125944Sjoergsppp_lcp_tlf(struct sppp *sp) 239225944Sjoerg{ 239342066Sphk STDDCL; 239425944Sjoerg 239525944Sjoerg sp->pp_phase = PHASE_DEAD; 239642066Sphk if (debug) 239742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 239842066Sphk sppp_phase_name(sp->pp_phase)); 239925944Sjoerg 240025944Sjoerg /* Notify lower layer if desired. */ 240125944Sjoerg if (sp->pp_tlf) 240225944Sjoerg (sp->pp_tlf)(sp); 240341881Sphk else 240441881Sphk (sp->pp_down)(sp); 240525944Sjoerg} 240625944Sjoerg 240725944Sjoergstatic void 240825944Sjoergsppp_lcp_scr(struct sppp *sp) 240925944Sjoerg{ 241030300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 241125944Sjoerg int i = 0; 241230300Sjoerg u_short authproto; 241325944Sjoerg 241425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 241525944Sjoerg if (! sp->lcp.magic) 241642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 241735064Sphk sp->lcp.magic = random(); 241840008Sjoerg#else 241940008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 242040008Sjoerg#endif 242125944Sjoerg opt[i++] = LCP_OPT_MAGIC; 242225944Sjoerg opt[i++] = 6; 242325944Sjoerg opt[i++] = sp->lcp.magic >> 24; 242425944Sjoerg opt[i++] = sp->lcp.magic >> 16; 242525944Sjoerg opt[i++] = sp->lcp.magic >> 8; 242625944Sjoerg opt[i++] = sp->lcp.magic; 242725944Sjoerg } 242825944Sjoerg 242925944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 243025944Sjoerg opt[i++] = LCP_OPT_MRU; 243125944Sjoerg opt[i++] = 4; 243225944Sjoerg opt[i++] = sp->lcp.mru >> 8; 243325944Sjoerg opt[i++] = sp->lcp.mru; 243425944Sjoerg } 243525944Sjoerg 243630300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 243730300Sjoerg authproto = sp->hisauth.proto; 243830300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 243930300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 244030300Sjoerg opt[i++] = authproto >> 8; 244130300Sjoerg opt[i++] = authproto; 244230300Sjoerg if (authproto == PPP_CHAP) 244330300Sjoerg opt[i++] = CHAP_MD5; 244430300Sjoerg } 244530300Sjoerg 244625944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 244725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 244825944Sjoerg} 244925944Sjoerg 245025944Sjoerg/* 245130300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 245230300Sjoerg */ 245330300Sjoergstatic int 245430300Sjoergsppp_ncp_check(struct sppp *sp) 245530300Sjoerg{ 245630300Sjoerg int i, mask; 245730300Sjoerg 245830300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 245930300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 246030300Sjoerg return 1; 246130300Sjoerg return 0; 246230300Sjoerg} 246330300Sjoerg 246430300Sjoerg/* 246525944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 246625944Sjoerg * Called by the NCPs during their tlf action handling. 246725944Sjoerg */ 246825944Sjoergstatic void 246930300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 247025944Sjoerg{ 247125944Sjoerg 247230300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 247330300Sjoerg /* don't bother, we are already going down */ 247430300Sjoerg return; 247530300Sjoerg 247630300Sjoerg if (sppp_ncp_check(sp)) 247730300Sjoerg return; 247830300Sjoerg 247925944Sjoerg lcp.Close(sp); 248025944Sjoerg} 248125944Sjoerg/* 248225944Sjoerg *--------------------------------------------------------------------------* 248325944Sjoerg * * 248425944Sjoerg * The IPCP implementation. * 248525944Sjoerg * * 248625944Sjoerg *--------------------------------------------------------------------------* 248725944Sjoerg */ 248825944Sjoerg 248925944Sjoergstatic void 249025944Sjoergsppp_ipcp_init(struct sppp *sp) 249125944Sjoerg{ 249225944Sjoerg sp->ipcp.opts = 0; 249325944Sjoerg sp->ipcp.flags = 0; 249425944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 249525944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 249642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 249729681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 249840008Sjoerg#endif 249925944Sjoerg} 250025944Sjoerg 250125944Sjoergstatic void 250225944Sjoergsppp_ipcp_up(struct sppp *sp) 250325944Sjoerg{ 250425944Sjoerg sppp_up_event(&ipcp, sp); 250525944Sjoerg} 250625944Sjoerg 250725944Sjoergstatic void 250825944Sjoergsppp_ipcp_down(struct sppp *sp) 250925944Sjoerg{ 251025944Sjoerg sppp_down_event(&ipcp, sp); 251125944Sjoerg} 251225944Sjoerg 251325944Sjoergstatic void 251425944Sjoergsppp_ipcp_open(struct sppp *sp) 251525944Sjoerg{ 251625944Sjoerg STDDCL; 251725944Sjoerg u_long myaddr, hisaddr; 251825944Sjoerg 251942104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 252042104Sphk 252130300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 252225944Sjoerg /* 252325944Sjoerg * If we don't have his address, this probably means our 252425944Sjoerg * interface doesn't want to talk IP at all. (This could 252525944Sjoerg * be the case if somebody wants to speak only IPX, for 252625944Sjoerg * example.) Don't open IPCP in this case. 252725944Sjoerg */ 252825944Sjoerg if (hisaddr == 0L) { 252925944Sjoerg /* XXX this message should go away */ 253025944Sjoerg if (debug) 253140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 253240008Sjoerg SPP_ARGS(ifp)); 253325944Sjoerg return; 253425944Sjoerg } 253525944Sjoerg 253625944Sjoerg if (myaddr == 0L) { 253725944Sjoerg /* 253825944Sjoerg * I don't have an assigned address, so i need to 253925944Sjoerg * negotiate my address. 254025944Sjoerg */ 254125944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 254225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 254342104Sphk } else 254442104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 254525944Sjoerg sppp_open_event(&ipcp, sp); 254625944Sjoerg} 254725944Sjoerg 254825944Sjoergstatic void 254925944Sjoergsppp_ipcp_close(struct sppp *sp) 255025944Sjoerg{ 255125944Sjoerg sppp_close_event(&ipcp, sp); 255225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 255325944Sjoerg /* 255425944Sjoerg * My address was dynamic, clear it again. 255525944Sjoerg */ 255625944Sjoerg sppp_set_ip_addr(sp, 0L); 255725944Sjoerg} 255825944Sjoerg 255925944Sjoergstatic void 256025944Sjoergsppp_ipcp_TO(void *cookie) 256125944Sjoerg{ 256225944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 256325944Sjoerg} 256425944Sjoerg 256525944Sjoerg/* 256625944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 256725944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 256825944Sjoerg * caused action scn. (The return value is used to make the state 256925944Sjoerg * transition decision in the state automaton.) 257025944Sjoerg */ 257125944Sjoergstatic int 257225944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 257325944Sjoerg{ 257425944Sjoerg u_char *buf, *r, *p; 257525944Sjoerg struct ifnet *ifp = &sp->pp_if; 257625944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 257725944Sjoerg u_long hisaddr, desiredaddr; 257842104Sphk int gotmyaddr = 0; 257925944Sjoerg 258025944Sjoerg len -= 4; 258125944Sjoerg origlen = len; 258225944Sjoerg /* 258325944Sjoerg * Make sure to allocate a buf that can at least hold a 258425944Sjoerg * conf-nak with an `address' option. We might need it below. 258525944Sjoerg */ 258625944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 258725944Sjoerg if (! buf) 258825944Sjoerg return (0); 258925944Sjoerg 259025944Sjoerg /* pass 1: see if we can recognize them */ 259125944Sjoerg if (debug) 259240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 259340008Sjoerg SPP_ARGS(ifp)); 259425944Sjoerg p = (void*) (h+1); 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: 260025944Sjoerg if (len >= 6 && p[1] == 6) { 260125944Sjoerg /* correctly formed address option */ 260225944Sjoerg continue; 260325944Sjoerg } 260425706Sjoerg if (debug) 260525944Sjoerg addlog("[invalid] "); 260611189Sjkh break; 260725944Sjoerg default: 260825944Sjoerg /* Others not supported. */ 260925944Sjoerg if (debug) 261025944Sjoerg addlog("[rej] "); 26114910Swollman break; 26124910Swollman } 261325944Sjoerg /* Add the option to rejected list. */ 261425944Sjoerg bcopy (p, r, p[1]); 261525944Sjoerg r += p[1]; 261625944Sjoerg rlen += p[1]; 261725944Sjoerg } 261825944Sjoerg if (rlen) { 261925944Sjoerg if (debug) 262025944Sjoerg addlog(" send conf-rej\n"); 262125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 262225944Sjoerg return 0; 262325944Sjoerg } else if (debug) 262425944Sjoerg addlog("\n"); 262525944Sjoerg 262625944Sjoerg /* pass 2: parse option values */ 262730300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 262825944Sjoerg if (debug) 262940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 263040008Sjoerg SPP_ARGS(ifp)); 263125944Sjoerg p = (void*) (h+1); 263225944Sjoerg len = origlen; 263325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 263425944Sjoerg if (debug) 263525944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 263625944Sjoerg switch (*p) { 263725944Sjoerg case IPCP_OPT_ADDRESS: 263842104Sphk /* This is the address he wants in his end */ 263925944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 264025944Sjoerg p[4] << 8 | p[5]; 264133928Sphk if (desiredaddr == hisaddr || 264242104Sphk (hisaddr == 1 && desiredaddr != 0)) { 264325944Sjoerg /* 264425944Sjoerg * Peer's address is same as our value, 264533928Sphk * or we have set it to 0.0.0.1 to 264633928Sphk * indicate that we do not really care, 264725944Sjoerg * this is agreeable. Gonna conf-ack 264825944Sjoerg * it. 264925944Sjoerg */ 265025944Sjoerg if (debug) 265130300Sjoerg addlog("%s [ack] ", 265242104Sphk sppp_dotted_quad(hisaddr)); 265325944Sjoerg /* record that we've seen it already */ 265425944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 265525944Sjoerg continue; 265625944Sjoerg } 265725944Sjoerg /* 265825944Sjoerg * The address wasn't agreeable. This is either 265925944Sjoerg * he sent us 0.0.0.0, asking to assign him an 266025944Sjoerg * address, or he send us another address not 266125944Sjoerg * matching our value. Either case, we gonna 266225944Sjoerg * conf-nak it with our value. 266342104Sphk * XXX: we should "rej" if hisaddr == 0 266425944Sjoerg */ 266525944Sjoerg if (debug) { 266625944Sjoerg if (desiredaddr == 0) 266725944Sjoerg addlog("[addr requested] "); 266825944Sjoerg else 266930300Sjoerg addlog("%s [not agreed] ", 267042104Sphk sppp_dotted_quad(desiredaddr)); 267125944Sjoerg 267225944Sjoerg } 267344235Sphk p[2] = hisaddr >> 24; 267444235Sphk p[3] = hisaddr >> 16; 267544235Sphk p[4] = hisaddr >> 8; 267644235Sphk p[5] = hisaddr; 267711189Sjkh break; 267825706Sjoerg } 267925944Sjoerg /* Add the option to nak'ed list. */ 268025944Sjoerg bcopy (p, r, p[1]); 268125944Sjoerg r += p[1]; 268225944Sjoerg rlen += p[1]; 268325944Sjoerg } 268425944Sjoerg 268525944Sjoerg /* 268625944Sjoerg * If we are about to conf-ack the request, but haven't seen 268725944Sjoerg * his address so far, gonna conf-nak it instead, with the 268825944Sjoerg * `address' option present and our idea of his address being 268925944Sjoerg * filled in there, to request negotiation of both addresses. 269025944Sjoerg * 269125944Sjoerg * XXX This can result in an endless req - nak loop if peer 269225944Sjoerg * doesn't want to send us his address. Q: What should we do 269325944Sjoerg * about it? XXX A: implement the max-failure counter. 269425944Sjoerg */ 269542104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 269625944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 269725944Sjoerg buf[1] = 6; 269825944Sjoerg buf[2] = hisaddr >> 24; 269925944Sjoerg buf[3] = hisaddr >> 16; 270025944Sjoerg buf[4] = hisaddr >> 8; 270125944Sjoerg buf[5] = hisaddr; 270225944Sjoerg rlen = 6; 270325706Sjoerg if (debug) 270425944Sjoerg addlog("still need hisaddr "); 270525944Sjoerg } 270625944Sjoerg 270725944Sjoerg if (rlen) { 270825706Sjoerg if (debug) 270925944Sjoerg addlog(" send conf-nak\n"); 271025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 271125944Sjoerg } else { 271225706Sjoerg if (debug) 271325944Sjoerg addlog(" send conf-ack\n"); 271425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 271525944Sjoerg h->ident, origlen, h+1); 271625944Sjoerg } 271725944Sjoerg 271825944Sjoerg free (buf, M_TEMP); 271925944Sjoerg return (rlen == 0); 272025944Sjoerg} 272125944Sjoerg 272225944Sjoerg/* 272325944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 272425944Sjoerg * negotiation. 272525944Sjoerg */ 272625944Sjoergstatic void 272725944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 272825944Sjoerg{ 272925944Sjoerg u_char *buf, *p; 273025944Sjoerg struct ifnet *ifp = &sp->pp_if; 273125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 273225944Sjoerg 273325944Sjoerg len -= 4; 273425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 273525944Sjoerg if (!buf) 273625944Sjoerg return; 273725944Sjoerg 273825944Sjoerg if (debug) 273940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 274040008Sjoerg SPP_ARGS(ifp)); 274125944Sjoerg 274225944Sjoerg p = (void*) (h+1); 274325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 274425706Sjoerg if (debug) 274525944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 274625944Sjoerg switch (*p) { 274725944Sjoerg case IPCP_OPT_ADDRESS: 274825944Sjoerg /* 274925944Sjoerg * Peer doesn't grok address option. This is 275025944Sjoerg * bad. XXX Should we better give up here? 275142104Sphk * XXX We could try old "addresses" option... 275225944Sjoerg */ 275325944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 275425944Sjoerg break; 275525944Sjoerg } 27564910Swollman } 275725944Sjoerg if (debug) 275825944Sjoerg addlog("\n"); 275925944Sjoerg free (buf, M_TEMP); 276025944Sjoerg return; 27614910Swollman} 27624910Swollman 276325944Sjoerg/* 276425944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 276525944Sjoerg * negotiation. 276625944Sjoerg */ 276712820Sphkstatic void 276825944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 27694910Swollman{ 277025944Sjoerg u_char *buf, *p; 277125944Sjoerg struct ifnet *ifp = &sp->pp_if; 277225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 277325944Sjoerg u_long wantaddr; 27744910Swollman 277525944Sjoerg len -= 4; 277625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 277725944Sjoerg if (!buf) 277825944Sjoerg return; 277925944Sjoerg 278025944Sjoerg if (debug) 278140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 278240008Sjoerg SPP_ARGS(ifp)); 278325944Sjoerg 278425944Sjoerg p = (void*) (h+1); 278525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 278625944Sjoerg if (debug) 278725944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 278825944Sjoerg switch (*p) { 278925944Sjoerg case IPCP_OPT_ADDRESS: 279025944Sjoerg /* 279125944Sjoerg * Peer doesn't like our local IP address. See 279225944Sjoerg * if we can do something for him. We'll drop 279325944Sjoerg * him our address then. 279425944Sjoerg */ 279525944Sjoerg if (len >= 6 && p[1] == 6) { 279625944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 279725944Sjoerg p[4] << 8 | p[5]; 279825944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 279925944Sjoerg if (debug) 280030300Sjoerg addlog("[wantaddr %s] ", 280130300Sjoerg sppp_dotted_quad(wantaddr)); 280225944Sjoerg /* 280325944Sjoerg * When doing dynamic address assignment, 280425944Sjoerg * we accept his offer. Otherwise, we 280525944Sjoerg * ignore it and thus continue to negotiate 280625944Sjoerg * our already existing value. 280742104Sphk * XXX: Bogus, if he said no once, he'll 280842104Sphk * just say no again, might as well die. 280925944Sjoerg */ 281025944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 281125944Sjoerg sppp_set_ip_addr(sp, wantaddr); 281225944Sjoerg if (debug) 281325944Sjoerg addlog("[agree] "); 281442104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 281525944Sjoerg } 281625944Sjoerg } 281725944Sjoerg break; 281825944Sjoerg } 281925944Sjoerg } 282025944Sjoerg if (debug) 282125944Sjoerg addlog("\n"); 282225944Sjoerg free (buf, M_TEMP); 282325944Sjoerg return; 28244910Swollman} 28254910Swollman 282612820Sphkstatic void 282725944Sjoergsppp_ipcp_tlu(struct sppp *sp) 28284910Swollman{ 282942104Sphk /* we are up - notify isdn daemon */ 283042104Sphk if (sp->pp_con) 283142104Sphk sp->pp_con(sp); 28324910Swollman} 28334910Swollman 283425944Sjoergstatic void 283525944Sjoergsppp_ipcp_tld(struct sppp *sp) 283625944Sjoerg{ 283725944Sjoerg} 283825944Sjoerg 283925944Sjoergstatic void 284025944Sjoergsppp_ipcp_tls(struct sppp *sp) 284125944Sjoerg{ 284225944Sjoerg /* indicate to LCP that it must stay alive */ 284325944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 284425944Sjoerg} 284525944Sjoerg 284625944Sjoergstatic void 284725944Sjoergsppp_ipcp_tlf(struct sppp *sp) 284825944Sjoerg{ 284925944Sjoerg /* we no longer need LCP */ 285025944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 285130300Sjoerg sppp_lcp_check_and_close(sp); 285225944Sjoerg} 285325944Sjoerg 285425944Sjoergstatic void 285525944Sjoergsppp_ipcp_scr(struct sppp *sp) 285625944Sjoerg{ 285725944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 285825944Sjoerg u_long ouraddr; 285925944Sjoerg int i = 0; 286025944Sjoerg 286125944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 286230300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 286325944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 286425944Sjoerg opt[i++] = 6; 286525944Sjoerg opt[i++] = ouraddr >> 24; 286625944Sjoerg opt[i++] = ouraddr >> 16; 286725944Sjoerg opt[i++] = ouraddr >> 8; 286825944Sjoerg opt[i++] = ouraddr; 286925944Sjoerg } 287025944Sjoerg 287125944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 287225944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 287325944Sjoerg} 287425944Sjoerg 287525944Sjoerg 287625944Sjoerg/* 287730300Sjoerg *--------------------------------------------------------------------------* 287830300Sjoerg * * 287930300Sjoerg * The CHAP implementation. * 288030300Sjoerg * * 288130300Sjoerg *--------------------------------------------------------------------------* 288230300Sjoerg */ 288330300Sjoerg 288430300Sjoerg/* 288530300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 288630300Sjoerg * the control protocols do, since they do have Open and Close events, but 288730300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 288830300Sjoerg * authentication protocols may be different in both directions (this makes 288930300Sjoerg * sense, think of a machine that never accepts incoming calls but only 289030300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 289130300Sjoerg * 289230300Sjoerg * Our state machine for the local authentication protocol (we are requesting 289330300Sjoerg * the peer to authenticate) looks like: 289430300Sjoerg * 289530300Sjoerg * RCA- 289630300Sjoerg * +--------------------------------------------+ 289730300Sjoerg * V scn,tld| 289830300Sjoerg * +--------+ Close +---------+ RCA+ 289930300Sjoerg * | |<----------------------------------| |------+ 290030300Sjoerg * +--->| Closed | TO* | Opened | sca | 290130300Sjoerg * | | |-----+ +-------| |<-----+ 290230300Sjoerg * | +--------+ irc | | +---------+ 290330300Sjoerg * | ^ | | ^ 290430300Sjoerg * | | | | | 290530300Sjoerg * | | | | | 290630300Sjoerg * | TO-| | | | 290730300Sjoerg * | |tld TO+ V | | 290830300Sjoerg * | | +------->+ | | 290930300Sjoerg * | | | | | | 291030300Sjoerg * | +--------+ V | | 291130300Sjoerg * | | |<----+<--------------------+ | 291230300Sjoerg * | | Req- | scr | 291330300Sjoerg * | | Sent | | 291430300Sjoerg * | | | | 291530300Sjoerg * | +--------+ | 291630300Sjoerg * | RCA- | | RCA+ | 291730300Sjoerg * +------+ +------------------------------------------+ 291830300Sjoerg * scn,tld sca,irc,ict,tlu 291930300Sjoerg * 292030300Sjoerg * 292130300Sjoerg * with: 292230300Sjoerg * 292330300Sjoerg * Open: LCP reached authentication phase 292430300Sjoerg * Close: LCP reached terminate phase 292530300Sjoerg * 292630300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 292730300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 292830300Sjoerg * TO+: timeout with restart counter >= 0 292930300Sjoerg * TO-: timeout with restart counter < 0 293030300Sjoerg * TO*: reschedule timeout for CHAP 293130300Sjoerg * 293230300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 293330300Sjoerg * sca: send ack packet (pap-ack, chap-success) 293430300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 293530300Sjoerg * ict: initialize re-challenge timer (CHAP only) 293630300Sjoerg * 293730300Sjoerg * tlu: this-layer-up, LCP reaches network phase 293830300Sjoerg * tld: this-layer-down, LCP enters terminate phase 293930300Sjoerg * 294030300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 294130300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 294230300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 294330300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 294430300Sjoerg * causing LCP to enter terminate phase. 294530300Sjoerg * 294630300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 294730300Sjoerg * expected to send one based on the successful negotiation of PAP as 294830300Sjoerg * the authentication protocol during the LCP option negotiation. 294930300Sjoerg * 295030300Sjoerg * Incoming authentication protocol requests (remote requests 295130300Sjoerg * authentication, we are peer) don't employ a state machine at all, 295230300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 295330300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 295430300Sjoerg * still in authentication phase (thereby violating the standard that 295530300Sjoerg * demands that these NCP packets are to be discarded), so we keep 295630300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 295730300Sjoerg * phase network once we've seen a positive acknowledge for the 295830300Sjoerg * authentication. 295930300Sjoerg */ 296030300Sjoerg 296130300Sjoerg/* 296230300Sjoerg * Handle incoming CHAP packets. 296330300Sjoerg */ 296430300Sjoergvoid 296530300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 296630300Sjoerg{ 296730300Sjoerg STDDCL; 296830300Sjoerg struct lcp_header *h; 296930300Sjoerg int len, x; 297030300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 297130300Sjoerg int value_len, name_len; 297230300Sjoerg MD5_CTX ctx; 297330300Sjoerg 297430300Sjoerg len = m->m_pkthdr.len; 297530300Sjoerg if (len < 4) { 297630300Sjoerg if (debug) 297730300Sjoerg log(LOG_DEBUG, 297840008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 297940008Sjoerg SPP_ARGS(ifp), len); 298030300Sjoerg return; 298130300Sjoerg } 298230300Sjoerg h = mtod (m, struct lcp_header*); 298330300Sjoerg if (len > ntohs (h->len)) 298430300Sjoerg len = ntohs (h->len); 298530300Sjoerg 298630300Sjoerg switch (h->type) { 298730300Sjoerg /* challenge, failure and success are his authproto */ 298830300Sjoerg case CHAP_CHALLENGE: 298930300Sjoerg value = 1 + (u_char*)(h+1); 299030300Sjoerg value_len = value[-1]; 299130300Sjoerg name = value + value_len; 299230300Sjoerg name_len = len - value_len - 5; 299330300Sjoerg if (name_len < 0) { 299430300Sjoerg if (debug) { 299530300Sjoerg log(LOG_DEBUG, 299640008Sjoerg SPP_FMT "chap corrupted challenge " 299730300Sjoerg "<%s id=0x%x len=%d", 299840008Sjoerg SPP_ARGS(ifp), 299930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 300030300Sjoerg h->ident, ntohs(h->len)); 300144145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 300230300Sjoerg addlog(">\n"); 300330300Sjoerg } 300430300Sjoerg break; 300530300Sjoerg } 300630300Sjoerg 300730300Sjoerg if (debug) { 300830300Sjoerg log(LOG_DEBUG, 300940008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 301040008Sjoerg SPP_ARGS(ifp), 301130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 301230300Sjoerg ntohs(h->len)); 301330300Sjoerg sppp_print_string((char*) name, name_len); 301430300Sjoerg addlog(" value-size=%d value=", value_len); 301530300Sjoerg sppp_print_bytes(value, value_len); 301630300Sjoerg addlog(">\n"); 301730300Sjoerg } 301830300Sjoerg 301930300Sjoerg /* Compute reply value. */ 302030300Sjoerg MD5Init(&ctx); 302130300Sjoerg MD5Update(&ctx, &h->ident, 1); 302230300Sjoerg MD5Update(&ctx, sp->myauth.secret, 302330300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 302430300Sjoerg MD5Update(&ctx, value, value_len); 302530300Sjoerg MD5Final(digest, &ctx); 302630300Sjoerg dsize = sizeof digest; 302730300Sjoerg 302830300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 302930300Sjoerg sizeof dsize, (const char *)&dsize, 303030300Sjoerg sizeof digest, digest, 303140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 303230300Sjoerg sp->myauth.name, 303330300Sjoerg 0); 303430300Sjoerg break; 303530300Sjoerg 303630300Sjoerg case CHAP_SUCCESS: 303730300Sjoerg if (debug) { 303840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 303940008Sjoerg SPP_ARGS(ifp)); 304030300Sjoerg if (len > 4) { 304130300Sjoerg addlog(": "); 304230300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 304330300Sjoerg } 304430300Sjoerg addlog("\n"); 304530300Sjoerg } 304630300Sjoerg x = splimp(); 304730300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 304830300Sjoerg if (sp->myauth.proto == PPP_CHAP && 304932169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 305030300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 305130300Sjoerg /* 305230300Sjoerg * We are authenticator for CHAP but didn't 305330300Sjoerg * complete yet. Leave it to tlu to proceed 305430300Sjoerg * to network phase. 305530300Sjoerg */ 305630300Sjoerg splx(x); 305730300Sjoerg break; 305830300Sjoerg } 305930300Sjoerg splx(x); 306030300Sjoerg sppp_phase_network(sp); 306130300Sjoerg break; 306230300Sjoerg 306330300Sjoerg case CHAP_FAILURE: 306430300Sjoerg if (debug) { 306540008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 306640008Sjoerg SPP_ARGS(ifp)); 306730300Sjoerg if (len > 4) { 306830300Sjoerg addlog(": "); 306930300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 307030300Sjoerg } 307130300Sjoerg addlog("\n"); 307230300Sjoerg } else 307340008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 307440008Sjoerg SPP_ARGS(ifp)); 307530300Sjoerg /* await LCP shutdown by authenticator */ 307630300Sjoerg break; 307730300Sjoerg 307830300Sjoerg /* response is my authproto */ 307930300Sjoerg case CHAP_RESPONSE: 308030300Sjoerg value = 1 + (u_char*)(h+1); 308130300Sjoerg value_len = value[-1]; 308230300Sjoerg name = value + value_len; 308330300Sjoerg name_len = len - value_len - 5; 308430300Sjoerg if (name_len < 0) { 308530300Sjoerg if (debug) { 308630300Sjoerg log(LOG_DEBUG, 308740008Sjoerg SPP_FMT "chap corrupted response " 308830300Sjoerg "<%s id=0x%x len=%d", 308940008Sjoerg SPP_ARGS(ifp), 309030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 309130300Sjoerg h->ident, ntohs(h->len)); 309244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 309330300Sjoerg addlog(">\n"); 309430300Sjoerg } 309530300Sjoerg break; 309630300Sjoerg } 309730300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 309830300Sjoerg if (debug) 309930300Sjoerg log(LOG_DEBUG, 310040008Sjoerg SPP_FMT "chap dropping response for old ID " 310130300Sjoerg "(got %d, expected %d)\n", 310240008Sjoerg SPP_ARGS(ifp), 310330300Sjoerg h->ident, sp->confid[IDX_CHAP]); 310430300Sjoerg break; 310530300Sjoerg } 310630300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 310730300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 310840008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 310940008Sjoerg SPP_ARGS(ifp)); 311030300Sjoerg sppp_print_string(name, name_len); 311130300Sjoerg addlog(" != expected "); 311230300Sjoerg sppp_print_string(sp->hisauth.name, 311330300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 311430300Sjoerg addlog("\n"); 311530300Sjoerg } 311630300Sjoerg if (debug) { 311740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 311830300Sjoerg "<%s id=0x%x len=%d name=", 311940008Sjoerg SPP_ARGS(ifp), 312030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 312130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 312230300Sjoerg h->ident, ntohs (h->len)); 312330300Sjoerg sppp_print_string((char*)name, name_len); 312430300Sjoerg addlog(" value-size=%d value=", value_len); 312530300Sjoerg sppp_print_bytes(value, value_len); 312630300Sjoerg addlog(">\n"); 312730300Sjoerg } 312830300Sjoerg if (value_len != AUTHKEYLEN) { 312930300Sjoerg if (debug) 313030300Sjoerg log(LOG_DEBUG, 313140008Sjoerg SPP_FMT "chap bad hash value length: " 313230300Sjoerg "%d bytes, should be %d\n", 313340008Sjoerg SPP_ARGS(ifp), value_len, 313430300Sjoerg AUTHKEYLEN); 313530300Sjoerg break; 313630300Sjoerg } 313730300Sjoerg 313830300Sjoerg MD5Init(&ctx); 313930300Sjoerg MD5Update(&ctx, &h->ident, 1); 314030300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 314130300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 314230300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 314330300Sjoerg MD5Final(digest, &ctx); 314430300Sjoerg 314530300Sjoerg#define FAILMSG "Failed..." 314630300Sjoerg#define SUCCMSG "Welcome!" 314730300Sjoerg 314830300Sjoerg if (value_len != sizeof digest || 314930300Sjoerg bcmp(digest, value, value_len) != 0) { 315030300Sjoerg /* action scn, tld */ 315130300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 315230300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 315330300Sjoerg 0); 315430300Sjoerg chap.tld(sp); 315530300Sjoerg break; 315630300Sjoerg } 315730300Sjoerg /* action sca, perhaps tlu */ 315830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 315930300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 316030300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 316130300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 316230300Sjoerg 0); 316330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 316430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 316530300Sjoerg chap.tlu(sp); 316630300Sjoerg } 316730300Sjoerg break; 316830300Sjoerg 316930300Sjoerg default: 317030300Sjoerg /* Unknown CHAP packet type -- ignore. */ 317130300Sjoerg if (debug) { 317240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 317330300Sjoerg "<0x%x id=0x%xh len=%d", 317440008Sjoerg SPP_ARGS(ifp), 317530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 317630300Sjoerg h->type, h->ident, ntohs(h->len)); 317744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 317830300Sjoerg addlog(">\n"); 317930300Sjoerg } 318030300Sjoerg break; 318130300Sjoerg 318230300Sjoerg } 318330300Sjoerg} 318430300Sjoerg 318530300Sjoergstatic void 318630300Sjoergsppp_chap_init(struct sppp *sp) 318730300Sjoerg{ 318830300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 318930300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 319030300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 319142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 319230300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 319340008Sjoerg#endif 319430300Sjoerg} 319530300Sjoerg 319630300Sjoergstatic void 319730300Sjoergsppp_chap_open(struct sppp *sp) 319830300Sjoerg{ 319930300Sjoerg if (sp->myauth.proto == PPP_CHAP && 320030300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 320130300Sjoerg /* we are authenticator for CHAP, start it */ 320230300Sjoerg chap.scr(sp); 320330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 320430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 320530300Sjoerg } 320630300Sjoerg /* nothing to be done if we are peer, await a challenge */ 320730300Sjoerg} 320830300Sjoerg 320930300Sjoergstatic void 321030300Sjoergsppp_chap_close(struct sppp *sp) 321130300Sjoerg{ 321230300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 321330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 321430300Sjoerg} 321530300Sjoerg 321630300Sjoergstatic void 321730300Sjoergsppp_chap_TO(void *cookie) 321830300Sjoerg{ 321930300Sjoerg struct sppp *sp = (struct sppp *)cookie; 322030300Sjoerg STDDCL; 322130300Sjoerg int s; 322230300Sjoerg 322330300Sjoerg s = splimp(); 322430300Sjoerg if (debug) 322540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 322640008Sjoerg SPP_ARGS(ifp), 322730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 322830300Sjoerg sp->rst_counter[IDX_CHAP]); 322930300Sjoerg 323030300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 323130300Sjoerg /* TO- event */ 323230300Sjoerg switch (sp->state[IDX_CHAP]) { 323330300Sjoerg case STATE_REQ_SENT: 323430300Sjoerg chap.tld(sp); 323530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 323630300Sjoerg break; 323730300Sjoerg } 323830300Sjoerg else 323930300Sjoerg /* TO+ (or TO*) event */ 324030300Sjoerg switch (sp->state[IDX_CHAP]) { 324130300Sjoerg case STATE_OPENED: 324230300Sjoerg /* TO* event */ 324330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 324430300Sjoerg /* fall through */ 324530300Sjoerg case STATE_REQ_SENT: 324630300Sjoerg chap.scr(sp); 324730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 324830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 324930300Sjoerg break; 325030300Sjoerg } 325130300Sjoerg 325230300Sjoerg splx(s); 325330300Sjoerg} 325430300Sjoerg 325530300Sjoergstatic void 325630300Sjoergsppp_chap_tlu(struct sppp *sp) 325730300Sjoerg{ 325830300Sjoerg STDDCL; 325930300Sjoerg int i, x; 326030300Sjoerg 326140010Sjoerg i = 0; 326230300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 326330300Sjoerg 326430300Sjoerg /* 326530300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 326630300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 326730300Sjoerg * initial challenge-response exchange has taken place. 326830300Sjoerg * Provide for an option to avoid rechallenges. 326930300Sjoerg */ 327030300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 327130300Sjoerg /* 327230300Sjoerg * Compute the re-challenge timeout. This will yield 327330300Sjoerg * a number between 300 and 810 seconds. 327430300Sjoerg */ 327530300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 327642064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 327730300Sjoerg } 327830300Sjoerg 327930300Sjoerg if (debug) { 328030300Sjoerg log(LOG_DEBUG, 328140008Sjoerg SPP_FMT "chap %s, ", 328240008Sjoerg SPP_ARGS(ifp), 328330300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 328430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 328530300Sjoerg addlog("next re-challenge in %d seconds\n", i); 328630300Sjoerg else 328730300Sjoerg addlog("re-challenging supressed\n"); 328830300Sjoerg } 328930300Sjoerg 329030300Sjoerg x = splimp(); 329130300Sjoerg /* indicate to LCP that we need to be closed down */ 329230300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 329330300Sjoerg 329430300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 329530300Sjoerg /* 329630300Sjoerg * Remote is authenticator, but his auth proto didn't 329730300Sjoerg * complete yet. Defer the transition to network 329830300Sjoerg * phase. 329930300Sjoerg */ 330030300Sjoerg splx(x); 330130300Sjoerg return; 330230300Sjoerg } 330330300Sjoerg splx(x); 330430300Sjoerg 330530300Sjoerg /* 330630300Sjoerg * If we are already in phase network, we are done here. This 330730300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 330830300Sjoerg */ 330930300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 331030300Sjoerg sppp_phase_network(sp); 331130300Sjoerg} 331230300Sjoerg 331330300Sjoergstatic void 331430300Sjoergsppp_chap_tld(struct sppp *sp) 331530300Sjoerg{ 331630300Sjoerg STDDCL; 331730300Sjoerg 331830300Sjoerg if (debug) 331940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 332040008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 332130300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 332230300Sjoerg 332330300Sjoerg lcp.Close(sp); 332430300Sjoerg} 332530300Sjoerg 332630300Sjoergstatic void 332730300Sjoergsppp_chap_scr(struct sppp *sp) 332830300Sjoerg{ 332930300Sjoerg u_long *ch, seed; 333030300Sjoerg u_char clen; 333130300Sjoerg 333230300Sjoerg /* Compute random challenge. */ 333330300Sjoerg ch = (u_long *)sp->myauth.challenge; 333442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 333535064Sphk read_random(&seed, sizeof seed); 333640008Sjoerg#else 333742104Sphk { 333842104Sphk struct timeval tv; 333940008Sjoerg microtime(&tv); 334040008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 334142104Sphk } 334240008Sjoerg#endif 334330300Sjoerg ch[0] = seed ^ random(); 334430300Sjoerg ch[1] = seed ^ random(); 334530300Sjoerg ch[2] = seed ^ random(); 334630300Sjoerg ch[3] = seed ^ random(); 334730300Sjoerg clen = AUTHKEYLEN; 334830300Sjoerg 334930300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 335030300Sjoerg 335130300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 335230300Sjoerg sizeof clen, (const char *)&clen, 335340008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 335440008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 335530300Sjoerg sp->myauth.name, 335630300Sjoerg 0); 335730300Sjoerg} 335830300Sjoerg/* 335930300Sjoerg *--------------------------------------------------------------------------* 336030300Sjoerg * * 336130300Sjoerg * The PAP implementation. * 336230300Sjoerg * * 336330300Sjoerg *--------------------------------------------------------------------------* 336430300Sjoerg */ 336530300Sjoerg/* 336630300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 336730300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 336830300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 336930300Sjoerg * retry counter is expired). 337030300Sjoerg */ 337130300Sjoerg 337230300Sjoerg/* 337330300Sjoerg * Handle incoming PAP packets. */ 337430300Sjoergstatic void 337530300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 337630300Sjoerg{ 337730300Sjoerg STDDCL; 337830300Sjoerg struct lcp_header *h; 337930300Sjoerg int len, x; 338030300Sjoerg u_char *name, *passwd, mlen; 338130300Sjoerg int name_len, passwd_len; 338230300Sjoerg 338330300Sjoerg len = m->m_pkthdr.len; 338430300Sjoerg if (len < 5) { 338530300Sjoerg if (debug) 338630300Sjoerg log(LOG_DEBUG, 338740008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 338840008Sjoerg SPP_ARGS(ifp), len); 338930300Sjoerg return; 339030300Sjoerg } 339130300Sjoerg h = mtod (m, struct lcp_header*); 339230300Sjoerg if (len > ntohs (h->len)) 339330300Sjoerg len = ntohs (h->len); 339430300Sjoerg switch (h->type) { 339530300Sjoerg /* PAP request is my authproto */ 339630300Sjoerg case PAP_REQ: 339730300Sjoerg name = 1 + (u_char*)(h+1); 339830300Sjoerg name_len = name[-1]; 339930300Sjoerg passwd = name + name_len + 1; 340030300Sjoerg if (name_len > len - 6 || 340130300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 340230300Sjoerg if (debug) { 340340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 340430300Sjoerg "<%s id=0x%x len=%d", 340540008Sjoerg SPP_ARGS(ifp), 340630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 340730300Sjoerg h->ident, ntohs(h->len)); 340844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 340930300Sjoerg addlog(">\n"); 341030300Sjoerg } 341130300Sjoerg break; 341230300Sjoerg } 341330300Sjoerg if (debug) { 341440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 341530300Sjoerg "<%s id=0x%x len=%d name=", 341640008Sjoerg SPP_ARGS(ifp), 341730300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 341830300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 341930300Sjoerg h->ident, ntohs(h->len)); 342030300Sjoerg sppp_print_string((char*)name, name_len); 342130300Sjoerg addlog(" passwd="); 342230300Sjoerg sppp_print_string((char*)passwd, passwd_len); 342330300Sjoerg addlog(">\n"); 342430300Sjoerg } 342530300Sjoerg if (name_len > AUTHNAMELEN || 342630300Sjoerg passwd_len > AUTHKEYLEN || 342730300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 342830300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 342930300Sjoerg /* action scn, tld */ 343030300Sjoerg mlen = sizeof(FAILMSG) - 1; 343130300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 343230300Sjoerg sizeof mlen, (const char *)&mlen, 343330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 343430300Sjoerg 0); 343530300Sjoerg pap.tld(sp); 343630300Sjoerg break; 343730300Sjoerg } 343830300Sjoerg /* action sca, perhaps tlu */ 343930300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 344030300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 344130300Sjoerg mlen = sizeof(SUCCMSG) - 1; 344230300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 344330300Sjoerg sizeof mlen, (const char *)&mlen, 344430300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 344530300Sjoerg 0); 344630300Sjoerg } 344730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 344830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 344930300Sjoerg pap.tlu(sp); 345030300Sjoerg } 345130300Sjoerg break; 345230300Sjoerg 345330300Sjoerg /* ack and nak are his authproto */ 345430300Sjoerg case PAP_ACK: 345540008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 345630300Sjoerg if (debug) { 345740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 345840008Sjoerg SPP_ARGS(ifp)); 345930300Sjoerg name_len = *((char *)h); 346030300Sjoerg if (len > 5 && name_len) { 346130300Sjoerg addlog(": "); 346230300Sjoerg sppp_print_string((char*)(h+1), name_len); 346330300Sjoerg } 346430300Sjoerg addlog("\n"); 346530300Sjoerg } 346630300Sjoerg x = splimp(); 346730300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 346830300Sjoerg if (sp->myauth.proto == PPP_PAP && 346932169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 347030300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 347130300Sjoerg /* 347230300Sjoerg * We are authenticator for PAP but didn't 347330300Sjoerg * complete yet. Leave it to tlu to proceed 347430300Sjoerg * to network phase. 347530300Sjoerg */ 347630300Sjoerg splx(x); 347730300Sjoerg break; 347830300Sjoerg } 347930300Sjoerg splx(x); 348030300Sjoerg sppp_phase_network(sp); 348130300Sjoerg break; 348230300Sjoerg 348330300Sjoerg case PAP_NAK: 348440008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 348530300Sjoerg if (debug) { 348640008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 348740008Sjoerg SPP_ARGS(ifp)); 348830300Sjoerg name_len = *((char *)h); 348930300Sjoerg if (len > 5 && name_len) { 349030300Sjoerg addlog(": "); 349130300Sjoerg sppp_print_string((char*)(h+1), name_len); 349230300Sjoerg } 349330300Sjoerg addlog("\n"); 349430300Sjoerg } else 349540008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 349640008Sjoerg SPP_ARGS(ifp)); 349730300Sjoerg /* await LCP shutdown by authenticator */ 349830300Sjoerg break; 349930300Sjoerg 350030300Sjoerg default: 350130300Sjoerg /* Unknown PAP packet type -- ignore. */ 350230300Sjoerg if (debug) { 350340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 350430300Sjoerg "<0x%x id=0x%x len=%d", 350540008Sjoerg SPP_ARGS(ifp), 350630300Sjoerg h->type, h->ident, ntohs(h->len)); 350744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 350830300Sjoerg addlog(">\n"); 350930300Sjoerg } 351030300Sjoerg break; 351130300Sjoerg 351230300Sjoerg } 351330300Sjoerg} 351430300Sjoerg 351530300Sjoergstatic void 351630300Sjoergsppp_pap_init(struct sppp *sp) 351730300Sjoerg{ 351830300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 351930300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 352030300Sjoerg sp->fail_counter[IDX_PAP] = 0; 352142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 352230300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 352330300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 352440008Sjoerg#endif 352530300Sjoerg} 352630300Sjoerg 352730300Sjoergstatic void 352830300Sjoergsppp_pap_open(struct sppp *sp) 352930300Sjoerg{ 353030300Sjoerg if (sp->hisauth.proto == PPP_PAP && 353130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 353230300Sjoerg /* we are authenticator for PAP, start our timer */ 353330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 353430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 353530300Sjoerg } 353630300Sjoerg if (sp->myauth.proto == PPP_PAP) { 353730300Sjoerg /* we are peer, send a request, and start a timer */ 353830300Sjoerg pap.scr(sp); 353942064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 354042064Sphk sp->pap_my_to_ch); 354130300Sjoerg } 354230300Sjoerg} 354330300Sjoerg 354430300Sjoergstatic void 354530300Sjoergsppp_pap_close(struct sppp *sp) 354630300Sjoerg{ 354730300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 354830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 354930300Sjoerg} 355030300Sjoerg 355130300Sjoerg/* 355230300Sjoerg * That's the timeout routine if we are authenticator. Since the 355330300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 355430300Sjoerg */ 355530300Sjoergstatic void 355630300Sjoergsppp_pap_TO(void *cookie) 355730300Sjoerg{ 355830300Sjoerg struct sppp *sp = (struct sppp *)cookie; 355930300Sjoerg STDDCL; 356030300Sjoerg int s; 356130300Sjoerg 356230300Sjoerg s = splimp(); 356330300Sjoerg if (debug) 356440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 356540008Sjoerg SPP_ARGS(ifp), 356630300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 356730300Sjoerg sp->rst_counter[IDX_PAP]); 356830300Sjoerg 356930300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 357030300Sjoerg /* TO- event */ 357130300Sjoerg switch (sp->state[IDX_PAP]) { 357230300Sjoerg case STATE_REQ_SENT: 357330300Sjoerg pap.tld(sp); 357430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 357530300Sjoerg break; 357630300Sjoerg } 357730300Sjoerg else 357830300Sjoerg /* TO+ event, not very much we could do */ 357930300Sjoerg switch (sp->state[IDX_PAP]) { 358030300Sjoerg case STATE_REQ_SENT: 358130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 358230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 358330300Sjoerg break; 358430300Sjoerg } 358530300Sjoerg 358630300Sjoerg splx(s); 358730300Sjoerg} 358830300Sjoerg 358930300Sjoerg/* 359030300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 359130300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 359230300Sjoerg * XXX We should impose a max counter. 359330300Sjoerg */ 359430300Sjoergstatic void 359530300Sjoergsppp_pap_my_TO(void *cookie) 359630300Sjoerg{ 359730300Sjoerg struct sppp *sp = (struct sppp *)cookie; 359830300Sjoerg STDDCL; 359930300Sjoerg 360030300Sjoerg if (debug) 360140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 360240008Sjoerg SPP_ARGS(ifp)); 360330300Sjoerg 360430300Sjoerg pap.scr(sp); 360530300Sjoerg} 360630300Sjoerg 360730300Sjoergstatic void 360830300Sjoergsppp_pap_tlu(struct sppp *sp) 360930300Sjoerg{ 361030300Sjoerg STDDCL; 361130300Sjoerg int x; 361230300Sjoerg 361330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 361430300Sjoerg 361530300Sjoerg if (debug) 361640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 361740008Sjoerg SPP_ARGS(ifp), pap.name); 361830300Sjoerg 361930300Sjoerg x = splimp(); 362030300Sjoerg /* indicate to LCP that we need to be closed down */ 362130300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 362230300Sjoerg 362330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 362430300Sjoerg /* 362530300Sjoerg * Remote is authenticator, but his auth proto didn't 362630300Sjoerg * complete yet. Defer the transition to network 362730300Sjoerg * phase. 362830300Sjoerg */ 362930300Sjoerg splx(x); 363030300Sjoerg return; 363130300Sjoerg } 363230300Sjoerg splx(x); 363330300Sjoerg sppp_phase_network(sp); 363430300Sjoerg} 363530300Sjoerg 363630300Sjoergstatic void 363730300Sjoergsppp_pap_tld(struct sppp *sp) 363830300Sjoerg{ 363930300Sjoerg STDDCL; 364030300Sjoerg 364130300Sjoerg if (debug) 364240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 364340008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 364440008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 364530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 364630300Sjoerg 364730300Sjoerg lcp.Close(sp); 364830300Sjoerg} 364930300Sjoerg 365030300Sjoergstatic void 365130300Sjoergsppp_pap_scr(struct sppp *sp) 365230300Sjoerg{ 365330300Sjoerg u_char idlen, pwdlen; 365430300Sjoerg 365530300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 365630300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 365730300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 365830300Sjoerg 365930300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 366030300Sjoerg sizeof idlen, (const char *)&idlen, 366140008Sjoerg (size_t)idlen, sp->myauth.name, 366230300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 366340008Sjoerg (size_t)pwdlen, sp->myauth.secret, 366430300Sjoerg 0); 366530300Sjoerg} 366630300Sjoerg/* 366725944Sjoerg * Random miscellaneous functions. 366825944Sjoerg */ 366925944Sjoerg 36704910Swollman/* 367130300Sjoerg * Send a PAP or CHAP proto packet. 367230300Sjoerg * 367330300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 367440008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 367530300Sjoerg * mlen == 0. 367642104Sphk * NOTE: never declare variadic functions with types subject to type 367742104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 367842104Sphk * on the architecture you are on... 367930300Sjoerg */ 368030300Sjoerg 368130300Sjoergstatic void 368242104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 368342104Sphk unsigned int type, unsigned int id, 368430300Sjoerg ...) 368530300Sjoerg{ 368630300Sjoerg STDDCL; 368730300Sjoerg struct ppp_header *h; 368830300Sjoerg struct lcp_header *lh; 368930300Sjoerg struct mbuf *m; 369030300Sjoerg u_char *p; 369130300Sjoerg int len; 369242104Sphk unsigned int mlen; 369330300Sjoerg const char *msg; 369430300Sjoerg va_list ap; 369530300Sjoerg 369630300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 369730300Sjoerg if (! m) 369830300Sjoerg return; 369930300Sjoerg m->m_pkthdr.rcvif = 0; 370030300Sjoerg 370130300Sjoerg h = mtod (m, struct ppp_header*); 370230300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 370330300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 370430300Sjoerg h->protocol = htons(cp->proto); 370530300Sjoerg 370630300Sjoerg lh = (struct lcp_header*)(h + 1); 370730300Sjoerg lh->type = type; 370830300Sjoerg lh->ident = id; 370930300Sjoerg p = (u_char*) (lh+1); 371030300Sjoerg 371130300Sjoerg va_start(ap, id); 371230300Sjoerg len = 0; 371330300Sjoerg 371442104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 371530300Sjoerg msg = va_arg(ap, const char *); 371630300Sjoerg len += mlen; 371730300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 371830300Sjoerg va_end(ap); 371930300Sjoerg m_freem(m); 372030300Sjoerg return; 372130300Sjoerg } 372230300Sjoerg 372330300Sjoerg bcopy(msg, p, mlen); 372430300Sjoerg p += mlen; 372530300Sjoerg } 372630300Sjoerg va_end(ap); 372730300Sjoerg 372830300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 372930300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 373030300Sjoerg 373130300Sjoerg if (debug) { 373240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 373340008Sjoerg SPP_ARGS(ifp), cp->name, 373430300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 373530300Sjoerg lh->ident, ntohs(lh->len)); 373644145Sphk sppp_print_bytes((u_char*) (lh+1), len); 373730300Sjoerg addlog(">\n"); 373830300Sjoerg } 373930300Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 374030300Sjoerg IF_DROP (&sp->pp_fastq); 374130300Sjoerg IF_DROP (&ifp->if_snd); 374230300Sjoerg m_freem (m); 374330300Sjoerg ++ifp->if_oerrors; 374430300Sjoerg } else 374530300Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 374630300Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 374730300Sjoerg (*ifp->if_start) (ifp); 374830300Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 374930300Sjoerg} 375030300Sjoerg 375130300Sjoerg/* 375225944Sjoerg * Flush interface queue. 37534910Swollman */ 375412820Sphkstatic void 375525944Sjoergsppp_qflush(struct ifqueue *ifq) 37564910Swollman{ 375725944Sjoerg struct mbuf *m, *n; 37584910Swollman 375925944Sjoerg n = ifq->ifq_head; 376025944Sjoerg while ((m = n)) { 376125944Sjoerg n = m->m_act; 376225944Sjoerg m_freem (m); 376311189Sjkh } 376425944Sjoerg ifq->ifq_head = 0; 376525944Sjoerg ifq->ifq_tail = 0; 376625944Sjoerg ifq->ifq_len = 0; 376725944Sjoerg} 376825944Sjoerg 376925944Sjoerg/* 377025944Sjoerg * Send keepalive packets, every 10 seconds. 377125944Sjoerg */ 377225944Sjoergstatic void 377325944Sjoergsppp_keepalive(void *dummy) 377425944Sjoerg{ 377525944Sjoerg struct sppp *sp; 377625944Sjoerg int s; 377725944Sjoerg 377825944Sjoerg s = splimp(); 377925944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 378025944Sjoerg struct ifnet *ifp = &sp->pp_if; 378125944Sjoerg 378225944Sjoerg /* Keepalive mode disabled or channel down? */ 378325944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 378425944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 378525944Sjoerg continue; 378625944Sjoerg 378725944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 378845152Sphk if (sp->pp_mode != IFF_CISCO && 378925944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 379025944Sjoerg continue; 379125944Sjoerg 379225944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 379325944Sjoerg /* No keepalive packets got. Stop the interface. */ 379440008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 379525944Sjoerg if_down (ifp); 379626018Sjoerg sppp_qflush (&sp->pp_cpq); 379745152Sphk if (sp->pp_mode != IFF_CISCO) { 379825944Sjoerg /* XXX */ 379925944Sjoerg /* Shut down the PPP link. */ 380025944Sjoerg lcp.Down(sp); 380125944Sjoerg /* Initiate negotiation. XXX */ 380225944Sjoerg lcp.Up(sp); 380325944Sjoerg } 38044910Swollman } 380525944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 380625944Sjoerg ++sp->pp_alivecnt; 380745152Sphk if (sp->pp_mode == IFF_CISCO) 380825944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 380925944Sjoerg sp->pp_rseq); 381025944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 381125944Sjoerg long nmagic = htonl (sp->lcp.magic); 381225944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 381325944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 381425944Sjoerg sp->lcp.echoid, 4, &nmagic); 381525944Sjoerg } 38164910Swollman } 381725944Sjoerg splx(s); 381842064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 38194910Swollman} 38204910Swollman 382125944Sjoerg/* 382225944Sjoerg * Get both IP addresses. 382325944Sjoerg */ 382425944Sjoergstatic void 382530300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 382625944Sjoerg{ 382725944Sjoerg struct ifnet *ifp = &sp->pp_if; 382825944Sjoerg struct ifaddr *ifa; 382930300Sjoerg struct sockaddr_in *si, *sm; 383025944Sjoerg u_long ssrc, ddst; 383125944Sjoerg 383240010Sjoerg sm = NULL; 383325944Sjoerg ssrc = ddst = 0L; 383425944Sjoerg /* 383525944Sjoerg * Pick the first AF_INET address from the list, 383625944Sjoerg * aliases don't make any sense on a p2p link anyway. 383725944Sjoerg */ 383842065Sphk si = 0; 383942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 384042065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 384142104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 384242065Sphk for (ifa = ifp->if_addrlist.tqh_first; 384340008Sjoerg ifa; 384440008Sjoerg ifa = ifa->ifa_list.tqe_next) 384542104Sphk#else 384642104Sphk for (ifa = ifp->if_addrlist; 384742104Sphk ifa; 384842104Sphk ifa = ifa->ifa_next) 384940008Sjoerg#endif 385025944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 385125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 385230300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 385325944Sjoerg if (si) 385425944Sjoerg break; 385525944Sjoerg } 385625944Sjoerg if (ifa) { 385730300Sjoerg if (si && si->sin_addr.s_addr) { 385825944Sjoerg ssrc = si->sin_addr.s_addr; 385930300Sjoerg if (srcmask) 386030300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 386130300Sjoerg } 386225944Sjoerg 386325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 386425944Sjoerg if (si && si->sin_addr.s_addr) 386525944Sjoerg ddst = si->sin_addr.s_addr; 386625944Sjoerg } 386725944Sjoerg 386825944Sjoerg if (dst) *dst = ntohl(ddst); 386925944Sjoerg if (src) *src = ntohl(ssrc); 387025944Sjoerg} 387125944Sjoerg 387225944Sjoerg/* 387325944Sjoerg * Set my IP address. Must be called at splimp. 387425944Sjoerg */ 387525944Sjoergstatic void 387625944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 387725944Sjoerg{ 387842104Sphk STDDCL; 387925944Sjoerg struct ifaddr *ifa; 388025944Sjoerg struct sockaddr_in *si; 388125944Sjoerg 388225944Sjoerg /* 388325944Sjoerg * Pick the first AF_INET address from the list, 388425944Sjoerg * aliases don't make any sense on a p2p link anyway. 388525944Sjoerg */ 388642065Sphk si = 0; 388742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 388842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 388942104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 389042065Sphk for (ifa = ifp->if_addrlist.tqh_first; 389140008Sjoerg ifa; 389240008Sjoerg ifa = ifa->ifa_list.tqe_next) 389342104Sphk#else 389442104Sphk for (ifa = ifp->if_addrlist; 389542104Sphk ifa; 389642104Sphk ifa = ifa->ifa_next) 389740008Sjoerg#endif 389840008Sjoerg { 389940008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 390040008Sjoerg { 390125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 390225944Sjoerg if (si) 390325944Sjoerg break; 390425944Sjoerg } 390540008Sjoerg } 390640008Sjoerg 390725944Sjoerg if (ifa && si) 390842104Sphk { 390942104Sphk int error; 391042104Sphk#if __NetBSD_Version__ >= 103080000 391142104Sphk struct sockaddr_in new_sin = *si; 391242104Sphk 391342104Sphk new_sin.sin_addr.s_addr = htonl(src); 391442104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 391542104Sphk if(debug && error) 391642104Sphk { 391742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 391842104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 391942104Sphk } 392042104Sphk#else 392142104Sphk /* delete old route */ 392242104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 392342104Sphk if(debug && error) 392442104Sphk { 392542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 392642104Sphk SPP_ARGS(ifp), error); 392742104Sphk } 392842104Sphk 392942104Sphk /* set new address */ 393025944Sjoerg si->sin_addr.s_addr = htonl(src); 393125944Sjoerg 393242104Sphk /* add new route */ 393342104Sphk error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 393442104Sphk if (debug && error) 393542104Sphk { 393642104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 393742104Sphk SPP_ARGS(ifp), error); 393842104Sphk } 393942104Sphk#endif 394042104Sphk } 394142104Sphk} 394242104Sphk 394330300Sjoergstatic int 394438343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 394530300Sjoerg{ 394638343Sbde u_long subcmd; 394730300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 394830300Sjoerg struct spppreq spr; 394930300Sjoerg 395030300Sjoerg /* 395130300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 395230300Sjoerg * Check the cmd word first before attempting to fetch all the 395330300Sjoerg * data. 395430300Sjoerg */ 395530300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 395630300Sjoerg return EFAULT; 395730300Sjoerg 395830300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 395930300Sjoerg return EFAULT; 396030300Sjoerg 396130300Sjoerg switch (subcmd) { 396230300Sjoerg case SPPPIOGDEFS: 396330300Sjoerg if (cmd != SIOCGIFGENERIC) 396430300Sjoerg return EINVAL; 396530300Sjoerg /* 396630300Sjoerg * We copy over the entire current state, but clean 396730300Sjoerg * out some of the stuff we don't wanna pass up. 396830300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 396930300Sjoerg * called by any user. No need to ever get PAP or 397030300Sjoerg * CHAP secrets back to userland anyway. 397130300Sjoerg */ 397230300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 397330300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 397430300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 397530300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 397630300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 397730300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 397830300Sjoerg 397930300Sjoerg case SPPPIOSDEFS: 398030300Sjoerg if (cmd != SIOCSIFGENERIC) 398130300Sjoerg return EINVAL; 398230300Sjoerg /* 398330300Sjoerg * We have a very specific idea of which fields we allow 398430300Sjoerg * being passed back from userland, so to not clobber our 398530300Sjoerg * current state. For one, we only allow setting 398630300Sjoerg * anything if LCP is in dead phase. Once the LCP 398730300Sjoerg * negotiations started, the authentication settings must 398830300Sjoerg * not be changed again. (The administrator can force an 398930300Sjoerg * ifconfig down in order to get LCP back into dead 399030300Sjoerg * phase.) 399130300Sjoerg * 399230300Sjoerg * Also, we only allow for authentication parameters to be 399330300Sjoerg * specified. 399430300Sjoerg * 399530300Sjoerg * XXX Should allow to set or clear pp_flags. 399630300Sjoerg * 399730300Sjoerg * Finally, if the respective authentication protocol to 399830300Sjoerg * be used is set differently than 0, but the secret is 399930300Sjoerg * passed as all zeros, we don't trash the existing secret. 400030300Sjoerg * This allows an administrator to change the system name 400130300Sjoerg * only without clobbering the secret (which he didn't get 400230300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 400330300Sjoerg * secrets are cleared if the authentication protocol is 400430300Sjoerg * reset to 0. 400530300Sjoerg */ 400630300Sjoerg if (sp->pp_phase != PHASE_DEAD) 400730300Sjoerg return EBUSY; 400830300Sjoerg 400930300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 401030300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 401130300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 401230300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 401330300Sjoerg return EINVAL; 401430300Sjoerg 401530300Sjoerg if (spr.defs.myauth.proto == 0) 401630300Sjoerg /* resetting myauth */ 401730300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 401830300Sjoerg else { 401930300Sjoerg /* setting/changing myauth */ 402030300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 402130300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 402230300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 402330300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 402430300Sjoerg AUTHKEYLEN); 402530300Sjoerg } 402630300Sjoerg if (spr.defs.hisauth.proto == 0) 402730300Sjoerg /* resetting hisauth */ 402830300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 402930300Sjoerg else { 403030300Sjoerg /* setting/changing hisauth */ 403130300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 403230300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 403330300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 403430300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 403530300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 403630300Sjoerg AUTHKEYLEN); 403730300Sjoerg } 403830300Sjoerg break; 403930300Sjoerg 404030300Sjoerg default: 404130300Sjoerg return EINVAL; 404230300Sjoerg } 404330300Sjoerg 404430300Sjoerg return 0; 404530300Sjoerg} 404630300Sjoerg 404730300Sjoergstatic void 404830300Sjoergsppp_phase_network(struct sppp *sp) 404930300Sjoerg{ 405042066Sphk STDDCL; 405130300Sjoerg int i; 405230300Sjoerg u_long mask; 405330300Sjoerg 405430300Sjoerg sp->pp_phase = PHASE_NETWORK; 405530300Sjoerg 405642066Sphk if (debug) 405742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 405842066Sphk sppp_phase_name(sp->pp_phase)); 405930300Sjoerg 406030300Sjoerg /* Notify NCPs now. */ 406130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 406230300Sjoerg if ((cps[i])->flags & CP_NCP) 406330300Sjoerg (cps[i])->Open(sp); 406430300Sjoerg 406530300Sjoerg /* Send Up events to all NCPs. */ 406630300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 406730300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 406830300Sjoerg (cps[i])->Up(sp); 406930300Sjoerg 407030300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 407130300Sjoerg sppp_lcp_check_and_close(sp); 407230300Sjoerg} 407330300Sjoerg 407430300Sjoerg 407525706Sjoergstatic const char * 407625944Sjoergsppp_cp_type_name(u_char type) 40774910Swollman{ 407830300Sjoerg static char buf[12]; 40794910Swollman switch (type) { 408030300Sjoerg case CONF_REQ: return "conf-req"; 408130300Sjoerg case CONF_ACK: return "conf-ack"; 408230300Sjoerg case CONF_NAK: return "conf-nak"; 408330300Sjoerg case CONF_REJ: return "conf-rej"; 408430300Sjoerg case TERM_REQ: return "term-req"; 408530300Sjoerg case TERM_ACK: return "term-ack"; 408630300Sjoerg case CODE_REJ: return "code-rej"; 408730300Sjoerg case PROTO_REJ: return "proto-rej"; 408830300Sjoerg case ECHO_REQ: return "echo-req"; 408930300Sjoerg case ECHO_REPLY: return "echo-reply"; 409030300Sjoerg case DISC_REQ: return "discard-req"; 40914910Swollman } 409244145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 409330300Sjoerg return buf; 40944910Swollman} 40954910Swollman 409625706Sjoergstatic const char * 409730300Sjoergsppp_auth_type_name(u_short proto, u_char type) 409830300Sjoerg{ 409930300Sjoerg static char buf[12]; 410030300Sjoerg switch (proto) { 410130300Sjoerg case PPP_CHAP: 410230300Sjoerg switch (type) { 410330300Sjoerg case CHAP_CHALLENGE: return "challenge"; 410430300Sjoerg case CHAP_RESPONSE: return "response"; 410530300Sjoerg case CHAP_SUCCESS: return "success"; 410630300Sjoerg case CHAP_FAILURE: return "failure"; 410730300Sjoerg } 410830300Sjoerg case PPP_PAP: 410930300Sjoerg switch (type) { 411030300Sjoerg case PAP_REQ: return "req"; 411130300Sjoerg case PAP_ACK: return "ack"; 411230300Sjoerg case PAP_NAK: return "nak"; 411330300Sjoerg } 411430300Sjoerg } 411544145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 411630300Sjoerg return buf; 411730300Sjoerg} 411830300Sjoerg 411930300Sjoergstatic const char * 412025944Sjoergsppp_lcp_opt_name(u_char opt) 41214910Swollman{ 412230300Sjoerg static char buf[12]; 412325944Sjoerg switch (opt) { 412430300Sjoerg case LCP_OPT_MRU: return "mru"; 412530300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 412630300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 412730300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 412830300Sjoerg case LCP_OPT_MAGIC: return "magic"; 412930300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 413030300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 41314910Swollman } 413244145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 413330300Sjoerg return buf; 41344910Swollman} 41354910Swollman 413625944Sjoergstatic const char * 413725944Sjoergsppp_ipcp_opt_name(u_char opt) 413825944Sjoerg{ 413930300Sjoerg static char buf[12]; 414025944Sjoerg switch (opt) { 414130300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 414230300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 414330300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 414425944Sjoerg } 414544145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 414630300Sjoerg return buf; 414725944Sjoerg} 414825944Sjoerg 414925944Sjoergstatic const char * 415025944Sjoergsppp_state_name(int state) 415125944Sjoerg{ 415225944Sjoerg switch (state) { 415325944Sjoerg case STATE_INITIAL: return "initial"; 415425944Sjoerg case STATE_STARTING: return "starting"; 415525944Sjoerg case STATE_CLOSED: return "closed"; 415625944Sjoerg case STATE_STOPPED: return "stopped"; 415725944Sjoerg case STATE_CLOSING: return "closing"; 415825944Sjoerg case STATE_STOPPING: return "stopping"; 415925944Sjoerg case STATE_REQ_SENT: return "req-sent"; 416025944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 416125944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 416225944Sjoerg case STATE_OPENED: return "opened"; 416325944Sjoerg } 416425944Sjoerg return "illegal"; 416525944Sjoerg} 416625944Sjoerg 416725944Sjoergstatic const char * 416825944Sjoergsppp_phase_name(enum ppp_phase phase) 416925944Sjoerg{ 417025944Sjoerg switch (phase) { 417125944Sjoerg case PHASE_DEAD: return "dead"; 417225944Sjoerg case PHASE_ESTABLISH: return "establish"; 417325944Sjoerg case PHASE_TERMINATE: return "terminate"; 417425944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 417525944Sjoerg case PHASE_NETWORK: return "network"; 417625944Sjoerg } 417725944Sjoerg return "illegal"; 417825944Sjoerg} 417925944Sjoerg 418025944Sjoergstatic const char * 418125944Sjoergsppp_proto_name(u_short proto) 418225944Sjoerg{ 418325944Sjoerg static char buf[12]; 418425944Sjoerg switch (proto) { 418525944Sjoerg case PPP_LCP: return "lcp"; 418625944Sjoerg case PPP_IPCP: return "ipcp"; 418730300Sjoerg case PPP_PAP: return "pap"; 418830300Sjoerg case PPP_CHAP: return "chap"; 418925944Sjoerg } 419044145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 419125944Sjoerg return buf; 419225944Sjoerg} 419325944Sjoerg 419412820Sphkstatic void 419530300Sjoergsppp_print_bytes(const u_char *p, u_short len) 41964910Swollman{ 419744145Sphk if (len) 419844145Sphk addlog(" %*D", len, p, "-"); 41994910Swollman} 420025944Sjoerg 420130300Sjoergstatic void 420230300Sjoergsppp_print_string(const char *p, u_short len) 420330300Sjoerg{ 420430300Sjoerg u_char c; 420530300Sjoerg 420630300Sjoerg while (len-- > 0) { 420730300Sjoerg c = *p++; 420830300Sjoerg /* 420930300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 421030300Sjoerg * using only them, but we don't rely on it. */ 421130300Sjoerg if (c < ' ' || c > '~') 421230300Sjoerg addlog("\\x%x", c); 421330300Sjoerg else 421430300Sjoerg addlog("%c", c); 421530300Sjoerg } 421630300Sjoerg} 421730300Sjoerg 421830300Sjoergstatic const char * 421930300Sjoergsppp_dotted_quad(u_long addr) 422030300Sjoerg{ 422130300Sjoerg static char s[16]; 422230300Sjoerg sprintf(s, "%d.%d.%d.%d", 422340008Sjoerg (int)((addr >> 24) & 0xff), 422440008Sjoerg (int)((addr >> 16) & 0xff), 422540008Sjoerg (int)((addr >> 8) & 0xff), 422638372Sbde (int)(addr & 0xff)); 422730300Sjoerg return s; 422830300Sjoerg} 422930300Sjoerg 423030300Sjoergstatic int 423130300Sjoergsppp_strnlen(u_char *p, int max) 423230300Sjoerg{ 423330300Sjoerg int len; 423430300Sjoerg 423530300Sjoerg for (len = 0; len < max && *p; ++p) 423630300Sjoerg ++len; 423730300Sjoerg return len; 423830300Sjoerg} 423930300Sjoerg 424030300Sjoerg/* a dummy, used to drop uninteresting events */ 424130300Sjoergstatic void 424230300Sjoergsppp_null(struct sppp *unused) 424330300Sjoerg{ 424430300Sjoerg /* do just nothing */ 424530300Sjoerg} 4246