if_spppsubr.c revision 42104
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 * 2042104Sphk * $Id: if_spppsubr.c,v 1.51 1998/12/26 13:14:45 phk Exp $ 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 */ 13725944Sjoerg 13830300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13930300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 14030300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 14130300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 14230300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 14330300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 14430300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14530300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14630300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14730300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 1484910Swollman 14925944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 15025944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 15125944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 15225944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 15325944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 15425944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 15525944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15625944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15725944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 15825944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 15925944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1604910Swollman 16130300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 16230300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 16330300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 16430300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 16530300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16630300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16730300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 16830300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1694910Swollman 17025944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 17125944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 17225944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1734910Swollman 17430300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 17530300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 17630300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1774910Swollman 17830300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 17930300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 18030300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18130300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18230300Sjoerg 18330300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18430300Sjoerg 18530300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 18630300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 18730300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 18830300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 18930300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 19030300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19130300Sjoerg 19225944Sjoerg/* states are named and numbered according to RFC 1661 */ 19325944Sjoerg#define STATE_INITIAL 0 19425944Sjoerg#define STATE_STARTING 1 19525944Sjoerg#define STATE_CLOSED 2 19625944Sjoerg#define STATE_STOPPED 3 19725944Sjoerg#define STATE_CLOSING 4 19825944Sjoerg#define STATE_STOPPING 5 19925944Sjoerg#define STATE_REQ_SENT 6 20025944Sjoerg#define STATE_ACK_RCVD 7 20125944Sjoerg#define STATE_ACK_SENT 8 20225944Sjoerg#define STATE_OPENED 9 20325944Sjoerg 2044910Swollmanstruct ppp_header { 20511189Sjkh u_char address; 20611189Sjkh u_char control; 20711189Sjkh u_short protocol; 2084910Swollman}; 2094910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2104910Swollman 2114910Swollmanstruct lcp_header { 21211189Sjkh u_char type; 21311189Sjkh u_char ident; 21411189Sjkh u_short len; 2154910Swollman}; 2164910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2174910Swollman 2184910Swollmanstruct cisco_packet { 21911189Sjkh u_long type; 22011189Sjkh u_long par1; 22111189Sjkh u_long par2; 22211189Sjkh u_short rel; 22311189Sjkh u_short time0; 22411189Sjkh u_short time1; 2254910Swollman}; 2264910Swollman#define CISCO_PACKET_LEN 18 2274910Swollman 22825944Sjoerg/* 22925944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 23025944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23125944Sjoerg * case you can't make sense out of these abbreviation; it will also 23225944Sjoerg * explain the semantics related to the various events and actions. 23325944Sjoerg */ 23425944Sjoergstruct cp { 23525944Sjoerg u_short proto; /* PPP control protocol number */ 23625944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 23725944Sjoerg u_char flags; 23825944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 23925944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 24025944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24125944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24225944Sjoerg const char *name; /* name of this control protocol */ 24325944Sjoerg /* event handlers */ 24425944Sjoerg void (*Up)(struct sppp *sp); 24525944Sjoerg void (*Down)(struct sppp *sp); 24625944Sjoerg void (*Open)(struct sppp *sp); 24725944Sjoerg void (*Close)(struct sppp *sp); 24825944Sjoerg void (*TO)(void *sp); 24925944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 25025944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25125944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25225944Sjoerg /* actions */ 25325944Sjoerg void (*tlu)(struct sppp *sp); 25425944Sjoerg void (*tld)(struct sppp *sp); 25525944Sjoerg void (*tls)(struct sppp *sp); 25625944Sjoerg void (*tlf)(struct sppp *sp); 25725944Sjoerg void (*scr)(struct sppp *sp); 25825944Sjoerg}; 25925944Sjoerg 26012820Sphkstatic struct sppp *spppq; 26142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26230300Sjoergstatic struct callout_handle keepalive_ch; 26340008Sjoerg#endif 2644910Swollman 26542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26640008Sjoerg#define SPP_FMT "%s%d: " 26740008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 26840008Sjoerg#else 26940008Sjoerg#define SPP_FMT "%s: " 27040008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27140008Sjoerg#endif 27240008Sjoerg 2734910Swollman/* 2744910Swollman * The following disgusting hack gets around the problem that IP TOS 2754910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2764910Swollman * priority queue. To decide if traffic is interactive, we check that 2774910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 27830300Sjoerg * 27930300Sjoerg * XXX is this really still necessary? - joerg - 2804910Swollman */ 28111189Sjkhstatic u_short interactive_ports[8] = { 2824910Swollman 0, 513, 0, 0, 2834910Swollman 0, 21, 0, 23, 2844910Swollman}; 2854910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2864910Swollman 28725944Sjoerg/* almost every function needs these */ 28825944Sjoerg#define STDDCL \ 28925944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 29025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29111189Sjkh 29230300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 29325944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2944910Swollman 29525944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 29625944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 29725944Sjoerg 29825944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 29925944Sjoerg struct mbuf *m); 30025944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30125944Sjoerg u_char ident, u_short len, void *data); 30242104Sphk/* static void sppp_cp_timeout(void *arg); */ 30325944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 30425944Sjoerg int newstate); 30530300Sjoergstatic void sppp_auth_send(const struct cp *cp, 30642104Sphk struct sppp *sp, unsigned int type, unsigned int id, 30730300Sjoerg ...); 30825944Sjoerg 30925944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 31025944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31125944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31225944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 31325944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 31425944Sjoerg 31530300Sjoergstatic void sppp_null(struct sppp *sp); 31630300Sjoerg 31725944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 31825944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 31925944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 32025944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32125944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32225944Sjoergstatic void sppp_lcp_TO(void *sp); 32325944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32425944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 32525944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 32625944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 33025944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33130300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33230300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 33325944Sjoerg 33425944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 33525944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 33625944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 33725944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 33825944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 33925944Sjoergstatic void sppp_ipcp_TO(void *sp); 34025944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34125944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34225944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34325944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 34725944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 34825944Sjoerg 34930300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 35030300Sjoergstatic void sppp_pap_init(struct sppp *sp); 35130300Sjoergstatic void sppp_pap_open(struct sppp *sp); 35230300Sjoergstatic void sppp_pap_close(struct sppp *sp); 35330300Sjoergstatic void sppp_pap_TO(void *sp); 35430300Sjoergstatic void sppp_pap_my_TO(void *sp); 35530300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 35630300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 35730300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 35830300Sjoerg 35930300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 36030300Sjoergstatic void sppp_chap_init(struct sppp *sp); 36130300Sjoergstatic void sppp_chap_open(struct sppp *sp); 36230300Sjoergstatic void sppp_chap_close(struct sppp *sp); 36330300Sjoergstatic void sppp_chap_TO(void *sp); 36430300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 36530300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 36630300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 36730300Sjoerg 36830300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 36925944Sjoergstatic const char *sppp_cp_type_name(u_char type); 37030300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 37130300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 37225944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 37325944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 37425944Sjoergstatic const char *sppp_proto_name(u_short proto); 37530300Sjoergstatic const char *sppp_state_name(int state); 37638343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 37730300Sjoergstatic int sppp_strnlen(u_char *p, int max); 37830300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 37930300Sjoerg u_long *srcmask); 38025944Sjoergstatic void sppp_keepalive(void *dummy); 38130300Sjoergstatic void sppp_phase_network(struct sppp *sp); 38230300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 38330300Sjoergstatic void sppp_print_string(const char *p, u_short len); 38425944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 38525944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 38625944Sjoerg 38725944Sjoerg/* our control protocol descriptors */ 38833181Seivindstatic const struct cp lcp = { 38925944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 39025944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 39125944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 39225944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 39325944Sjoerg sppp_lcp_scr 39425944Sjoerg}; 39525944Sjoerg 39633181Seivindstatic const struct cp ipcp = { 39725944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 39825944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 39925944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 40025944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 40125944Sjoerg sppp_ipcp_scr 40225944Sjoerg}; 40325944Sjoerg 40433181Seivindstatic const struct cp pap = { 40530300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 40630300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 40730300Sjoerg sppp_pap_TO, 0, 0, 0, 40830300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 40930300Sjoerg sppp_pap_scr 41030300Sjoerg}; 41130300Sjoerg 41233181Seivindstatic const struct cp chap = { 41330300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 41430300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 41530300Sjoerg sppp_chap_TO, 0, 0, 0, 41630300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 41730300Sjoerg sppp_chap_scr 41830300Sjoerg}; 41930300Sjoerg 42033181Seivindstatic const struct cp *cps[IDX_COUNT] = { 42125944Sjoerg &lcp, /* IDX_LCP */ 42225944Sjoerg &ipcp, /* IDX_IPCP */ 42330300Sjoerg &pap, /* IDX_PAP */ 42430300Sjoerg &chap, /* IDX_CHAP */ 42525944Sjoerg}; 42625944Sjoerg 42725944Sjoerg 42825944Sjoerg/* 42925944Sjoerg * Exported functions, comprising our interface to the lower layer. 4304910Swollman */ 4314910Swollman 4324910Swollman/* 4334910Swollman * Process the received packet. 4344910Swollman */ 43525706Sjoergvoid 43625706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 4374910Swollman{ 4384910Swollman struct ppp_header *h; 4394910Swollman struct ifqueue *inq = 0; 44011189Sjkh int s; 44125944Sjoerg struct sppp *sp = (struct sppp *)ifp; 44225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 4434910Swollman 4444910Swollman if (ifp->if_flags & IFF_UP) 4454910Swollman /* Count received bytes, add FCS and one flag */ 4464910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 4474910Swollman 4484910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 4494910Swollman /* Too small packet, drop it. */ 45025944Sjoerg if (debug) 45125706Sjoerg log(LOG_DEBUG, 45240008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 45340008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 45425944Sjoerg drop: 45525944Sjoerg ++ifp->if_ierrors; 45625944Sjoerg ++ifp->if_iqdrops; 4574910Swollman m_freem (m); 4584910Swollman return; 4594910Swollman } 4604910Swollman 4614910Swollman /* Get PPP header. */ 4624910Swollman h = mtod (m, struct ppp_header*); 4634910Swollman m_adj (m, PPP_HEADER_LEN); 4644910Swollman 4654910Swollman switch (h->address) { 4664910Swollman case PPP_ALLSTATIONS: 4674910Swollman if (h->control != PPP_UI) 4684910Swollman goto invalid; 46911189Sjkh if (sp->pp_flags & PP_CISCO) { 47025944Sjoerg if (debug) 47125706Sjoerg log(LOG_DEBUG, 47240008Sjoerg SPP_FMT "PPP packet in Cisco mode " 47325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 47440008Sjoerg SPP_ARGS(ifp), 47525706Sjoerg h->address, h->control, ntohs(h->protocol)); 47611189Sjkh goto drop; 47711189Sjkh } 4784910Swollman switch (ntohs (h->protocol)) { 4794910Swollman default: 48025944Sjoerg if (sp->state[IDX_LCP] == STATE_OPENED) 48125944Sjoerg sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 48211189Sjkh ++sp->pp_seq, m->m_pkthdr.len + 2, 4834910Swollman &h->protocol); 48425944Sjoerg if (debug) 48525706Sjoerg log(LOG_DEBUG, 48640008Sjoerg SPP_FMT "invalid input protocol " 48725706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 48840008Sjoerg SPP_ARGS(ifp), 48925706Sjoerg h->address, h->control, ntohs(h->protocol)); 4904910Swollman ++ifp->if_noproto; 4914910Swollman goto drop; 4924910Swollman case PPP_LCP: 49330300Sjoerg sppp_cp_input(&lcp, sp, m); 4944910Swollman m_freem (m); 4954910Swollman return; 49630300Sjoerg case PPP_PAP: 49730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 49830300Sjoerg sppp_pap_input(sp, m); 49930300Sjoerg m_freem (m); 50030300Sjoerg return; 50130300Sjoerg case PPP_CHAP: 50230300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 50330300Sjoerg sppp_chap_input(sp, m); 50430300Sjoerg m_freem (m); 50530300Sjoerg return; 5064910Swollman#ifdef INET 5074910Swollman case PPP_IPCP: 50825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 50930300Sjoerg sppp_cp_input(&ipcp, sp, m); 5104910Swollman m_freem (m); 5114910Swollman return; 5124910Swollman case PPP_IP: 51325944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5144910Swollman schednetisr (NETISR_IP); 5154910Swollman inq = &ipintrq; 5164910Swollman } 5174910Swollman break; 5184910Swollman#endif 51912495Speter#ifdef IPX 52012495Speter case PPP_IPX: 52112495Speter /* IPX IPXCP not implemented yet */ 52225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 52312495Speter schednetisr (NETISR_IPX); 52412495Speter inq = &ipxintrq; 52512495Speter } 52612495Speter break; 52712495Speter#endif 5284910Swollman#ifdef NS 5294910Swollman case PPP_XNS: 5304910Swollman /* XNS IDPCP not implemented yet */ 53125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5324910Swollman schednetisr (NETISR_NS); 5334910Swollman inq = &nsintrq; 5344910Swollman } 5354910Swollman break; 5364910Swollman#endif 5374910Swollman#ifdef ISO 5384910Swollman case PPP_ISO: 5394910Swollman /* OSI NLCP not implemented yet */ 54025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 5414910Swollman schednetisr (NETISR_ISO); 5424910Swollman inq = &clnlintrq; 5434910Swollman } 5444910Swollman break; 5454910Swollman#endif 5464910Swollman } 5474910Swollman break; 5484910Swollman case CISCO_MULTICAST: 5494910Swollman case CISCO_UNICAST: 5504910Swollman /* Don't check the control field here (RFC 1547). */ 55111189Sjkh if (! (sp->pp_flags & PP_CISCO)) { 55225944Sjoerg if (debug) 55325706Sjoerg log(LOG_DEBUG, 55440008Sjoerg SPP_FMT "Cisco packet in PPP mode " 55525706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55640008Sjoerg SPP_ARGS(ifp), 55725706Sjoerg h->address, h->control, ntohs(h->protocol)); 55811189Sjkh goto drop; 55911189Sjkh } 5604910Swollman switch (ntohs (h->protocol)) { 5614910Swollman default: 5624910Swollman ++ifp->if_noproto; 5634910Swollman goto invalid; 5644910Swollman case CISCO_KEEPALIVE: 5654910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 5664910Swollman m_freem (m); 5674910Swollman return; 5684910Swollman#ifdef INET 5694910Swollman case ETHERTYPE_IP: 5704910Swollman schednetisr (NETISR_IP); 5714910Swollman inq = &ipintrq; 5724910Swollman break; 5734910Swollman#endif 57412495Speter#ifdef IPX 57512495Speter case ETHERTYPE_IPX: 57612495Speter schednetisr (NETISR_IPX); 57712495Speter inq = &ipxintrq; 57812495Speter break; 57912495Speter#endif 5804910Swollman#ifdef NS 5814910Swollman case ETHERTYPE_NS: 5824910Swollman schednetisr (NETISR_NS); 5834910Swollman inq = &nsintrq; 5844910Swollman break; 5854910Swollman#endif 5864910Swollman } 5874910Swollman break; 58825944Sjoerg default: /* Invalid PPP packet. */ 58925944Sjoerg invalid: 59025944Sjoerg if (debug) 59125944Sjoerg log(LOG_DEBUG, 59240008Sjoerg SPP_FMT "invalid input packet " 59325944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 59440008Sjoerg SPP_ARGS(ifp), 59525944Sjoerg h->address, h->control, ntohs(h->protocol)); 59625944Sjoerg goto drop; 5974910Swollman } 5984910Swollman 5994910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 6004910Swollman goto drop; 6014910Swollman 6024910Swollman /* Check queue. */ 60325944Sjoerg s = splimp(); 6044910Swollman if (IF_QFULL (inq)) { 6054910Swollman /* Queue overflow. */ 60625944Sjoerg IF_DROP(inq); 60725944Sjoerg splx(s); 60825944Sjoerg if (debug) 60940008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 61040008Sjoerg SPP_ARGS(ifp)); 6114910Swollman goto drop; 6124910Swollman } 61325944Sjoerg IF_ENQUEUE(inq, m); 61425944Sjoerg splx(s); 6154910Swollman} 6164910Swollman 6174910Swollman/* 6184910Swollman * Enqueue transmit packet. 6194910Swollman */ 62012820Sphkstatic int 62125706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 62225706Sjoerg struct sockaddr *dst, struct rtentry *rt) 6234910Swollman{ 6244910Swollman struct sppp *sp = (struct sppp*) ifp; 6254910Swollman struct ppp_header *h; 6264910Swollman struct ifqueue *ifq; 62725955Sjoerg int s, rv = 0; 62842066Sphk int debug = ifp->if_flags & IFF_DEBUG; 6294910Swollman 63025944Sjoerg s = splimp(); 63125944Sjoerg 63225944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 63325944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 6344910Swollman m_freem (m); 6354910Swollman splx (s); 6364910Swollman return (ENETDOWN); 6374910Swollman } 6384910Swollman 63925944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 64025944Sjoerg /* 64125944Sjoerg * Interface is not yet running, but auto-dial. Need 64225944Sjoerg * to start LCP for it. 64325944Sjoerg */ 64425944Sjoerg ifp->if_flags |= IFF_RUNNING; 64525944Sjoerg splx(s); 64625944Sjoerg lcp.Open(sp); 64725944Sjoerg s = splimp(); 64825944Sjoerg } 64925944Sjoerg 6504910Swollman ifq = &ifp->if_snd; 6514910Swollman#ifdef INET 65212436Speter if (dst->sa_family == AF_INET) { 65340008Sjoerg /* XXX Check mbuf length here? */ 65412436Speter struct ip *ip = mtod (m, struct ip*); 65512436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 6564910Swollman 65742104Sphk /* 65842104Sphk * When using dynamic local IP address assignment by using 65942104Sphk * 0.0.0.0 as a local address, the first TCP session will 66042104Sphk * not connect because the local TCP checksum is computed 66142104Sphk * using 0.0.0.0 which will later become our real IP address 66242104Sphk * so the TCP checksum computed at the remote end will 66342104Sphk * become invalid. So we 66442104Sphk * - don't let packets with src ip addr 0 thru 66542104Sphk * - we flag TCP packets with src ip 0 as an error 66642104Sphk */ 66742104Sphk 66842104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 66942104Sphk { 67042104Sphk m_freem(m); 67142104Sphk splx(s); 67242104Sphk if(ip->ip_p == IPPROTO_TCP) 67342104Sphk return(EADDRNOTAVAIL); 67442104Sphk else 67542104Sphk return(0); 67642104Sphk } 67742104Sphk 67842104Sphk /* 67942104Sphk * Put low delay, telnet, rlogin and ftp control packets 68042104Sphk * in front of the queue. 68142104Sphk */ 68241686Sphk if (IF_QFULL (&sp->pp_fastq)) 68341686Sphk ; 68441686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 68512436Speter ifq = &sp->pp_fastq; 68641686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 68741686Sphk ; 68841686Sphk else if (ip->ip_p != IPPROTO_TCP) 68941686Sphk ; 69041686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 69141686Sphk ifq = &sp->pp_fastq; 69241686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 69341686Sphk ifq = &sp->pp_fastq; 6944910Swollman } 6954910Swollman#endif 6964910Swollman 6974910Swollman /* 6984910Swollman * Prepend general data packet PPP header. For now, IP only. 6994910Swollman */ 7004910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 7014910Swollman if (! m) { 70242066Sphk if (debug) 70340008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 70440008Sjoerg SPP_ARGS(ifp)); 70525944Sjoerg ++ifp->if_oerrors; 7064910Swollman splx (s); 7074910Swollman return (ENOBUFS); 7084910Swollman } 70940008Sjoerg /* 71040008Sjoerg * May want to check size of packet 71140008Sjoerg * (albeit due to the implementation it's always enough) 71240008Sjoerg */ 7134910Swollman h = mtod (m, struct ppp_header*); 7144910Swollman if (sp->pp_flags & PP_CISCO) { 71528088Skjc h->address = CISCO_UNICAST; /* unicast address */ 7164910Swollman h->control = 0; 7174910Swollman } else { 7184910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 7194910Swollman h->control = PPP_UI; /* Unnumbered Info */ 7204910Swollman } 7214910Swollman 7224910Swollman switch (dst->sa_family) { 7234910Swollman#ifdef INET 7244910Swollman case AF_INET: /* Internet Protocol */ 72511189Sjkh if (sp->pp_flags & PP_CISCO) 72611189Sjkh h->protocol = htons (ETHERTYPE_IP); 72711189Sjkh else { 72825955Sjoerg /* 72925955Sjoerg * Don't choke with an ENETDOWN early. It's 73025955Sjoerg * possible that we just started dialing out, 73125955Sjoerg * so don't drop the packet immediately. If 73225955Sjoerg * we notice that we run out of buffer space 73325955Sjoerg * below, we will however remember that we are 73425955Sjoerg * not ready to carry IP packets, and return 73525955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 73625955Sjoerg */ 73725955Sjoerg h->protocol = htons(PPP_IP); 73825955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 73925955Sjoerg rv = ENETDOWN; 74011189Sjkh } 7414910Swollman break; 7424910Swollman#endif 7434910Swollman#ifdef NS 7444910Swollman case AF_NS: /* Xerox NS Protocol */ 7454910Swollman h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 7464910Swollman ETHERTYPE_NS : PPP_XNS); 7474910Swollman break; 7484910Swollman#endif 74911819Sjulian#ifdef IPX 75012495Speter case AF_IPX: /* Novell IPX Protocol */ 75111819Sjulian h->protocol = htons ((sp->pp_flags & PP_CISCO) ? 75212495Speter ETHERTYPE_IPX : PPP_IPX); 75311819Sjulian break; 75411819Sjulian#endif 7554910Swollman#ifdef ISO 7564910Swollman case AF_ISO: /* ISO OSI Protocol */ 7574910Swollman if (sp->pp_flags & PP_CISCO) 7584910Swollman goto nosupport; 7594910Swollman h->protocol = htons (PPP_ISO); 7604910Swollman break; 76112820Sphknosupport: 7624910Swollman#endif 7634910Swollman default: 7644910Swollman m_freem (m); 76525944Sjoerg ++ifp->if_oerrors; 7664910Swollman splx (s); 7674910Swollman return (EAFNOSUPPORT); 7684910Swollman } 7694910Swollman 7704910Swollman /* 7714910Swollman * Queue message on interface, and start output if interface 7724910Swollman * not yet active. 7734910Swollman */ 7744910Swollman if (IF_QFULL (ifq)) { 7754910Swollman IF_DROP (&ifp->if_snd); 7764910Swollman m_freem (m); 77725944Sjoerg ++ifp->if_oerrors; 7784910Swollman splx (s); 77925955Sjoerg return (rv? rv: ENOBUFS); 7804910Swollman } 7814910Swollman IF_ENQUEUE (ifq, m); 7824910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 7834910Swollman (*ifp->if_start) (ifp); 7844910Swollman 7854910Swollman /* 7864910Swollman * Count output packets and bytes. 7874910Swollman * The packet length includes header, FCS and 1 flag, 7884910Swollman * according to RFC 1333. 7894910Swollman */ 7904910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 7914910Swollman splx (s); 7924910Swollman return (0); 7934910Swollman} 7944910Swollman 79525706Sjoergvoid 79625706Sjoergsppp_attach(struct ifnet *ifp) 7974910Swollman{ 7984910Swollman struct sppp *sp = (struct sppp*) ifp; 7994910Swollman 8004910Swollman /* Initialize keepalive handler. */ 8014910Swollman if (! spppq) 80242064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 8034910Swollman 8044910Swollman /* Insert new entry into the keepalive list. */ 8054910Swollman sp->pp_next = spppq; 8064910Swollman spppq = sp; 8074910Swollman 80842064Sphk sp->pp_if.if_mtu = PP_MTU; 80942064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 8104910Swollman sp->pp_if.if_type = IFT_PPP; 8114910Swollman sp->pp_if.if_output = sppp_output; 81242104Sphk#if 0 81342064Sphk sp->pp_flags = PP_KEEPALIVE; 81442104Sphk#endif 8154910Swollman sp->pp_fastq.ifq_maxlen = 32; 81626018Sjoerg sp->pp_cpq.ifq_maxlen = 20; 8174910Swollman sp->pp_loopcnt = 0; 8184910Swollman sp->pp_alivecnt = 0; 81911189Sjkh sp->pp_seq = 0; 8204910Swollman sp->pp_rseq = 0; 82125944Sjoerg sp->pp_phase = PHASE_DEAD; 82225944Sjoerg sp->pp_up = lcp.Up; 82325944Sjoerg sp->pp_down = lcp.Down; 82425944Sjoerg 82525944Sjoerg sppp_lcp_init(sp); 82625944Sjoerg sppp_ipcp_init(sp); 82730300Sjoerg sppp_pap_init(sp); 82830300Sjoerg sppp_chap_init(sp); 8294910Swollman} 8304910Swollman 83130300Sjoergvoid 83225706Sjoergsppp_detach(struct ifnet *ifp) 8334910Swollman{ 8344910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 83525944Sjoerg int i; 8364910Swollman 8374910Swollman /* Remove the entry from the keepalive list. */ 8384910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 8394910Swollman if (p == sp) { 8404910Swollman *q = p->pp_next; 8414910Swollman break; 8424910Swollman } 8434910Swollman 8444910Swollman /* Stop keepalive handler. */ 8454910Swollman if (! spppq) 84640008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 84725944Sjoerg 84825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 84940008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 85040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 8514910Swollman} 8524910Swollman 8534910Swollman/* 8544910Swollman * Flush the interface output queue. 8554910Swollman */ 85625706Sjoergvoid 85725706Sjoergsppp_flush(struct ifnet *ifp) 8584910Swollman{ 8594910Swollman struct sppp *sp = (struct sppp*) ifp; 8604910Swollman 86125944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 86225944Sjoerg sppp_qflush (&sp->pp_fastq); 86326018Sjoerg sppp_qflush (&sp->pp_cpq); 8644910Swollman} 8654910Swollman 8664910Swollman/* 86711189Sjkh * Check if the output queue is empty. 86811189Sjkh */ 86912820Sphkint 87025706Sjoergsppp_isempty(struct ifnet *ifp) 87111189Sjkh{ 87211189Sjkh struct sppp *sp = (struct sppp*) ifp; 87325944Sjoerg int empty, s; 87411189Sjkh 87525944Sjoerg s = splimp(); 87626018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 87726018Sjoerg !sp->pp_if.if_snd.ifq_head; 87825944Sjoerg splx(s); 87911189Sjkh return (empty); 88011189Sjkh} 88111189Sjkh 88211189Sjkh/* 8834910Swollman * Get next packet to send. 8844910Swollman */ 88525706Sjoergstruct mbuf * 88625706Sjoergsppp_dequeue(struct ifnet *ifp) 8874910Swollman{ 8884910Swollman struct sppp *sp = (struct sppp*) ifp; 8894910Swollman struct mbuf *m; 89025944Sjoerg int s; 8914910Swollman 89225944Sjoerg s = splimp(); 89326018Sjoerg /* 89430300Sjoerg * Process only the control protocol queue until we have at 89530300Sjoerg * least one NCP open. 89626018Sjoerg * 89726018Sjoerg * Do always serve all three queues in Cisco mode. 89826018Sjoerg */ 89926018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 90026018Sjoerg if (m == NULL && 90130300Sjoerg (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) { 90226018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 90326018Sjoerg if (m == NULL) 90426018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 90526018Sjoerg } 90626018Sjoerg splx(s); 90726018Sjoerg return m; 9084910Swollman} 9094910Swollman 9104910Swollman/* 91130300Sjoerg * Pick the next packet, do not remove it from the queue. 91230300Sjoerg */ 91330300Sjoergstruct mbuf * 91430300Sjoergsppp_pick(struct ifnet *ifp) 91530300Sjoerg{ 91630300Sjoerg struct sppp *sp = (struct sppp*)ifp; 91730300Sjoerg struct mbuf *m; 91830300Sjoerg int s; 91930300Sjoerg 92030300Sjoerg s= splimp (); 92130300Sjoerg 92230300Sjoerg m = sp->pp_cpq.ifq_head; 92330300Sjoerg if (m == NULL && 92430300Sjoerg (sp->pp_phase == PHASE_NETWORK || 92530300Sjoerg (sp->pp_flags & PP_CISCO) != 0)) 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; 95825944Sjoerg newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE); 95925944Sjoerg if (newmode == (IFF_AUTO | IFF_PASSIVE)) { 96025944Sjoerg /* sanity */ 96125944Sjoerg newmode = IFF_PASSIVE; 96225944Sjoerg ifp->if_flags &= ~IFF_AUTO; 9634910Swollman } 9644910Swollman 96525944Sjoerg if (going_up || going_down) 96625944Sjoerg lcp.Close(sp); 96725944Sjoerg if (going_up && newmode == 0) { 96825944Sjoerg /* neither auto-dial nor passive */ 96925944Sjoerg ifp->if_flags |= IFF_RUNNING; 97025944Sjoerg if (!(sp->pp_flags & PP_CISCO)) 97125944Sjoerg lcp.Open(sp); 97226018Sjoerg } else if (going_down) { 97326018Sjoerg sppp_flush(ifp); 97425944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 97526018Sjoerg } 9764910Swollman 9774910Swollman break; 97811189Sjkh 97925944Sjoerg#ifdef SIOCSIFMTU 98025944Sjoerg#ifndef ifr_mtu 98125944Sjoerg#define ifr_mtu ifr_metric 98225944Sjoerg#endif 98325944Sjoerg case SIOCSIFMTU: 98425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 98525944Sjoerg return (EINVAL); 98625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 9874910Swollman break; 98825944Sjoerg#endif 98925944Sjoerg#ifdef SLIOCSETMTU 99025944Sjoerg case SLIOCSETMTU: 99125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 99225944Sjoerg return (EINVAL); 99325944Sjoerg ifp->if_mtu = *(short*)data; 9944910Swollman break; 99525944Sjoerg#endif 99625944Sjoerg#ifdef SIOCGIFMTU 99725944Sjoerg case SIOCGIFMTU: 99825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 99911189Sjkh break; 100025944Sjoerg#endif 100125944Sjoerg#ifdef SLIOCGETMTU 100225944Sjoerg case SLIOCGETMTU: 100325944Sjoerg *(short*)data = ifp->if_mtu; 10044910Swollman break; 100525944Sjoerg#endif 100625944Sjoerg case SIOCADDMULTI: 100725944Sjoerg case SIOCDELMULTI: 10084910Swollman break; 100911189Sjkh 101030300Sjoerg case SIOCGIFGENERIC: 101130300Sjoerg case SIOCSIFGENERIC: 101230300Sjoerg rv = sppp_params(sp, cmd, data); 101330300Sjoerg break; 101430300Sjoerg 101525944Sjoerg default: 101630300Sjoerg rv = ENOTTY; 10174910Swollman } 101825944Sjoerg splx(s); 101930300Sjoerg return rv; 10204910Swollman} 10214910Swollman 102225944Sjoerg 102325944Sjoerg/* 102425944Sjoerg * Cisco framing implementation. 102525944Sjoerg */ 102625944Sjoerg 10274910Swollman/* 10284910Swollman * Handle incoming Cisco keepalive protocol packets. 10294910Swollman */ 103030300Sjoergstatic void 103125706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 10324910Swollman{ 103325944Sjoerg STDDCL; 10344910Swollman struct cisco_packet *h; 103530300Sjoerg u_long me, mymask; 10364910Swollman 103727929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 103825706Sjoerg if (debug) 103925706Sjoerg log(LOG_DEBUG, 104040008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 104140008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 10424910Swollman return; 10434910Swollman } 10444910Swollman h = mtod (m, struct cisco_packet*); 104525706Sjoerg if (debug) 104625706Sjoerg log(LOG_DEBUG, 104740008Sjoerg SPP_FMT "cisco input: %d bytes " 104825706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 104940008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 105040008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 105140008Sjoerg (u_int)h->time0, (u_int)h->time1); 10524910Swollman switch (ntohl (h->type)) { 10534910Swollman default: 105425706Sjoerg if (debug) 105540008Sjoerg addlog(SPP_FMT "cisco unknown packet type: 0x%lx\n", 105640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 10574910Swollman break; 10584910Swollman case CISCO_ADDR_REPLY: 10594910Swollman /* Reply on address request, ignore */ 10604910Swollman break; 10614910Swollman case CISCO_KEEPALIVE_REQ: 10624910Swollman sp->pp_alivecnt = 0; 10634910Swollman sp->pp_rseq = ntohl (h->par1); 10644910Swollman if (sp->pp_seq == sp->pp_rseq) { 10654910Swollman /* Local and remote sequence numbers are equal. 10664910Swollman * Probably, the line is in loopback mode. */ 106711189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 106840008Sjoerg printf (SPP_FMT "loopback\n", 106940008Sjoerg SPP_ARGS(ifp)); 107011189Sjkh sp->pp_loopcnt = 0; 107111189Sjkh if (ifp->if_flags & IFF_UP) { 107211189Sjkh if_down (ifp); 107326018Sjoerg sppp_qflush (&sp->pp_cpq); 107411189Sjkh } 107511189Sjkh } 10764910Swollman ++sp->pp_loopcnt; 10774910Swollman 10784910Swollman /* Generate new local sequence number */ 107942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 108035064Sphk sp->pp_seq = random(); 108140008Sjoerg#else 108240008Sjoerg sp->pp_seq ^= time.tv_sec ^ time.tv_usec; 108340008Sjoerg#endif 108411189Sjkh break; 108511189Sjkh } 108630300Sjoerg sp->pp_loopcnt = 0; 108711189Sjkh if (! (ifp->if_flags & IFF_UP) && 108811189Sjkh (ifp->if_flags & IFF_RUNNING)) { 108930300Sjoerg if_up(ifp); 109040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 109111189Sjkh } 10924910Swollman break; 10934910Swollman case CISCO_ADDR_REQ: 109430300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 109530300Sjoerg if (me != 0L) 109630300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 10974910Swollman break; 10984910Swollman } 10994910Swollman} 11004910Swollman 11014910Swollman/* 110225944Sjoerg * Send Cisco keepalive packet. 11034910Swollman */ 110412820Sphkstatic void 110525944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 110625944Sjoerg{ 110725944Sjoerg STDDCL; 110825944Sjoerg struct ppp_header *h; 110925944Sjoerg struct cisco_packet *ch; 111025944Sjoerg struct mbuf *m; 111142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 111235029Sphk struct timeval tv; 111340008Sjoerg#else 111440008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 111540008Sjoerg#endif 111625944Sjoerg 111742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 111836119Sphk getmicrouptime(&tv); 111940008Sjoerg#endif 112035029Sphk 112125944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 112225944Sjoerg if (! m) 112325944Sjoerg return; 112425944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 112525944Sjoerg m->m_pkthdr.rcvif = 0; 112625944Sjoerg 112725944Sjoerg h = mtod (m, struct ppp_header*); 112825944Sjoerg h->address = CISCO_MULTICAST; 112925944Sjoerg h->control = 0; 113025944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 113125944Sjoerg 113225944Sjoerg ch = (struct cisco_packet*) (h + 1); 113325944Sjoerg ch->type = htonl (type); 113425944Sjoerg ch->par1 = htonl (par1); 113525944Sjoerg ch->par2 = htonl (par2); 113625944Sjoerg ch->rel = -1; 113740008Sjoerg 113842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 113935029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 114035029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 114140008Sjoerg#else 114240008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 114340008Sjoerg ch->time1 = htons ((u_short) t); 114440008Sjoerg#endif 114525944Sjoerg 114625944Sjoerg if (debug) 114725944Sjoerg log(LOG_DEBUG, 114840008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 114940008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 115040008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 115125944Sjoerg 115226018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 115326018Sjoerg IF_DROP (&sp->pp_fastq); 115425944Sjoerg IF_DROP (&ifp->if_snd); 115525944Sjoerg m_freem (m); 115625944Sjoerg } else 115726018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 115825944Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 115925944Sjoerg (*ifp->if_start) (ifp); 116025944Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 116125944Sjoerg} 116225944Sjoerg 116325944Sjoerg/* 116425944Sjoerg * PPP protocol implementation. 116525944Sjoerg */ 116625944Sjoerg 116725944Sjoerg/* 116825944Sjoerg * Send PPP control protocol packet. 116925944Sjoerg */ 117025944Sjoergstatic void 117125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 117225706Sjoerg u_char ident, u_short len, void *data) 11734910Swollman{ 117425944Sjoerg STDDCL; 11754910Swollman struct ppp_header *h; 11764910Swollman struct lcp_header *lh; 11774910Swollman struct mbuf *m; 11784910Swollman 11794910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 11804910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 11814910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 11824910Swollman if (! m) 11834910Swollman return; 11844910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 11854910Swollman m->m_pkthdr.rcvif = 0; 11864910Swollman 11874910Swollman h = mtod (m, struct ppp_header*); 11884910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 11894910Swollman h->control = PPP_UI; /* Unnumbered Info */ 11904910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 11914910Swollman 11924910Swollman lh = (struct lcp_header*) (h + 1); 11934910Swollman lh->type = type; 11944910Swollman lh->ident = ident; 11954910Swollman lh->len = htons (LCP_HEADER_LEN + len); 11964910Swollman if (len) 11974910Swollman bcopy (data, lh+1, len); 11984910Swollman 119925706Sjoerg if (debug) { 120040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 120140008Sjoerg SPP_ARGS(ifp), 120225944Sjoerg sppp_proto_name(proto), 120325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 120425944Sjoerg ntohs (lh->len)); 12054910Swollman if (len) 120611189Sjkh sppp_print_bytes ((u_char*) (lh+1), len); 120725706Sjoerg addlog(">\n"); 12084910Swollman } 120926018Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 121026018Sjoerg IF_DROP (&sp->pp_fastq); 12114910Swollman IF_DROP (&ifp->if_snd); 12124910Swollman m_freem (m); 121325944Sjoerg ++ifp->if_oerrors; 12144910Swollman } else 121526018Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 12164910Swollman if (! (ifp->if_flags & IFF_OACTIVE)) 12174910Swollman (*ifp->if_start) (ifp); 12184910Swollman ifp->if_obytes += m->m_pkthdr.len + 3; 12194910Swollman} 12204910Swollman 12214910Swollman/* 122225944Sjoerg * Handle incoming PPP control protocol packets. 12234910Swollman */ 122412820Sphkstatic void 122525944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 12264910Swollman{ 122725944Sjoerg STDDCL; 122825944Sjoerg struct lcp_header *h; 122925944Sjoerg int len = m->m_pkthdr.len; 123025944Sjoerg int rv; 123125944Sjoerg u_char *p; 12324910Swollman 123325944Sjoerg if (len < 4) { 123425944Sjoerg if (debug) 123525944Sjoerg log(LOG_DEBUG, 123640008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 123740008Sjoerg SPP_ARGS(ifp), cp->name, len); 12384910Swollman return; 123925944Sjoerg } 124025944Sjoerg h = mtod (m, struct lcp_header*); 124125944Sjoerg if (debug) { 124225944Sjoerg log(LOG_DEBUG, 124340008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 124440008Sjoerg SPP_ARGS(ifp), cp->name, 124525944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 124625944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 124725944Sjoerg if (len > 4) 124825944Sjoerg sppp_print_bytes ((u_char*) (h+1), len-4); 124925944Sjoerg addlog(">\n"); 125025944Sjoerg } 125125944Sjoerg if (len > ntohs (h->len)) 125225944Sjoerg len = ntohs (h->len); 125330300Sjoerg p = (u_char *)(h + 1); 125425944Sjoerg switch (h->type) { 125525944Sjoerg case CONF_REQ: 125625944Sjoerg if (len < 4) { 125725944Sjoerg if (debug) 125840008Sjoerg addlog(SPP_FMT "%s invalid conf-req length %d\n", 125940008Sjoerg SPP_ARGS(ifp), cp->name, 126025944Sjoerg len); 126125944Sjoerg ++ifp->if_ierrors; 126225944Sjoerg break; 126325944Sjoerg } 126430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 126530300Sjoerg switch (sp->state[cp->protoidx]) { 126630300Sjoerg case STATE_CLOSING: 126730300Sjoerg case STATE_STOPPING: 126830300Sjoerg return; 126930300Sjoerg case STATE_CLOSED: 127030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 127130300Sjoerg 0, 0); 127230300Sjoerg return; 127330300Sjoerg } 127425944Sjoerg rv = (cp->RCR)(sp, h, len); 127525944Sjoerg switch (sp->state[cp->protoidx]) { 127625944Sjoerg case STATE_OPENED: 127725944Sjoerg (cp->tld)(sp); 127825944Sjoerg (cp->scr)(sp); 127925944Sjoerg /* fall through... */ 128025944Sjoerg case STATE_ACK_SENT: 128125944Sjoerg case STATE_REQ_SENT: 128225944Sjoerg sppp_cp_change_state(cp, sp, rv? 128325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 128425944Sjoerg break; 128525944Sjoerg case STATE_STOPPED: 128625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 128725944Sjoerg (cp->scr)(sp); 128825944Sjoerg sppp_cp_change_state(cp, sp, rv? 128925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 129025944Sjoerg break; 129125944Sjoerg case STATE_ACK_RCVD: 129225944Sjoerg if (rv) { 129325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 129425944Sjoerg if (debug) 129540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 129640008Sjoerg SPP_ARGS(ifp), 129726077Sjoerg cp->name); 129825944Sjoerg (cp->tlu)(sp); 129925944Sjoerg } else 130025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 130125944Sjoerg break; 130225944Sjoerg default: 130340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 130440008Sjoerg SPP_ARGS(ifp), cp->name, 130525944Sjoerg sppp_cp_type_name(h->type), 130625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 130725944Sjoerg ++ifp->if_ierrors; 130825944Sjoerg } 130925944Sjoerg break; 131025944Sjoerg case CONF_ACK: 131125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 131225944Sjoerg if (debug) 131340008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 131440008Sjoerg SPP_ARGS(ifp), cp->name, 131525944Sjoerg h->ident, sp->confid[cp->protoidx]); 131625944Sjoerg ++ifp->if_ierrors; 131725944Sjoerg break; 131825944Sjoerg } 131925944Sjoerg switch (sp->state[cp->protoidx]) { 132025944Sjoerg case STATE_CLOSED: 132125944Sjoerg case STATE_STOPPED: 132225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 132325944Sjoerg break; 132425944Sjoerg case STATE_CLOSING: 132525944Sjoerg case STATE_STOPPING: 132625944Sjoerg break; 132725944Sjoerg case STATE_REQ_SENT: 132825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 132925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 133025944Sjoerg break; 133125944Sjoerg case STATE_OPENED: 133225944Sjoerg (cp->tld)(sp); 133325944Sjoerg /* fall through */ 133425944Sjoerg case STATE_ACK_RCVD: 133525944Sjoerg (cp->scr)(sp); 133625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 133725944Sjoerg break; 133825944Sjoerg case STATE_ACK_SENT: 133925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 134025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 134125944Sjoerg if (debug) 134240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 134340008Sjoerg SPP_ARGS(ifp), cp->name); 134425944Sjoerg (cp->tlu)(sp); 134525944Sjoerg break; 134625944Sjoerg default: 134740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 134840008Sjoerg SPP_ARGS(ifp), cp->name, 134925944Sjoerg sppp_cp_type_name(h->type), 135025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 135125944Sjoerg ++ifp->if_ierrors; 135225944Sjoerg } 135325944Sjoerg break; 135425944Sjoerg case CONF_NAK: 135525944Sjoerg case CONF_REJ: 135625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 135725944Sjoerg if (debug) 135840008Sjoerg addlog(SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 135940008Sjoerg SPP_ARGS(ifp), cp->name, 136025944Sjoerg h->ident, sp->confid[cp->protoidx]); 136125944Sjoerg ++ifp->if_ierrors; 136225944Sjoerg break; 136325944Sjoerg } 136425944Sjoerg if (h->type == CONF_NAK) 136525944Sjoerg (cp->RCN_nak)(sp, h, len); 136625944Sjoerg else /* CONF_REJ */ 136725944Sjoerg (cp->RCN_rej)(sp, h, len); 13684910Swollman 136925944Sjoerg switch (sp->state[cp->protoidx]) { 137025944Sjoerg case STATE_CLOSED: 137125944Sjoerg case STATE_STOPPED: 137225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 137325944Sjoerg break; 137425944Sjoerg case STATE_REQ_SENT: 137525944Sjoerg case STATE_ACK_SENT: 137625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 137725944Sjoerg (cp->scr)(sp); 137825944Sjoerg break; 137925944Sjoerg case STATE_OPENED: 138025944Sjoerg (cp->tld)(sp); 138125944Sjoerg /* fall through */ 138225944Sjoerg case STATE_ACK_RCVD: 138325944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_SENT); 138425944Sjoerg (cp->scr)(sp); 138525944Sjoerg break; 138625944Sjoerg case STATE_CLOSING: 138725944Sjoerg case STATE_STOPPING: 138825944Sjoerg break; 138925944Sjoerg default: 139040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 139140008Sjoerg SPP_ARGS(ifp), cp->name, 139225944Sjoerg sppp_cp_type_name(h->type), 139325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 139425944Sjoerg ++ifp->if_ierrors; 139525944Sjoerg } 139625944Sjoerg break; 13974910Swollman 139825944Sjoerg case TERM_REQ: 139925944Sjoerg switch (sp->state[cp->protoidx]) { 140025944Sjoerg case STATE_ACK_RCVD: 140125944Sjoerg case STATE_ACK_SENT: 140225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 140325944Sjoerg /* fall through */ 140425944Sjoerg case STATE_CLOSED: 140525944Sjoerg case STATE_STOPPED: 140625944Sjoerg case STATE_CLOSING: 140725944Sjoerg case STATE_STOPPING: 140825944Sjoerg case STATE_REQ_SENT: 140925944Sjoerg sta: 141025944Sjoerg /* Send Terminate-Ack packet. */ 141125944Sjoerg if (debug) 141240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 141340008Sjoerg SPP_ARGS(ifp), cp->name); 141425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 141525944Sjoerg break; 141625944Sjoerg case STATE_OPENED: 141725944Sjoerg (cp->tld)(sp); 141825944Sjoerg sp->rst_counter[cp->protoidx] = 0; 141925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 142025944Sjoerg goto sta; 142125944Sjoerg break; 142225944Sjoerg default: 142340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 142440008Sjoerg SPP_ARGS(ifp), cp->name, 142525944Sjoerg sppp_cp_type_name(h->type), 142625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 142725944Sjoerg ++ifp->if_ierrors; 142825944Sjoerg } 142925944Sjoerg break; 143025944Sjoerg case TERM_ACK: 143125944Sjoerg switch (sp->state[cp->protoidx]) { 143225944Sjoerg case STATE_CLOSED: 143325944Sjoerg case STATE_STOPPED: 143425944Sjoerg case STATE_REQ_SENT: 143525944Sjoerg case STATE_ACK_SENT: 143625944Sjoerg break; 143725944Sjoerg case STATE_CLOSING: 143841881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 143925944Sjoerg (cp->tlf)(sp); 144025944Sjoerg break; 144125944Sjoerg case STATE_STOPPING: 144241881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 144325944Sjoerg (cp->tlf)(sp); 144425944Sjoerg break; 144525944Sjoerg case STATE_ACK_RCVD: 144625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 144725944Sjoerg break; 144825944Sjoerg case STATE_OPENED: 144925944Sjoerg (cp->tld)(sp); 145025944Sjoerg (cp->scr)(sp); 145125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 145225944Sjoerg break; 145325944Sjoerg default: 145440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 145540008Sjoerg SPP_ARGS(ifp), cp->name, 145625944Sjoerg sppp_cp_type_name(h->type), 145725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 145825944Sjoerg ++ifp->if_ierrors; 145925944Sjoerg } 146025944Sjoerg break; 146125944Sjoerg case CODE_REJ: 146225944Sjoerg case PROTO_REJ: 146325944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 146430300Sjoerg log(LOG_INFO, 146540008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 146630300Sjoerg "danger will robinson\n", 146740008Sjoerg SPP_ARGS(ifp), cp->name, 146830300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 146925944Sjoerg switch (sp->state[cp->protoidx]) { 147025944Sjoerg case STATE_CLOSED: 147125944Sjoerg case STATE_STOPPED: 147225944Sjoerg case STATE_REQ_SENT: 147325944Sjoerg case STATE_ACK_SENT: 147425944Sjoerg case STATE_CLOSING: 147525944Sjoerg case STATE_STOPPING: 147625944Sjoerg case STATE_OPENED: 147725944Sjoerg break; 147825944Sjoerg case STATE_ACK_RCVD: 147925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148025944Sjoerg break; 148125944Sjoerg default: 148240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 148340008Sjoerg SPP_ARGS(ifp), cp->name, 148425944Sjoerg sppp_cp_type_name(h->type), 148525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 148625944Sjoerg ++ifp->if_ierrors; 148725944Sjoerg } 148825944Sjoerg break; 148925944Sjoerg case DISC_REQ: 149025944Sjoerg if (cp->proto != PPP_LCP) 149125944Sjoerg goto illegal; 149225944Sjoerg /* Discard the packet. */ 149325944Sjoerg break; 149425944Sjoerg case ECHO_REQ: 149525944Sjoerg if (cp->proto != PPP_LCP) 149625944Sjoerg goto illegal; 149725944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 149825944Sjoerg if (debug) 149940008Sjoerg addlog(SPP_FMT "lcp echo req but lcp closed\n", 150040008Sjoerg SPP_ARGS(ifp)); 150125944Sjoerg ++ifp->if_ierrors; 150225944Sjoerg break; 150325944Sjoerg } 150425944Sjoerg if (len < 8) { 150525944Sjoerg if (debug) 150640008Sjoerg addlog(SPP_FMT "invalid lcp echo request " 150725944Sjoerg "packet length: %d bytes\n", 150840008Sjoerg SPP_ARGS(ifp), len); 150925944Sjoerg break; 151025944Sjoerg } 151125944Sjoerg if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { 151225944Sjoerg /* Line loopback mode detected. */ 151340008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 151425944Sjoerg if_down (ifp); 151526018Sjoerg sppp_qflush (&sp->pp_cpq); 15164910Swollman 151725944Sjoerg /* Shut down the PPP link. */ 151825944Sjoerg /* XXX */ 151925944Sjoerg lcp.Down(sp); 152025944Sjoerg lcp.Up(sp); 152125944Sjoerg break; 152225944Sjoerg } 152325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 152425944Sjoerg if (debug) 152540008Sjoerg addlog(SPP_FMT "got lcp echo req, sending echo rep\n", 152640008Sjoerg SPP_ARGS(ifp)); 152725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 152825944Sjoerg break; 152925944Sjoerg case ECHO_REPLY: 153025944Sjoerg if (cp->proto != PPP_LCP) 153125944Sjoerg goto illegal; 153225944Sjoerg if (h->ident != sp->lcp.echoid) { 153325944Sjoerg ++ifp->if_ierrors; 153425944Sjoerg break; 153525944Sjoerg } 153625944Sjoerg if (len < 8) { 153725944Sjoerg if (debug) 153840008Sjoerg addlog(SPP_FMT "lcp invalid echo reply " 153925944Sjoerg "packet length: %d bytes\n", 154040008Sjoerg SPP_ARGS(ifp), len); 154125944Sjoerg break; 154225944Sjoerg } 154325944Sjoerg if (debug) 154440008Sjoerg addlog(SPP_FMT "lcp got echo rep\n", 154540008Sjoerg SPP_ARGS(ifp)); 154625944Sjoerg if (ntohl (*(long*)(h+1)) != sp->lcp.magic) 154725944Sjoerg sp->pp_alivecnt = 0; 154825944Sjoerg break; 154925944Sjoerg default: 155025944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 155125944Sjoerg illegal: 155225944Sjoerg if (debug) 155340008Sjoerg addlog(SPP_FMT "%s send code-rej for 0x%x\n", 155440008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 155525944Sjoerg sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq, 155625944Sjoerg m->m_pkthdr.len, h); 155725944Sjoerg ++ifp->if_ierrors; 155825944Sjoerg } 15594910Swollman} 15604910Swollman 156125944Sjoerg 15624910Swollman/* 156325944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 156425944Sjoerg * Basically, the state transition handling in the automaton. 15654910Swollman */ 156625944Sjoergstatic void 156725944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 15684910Swollman{ 156925944Sjoerg STDDCL; 15704910Swollman 157125944Sjoerg if (debug) 157240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 157340008Sjoerg SPP_ARGS(ifp), cp->name, 157425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 157525944Sjoerg 157625944Sjoerg switch (sp->state[cp->protoidx]) { 157725944Sjoerg case STATE_INITIAL: 157825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 157925944Sjoerg break; 158025944Sjoerg case STATE_STARTING: 158125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 158225944Sjoerg (cp->scr)(sp); 158325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 158425944Sjoerg break; 15854910Swollman default: 158640008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 158740008Sjoerg SPP_ARGS(ifp), cp->name, 158825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158925944Sjoerg } 159025944Sjoerg} 15914910Swollman 159225944Sjoergstatic void 159325944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 159425944Sjoerg{ 159525944Sjoerg STDDCL; 159625944Sjoerg 159725944Sjoerg if (debug) 159840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 159940008Sjoerg SPP_ARGS(ifp), cp->name, 160025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160125944Sjoerg 160225944Sjoerg switch (sp->state[cp->protoidx]) { 160325944Sjoerg case STATE_CLOSED: 160425944Sjoerg case STATE_CLOSING: 160525944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 16064910Swollman break; 160725944Sjoerg case STATE_STOPPED: 160841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 160925944Sjoerg (cp->tls)(sp); 161041881Sphk break; 161125944Sjoerg case STATE_STOPPING: 161225944Sjoerg case STATE_REQ_SENT: 161325944Sjoerg case STATE_ACK_RCVD: 161425944Sjoerg case STATE_ACK_SENT: 161525944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 161625944Sjoerg break; 161725944Sjoerg case STATE_OPENED: 161825944Sjoerg (cp->tld)(sp); 161925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 162025944Sjoerg break; 162125944Sjoerg default: 162240008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 162340008Sjoerg SPP_ARGS(ifp), cp->name, 162425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 162525944Sjoerg } 162625944Sjoerg} 16274910Swollman 162811189Sjkh 162925944Sjoergstatic void 163025944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 163125944Sjoerg{ 163225944Sjoerg STDDCL; 163325944Sjoerg 163425944Sjoerg if (debug) 163540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 163640008Sjoerg SPP_ARGS(ifp), cp->name, 163725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163825944Sjoerg 163925944Sjoerg switch (sp->state[cp->protoidx]) { 164025944Sjoerg case STATE_INITIAL: 164141881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 164225944Sjoerg (cp->tls)(sp); 16434910Swollman break; 164425944Sjoerg case STATE_STARTING: 164525944Sjoerg break; 164625944Sjoerg case STATE_CLOSED: 164725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 164825944Sjoerg (cp->scr)(sp); 164925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 165025944Sjoerg break; 165125944Sjoerg case STATE_STOPPED: 165225944Sjoerg case STATE_STOPPING: 165325944Sjoerg case STATE_REQ_SENT: 165425944Sjoerg case STATE_ACK_RCVD: 165525944Sjoerg case STATE_ACK_SENT: 165625944Sjoerg case STATE_OPENED: 165725944Sjoerg break; 165825944Sjoerg case STATE_CLOSING: 165925944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 166025944Sjoerg break; 166125944Sjoerg } 166225944Sjoerg} 16634910Swollman 166425944Sjoerg 166525944Sjoergstatic void 166625944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 166725944Sjoerg{ 166825944Sjoerg STDDCL; 166925944Sjoerg 167025944Sjoerg if (debug) 167140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 167240008Sjoerg SPP_ARGS(ifp), cp->name, 167325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 167425944Sjoerg 167525944Sjoerg switch (sp->state[cp->protoidx]) { 167625944Sjoerg case STATE_INITIAL: 167725944Sjoerg case STATE_CLOSED: 167825944Sjoerg case STATE_CLOSING: 16794910Swollman break; 168025944Sjoerg case STATE_STARTING: 168141881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 168225944Sjoerg (cp->tlf)(sp); 16834910Swollman break; 168425944Sjoerg case STATE_STOPPED: 168525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 16864910Swollman break; 168725944Sjoerg case STATE_STOPPING: 168825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16894910Swollman break; 169025944Sjoerg case STATE_OPENED: 169125944Sjoerg (cp->tld)(sp); 169225944Sjoerg /* fall through */ 169325944Sjoerg case STATE_REQ_SENT: 169425944Sjoerg case STATE_ACK_RCVD: 169525944Sjoerg case STATE_ACK_SENT: 169625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 169725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0); 169825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 16994910Swollman break; 17004910Swollman } 17014910Swollman} 17024910Swollman 170325944Sjoergstatic void 170425944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 170525944Sjoerg{ 170625944Sjoerg STDDCL; 170725944Sjoerg int s; 170825944Sjoerg 170925944Sjoerg s = splimp(); 171025944Sjoerg if (debug) 171140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 171240008Sjoerg SPP_ARGS(ifp), cp->name, 171325944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 171425944Sjoerg sp->rst_counter[cp->protoidx]); 171525944Sjoerg 171625944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 171725944Sjoerg /* TO- event */ 171825944Sjoerg switch (sp->state[cp->protoidx]) { 171925944Sjoerg case STATE_CLOSING: 172041881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 172125944Sjoerg (cp->tlf)(sp); 172225944Sjoerg break; 172325944Sjoerg case STATE_STOPPING: 172441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 172525944Sjoerg (cp->tlf)(sp); 172625944Sjoerg break; 172725944Sjoerg case STATE_REQ_SENT: 172825944Sjoerg case STATE_ACK_RCVD: 172925944Sjoerg case STATE_ACK_SENT: 173041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 173125944Sjoerg (cp->tlf)(sp); 173225944Sjoerg break; 173325944Sjoerg } 173425944Sjoerg else 173525944Sjoerg /* TO+ event */ 173625944Sjoerg switch (sp->state[cp->protoidx]) { 173725944Sjoerg case STATE_CLOSING: 173825944Sjoerg case STATE_STOPPING: 173925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 174025944Sjoerg 0, 0); 174142064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 174242064Sphk sp->ch[cp->protoidx]); 174325944Sjoerg break; 174425944Sjoerg case STATE_REQ_SENT: 174525944Sjoerg case STATE_ACK_RCVD: 174625944Sjoerg (cp->scr)(sp); 174725944Sjoerg /* sppp_cp_change_state() will restart the timer */ 174825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174925944Sjoerg break; 175025944Sjoerg case STATE_ACK_SENT: 175125944Sjoerg (cp->scr)(sp); 175242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 175342064Sphk sp->ch[cp->protoidx]); 175425944Sjoerg break; 175525944Sjoerg } 175625944Sjoerg 175725944Sjoerg splx(s); 175825944Sjoerg} 175925944Sjoerg 176011189Sjkh/* 176125944Sjoerg * Change the state of a control protocol in the state automaton. 176225944Sjoerg * Takes care of starting/stopping the restart timer. 176311189Sjkh */ 176425944Sjoergvoid 176525944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 176625944Sjoerg{ 176725944Sjoerg sp->state[cp->protoidx] = newstate; 176825944Sjoerg 176940008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 177025944Sjoerg switch (newstate) { 177125944Sjoerg case STATE_INITIAL: 177225944Sjoerg case STATE_STARTING: 177325944Sjoerg case STATE_CLOSED: 177425944Sjoerg case STATE_STOPPED: 177525944Sjoerg case STATE_OPENED: 177625944Sjoerg break; 177725944Sjoerg case STATE_CLOSING: 177825944Sjoerg case STATE_STOPPING: 177925944Sjoerg case STATE_REQ_SENT: 178025944Sjoerg case STATE_ACK_RCVD: 178125944Sjoerg case STATE_ACK_SENT: 178242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 178342064Sphk sp->ch[cp->protoidx]); 178425944Sjoerg break; 178525944Sjoerg } 178625944Sjoerg} 178725944Sjoerg/* 178825944Sjoerg *--------------------------------------------------------------------------* 178925944Sjoerg * * 179025944Sjoerg * The LCP implementation. * 179125944Sjoerg * * 179225944Sjoerg *--------------------------------------------------------------------------* 179325944Sjoerg */ 179425944Sjoergstatic void 179525944Sjoergsppp_lcp_init(struct sppp *sp) 179625944Sjoerg{ 179725944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 179825944Sjoerg sp->lcp.magic = 0; 179925944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 180025944Sjoerg sp->fail_counter[IDX_LCP] = 0; 180125944Sjoerg sp->lcp.protos = 0; 180225944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 180330300Sjoerg 180425944Sjoerg /* 180525944Sjoerg * Initialize counters and timeout values. Note that we don't 180625944Sjoerg * use the 3 seconds suggested in RFC 1661 since we are likely 180725944Sjoerg * running on a fast link. XXX We should probably implement 180825944Sjoerg * the exponential backoff option. Note that these values are 180925944Sjoerg * relevant for all control protocols, not just LCP only. 181025944Sjoerg */ 181125944Sjoerg sp->lcp.timeout = 1 * hz; 181225944Sjoerg sp->lcp.max_terminate = 2; 181325944Sjoerg sp->lcp.max_configure = 10; 181425944Sjoerg sp->lcp.max_failure = 10; 181542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 181630300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 181740008Sjoerg#endif 181825944Sjoerg} 181925944Sjoerg 182025944Sjoergstatic void 182125944Sjoergsppp_lcp_up(struct sppp *sp) 182225944Sjoerg{ 182325944Sjoerg STDDCL; 182425944Sjoerg 182525944Sjoerg /* 182630300Sjoerg * If this interface is passive or dial-on-demand, and we are 182730300Sjoerg * still in Initial state, it means we've got an incoming 182830300Sjoerg * call. Activate the interface. 182925944Sjoerg */ 183025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 183125944Sjoerg if (debug) 183225944Sjoerg log(LOG_DEBUG, 183340008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 183425944Sjoerg ifp->if_flags |= IFF_RUNNING; 183530300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 183630300Sjoerg if (debug) 183730300Sjoerg addlog("(incoming call)\n"); 183830300Sjoerg sp->pp_flags |= PP_CALLIN; 183930300Sjoerg lcp.Open(sp); 184030300Sjoerg } else if (debug) 184130300Sjoerg addlog("\n"); 184225944Sjoerg } 184325944Sjoerg 184425944Sjoerg sppp_up_event(&lcp, sp); 184525944Sjoerg} 184625944Sjoerg 184725944Sjoergstatic void 184825944Sjoergsppp_lcp_down(struct sppp *sp) 184925944Sjoerg{ 185025944Sjoerg STDDCL; 185125944Sjoerg 185225944Sjoerg sppp_down_event(&lcp, sp); 185325944Sjoerg 185425944Sjoerg /* 185525944Sjoerg * If this is neither a dial-on-demand nor a passive 185625944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 185725944Sjoerg * administrator can force a redial by another ``ifconfig 185825944Sjoerg * up''. XXX For leased line operation, should we immediately 185925944Sjoerg * try to reopen the connection here? 186025944Sjoerg */ 186125944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 186225944Sjoerg log(LOG_INFO, 186342066Sphk SPP_FMT "Down event, taking interface down.\n", 186440008Sjoerg SPP_ARGS(ifp)); 186525944Sjoerg if_down(ifp); 186625944Sjoerg } else { 186725944Sjoerg if (debug) 186825944Sjoerg log(LOG_DEBUG, 186940008Sjoerg SPP_FMT "Down event (carrier loss)\n", 187040008Sjoerg SPP_ARGS(ifp)); 187125944Sjoerg } 187230300Sjoerg sp->pp_flags &= ~PP_CALLIN; 187330300Sjoerg if (sp->state[IDX_LCP] != STATE_INITIAL) 187430300Sjoerg lcp.Close(sp); 187525944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 187625944Sjoerg} 187725944Sjoerg 187825944Sjoergstatic void 187925944Sjoergsppp_lcp_open(struct sppp *sp) 188025944Sjoerg{ 188130300Sjoerg /* 188230300Sjoerg * If we are authenticator, negotiate LCP_AUTH 188330300Sjoerg */ 188430300Sjoerg if (sp->hisauth.proto != 0) 188530300Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 188630300Sjoerg else 188730300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 188830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 188925944Sjoerg sppp_open_event(&lcp, sp); 189025944Sjoerg} 189125944Sjoerg 189225944Sjoergstatic void 189325944Sjoergsppp_lcp_close(struct sppp *sp) 189425944Sjoerg{ 189525944Sjoerg sppp_close_event(&lcp, sp); 189625944Sjoerg} 189725944Sjoerg 189825944Sjoergstatic void 189925944Sjoergsppp_lcp_TO(void *cookie) 190025944Sjoerg{ 190125944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 190225944Sjoerg} 190325944Sjoerg 190425944Sjoerg/* 190525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 190625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 190725944Sjoerg * caused action scn. (The return value is used to make the state 190825944Sjoerg * transition decision in the state automaton.) 190925944Sjoerg */ 191012820Sphkstatic int 191125944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 19124910Swollman{ 191325944Sjoerg STDDCL; 191411189Sjkh u_char *buf, *r, *p; 191525944Sjoerg int origlen, rlen; 191625944Sjoerg u_long nmagic; 191730300Sjoerg u_short authproto; 19184910Swollman 191911189Sjkh len -= 4; 192025944Sjoerg origlen = len; 192111189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 192211189Sjkh if (! buf) 192311189Sjkh return (0); 19244910Swollman 192525706Sjoerg if (debug) 192640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 192740008Sjoerg SPP_ARGS(ifp)); 192825706Sjoerg 192925944Sjoerg /* pass 1: check for things that need to be rejected */ 193011189Sjkh p = (void*) (h+1); 193111189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 193225944Sjoerg if (debug) 193325944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 193411189Sjkh switch (*p) { 193511189Sjkh case LCP_OPT_MAGIC: 193625944Sjoerg /* Magic number. */ 193725944Sjoerg /* fall through, both are same length */ 193825944Sjoerg case LCP_OPT_ASYNC_MAP: 193925944Sjoerg /* Async control character map. */ 194025944Sjoerg if (len >= 6 || p[1] == 6) 194125944Sjoerg continue; 194225944Sjoerg if (debug) 194325944Sjoerg addlog("[invalid] "); 194425944Sjoerg break; 194525944Sjoerg case LCP_OPT_MRU: 194625944Sjoerg /* Maximum receive unit. */ 194725944Sjoerg if (len >= 4 && p[1] == 4) 194825944Sjoerg continue; 194925944Sjoerg if (debug) 195025944Sjoerg addlog("[invalid] "); 195125944Sjoerg break; 195230300Sjoerg case LCP_OPT_AUTH_PROTO: 195330300Sjoerg if (len < 4) { 195430300Sjoerg if (debug) 195530300Sjoerg addlog("[invalid] "); 195630300Sjoerg break; 195730300Sjoerg } 195830300Sjoerg authproto = (p[2] << 8) + p[3]; 195930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 196030300Sjoerg if (debug) 196130300Sjoerg addlog("[invalid chap len] "); 196230300Sjoerg break; 196330300Sjoerg } 196430300Sjoerg if (sp->myauth.proto == 0) { 196530300Sjoerg /* we are not configured to do auth */ 196630300Sjoerg if (debug) 196730300Sjoerg addlog("[not configured] "); 196830300Sjoerg break; 196930300Sjoerg } 197030300Sjoerg /* 197130300Sjoerg * Remote want us to authenticate, remember this, 197230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 197330300Sjoerg * up. 197430300Sjoerg */ 197530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 197630300Sjoerg continue; 197725944Sjoerg default: 197825944Sjoerg /* Others not supported. */ 197925944Sjoerg if (debug) 198025944Sjoerg addlog("[rej] "); 198125944Sjoerg break; 198225944Sjoerg } 198325944Sjoerg /* Add the option to rejected list. */ 198425944Sjoerg bcopy (p, r, p[1]); 198525944Sjoerg r += p[1]; 198625944Sjoerg rlen += p[1]; 198725944Sjoerg } 198825944Sjoerg if (rlen) { 198925944Sjoerg if (debug) 199025944Sjoerg addlog(" send conf-rej\n"); 199125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 199225944Sjoerg return 0; 199325944Sjoerg } else if (debug) 199425944Sjoerg addlog("\n"); 199525944Sjoerg 199625944Sjoerg /* 199725944Sjoerg * pass 2: check for option values that are unacceptable and 199825944Sjoerg * thus require to be nak'ed. 199925944Sjoerg */ 200025944Sjoerg if (debug) 200140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 200240008Sjoerg SPP_ARGS(ifp)); 200325944Sjoerg 200425944Sjoerg p = (void*) (h+1); 200525944Sjoerg len = origlen; 200625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 200725944Sjoerg if (debug) 200825944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 200925944Sjoerg switch (*p) { 201025944Sjoerg case LCP_OPT_MAGIC: 201111189Sjkh /* Magic number -- extract. */ 201225944Sjoerg nmagic = (u_long)p[2] << 24 | 201325944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 201425944Sjoerg if (nmagic != sp->lcp.magic) { 201525706Sjoerg if (debug) 201638372Sbde addlog("0x%lx ", nmagic); 201711189Sjkh continue; 201811189Sjkh } 201925944Sjoerg /* 202025944Sjoerg * Local and remote magics equal -- loopback? 202125944Sjoerg */ 202225944Sjoerg if (sp->pp_loopcnt >= MAXALIVECNT*5) { 202340008Sjoerg printf (SPP_FMT "loopback\n", 202440008Sjoerg SPP_ARGS(ifp)); 202525944Sjoerg sp->pp_loopcnt = 0; 202625944Sjoerg if (ifp->if_flags & IFF_UP) { 202725944Sjoerg if_down(ifp); 202826018Sjoerg sppp_qflush(&sp->pp_cpq); 202925944Sjoerg /* XXX ? */ 203025944Sjoerg lcp.Down(sp); 203125944Sjoerg lcp.Up(sp); 203225944Sjoerg } 203325944Sjoerg } else if (debug) 203425944Sjoerg addlog("[glitch] "); 203525944Sjoerg ++sp->pp_loopcnt; 203625944Sjoerg /* 203725944Sjoerg * We negate our magic here, and NAK it. If 203825944Sjoerg * we see it later in an NAK packet, we 203925944Sjoerg * suggest a new one. 204025944Sjoerg */ 204125944Sjoerg nmagic = ~sp->lcp.magic; 204225944Sjoerg /* Gonna NAK it. */ 204325944Sjoerg p[2] = nmagic >> 24; 204425944Sjoerg p[3] = nmagic >> 16; 204525944Sjoerg p[4] = nmagic >> 8; 204625944Sjoerg p[5] = nmagic; 204711189Sjkh break; 204825944Sjoerg 204911189Sjkh case LCP_OPT_ASYNC_MAP: 205011189Sjkh /* Async control character map -- check to be zero. */ 205125944Sjoerg if (! p[2] && ! p[3] && ! p[4] && ! p[5]) { 205225706Sjoerg if (debug) 205325944Sjoerg addlog("[empty] "); 205411189Sjkh continue; 205525706Sjoerg } 205625706Sjoerg if (debug) 205725944Sjoerg addlog("[non-empty] "); 205825944Sjoerg /* suggest a zero one */ 205925944Sjoerg p[2] = p[3] = p[4] = p[5] = 0; 206011189Sjkh break; 206125944Sjoerg 206211189Sjkh case LCP_OPT_MRU: 206325944Sjoerg /* 206425944Sjoerg * Maximum receive unit. Always agreeable, 206525944Sjoerg * but ignored by now. 206625944Sjoerg */ 206725944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 206825706Sjoerg if (debug) 206938372Sbde addlog("%lu ", sp->lcp.their_mru); 207011189Sjkh continue; 207130300Sjoerg 207230300Sjoerg case LCP_OPT_AUTH_PROTO: 207330300Sjoerg authproto = (p[2] << 8) + p[3]; 207430300Sjoerg if (sp->myauth.proto != authproto) { 207530300Sjoerg /* not agreed, nak */ 207630300Sjoerg if (debug) 207730300Sjoerg addlog("[mine %s != his %s] ", 207830300Sjoerg sppp_proto_name(sp->hisauth.proto), 207930300Sjoerg sppp_proto_name(authproto)); 208030300Sjoerg p[2] = sp->myauth.proto >> 8; 208130300Sjoerg p[3] = sp->myauth.proto; 208230300Sjoerg break; 208330300Sjoerg } 208430300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 208530300Sjoerg if (debug) 208630300Sjoerg addlog("[chap not MD5] "); 208739981Sjoerg p[4] = CHAP_MD5; 208830300Sjoerg break; 208930300Sjoerg } 209030300Sjoerg continue; 209111189Sjkh } 209225944Sjoerg /* Add the option to nak'ed list. */ 209325706Sjoerg bcopy (p, r, p[1]); 209425706Sjoerg r += p[1]; 209511189Sjkh rlen += p[1]; 209612436Speter } 209725706Sjoerg if (rlen) { 209828036Sjoerg if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 209928036Sjoerg if (debug) 210028036Sjoerg addlog(" max_failure (%d) exceeded, " 210128036Sjoerg "send conf-rej\n", 210228036Sjoerg sp->lcp.max_failure); 210328036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 210428036Sjoerg } else { 210528036Sjoerg if (debug) 210628036Sjoerg addlog(" send conf-nak\n"); 210728036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 210828036Sjoerg } 210925944Sjoerg return 0; 211025944Sjoerg } else { 211125944Sjoerg if (debug) 211225944Sjoerg addlog(" send conf-ack\n"); 211328036Sjoerg sp->fail_counter[IDX_LCP] = 0; 211425944Sjoerg sp->pp_loopcnt = 0; 211525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 211625944Sjoerg h->ident, origlen, h+1); 211725944Sjoerg } 211825944Sjoerg 211911189Sjkh free (buf, M_TEMP); 212011189Sjkh return (rlen == 0); 21214910Swollman} 21224910Swollman 212325944Sjoerg/* 212425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 212525944Sjoerg * negotiation. 212625944Sjoerg */ 212712820Sphkstatic void 212825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 21294910Swollman{ 213025944Sjoerg STDDCL; 213125944Sjoerg u_char *buf, *p; 21324910Swollman 213325944Sjoerg len -= 4; 213425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 213525944Sjoerg if (!buf) 21364910Swollman return; 213725944Sjoerg 213825944Sjoerg if (debug) 213940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 214040008Sjoerg SPP_ARGS(ifp)); 214125944Sjoerg 214225944Sjoerg p = (void*) (h+1); 214325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 214425944Sjoerg if (debug) 214525944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 214625944Sjoerg switch (*p) { 214725944Sjoerg case LCP_OPT_MAGIC: 214825944Sjoerg /* Magic number -- can't use it, use 0 */ 214925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 215025944Sjoerg sp->lcp.magic = 0; 215125944Sjoerg break; 215225944Sjoerg case LCP_OPT_MRU: 215325944Sjoerg /* 215425944Sjoerg * Should not be rejected anyway, since we only 215525944Sjoerg * negotiate a MRU if explicitly requested by 215625944Sjoerg * peer. 215725944Sjoerg */ 215825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 215925944Sjoerg break; 216030300Sjoerg case LCP_OPT_AUTH_PROTO: 216130300Sjoerg /* 216230300Sjoerg * Peer doesn't want to authenticate himself, 216330300Sjoerg * deny unless this is a dialout call, and 216430300Sjoerg * AUTHFLAG_NOCALLOUT is set. 216530300Sjoerg */ 216630300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 216730300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 216830300Sjoerg if (debug) 216930300Sjoerg addlog("[don't insist on auth " 217030300Sjoerg "for callout]"); 217130300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 217230300Sjoerg break; 217330300Sjoerg } 217430300Sjoerg if (debug) 217530300Sjoerg addlog("[access denied]\n"); 217630300Sjoerg lcp.Close(sp); 217730300Sjoerg break; 217825944Sjoerg } 21794910Swollman } 218025944Sjoerg if (debug) 218125944Sjoerg addlog("\n"); 218225944Sjoerg free (buf, M_TEMP); 218325944Sjoerg return; 218425944Sjoerg} 218525944Sjoerg 218625944Sjoerg/* 218725944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 218825944Sjoerg * negotiation. 218925944Sjoerg */ 219025944Sjoergstatic void 219125944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 219225944Sjoerg{ 219325944Sjoerg STDDCL; 219425944Sjoerg u_char *buf, *p; 219525944Sjoerg u_long magic; 219625944Sjoerg 219725944Sjoerg len -= 4; 219825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 219925944Sjoerg if (!buf) 220025944Sjoerg return; 220125944Sjoerg 220225944Sjoerg if (debug) 220340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 220440008Sjoerg SPP_ARGS(ifp)); 220525944Sjoerg 220625944Sjoerg p = (void*) (h+1); 220725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 220825706Sjoerg if (debug) 220925944Sjoerg addlog(" %s ", sppp_lcp_opt_name(*p)); 221025944Sjoerg switch (*p) { 221125944Sjoerg case LCP_OPT_MAGIC: 221225944Sjoerg /* Magic number -- renegotiate */ 221325944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 221425944Sjoerg len >= 6 && p[1] == 6) { 221525944Sjoerg magic = (u_long)p[2] << 24 | 221625944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 221725944Sjoerg /* 221825944Sjoerg * If the remote magic is our negated one, 221925944Sjoerg * this looks like a loopback problem. 222025944Sjoerg * Suggest a new magic to make sure. 222125944Sjoerg */ 222225944Sjoerg if (magic == ~sp->lcp.magic) { 222325944Sjoerg if (debug) 222425944Sjoerg addlog("magic glitch "); 222542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 222635064Sphk sp->lcp.magic = random(); 222740008Sjoerg#else 222840008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 222940008Sjoerg#endif 223025944Sjoerg } else { 223125944Sjoerg sp->lcp.magic = magic; 223225944Sjoerg if (debug) 223340008Sjoerg addlog("%lu ", magic); 223425944Sjoerg } 223525944Sjoerg } 223625944Sjoerg break; 223725944Sjoerg case LCP_OPT_MRU: 223825944Sjoerg /* 223925944Sjoerg * Peer wants to advise us to negotiate an MRU. 224025944Sjoerg * Agree on it if it's reasonable, or use 224125944Sjoerg * default otherwise. 224225944Sjoerg */ 224325944Sjoerg if (len >= 4 && p[1] == 4) { 224425944Sjoerg u_int mru = p[2] * 256 + p[3]; 224525944Sjoerg if (debug) 224625944Sjoerg addlog("%d ", mru); 224725944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 224825944Sjoerg mru = PP_MTU; 224925944Sjoerg sp->lcp.mru = mru; 225025944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 225125944Sjoerg } 225225944Sjoerg break; 225330300Sjoerg case LCP_OPT_AUTH_PROTO: 225430300Sjoerg /* 225530300Sjoerg * Peer doesn't like our authentication method, 225630300Sjoerg * deny. 225730300Sjoerg */ 225830300Sjoerg if (debug) 225930300Sjoerg addlog("[access denied]\n"); 226030300Sjoerg lcp.Close(sp); 226130300Sjoerg break; 22624910Swollman } 226325944Sjoerg } 226425944Sjoerg if (debug) 226525944Sjoerg addlog("\n"); 226625944Sjoerg free (buf, M_TEMP); 226725944Sjoerg return; 226825944Sjoerg} 226911189Sjkh 227025944Sjoergstatic void 227125944Sjoergsppp_lcp_tlu(struct sppp *sp) 227225944Sjoerg{ 227342066Sphk STDDCL; 227425944Sjoerg int i; 227525944Sjoerg u_long mask; 227625944Sjoerg 227725944Sjoerg /* XXX ? */ 227825944Sjoerg if (! (ifp->if_flags & IFF_UP) && 227925944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 228025944Sjoerg /* Coming out of loopback mode. */ 228125944Sjoerg if_up(ifp); 228240008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 228325944Sjoerg } 228425944Sjoerg 228525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 228625944Sjoerg if ((cps[i])->flags & CP_QUAL) 228725944Sjoerg (cps[i])->Open(sp); 228825944Sjoerg 228930300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 229030300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 229125944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 229225944Sjoerg else 229325944Sjoerg sp->pp_phase = PHASE_NETWORK; 229425944Sjoerg 229542066Sphk if (debug) 229642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 229742066Sphk sppp_phase_name(sp->pp_phase)); 229825944Sjoerg 229930300Sjoerg /* 230030300Sjoerg * Open all authentication protocols. This is even required 230130300Sjoerg * if we already proceeded to network phase, since it might be 230230300Sjoerg * that remote wants us to authenticate, so we might have to 230330300Sjoerg * send a PAP request. Undesired authentication protocols 230430300Sjoerg * don't do anything when they get an Open event. 230530300Sjoerg */ 230630300Sjoerg for (i = 0; i < IDX_COUNT; i++) 230730300Sjoerg if ((cps[i])->flags & CP_AUTH) 230830300Sjoerg (cps[i])->Open(sp); 230930300Sjoerg 231030300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 231125944Sjoerg /* Notify all NCPs. */ 231225944Sjoerg for (i = 0; i < IDX_COUNT; i++) 231325944Sjoerg if ((cps[i])->flags & CP_NCP) 231425944Sjoerg (cps[i])->Open(sp); 231525944Sjoerg } 231625944Sjoerg 231725944Sjoerg /* Send Up events to all started protos. */ 231825944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 231925944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 232025944Sjoerg (cps[i])->Up(sp); 232125944Sjoerg 232242104Sphk /* notify low-level driver of state change */ 232342104Sphk if (sp->pp_chg) 232442104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 232542104Sphk 232625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 232725944Sjoerg /* if no NCP is starting, close down */ 232830300Sjoerg sppp_lcp_check_and_close(sp); 232925944Sjoerg} 233025944Sjoerg 233125944Sjoergstatic void 233225944Sjoergsppp_lcp_tld(struct sppp *sp) 233325944Sjoerg{ 233442066Sphk STDDCL; 233525944Sjoerg int i; 233625944Sjoerg u_long mask; 233725944Sjoerg 233825944Sjoerg sp->pp_phase = PHASE_TERMINATE; 233925944Sjoerg 234042066Sphk if (debug) 234142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 234242066Sphk sppp_phase_name(sp->pp_phase)); 234325944Sjoerg 234425944Sjoerg /* 234525944Sjoerg * Take upper layers down. We send the Down event first and 234625944Sjoerg * the Close second to prevent the upper layers from sending 234725944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 234825944Sjoerg * describes it. 234925944Sjoerg */ 235025944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 235125944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 235225944Sjoerg (cps[i])->Down(sp); 235325944Sjoerg (cps[i])->Close(sp); 235425944Sjoerg } 235525944Sjoerg} 235625944Sjoerg 235725944Sjoergstatic void 235825944Sjoergsppp_lcp_tls(struct sppp *sp) 235925944Sjoerg{ 236042066Sphk STDDCL; 236125944Sjoerg 236225944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 236325944Sjoerg 236442066Sphk if (debug) 236542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 236642066Sphk sppp_phase_name(sp->pp_phase)); 236725944Sjoerg 236825944Sjoerg /* Notify lower layer if desired. */ 236925944Sjoerg if (sp->pp_tls) 237025944Sjoerg (sp->pp_tls)(sp); 237141881Sphk else 237241881Sphk (sp->pp_up)(sp); 237325944Sjoerg} 237425944Sjoerg 237525944Sjoergstatic void 237625944Sjoergsppp_lcp_tlf(struct sppp *sp) 237725944Sjoerg{ 237842066Sphk STDDCL; 237925944Sjoerg 238025944Sjoerg sp->pp_phase = PHASE_DEAD; 238142066Sphk if (debug) 238242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 238342066Sphk sppp_phase_name(sp->pp_phase)); 238425944Sjoerg 238525944Sjoerg /* Notify lower layer if desired. */ 238625944Sjoerg if (sp->pp_tlf) 238725944Sjoerg (sp->pp_tlf)(sp); 238841881Sphk else 238941881Sphk (sp->pp_down)(sp); 239025944Sjoerg} 239125944Sjoerg 239225944Sjoergstatic void 239325944Sjoergsppp_lcp_scr(struct sppp *sp) 239425944Sjoerg{ 239530300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 239625944Sjoerg int i = 0; 239730300Sjoerg u_short authproto; 239825944Sjoerg 239925944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 240025944Sjoerg if (! sp->lcp.magic) 240142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 240235064Sphk sp->lcp.magic = random(); 240340008Sjoerg#else 240440008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 240540008Sjoerg#endif 240625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 240725944Sjoerg opt[i++] = 6; 240825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 240925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 241025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 241125944Sjoerg opt[i++] = sp->lcp.magic; 241225944Sjoerg } 241325944Sjoerg 241425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 241525944Sjoerg opt[i++] = LCP_OPT_MRU; 241625944Sjoerg opt[i++] = 4; 241725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 241825944Sjoerg opt[i++] = sp->lcp.mru; 241925944Sjoerg } 242025944Sjoerg 242130300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 242230300Sjoerg authproto = sp->hisauth.proto; 242330300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 242430300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 242530300Sjoerg opt[i++] = authproto >> 8; 242630300Sjoerg opt[i++] = authproto; 242730300Sjoerg if (authproto == PPP_CHAP) 242830300Sjoerg opt[i++] = CHAP_MD5; 242930300Sjoerg } 243030300Sjoerg 243125944Sjoerg sp->confid[IDX_LCP] = ++sp->pp_seq; 243225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 243325944Sjoerg} 243425944Sjoerg 243525944Sjoerg/* 243630300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 243730300Sjoerg */ 243830300Sjoergstatic int 243930300Sjoergsppp_ncp_check(struct sppp *sp) 244030300Sjoerg{ 244130300Sjoerg int i, mask; 244230300Sjoerg 244330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 244430300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 244530300Sjoerg return 1; 244630300Sjoerg return 0; 244730300Sjoerg} 244830300Sjoerg 244930300Sjoerg/* 245025944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 245125944Sjoerg * Called by the NCPs during their tlf action handling. 245225944Sjoerg */ 245325944Sjoergstatic void 245430300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 245525944Sjoerg{ 245625944Sjoerg 245730300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 245830300Sjoerg /* don't bother, we are already going down */ 245930300Sjoerg return; 246030300Sjoerg 246130300Sjoerg if (sppp_ncp_check(sp)) 246230300Sjoerg return; 246330300Sjoerg 246425944Sjoerg lcp.Close(sp); 246525944Sjoerg} 246625944Sjoerg/* 246725944Sjoerg *--------------------------------------------------------------------------* 246825944Sjoerg * * 246925944Sjoerg * The IPCP implementation. * 247025944Sjoerg * * 247125944Sjoerg *--------------------------------------------------------------------------* 247225944Sjoerg */ 247325944Sjoerg 247425944Sjoergstatic void 247525944Sjoergsppp_ipcp_init(struct sppp *sp) 247625944Sjoerg{ 247725944Sjoerg sp->ipcp.opts = 0; 247825944Sjoerg sp->ipcp.flags = 0; 247925944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 248025944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 248142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 248229681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 248340008Sjoerg#endif 248425944Sjoerg} 248525944Sjoerg 248625944Sjoergstatic void 248725944Sjoergsppp_ipcp_up(struct sppp *sp) 248825944Sjoerg{ 248925944Sjoerg sppp_up_event(&ipcp, sp); 249025944Sjoerg} 249125944Sjoerg 249225944Sjoergstatic void 249325944Sjoergsppp_ipcp_down(struct sppp *sp) 249425944Sjoerg{ 249525944Sjoerg sppp_down_event(&ipcp, sp); 249625944Sjoerg} 249725944Sjoerg 249825944Sjoergstatic void 249925944Sjoergsppp_ipcp_open(struct sppp *sp) 250025944Sjoerg{ 250125944Sjoerg STDDCL; 250225944Sjoerg u_long myaddr, hisaddr; 250325944Sjoerg 250442104Sphk sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); 250542104Sphk 250630300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 250725944Sjoerg /* 250825944Sjoerg * If we don't have his address, this probably means our 250925944Sjoerg * interface doesn't want to talk IP at all. (This could 251025944Sjoerg * be the case if somebody wants to speak only IPX, for 251125944Sjoerg * example.) Don't open IPCP in this case. 251225944Sjoerg */ 251325944Sjoerg if (hisaddr == 0L) { 251425944Sjoerg /* XXX this message should go away */ 251525944Sjoerg if (debug) 251640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 251740008Sjoerg SPP_ARGS(ifp)); 251825944Sjoerg return; 251925944Sjoerg } 252025944Sjoerg 252125944Sjoerg if (myaddr == 0L) { 252225944Sjoerg /* 252325944Sjoerg * I don't have an assigned address, so i need to 252425944Sjoerg * negotiate my address. 252525944Sjoerg */ 252625944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 252725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 252842104Sphk } else 252942104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 253025944Sjoerg sppp_open_event(&ipcp, sp); 253125944Sjoerg} 253225944Sjoerg 253325944Sjoergstatic void 253425944Sjoergsppp_ipcp_close(struct sppp *sp) 253525944Sjoerg{ 253625944Sjoerg sppp_close_event(&ipcp, sp); 253725944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 253825944Sjoerg /* 253925944Sjoerg * My address was dynamic, clear it again. 254025944Sjoerg */ 254125944Sjoerg sppp_set_ip_addr(sp, 0L); 254225944Sjoerg} 254325944Sjoerg 254425944Sjoergstatic void 254525944Sjoergsppp_ipcp_TO(void *cookie) 254625944Sjoerg{ 254725944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 254825944Sjoerg} 254925944Sjoerg 255025944Sjoerg/* 255125944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 255225944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 255325944Sjoerg * caused action scn. (The return value is used to make the state 255425944Sjoerg * transition decision in the state automaton.) 255525944Sjoerg */ 255625944Sjoergstatic int 255725944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 255825944Sjoerg{ 255925944Sjoerg u_char *buf, *r, *p; 256025944Sjoerg struct ifnet *ifp = &sp->pp_if; 256125944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 256225944Sjoerg u_long hisaddr, desiredaddr; 256342104Sphk int gotmyaddr = 0; 256425944Sjoerg 256525944Sjoerg len -= 4; 256625944Sjoerg origlen = len; 256725944Sjoerg /* 256825944Sjoerg * Make sure to allocate a buf that can at least hold a 256925944Sjoerg * conf-nak with an `address' option. We might need it below. 257025944Sjoerg */ 257125944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 257225944Sjoerg if (! buf) 257325944Sjoerg return (0); 257425944Sjoerg 257525944Sjoerg /* pass 1: see if we can recognize them */ 257625944Sjoerg if (debug) 257740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 257840008Sjoerg SPP_ARGS(ifp)); 257925944Sjoerg p = (void*) (h+1); 258025944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 258125944Sjoerg if (debug) 258225944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 258325944Sjoerg switch (*p) { 258425944Sjoerg#ifdef notyet 258525944Sjoerg case IPCP_OPT_COMPRESSION: 258625944Sjoerg if (len >= 6 && p[1] >= 6) { 258725944Sjoerg /* correctly formed compress option */ 258825944Sjoerg continue; 258911189Sjkh } 259025706Sjoerg if (debug) 259125944Sjoerg addlog("[invalid] "); 259225944Sjoerg break; 259325944Sjoerg#endif 259425944Sjoerg case IPCP_OPT_ADDRESS: 259525944Sjoerg if (len >= 6 && p[1] == 6) { 259625944Sjoerg /* correctly formed address option */ 259725944Sjoerg continue; 259825944Sjoerg } 259925706Sjoerg if (debug) 260025944Sjoerg addlog("[invalid] "); 260111189Sjkh break; 260225944Sjoerg default: 260325944Sjoerg /* Others not supported. */ 260425944Sjoerg if (debug) 260525944Sjoerg addlog("[rej] "); 26064910Swollman break; 26074910Swollman } 260825944Sjoerg /* Add the option to rejected list. */ 260925944Sjoerg bcopy (p, r, p[1]); 261025944Sjoerg r += p[1]; 261125944Sjoerg rlen += p[1]; 261225944Sjoerg } 261325944Sjoerg if (rlen) { 261425944Sjoerg if (debug) 261525944Sjoerg addlog(" send conf-rej\n"); 261625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 261725944Sjoerg return 0; 261825944Sjoerg } else if (debug) 261925944Sjoerg addlog("\n"); 262025944Sjoerg 262125944Sjoerg /* pass 2: parse option values */ 262230300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 262325944Sjoerg if (debug) 262440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 262540008Sjoerg SPP_ARGS(ifp)); 262625944Sjoerg p = (void*) (h+1); 262725944Sjoerg len = origlen; 262825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 262925944Sjoerg if (debug) 263025944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 263125944Sjoerg switch (*p) { 263225944Sjoerg#ifdef notyet 263325944Sjoerg case IPCP_OPT_COMPRESSION: 263425944Sjoerg continue; 263525944Sjoerg#endif 263625944Sjoerg case IPCP_OPT_ADDRESS: 263742104Sphk /* This is the address he wants in his end */ 263825944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 263925944Sjoerg p[4] << 8 | p[5]; 264033928Sphk if (desiredaddr == hisaddr || 264142104Sphk (hisaddr == 1 && desiredaddr != 0)) { 264225944Sjoerg /* 264325944Sjoerg * Peer's address is same as our value, 264433928Sphk * or we have set it to 0.0.0.1 to 264533928Sphk * indicate that we do not really care, 264625944Sjoerg * this is agreeable. Gonna conf-ack 264725944Sjoerg * it. 264825944Sjoerg */ 264925944Sjoerg if (debug) 265030300Sjoerg addlog("%s [ack] ", 265142104Sphk sppp_dotted_quad(hisaddr)); 265225944Sjoerg /* record that we've seen it already */ 265325944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 265425944Sjoerg continue; 265525944Sjoerg } 265625944Sjoerg /* 265725944Sjoerg * The address wasn't agreeable. This is either 265825944Sjoerg * he sent us 0.0.0.0, asking to assign him an 265925944Sjoerg * address, or he send us another address not 266025944Sjoerg * matching our value. Either case, we gonna 266125944Sjoerg * conf-nak it with our value. 266242104Sphk * XXX: we should "rej" if hisaddr == 0 266325944Sjoerg */ 266425944Sjoerg if (debug) { 266525944Sjoerg if (desiredaddr == 0) 266625944Sjoerg addlog("[addr requested] "); 266725944Sjoerg else 266830300Sjoerg addlog("%s [not agreed] ", 266942104Sphk sppp_dotted_quad(desiredaddr)); 267025944Sjoerg 267125944Sjoerg p[2] = hisaddr >> 24; 267225944Sjoerg p[3] = hisaddr >> 16; 267325944Sjoerg p[4] = hisaddr >> 8; 267425944Sjoerg p[5] = hisaddr; 267525944Sjoerg } 267611189Sjkh break; 267725706Sjoerg } 267825944Sjoerg /* Add the option to nak'ed list. */ 267925944Sjoerg bcopy (p, r, p[1]); 268025944Sjoerg r += p[1]; 268125944Sjoerg rlen += p[1]; 268225944Sjoerg } 268325944Sjoerg 268425944Sjoerg /* 268525944Sjoerg * If we are about to conf-ack the request, but haven't seen 268625944Sjoerg * his address so far, gonna conf-nak it instead, with the 268725944Sjoerg * `address' option present and our idea of his address being 268825944Sjoerg * filled in there, to request negotiation of both addresses. 268925944Sjoerg * 269025944Sjoerg * XXX This can result in an endless req - nak loop if peer 269125944Sjoerg * doesn't want to send us his address. Q: What should we do 269225944Sjoerg * about it? XXX A: implement the max-failure counter. 269325944Sjoerg */ 269442104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 269525944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 269625944Sjoerg buf[1] = 6; 269725944Sjoerg buf[2] = hisaddr >> 24; 269825944Sjoerg buf[3] = hisaddr >> 16; 269925944Sjoerg buf[4] = hisaddr >> 8; 270025944Sjoerg buf[5] = hisaddr; 270125944Sjoerg rlen = 6; 270225706Sjoerg if (debug) 270325944Sjoerg addlog("still need hisaddr "); 270425944Sjoerg } 270525944Sjoerg 270625944Sjoerg if (rlen) { 270725706Sjoerg if (debug) 270825944Sjoerg addlog(" send conf-nak\n"); 270925944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 271025944Sjoerg } else { 271125706Sjoerg if (debug) 271225944Sjoerg addlog(" send conf-ack\n"); 271325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 271425944Sjoerg h->ident, origlen, h+1); 271525944Sjoerg } 271625944Sjoerg 271725944Sjoerg free (buf, M_TEMP); 271825944Sjoerg return (rlen == 0); 271925944Sjoerg} 272025944Sjoerg 272125944Sjoerg/* 272225944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 272325944Sjoerg * negotiation. 272425944Sjoerg */ 272525944Sjoergstatic void 272625944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 272725944Sjoerg{ 272825944Sjoerg u_char *buf, *p; 272925944Sjoerg struct ifnet *ifp = &sp->pp_if; 273025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 273125944Sjoerg 273225944Sjoerg len -= 4; 273325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 273425944Sjoerg if (!buf) 273525944Sjoerg return; 273625944Sjoerg 273725944Sjoerg if (debug) 273840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 273940008Sjoerg SPP_ARGS(ifp)); 274025944Sjoerg 274125944Sjoerg p = (void*) (h+1); 274225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 274325706Sjoerg if (debug) 274425944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 274525944Sjoerg switch (*p) { 274625944Sjoerg case IPCP_OPT_ADDRESS: 274725944Sjoerg /* 274825944Sjoerg * Peer doesn't grok address option. This is 274925944Sjoerg * bad. XXX Should we better give up here? 275042104Sphk * XXX We could try old "addresses" option... 275125944Sjoerg */ 275225944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 275325944Sjoerg break; 275425944Sjoerg#ifdef notyet 275525944Sjoerg case IPCP_OPT_COMPRESS: 275625944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS); 275725944Sjoerg break; 275825944Sjoerg#endif 275925944Sjoerg } 27604910Swollman } 276125944Sjoerg if (debug) 276225944Sjoerg addlog("\n"); 276325944Sjoerg free (buf, M_TEMP); 276425944Sjoerg return; 27654910Swollman} 27664910Swollman 276725944Sjoerg/* 276825944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 276925944Sjoerg * negotiation. 277025944Sjoerg */ 277112820Sphkstatic void 277225944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 27734910Swollman{ 277425944Sjoerg u_char *buf, *p; 277525944Sjoerg struct ifnet *ifp = &sp->pp_if; 277625944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 277725944Sjoerg u_long wantaddr; 27784910Swollman 277925944Sjoerg len -= 4; 278025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 278125944Sjoerg if (!buf) 278225944Sjoerg return; 278325944Sjoerg 278425944Sjoerg if (debug) 278540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 278640008Sjoerg SPP_ARGS(ifp)); 278725944Sjoerg 278825944Sjoerg p = (void*) (h+1); 278925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 279025944Sjoerg if (debug) 279125944Sjoerg addlog(" %s ", sppp_ipcp_opt_name(*p)); 279225944Sjoerg switch (*p) { 279325944Sjoerg case IPCP_OPT_ADDRESS: 279425944Sjoerg /* 279525944Sjoerg * Peer doesn't like our local IP address. See 279625944Sjoerg * if we can do something for him. We'll drop 279725944Sjoerg * him our address then. 279825944Sjoerg */ 279925944Sjoerg if (len >= 6 && p[1] == 6) { 280025944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 280125944Sjoerg p[4] << 8 | p[5]; 280225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 280325944Sjoerg if (debug) 280430300Sjoerg addlog("[wantaddr %s] ", 280530300Sjoerg sppp_dotted_quad(wantaddr)); 280625944Sjoerg /* 280725944Sjoerg * When doing dynamic address assignment, 280825944Sjoerg * we accept his offer. Otherwise, we 280925944Sjoerg * ignore it and thus continue to negotiate 281025944Sjoerg * our already existing value. 281142104Sphk * XXX: Bogus, if he said no once, he'll 281242104Sphk * just say no again, might as well die. 281325944Sjoerg */ 281425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 281525944Sjoerg sppp_set_ip_addr(sp, wantaddr); 281625944Sjoerg if (debug) 281725944Sjoerg addlog("[agree] "); 281842104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 281925944Sjoerg } 282025944Sjoerg } 282125944Sjoerg break; 282225944Sjoerg#ifdef notyet 282325944Sjoerg case IPCP_OPT_COMPRESS: 282425944Sjoerg /* 282525944Sjoerg * Peer wants different compression parameters. 282625944Sjoerg */ 282725944Sjoerg break; 282825944Sjoerg#endif 282925944Sjoerg } 283025944Sjoerg } 283125944Sjoerg if (debug) 283225944Sjoerg addlog("\n"); 283325944Sjoerg free (buf, M_TEMP); 283425944Sjoerg return; 28354910Swollman} 28364910Swollman 283712820Sphkstatic void 283825944Sjoergsppp_ipcp_tlu(struct sppp *sp) 28394910Swollman{ 284042104Sphk /* we are up - notify isdn daemon */ 284142104Sphk if (sp->pp_con) 284242104Sphk sp->pp_con(sp); 28434910Swollman} 28444910Swollman 284525944Sjoergstatic void 284625944Sjoergsppp_ipcp_tld(struct sppp *sp) 284725944Sjoerg{ 284825944Sjoerg} 284925944Sjoerg 285025944Sjoergstatic void 285125944Sjoergsppp_ipcp_tls(struct sppp *sp) 285225944Sjoerg{ 285325944Sjoerg /* indicate to LCP that it must stay alive */ 285425944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 285525944Sjoerg} 285625944Sjoerg 285725944Sjoergstatic void 285825944Sjoergsppp_ipcp_tlf(struct sppp *sp) 285925944Sjoerg{ 286025944Sjoerg /* we no longer need LCP */ 286125944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 286230300Sjoerg sppp_lcp_check_and_close(sp); 286325944Sjoerg} 286425944Sjoerg 286525944Sjoergstatic void 286625944Sjoergsppp_ipcp_scr(struct sppp *sp) 286725944Sjoerg{ 286825944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 286925944Sjoerg u_long ouraddr; 287025944Sjoerg int i = 0; 287125944Sjoerg 287225944Sjoerg#ifdef notyet 287325944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 287425944Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 287525944Sjoerg opt[i++] = 6; 287625944Sjoerg opt[i++] = 0; /* VJ header compression */ 287725944Sjoerg opt[i++] = 0x2d; /* VJ header compression */ 287825944Sjoerg opt[i++] = max_slot_id; 287925944Sjoerg opt[i++] = comp_slot_id; 288025944Sjoerg } 288125944Sjoerg#endif 288225944Sjoerg 288325944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 288430300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 288525944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 288625944Sjoerg opt[i++] = 6; 288725944Sjoerg opt[i++] = ouraddr >> 24; 288825944Sjoerg opt[i++] = ouraddr >> 16; 288925944Sjoerg opt[i++] = ouraddr >> 8; 289025944Sjoerg opt[i++] = ouraddr; 289125944Sjoerg } 289225944Sjoerg 289325944Sjoerg sp->confid[IDX_IPCP] = ++sp->pp_seq; 289425944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 289525944Sjoerg} 289625944Sjoerg 289725944Sjoerg 289825944Sjoerg/* 289930300Sjoerg *--------------------------------------------------------------------------* 290030300Sjoerg * * 290130300Sjoerg * The CHAP implementation. * 290230300Sjoerg * * 290330300Sjoerg *--------------------------------------------------------------------------* 290430300Sjoerg */ 290530300Sjoerg 290630300Sjoerg/* 290730300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 290830300Sjoerg * the control protocols do, since they do have Open and Close events, but 290930300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 291030300Sjoerg * authentication protocols may be different in both directions (this makes 291130300Sjoerg * sense, think of a machine that never accepts incoming calls but only 291230300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 291330300Sjoerg * 291430300Sjoerg * Our state machine for the local authentication protocol (we are requesting 291530300Sjoerg * the peer to authenticate) looks like: 291630300Sjoerg * 291730300Sjoerg * RCA- 291830300Sjoerg * +--------------------------------------------+ 291930300Sjoerg * V scn,tld| 292030300Sjoerg * +--------+ Close +---------+ RCA+ 292130300Sjoerg * | |<----------------------------------| |------+ 292230300Sjoerg * +--->| Closed | TO* | Opened | sca | 292330300Sjoerg * | | |-----+ +-------| |<-----+ 292430300Sjoerg * | +--------+ irc | | +---------+ 292530300Sjoerg * | ^ | | ^ 292630300Sjoerg * | | | | | 292730300Sjoerg * | | | | | 292830300Sjoerg * | TO-| | | | 292930300Sjoerg * | |tld TO+ V | | 293030300Sjoerg * | | +------->+ | | 293130300Sjoerg * | | | | | | 293230300Sjoerg * | +--------+ V | | 293330300Sjoerg * | | |<----+<--------------------+ | 293430300Sjoerg * | | Req- | scr | 293530300Sjoerg * | | Sent | | 293630300Sjoerg * | | | | 293730300Sjoerg * | +--------+ | 293830300Sjoerg * | RCA- | | RCA+ | 293930300Sjoerg * +------+ +------------------------------------------+ 294030300Sjoerg * scn,tld sca,irc,ict,tlu 294130300Sjoerg * 294230300Sjoerg * 294330300Sjoerg * with: 294430300Sjoerg * 294530300Sjoerg * Open: LCP reached authentication phase 294630300Sjoerg * Close: LCP reached terminate phase 294730300Sjoerg * 294830300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 294930300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 295030300Sjoerg * TO+: timeout with restart counter >= 0 295130300Sjoerg * TO-: timeout with restart counter < 0 295230300Sjoerg * TO*: reschedule timeout for CHAP 295330300Sjoerg * 295430300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 295530300Sjoerg * sca: send ack packet (pap-ack, chap-success) 295630300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 295730300Sjoerg * ict: initialize re-challenge timer (CHAP only) 295830300Sjoerg * 295930300Sjoerg * tlu: this-layer-up, LCP reaches network phase 296030300Sjoerg * tld: this-layer-down, LCP enters terminate phase 296130300Sjoerg * 296230300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 296330300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 296430300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 296530300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 296630300Sjoerg * causing LCP to enter terminate phase. 296730300Sjoerg * 296830300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 296930300Sjoerg * expected to send one based on the successful negotiation of PAP as 297030300Sjoerg * the authentication protocol during the LCP option negotiation. 297130300Sjoerg * 297230300Sjoerg * Incoming authentication protocol requests (remote requests 297330300Sjoerg * authentication, we are peer) don't employ a state machine at all, 297430300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 297530300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 297630300Sjoerg * still in authentication phase (thereby violating the standard that 297730300Sjoerg * demands that these NCP packets are to be discarded), so we keep 297830300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 297930300Sjoerg * phase network once we've seen a positive acknowledge for the 298030300Sjoerg * authentication. 298130300Sjoerg */ 298230300Sjoerg 298330300Sjoerg/* 298430300Sjoerg * Handle incoming CHAP packets. 298530300Sjoerg */ 298630300Sjoergvoid 298730300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 298830300Sjoerg{ 298930300Sjoerg STDDCL; 299030300Sjoerg struct lcp_header *h; 299130300Sjoerg int len, x; 299230300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 299330300Sjoerg int value_len, name_len; 299430300Sjoerg MD5_CTX ctx; 299530300Sjoerg 299630300Sjoerg len = m->m_pkthdr.len; 299730300Sjoerg if (len < 4) { 299830300Sjoerg if (debug) 299930300Sjoerg log(LOG_DEBUG, 300040008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 300140008Sjoerg SPP_ARGS(ifp), len); 300230300Sjoerg return; 300330300Sjoerg } 300430300Sjoerg h = mtod (m, struct lcp_header*); 300530300Sjoerg if (len > ntohs (h->len)) 300630300Sjoerg len = ntohs (h->len); 300730300Sjoerg 300830300Sjoerg switch (h->type) { 300930300Sjoerg /* challenge, failure and success are his authproto */ 301030300Sjoerg case CHAP_CHALLENGE: 301130300Sjoerg value = 1 + (u_char*)(h+1); 301230300Sjoerg value_len = value[-1]; 301330300Sjoerg name = value + value_len; 301430300Sjoerg name_len = len - value_len - 5; 301530300Sjoerg if (name_len < 0) { 301630300Sjoerg if (debug) { 301730300Sjoerg log(LOG_DEBUG, 301840008Sjoerg SPP_FMT "chap corrupted challenge " 301930300Sjoerg "<%s id=0x%x len=%d", 302040008Sjoerg SPP_ARGS(ifp), 302130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 302230300Sjoerg h->ident, ntohs(h->len)); 302330300Sjoerg if (len > 4) 302430300Sjoerg sppp_print_bytes((u_char*) (h+1), len-4); 302530300Sjoerg addlog(">\n"); 302630300Sjoerg } 302730300Sjoerg break; 302830300Sjoerg } 302930300Sjoerg 303030300Sjoerg if (debug) { 303130300Sjoerg log(LOG_DEBUG, 303240008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 303340008Sjoerg SPP_ARGS(ifp), 303430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 303530300Sjoerg ntohs(h->len)); 303630300Sjoerg sppp_print_string((char*) name, name_len); 303730300Sjoerg addlog(" value-size=%d value=", value_len); 303830300Sjoerg sppp_print_bytes(value, value_len); 303930300Sjoerg addlog(">\n"); 304030300Sjoerg } 304130300Sjoerg 304230300Sjoerg /* Compute reply value. */ 304330300Sjoerg MD5Init(&ctx); 304430300Sjoerg MD5Update(&ctx, &h->ident, 1); 304530300Sjoerg MD5Update(&ctx, sp->myauth.secret, 304630300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 304730300Sjoerg MD5Update(&ctx, value, value_len); 304830300Sjoerg MD5Final(digest, &ctx); 304930300Sjoerg dsize = sizeof digest; 305030300Sjoerg 305130300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 305230300Sjoerg sizeof dsize, (const char *)&dsize, 305330300Sjoerg sizeof digest, digest, 305440008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 305530300Sjoerg sp->myauth.name, 305630300Sjoerg 0); 305730300Sjoerg break; 305830300Sjoerg 305930300Sjoerg case CHAP_SUCCESS: 306030300Sjoerg if (debug) { 306140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 306240008Sjoerg SPP_ARGS(ifp)); 306330300Sjoerg if (len > 4) { 306430300Sjoerg addlog(": "); 306530300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 306630300Sjoerg } 306730300Sjoerg addlog("\n"); 306830300Sjoerg } 306930300Sjoerg x = splimp(); 307030300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 307130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 307232169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 307330300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 307430300Sjoerg /* 307530300Sjoerg * We are authenticator for CHAP but didn't 307630300Sjoerg * complete yet. Leave it to tlu to proceed 307730300Sjoerg * to network phase. 307830300Sjoerg */ 307930300Sjoerg splx(x); 308030300Sjoerg break; 308130300Sjoerg } 308230300Sjoerg splx(x); 308330300Sjoerg sppp_phase_network(sp); 308430300Sjoerg break; 308530300Sjoerg 308630300Sjoerg case CHAP_FAILURE: 308730300Sjoerg if (debug) { 308840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 308940008Sjoerg SPP_ARGS(ifp)); 309030300Sjoerg if (len > 4) { 309130300Sjoerg addlog(": "); 309230300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 309330300Sjoerg } 309430300Sjoerg addlog("\n"); 309530300Sjoerg } else 309640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 309740008Sjoerg SPP_ARGS(ifp)); 309830300Sjoerg /* await LCP shutdown by authenticator */ 309930300Sjoerg break; 310030300Sjoerg 310130300Sjoerg /* response is my authproto */ 310230300Sjoerg case CHAP_RESPONSE: 310330300Sjoerg value = 1 + (u_char*)(h+1); 310430300Sjoerg value_len = value[-1]; 310530300Sjoerg name = value + value_len; 310630300Sjoerg name_len = len - value_len - 5; 310730300Sjoerg if (name_len < 0) { 310830300Sjoerg if (debug) { 310930300Sjoerg log(LOG_DEBUG, 311040008Sjoerg SPP_FMT "chap corrupted response " 311130300Sjoerg "<%s id=0x%x len=%d", 311240008Sjoerg SPP_ARGS(ifp), 311330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 311430300Sjoerg h->ident, ntohs(h->len)); 311530300Sjoerg if (len > 4) 311630300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 311730300Sjoerg addlog(">\n"); 311830300Sjoerg } 311930300Sjoerg break; 312030300Sjoerg } 312130300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 312230300Sjoerg if (debug) 312330300Sjoerg log(LOG_DEBUG, 312440008Sjoerg SPP_FMT "chap dropping response for old ID " 312530300Sjoerg "(got %d, expected %d)\n", 312640008Sjoerg SPP_ARGS(ifp), 312730300Sjoerg h->ident, sp->confid[IDX_CHAP]); 312830300Sjoerg break; 312930300Sjoerg } 313030300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 313130300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 313240008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 313340008Sjoerg SPP_ARGS(ifp)); 313430300Sjoerg sppp_print_string(name, name_len); 313530300Sjoerg addlog(" != expected "); 313630300Sjoerg sppp_print_string(sp->hisauth.name, 313730300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 313830300Sjoerg addlog("\n"); 313930300Sjoerg } 314030300Sjoerg if (debug) { 314140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 314230300Sjoerg "<%s id=0x%x len=%d name=", 314340008Sjoerg SPP_ARGS(ifp), 314430300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 314530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 314630300Sjoerg h->ident, ntohs (h->len)); 314730300Sjoerg sppp_print_string((char*)name, name_len); 314830300Sjoerg addlog(" value-size=%d value=", value_len); 314930300Sjoerg sppp_print_bytes(value, value_len); 315030300Sjoerg addlog(">\n"); 315130300Sjoerg } 315230300Sjoerg if (value_len != AUTHKEYLEN) { 315330300Sjoerg if (debug) 315430300Sjoerg log(LOG_DEBUG, 315540008Sjoerg SPP_FMT "chap bad hash value length: " 315630300Sjoerg "%d bytes, should be %d\n", 315740008Sjoerg SPP_ARGS(ifp), value_len, 315830300Sjoerg AUTHKEYLEN); 315930300Sjoerg break; 316030300Sjoerg } 316130300Sjoerg 316230300Sjoerg MD5Init(&ctx); 316330300Sjoerg MD5Update(&ctx, &h->ident, 1); 316430300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 316530300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 316630300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 316730300Sjoerg MD5Final(digest, &ctx); 316830300Sjoerg 316930300Sjoerg#define FAILMSG "Failed..." 317030300Sjoerg#define SUCCMSG "Welcome!" 317130300Sjoerg 317230300Sjoerg if (value_len != sizeof digest || 317330300Sjoerg bcmp(digest, value, value_len) != 0) { 317430300Sjoerg /* action scn, tld */ 317530300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 317630300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 317730300Sjoerg 0); 317830300Sjoerg chap.tld(sp); 317930300Sjoerg break; 318030300Sjoerg } 318130300Sjoerg /* action sca, perhaps tlu */ 318230300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 318330300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 318430300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 318530300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 318630300Sjoerg 0); 318730300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 318830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 318930300Sjoerg chap.tlu(sp); 319030300Sjoerg } 319130300Sjoerg break; 319230300Sjoerg 319330300Sjoerg default: 319430300Sjoerg /* Unknown CHAP packet type -- ignore. */ 319530300Sjoerg if (debug) { 319640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 319730300Sjoerg "<0x%x id=0x%xh len=%d", 319840008Sjoerg SPP_ARGS(ifp), 319930300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 320030300Sjoerg h->type, h->ident, ntohs(h->len)); 320130300Sjoerg if (len > 4) 320230300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 320330300Sjoerg addlog(">\n"); 320430300Sjoerg } 320530300Sjoerg break; 320630300Sjoerg 320730300Sjoerg } 320830300Sjoerg} 320930300Sjoerg 321030300Sjoergstatic void 321130300Sjoergsppp_chap_init(struct sppp *sp) 321230300Sjoerg{ 321330300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 321430300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 321530300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 321642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 321730300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 321840008Sjoerg#endif 321930300Sjoerg} 322030300Sjoerg 322130300Sjoergstatic void 322230300Sjoergsppp_chap_open(struct sppp *sp) 322330300Sjoerg{ 322430300Sjoerg if (sp->myauth.proto == PPP_CHAP && 322530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 322630300Sjoerg /* we are authenticator for CHAP, start it */ 322730300Sjoerg chap.scr(sp); 322830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 322930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 323030300Sjoerg } 323130300Sjoerg /* nothing to be done if we are peer, await a challenge */ 323230300Sjoerg} 323330300Sjoerg 323430300Sjoergstatic void 323530300Sjoergsppp_chap_close(struct sppp *sp) 323630300Sjoerg{ 323730300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 323830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 323930300Sjoerg} 324030300Sjoerg 324130300Sjoergstatic void 324230300Sjoergsppp_chap_TO(void *cookie) 324330300Sjoerg{ 324430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 324530300Sjoerg STDDCL; 324630300Sjoerg int s; 324730300Sjoerg 324830300Sjoerg s = splimp(); 324930300Sjoerg if (debug) 325040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 325140008Sjoerg SPP_ARGS(ifp), 325230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 325330300Sjoerg sp->rst_counter[IDX_CHAP]); 325430300Sjoerg 325530300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 325630300Sjoerg /* TO- event */ 325730300Sjoerg switch (sp->state[IDX_CHAP]) { 325830300Sjoerg case STATE_REQ_SENT: 325930300Sjoerg chap.tld(sp); 326030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 326130300Sjoerg break; 326230300Sjoerg } 326330300Sjoerg else 326430300Sjoerg /* TO+ (or TO*) event */ 326530300Sjoerg switch (sp->state[IDX_CHAP]) { 326630300Sjoerg case STATE_OPENED: 326730300Sjoerg /* TO* event */ 326830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 326930300Sjoerg /* fall through */ 327030300Sjoerg case STATE_REQ_SENT: 327130300Sjoerg chap.scr(sp); 327230300Sjoerg /* sppp_cp_change_state() will restart the timer */ 327330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 327430300Sjoerg break; 327530300Sjoerg } 327630300Sjoerg 327730300Sjoerg splx(s); 327830300Sjoerg} 327930300Sjoerg 328030300Sjoergstatic void 328130300Sjoergsppp_chap_tlu(struct sppp *sp) 328230300Sjoerg{ 328330300Sjoerg STDDCL; 328430300Sjoerg int i, x; 328530300Sjoerg 328640010Sjoerg i = 0; 328730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 328830300Sjoerg 328930300Sjoerg /* 329030300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 329130300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 329230300Sjoerg * initial challenge-response exchange has taken place. 329330300Sjoerg * Provide for an option to avoid rechallenges. 329430300Sjoerg */ 329530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 329630300Sjoerg /* 329730300Sjoerg * Compute the re-challenge timeout. This will yield 329830300Sjoerg * a number between 300 and 810 seconds. 329930300Sjoerg */ 330030300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 330142064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 330230300Sjoerg } 330330300Sjoerg 330430300Sjoerg if (debug) { 330530300Sjoerg log(LOG_DEBUG, 330640008Sjoerg SPP_FMT "chap %s, ", 330740008Sjoerg SPP_ARGS(ifp), 330830300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 330930300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 331030300Sjoerg addlog("next re-challenge in %d seconds\n", i); 331130300Sjoerg else 331230300Sjoerg addlog("re-challenging supressed\n"); 331330300Sjoerg } 331430300Sjoerg 331530300Sjoerg x = splimp(); 331630300Sjoerg /* indicate to LCP that we need to be closed down */ 331730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 331830300Sjoerg 331930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 332030300Sjoerg /* 332130300Sjoerg * Remote is authenticator, but his auth proto didn't 332230300Sjoerg * complete yet. Defer the transition to network 332330300Sjoerg * phase. 332430300Sjoerg */ 332530300Sjoerg splx(x); 332630300Sjoerg return; 332730300Sjoerg } 332830300Sjoerg splx(x); 332930300Sjoerg 333030300Sjoerg /* 333130300Sjoerg * If we are already in phase network, we are done here. This 333230300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 333330300Sjoerg */ 333430300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 333530300Sjoerg sppp_phase_network(sp); 333630300Sjoerg} 333730300Sjoerg 333830300Sjoergstatic void 333930300Sjoergsppp_chap_tld(struct sppp *sp) 334030300Sjoerg{ 334130300Sjoerg STDDCL; 334230300Sjoerg 334330300Sjoerg if (debug) 334440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 334540008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 334630300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 334730300Sjoerg 334830300Sjoerg lcp.Close(sp); 334930300Sjoerg} 335030300Sjoerg 335130300Sjoergstatic void 335230300Sjoergsppp_chap_scr(struct sppp *sp) 335330300Sjoerg{ 335430300Sjoerg u_long *ch, seed; 335530300Sjoerg u_char clen; 335630300Sjoerg 335730300Sjoerg /* Compute random challenge. */ 335830300Sjoerg ch = (u_long *)sp->myauth.challenge; 335942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 336035064Sphk read_random(&seed, sizeof seed); 336140008Sjoerg#else 336242104Sphk { 336342104Sphk struct timeval tv; 336440008Sjoerg microtime(&tv); 336540008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 336642104Sphk } 336740008Sjoerg#endif 336830300Sjoerg ch[0] = seed ^ random(); 336930300Sjoerg ch[1] = seed ^ random(); 337030300Sjoerg ch[2] = seed ^ random(); 337130300Sjoerg ch[3] = seed ^ random(); 337230300Sjoerg clen = AUTHKEYLEN; 337330300Sjoerg 337430300Sjoerg sp->confid[IDX_CHAP] = ++sp->pp_seq; 337530300Sjoerg 337630300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 337730300Sjoerg sizeof clen, (const char *)&clen, 337840008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 337940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 338030300Sjoerg sp->myauth.name, 338130300Sjoerg 0); 338230300Sjoerg} 338330300Sjoerg/* 338430300Sjoerg *--------------------------------------------------------------------------* 338530300Sjoerg * * 338630300Sjoerg * The PAP implementation. * 338730300Sjoerg * * 338830300Sjoerg *--------------------------------------------------------------------------* 338930300Sjoerg */ 339030300Sjoerg/* 339130300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 339230300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 339330300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 339430300Sjoerg * retry counter is expired). 339530300Sjoerg */ 339630300Sjoerg 339730300Sjoerg/* 339830300Sjoerg * Handle incoming PAP packets. */ 339930300Sjoergstatic void 340030300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 340130300Sjoerg{ 340230300Sjoerg STDDCL; 340330300Sjoerg struct lcp_header *h; 340430300Sjoerg int len, x; 340530300Sjoerg u_char *name, *passwd, mlen; 340630300Sjoerg int name_len, passwd_len; 340730300Sjoerg 340830300Sjoerg len = m->m_pkthdr.len; 340930300Sjoerg if (len < 5) { 341030300Sjoerg if (debug) 341130300Sjoerg log(LOG_DEBUG, 341240008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 341340008Sjoerg SPP_ARGS(ifp), len); 341430300Sjoerg return; 341530300Sjoerg } 341630300Sjoerg h = mtod (m, struct lcp_header*); 341730300Sjoerg if (len > ntohs (h->len)) 341830300Sjoerg len = ntohs (h->len); 341930300Sjoerg switch (h->type) { 342030300Sjoerg /* PAP request is my authproto */ 342130300Sjoerg case PAP_REQ: 342230300Sjoerg name = 1 + (u_char*)(h+1); 342330300Sjoerg name_len = name[-1]; 342430300Sjoerg passwd = name + name_len + 1; 342530300Sjoerg if (name_len > len - 6 || 342630300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 342730300Sjoerg if (debug) { 342840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 342930300Sjoerg "<%s id=0x%x len=%d", 343040008Sjoerg SPP_ARGS(ifp), 343130300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 343230300Sjoerg h->ident, ntohs(h->len)); 343330300Sjoerg if (len > 4) 343430300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 343530300Sjoerg addlog(">\n"); 343630300Sjoerg } 343730300Sjoerg break; 343830300Sjoerg } 343930300Sjoerg if (debug) { 344040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 344130300Sjoerg "<%s id=0x%x len=%d name=", 344240008Sjoerg SPP_ARGS(ifp), 344330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 344430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 344530300Sjoerg h->ident, ntohs(h->len)); 344630300Sjoerg sppp_print_string((char*)name, name_len); 344730300Sjoerg addlog(" passwd="); 344830300Sjoerg sppp_print_string((char*)passwd, passwd_len); 344930300Sjoerg addlog(">\n"); 345030300Sjoerg } 345130300Sjoerg if (name_len > AUTHNAMELEN || 345230300Sjoerg passwd_len > AUTHKEYLEN || 345330300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 345430300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 345530300Sjoerg /* action scn, tld */ 345630300Sjoerg mlen = sizeof(FAILMSG) - 1; 345730300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 345830300Sjoerg sizeof mlen, (const char *)&mlen, 345930300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 346030300Sjoerg 0); 346130300Sjoerg pap.tld(sp); 346230300Sjoerg break; 346330300Sjoerg } 346430300Sjoerg /* action sca, perhaps tlu */ 346530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 346630300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 346730300Sjoerg mlen = sizeof(SUCCMSG) - 1; 346830300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 346930300Sjoerg sizeof mlen, (const char *)&mlen, 347030300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 347130300Sjoerg 0); 347230300Sjoerg } 347330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 347430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 347530300Sjoerg pap.tlu(sp); 347630300Sjoerg } 347730300Sjoerg break; 347830300Sjoerg 347930300Sjoerg /* ack and nak are his authproto */ 348030300Sjoerg case PAP_ACK: 348140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 348230300Sjoerg if (debug) { 348340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 348440008Sjoerg SPP_ARGS(ifp)); 348530300Sjoerg name_len = *((char *)h); 348630300Sjoerg if (len > 5 && name_len) { 348730300Sjoerg addlog(": "); 348830300Sjoerg sppp_print_string((char*)(h+1), name_len); 348930300Sjoerg } 349030300Sjoerg addlog("\n"); 349130300Sjoerg } 349230300Sjoerg x = splimp(); 349330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 349430300Sjoerg if (sp->myauth.proto == PPP_PAP && 349532169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 349630300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 349730300Sjoerg /* 349830300Sjoerg * We are authenticator for PAP but didn't 349930300Sjoerg * complete yet. Leave it to tlu to proceed 350030300Sjoerg * to network phase. 350130300Sjoerg */ 350230300Sjoerg splx(x); 350330300Sjoerg break; 350430300Sjoerg } 350530300Sjoerg splx(x); 350630300Sjoerg sppp_phase_network(sp); 350730300Sjoerg break; 350830300Sjoerg 350930300Sjoerg case PAP_NAK: 351040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 351130300Sjoerg if (debug) { 351240008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 351340008Sjoerg SPP_ARGS(ifp)); 351430300Sjoerg name_len = *((char *)h); 351530300Sjoerg if (len > 5 && name_len) { 351630300Sjoerg addlog(": "); 351730300Sjoerg sppp_print_string((char*)(h+1), name_len); 351830300Sjoerg } 351930300Sjoerg addlog("\n"); 352030300Sjoerg } else 352140008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 352240008Sjoerg SPP_ARGS(ifp)); 352330300Sjoerg /* await LCP shutdown by authenticator */ 352430300Sjoerg break; 352530300Sjoerg 352630300Sjoerg default: 352730300Sjoerg /* Unknown PAP packet type -- ignore. */ 352830300Sjoerg if (debug) { 352940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 353030300Sjoerg "<0x%x id=0x%x len=%d", 353140008Sjoerg SPP_ARGS(ifp), 353230300Sjoerg h->type, h->ident, ntohs(h->len)); 353330300Sjoerg if (len > 4) 353430300Sjoerg sppp_print_bytes((u_char*)(h+1), len-4); 353530300Sjoerg addlog(">\n"); 353630300Sjoerg } 353730300Sjoerg break; 353830300Sjoerg 353930300Sjoerg } 354030300Sjoerg} 354130300Sjoerg 354230300Sjoergstatic void 354330300Sjoergsppp_pap_init(struct sppp *sp) 354430300Sjoerg{ 354530300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 354630300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 354730300Sjoerg sp->fail_counter[IDX_PAP] = 0; 354842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 354930300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 355030300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 355140008Sjoerg#endif 355230300Sjoerg} 355330300Sjoerg 355430300Sjoergstatic void 355530300Sjoergsppp_pap_open(struct sppp *sp) 355630300Sjoerg{ 355730300Sjoerg if (sp->hisauth.proto == PPP_PAP && 355830300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 355930300Sjoerg /* we are authenticator for PAP, start our timer */ 356030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 356130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 356230300Sjoerg } 356330300Sjoerg if (sp->myauth.proto == PPP_PAP) { 356430300Sjoerg /* we are peer, send a request, and start a timer */ 356530300Sjoerg pap.scr(sp); 356642064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 356742064Sphk sp->pap_my_to_ch); 356830300Sjoerg } 356930300Sjoerg} 357030300Sjoerg 357130300Sjoergstatic void 357230300Sjoergsppp_pap_close(struct sppp *sp) 357330300Sjoerg{ 357430300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 357530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 357630300Sjoerg} 357730300Sjoerg 357830300Sjoerg/* 357930300Sjoerg * That's the timeout routine if we are authenticator. Since the 358030300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 358130300Sjoerg */ 358230300Sjoergstatic void 358330300Sjoergsppp_pap_TO(void *cookie) 358430300Sjoerg{ 358530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 358630300Sjoerg STDDCL; 358730300Sjoerg int s; 358830300Sjoerg 358930300Sjoerg s = splimp(); 359030300Sjoerg if (debug) 359140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 359240008Sjoerg SPP_ARGS(ifp), 359330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 359430300Sjoerg sp->rst_counter[IDX_PAP]); 359530300Sjoerg 359630300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 359730300Sjoerg /* TO- event */ 359830300Sjoerg switch (sp->state[IDX_PAP]) { 359930300Sjoerg case STATE_REQ_SENT: 360030300Sjoerg pap.tld(sp); 360130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 360230300Sjoerg break; 360330300Sjoerg } 360430300Sjoerg else 360530300Sjoerg /* TO+ event, not very much we could do */ 360630300Sjoerg switch (sp->state[IDX_PAP]) { 360730300Sjoerg case STATE_REQ_SENT: 360830300Sjoerg /* sppp_cp_change_state() will restart the timer */ 360930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 361030300Sjoerg break; 361130300Sjoerg } 361230300Sjoerg 361330300Sjoerg splx(s); 361430300Sjoerg} 361530300Sjoerg 361630300Sjoerg/* 361730300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 361830300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 361930300Sjoerg * XXX We should impose a max counter. 362030300Sjoerg */ 362130300Sjoergstatic void 362230300Sjoergsppp_pap_my_TO(void *cookie) 362330300Sjoerg{ 362430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 362530300Sjoerg STDDCL; 362630300Sjoerg 362730300Sjoerg if (debug) 362840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 362940008Sjoerg SPP_ARGS(ifp)); 363030300Sjoerg 363130300Sjoerg pap.scr(sp); 363230300Sjoerg} 363330300Sjoerg 363430300Sjoergstatic void 363530300Sjoergsppp_pap_tlu(struct sppp *sp) 363630300Sjoerg{ 363730300Sjoerg STDDCL; 363830300Sjoerg int x; 363930300Sjoerg 364030300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 364130300Sjoerg 364230300Sjoerg if (debug) 364340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 364440008Sjoerg SPP_ARGS(ifp), pap.name); 364530300Sjoerg 364630300Sjoerg x = splimp(); 364730300Sjoerg /* indicate to LCP that we need to be closed down */ 364830300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 364930300Sjoerg 365030300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 365130300Sjoerg /* 365230300Sjoerg * Remote is authenticator, but his auth proto didn't 365330300Sjoerg * complete yet. Defer the transition to network 365430300Sjoerg * phase. 365530300Sjoerg */ 365630300Sjoerg splx(x); 365730300Sjoerg return; 365830300Sjoerg } 365930300Sjoerg splx(x); 366030300Sjoerg sppp_phase_network(sp); 366130300Sjoerg} 366230300Sjoerg 366330300Sjoergstatic void 366430300Sjoergsppp_pap_tld(struct sppp *sp) 366530300Sjoerg{ 366630300Sjoerg STDDCL; 366730300Sjoerg 366830300Sjoerg if (debug) 366940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 367040008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 367140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 367230300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 367330300Sjoerg 367430300Sjoerg lcp.Close(sp); 367530300Sjoerg} 367630300Sjoerg 367730300Sjoergstatic void 367830300Sjoergsppp_pap_scr(struct sppp *sp) 367930300Sjoerg{ 368030300Sjoerg u_char idlen, pwdlen; 368130300Sjoerg 368230300Sjoerg sp->confid[IDX_PAP] = ++sp->pp_seq; 368330300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 368430300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 368530300Sjoerg 368630300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 368730300Sjoerg sizeof idlen, (const char *)&idlen, 368840008Sjoerg (size_t)idlen, sp->myauth.name, 368930300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 369040008Sjoerg (size_t)pwdlen, sp->myauth.secret, 369130300Sjoerg 0); 369230300Sjoerg} 369330300Sjoerg/* 369425944Sjoerg * Random miscellaneous functions. 369525944Sjoerg */ 369625944Sjoerg 36974910Swollman/* 369830300Sjoerg * Send a PAP or CHAP proto packet. 369930300Sjoerg * 370030300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 370140008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 370230300Sjoerg * mlen == 0. 370342104Sphk * NOTE: never declare variadic functions with types subject to type 370442104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 370542104Sphk * on the architecture you are on... 370630300Sjoerg */ 370730300Sjoerg 370830300Sjoergstatic void 370942104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 371042104Sphk unsigned int type, unsigned int id, 371130300Sjoerg ...) 371230300Sjoerg{ 371330300Sjoerg STDDCL; 371430300Sjoerg struct ppp_header *h; 371530300Sjoerg struct lcp_header *lh; 371630300Sjoerg struct mbuf *m; 371730300Sjoerg u_char *p; 371830300Sjoerg int len; 371942104Sphk unsigned int mlen; 372030300Sjoerg const char *msg; 372130300Sjoerg va_list ap; 372230300Sjoerg 372330300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 372430300Sjoerg if (! m) 372530300Sjoerg return; 372630300Sjoerg m->m_pkthdr.rcvif = 0; 372730300Sjoerg 372830300Sjoerg h = mtod (m, struct ppp_header*); 372930300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 373030300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 373130300Sjoerg h->protocol = htons(cp->proto); 373230300Sjoerg 373330300Sjoerg lh = (struct lcp_header*)(h + 1); 373430300Sjoerg lh->type = type; 373530300Sjoerg lh->ident = id; 373630300Sjoerg p = (u_char*) (lh+1); 373730300Sjoerg 373830300Sjoerg va_start(ap, id); 373930300Sjoerg len = 0; 374030300Sjoerg 374142104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 374230300Sjoerg msg = va_arg(ap, const char *); 374330300Sjoerg len += mlen; 374430300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 374530300Sjoerg va_end(ap); 374630300Sjoerg m_freem(m); 374730300Sjoerg return; 374830300Sjoerg } 374930300Sjoerg 375030300Sjoerg bcopy(msg, p, mlen); 375130300Sjoerg p += mlen; 375230300Sjoerg } 375330300Sjoerg va_end(ap); 375430300Sjoerg 375530300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 375630300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 375730300Sjoerg 375830300Sjoerg if (debug) { 375940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 376040008Sjoerg SPP_ARGS(ifp), cp->name, 376130300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 376230300Sjoerg lh->ident, ntohs(lh->len)); 376330300Sjoerg if (len) 376430300Sjoerg sppp_print_bytes((u_char*) (lh+1), len); 376530300Sjoerg addlog(">\n"); 376630300Sjoerg } 376730300Sjoerg if (IF_QFULL (&sp->pp_cpq)) { 376830300Sjoerg IF_DROP (&sp->pp_fastq); 376930300Sjoerg IF_DROP (&ifp->if_snd); 377030300Sjoerg m_freem (m); 377130300Sjoerg ++ifp->if_oerrors; 377230300Sjoerg } else 377330300Sjoerg IF_ENQUEUE (&sp->pp_cpq, m); 377430300Sjoerg if (! (ifp->if_flags & IFF_OACTIVE)) 377530300Sjoerg (*ifp->if_start) (ifp); 377630300Sjoerg ifp->if_obytes += m->m_pkthdr.len + 3; 377730300Sjoerg} 377830300Sjoerg 377930300Sjoerg/* 378025944Sjoerg * Flush interface queue. 37814910Swollman */ 378212820Sphkstatic void 378325944Sjoergsppp_qflush(struct ifqueue *ifq) 37844910Swollman{ 378525944Sjoerg struct mbuf *m, *n; 37864910Swollman 378725944Sjoerg n = ifq->ifq_head; 378825944Sjoerg while ((m = n)) { 378925944Sjoerg n = m->m_act; 379025944Sjoerg m_freem (m); 379111189Sjkh } 379225944Sjoerg ifq->ifq_head = 0; 379325944Sjoerg ifq->ifq_tail = 0; 379425944Sjoerg ifq->ifq_len = 0; 379525944Sjoerg} 379625944Sjoerg 379725944Sjoerg/* 379825944Sjoerg * Send keepalive packets, every 10 seconds. 379925944Sjoerg */ 380025944Sjoergstatic void 380125944Sjoergsppp_keepalive(void *dummy) 380225944Sjoerg{ 380325944Sjoerg struct sppp *sp; 380425944Sjoerg int s; 380525944Sjoerg 380625944Sjoerg s = splimp(); 380725944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 380825944Sjoerg struct ifnet *ifp = &sp->pp_if; 380925944Sjoerg 381025944Sjoerg /* Keepalive mode disabled or channel down? */ 381125944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 381225944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 381325944Sjoerg continue; 381425944Sjoerg 381525944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 381625944Sjoerg if (! (sp->pp_flags & PP_CISCO) && 381725944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 381825944Sjoerg continue; 381925944Sjoerg 382025944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 382125944Sjoerg /* No keepalive packets got. Stop the interface. */ 382240008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 382325944Sjoerg if_down (ifp); 382426018Sjoerg sppp_qflush (&sp->pp_cpq); 382525944Sjoerg if (! (sp->pp_flags & PP_CISCO)) { 382625944Sjoerg /* XXX */ 382725944Sjoerg /* Shut down the PPP link. */ 382825944Sjoerg lcp.Down(sp); 382925944Sjoerg /* Initiate negotiation. XXX */ 383025944Sjoerg lcp.Up(sp); 383125944Sjoerg } 38324910Swollman } 383325944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 383425944Sjoerg ++sp->pp_alivecnt; 383525944Sjoerg if (sp->pp_flags & PP_CISCO) 383625944Sjoerg sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, 383725944Sjoerg sp->pp_rseq); 383825944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 383925944Sjoerg long nmagic = htonl (sp->lcp.magic); 384025944Sjoerg sp->lcp.echoid = ++sp->pp_seq; 384125944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 384225944Sjoerg sp->lcp.echoid, 4, &nmagic); 384325944Sjoerg } 38444910Swollman } 384525944Sjoerg splx(s); 384642064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 38474910Swollman} 38484910Swollman 384925944Sjoerg/* 385025944Sjoerg * Get both IP addresses. 385125944Sjoerg */ 385225944Sjoergstatic void 385330300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 385425944Sjoerg{ 385525944Sjoerg struct ifnet *ifp = &sp->pp_if; 385625944Sjoerg struct ifaddr *ifa; 385730300Sjoerg struct sockaddr_in *si, *sm; 385825944Sjoerg u_long ssrc, ddst; 385925944Sjoerg 386040010Sjoerg sm = NULL; 386125944Sjoerg ssrc = ddst = 0L; 386225944Sjoerg /* 386325944Sjoerg * Pick the first AF_INET address from the list, 386425944Sjoerg * aliases don't make any sense on a p2p link anyway. 386525944Sjoerg */ 386642065Sphk si = 0; 386742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 386842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 386942104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 387042065Sphk for (ifa = ifp->if_addrlist.tqh_first; 387140008Sjoerg ifa; 387240008Sjoerg ifa = ifa->ifa_list.tqe_next) 387342104Sphk#else 387442104Sphk for (ifa = ifp->if_addrlist; 387542104Sphk ifa; 387642104Sphk ifa = ifa->ifa_next) 387740008Sjoerg#endif 387825944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 387925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 388030300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 388125944Sjoerg if (si) 388225944Sjoerg break; 388325944Sjoerg } 388425944Sjoerg if (ifa) { 388530300Sjoerg if (si && si->sin_addr.s_addr) { 388625944Sjoerg ssrc = si->sin_addr.s_addr; 388730300Sjoerg if (srcmask) 388830300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 388930300Sjoerg } 389025944Sjoerg 389125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 389225944Sjoerg if (si && si->sin_addr.s_addr) 389325944Sjoerg ddst = si->sin_addr.s_addr; 389425944Sjoerg } 389525944Sjoerg 389625944Sjoerg if (dst) *dst = ntohl(ddst); 389725944Sjoerg if (src) *src = ntohl(ssrc); 389825944Sjoerg} 389925944Sjoerg 390025944Sjoerg/* 390125944Sjoerg * Set my IP address. Must be called at splimp. 390225944Sjoerg */ 390325944Sjoergstatic void 390425944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 390525944Sjoerg{ 390642104Sphk STDDCL; 390725944Sjoerg struct ifaddr *ifa; 390825944Sjoerg struct sockaddr_in *si; 390925944Sjoerg 391025944Sjoerg /* 391125944Sjoerg * Pick the first AF_INET address from the list, 391225944Sjoerg * aliases don't make any sense on a p2p link anyway. 391325944Sjoerg */ 391442065Sphk si = 0; 391542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 391642065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 391742104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 391842065Sphk for (ifa = ifp->if_addrlist.tqh_first; 391940008Sjoerg ifa; 392040008Sjoerg ifa = ifa->ifa_list.tqe_next) 392142104Sphk#else 392242104Sphk for (ifa = ifp->if_addrlist; 392342104Sphk ifa; 392442104Sphk ifa = ifa->ifa_next) 392540008Sjoerg#endif 392640008Sjoerg { 392740008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 392840008Sjoerg { 392925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 393025944Sjoerg if (si) 393125944Sjoerg break; 393225944Sjoerg } 393340008Sjoerg } 393440008Sjoerg 393525944Sjoerg if (ifa && si) 393642104Sphk { 393742104Sphk int error; 393842104Sphk#if __NetBSD_Version__ >= 103080000 393942104Sphk struct sockaddr_in new_sin = *si; 394042104Sphk 394142104Sphk new_sin.sin_addr.s_addr = htonl(src); 394242104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 394342104Sphk if(debug && error) 394442104Sphk { 394542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 394642104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 394742104Sphk } 394842104Sphk#else 394942104Sphk /* delete old route */ 395042104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 395142104Sphk if(debug && error) 395242104Sphk { 395342104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 395442104Sphk SPP_ARGS(ifp), error); 395542104Sphk } 395642104Sphk 395742104Sphk /* set new address */ 395825944Sjoerg si->sin_addr.s_addr = htonl(src); 395925944Sjoerg 396042104Sphk /* add new route */ 396142104Sphk error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 396242104Sphk if (debug && error) 396342104Sphk { 396442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 396542104Sphk SPP_ARGS(ifp), error); 396642104Sphk } 396742104Sphk#endif 396842104Sphk } 396942104Sphk} 397042104Sphk 397130300Sjoergstatic int 397238343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 397330300Sjoerg{ 397438343Sbde u_long subcmd; 397530300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 397630300Sjoerg struct spppreq spr; 397730300Sjoerg 397830300Sjoerg /* 397930300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 398030300Sjoerg * Check the cmd word first before attempting to fetch all the 398130300Sjoerg * data. 398230300Sjoerg */ 398330300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 398430300Sjoerg return EFAULT; 398530300Sjoerg 398630300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 398730300Sjoerg return EFAULT; 398830300Sjoerg 398930300Sjoerg switch (subcmd) { 399030300Sjoerg case SPPPIOGDEFS: 399130300Sjoerg if (cmd != SIOCGIFGENERIC) 399230300Sjoerg return EINVAL; 399330300Sjoerg /* 399430300Sjoerg * We copy over the entire current state, but clean 399530300Sjoerg * out some of the stuff we don't wanna pass up. 399630300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 399730300Sjoerg * called by any user. No need to ever get PAP or 399830300Sjoerg * CHAP secrets back to userland anyway. 399930300Sjoerg */ 400030300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 400130300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 400230300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 400330300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 400430300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 400530300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 400630300Sjoerg 400730300Sjoerg case SPPPIOSDEFS: 400830300Sjoerg if (cmd != SIOCSIFGENERIC) 400930300Sjoerg return EINVAL; 401030300Sjoerg /* 401130300Sjoerg * We have a very specific idea of which fields we allow 401230300Sjoerg * being passed back from userland, so to not clobber our 401330300Sjoerg * current state. For one, we only allow setting 401430300Sjoerg * anything if LCP is in dead phase. Once the LCP 401530300Sjoerg * negotiations started, the authentication settings must 401630300Sjoerg * not be changed again. (The administrator can force an 401730300Sjoerg * ifconfig down in order to get LCP back into dead 401830300Sjoerg * phase.) 401930300Sjoerg * 402030300Sjoerg * Also, we only allow for authentication parameters to be 402130300Sjoerg * specified. 402230300Sjoerg * 402330300Sjoerg * XXX Should allow to set or clear pp_flags. 402430300Sjoerg * 402530300Sjoerg * Finally, if the respective authentication protocol to 402630300Sjoerg * be used is set differently than 0, but the secret is 402730300Sjoerg * passed as all zeros, we don't trash the existing secret. 402830300Sjoerg * This allows an administrator to change the system name 402930300Sjoerg * only without clobbering the secret (which he didn't get 403030300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 403130300Sjoerg * secrets are cleared if the authentication protocol is 403230300Sjoerg * reset to 0. 403330300Sjoerg */ 403430300Sjoerg if (sp->pp_phase != PHASE_DEAD) 403530300Sjoerg return EBUSY; 403630300Sjoerg 403730300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 403830300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 403930300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 404030300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 404130300Sjoerg return EINVAL; 404230300Sjoerg 404330300Sjoerg if (spr.defs.myauth.proto == 0) 404430300Sjoerg /* resetting myauth */ 404530300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 404630300Sjoerg else { 404730300Sjoerg /* setting/changing myauth */ 404830300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 404930300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 405030300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 405130300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 405230300Sjoerg AUTHKEYLEN); 405330300Sjoerg } 405430300Sjoerg if (spr.defs.hisauth.proto == 0) 405530300Sjoerg /* resetting hisauth */ 405630300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 405730300Sjoerg else { 405830300Sjoerg /* setting/changing hisauth */ 405930300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 406030300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 406130300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 406230300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 406330300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 406430300Sjoerg AUTHKEYLEN); 406530300Sjoerg } 406630300Sjoerg break; 406730300Sjoerg 406830300Sjoerg default: 406930300Sjoerg return EINVAL; 407030300Sjoerg } 407130300Sjoerg 407230300Sjoerg return 0; 407330300Sjoerg} 407430300Sjoerg 407530300Sjoergstatic void 407630300Sjoergsppp_phase_network(struct sppp *sp) 407730300Sjoerg{ 407842066Sphk STDDCL; 407930300Sjoerg int i; 408030300Sjoerg u_long mask; 408130300Sjoerg 408230300Sjoerg sp->pp_phase = PHASE_NETWORK; 408330300Sjoerg 408442066Sphk if (debug) 408542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 408642066Sphk sppp_phase_name(sp->pp_phase)); 408730300Sjoerg 408830300Sjoerg /* Notify NCPs now. */ 408930300Sjoerg for (i = 0; i < IDX_COUNT; i++) 409030300Sjoerg if ((cps[i])->flags & CP_NCP) 409130300Sjoerg (cps[i])->Open(sp); 409230300Sjoerg 409330300Sjoerg /* Send Up events to all NCPs. */ 409430300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 409530300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 409630300Sjoerg (cps[i])->Up(sp); 409730300Sjoerg 409830300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 409930300Sjoerg sppp_lcp_check_and_close(sp); 410030300Sjoerg} 410130300Sjoerg 410230300Sjoerg 410325706Sjoergstatic const char * 410425944Sjoergsppp_cp_type_name(u_char type) 41054910Swollman{ 410630300Sjoerg static char buf[12]; 41074910Swollman switch (type) { 410830300Sjoerg case CONF_REQ: return "conf-req"; 410930300Sjoerg case CONF_ACK: return "conf-ack"; 411030300Sjoerg case CONF_NAK: return "conf-nak"; 411130300Sjoerg case CONF_REJ: return "conf-rej"; 411230300Sjoerg case TERM_REQ: return "term-req"; 411330300Sjoerg case TERM_ACK: return "term-ack"; 411430300Sjoerg case CODE_REJ: return "code-rej"; 411530300Sjoerg case PROTO_REJ: return "proto-rej"; 411630300Sjoerg case ECHO_REQ: return "echo-req"; 411730300Sjoerg case ECHO_REPLY: return "echo-reply"; 411830300Sjoerg case DISC_REQ: return "discard-req"; 41194910Swollman } 412041514Sarchie snprintf (buf, sizeof(buf), "0x%x", type); 412130300Sjoerg return buf; 41224910Swollman} 41234910Swollman 412425706Sjoergstatic const char * 412530300Sjoergsppp_auth_type_name(u_short proto, u_char type) 412630300Sjoerg{ 412730300Sjoerg static char buf[12]; 412830300Sjoerg switch (proto) { 412930300Sjoerg case PPP_CHAP: 413030300Sjoerg switch (type) { 413130300Sjoerg case CHAP_CHALLENGE: return "challenge"; 413230300Sjoerg case CHAP_RESPONSE: return "response"; 413330300Sjoerg case CHAP_SUCCESS: return "success"; 413430300Sjoerg case CHAP_FAILURE: return "failure"; 413530300Sjoerg } 413630300Sjoerg case PPP_PAP: 413730300Sjoerg switch (type) { 413830300Sjoerg case PAP_REQ: return "req"; 413930300Sjoerg case PAP_ACK: return "ack"; 414030300Sjoerg case PAP_NAK: return "nak"; 414130300Sjoerg } 414230300Sjoerg } 414341514Sarchie snprintf (buf, sizeof(buf), "0x%x", type); 414430300Sjoerg return buf; 414530300Sjoerg} 414630300Sjoerg 414730300Sjoergstatic const char * 414825944Sjoergsppp_lcp_opt_name(u_char opt) 41494910Swollman{ 415030300Sjoerg static char buf[12]; 415125944Sjoerg switch (opt) { 415230300Sjoerg case LCP_OPT_MRU: return "mru"; 415330300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 415430300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 415530300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 415630300Sjoerg case LCP_OPT_MAGIC: return "magic"; 415730300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 415830300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 41594910Swollman } 416041514Sarchie snprintf (buf, sizeof(buf), "0x%x", opt); 416130300Sjoerg return buf; 41624910Swollman} 41634910Swollman 416425944Sjoergstatic const char * 416525944Sjoergsppp_ipcp_opt_name(u_char opt) 416625944Sjoerg{ 416730300Sjoerg static char buf[12]; 416825944Sjoerg switch (opt) { 416930300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 417030300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 417130300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 417225944Sjoerg } 417341514Sarchie snprintf (buf, sizeof(buf), "0x%x", opt); 417430300Sjoerg return buf; 417525944Sjoerg} 417625944Sjoerg 417725944Sjoergstatic const char * 417825944Sjoergsppp_state_name(int state) 417925944Sjoerg{ 418025944Sjoerg switch (state) { 418125944Sjoerg case STATE_INITIAL: return "initial"; 418225944Sjoerg case STATE_STARTING: return "starting"; 418325944Sjoerg case STATE_CLOSED: return "closed"; 418425944Sjoerg case STATE_STOPPED: return "stopped"; 418525944Sjoerg case STATE_CLOSING: return "closing"; 418625944Sjoerg case STATE_STOPPING: return "stopping"; 418725944Sjoerg case STATE_REQ_SENT: return "req-sent"; 418825944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 418925944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 419025944Sjoerg case STATE_OPENED: return "opened"; 419125944Sjoerg } 419225944Sjoerg return "illegal"; 419325944Sjoerg} 419425944Sjoerg 419525944Sjoergstatic const char * 419625944Sjoergsppp_phase_name(enum ppp_phase phase) 419725944Sjoerg{ 419825944Sjoerg switch (phase) { 419925944Sjoerg case PHASE_DEAD: return "dead"; 420025944Sjoerg case PHASE_ESTABLISH: return "establish"; 420125944Sjoerg case PHASE_TERMINATE: return "terminate"; 420225944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 420325944Sjoerg case PHASE_NETWORK: return "network"; 420425944Sjoerg } 420525944Sjoerg return "illegal"; 420625944Sjoerg} 420725944Sjoerg 420825944Sjoergstatic const char * 420925944Sjoergsppp_proto_name(u_short proto) 421025944Sjoerg{ 421125944Sjoerg static char buf[12]; 421225944Sjoerg switch (proto) { 421325944Sjoerg case PPP_LCP: return "lcp"; 421425944Sjoerg case PPP_IPCP: return "ipcp"; 421530300Sjoerg case PPP_PAP: return "pap"; 421630300Sjoerg case PPP_CHAP: return "chap"; 421725944Sjoerg } 421841514Sarchie snprintf(buf, sizeof(buf), "0x%x", (unsigned)proto); 421925944Sjoerg return buf; 422025944Sjoerg} 422125944Sjoerg 422212820Sphkstatic void 422330300Sjoergsppp_print_bytes(const u_char *p, u_short len) 42244910Swollman{ 422540008Sjoerg addlog(" %02x", *p++); 42264910Swollman while (--len > 0) 422740008Sjoerg addlog("-%02x", *p++); 42284910Swollman} 422925944Sjoerg 423030300Sjoergstatic void 423130300Sjoergsppp_print_string(const char *p, u_short len) 423230300Sjoerg{ 423330300Sjoerg u_char c; 423430300Sjoerg 423530300Sjoerg while (len-- > 0) { 423630300Sjoerg c = *p++; 423730300Sjoerg /* 423830300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 423930300Sjoerg * using only them, but we don't rely on it. */ 424030300Sjoerg if (c < ' ' || c > '~') 424130300Sjoerg addlog("\\x%x", c); 424230300Sjoerg else 424330300Sjoerg addlog("%c", c); 424430300Sjoerg } 424530300Sjoerg} 424630300Sjoerg 424730300Sjoergstatic const char * 424830300Sjoergsppp_dotted_quad(u_long addr) 424930300Sjoerg{ 425030300Sjoerg static char s[16]; 425130300Sjoerg sprintf(s, "%d.%d.%d.%d", 425240008Sjoerg (int)((addr >> 24) & 0xff), 425340008Sjoerg (int)((addr >> 16) & 0xff), 425440008Sjoerg (int)((addr >> 8) & 0xff), 425538372Sbde (int)(addr & 0xff)); 425630300Sjoerg return s; 425730300Sjoerg} 425830300Sjoerg 425930300Sjoergstatic int 426030300Sjoergsppp_strnlen(u_char *p, int max) 426130300Sjoerg{ 426230300Sjoerg int len; 426330300Sjoerg 426430300Sjoerg for (len = 0; len < max && *p; ++p) 426530300Sjoerg ++len; 426630300Sjoerg return len; 426730300Sjoerg} 426830300Sjoerg 426930300Sjoerg/* a dummy, used to drop uninteresting events */ 427030300Sjoergstatic void 427130300Sjoergsppp_null(struct sppp *unused) 427230300Sjoerg{ 427330300Sjoerg /* do just nothing */ 427430300Sjoerg} 4275