if_spppsubr.c revision 88600
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. 988534Sjoerg * Copyright (C) 1997, 2001 Joerg Wunsch. 1025944Sjoerg * 114910Swollman * This software is distributed with NO WARRANTIES, not even the implied 124910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 134910Swollman * 144910Swollman * Authors grant any other persons or organisations permission to use 154910Swollman * or modify this software as long as this message is kept with the software, 164910Swollman * all derivative works or modified versions. 174910Swollman * 1830300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 1916288Sgpalmer * 2050477Speter * $FreeBSD: head/sys/net/if_spppsubr.c 88600 2001-12-28 23:36:35Z joerg $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2940008Sjoerg#endif 3031742Seivind 3140008Sjoerg#ifdef NetBSD1_3 3240008Sjoerg# if NetBSD1_3 > 6 3340008Sjoerg# include "opt_inet.h" 3454263Sshin# include "opt_inet6.h" 3540008Sjoerg# include "opt_iso.h" 3640008Sjoerg# endif 3740008Sjoerg#endif 3840008Sjoerg 394952Sbde#include <sys/systm.h> 404952Sbde#include <sys/kernel.h> 4170199Sjhay#include <sys/module.h> 4224204Sbde#include <sys/sockio.h> 434910Swollman#include <sys/socket.h> 4425706Sjoerg#include <sys/syslog.h> 4542104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4659604Sobrien#include <sys/random.h> 4742104Sphk#endif 4829024Sbde#include <sys/malloc.h> 494910Swollman#include <sys/mbuf.h> 5040008Sjoerg 5140008Sjoerg#if defined (__OpenBSD__) 5240008Sjoerg#include <sys/md5k.h> 5340008Sjoerg#else 5430300Sjoerg#include <sys/md5.h> 5540008Sjoerg#endif 564910Swollman 574910Swollman#include <net/if.h> 584910Swollman#include <net/netisr.h> 594910Swollman#include <net/if_types.h> 6042104Sphk#include <net/route.h> 6188534Sjoerg#include <netinet/in.h> 6288534Sjoerg#include <netinet/in_systm.h> 6388534Sjoerg#include <netinet/ip.h> 6488534Sjoerg#include <net/slcompress.h> 654910Swollman 6640008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6740008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6840008Sjoerg#endif 6942104Sphk 7030300Sjoerg#include <machine/stdarg.h> 7130300Sjoerg 724910Swollman#ifdef INET 734910Swollman#include <netinet/in.h> 744910Swollman#include <netinet/in_systm.h> 754910Swollman#include <netinet/in_var.h> 764910Swollman#include <netinet/ip.h> 774910Swollman#include <netinet/tcp.h> 7840008Sjoerg# if defined (__FreeBSD__) || defined (__OpenBSD__) 7940008Sjoerg# include <netinet/if_ether.h> 8040008Sjoerg# else 8140008Sjoerg# include <net/ethertypes.h> 8240008Sjoerg# endif 834910Swollman#endif 844910Swollman 8511819Sjulian#ifdef IPX 8611819Sjulian#include <netipx/ipx.h> 8711819Sjulian#include <netipx/ipx_if.h> 8811819Sjulian#endif 8911819Sjulian 904910Swollman#ifdef NS 914910Swollman#include <netns/ns.h> 924910Swollman#include <netns/ns_if.h> 934910Swollman#endif 944910Swollman 954910Swollman#include <net/if_sppp.h> 964910Swollman 9742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 9842064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 9942064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 10042104Sphk# define IOCTL_CMD_T u_long 10140008Sjoerg#else 10242064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10342064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10442104Sphk# define IOCTL_CMD_T int 10540008Sjoerg#endif 10642104Sphk 1074910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1084910Swollman 10925944Sjoerg/* 11025944Sjoerg * Interface flags that can be set in an ifconfig command. 11125944Sjoerg * 11225955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11325944Sjoerg * as being administrative openable, but won't be opened to begin 11425944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11525944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11625955Sjoerg * 11725955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 11825955Sjoerg * arrive to be sent. 11930300Sjoerg * 12030300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 12130300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12230300Sjoerg * like 12330300Sjoerg * 12430300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12530300Sjoerg * 12630300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12730300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 12825944Sjoerg */ 12925944Sjoerg 13025955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 13125955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13245152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13325944Sjoerg 13430300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13530300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13630300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13730300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 13830300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 13930300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 14088534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 14188534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 14278064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 14330300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14430300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14530300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14630300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 14778064Sume#define PPP_IPV6CP 0x8057 /* IPv6 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 17478064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 17578064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 17678064Sume 17788534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 17888534Sjoerg 17930300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 18030300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 18130300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1824910Swollman 18330300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 18430300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 18530300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18630300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18730300Sjoerg 18830300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 18930300Sjoerg 19030300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 19130300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 19230300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 19330300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 19430300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 19530300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19630300Sjoerg 19725944Sjoerg/* states are named and numbered according to RFC 1661 */ 19825944Sjoerg#define STATE_INITIAL 0 19925944Sjoerg#define STATE_STARTING 1 20025944Sjoerg#define STATE_CLOSED 2 20125944Sjoerg#define STATE_STOPPED 3 20225944Sjoerg#define STATE_CLOSING 4 20325944Sjoerg#define STATE_STOPPING 5 20425944Sjoerg#define STATE_REQ_SENT 6 20525944Sjoerg#define STATE_ACK_RCVD 7 20625944Sjoerg#define STATE_ACK_SENT 8 20725944Sjoerg#define STATE_OPENED 9 20825944Sjoerg 2094910Swollmanstruct ppp_header { 21011189Sjkh u_char address; 21111189Sjkh u_char control; 21211189Sjkh u_short protocol; 2134910Swollman}; 2144910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2154910Swollman 2164910Swollmanstruct lcp_header { 21711189Sjkh u_char type; 21811189Sjkh u_char ident; 21911189Sjkh u_short len; 2204910Swollman}; 2214910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2224910Swollman 2234910Swollmanstruct cisco_packet { 22411189Sjkh u_long type; 22511189Sjkh u_long par1; 22611189Sjkh u_long par2; 22711189Sjkh u_short rel; 22811189Sjkh u_short time0; 22911189Sjkh u_short time1; 2304910Swollman}; 2314910Swollman#define CISCO_PACKET_LEN 18 2324910Swollman 23325944Sjoerg/* 23425944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 23525944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23625944Sjoerg * case you can't make sense out of these abbreviation; it will also 23725944Sjoerg * explain the semantics related to the various events and actions. 23825944Sjoerg */ 23925944Sjoergstruct cp { 24025944Sjoerg u_short proto; /* PPP control protocol number */ 24125944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 24225944Sjoerg u_char flags; 24325944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 24425944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 24525944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24625944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24725944Sjoerg const char *name; /* name of this control protocol */ 24825944Sjoerg /* event handlers */ 24925944Sjoerg void (*Up)(struct sppp *sp); 25025944Sjoerg void (*Down)(struct sppp *sp); 25125944Sjoerg void (*Open)(struct sppp *sp); 25225944Sjoerg void (*Close)(struct sppp *sp); 25325944Sjoerg void (*TO)(void *sp); 25425944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 25525944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25625944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25725944Sjoerg /* actions */ 25825944Sjoerg void (*tlu)(struct sppp *sp); 25925944Sjoerg void (*tld)(struct sppp *sp); 26025944Sjoerg void (*tls)(struct sppp *sp); 26125944Sjoerg void (*tlf)(struct sppp *sp); 26225944Sjoerg void (*scr)(struct sppp *sp); 26325944Sjoerg}; 26425944Sjoerg 26512820Sphkstatic struct sppp *spppq; 26642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26730300Sjoergstatic struct callout_handle keepalive_ch; 26840008Sjoerg#endif 2694910Swollman 27042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 27140008Sjoerg#define SPP_FMT "%s%d: " 27240008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 27340008Sjoerg#else 27440008Sjoerg#define SPP_FMT "%s: " 27540008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27640008Sjoerg#endif 27740008Sjoerg 2784910Swollman/* 2794910Swollman * The following disgusting hack gets around the problem that IP TOS 2804910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2814910Swollman * priority queue. To decide if traffic is interactive, we check that 2824910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 28330300Sjoerg * 28430300Sjoerg * XXX is this really still necessary? - joerg - 2854910Swollman */ 28611189Sjkhstatic u_short interactive_ports[8] = { 2874910Swollman 0, 513, 0, 0, 2884910Swollman 0, 21, 0, 23, 2894910Swollman}; 2904910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2914910Swollman 29225944Sjoerg/* almost every function needs these */ 29325944Sjoerg#define STDDCL \ 29425944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 29525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29611189Sjkh 29730300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 29825944Sjoerg struct sockaddr *dst, struct rtentry *rt); 2994910Swollman 30025944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 30125944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 30225944Sjoerg 30325944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 30425944Sjoerg struct mbuf *m); 30525944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30625944Sjoerg u_char ident, u_short len, void *data); 30742104Sphk/* static void sppp_cp_timeout(void *arg); */ 30825944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 30925944Sjoerg int newstate); 31030300Sjoergstatic void sppp_auth_send(const struct cp *cp, 31142104Sphk struct sppp *sp, unsigned int type, unsigned int id, 31230300Sjoerg ...); 31325944Sjoerg 31425944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 31525944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31625944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31725944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 31825944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 31925944Sjoerg 32030300Sjoergstatic void sppp_null(struct sppp *sp); 32130300Sjoerg 32225944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 32325944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 32425944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 32525944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32625944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_TO(void *sp); 32825944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 32925944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33025944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33125944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 33225944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 33325944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 33425944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 33525944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33630300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33730300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 33825944Sjoerg 33925944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 34025944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 34125944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 34225944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 34325944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_TO(void *sp); 34525944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34625944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34725944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 34825944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 34925944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 35025944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 35125944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 35225944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 35325944Sjoerg 35478064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 35578064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 35678064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 35778064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 35878064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 35978064Sumestatic void sppp_ipv6cp_TO(void *sp); 36078064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 36178064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 36278064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 36378064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 36478064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 36578064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 36678064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 36778064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 36878064Sume 36930300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 37030300Sjoergstatic void sppp_pap_init(struct sppp *sp); 37130300Sjoergstatic void sppp_pap_open(struct sppp *sp); 37230300Sjoergstatic void sppp_pap_close(struct sppp *sp); 37330300Sjoergstatic void sppp_pap_TO(void *sp); 37430300Sjoergstatic void sppp_pap_my_TO(void *sp); 37530300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 37630300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 37730300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 37830300Sjoerg 37930300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 38030300Sjoergstatic void sppp_chap_init(struct sppp *sp); 38130300Sjoergstatic void sppp_chap_open(struct sppp *sp); 38230300Sjoergstatic void sppp_chap_close(struct sppp *sp); 38330300Sjoergstatic void sppp_chap_TO(void *sp); 38430300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 38530300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 38630300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 38730300Sjoerg 38830300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 38925944Sjoergstatic const char *sppp_cp_type_name(u_char type); 39030300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 39130300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 39278064Sume#ifdef INET6 39378064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 39478064Sume#endif 39525944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 39625944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 39725944Sjoergstatic const char *sppp_proto_name(u_short proto); 39830300Sjoergstatic const char *sppp_state_name(int state); 39938343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 40030300Sjoergstatic int sppp_strnlen(u_char *p, int max); 40130300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 40230300Sjoerg u_long *srcmask); 40325944Sjoergstatic void sppp_keepalive(void *dummy); 40430300Sjoergstatic void sppp_phase_network(struct sppp *sp); 40530300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 40630300Sjoergstatic void sppp_print_string(const char *p, u_short len); 40725944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 40825944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 40978064Sume#ifdef INET6 41078064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 41178064Sume struct in6_addr *dst, struct in6_addr *srcmask); 41278064Sume#ifdef IPV6CP_MYIFID_DYN 41378064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41478064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41578064Sume#endif 41678064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 41778064Sume#endif 41825944Sjoerg 41925944Sjoerg/* our control protocol descriptors */ 42033181Seivindstatic const struct cp lcp = { 42125944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 42225944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 42325944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 42425944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 42525944Sjoerg sppp_lcp_scr 42625944Sjoerg}; 42725944Sjoerg 42833181Seivindstatic const struct cp ipcp = { 42925944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 43025944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 43125944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 43225944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 43325944Sjoerg sppp_ipcp_scr 43425944Sjoerg}; 43525944Sjoerg 43678064Sumestatic const struct cp ipv6cp = { 43778064Sume PPP_IPV6CP, IDX_IPV6CP, 43878064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 43978064Sume CP_NCP, 44078064Sume#else 44178064Sume 0, 44278064Sume#endif 44378064Sume "ipv6cp", 44478064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 44578064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 44678064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 44778064Sume sppp_ipv6cp_scr 44878064Sume}; 44978064Sume 45033181Seivindstatic const struct cp pap = { 45130300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 45230300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 45330300Sjoerg sppp_pap_TO, 0, 0, 0, 45430300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 45530300Sjoerg sppp_pap_scr 45630300Sjoerg}; 45730300Sjoerg 45833181Seivindstatic const struct cp chap = { 45930300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 46030300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 46130300Sjoerg sppp_chap_TO, 0, 0, 0, 46230300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 46330300Sjoerg sppp_chap_scr 46430300Sjoerg}; 46530300Sjoerg 46633181Seivindstatic const struct cp *cps[IDX_COUNT] = { 46725944Sjoerg &lcp, /* IDX_LCP */ 46825944Sjoerg &ipcp, /* IDX_IPCP */ 46978064Sume &ipv6cp, /* IDX_IPV6CP */ 47030300Sjoerg &pap, /* IDX_PAP */ 47130300Sjoerg &chap, /* IDX_CHAP */ 47225944Sjoerg}; 47325944Sjoerg 47470199Sjhaystatic int 47570199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47670199Sjhay{ 47770199Sjhay switch (type) { 47870199Sjhay case MOD_LOAD: 47970199Sjhay break; 48070199Sjhay case MOD_UNLOAD: 48170199Sjhay return EACCES; 48270199Sjhay break; 48370199Sjhay default: 48470199Sjhay break; 48570199Sjhay } 48670199Sjhay return 0; 48770199Sjhay} 48870199Sjhaystatic moduledata_t spppmod = { 48970199Sjhay "sppp", 49070199Sjhay sppp_modevent, 49170199Sjhay 0 49270199Sjhay}; 49370199SjhayMODULE_VERSION(sppp, 1); 49470199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 49525944Sjoerg 49670199Sjhay/* 49725944Sjoerg * Exported functions, comprising our interface to the lower layer. 4984910Swollman */ 4994910Swollman 5004910Swollman/* 5014910Swollman * Process the received packet. 5024910Swollman */ 50325706Sjoergvoid 50425706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5054910Swollman{ 5064910Swollman struct ppp_header *h; 5074910Swollman struct ifqueue *inq = 0; 50825944Sjoerg struct sppp *sp = (struct sppp *)ifp; 50988577Sjoerg int len, do_account = 0; 51025944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5114910Swollman 5124910Swollman if (ifp->if_flags & IFF_UP) 5134910Swollman /* Count received bytes, add FCS and one flag */ 5144910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5154910Swollman 5164910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5174910Swollman /* Too small packet, drop it. */ 51825944Sjoerg if (debug) 51925706Sjoerg log(LOG_DEBUG, 52040008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 52140008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 52225944Sjoerg drop: 52325944Sjoerg ++ifp->if_ierrors; 52425944Sjoerg ++ifp->if_iqdrops; 5254910Swollman m_freem (m); 5264910Swollman return; 5274910Swollman } 5284910Swollman 5294910Swollman /* Get PPP header. */ 5304910Swollman h = mtod (m, struct ppp_header*); 5314910Swollman m_adj (m, PPP_HEADER_LEN); 5324910Swollman 5334910Swollman switch (h->address) { 5344910Swollman case PPP_ALLSTATIONS: 5354910Swollman if (h->control != PPP_UI) 5364910Swollman goto invalid; 53745152Sphk if (sp->pp_mode == IFF_CISCO) { 53825944Sjoerg if (debug) 53925706Sjoerg log(LOG_DEBUG, 54040008Sjoerg SPP_FMT "PPP packet in Cisco mode " 54125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54240008Sjoerg SPP_ARGS(ifp), 54325706Sjoerg h->address, h->control, ntohs(h->protocol)); 54411189Sjkh goto drop; 54511189Sjkh } 5464910Swollman switch (ntohs (h->protocol)) { 5474910Swollman default: 54825944Sjoerg if (debug) 54925706Sjoerg log(LOG_DEBUG, 55044145Sphk SPP_FMT "rejecting protocol " 55125706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55240008Sjoerg SPP_ARGS(ifp), 55325706Sjoerg h->address, h->control, ntohs(h->protocol)); 55444145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 55544145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 55678064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 55744145Sphk &h->protocol); 5584910Swollman ++ifp->if_noproto; 5594910Swollman goto drop; 5604910Swollman case PPP_LCP: 56130300Sjoerg sppp_cp_input(&lcp, sp, m); 5624910Swollman m_freem (m); 5634910Swollman return; 56430300Sjoerg case PPP_PAP: 56530300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 56630300Sjoerg sppp_pap_input(sp, m); 56730300Sjoerg m_freem (m); 56830300Sjoerg return; 56930300Sjoerg case PPP_CHAP: 57030300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 57130300Sjoerg sppp_chap_input(sp, m); 57230300Sjoerg m_freem (m); 57330300Sjoerg return; 5744910Swollman#ifdef INET 5754910Swollman case PPP_IPCP: 57625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 57730300Sjoerg sppp_cp_input(&ipcp, sp, m); 5784910Swollman m_freem (m); 5794910Swollman return; 5804910Swollman case PPP_IP: 58125944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5824910Swollman schednetisr (NETISR_IP); 5834910Swollman inq = &ipintrq; 5844910Swollman } 58588577Sjoerg do_account++; 5864910Swollman break; 58788534Sjoerg case PPP_VJ_COMP: 58888534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 58988534Sjoerg if ((len = 59088534Sjoerg sl_uncompress_tcp((u_char **)&m->m_data, 59188534Sjoerg m->m_len, 59288534Sjoerg TYPE_COMPRESSED_TCP, 59388599Sjoerg sp->pp_comp)) <= 0) 59488534Sjoerg goto drop; 59588534Sjoerg m->m_len = m->m_pkthdr.len = len; 59688534Sjoerg schednetisr (NETISR_IP); 59788534Sjoerg inq = &ipintrq; 59888534Sjoerg } 59988599Sjoerg do_account++; 60088534Sjoerg break; 60188534Sjoerg case PPP_VJ_UCOMP: 60288534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 60388534Sjoerg if ((len = 60488534Sjoerg sl_uncompress_tcp((u_char **)&m->m_data, 60588534Sjoerg m->m_len, 60688534Sjoerg TYPE_UNCOMPRESSED_TCP, 60788599Sjoerg sp->pp_comp)) <= 0) 60888534Sjoerg goto drop; 60988534Sjoerg m->m_len = m->m_pkthdr.len = len; 61088534Sjoerg schednetisr (NETISR_IP); 61188534Sjoerg inq = &ipintrq; 61288534Sjoerg } 61388599Sjoerg do_account++; 61488534Sjoerg break; 61578064Sume#endif 61688599Sjoerg#ifdef INET6 61788599Sjoerg case PPP_IPV6CP: 61888599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 61988599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 62088599Sjoerg m_freem (m); 62188599Sjoerg return; 62288599Sjoerg 62388599Sjoerg case PPP_IPV6: 62488599Sjoerg if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 62588599Sjoerg schednetisr (NETISR_IPV6); 62688599Sjoerg inq = &ip6intrq; 62788599Sjoerg } 62888599Sjoerg do_account++; 62988599Sjoerg break; 63088599Sjoerg#endif 63112495Speter#ifdef IPX 63212495Speter case PPP_IPX: 63312495Speter /* IPX IPXCP not implemented yet */ 63425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 63512495Speter schednetisr (NETISR_IPX); 63612495Speter inq = &ipxintrq; 63712495Speter } 63888577Sjoerg do_account++; 63912495Speter break; 64012495Speter#endif 6414910Swollman#ifdef NS 6424910Swollman case PPP_XNS: 6434910Swollman /* XNS IDPCP not implemented yet */ 64425944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6454910Swollman schednetisr (NETISR_NS); 6464910Swollman inq = &nsintrq; 6474910Swollman } 64888577Sjoerg do_account++; 6494910Swollman break; 6504910Swollman#endif 6514910Swollman } 6524910Swollman break; 6534910Swollman case CISCO_MULTICAST: 6544910Swollman case CISCO_UNICAST: 6554910Swollman /* Don't check the control field here (RFC 1547). */ 65645152Sphk if (sp->pp_mode != IFF_CISCO) { 65725944Sjoerg if (debug) 65825706Sjoerg log(LOG_DEBUG, 65940008Sjoerg SPP_FMT "Cisco packet in PPP mode " 66025706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 66140008Sjoerg SPP_ARGS(ifp), 66225706Sjoerg h->address, h->control, ntohs(h->protocol)); 66311189Sjkh goto drop; 66411189Sjkh } 6654910Swollman switch (ntohs (h->protocol)) { 6664910Swollman default: 6674910Swollman ++ifp->if_noproto; 6684910Swollman goto invalid; 6694910Swollman case CISCO_KEEPALIVE: 6704910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 6714910Swollman m_freem (m); 6724910Swollman return; 6734910Swollman#ifdef INET 6744910Swollman case ETHERTYPE_IP: 6754910Swollman schednetisr (NETISR_IP); 6764910Swollman inq = &ipintrq; 67788577Sjoerg do_account++; 6784910Swollman break; 6794910Swollman#endif 68054263Sshin#ifdef INET6 68154263Sshin case ETHERTYPE_IPV6: 68254263Sshin schednetisr (NETISR_IPV6); 68354263Sshin inq = &ip6intrq; 68488577Sjoerg do_account++; 68554263Sshin break; 68654263Sshin#endif 68712495Speter#ifdef IPX 68812495Speter case ETHERTYPE_IPX: 68912495Speter schednetisr (NETISR_IPX); 69012495Speter inq = &ipxintrq; 69188577Sjoerg do_account++; 69212495Speter break; 69312495Speter#endif 6944910Swollman#ifdef NS 6954910Swollman case ETHERTYPE_NS: 6964910Swollman schednetisr (NETISR_NS); 6974910Swollman inq = &nsintrq; 69888577Sjoerg do_account++; 6994910Swollman break; 7004910Swollman#endif 7014910Swollman } 7024910Swollman break; 70325944Sjoerg default: /* Invalid PPP packet. */ 70425944Sjoerg invalid: 70525944Sjoerg if (debug) 70625944Sjoerg log(LOG_DEBUG, 70740008Sjoerg SPP_FMT "invalid input packet " 70825944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 70940008Sjoerg SPP_ARGS(ifp), 71025944Sjoerg h->address, h->control, ntohs(h->protocol)); 71125944Sjoerg goto drop; 7124910Swollman } 7134910Swollman 7144910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 7154910Swollman goto drop; 7164910Swollman 7174910Swollman /* Check queue. */ 71869152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 71925944Sjoerg if (debug) 72040008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 72140008Sjoerg SPP_ARGS(ifp)); 7224910Swollman goto drop; 7234910Swollman } 72488577Sjoerg if (do_account) 72588577Sjoerg /* 72688577Sjoerg * Do only account for network packets, not for control 72788577Sjoerg * packets. This is used by some subsystems to detect 72888577Sjoerg * idle lines. 72988577Sjoerg */ 73088577Sjoerg sp->pp_last_recv = time_second; 7314910Swollman} 7324910Swollman 7334910Swollman/* 7344910Swollman * Enqueue transmit packet. 7354910Swollman */ 73612820Sphkstatic int 73725706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 73825706Sjoerg struct sockaddr *dst, struct rtentry *rt) 7394910Swollman{ 7404910Swollman struct sppp *sp = (struct sppp*) ifp; 7414910Swollman struct ppp_header *h; 74278064Sume struct ifqueue *ifq = NULL; 74325955Sjoerg int s, rv = 0; 74488534Sjoerg int ipproto = PPP_IP; 74542066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7464910Swollman 74725944Sjoerg s = splimp(); 74825944Sjoerg 74925944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 75025944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 7514910Swollman m_freem (m); 7524910Swollman splx (s); 7534910Swollman return (ENETDOWN); 7544910Swollman } 7554910Swollman 75625944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 75725944Sjoerg /* 75825944Sjoerg * Interface is not yet running, but auto-dial. Need 75925944Sjoerg * to start LCP for it. 76025944Sjoerg */ 76125944Sjoerg ifp->if_flags |= IFF_RUNNING; 76225944Sjoerg splx(s); 76325944Sjoerg lcp.Open(sp); 76425944Sjoerg s = splimp(); 76525944Sjoerg } 76625944Sjoerg 76778134Sume ifq = &ifp->if_snd; 7684910Swollman#ifdef INET 76912436Speter if (dst->sa_family == AF_INET) { 77040008Sjoerg /* XXX Check mbuf length here? */ 77112436Speter struct ip *ip = mtod (m, struct ip*); 77212436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 7734910Swollman 77442104Sphk /* 77542104Sphk * When using dynamic local IP address assignment by using 77642104Sphk * 0.0.0.0 as a local address, the first TCP session will 77742104Sphk * not connect because the local TCP checksum is computed 77842104Sphk * using 0.0.0.0 which will later become our real IP address 77942104Sphk * so the TCP checksum computed at the remote end will 78042104Sphk * become invalid. So we 78142104Sphk * - don't let packets with src ip addr 0 thru 78242104Sphk * - we flag TCP packets with src ip 0 as an error 78370199Sjhay */ 78442104Sphk 78542104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 78642104Sphk { 78742104Sphk m_freem(m); 78842104Sphk splx(s); 78942104Sphk if(ip->ip_p == IPPROTO_TCP) 79042104Sphk return(EADDRNOTAVAIL); 79142104Sphk else 79242104Sphk return(0); 79342104Sphk } 79470199Sjhay 79542104Sphk /* 79642104Sphk * Put low delay, telnet, rlogin and ftp control packets 79742104Sphk * in front of the queue. 79842104Sphk */ 79969152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 80041686Sphk ; 80141686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 80212436Speter ifq = &sp->pp_fastq; 80341686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 80441686Sphk ; 80541686Sphk else if (ip->ip_p != IPPROTO_TCP) 80641686Sphk ; 80741686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 80841686Sphk ifq = &sp->pp_fastq; 80941686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 81041686Sphk ifq = &sp->pp_fastq; 81188534Sjoerg 81288534Sjoerg /* 81388534Sjoerg * Do IP Header compression 81488534Sjoerg */ 81588534Sjoerg if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 81688534Sjoerg ip->ip_p == IPPROTO_TCP) 81788599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 81888534Sjoerg sp->ipcp.compress_cid)) { 81988534Sjoerg case TYPE_COMPRESSED_TCP: 82088534Sjoerg ipproto = PPP_VJ_COMP; 82188534Sjoerg break; 82288534Sjoerg case TYPE_UNCOMPRESSED_TCP: 82388534Sjoerg ipproto = PPP_VJ_UCOMP; 82488534Sjoerg break; 82588534Sjoerg case TYPE_IP: 82688534Sjoerg ipproto = PPP_IP; 82788534Sjoerg break; 82888534Sjoerg default: 82988534Sjoerg m_freem(m); 83088534Sjoerg splx(s); 83188534Sjoerg return (EINVAL); 83288534Sjoerg } 8334910Swollman } 8344910Swollman#endif 8354910Swollman 83678064Sume#ifdef INET6 83778064Sume if (dst->sa_family == AF_INET6) { 83878064Sume /* XXX do something tricky here? */ 83978064Sume } 84078064Sume#endif 84178064Sume 8424910Swollman /* 8434910Swollman * Prepend general data packet PPP header. For now, IP only. 8444910Swollman */ 8454910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 8464910Swollman if (! m) { 84742066Sphk if (debug) 84840008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 84940008Sjoerg SPP_ARGS(ifp)); 85025944Sjoerg ++ifp->if_oerrors; 8514910Swollman splx (s); 8524910Swollman return (ENOBUFS); 8534910Swollman } 85440008Sjoerg /* 85540008Sjoerg * May want to check size of packet 85640008Sjoerg * (albeit due to the implementation it's always enough) 85740008Sjoerg */ 8584910Swollman h = mtod (m, struct ppp_header*); 85945152Sphk if (sp->pp_mode == IFF_CISCO) { 86028088Skjc h->address = CISCO_UNICAST; /* unicast address */ 8614910Swollman h->control = 0; 8624910Swollman } else { 8634910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 8644910Swollman h->control = PPP_UI; /* Unnumbered Info */ 8654910Swollman } 8664910Swollman 8674910Swollman switch (dst->sa_family) { 8684910Swollman#ifdef INET 8694910Swollman case AF_INET: /* Internet Protocol */ 87045152Sphk if (sp->pp_mode == IFF_CISCO) 87111189Sjkh h->protocol = htons (ETHERTYPE_IP); 87211189Sjkh else { 87325955Sjoerg /* 87425955Sjoerg * Don't choke with an ENETDOWN early. It's 87525955Sjoerg * possible that we just started dialing out, 87625955Sjoerg * so don't drop the packet immediately. If 87725955Sjoerg * we notice that we run out of buffer space 87825955Sjoerg * below, we will however remember that we are 87925955Sjoerg * not ready to carry IP packets, and return 88025955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 88125955Sjoerg */ 88288534Sjoerg h->protocol = htons(ipproto); 88325955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 88425955Sjoerg rv = ENETDOWN; 88511189Sjkh } 8864910Swollman break; 8874910Swollman#endif 88854263Sshin#ifdef INET6 88954263Sshin case AF_INET6: /* Internet Protocol */ 89054263Sshin if (sp->pp_mode == IFF_CISCO) 89154263Sshin h->protocol = htons (ETHERTYPE_IPV6); 89254263Sshin else { 89378064Sume /* 89478064Sume * Don't choke with an ENETDOWN early. It's 89578064Sume * possible that we just started dialing out, 89678064Sume * so don't drop the packet immediately. If 89778064Sume * we notice that we run out of buffer space 89878064Sume * below, we will however remember that we are 89978064Sume * not ready to carry IP packets, and return 90078064Sume * ENETDOWN, as opposed to ENOBUFS. 90178064Sume */ 90278064Sume h->protocol = htons(PPP_IPV6); 90378064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 90478064Sume rv = ENETDOWN; 90554263Sshin } 90654263Sshin break; 90754263Sshin#endif 9084910Swollman#ifdef NS 9094910Swollman case AF_NS: /* Xerox NS Protocol */ 91045152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 9114910Swollman ETHERTYPE_NS : PPP_XNS); 9124910Swollman break; 9134910Swollman#endif 91411819Sjulian#ifdef IPX 91512495Speter case AF_IPX: /* Novell IPX Protocol */ 91645152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 91712495Speter ETHERTYPE_IPX : PPP_IPX); 91811819Sjulian break; 91911819Sjulian#endif 9204910Swollman default: 9214910Swollman m_freem (m); 92225944Sjoerg ++ifp->if_oerrors; 9234910Swollman splx (s); 9244910Swollman return (EAFNOSUPPORT); 9254910Swollman } 9264910Swollman 9274910Swollman /* 9284910Swollman * Queue message on interface, and start output if interface 92988577Sjoerg * not yet active. 9304910Swollman */ 93169152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 93225944Sjoerg ++ifp->if_oerrors; 93325955Sjoerg return (rv? rv: ENOBUFS); 9344910Swollman } 93588577Sjoerg /* 93688577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 93788577Sjoerg * here since sppp_output() is only called on behalf of 93888577Sjoerg * network-layer traffic; control-layer traffic is handled 93988577Sjoerg * by sppp_cp_send(). 94088577Sjoerg */ 94188577Sjoerg sp->pp_last_sent = time_second; 9424910Swollman return (0); 9434910Swollman} 9444910Swollman 94525706Sjoergvoid 94625706Sjoergsppp_attach(struct ifnet *ifp) 9474910Swollman{ 9484910Swollman struct sppp *sp = (struct sppp*) ifp; 9494910Swollman 9504910Swollman /* Initialize keepalive handler. */ 9514910Swollman if (! spppq) 95242064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 9534910Swollman 9544910Swollman /* Insert new entry into the keepalive list. */ 9554910Swollman sp->pp_next = spppq; 9564910Swollman spppq = sp; 9574910Swollman 95842064Sphk sp->pp_if.if_mtu = PP_MTU; 95942064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 9604910Swollman sp->pp_if.if_type = IFT_PPP; 9614910Swollman sp->pp_if.if_output = sppp_output; 96242104Sphk#if 0 96342064Sphk sp->pp_flags = PP_KEEPALIVE; 96442104Sphk#endif 96570199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 96670199Sjhay sp->pp_fastq.ifq_maxlen = 32; 96770199Sjhay sp->pp_cpq.ifq_maxlen = 20; 9684910Swollman sp->pp_loopcnt = 0; 9694910Swollman sp->pp_alivecnt = 0; 97078064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 97178064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 97225944Sjoerg sp->pp_phase = PHASE_DEAD; 97325944Sjoerg sp->pp_up = lcp.Up; 97425944Sjoerg sp->pp_down = lcp.Down; 97569152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 97669152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 97788599Sjoerg sp->pp_last_recv = sp->pp_last_sent = time_second; 97888534Sjoerg sp->enable_vj = 1; 97988599Sjoerg sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAIT); 98088599Sjoerg sl_compress_init(sp->pp_comp, -1); 98125944Sjoerg sppp_lcp_init(sp); 98225944Sjoerg sppp_ipcp_init(sp); 98378064Sume sppp_ipv6cp_init(sp); 98430300Sjoerg sppp_pap_init(sp); 98530300Sjoerg sppp_chap_init(sp); 9864910Swollman} 9874910Swollman 98830300Sjoergvoid 98925706Sjoergsppp_detach(struct ifnet *ifp) 9904910Swollman{ 9914910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 99225944Sjoerg int i; 9934910Swollman 9944910Swollman /* Remove the entry from the keepalive list. */ 9954910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 9964910Swollman if (p == sp) { 9974910Swollman *q = p->pp_next; 9984910Swollman break; 9994910Swollman } 10004910Swollman 10014910Swollman /* Stop keepalive handler. */ 10024910Swollman if (! spppq) 100340008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 100425944Sjoerg 100525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 100640008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 100740008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 100869152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 100969152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 10104910Swollman} 10114910Swollman 10124910Swollman/* 10134910Swollman * Flush the interface output queue. 10144910Swollman */ 101525706Sjoergvoid 101625706Sjoergsppp_flush(struct ifnet *ifp) 10174910Swollman{ 10184910Swollman struct sppp *sp = (struct sppp*) ifp; 10194910Swollman 102025944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 102125944Sjoerg sppp_qflush (&sp->pp_fastq); 102226018Sjoerg sppp_qflush (&sp->pp_cpq); 10234910Swollman} 10244910Swollman 10254910Swollman/* 102611189Sjkh * Check if the output queue is empty. 102711189Sjkh */ 102812820Sphkint 102925706Sjoergsppp_isempty(struct ifnet *ifp) 103011189Sjkh{ 103111189Sjkh struct sppp *sp = (struct sppp*) ifp; 103225944Sjoerg int empty, s; 103311189Sjkh 103425944Sjoerg s = splimp(); 103526018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 103626018Sjoerg !sp->pp_if.if_snd.ifq_head; 103725944Sjoerg splx(s); 103811189Sjkh return (empty); 103911189Sjkh} 104011189Sjkh 104111189Sjkh/* 10424910Swollman * Get next packet to send. 10434910Swollman */ 104425706Sjoergstruct mbuf * 104525706Sjoergsppp_dequeue(struct ifnet *ifp) 10464910Swollman{ 10474910Swollman struct sppp *sp = (struct sppp*) ifp; 10484910Swollman struct mbuf *m; 104925944Sjoerg int s; 10504910Swollman 105125944Sjoerg s = splimp(); 105226018Sjoerg /* 105330300Sjoerg * Process only the control protocol queue until we have at 105430300Sjoerg * least one NCP open. 105526018Sjoerg * 105626018Sjoerg * Do always serve all three queues in Cisco mode. 105726018Sjoerg */ 105826018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 105926018Sjoerg if (m == NULL && 106045152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 106126018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 106226018Sjoerg if (m == NULL) 106326018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 106426018Sjoerg } 106526018Sjoerg splx(s); 106626018Sjoerg return m; 10674910Swollman} 10684910Swollman 10694910Swollman/* 107030300Sjoerg * Pick the next packet, do not remove it from the queue. 107130300Sjoerg */ 107230300Sjoergstruct mbuf * 107330300Sjoergsppp_pick(struct ifnet *ifp) 107430300Sjoerg{ 107530300Sjoerg struct sppp *sp = (struct sppp*)ifp; 107630300Sjoerg struct mbuf *m; 107730300Sjoerg int s; 107830300Sjoerg 107930300Sjoerg s= splimp (); 108030300Sjoerg 108130300Sjoerg m = sp->pp_cpq.ifq_head; 108230300Sjoerg if (m == NULL && 108345152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 108430300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 108530300Sjoerg m = sp->pp_if.if_snd.ifq_head; 108630300Sjoerg splx (s); 108730300Sjoerg return (m); 108830300Sjoerg} 108930300Sjoerg 109030300Sjoerg/* 109125944Sjoerg * Process an ioctl request. Called on low priority level. 10924910Swollman */ 109325944Sjoergint 109442104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 10954910Swollman{ 109625944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 109725944Sjoerg struct sppp *sp = (struct sppp*) ifp; 109830300Sjoerg int s, rv, going_up, going_down, newmode; 10994910Swollman 110025944Sjoerg s = splimp(); 110130300Sjoerg rv = 0; 110225944Sjoerg switch (cmd) { 110325944Sjoerg case SIOCAIFADDR: 110425944Sjoerg case SIOCSIFDSTADDR: 110525944Sjoerg break; 11064910Swollman 110725944Sjoerg case SIOCSIFADDR: 110888503Sjoerg /* set the interface "up" when assigning an IP address */ 110988503Sjoerg ifp->if_flags |= IFF_UP; 111025944Sjoerg /* fall through... */ 111111189Sjkh 111225944Sjoerg case SIOCSIFFLAGS: 111325944Sjoerg going_up = ifp->if_flags & IFF_UP && 111425944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 111525944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 111625944Sjoerg ifp->if_flags & IFF_RUNNING; 111745152Sphk 111845152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 111945152Sphk if (!newmode) 112045152Sphk newmode = ifp->if_flags & IFF_AUTO; 112145152Sphk if (!newmode) 112245152Sphk newmode = ifp->if_flags & IFF_CISCO; 112345152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 112445152Sphk ifp->if_flags |= newmode; 112545152Sphk 112645152Sphk if (newmode != sp->pp_mode) { 112745152Sphk going_down = 1; 112845152Sphk if (!going_up) 112945152Sphk going_up = ifp->if_flags & IFF_RUNNING; 11304910Swollman } 11314910Swollman 113245152Sphk if (going_down) { 113370199Sjhay if (sp->pp_mode != IFF_CISCO) 113445152Sphk lcp.Close(sp); 113545152Sphk else if (sp->pp_tlf) 113645152Sphk (sp->pp_tlf)(sp); 113726018Sjoerg sppp_flush(ifp); 113825944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 113945152Sphk sp->pp_mode = newmode; 114026018Sjoerg } 11414910Swollman 114245152Sphk if (going_up) { 114370199Sjhay if (sp->pp_mode != IFF_CISCO) 114445152Sphk lcp.Close(sp); 114545152Sphk sp->pp_mode = newmode; 114645152Sphk if (sp->pp_mode == 0) { 114745152Sphk ifp->if_flags |= IFF_RUNNING; 114845152Sphk lcp.Open(sp); 114945152Sphk } 115045152Sphk if (sp->pp_mode == IFF_CISCO) { 115145152Sphk if (sp->pp_tls) 115245152Sphk (sp->pp_tls)(sp); 115345152Sphk ifp->if_flags |= IFF_RUNNING; 115445152Sphk } 115545152Sphk } 115645152Sphk 11574910Swollman break; 115811189Sjkh 115925944Sjoerg#ifdef SIOCSIFMTU 116025944Sjoerg#ifndef ifr_mtu 116125944Sjoerg#define ifr_mtu ifr_metric 116225944Sjoerg#endif 116325944Sjoerg case SIOCSIFMTU: 116425944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 116525944Sjoerg return (EINVAL); 116625944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 11674910Swollman break; 116825944Sjoerg#endif 116925944Sjoerg#ifdef SLIOCSETMTU 117025944Sjoerg case SLIOCSETMTU: 117125944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 117225944Sjoerg return (EINVAL); 117325944Sjoerg ifp->if_mtu = *(short*)data; 11744910Swollman break; 117525944Sjoerg#endif 117625944Sjoerg#ifdef SIOCGIFMTU 117725944Sjoerg case SIOCGIFMTU: 117825944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 117911189Sjkh break; 118025944Sjoerg#endif 118125944Sjoerg#ifdef SLIOCGETMTU 118225944Sjoerg case SLIOCGETMTU: 118325944Sjoerg *(short*)data = ifp->if_mtu; 11844910Swollman break; 118525944Sjoerg#endif 118625944Sjoerg case SIOCADDMULTI: 118725944Sjoerg case SIOCDELMULTI: 11884910Swollman break; 118911189Sjkh 119030300Sjoerg case SIOCGIFGENERIC: 119130300Sjoerg case SIOCSIFGENERIC: 119230300Sjoerg rv = sppp_params(sp, cmd, data); 119330300Sjoerg break; 119430300Sjoerg 119525944Sjoerg default: 119630300Sjoerg rv = ENOTTY; 11974910Swollman } 119825944Sjoerg splx(s); 119930300Sjoerg return rv; 12004910Swollman} 12014910Swollman 120270199Sjhay/* 120325944Sjoerg * Cisco framing implementation. 120425944Sjoerg */ 120525944Sjoerg 12064910Swollman/* 12074910Swollman * Handle incoming Cisco keepalive protocol packets. 12084910Swollman */ 120930300Sjoergstatic void 121025706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 12114910Swollman{ 121225944Sjoerg STDDCL; 12134910Swollman struct cisco_packet *h; 121430300Sjoerg u_long me, mymask; 12154910Swollman 121627929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 121725706Sjoerg if (debug) 121825706Sjoerg log(LOG_DEBUG, 121940008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 122040008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 12214910Swollman return; 12224910Swollman } 12234910Swollman h = mtod (m, struct cisco_packet*); 122425706Sjoerg if (debug) 122525706Sjoerg log(LOG_DEBUG, 122640008Sjoerg SPP_FMT "cisco input: %d bytes " 122725706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 122840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 122940008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 123040008Sjoerg (u_int)h->time0, (u_int)h->time1); 12314910Swollman switch (ntohl (h->type)) { 12324910Swollman default: 123325706Sjoerg if (debug) 123469211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 123540008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 12364910Swollman break; 12374910Swollman case CISCO_ADDR_REPLY: 12384910Swollman /* Reply on address request, ignore */ 12394910Swollman break; 12404910Swollman case CISCO_KEEPALIVE_REQ: 12414910Swollman sp->pp_alivecnt = 0; 124278064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 124378064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 12444910Swollman /* Local and remote sequence numbers are equal. 12454910Swollman * Probably, the line is in loopback mode. */ 124611189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 124740008Sjoerg printf (SPP_FMT "loopback\n", 124840008Sjoerg SPP_ARGS(ifp)); 124911189Sjkh sp->pp_loopcnt = 0; 125011189Sjkh if (ifp->if_flags & IFF_UP) { 125111189Sjkh if_down (ifp); 125226018Sjoerg sppp_qflush (&sp->pp_cpq); 125311189Sjkh } 125411189Sjkh } 12554910Swollman ++sp->pp_loopcnt; 12564910Swollman 12574910Swollman /* Generate new local sequence number */ 125842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 125978064Sume sp->pp_seq[IDX_LCP] = random(); 126040008Sjoerg#else 126178064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 126240008Sjoerg#endif 126311189Sjkh break; 126411189Sjkh } 126530300Sjoerg sp->pp_loopcnt = 0; 126611189Sjkh if (! (ifp->if_flags & IFF_UP) && 126711189Sjkh (ifp->if_flags & IFF_RUNNING)) { 126830300Sjoerg if_up(ifp); 126940008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 127011189Sjkh } 12714910Swollman break; 12724910Swollman case CISCO_ADDR_REQ: 127330300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 127430300Sjoerg if (me != 0L) 127530300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 12764910Swollman break; 12774910Swollman } 12784910Swollman} 12794910Swollman 12804910Swollman/* 128125944Sjoerg * Send Cisco keepalive packet. 12824910Swollman */ 128312820Sphkstatic void 128425944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 128525944Sjoerg{ 128625944Sjoerg STDDCL; 128725944Sjoerg struct ppp_header *h; 128825944Sjoerg struct cisco_packet *ch; 128925944Sjoerg struct mbuf *m; 129042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 129135029Sphk struct timeval tv; 129240008Sjoerg#else 129340008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 129440008Sjoerg#endif 129525944Sjoerg 129642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 129736119Sphk getmicrouptime(&tv); 129840008Sjoerg#endif 129970199Sjhay 130025944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 130125944Sjoerg if (! m) 130225944Sjoerg return; 130325944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 130425944Sjoerg m->m_pkthdr.rcvif = 0; 130525944Sjoerg 130625944Sjoerg h = mtod (m, struct ppp_header*); 130725944Sjoerg h->address = CISCO_MULTICAST; 130825944Sjoerg h->control = 0; 130925944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 131025944Sjoerg 131125944Sjoerg ch = (struct cisco_packet*) (h + 1); 131225944Sjoerg ch->type = htonl (type); 131325944Sjoerg ch->par1 = htonl (par1); 131425944Sjoerg ch->par2 = htonl (par2); 131525944Sjoerg ch->rel = -1; 131640008Sjoerg 131742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 131835029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 131935029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 132040008Sjoerg#else 132140008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 132240008Sjoerg ch->time1 = htons ((u_short) t); 132340008Sjoerg#endif 132425944Sjoerg 132525944Sjoerg if (debug) 132625944Sjoerg log(LOG_DEBUG, 132740008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 132840008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 132940008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 133025944Sjoerg 133169152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 133269152Sjlemon ifp->if_oerrors++; 133325944Sjoerg} 133425944Sjoerg 133570199Sjhay/* 133625944Sjoerg * PPP protocol implementation. 133725944Sjoerg */ 133825944Sjoerg 133925944Sjoerg/* 134025944Sjoerg * Send PPP control protocol packet. 134125944Sjoerg */ 134225944Sjoergstatic void 134325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 134425706Sjoerg u_char ident, u_short len, void *data) 13454910Swollman{ 134625944Sjoerg STDDCL; 13474910Swollman struct ppp_header *h; 13484910Swollman struct lcp_header *lh; 13494910Swollman struct mbuf *m; 13504910Swollman 13514910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 13524910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 13534910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 13544910Swollman if (! m) 13554910Swollman return; 13564910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 13574910Swollman m->m_pkthdr.rcvif = 0; 13584910Swollman 13594910Swollman h = mtod (m, struct ppp_header*); 13604910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 13614910Swollman h->control = PPP_UI; /* Unnumbered Info */ 13624910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 13634910Swollman 13644910Swollman lh = (struct lcp_header*) (h + 1); 13654910Swollman lh->type = type; 13664910Swollman lh->ident = ident; 13674910Swollman lh->len = htons (LCP_HEADER_LEN + len); 13684910Swollman if (len) 13694910Swollman bcopy (data, lh+1, len); 13704910Swollman 137125706Sjoerg if (debug) { 137240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 137340008Sjoerg SPP_ARGS(ifp), 137425944Sjoerg sppp_proto_name(proto), 137525944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 137625944Sjoerg ntohs (lh->len)); 137744145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 137869211Sphk log(-1, ">\n"); 13794910Swollman } 138069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 138169152Sjlemon ifp->if_oerrors++; 13824910Swollman} 13834910Swollman 13844910Swollman/* 138525944Sjoerg * Handle incoming PPP control protocol packets. 13864910Swollman */ 138712820Sphkstatic void 138825944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13894910Swollman{ 139025944Sjoerg STDDCL; 139125944Sjoerg struct lcp_header *h; 139225944Sjoerg int len = m->m_pkthdr.len; 139325944Sjoerg int rv; 139425944Sjoerg u_char *p; 13954910Swollman 139625944Sjoerg if (len < 4) { 139725944Sjoerg if (debug) 139825944Sjoerg log(LOG_DEBUG, 139940008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 140040008Sjoerg SPP_ARGS(ifp), cp->name, len); 14014910Swollman return; 140225944Sjoerg } 140325944Sjoerg h = mtod (m, struct lcp_header*); 140425944Sjoerg if (debug) { 140525944Sjoerg log(LOG_DEBUG, 140640008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 140740008Sjoerg SPP_ARGS(ifp), cp->name, 140825944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 140925944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 141044145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 141169211Sphk log(-1, ">\n"); 141225944Sjoerg } 141325944Sjoerg if (len > ntohs (h->len)) 141425944Sjoerg len = ntohs (h->len); 141530300Sjoerg p = (u_char *)(h + 1); 141625944Sjoerg switch (h->type) { 141725944Sjoerg case CONF_REQ: 141825944Sjoerg if (len < 4) { 141925944Sjoerg if (debug) 142069211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 142140008Sjoerg SPP_ARGS(ifp), cp->name, 142225944Sjoerg len); 142325944Sjoerg ++ifp->if_ierrors; 142425944Sjoerg break; 142525944Sjoerg } 142630300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 142730300Sjoerg switch (sp->state[cp->protoidx]) { 142830300Sjoerg case STATE_CLOSING: 142930300Sjoerg case STATE_STOPPING: 143030300Sjoerg return; 143130300Sjoerg case STATE_CLOSED: 143230300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 143330300Sjoerg 0, 0); 143430300Sjoerg return; 143530300Sjoerg } 143625944Sjoerg rv = (cp->RCR)(sp, h, len); 143725944Sjoerg switch (sp->state[cp->protoidx]) { 143825944Sjoerg case STATE_OPENED: 143925944Sjoerg (cp->tld)(sp); 144025944Sjoerg (cp->scr)(sp); 144125944Sjoerg /* fall through... */ 144225944Sjoerg case STATE_ACK_SENT: 144325944Sjoerg case STATE_REQ_SENT: 144470199Sjhay /* 144570199Sjhay * sppp_cp_change_state() have the side effect of 144670199Sjhay * restarting the timeouts. We want to avoid that 144770199Sjhay * if the state don't change, otherwise we won't 144870199Sjhay * ever timeout and resend a configuration request 144970199Sjhay * that got lost. 145070199Sjhay */ 145170199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 145270199Sjhay STATE_REQ_SENT)) 145370199Sjhay break; 145425944Sjoerg sppp_cp_change_state(cp, sp, rv? 145525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 145625944Sjoerg break; 145725944Sjoerg case STATE_STOPPED: 145825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 145925944Sjoerg (cp->scr)(sp); 146025944Sjoerg sppp_cp_change_state(cp, sp, rv? 146125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 146225944Sjoerg break; 146325944Sjoerg case STATE_ACK_RCVD: 146425944Sjoerg if (rv) { 146525944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 146625944Sjoerg if (debug) 146740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 146840008Sjoerg SPP_ARGS(ifp), 146926077Sjoerg cp->name); 147025944Sjoerg (cp->tlu)(sp); 147125944Sjoerg } else 147225944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 147325944Sjoerg break; 147425944Sjoerg default: 147540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 147640008Sjoerg SPP_ARGS(ifp), cp->name, 147725944Sjoerg sppp_cp_type_name(h->type), 147825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 147925944Sjoerg ++ifp->if_ierrors; 148025944Sjoerg } 148125944Sjoerg break; 148225944Sjoerg case CONF_ACK: 148325944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 148425944Sjoerg if (debug) 148569211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 148640008Sjoerg SPP_ARGS(ifp), cp->name, 148725944Sjoerg h->ident, sp->confid[cp->protoidx]); 148825944Sjoerg ++ifp->if_ierrors; 148925944Sjoerg break; 149025944Sjoerg } 149125944Sjoerg switch (sp->state[cp->protoidx]) { 149225944Sjoerg case STATE_CLOSED: 149325944Sjoerg case STATE_STOPPED: 149425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 149525944Sjoerg break; 149625944Sjoerg case STATE_CLOSING: 149725944Sjoerg case STATE_STOPPING: 149825944Sjoerg break; 149925944Sjoerg case STATE_REQ_SENT: 150025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 150125944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 150225944Sjoerg break; 150325944Sjoerg case STATE_OPENED: 150425944Sjoerg (cp->tld)(sp); 150525944Sjoerg /* fall through */ 150625944Sjoerg case STATE_ACK_RCVD: 150725944Sjoerg (cp->scr)(sp); 150825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 150925944Sjoerg break; 151025944Sjoerg case STATE_ACK_SENT: 151125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 151225944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 151325944Sjoerg if (debug) 151440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 151540008Sjoerg SPP_ARGS(ifp), cp->name); 151625944Sjoerg (cp->tlu)(sp); 151725944Sjoerg break; 151825944Sjoerg default: 151940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 152040008Sjoerg SPP_ARGS(ifp), cp->name, 152125944Sjoerg sppp_cp_type_name(h->type), 152225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 152325944Sjoerg ++ifp->if_ierrors; 152425944Sjoerg } 152525944Sjoerg break; 152625944Sjoerg case CONF_NAK: 152725944Sjoerg case CONF_REJ: 152825944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 152925944Sjoerg if (debug) 153069211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 153140008Sjoerg SPP_ARGS(ifp), cp->name, 153225944Sjoerg h->ident, sp->confid[cp->protoidx]); 153325944Sjoerg ++ifp->if_ierrors; 153425944Sjoerg break; 153525944Sjoerg } 153625944Sjoerg if (h->type == CONF_NAK) 153725944Sjoerg (cp->RCN_nak)(sp, h, len); 153825944Sjoerg else /* CONF_REJ */ 153925944Sjoerg (cp->RCN_rej)(sp, h, len); 15404910Swollman 154125944Sjoerg switch (sp->state[cp->protoidx]) { 154225944Sjoerg case STATE_CLOSED: 154325944Sjoerg case STATE_STOPPED: 154425944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 154525944Sjoerg break; 154625944Sjoerg case STATE_REQ_SENT: 154725944Sjoerg case STATE_ACK_SENT: 154825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 154970199Sjhay /* 155070199Sjhay * Slow things down a bit if we think we might be 155170199Sjhay * in loopback. Depend on the timeout to send the 155270199Sjhay * next configuration request. 155370199Sjhay */ 155470199Sjhay if (sp->pp_loopcnt) 155570199Sjhay break; 155625944Sjoerg (cp->scr)(sp); 155725944Sjoerg break; 155825944Sjoerg case STATE_OPENED: 155925944Sjoerg (cp->tld)(sp); 156025944Sjoerg /* fall through */ 156125944Sjoerg case STATE_ACK_RCVD: 156252633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 156325944Sjoerg (cp->scr)(sp); 156425944Sjoerg break; 156525944Sjoerg case STATE_CLOSING: 156625944Sjoerg case STATE_STOPPING: 156725944Sjoerg break; 156825944Sjoerg default: 156940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 157040008Sjoerg SPP_ARGS(ifp), cp->name, 157125944Sjoerg sppp_cp_type_name(h->type), 157225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 157325944Sjoerg ++ifp->if_ierrors; 157425944Sjoerg } 157525944Sjoerg break; 15764910Swollman 157725944Sjoerg case TERM_REQ: 157825944Sjoerg switch (sp->state[cp->protoidx]) { 157925944Sjoerg case STATE_ACK_RCVD: 158025944Sjoerg case STATE_ACK_SENT: 158125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 158225944Sjoerg /* fall through */ 158325944Sjoerg case STATE_CLOSED: 158425944Sjoerg case STATE_STOPPED: 158525944Sjoerg case STATE_CLOSING: 158625944Sjoerg case STATE_STOPPING: 158725944Sjoerg case STATE_REQ_SENT: 158825944Sjoerg sta: 158925944Sjoerg /* Send Terminate-Ack packet. */ 159025944Sjoerg if (debug) 159140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 159240008Sjoerg SPP_ARGS(ifp), cp->name); 159325944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 159425944Sjoerg break; 159525944Sjoerg case STATE_OPENED: 159625944Sjoerg (cp->tld)(sp); 159725944Sjoerg sp->rst_counter[cp->protoidx] = 0; 159825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 159925944Sjoerg goto sta; 160025944Sjoerg break; 160125944Sjoerg default: 160240008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 160340008Sjoerg SPP_ARGS(ifp), cp->name, 160425944Sjoerg sppp_cp_type_name(h->type), 160525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160625944Sjoerg ++ifp->if_ierrors; 160725944Sjoerg } 160825944Sjoerg break; 160925944Sjoerg case TERM_ACK: 161025944Sjoerg switch (sp->state[cp->protoidx]) { 161125944Sjoerg case STATE_CLOSED: 161225944Sjoerg case STATE_STOPPED: 161325944Sjoerg case STATE_REQ_SENT: 161425944Sjoerg case STATE_ACK_SENT: 161525944Sjoerg break; 161625944Sjoerg case STATE_CLOSING: 161741881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 161825944Sjoerg (cp->tlf)(sp); 161925944Sjoerg break; 162025944Sjoerg case STATE_STOPPING: 162141881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 162225944Sjoerg (cp->tlf)(sp); 162325944Sjoerg break; 162425944Sjoerg case STATE_ACK_RCVD: 162525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 162625944Sjoerg break; 162725944Sjoerg case STATE_OPENED: 162825944Sjoerg (cp->tld)(sp); 162925944Sjoerg (cp->scr)(sp); 163025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 163125944Sjoerg break; 163225944Sjoerg default: 163340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163440008Sjoerg SPP_ARGS(ifp), cp->name, 163525944Sjoerg sppp_cp_type_name(h->type), 163625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163725944Sjoerg ++ifp->if_ierrors; 163825944Sjoerg } 163925944Sjoerg break; 164025944Sjoerg case CODE_REJ: 164125944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 164230300Sjoerg log(LOG_INFO, 164340008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 164430300Sjoerg "danger will robinson\n", 164540008Sjoerg SPP_ARGS(ifp), cp->name, 164630300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 164725944Sjoerg switch (sp->state[cp->protoidx]) { 164825944Sjoerg case STATE_CLOSED: 164925944Sjoerg case STATE_STOPPED: 165025944Sjoerg case STATE_REQ_SENT: 165125944Sjoerg case STATE_ACK_SENT: 165225944Sjoerg case STATE_CLOSING: 165325944Sjoerg case STATE_STOPPING: 165425944Sjoerg case STATE_OPENED: 165525944Sjoerg break; 165625944Sjoerg case STATE_ACK_RCVD: 165725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 165825944Sjoerg break; 165925944Sjoerg default: 166040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 166140008Sjoerg SPP_ARGS(ifp), cp->name, 166225944Sjoerg sppp_cp_type_name(h->type), 166325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166425944Sjoerg ++ifp->if_ierrors; 166525944Sjoerg } 166625944Sjoerg break; 166780715Sume case PROTO_REJ: 166880715Sume { 166980715Sume int catastrophic; 167080715Sume const struct cp *upper; 167180715Sume int i; 167280715Sume u_int16_t proto; 167380715Sume 167480715Sume catastrophic = 0; 167580715Sume upper = NULL; 167680715Sume proto = ntohs(*((u_int16_t *)p)); 167780715Sume for (i = 0; i < IDX_COUNT; i++) { 167880715Sume if (cps[i]->proto == proto) { 167980715Sume upper = cps[i]; 168080715Sume break; 168180715Sume } 168280715Sume } 168380715Sume if (upper == NULL) 168480715Sume catastrophic++; 168580715Sume 168688508Sjoerg if (catastrophic || debug) 168788508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 168888508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 168988508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 169088508Sjoerg sppp_cp_type_name(h->type), proto, 169188508Sjoerg upper ? upper->name : "unknown", 169288508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 169380715Sume 169480715Sume /* 169580715Sume * if we got RXJ+ against conf-req, the peer does not implement 169680715Sume * this particular protocol type. terminate the protocol. 169780715Sume */ 169880715Sume if (upper && !catastrophic) { 169980715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 170080715Sume upper->Close(sp); 170180715Sume break; 170280715Sume } 170380715Sume } 170480715Sume 170580715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 170680715Sume switch (sp->state[cp->protoidx]) { 170780715Sume case STATE_CLOSED: 170880715Sume case STATE_STOPPED: 170980715Sume case STATE_REQ_SENT: 171080715Sume case STATE_ACK_SENT: 171180715Sume case STATE_CLOSING: 171280715Sume case STATE_STOPPING: 171380715Sume case STATE_OPENED: 171480715Sume break; 171580715Sume case STATE_ACK_RCVD: 171680715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171780715Sume break; 171880715Sume default: 171980715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 172080715Sume SPP_ARGS(ifp), cp->name, 172180715Sume sppp_cp_type_name(h->type), 172280715Sume sppp_state_name(sp->state[cp->protoidx])); 172380715Sume ++ifp->if_ierrors; 172480715Sume } 172580715Sume break; 172680715Sume } 172725944Sjoerg case DISC_REQ: 172825944Sjoerg if (cp->proto != PPP_LCP) 172925944Sjoerg goto illegal; 173025944Sjoerg /* Discard the packet. */ 173125944Sjoerg break; 173225944Sjoerg case ECHO_REQ: 173325944Sjoerg if (cp->proto != PPP_LCP) 173425944Sjoerg goto illegal; 173525944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 173625944Sjoerg if (debug) 173769211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 173840008Sjoerg SPP_ARGS(ifp)); 173925944Sjoerg ++ifp->if_ierrors; 174025944Sjoerg break; 174125944Sjoerg } 174225944Sjoerg if (len < 8) { 174325944Sjoerg if (debug) 174469211Sphk log(-1, SPP_FMT "invalid lcp echo request " 174525944Sjoerg "packet length: %d bytes\n", 174640008Sjoerg SPP_ARGS(ifp), len); 174725944Sjoerg break; 174825944Sjoerg } 174944145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 175044145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 175125944Sjoerg /* Line loopback mode detected. */ 175240008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 175370199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 175425944Sjoerg if_down (ifp); 175526018Sjoerg sppp_qflush (&sp->pp_cpq); 17564910Swollman 175725944Sjoerg /* Shut down the PPP link. */ 175825944Sjoerg /* XXX */ 175925944Sjoerg lcp.Down(sp); 176025944Sjoerg lcp.Up(sp); 176125944Sjoerg break; 176225944Sjoerg } 176325944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 176425944Sjoerg if (debug) 176569211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 176640008Sjoerg SPP_ARGS(ifp)); 176725944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 176825944Sjoerg break; 176925944Sjoerg case ECHO_REPLY: 177025944Sjoerg if (cp->proto != PPP_LCP) 177125944Sjoerg goto illegal; 177225944Sjoerg if (h->ident != sp->lcp.echoid) { 177325944Sjoerg ++ifp->if_ierrors; 177425944Sjoerg break; 177525944Sjoerg } 177625944Sjoerg if (len < 8) { 177725944Sjoerg if (debug) 177869211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 177925944Sjoerg "packet length: %d bytes\n", 178040008Sjoerg SPP_ARGS(ifp), len); 178125944Sjoerg break; 178225944Sjoerg } 178325944Sjoerg if (debug) 178469211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 178540008Sjoerg SPP_ARGS(ifp)); 178644145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 178744145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 178825944Sjoerg sp->pp_alivecnt = 0; 178925944Sjoerg break; 179025944Sjoerg default: 179125944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 179225944Sjoerg illegal: 179325944Sjoerg if (debug) 179469211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 179540008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 179678064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 179778064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 179825944Sjoerg ++ifp->if_ierrors; 179925944Sjoerg } 18004910Swollman} 18014910Swollman 180225944Sjoerg 18034910Swollman/* 180425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 180525944Sjoerg * Basically, the state transition handling in the automaton. 18064910Swollman */ 180725944Sjoergstatic void 180825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18094910Swollman{ 181025944Sjoerg STDDCL; 18114910Swollman 181225944Sjoerg if (debug) 181340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 181440008Sjoerg SPP_ARGS(ifp), cp->name, 181525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 181625944Sjoerg 181725944Sjoerg switch (sp->state[cp->protoidx]) { 181825944Sjoerg case STATE_INITIAL: 181925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 182025944Sjoerg break; 182125944Sjoerg case STATE_STARTING: 182225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 182325944Sjoerg (cp->scr)(sp); 182425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 182525944Sjoerg break; 18264910Swollman default: 182740008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 182840008Sjoerg SPP_ARGS(ifp), cp->name, 182925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 183025944Sjoerg } 183125944Sjoerg} 18324910Swollman 183325944Sjoergstatic void 183425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 183525944Sjoerg{ 183625944Sjoerg STDDCL; 183725944Sjoerg 183825944Sjoerg if (debug) 183940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 184040008Sjoerg SPP_ARGS(ifp), cp->name, 184125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 184225944Sjoerg 184325944Sjoerg switch (sp->state[cp->protoidx]) { 184425944Sjoerg case STATE_CLOSED: 184525944Sjoerg case STATE_CLOSING: 184625944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 18474910Swollman break; 184825944Sjoerg case STATE_STOPPED: 184941881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 185025944Sjoerg (cp->tls)(sp); 185141881Sphk break; 185225944Sjoerg case STATE_STOPPING: 185325944Sjoerg case STATE_REQ_SENT: 185425944Sjoerg case STATE_ACK_RCVD: 185525944Sjoerg case STATE_ACK_SENT: 185625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 185725944Sjoerg break; 185825944Sjoerg case STATE_OPENED: 185925944Sjoerg (cp->tld)(sp); 186025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 186125944Sjoerg break; 186225944Sjoerg default: 186340008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 186440008Sjoerg SPP_ARGS(ifp), cp->name, 186525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 186625944Sjoerg } 186725944Sjoerg} 18684910Swollman 186911189Sjkh 187025944Sjoergstatic void 187125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 187225944Sjoerg{ 187325944Sjoerg STDDCL; 187425944Sjoerg 187525944Sjoerg if (debug) 187640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 187740008Sjoerg SPP_ARGS(ifp), cp->name, 187825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 187925944Sjoerg 188025944Sjoerg switch (sp->state[cp->protoidx]) { 188125944Sjoerg case STATE_INITIAL: 188241881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 188325944Sjoerg (cp->tls)(sp); 18844910Swollman break; 188525944Sjoerg case STATE_STARTING: 188625944Sjoerg break; 188725944Sjoerg case STATE_CLOSED: 188825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 188925944Sjoerg (cp->scr)(sp); 189025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 189125944Sjoerg break; 189225944Sjoerg case STATE_STOPPED: 189374703Sjoerg /* 189474703Sjoerg * Try escaping stopped state. This seems to bite 189574703Sjoerg * people occasionally, in particular for IPCP, 189674703Sjoerg * presumably following previous IPCP negotiation 189774703Sjoerg * aborts. Somehow, we must have missed a Down event 189874703Sjoerg * which would have caused a transition into starting 189974703Sjoerg * state, so as a bandaid we force the Down event now. 190074703Sjoerg * This effectively implements (something like the) 190174703Sjoerg * `restart' option mentioned in the state transition 190274703Sjoerg * table of RFC 1661. 190374703Sjoerg */ 190474703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 190574703Sjoerg (cp->tls)(sp); 190674703Sjoerg break; 190725944Sjoerg case STATE_STOPPING: 190825944Sjoerg case STATE_REQ_SENT: 190925944Sjoerg case STATE_ACK_RCVD: 191025944Sjoerg case STATE_ACK_SENT: 191125944Sjoerg case STATE_OPENED: 191225944Sjoerg break; 191325944Sjoerg case STATE_CLOSING: 191425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 191525944Sjoerg break; 191625944Sjoerg } 191725944Sjoerg} 19184910Swollman 191925944Sjoerg 192025944Sjoergstatic void 192125944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 192225944Sjoerg{ 192325944Sjoerg STDDCL; 192425944Sjoerg 192525944Sjoerg if (debug) 192640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 192740008Sjoerg SPP_ARGS(ifp), cp->name, 192825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 192925944Sjoerg 193025944Sjoerg switch (sp->state[cp->protoidx]) { 193125944Sjoerg case STATE_INITIAL: 193225944Sjoerg case STATE_CLOSED: 193325944Sjoerg case STATE_CLOSING: 19344910Swollman break; 193525944Sjoerg case STATE_STARTING: 193641881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 193725944Sjoerg (cp->tlf)(sp); 19384910Swollman break; 193925944Sjoerg case STATE_STOPPED: 194025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 19414910Swollman break; 194225944Sjoerg case STATE_STOPPING: 194325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19444910Swollman break; 194525944Sjoerg case STATE_OPENED: 194625944Sjoerg (cp->tld)(sp); 194725944Sjoerg /* fall through */ 194825944Sjoerg case STATE_REQ_SENT: 194925944Sjoerg case STATE_ACK_RCVD: 195025944Sjoerg case STATE_ACK_SENT: 195125944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 195278064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 195378064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 195425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19554910Swollman break; 19564910Swollman } 19574910Swollman} 19584910Swollman 195925944Sjoergstatic void 196025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 196125944Sjoerg{ 196225944Sjoerg STDDCL; 196325944Sjoerg int s; 196425944Sjoerg 196525944Sjoerg s = splimp(); 196625944Sjoerg if (debug) 196740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 196840008Sjoerg SPP_ARGS(ifp), cp->name, 196925944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 197025944Sjoerg sp->rst_counter[cp->protoidx]); 197125944Sjoerg 197225944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 197325944Sjoerg /* TO- event */ 197425944Sjoerg switch (sp->state[cp->protoidx]) { 197525944Sjoerg case STATE_CLOSING: 197641881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 197725944Sjoerg (cp->tlf)(sp); 197825944Sjoerg break; 197925944Sjoerg case STATE_STOPPING: 198041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 198125944Sjoerg (cp->tlf)(sp); 198225944Sjoerg break; 198325944Sjoerg case STATE_REQ_SENT: 198425944Sjoerg case STATE_ACK_RCVD: 198525944Sjoerg case STATE_ACK_SENT: 198641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 198725944Sjoerg (cp->tlf)(sp); 198825944Sjoerg break; 198925944Sjoerg } 199025944Sjoerg else 199125944Sjoerg /* TO+ event */ 199225944Sjoerg switch (sp->state[cp->protoidx]) { 199325944Sjoerg case STATE_CLOSING: 199425944Sjoerg case STATE_STOPPING: 199578064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 199678064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 199770199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 199842064Sphk sp->ch[cp->protoidx]); 199925944Sjoerg break; 200025944Sjoerg case STATE_REQ_SENT: 200125944Sjoerg case STATE_ACK_RCVD: 200225944Sjoerg (cp->scr)(sp); 200325944Sjoerg /* sppp_cp_change_state() will restart the timer */ 200425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 200525944Sjoerg break; 200625944Sjoerg case STATE_ACK_SENT: 200725944Sjoerg (cp->scr)(sp); 200842064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 200942064Sphk sp->ch[cp->protoidx]); 201025944Sjoerg break; 201125944Sjoerg } 201225944Sjoerg 201325944Sjoerg splx(s); 201425944Sjoerg} 201525944Sjoerg 201611189Sjkh/* 201725944Sjoerg * Change the state of a control protocol in the state automaton. 201825944Sjoerg * Takes care of starting/stopping the restart timer. 201911189Sjkh */ 202025944Sjoergvoid 202125944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 202225944Sjoerg{ 202325944Sjoerg sp->state[cp->protoidx] = newstate; 202425944Sjoerg 202540008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 202625944Sjoerg switch (newstate) { 202725944Sjoerg case STATE_INITIAL: 202825944Sjoerg case STATE_STARTING: 202925944Sjoerg case STATE_CLOSED: 203025944Sjoerg case STATE_STOPPED: 203125944Sjoerg case STATE_OPENED: 203225944Sjoerg break; 203325944Sjoerg case STATE_CLOSING: 203425944Sjoerg case STATE_STOPPING: 203525944Sjoerg case STATE_REQ_SENT: 203625944Sjoerg case STATE_ACK_RCVD: 203725944Sjoerg case STATE_ACK_SENT: 203870199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 203942064Sphk sp->ch[cp->protoidx]); 204025944Sjoerg break; 204125944Sjoerg } 204225944Sjoerg} 204370199Sjhay 204470199Sjhay/* 204525944Sjoerg *--------------------------------------------------------------------------* 204625944Sjoerg * * 204725944Sjoerg * The LCP implementation. * 204825944Sjoerg * * 204925944Sjoerg *--------------------------------------------------------------------------* 205025944Sjoerg */ 205125944Sjoergstatic void 205225944Sjoergsppp_lcp_init(struct sppp *sp) 205325944Sjoerg{ 205425944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 205525944Sjoerg sp->lcp.magic = 0; 205625944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 205725944Sjoerg sp->fail_counter[IDX_LCP] = 0; 205878064Sume sp->pp_seq[IDX_LCP] = 0; 205978064Sume sp->pp_rseq[IDX_LCP] = 0; 206025944Sjoerg sp->lcp.protos = 0; 206125944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 206230300Sjoerg 206344145Sphk /* Note that these values are relevant for all control protocols */ 206444145Sphk sp->lcp.timeout = 3 * hz; 206525944Sjoerg sp->lcp.max_terminate = 2; 206625944Sjoerg sp->lcp.max_configure = 10; 206725944Sjoerg sp->lcp.max_failure = 10; 206842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 206930300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 207040008Sjoerg#endif 207125944Sjoerg} 207225944Sjoerg 207325944Sjoergstatic void 207425944Sjoergsppp_lcp_up(struct sppp *sp) 207525944Sjoerg{ 207625944Sjoerg STDDCL; 207725944Sjoerg 207870199Sjhay sp->pp_alivecnt = 0; 207970199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 208070199Sjhay sp->lcp.magic = 0; 208170199Sjhay sp->lcp.protos = 0; 208270199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 208325944Sjoerg /* 208475321Sjoerg * If we are authenticator, negotiate LCP_AUTH 208575321Sjoerg */ 208675321Sjoerg if (sp->hisauth.proto != 0) 208775321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 208875321Sjoerg else 208975321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 209075321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 209175321Sjoerg /* 209230300Sjoerg * If this interface is passive or dial-on-demand, and we are 209330300Sjoerg * still in Initial state, it means we've got an incoming 209430300Sjoerg * call. Activate the interface. 209525944Sjoerg */ 209625944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 209725944Sjoerg if (debug) 209825944Sjoerg log(LOG_DEBUG, 209940008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 210025944Sjoerg ifp->if_flags |= IFF_RUNNING; 210130300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 210230300Sjoerg if (debug) 210369211Sphk log(-1, "(incoming call)\n"); 210430300Sjoerg sp->pp_flags |= PP_CALLIN; 210530300Sjoerg lcp.Open(sp); 210630300Sjoerg } else if (debug) 210769211Sphk log(-1, "\n"); 210825944Sjoerg } 210925944Sjoerg 211025944Sjoerg sppp_up_event(&lcp, sp); 211125944Sjoerg} 211225944Sjoerg 211325944Sjoergstatic void 211425944Sjoergsppp_lcp_down(struct sppp *sp) 211525944Sjoerg{ 211625944Sjoerg STDDCL; 211725944Sjoerg 211825944Sjoerg sppp_down_event(&lcp, sp); 211925944Sjoerg 212025944Sjoerg /* 212125944Sjoerg * If this is neither a dial-on-demand nor a passive 212225944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 212325944Sjoerg * administrator can force a redial by another ``ifconfig 212425944Sjoerg * up''. XXX For leased line operation, should we immediately 212525944Sjoerg * try to reopen the connection here? 212625944Sjoerg */ 212725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 212825944Sjoerg log(LOG_INFO, 212942066Sphk SPP_FMT "Down event, taking interface down.\n", 213040008Sjoerg SPP_ARGS(ifp)); 213125944Sjoerg if_down(ifp); 213225944Sjoerg } else { 213325944Sjoerg if (debug) 213425944Sjoerg log(LOG_DEBUG, 213540008Sjoerg SPP_FMT "Down event (carrier loss)\n", 213640008Sjoerg SPP_ARGS(ifp)); 213770199Sjhay sp->pp_flags &= ~PP_CALLIN; 213870199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 213970199Sjhay lcp.Close(sp); 214070199Sjhay ifp->if_flags &= ~IFF_RUNNING; 214125944Sjoerg } 214225944Sjoerg} 214325944Sjoerg 214425944Sjoergstatic void 214525944Sjoergsppp_lcp_open(struct sppp *sp) 214625944Sjoerg{ 214725944Sjoerg sppp_open_event(&lcp, sp); 214825944Sjoerg} 214925944Sjoerg 215025944Sjoergstatic void 215125944Sjoergsppp_lcp_close(struct sppp *sp) 215225944Sjoerg{ 215325944Sjoerg sppp_close_event(&lcp, sp); 215425944Sjoerg} 215525944Sjoerg 215625944Sjoergstatic void 215725944Sjoergsppp_lcp_TO(void *cookie) 215825944Sjoerg{ 215925944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 216025944Sjoerg} 216125944Sjoerg 216225944Sjoerg/* 216325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 216425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 216525944Sjoerg * caused action scn. (The return value is used to make the state 216625944Sjoerg * transition decision in the state automaton.) 216725944Sjoerg */ 216812820Sphkstatic int 216925944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 21704910Swollman{ 217125944Sjoerg STDDCL; 217211189Sjkh u_char *buf, *r, *p; 217325944Sjoerg int origlen, rlen; 217425944Sjoerg u_long nmagic; 217530300Sjoerg u_short authproto; 21764910Swollman 217711189Sjkh len -= 4; 217825944Sjoerg origlen = len; 217911189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 218011189Sjkh if (! buf) 218111189Sjkh return (0); 21824910Swollman 218325706Sjoerg if (debug) 218440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 218540008Sjoerg SPP_ARGS(ifp)); 218625706Sjoerg 218725944Sjoerg /* pass 1: check for things that need to be rejected */ 218811189Sjkh p = (void*) (h+1); 218911189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 219025944Sjoerg if (debug) 219169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 219211189Sjkh switch (*p) { 219311189Sjkh case LCP_OPT_MAGIC: 219425944Sjoerg /* Magic number. */ 219570199Sjhay if (len >= 6 && p[1] == 6) 219670199Sjhay continue; 219770199Sjhay if (debug) 219870199Sjhay log(-1, "[invalid] "); 219970199Sjhay break; 220025944Sjoerg case LCP_OPT_ASYNC_MAP: 220125944Sjoerg /* Async control character map. */ 220270199Sjhay if (len >= 6 && p[1] == 6) 220325944Sjoerg continue; 220425944Sjoerg if (debug) 220569211Sphk log(-1, "[invalid] "); 220625944Sjoerg break; 220725944Sjoerg case LCP_OPT_MRU: 220825944Sjoerg /* Maximum receive unit. */ 220925944Sjoerg if (len >= 4 && p[1] == 4) 221025944Sjoerg continue; 221125944Sjoerg if (debug) 221269211Sphk log(-1, "[invalid] "); 221325944Sjoerg break; 221430300Sjoerg case LCP_OPT_AUTH_PROTO: 221530300Sjoerg if (len < 4) { 221630300Sjoerg if (debug) 221769211Sphk log(-1, "[invalid] "); 221830300Sjoerg break; 221930300Sjoerg } 222030300Sjoerg authproto = (p[2] << 8) + p[3]; 222130300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 222230300Sjoerg if (debug) 222369211Sphk log(-1, "[invalid chap len] "); 222430300Sjoerg break; 222530300Sjoerg } 222630300Sjoerg if (sp->myauth.proto == 0) { 222730300Sjoerg /* we are not configured to do auth */ 222830300Sjoerg if (debug) 222969211Sphk log(-1, "[not configured] "); 223030300Sjoerg break; 223130300Sjoerg } 223230300Sjoerg /* 223330300Sjoerg * Remote want us to authenticate, remember this, 223430300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 223530300Sjoerg * up. 223630300Sjoerg */ 223730300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 223830300Sjoerg continue; 223925944Sjoerg default: 224025944Sjoerg /* Others not supported. */ 224125944Sjoerg if (debug) 224269211Sphk log(-1, "[rej] "); 224325944Sjoerg break; 224425944Sjoerg } 224525944Sjoerg /* Add the option to rejected list. */ 224625944Sjoerg bcopy (p, r, p[1]); 224725944Sjoerg r += p[1]; 224825944Sjoerg rlen += p[1]; 224925944Sjoerg } 225025944Sjoerg if (rlen) { 225125944Sjoerg if (debug) 225269211Sphk log(-1, " send conf-rej\n"); 225325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 225425944Sjoerg return 0; 225525944Sjoerg } else if (debug) 225669211Sphk log(-1, "\n"); 225725944Sjoerg 225825944Sjoerg /* 225925944Sjoerg * pass 2: check for option values that are unacceptable and 226025944Sjoerg * thus require to be nak'ed. 226125944Sjoerg */ 226225944Sjoerg if (debug) 226340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 226440008Sjoerg SPP_ARGS(ifp)); 226525944Sjoerg 226625944Sjoerg p = (void*) (h+1); 226725944Sjoerg len = origlen; 226825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 226925944Sjoerg if (debug) 227069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 227125944Sjoerg switch (*p) { 227225944Sjoerg case LCP_OPT_MAGIC: 227311189Sjkh /* Magic number -- extract. */ 227425944Sjoerg nmagic = (u_long)p[2] << 24 | 227525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 227625944Sjoerg if (nmagic != sp->lcp.magic) { 227770199Sjhay sp->pp_loopcnt = 0; 227825706Sjoerg if (debug) 227969211Sphk log(-1, "0x%lx ", nmagic); 228011189Sjkh continue; 228111189Sjkh } 228270199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 228369211Sphk log(-1, "[glitch] "); 228425944Sjoerg ++sp->pp_loopcnt; 228525944Sjoerg /* 228625944Sjoerg * We negate our magic here, and NAK it. If 228725944Sjoerg * we see it later in an NAK packet, we 228825944Sjoerg * suggest a new one. 228925944Sjoerg */ 229025944Sjoerg nmagic = ~sp->lcp.magic; 229125944Sjoerg /* Gonna NAK it. */ 229225944Sjoerg p[2] = nmagic >> 24; 229325944Sjoerg p[3] = nmagic >> 16; 229425944Sjoerg p[4] = nmagic >> 8; 229525944Sjoerg p[5] = nmagic; 229611189Sjkh break; 229725944Sjoerg 229811189Sjkh case LCP_OPT_ASYNC_MAP: 229988506Sjoerg /* 230088506Sjoerg * Async control character map -- just ignore it. 230188506Sjoerg * 230288506Sjoerg * Quote from RFC 1662, chapter 6: 230388506Sjoerg * To enable this functionality, synchronous PPP 230488506Sjoerg * implementations MUST always respond to the 230588506Sjoerg * Async-Control-Character-Map Configuration 230688506Sjoerg * Option with the LCP Configure-Ack. However, 230788506Sjoerg * acceptance of the Configuration Option does 230888506Sjoerg * not imply that the synchronous implementation 230988506Sjoerg * will do any ACCM mapping. Instead, all such 231088506Sjoerg * octet mapping will be performed by the 231188506Sjoerg * asynchronous-to-synchronous converter. 231288506Sjoerg */ 231388506Sjoerg continue; 231425944Sjoerg 231511189Sjkh case LCP_OPT_MRU: 231625944Sjoerg /* 231725944Sjoerg * Maximum receive unit. Always agreeable, 231825944Sjoerg * but ignored by now. 231925944Sjoerg */ 232025944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 232125706Sjoerg if (debug) 232269211Sphk log(-1, "%lu ", sp->lcp.their_mru); 232311189Sjkh continue; 232430300Sjoerg 232530300Sjoerg case LCP_OPT_AUTH_PROTO: 232630300Sjoerg authproto = (p[2] << 8) + p[3]; 232730300Sjoerg if (sp->myauth.proto != authproto) { 232830300Sjoerg /* not agreed, nak */ 232930300Sjoerg if (debug) 233069211Sphk log(-1, "[mine %s != his %s] ", 233130300Sjoerg sppp_proto_name(sp->hisauth.proto), 233230300Sjoerg sppp_proto_name(authproto)); 233330300Sjoerg p[2] = sp->myauth.proto >> 8; 233430300Sjoerg p[3] = sp->myauth.proto; 233530300Sjoerg break; 233630300Sjoerg } 233730300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 233830300Sjoerg if (debug) 233969211Sphk log(-1, "[chap not MD5] "); 234039981Sjoerg p[4] = CHAP_MD5; 234130300Sjoerg break; 234230300Sjoerg } 234330300Sjoerg continue; 234411189Sjkh } 234525944Sjoerg /* Add the option to nak'ed list. */ 234625706Sjoerg bcopy (p, r, p[1]); 234725706Sjoerg r += p[1]; 234811189Sjkh rlen += p[1]; 234912436Speter } 235025706Sjoerg if (rlen) { 235170199Sjhay /* 235270199Sjhay * Local and remote magics equal -- loopback? 235370199Sjhay */ 235470199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 235570199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 235670199Sjhay printf (SPP_FMT "loopback\n", 235770199Sjhay SPP_ARGS(ifp)); 235870199Sjhay if (ifp->if_flags & IFF_UP) { 235970199Sjhay if_down(ifp); 236070199Sjhay sppp_qflush(&sp->pp_cpq); 236170199Sjhay /* XXX ? */ 236270199Sjhay lcp.Down(sp); 236370199Sjhay lcp.Up(sp); 236470199Sjhay } 236570199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 236628036Sjoerg if (debug) 236769211Sphk log(-1, " max_failure (%d) exceeded, " 236828036Sjoerg "send conf-rej\n", 236928036Sjoerg sp->lcp.max_failure); 237028036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 237128036Sjoerg } else { 237228036Sjoerg if (debug) 237369211Sphk log(-1, " send conf-nak\n"); 237428036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 237528036Sjoerg } 237625944Sjoerg } else { 237725944Sjoerg if (debug) 237869211Sphk log(-1, " send conf-ack\n"); 237928036Sjoerg sp->fail_counter[IDX_LCP] = 0; 238025944Sjoerg sp->pp_loopcnt = 0; 238125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 238225944Sjoerg h->ident, origlen, h+1); 238325944Sjoerg } 238425944Sjoerg 238511189Sjkh free (buf, M_TEMP); 238611189Sjkh return (rlen == 0); 23874910Swollman} 23884910Swollman 238925944Sjoerg/* 239025944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 239125944Sjoerg * negotiation. 239225944Sjoerg */ 239312820Sphkstatic void 239425944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 23954910Swollman{ 239625944Sjoerg STDDCL; 239725944Sjoerg u_char *buf, *p; 23984910Swollman 239925944Sjoerg len -= 4; 240025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 240125944Sjoerg if (!buf) 24024910Swollman return; 240325944Sjoerg 240425944Sjoerg if (debug) 240540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 240640008Sjoerg SPP_ARGS(ifp)); 240725944Sjoerg 240825944Sjoerg p = (void*) (h+1); 240925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 241025944Sjoerg if (debug) 241169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 241225944Sjoerg switch (*p) { 241325944Sjoerg case LCP_OPT_MAGIC: 241425944Sjoerg /* Magic number -- can't use it, use 0 */ 241525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 241625944Sjoerg sp->lcp.magic = 0; 241725944Sjoerg break; 241825944Sjoerg case LCP_OPT_MRU: 241925944Sjoerg /* 242025944Sjoerg * Should not be rejected anyway, since we only 242125944Sjoerg * negotiate a MRU if explicitly requested by 242225944Sjoerg * peer. 242325944Sjoerg */ 242425944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 242525944Sjoerg break; 242630300Sjoerg case LCP_OPT_AUTH_PROTO: 242730300Sjoerg /* 242830300Sjoerg * Peer doesn't want to authenticate himself, 242930300Sjoerg * deny unless this is a dialout call, and 243030300Sjoerg * AUTHFLAG_NOCALLOUT is set. 243130300Sjoerg */ 243230300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 243330300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 243430300Sjoerg if (debug) 243569211Sphk log(-1, "[don't insist on auth " 243630300Sjoerg "for callout]"); 243730300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 243830300Sjoerg break; 243930300Sjoerg } 244030300Sjoerg if (debug) 244169211Sphk log(-1, "[access denied]\n"); 244230300Sjoerg lcp.Close(sp); 244330300Sjoerg break; 244425944Sjoerg } 24454910Swollman } 244625944Sjoerg if (debug) 244769211Sphk log(-1, "\n"); 244825944Sjoerg free (buf, M_TEMP); 244925944Sjoerg return; 245025944Sjoerg} 245125944Sjoerg 245225944Sjoerg/* 245325944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 245425944Sjoerg * negotiation. 245525944Sjoerg */ 245625944Sjoergstatic void 245725944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 245825944Sjoerg{ 245925944Sjoerg STDDCL; 246025944Sjoerg u_char *buf, *p; 246125944Sjoerg u_long magic; 246225944Sjoerg 246325944Sjoerg len -= 4; 246425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 246525944Sjoerg if (!buf) 246625944Sjoerg return; 246725944Sjoerg 246825944Sjoerg if (debug) 246940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 247040008Sjoerg SPP_ARGS(ifp)); 247125944Sjoerg 247225944Sjoerg p = (void*) (h+1); 247325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 247425706Sjoerg if (debug) 247569211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 247625944Sjoerg switch (*p) { 247725944Sjoerg case LCP_OPT_MAGIC: 247825944Sjoerg /* Magic number -- renegotiate */ 247925944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 248025944Sjoerg len >= 6 && p[1] == 6) { 248125944Sjoerg magic = (u_long)p[2] << 24 | 248225944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 248325944Sjoerg /* 248425944Sjoerg * If the remote magic is our negated one, 248525944Sjoerg * this looks like a loopback problem. 248625944Sjoerg * Suggest a new magic to make sure. 248725944Sjoerg */ 248825944Sjoerg if (magic == ~sp->lcp.magic) { 248925944Sjoerg if (debug) 249069211Sphk log(-1, "magic glitch "); 249142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 249235064Sphk sp->lcp.magic = random(); 249340008Sjoerg#else 249440008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 249540008Sjoerg#endif 249625944Sjoerg } else { 249725944Sjoerg sp->lcp.magic = magic; 249825944Sjoerg if (debug) 249969211Sphk log(-1, "%lu ", magic); 250025944Sjoerg } 250125944Sjoerg } 250225944Sjoerg break; 250325944Sjoerg case LCP_OPT_MRU: 250425944Sjoerg /* 250525944Sjoerg * Peer wants to advise us to negotiate an MRU. 250625944Sjoerg * Agree on it if it's reasonable, or use 250725944Sjoerg * default otherwise. 250825944Sjoerg */ 250925944Sjoerg if (len >= 4 && p[1] == 4) { 251025944Sjoerg u_int mru = p[2] * 256 + p[3]; 251125944Sjoerg if (debug) 251269211Sphk log(-1, "%d ", mru); 251325944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 251425944Sjoerg mru = PP_MTU; 251525944Sjoerg sp->lcp.mru = mru; 251625944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 251725944Sjoerg } 251825944Sjoerg break; 251930300Sjoerg case LCP_OPT_AUTH_PROTO: 252030300Sjoerg /* 252130300Sjoerg * Peer doesn't like our authentication method, 252230300Sjoerg * deny. 252330300Sjoerg */ 252430300Sjoerg if (debug) 252569211Sphk log(-1, "[access denied]\n"); 252630300Sjoerg lcp.Close(sp); 252730300Sjoerg break; 25284910Swollman } 252925944Sjoerg } 253025944Sjoerg if (debug) 253169211Sphk log(-1, "\n"); 253225944Sjoerg free (buf, M_TEMP); 253325944Sjoerg return; 253425944Sjoerg} 253511189Sjkh 253625944Sjoergstatic void 253725944Sjoergsppp_lcp_tlu(struct sppp *sp) 253825944Sjoerg{ 253942066Sphk STDDCL; 254025944Sjoerg int i; 254125944Sjoerg u_long mask; 254225944Sjoerg 254325944Sjoerg /* XXX ? */ 254425944Sjoerg if (! (ifp->if_flags & IFF_UP) && 254525944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 254625944Sjoerg /* Coming out of loopback mode. */ 254725944Sjoerg if_up(ifp); 254840008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 254925944Sjoerg } 255025944Sjoerg 255125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 255225944Sjoerg if ((cps[i])->flags & CP_QUAL) 255325944Sjoerg (cps[i])->Open(sp); 255425944Sjoerg 255530300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 255630300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 255725944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 255825944Sjoerg else 255925944Sjoerg sp->pp_phase = PHASE_NETWORK; 256025944Sjoerg 256142066Sphk if (debug) 256242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 256342066Sphk sppp_phase_name(sp->pp_phase)); 256425944Sjoerg 256530300Sjoerg /* 256630300Sjoerg * Open all authentication protocols. This is even required 256730300Sjoerg * if we already proceeded to network phase, since it might be 256830300Sjoerg * that remote wants us to authenticate, so we might have to 256930300Sjoerg * send a PAP request. Undesired authentication protocols 257030300Sjoerg * don't do anything when they get an Open event. 257130300Sjoerg */ 257230300Sjoerg for (i = 0; i < IDX_COUNT; i++) 257330300Sjoerg if ((cps[i])->flags & CP_AUTH) 257430300Sjoerg (cps[i])->Open(sp); 257530300Sjoerg 257630300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 257725944Sjoerg /* Notify all NCPs. */ 257825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 257925944Sjoerg if ((cps[i])->flags & CP_NCP) 258025944Sjoerg (cps[i])->Open(sp); 258125944Sjoerg } 258225944Sjoerg 258325944Sjoerg /* Send Up events to all started protos. */ 258425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 258525944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 258625944Sjoerg (cps[i])->Up(sp); 258725944Sjoerg 258842104Sphk /* notify low-level driver of state change */ 258942104Sphk if (sp->pp_chg) 259042104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 259142104Sphk 259225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 259325944Sjoerg /* if no NCP is starting, close down */ 259430300Sjoerg sppp_lcp_check_and_close(sp); 259525944Sjoerg} 259625944Sjoerg 259725944Sjoergstatic void 259825944Sjoergsppp_lcp_tld(struct sppp *sp) 259925944Sjoerg{ 260042066Sphk STDDCL; 260125944Sjoerg int i; 260225944Sjoerg u_long mask; 260325944Sjoerg 260425944Sjoerg sp->pp_phase = PHASE_TERMINATE; 260525944Sjoerg 260642066Sphk if (debug) 260742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 260842066Sphk sppp_phase_name(sp->pp_phase)); 260925944Sjoerg 261025944Sjoerg /* 261125944Sjoerg * Take upper layers down. We send the Down event first and 261225944Sjoerg * the Close second to prevent the upper layers from sending 261325944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 261425944Sjoerg * describes it. 261525944Sjoerg */ 261625944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 261725944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 261825944Sjoerg (cps[i])->Down(sp); 261925944Sjoerg (cps[i])->Close(sp); 262025944Sjoerg } 262125944Sjoerg} 262225944Sjoerg 262325944Sjoergstatic void 262425944Sjoergsppp_lcp_tls(struct sppp *sp) 262525944Sjoerg{ 262642066Sphk STDDCL; 262725944Sjoerg 262825944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 262925944Sjoerg 263042066Sphk if (debug) 263142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 263242066Sphk sppp_phase_name(sp->pp_phase)); 263325944Sjoerg 263425944Sjoerg /* Notify lower layer if desired. */ 263525944Sjoerg if (sp->pp_tls) 263625944Sjoerg (sp->pp_tls)(sp); 263741881Sphk else 263841881Sphk (sp->pp_up)(sp); 263925944Sjoerg} 264025944Sjoerg 264125944Sjoergstatic void 264225944Sjoergsppp_lcp_tlf(struct sppp *sp) 264325944Sjoerg{ 264442066Sphk STDDCL; 264525944Sjoerg 264625944Sjoerg sp->pp_phase = PHASE_DEAD; 264742066Sphk if (debug) 264842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 264942066Sphk sppp_phase_name(sp->pp_phase)); 265025944Sjoerg 265125944Sjoerg /* Notify lower layer if desired. */ 265225944Sjoerg if (sp->pp_tlf) 265325944Sjoerg (sp->pp_tlf)(sp); 265441881Sphk else 265541881Sphk (sp->pp_down)(sp); 265625944Sjoerg} 265725944Sjoerg 265825944Sjoergstatic void 265925944Sjoergsppp_lcp_scr(struct sppp *sp) 266025944Sjoerg{ 266130300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 266225944Sjoerg int i = 0; 266330300Sjoerg u_short authproto; 266425944Sjoerg 266525944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 266625944Sjoerg if (! sp->lcp.magic) 266742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 266835064Sphk sp->lcp.magic = random(); 266940008Sjoerg#else 267040008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 267140008Sjoerg#endif 267225944Sjoerg opt[i++] = LCP_OPT_MAGIC; 267325944Sjoerg opt[i++] = 6; 267425944Sjoerg opt[i++] = sp->lcp.magic >> 24; 267525944Sjoerg opt[i++] = sp->lcp.magic >> 16; 267625944Sjoerg opt[i++] = sp->lcp.magic >> 8; 267725944Sjoerg opt[i++] = sp->lcp.magic; 267825944Sjoerg } 267925944Sjoerg 268025944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 268125944Sjoerg opt[i++] = LCP_OPT_MRU; 268225944Sjoerg opt[i++] = 4; 268325944Sjoerg opt[i++] = sp->lcp.mru >> 8; 268425944Sjoerg opt[i++] = sp->lcp.mru; 268525944Sjoerg } 268625944Sjoerg 268730300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 268830300Sjoerg authproto = sp->hisauth.proto; 268930300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 269030300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 269130300Sjoerg opt[i++] = authproto >> 8; 269230300Sjoerg opt[i++] = authproto; 269330300Sjoerg if (authproto == PPP_CHAP) 269430300Sjoerg opt[i++] = CHAP_MD5; 269530300Sjoerg } 269630300Sjoerg 269778064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 269825944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 269925944Sjoerg} 270025944Sjoerg 270125944Sjoerg/* 270230300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 270330300Sjoerg */ 270430300Sjoergstatic int 270530300Sjoergsppp_ncp_check(struct sppp *sp) 270630300Sjoerg{ 270730300Sjoerg int i, mask; 270830300Sjoerg 270930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 271030300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 271130300Sjoerg return 1; 271230300Sjoerg return 0; 271330300Sjoerg} 271430300Sjoerg 271530300Sjoerg/* 271625944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 271725944Sjoerg * Called by the NCPs during their tlf action handling. 271825944Sjoerg */ 271925944Sjoergstatic void 272030300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 272125944Sjoerg{ 272225944Sjoerg 272330300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 272430300Sjoerg /* don't bother, we are already going down */ 272530300Sjoerg return; 272630300Sjoerg 272730300Sjoerg if (sppp_ncp_check(sp)) 272830300Sjoerg return; 272930300Sjoerg 273025944Sjoerg lcp.Close(sp); 273125944Sjoerg} 273270199Sjhay 273370199Sjhay/* 273425944Sjoerg *--------------------------------------------------------------------------* 273525944Sjoerg * * 273625944Sjoerg * The IPCP implementation. * 273725944Sjoerg * * 273825944Sjoerg *--------------------------------------------------------------------------* 273925944Sjoerg */ 274025944Sjoerg 274125944Sjoergstatic void 274225944Sjoergsppp_ipcp_init(struct sppp *sp) 274325944Sjoerg{ 274425944Sjoerg sp->ipcp.opts = 0; 274525944Sjoerg sp->ipcp.flags = 0; 274625944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 274725944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 274878064Sume sp->pp_seq[IDX_IPCP] = 0; 274978064Sume sp->pp_rseq[IDX_IPCP] = 0; 275042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 275129681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 275240008Sjoerg#endif 275325944Sjoerg} 275425944Sjoerg 275525944Sjoergstatic void 275625944Sjoergsppp_ipcp_up(struct sppp *sp) 275725944Sjoerg{ 275825944Sjoerg sppp_up_event(&ipcp, sp); 275925944Sjoerg} 276025944Sjoerg 276125944Sjoergstatic void 276225944Sjoergsppp_ipcp_down(struct sppp *sp) 276325944Sjoerg{ 276425944Sjoerg sppp_down_event(&ipcp, sp); 276525944Sjoerg} 276625944Sjoerg 276725944Sjoergstatic void 276825944Sjoergsppp_ipcp_open(struct sppp *sp) 276925944Sjoerg{ 277025944Sjoerg STDDCL; 277125944Sjoerg u_long myaddr, hisaddr; 277225944Sjoerg 277388534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 277488534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 277542104Sphk 277630300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 277725944Sjoerg /* 277825944Sjoerg * If we don't have his address, this probably means our 277925944Sjoerg * interface doesn't want to talk IP at all. (This could 278025944Sjoerg * be the case if somebody wants to speak only IPX, for 278125944Sjoerg * example.) Don't open IPCP in this case. 278225944Sjoerg */ 278325944Sjoerg if (hisaddr == 0L) { 278425944Sjoerg /* XXX this message should go away */ 278525944Sjoerg if (debug) 278640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 278740008Sjoerg SPP_ARGS(ifp)); 278825944Sjoerg return; 278925944Sjoerg } 279025944Sjoerg if (myaddr == 0L) { 279125944Sjoerg /* 279225944Sjoerg * I don't have an assigned address, so i need to 279325944Sjoerg * negotiate my address. 279425944Sjoerg */ 279525944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 279625944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 279742104Sphk } else 279842104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 279988534Sjoerg if (sp->enable_vj) { 280088534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 280188534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 280288534Sjoerg sp->ipcp.compress_cid = 1; 280388534Sjoerg } 280425944Sjoerg sppp_open_event(&ipcp, sp); 280525944Sjoerg} 280625944Sjoerg 280725944Sjoergstatic void 280825944Sjoergsppp_ipcp_close(struct sppp *sp) 280925944Sjoerg{ 281025944Sjoerg sppp_close_event(&ipcp, sp); 281125944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 281225944Sjoerg /* 281325944Sjoerg * My address was dynamic, clear it again. 281425944Sjoerg */ 281525944Sjoerg sppp_set_ip_addr(sp, 0L); 281625944Sjoerg} 281725944Sjoerg 281825944Sjoergstatic void 281925944Sjoergsppp_ipcp_TO(void *cookie) 282025944Sjoerg{ 282125944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 282225944Sjoerg} 282325944Sjoerg 282425944Sjoerg/* 282525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 282625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 282725944Sjoerg * caused action scn. (The return value is used to make the state 282825944Sjoerg * transition decision in the state automaton.) 282925944Sjoerg */ 283025944Sjoergstatic int 283125944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 283225944Sjoerg{ 283325944Sjoerg u_char *buf, *r, *p; 283425944Sjoerg struct ifnet *ifp = &sp->pp_if; 283525944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 283625944Sjoerg u_long hisaddr, desiredaddr; 283742104Sphk int gotmyaddr = 0; 283888534Sjoerg int desiredcomp; 283925944Sjoerg 284025944Sjoerg len -= 4; 284125944Sjoerg origlen = len; 284225944Sjoerg /* 284325944Sjoerg * Make sure to allocate a buf that can at least hold a 284425944Sjoerg * conf-nak with an `address' option. We might need it below. 284525944Sjoerg */ 284625944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 284725944Sjoerg if (! buf) 284825944Sjoerg return (0); 284925944Sjoerg 285025944Sjoerg /* pass 1: see if we can recognize them */ 285125944Sjoerg if (debug) 285240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 285340008Sjoerg SPP_ARGS(ifp)); 285425944Sjoerg p = (void*) (h+1); 285525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 285625944Sjoerg if (debug) 285769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 285825944Sjoerg switch (*p) { 285988534Sjoerg case IPCP_OPT_COMPRESSION: 286088534Sjoerg if (!sp->enable_vj) { 286188534Sjoerg /* VJ compression administratively disabled */ 286288534Sjoerg if (debug) 286388534Sjoerg log(-1, "[locally disabled] "); 286488534Sjoerg break; 286588534Sjoerg } 286688534Sjoerg /* 286788534Sjoerg * In theory, we should only conf-rej an 286888534Sjoerg * option that is shorter than RFC 1618 286988534Sjoerg * requires (i.e. < 4), and should conf-nak 287088534Sjoerg * anything else that is not VJ. However, 287188534Sjoerg * since our algorithm always uses the 287288534Sjoerg * original option to NAK it with new values, 287388534Sjoerg * things would become more complicated. In 287488534Sjoerg * pratice, the only commonly implemented IP 287588534Sjoerg * compression option is VJ anyway, so the 287688534Sjoerg * difference is negligible. 287788534Sjoerg */ 287888534Sjoerg if (len >= 6 && p[1] == 6) { 287988534Sjoerg /* 288088534Sjoerg * correctly formed compression option 288188534Sjoerg * that could be VJ compression 288288534Sjoerg */ 288388534Sjoerg continue; 288488534Sjoerg } 288588534Sjoerg if (debug) 288688534Sjoerg log(-1, 288788534Sjoerg "optlen %d [invalid/unsupported] ", 288888534Sjoerg p[1]); 288988534Sjoerg break; 289025944Sjoerg case IPCP_OPT_ADDRESS: 289125944Sjoerg if (len >= 6 && p[1] == 6) { 289225944Sjoerg /* correctly formed address option */ 289325944Sjoerg continue; 289425944Sjoerg } 289525706Sjoerg if (debug) 289669211Sphk log(-1, "[invalid] "); 289711189Sjkh break; 289825944Sjoerg default: 289925944Sjoerg /* Others not supported. */ 290025944Sjoerg if (debug) 290169211Sphk log(-1, "[rej] "); 29024910Swollman break; 29034910Swollman } 290425944Sjoerg /* Add the option to rejected list. */ 290525944Sjoerg bcopy (p, r, p[1]); 290625944Sjoerg r += p[1]; 290725944Sjoerg rlen += p[1]; 290825944Sjoerg } 290925944Sjoerg if (rlen) { 291025944Sjoerg if (debug) 291169211Sphk log(-1, " send conf-rej\n"); 291225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 291325944Sjoerg return 0; 291425944Sjoerg } else if (debug) 291569211Sphk log(-1, "\n"); 291625944Sjoerg 291725944Sjoerg /* pass 2: parse option values */ 291830300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 291925944Sjoerg if (debug) 292040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 292140008Sjoerg SPP_ARGS(ifp)); 292225944Sjoerg p = (void*) (h+1); 292325944Sjoerg len = origlen; 292425944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 292525944Sjoerg if (debug) 292669211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 292725944Sjoerg switch (*p) { 292888534Sjoerg case IPCP_OPT_COMPRESSION: 292988534Sjoerg desiredcomp = p[2] << 8 | p[3]; 293088534Sjoerg /* We only support VJ */ 293188534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 293288534Sjoerg if (debug) 293388534Sjoerg log(-1, "VJ [ack] "); 293488534Sjoerg sp->ipcp.flags |= IPCP_VJ; 293588599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 293688534Sjoerg sp->ipcp.max_state = p[4]; 293788534Sjoerg sp->ipcp.compress_cid = p[5]; 293888534Sjoerg continue; 293988534Sjoerg } 294088534Sjoerg if (debug) 294188534Sjoerg log(-1, 294288534Sjoerg "compproto %#04x [not supported] ", 294388534Sjoerg desiredcomp); 294488534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 294588534Sjoerg p[3] = IPCP_COMP_VJ; 294688534Sjoerg p[4] = sp->ipcp.max_state; 294788534Sjoerg p[5] = sp->ipcp.compress_cid; 294888534Sjoerg break; 294925944Sjoerg case IPCP_OPT_ADDRESS: 295042104Sphk /* This is the address he wants in his end */ 295125944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 295225944Sjoerg p[4] << 8 | p[5]; 295333928Sphk if (desiredaddr == hisaddr || 295442104Sphk (hisaddr == 1 && desiredaddr != 0)) { 295525944Sjoerg /* 295625944Sjoerg * Peer's address is same as our value, 295770199Sjhay * or we have set it to 0.0.0.1 to 295833928Sphk * indicate that we do not really care, 295925944Sjoerg * this is agreeable. Gonna conf-ack 296025944Sjoerg * it. 296125944Sjoerg */ 296225944Sjoerg if (debug) 296369211Sphk log(-1, "%s [ack] ", 296442104Sphk sppp_dotted_quad(hisaddr)); 296525944Sjoerg /* record that we've seen it already */ 296625944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 296725944Sjoerg continue; 296825944Sjoerg } 296925944Sjoerg /* 297025944Sjoerg * The address wasn't agreeable. This is either 297125944Sjoerg * he sent us 0.0.0.0, asking to assign him an 297225944Sjoerg * address, or he send us another address not 297325944Sjoerg * matching our value. Either case, we gonna 297425944Sjoerg * conf-nak it with our value. 297542104Sphk * XXX: we should "rej" if hisaddr == 0 297625944Sjoerg */ 297725944Sjoerg if (debug) { 297825944Sjoerg if (desiredaddr == 0) 297969211Sphk log(-1, "[addr requested] "); 298025944Sjoerg else 298169211Sphk log(-1, "%s [not agreed] ", 298242104Sphk sppp_dotted_quad(desiredaddr)); 298325944Sjoerg 298425944Sjoerg } 298544235Sphk p[2] = hisaddr >> 24; 298644235Sphk p[3] = hisaddr >> 16; 298744235Sphk p[4] = hisaddr >> 8; 298844235Sphk p[5] = hisaddr; 298911189Sjkh break; 299025706Sjoerg } 299125944Sjoerg /* Add the option to nak'ed list. */ 299225944Sjoerg bcopy (p, r, p[1]); 299325944Sjoerg r += p[1]; 299425944Sjoerg rlen += p[1]; 299525944Sjoerg } 299625944Sjoerg 299725944Sjoerg /* 299825944Sjoerg * If we are about to conf-ack the request, but haven't seen 299925944Sjoerg * his address so far, gonna conf-nak it instead, with the 300025944Sjoerg * `address' option present and our idea of his address being 300125944Sjoerg * filled in there, to request negotiation of both addresses. 300225944Sjoerg * 300325944Sjoerg * XXX This can result in an endless req - nak loop if peer 300425944Sjoerg * doesn't want to send us his address. Q: What should we do 300525944Sjoerg * about it? XXX A: implement the max-failure counter. 300625944Sjoerg */ 300742104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 300825944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 300925944Sjoerg buf[1] = 6; 301025944Sjoerg buf[2] = hisaddr >> 24; 301125944Sjoerg buf[3] = hisaddr >> 16; 301225944Sjoerg buf[4] = hisaddr >> 8; 301325944Sjoerg buf[5] = hisaddr; 301425944Sjoerg rlen = 6; 301525706Sjoerg if (debug) 301669211Sphk log(-1, "still need hisaddr "); 301725944Sjoerg } 301825944Sjoerg 301925944Sjoerg if (rlen) { 302025706Sjoerg if (debug) 302169211Sphk log(-1, " send conf-nak\n"); 302225944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 302325944Sjoerg } else { 302425706Sjoerg if (debug) 302569211Sphk log(-1, " send conf-ack\n"); 302625944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 302725944Sjoerg h->ident, origlen, h+1); 302825944Sjoerg } 302925944Sjoerg 303025944Sjoerg free (buf, M_TEMP); 303125944Sjoerg return (rlen == 0); 303225944Sjoerg} 303325944Sjoerg 303425944Sjoerg/* 303525944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 303625944Sjoerg * negotiation. 303725944Sjoerg */ 303825944Sjoergstatic void 303925944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 304025944Sjoerg{ 304125944Sjoerg u_char *buf, *p; 304225944Sjoerg struct ifnet *ifp = &sp->pp_if; 304325944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 304425944Sjoerg 304525944Sjoerg len -= 4; 304625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 304725944Sjoerg if (!buf) 304825944Sjoerg return; 304925944Sjoerg 305025944Sjoerg if (debug) 305140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 305240008Sjoerg SPP_ARGS(ifp)); 305325944Sjoerg 305425944Sjoerg p = (void*) (h+1); 305525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 305625706Sjoerg if (debug) 305769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 305825944Sjoerg switch (*p) { 305988534Sjoerg case IPCP_OPT_COMPRESSION: 306088534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 306188534Sjoerg break; 306225944Sjoerg case IPCP_OPT_ADDRESS: 306325944Sjoerg /* 306425944Sjoerg * Peer doesn't grok address option. This is 306525944Sjoerg * bad. XXX Should we better give up here? 306642104Sphk * XXX We could try old "addresses" option... 306725944Sjoerg */ 306825944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 306925944Sjoerg break; 307025944Sjoerg } 30714910Swollman } 307225944Sjoerg if (debug) 307369211Sphk log(-1, "\n"); 307425944Sjoerg free (buf, M_TEMP); 307525944Sjoerg return; 30764910Swollman} 30774910Swollman 307825944Sjoerg/* 307925944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 308025944Sjoerg * negotiation. 308125944Sjoerg */ 308212820Sphkstatic void 308325944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 30844910Swollman{ 308525944Sjoerg u_char *buf, *p; 308625944Sjoerg struct ifnet *ifp = &sp->pp_if; 308725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 308888534Sjoerg int desiredcomp; 308925944Sjoerg u_long wantaddr; 30904910Swollman 309125944Sjoerg len -= 4; 309225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 309325944Sjoerg if (!buf) 309425944Sjoerg return; 309525944Sjoerg 309625944Sjoerg if (debug) 309740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 309840008Sjoerg SPP_ARGS(ifp)); 309925944Sjoerg 310025944Sjoerg p = (void*) (h+1); 310125944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 310225944Sjoerg if (debug) 310369211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 310425944Sjoerg switch (*p) { 310588534Sjoerg case IPCP_OPT_COMPRESSION: 310688534Sjoerg if (len >= 6 && p[1] == 6) { 310788534Sjoerg desiredcomp = p[2] << 8 | p[3]; 310888534Sjoerg if (debug) 310988534Sjoerg log(-1, "[wantcomp %#04x] ", 311088534Sjoerg desiredcomp); 311188534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 311288599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 311388534Sjoerg sp->ipcp.max_state = p[4]; 311488534Sjoerg sp->ipcp.compress_cid = p[5]; 311588534Sjoerg if (debug) 311688534Sjoerg log(-1, "[agree] "); 311788534Sjoerg } else 311888534Sjoerg sp->ipcp.opts &= 311988534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 312088534Sjoerg } 312188534Sjoerg break; 312225944Sjoerg case IPCP_OPT_ADDRESS: 312325944Sjoerg /* 312425944Sjoerg * Peer doesn't like our local IP address. See 312525944Sjoerg * if we can do something for him. We'll drop 312625944Sjoerg * him our address then. 312725944Sjoerg */ 312825944Sjoerg if (len >= 6 && p[1] == 6) { 312925944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 313025944Sjoerg p[4] << 8 | p[5]; 313125944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 313225944Sjoerg if (debug) 313369211Sphk log(-1, "[wantaddr %s] ", 313430300Sjoerg sppp_dotted_quad(wantaddr)); 313525944Sjoerg /* 313625944Sjoerg * When doing dynamic address assignment, 313725944Sjoerg * we accept his offer. Otherwise, we 313825944Sjoerg * ignore it and thus continue to negotiate 313925944Sjoerg * our already existing value. 314042104Sphk * XXX: Bogus, if he said no once, he'll 314142104Sphk * just say no again, might as well die. 314225944Sjoerg */ 314325944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 314425944Sjoerg sppp_set_ip_addr(sp, wantaddr); 314525944Sjoerg if (debug) 314669211Sphk log(-1, "[agree] "); 314742104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 314825944Sjoerg } 314925944Sjoerg } 315025944Sjoerg break; 315125944Sjoerg } 315225944Sjoerg } 315325944Sjoerg if (debug) 315469211Sphk log(-1, "\n"); 315525944Sjoerg free (buf, M_TEMP); 315625944Sjoerg return; 31574910Swollman} 31584910Swollman 315912820Sphkstatic void 316025944Sjoergsppp_ipcp_tlu(struct sppp *sp) 31614910Swollman{ 316242104Sphk /* we are up - notify isdn daemon */ 316342104Sphk if (sp->pp_con) 316442104Sphk sp->pp_con(sp); 31654910Swollman} 31664910Swollman 316725944Sjoergstatic void 316825944Sjoergsppp_ipcp_tld(struct sppp *sp) 316925944Sjoerg{ 317025944Sjoerg} 317125944Sjoerg 317225944Sjoergstatic void 317325944Sjoergsppp_ipcp_tls(struct sppp *sp) 317425944Sjoerg{ 317525944Sjoerg /* indicate to LCP that it must stay alive */ 317625944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 317725944Sjoerg} 317825944Sjoerg 317925944Sjoergstatic void 318025944Sjoergsppp_ipcp_tlf(struct sppp *sp) 318125944Sjoerg{ 318225944Sjoerg /* we no longer need LCP */ 318325944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 318430300Sjoerg sppp_lcp_check_and_close(sp); 318525944Sjoerg} 318625944Sjoerg 318725944Sjoergstatic void 318825944Sjoergsppp_ipcp_scr(struct sppp *sp) 318925944Sjoerg{ 319025944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 319125944Sjoerg u_long ouraddr; 319225944Sjoerg int i = 0; 319325944Sjoerg 319488534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 319588534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 319688534Sjoerg opt[i++] = 6; 319788534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 319888534Sjoerg opt[i++] = IPCP_COMP_VJ; 319988534Sjoerg opt[i++] = sp->ipcp.max_state; 320088534Sjoerg opt[i++] = sp->ipcp.compress_cid; 320188534Sjoerg } 320225944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 320330300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 320425944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 320525944Sjoerg opt[i++] = 6; 320625944Sjoerg opt[i++] = ouraddr >> 24; 320725944Sjoerg opt[i++] = ouraddr >> 16; 320825944Sjoerg opt[i++] = ouraddr >> 8; 320925944Sjoerg opt[i++] = ouraddr; 321025944Sjoerg } 321125944Sjoerg 321278064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 321325944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 321425944Sjoerg} 321525944Sjoerg 321670199Sjhay/* 321730300Sjoerg *--------------------------------------------------------------------------* 321830300Sjoerg * * 321978064Sume * The IPv6CP implementation. * 322078064Sume * * 322178064Sume *--------------------------------------------------------------------------* 322278064Sume */ 322378064Sume 322478064Sume#ifdef INET6 322578064Sumestatic void 322678064Sumesppp_ipv6cp_init(struct sppp *sp) 322778064Sume{ 322878064Sume sp->ipv6cp.opts = 0; 322978064Sume sp->ipv6cp.flags = 0; 323078064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 323178064Sume sp->fail_counter[IDX_IPV6CP] = 0; 323278064Sume sp->pp_seq[IDX_IPV6CP] = 0; 323378064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 323478064Sume#if defined(__NetBSD__) 323578064Sume callout_init(&sp->ch[IDX_IPV6CP]); 323678064Sume#endif 323778064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 323878064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 323978064Sume#endif 324078064Sume} 324178064Sume 324278064Sumestatic void 324378064Sumesppp_ipv6cp_up(struct sppp *sp) 324478064Sume{ 324578064Sume sppp_up_event(&ipv6cp, sp); 324678064Sume} 324778064Sume 324878064Sumestatic void 324978064Sumesppp_ipv6cp_down(struct sppp *sp) 325078064Sume{ 325178064Sume sppp_down_event(&ipv6cp, sp); 325278064Sume} 325378064Sume 325478064Sumestatic void 325578064Sumesppp_ipv6cp_open(struct sppp *sp) 325678064Sume{ 325778064Sume STDDCL; 325878064Sume struct in6_addr myaddr, hisaddr; 325978064Sume 326078064Sume#ifdef IPV6CP_MYIFID_DYN 326178064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 326278064Sume#else 326378064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 326478064Sume#endif 326578064Sume 326678064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 326778064Sume /* 326878064Sume * If we don't have our address, this probably means our 326978064Sume * interface doesn't want to talk IPv6 at all. (This could 327078064Sume * be the case if somebody wants to speak only IPX, for 327178064Sume * example.) Don't open IPv6CP in this case. 327278064Sume */ 327378064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 327478064Sume /* XXX this message should go away */ 327578064Sume if (debug) 327678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 327778064Sume SPP_ARGS(ifp)); 327878064Sume return; 327978064Sume } 328078064Sume 328178064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 328278064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 328378064Sume sppp_open_event(&ipv6cp, sp); 328478064Sume} 328578064Sume 328678064Sumestatic void 328778064Sumesppp_ipv6cp_close(struct sppp *sp) 328878064Sume{ 328978064Sume sppp_close_event(&ipv6cp, sp); 329078064Sume} 329178064Sume 329278064Sumestatic void 329378064Sumesppp_ipv6cp_TO(void *cookie) 329478064Sume{ 329578064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 329678064Sume} 329778064Sume 329878064Sume/* 329978064Sume * Analyze a configure request. Return true if it was agreeable, and 330078064Sume * caused action sca, false if it has been rejected or nak'ed, and 330178064Sume * caused action scn. (The return value is used to make the state 330278064Sume * transition decision in the state automaton.) 330378064Sume */ 330478064Sumestatic int 330578064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 330678064Sume{ 330778064Sume u_char *buf, *r, *p; 330878064Sume struct ifnet *ifp = &sp->pp_if; 330978064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 331078064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 331178064Sume int ifidcount; 331278064Sume int type; 331378064Sume int collision, nohisaddr; 331478064Sume 331578064Sume len -= 4; 331678064Sume origlen = len; 331778064Sume /* 331878064Sume * Make sure to allocate a buf that can at least hold a 331978064Sume * conf-nak with an `address' option. We might need it below. 332078064Sume */ 332178064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 332278064Sume if (! buf) 332378064Sume return (0); 332478064Sume 332578064Sume /* pass 1: see if we can recognize them */ 332678064Sume if (debug) 332778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 332878064Sume SPP_ARGS(ifp)); 332978064Sume p = (void*) (h+1); 333078064Sume ifidcount = 0; 333178064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 333278064Sume if (debug) 333378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 333478064Sume switch (*p) { 333578064Sume case IPV6CP_OPT_IFID: 333678064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 333778064Sume /* correctly formed address option */ 333878064Sume ifidcount++; 333978064Sume continue; 334078064Sume } 334178064Sume if (debug) 334278176Sume log(-1, " [invalid]"); 334378064Sume break; 334478064Sume#ifdef notyet 334578064Sume case IPV6CP_OPT_COMPRESSION: 334678064Sume if (len >= 4 && p[1] >= 4) { 334778064Sume /* correctly formed compress option */ 334878064Sume continue; 334978064Sume } 335078064Sume if (debug) 335178176Sume log(-1, " [invalid]"); 335278064Sume break; 335378064Sume#endif 335478064Sume default: 335578064Sume /* Others not supported. */ 335678064Sume if (debug) 335778176Sume log(-1, " [rej]"); 335878064Sume break; 335978064Sume } 336078064Sume /* Add the option to rejected list. */ 336178064Sume bcopy (p, r, p[1]); 336278064Sume r += p[1]; 336378064Sume rlen += p[1]; 336478064Sume } 336578064Sume if (rlen) { 336678064Sume if (debug) 336778176Sume log(-1, " send conf-rej\n"); 336878064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 336978064Sume goto end; 337078064Sume } else if (debug) 337178176Sume log(-1, "\n"); 337278064Sume 337378064Sume /* pass 2: parse option values */ 337478064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 337578064Sume if (debug) 337678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 337778064Sume SPP_ARGS(ifp)); 337878064Sume p = (void*) (h+1); 337978064Sume len = origlen; 338078064Sume type = CONF_ACK; 338178064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 338278064Sume if (debug) 338378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 338478064Sume switch (*p) { 338578064Sume#ifdef notyet 338678064Sume case IPV6CP_OPT_COMPRESSION: 338778064Sume continue; 338878064Sume#endif 338978064Sume case IPV6CP_OPT_IFID: 339078064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 339178064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 339278064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 339378064Sume &myaddr.s6_addr[8], 8) == 0); 339478064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 339578064Sume 339678064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 339778064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 339878064Sume 339978064Sume if (!collision && !nohisaddr) { 340078064Sume /* no collision, hisaddr known - Conf-Ack */ 340178064Sume type = CONF_ACK; 340278064Sume 340378064Sume if (debug) { 340478176Sume log(-1, " %s [%s]", 340578064Sume ip6_sprintf(&desiredaddr), 340678064Sume sppp_cp_type_name(type)); 340778064Sume } 340878064Sume continue; 340978064Sume } 341078064Sume 341178064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 341278064Sume if (collision && nohisaddr) { 341378064Sume /* collision, hisaddr unknown - Conf-Rej */ 341478064Sume type = CONF_REJ; 341578064Sume bzero(&p[2], 8); 341678064Sume } else { 341778064Sume /* 341878064Sume * - no collision, hisaddr unknown, or 341978064Sume * - collision, hisaddr known 342078064Sume * Conf-Nak, suggest hisaddr 342178064Sume */ 342278064Sume type = CONF_NAK; 342378064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 342478064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 342578064Sume } 342678064Sume if (debug) 342778176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 342878064Sume sppp_cp_type_name(type)); 342978064Sume break; 343078064Sume } 343178064Sume /* Add the option to nak'ed list. */ 343278064Sume bcopy (p, r, p[1]); 343378064Sume r += p[1]; 343478064Sume rlen += p[1]; 343578064Sume } 343678064Sume 343778064Sume if (rlen == 0 && type == CONF_ACK) { 343878064Sume if (debug) 343978176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 344078064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 344178064Sume } else { 344278064Sume#ifdef DIAGNOSTIC 344378064Sume if (type == CONF_ACK) 344478064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 344578064Sume#endif 344678064Sume 344778064Sume if (debug) { 344878176Sume log(-1, " send %s suggest %s\n", 344978064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 345078064Sume } 345178064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 345278064Sume } 345378064Sume 345478064Sume end: 345578064Sume free (buf, M_TEMP); 345678064Sume return (rlen == 0); 345778064Sume} 345878064Sume 345978064Sume/* 346078064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 346178064Sume * negotiation. 346278064Sume */ 346378064Sumestatic void 346478064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 346578064Sume{ 346678064Sume u_char *buf, *p; 346778064Sume struct ifnet *ifp = &sp->pp_if; 346878064Sume int debug = ifp->if_flags & IFF_DEBUG; 346978064Sume 347078064Sume len -= 4; 347178064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 347278064Sume if (!buf) 347378064Sume return; 347478064Sume 347578064Sume if (debug) 347678064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 347778064Sume SPP_ARGS(ifp)); 347878064Sume 347978064Sume p = (void*) (h+1); 348078064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 348178064Sume if (debug) 348278176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 348378064Sume switch (*p) { 348478064Sume case IPV6CP_OPT_IFID: 348578064Sume /* 348678064Sume * Peer doesn't grok address option. This is 348778064Sume * bad. XXX Should we better give up here? 348878064Sume */ 348978064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 349078064Sume break; 349178064Sume#ifdef notyet 349278064Sume case IPV6CP_OPT_COMPRESS: 349378064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 349478064Sume break; 349578064Sume#endif 349678064Sume } 349778064Sume } 349878064Sume if (debug) 349978176Sume log(-1, "\n"); 350078064Sume free (buf, M_TEMP); 350178064Sume return; 350278064Sume} 350378064Sume 350478064Sume/* 350578064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 350678064Sume * negotiation. 350778064Sume */ 350878064Sumestatic void 350978064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 351078064Sume{ 351178064Sume u_char *buf, *p; 351278064Sume struct ifnet *ifp = &sp->pp_if; 351378064Sume int debug = ifp->if_flags & IFF_DEBUG; 351478064Sume struct in6_addr suggestaddr; 351578064Sume 351678064Sume len -= 4; 351778064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 351878064Sume if (!buf) 351978064Sume return; 352078064Sume 352178064Sume if (debug) 352278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 352378064Sume SPP_ARGS(ifp)); 352478064Sume 352578064Sume p = (void*) (h+1); 352678064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 352778064Sume if (debug) 352878176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 352978064Sume switch (*p) { 353078064Sume case IPV6CP_OPT_IFID: 353178064Sume /* 353278064Sume * Peer doesn't like our local ifid. See 353378064Sume * if we can do something for him. We'll drop 353478064Sume * him our address then. 353578064Sume */ 353678064Sume if (len < 10 || p[1] != 10) 353778064Sume break; 353878064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 353978064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 354078064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 354178064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 354278064Sume 354378064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 354478064Sume if (debug) 354578176Sume log(-1, " [suggestaddr %s]", 354678064Sume ip6_sprintf(&suggestaddr)); 354778064Sume#ifdef IPV6CP_MYIFID_DYN 354878064Sume /* 354978064Sume * When doing dynamic address assignment, 355078064Sume * we accept his offer. 355178064Sume */ 355278064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 355378064Sume struct in6_addr lastsuggest; 355478064Sume /* 355578064Sume * If <suggested myaddr from peer> equals to 355678064Sume * <hisaddr we have suggested last time>, 355778064Sume * we have a collision. generate new random 355878064Sume * ifid. 355978064Sume */ 356078064Sume sppp_suggest_ip6_addr(&lastsuggest); 356178064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 356278064Sume lastsuggest)) { 356378064Sume if (debug) 356478176Sume log(-1, " [random]"); 356578064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 356678064Sume } 356778064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 356878064Sume if (debug) 356978176Sume log(-1, " [agree]"); 357078064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 357178064Sume } 357278064Sume#else 357378064Sume /* 357478064Sume * Since we do not do dynamic address assignment, 357578064Sume * we ignore it and thus continue to negotiate 357678064Sume * our already existing value. This can possibly 357778064Sume * go into infinite request-reject loop. 357878064Sume * 357978064Sume * This is not likely because we normally use 358078064Sume * ifid based on MAC-address. 358178064Sume * If you have no ethernet card on the node, too bad. 358278064Sume * XXX should we use fail_counter? 358378064Sume */ 358478064Sume#endif 358578064Sume break; 358678064Sume#ifdef notyet 358778064Sume case IPV6CP_OPT_COMPRESS: 358878064Sume /* 358978064Sume * Peer wants different compression parameters. 359078064Sume */ 359178064Sume break; 359278064Sume#endif 359378064Sume } 359478064Sume } 359578064Sume if (debug) 359678176Sume log(-1, "\n"); 359778064Sume free (buf, M_TEMP); 359878064Sume return; 359978064Sume} 360078064Sumestatic void 360178064Sumesppp_ipv6cp_tlu(struct sppp *sp) 360278064Sume{ 360378064Sume /* we are up - notify isdn daemon */ 360478064Sume if (sp->pp_con) 360578064Sume sp->pp_con(sp); 360678064Sume} 360778064Sume 360878064Sumestatic void 360978064Sumesppp_ipv6cp_tld(struct sppp *sp) 361078064Sume{ 361178064Sume} 361278064Sume 361378064Sumestatic void 361478064Sumesppp_ipv6cp_tls(struct sppp *sp) 361578064Sume{ 361678064Sume /* indicate to LCP that it must stay alive */ 361778064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 361878064Sume} 361978064Sume 362078064Sumestatic void 362178064Sumesppp_ipv6cp_tlf(struct sppp *sp) 362278064Sume{ 362378064Sume 362478064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 362578064Sume /* we no longer need LCP */ 362678064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 362778064Sume sppp_lcp_check_and_close(sp); 362878064Sume#endif 362978064Sume} 363078064Sume 363178064Sumestatic void 363278064Sumesppp_ipv6cp_scr(struct sppp *sp) 363378064Sume{ 363478064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 363578064Sume struct in6_addr ouraddr; 363678064Sume int i = 0; 363778064Sume 363878064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 363978064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 364078064Sume opt[i++] = IPV6CP_OPT_IFID; 364178064Sume opt[i++] = 10; 364278064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 364378064Sume i += 8; 364478064Sume } 364578064Sume 364678064Sume#ifdef notyet 364778064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 364878064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 364978064Sume opt[i++] = 4; 365078064Sume opt[i++] = 0; /* TBD */ 365178064Sume opt[i++] = 0; /* TBD */ 365278064Sume /* variable length data may follow */ 365378064Sume } 365478064Sume#endif 365578064Sume 365678064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 365778064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 365878064Sume} 365978064Sume#else /*INET6*/ 366078064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 366178064Sume{ 366278064Sume} 366378064Sume 366478064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 366578064Sume{ 366678064Sume} 366778064Sume 366878064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 366978064Sume{ 367078064Sume} 367178064Sume 367278064Sume 367378064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 367478064Sume{ 367578064Sume} 367678064Sume 367778064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 367878064Sume{ 367978064Sume} 368078064Sume 368178064Sumestatic void sppp_ipv6cp_TO(void *sp) 368278064Sume{ 368378064Sume} 368478064Sume 368578064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 368678064Sume{ 368778064Sume return 0; 368878064Sume} 368978064Sume 369078064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 369178064Sume{ 369278064Sume} 369378064Sume 369478064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 369578064Sume{ 369678064Sume} 369778064Sume 369878064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 369978064Sume{ 370078064Sume} 370178064Sume 370278064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 370378064Sume{ 370478064Sume} 370578064Sume 370678064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 370778064Sume{ 370878064Sume} 370978064Sume 371078064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 371178064Sume{ 371278064Sume} 371378064Sume 371478064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 371578064Sume{ 371678064Sume} 371778064Sume#endif /*INET6*/ 371878064Sume 371978064Sume/* 372078064Sume *--------------------------------------------------------------------------* 372178064Sume * * 372230300Sjoerg * The CHAP implementation. * 372330300Sjoerg * * 372430300Sjoerg *--------------------------------------------------------------------------* 372530300Sjoerg */ 372630300Sjoerg 372730300Sjoerg/* 372830300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 372930300Sjoerg * the control protocols do, since they do have Open and Close events, but 373030300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 373130300Sjoerg * authentication protocols may be different in both directions (this makes 373230300Sjoerg * sense, think of a machine that never accepts incoming calls but only 373330300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 373430300Sjoerg * 373530300Sjoerg * Our state machine for the local authentication protocol (we are requesting 373630300Sjoerg * the peer to authenticate) looks like: 373730300Sjoerg * 373830300Sjoerg * RCA- 373930300Sjoerg * +--------------------------------------------+ 374030300Sjoerg * V scn,tld| 374130300Sjoerg * +--------+ Close +---------+ RCA+ 374230300Sjoerg * | |<----------------------------------| |------+ 374330300Sjoerg * +--->| Closed | TO* | Opened | sca | 374430300Sjoerg * | | |-----+ +-------| |<-----+ 374530300Sjoerg * | +--------+ irc | | +---------+ 374630300Sjoerg * | ^ | | ^ 374730300Sjoerg * | | | | | 374830300Sjoerg * | | | | | 374930300Sjoerg * | TO-| | | | 375030300Sjoerg * | |tld TO+ V | | 375130300Sjoerg * | | +------->+ | | 375230300Sjoerg * | | | | | | 375330300Sjoerg * | +--------+ V | | 375430300Sjoerg * | | |<----+<--------------------+ | 375530300Sjoerg * | | Req- | scr | 375630300Sjoerg * | | Sent | | 375730300Sjoerg * | | | | 375830300Sjoerg * | +--------+ | 375930300Sjoerg * | RCA- | | RCA+ | 376030300Sjoerg * +------+ +------------------------------------------+ 376130300Sjoerg * scn,tld sca,irc,ict,tlu 376230300Sjoerg * 376330300Sjoerg * 376430300Sjoerg * with: 376530300Sjoerg * 376630300Sjoerg * Open: LCP reached authentication phase 376730300Sjoerg * Close: LCP reached terminate phase 376830300Sjoerg * 376930300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 377030300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 377130300Sjoerg * TO+: timeout with restart counter >= 0 377230300Sjoerg * TO-: timeout with restart counter < 0 377330300Sjoerg * TO*: reschedule timeout for CHAP 377430300Sjoerg * 377530300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 377630300Sjoerg * sca: send ack packet (pap-ack, chap-success) 377730300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 377830300Sjoerg * ict: initialize re-challenge timer (CHAP only) 377930300Sjoerg * 378030300Sjoerg * tlu: this-layer-up, LCP reaches network phase 378130300Sjoerg * tld: this-layer-down, LCP enters terminate phase 378230300Sjoerg * 378330300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 378430300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 378530300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 378630300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 378730300Sjoerg * causing LCP to enter terminate phase. 378830300Sjoerg * 378930300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 379030300Sjoerg * expected to send one based on the successful negotiation of PAP as 379130300Sjoerg * the authentication protocol during the LCP option negotiation. 379230300Sjoerg * 379330300Sjoerg * Incoming authentication protocol requests (remote requests 379430300Sjoerg * authentication, we are peer) don't employ a state machine at all, 379530300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 379630300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 379730300Sjoerg * still in authentication phase (thereby violating the standard that 379830300Sjoerg * demands that these NCP packets are to be discarded), so we keep 379930300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 380030300Sjoerg * phase network once we've seen a positive acknowledge for the 380130300Sjoerg * authentication. 380230300Sjoerg */ 380330300Sjoerg 380430300Sjoerg/* 380530300Sjoerg * Handle incoming CHAP packets. 380630300Sjoerg */ 380730300Sjoergvoid 380830300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 380930300Sjoerg{ 381030300Sjoerg STDDCL; 381130300Sjoerg struct lcp_header *h; 381230300Sjoerg int len, x; 381330300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 381430300Sjoerg int value_len, name_len; 381530300Sjoerg MD5_CTX ctx; 381630300Sjoerg 381730300Sjoerg len = m->m_pkthdr.len; 381830300Sjoerg if (len < 4) { 381930300Sjoerg if (debug) 382030300Sjoerg log(LOG_DEBUG, 382140008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 382240008Sjoerg SPP_ARGS(ifp), len); 382330300Sjoerg return; 382430300Sjoerg } 382530300Sjoerg h = mtod (m, struct lcp_header*); 382630300Sjoerg if (len > ntohs (h->len)) 382730300Sjoerg len = ntohs (h->len); 382830300Sjoerg 382930300Sjoerg switch (h->type) { 383030300Sjoerg /* challenge, failure and success are his authproto */ 383130300Sjoerg case CHAP_CHALLENGE: 383230300Sjoerg value = 1 + (u_char*)(h+1); 383330300Sjoerg value_len = value[-1]; 383430300Sjoerg name = value + value_len; 383530300Sjoerg name_len = len - value_len - 5; 383630300Sjoerg if (name_len < 0) { 383730300Sjoerg if (debug) { 383830300Sjoerg log(LOG_DEBUG, 383940008Sjoerg SPP_FMT "chap corrupted challenge " 384030300Sjoerg "<%s id=0x%x len=%d", 384140008Sjoerg SPP_ARGS(ifp), 384230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 384330300Sjoerg h->ident, ntohs(h->len)); 384444145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 384569211Sphk log(-1, ">\n"); 384630300Sjoerg } 384730300Sjoerg break; 384830300Sjoerg } 384970199Sjhay 385030300Sjoerg if (debug) { 385130300Sjoerg log(LOG_DEBUG, 385240008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 385340008Sjoerg SPP_ARGS(ifp), 385430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 385530300Sjoerg ntohs(h->len)); 385630300Sjoerg sppp_print_string((char*) name, name_len); 385769211Sphk log(-1, " value-size=%d value=", value_len); 385830300Sjoerg sppp_print_bytes(value, value_len); 385969211Sphk log(-1, ">\n"); 386030300Sjoerg } 386130300Sjoerg 386230300Sjoerg /* Compute reply value. */ 386330300Sjoerg MD5Init(&ctx); 386430300Sjoerg MD5Update(&ctx, &h->ident, 1); 386530300Sjoerg MD5Update(&ctx, sp->myauth.secret, 386630300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 386730300Sjoerg MD5Update(&ctx, value, value_len); 386830300Sjoerg MD5Final(digest, &ctx); 386930300Sjoerg dsize = sizeof digest; 387030300Sjoerg 387130300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 387230300Sjoerg sizeof dsize, (const char *)&dsize, 387330300Sjoerg sizeof digest, digest, 387440008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 387530300Sjoerg sp->myauth.name, 387630300Sjoerg 0); 387730300Sjoerg break; 387830300Sjoerg 387930300Sjoerg case CHAP_SUCCESS: 388030300Sjoerg if (debug) { 388140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 388240008Sjoerg SPP_ARGS(ifp)); 388330300Sjoerg if (len > 4) { 388469211Sphk log(-1, ": "); 388530300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 388630300Sjoerg } 388769211Sphk log(-1, "\n"); 388830300Sjoerg } 388930300Sjoerg x = splimp(); 389030300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 389130300Sjoerg if (sp->myauth.proto == PPP_CHAP && 389232169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 389330300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 389430300Sjoerg /* 389530300Sjoerg * We are authenticator for CHAP but didn't 389630300Sjoerg * complete yet. Leave it to tlu to proceed 389730300Sjoerg * to network phase. 389830300Sjoerg */ 389930300Sjoerg splx(x); 390030300Sjoerg break; 390130300Sjoerg } 390230300Sjoerg splx(x); 390330300Sjoerg sppp_phase_network(sp); 390430300Sjoerg break; 390530300Sjoerg 390630300Sjoerg case CHAP_FAILURE: 390730300Sjoerg if (debug) { 390840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 390940008Sjoerg SPP_ARGS(ifp)); 391030300Sjoerg if (len > 4) { 391169211Sphk log(-1, ": "); 391230300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 391330300Sjoerg } 391469211Sphk log(-1, "\n"); 391530300Sjoerg } else 391640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 391740008Sjoerg SPP_ARGS(ifp)); 391830300Sjoerg /* await LCP shutdown by authenticator */ 391930300Sjoerg break; 392030300Sjoerg 392130300Sjoerg /* response is my authproto */ 392230300Sjoerg case CHAP_RESPONSE: 392330300Sjoerg value = 1 + (u_char*)(h+1); 392430300Sjoerg value_len = value[-1]; 392530300Sjoerg name = value + value_len; 392630300Sjoerg name_len = len - value_len - 5; 392730300Sjoerg if (name_len < 0) { 392830300Sjoerg if (debug) { 392930300Sjoerg log(LOG_DEBUG, 393040008Sjoerg SPP_FMT "chap corrupted response " 393130300Sjoerg "<%s id=0x%x len=%d", 393240008Sjoerg SPP_ARGS(ifp), 393330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 393430300Sjoerg h->ident, ntohs(h->len)); 393544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 393669211Sphk log(-1, ">\n"); 393730300Sjoerg } 393830300Sjoerg break; 393930300Sjoerg } 394030300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 394130300Sjoerg if (debug) 394230300Sjoerg log(LOG_DEBUG, 394340008Sjoerg SPP_FMT "chap dropping response for old ID " 394430300Sjoerg "(got %d, expected %d)\n", 394540008Sjoerg SPP_ARGS(ifp), 394630300Sjoerg h->ident, sp->confid[IDX_CHAP]); 394730300Sjoerg break; 394830300Sjoerg } 394930300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 395030300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 395140008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 395240008Sjoerg SPP_ARGS(ifp)); 395330300Sjoerg sppp_print_string(name, name_len); 395469211Sphk log(-1, " != expected "); 395530300Sjoerg sppp_print_string(sp->hisauth.name, 395630300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 395769211Sphk log(-1, "\n"); 395870199Sjhay } 395930300Sjoerg if (debug) { 396040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 396130300Sjoerg "<%s id=0x%x len=%d name=", 396240008Sjoerg SPP_ARGS(ifp), 396330300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 396430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 396530300Sjoerg h->ident, ntohs (h->len)); 396630300Sjoerg sppp_print_string((char*)name, name_len); 396769211Sphk log(-1, " value-size=%d value=", value_len); 396830300Sjoerg sppp_print_bytes(value, value_len); 396969211Sphk log(-1, ">\n"); 397030300Sjoerg } 397130300Sjoerg if (value_len != AUTHKEYLEN) { 397230300Sjoerg if (debug) 397330300Sjoerg log(LOG_DEBUG, 397440008Sjoerg SPP_FMT "chap bad hash value length: " 397530300Sjoerg "%d bytes, should be %d\n", 397640008Sjoerg SPP_ARGS(ifp), value_len, 397730300Sjoerg AUTHKEYLEN); 397830300Sjoerg break; 397930300Sjoerg } 398030300Sjoerg 398130300Sjoerg MD5Init(&ctx); 398230300Sjoerg MD5Update(&ctx, &h->ident, 1); 398330300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 398430300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 398530300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 398630300Sjoerg MD5Final(digest, &ctx); 398730300Sjoerg 398830300Sjoerg#define FAILMSG "Failed..." 398930300Sjoerg#define SUCCMSG "Welcome!" 399030300Sjoerg 399130300Sjoerg if (value_len != sizeof digest || 399230300Sjoerg bcmp(digest, value, value_len) != 0) { 399330300Sjoerg /* action scn, tld */ 399430300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 399530300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 399630300Sjoerg 0); 399730300Sjoerg chap.tld(sp); 399830300Sjoerg break; 399930300Sjoerg } 400030300Sjoerg /* action sca, perhaps tlu */ 400130300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 400230300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 400330300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 400430300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 400530300Sjoerg 0); 400630300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 400730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 400830300Sjoerg chap.tlu(sp); 400930300Sjoerg } 401030300Sjoerg break; 401130300Sjoerg 401230300Sjoerg default: 401330300Sjoerg /* Unknown CHAP packet type -- ignore. */ 401430300Sjoerg if (debug) { 401540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 401630300Sjoerg "<0x%x id=0x%xh len=%d", 401740008Sjoerg SPP_ARGS(ifp), 401830300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 401930300Sjoerg h->type, h->ident, ntohs(h->len)); 402044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 402169211Sphk log(-1, ">\n"); 402230300Sjoerg } 402330300Sjoerg break; 402430300Sjoerg 402530300Sjoerg } 402630300Sjoerg} 402730300Sjoerg 402830300Sjoergstatic void 402930300Sjoergsppp_chap_init(struct sppp *sp) 403030300Sjoerg{ 403130300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 403230300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 403330300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 403478064Sume sp->pp_seq[IDX_CHAP] = 0; 403578064Sume sp->pp_rseq[IDX_CHAP] = 0; 403642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 403730300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 403840008Sjoerg#endif 403930300Sjoerg} 404030300Sjoerg 404130300Sjoergstatic void 404230300Sjoergsppp_chap_open(struct sppp *sp) 404330300Sjoerg{ 404430300Sjoerg if (sp->myauth.proto == PPP_CHAP && 404530300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 404630300Sjoerg /* we are authenticator for CHAP, start it */ 404730300Sjoerg chap.scr(sp); 404830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 404930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 405030300Sjoerg } 405130300Sjoerg /* nothing to be done if we are peer, await a challenge */ 405230300Sjoerg} 405330300Sjoerg 405430300Sjoergstatic void 405530300Sjoergsppp_chap_close(struct sppp *sp) 405630300Sjoerg{ 405730300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 405830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 405930300Sjoerg} 406030300Sjoerg 406130300Sjoergstatic void 406230300Sjoergsppp_chap_TO(void *cookie) 406330300Sjoerg{ 406430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 406530300Sjoerg STDDCL; 406630300Sjoerg int s; 406730300Sjoerg 406830300Sjoerg s = splimp(); 406930300Sjoerg if (debug) 407040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 407140008Sjoerg SPP_ARGS(ifp), 407230300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 407330300Sjoerg sp->rst_counter[IDX_CHAP]); 407430300Sjoerg 407530300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 407630300Sjoerg /* TO- event */ 407730300Sjoerg switch (sp->state[IDX_CHAP]) { 407830300Sjoerg case STATE_REQ_SENT: 407930300Sjoerg chap.tld(sp); 408030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 408130300Sjoerg break; 408230300Sjoerg } 408330300Sjoerg else 408430300Sjoerg /* TO+ (or TO*) event */ 408530300Sjoerg switch (sp->state[IDX_CHAP]) { 408630300Sjoerg case STATE_OPENED: 408730300Sjoerg /* TO* event */ 408830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 408930300Sjoerg /* fall through */ 409030300Sjoerg case STATE_REQ_SENT: 409130300Sjoerg chap.scr(sp); 409230300Sjoerg /* sppp_cp_change_state() will restart the timer */ 409330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 409430300Sjoerg break; 409530300Sjoerg } 409630300Sjoerg 409730300Sjoerg splx(s); 409830300Sjoerg} 409930300Sjoerg 410030300Sjoergstatic void 410130300Sjoergsppp_chap_tlu(struct sppp *sp) 410230300Sjoerg{ 410330300Sjoerg STDDCL; 410430300Sjoerg int i, x; 410530300Sjoerg 410640010Sjoerg i = 0; 410730300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 410830300Sjoerg 410930300Sjoerg /* 411030300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 411130300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 411230300Sjoerg * initial challenge-response exchange has taken place. 411330300Sjoerg * Provide for an option to avoid rechallenges. 411430300Sjoerg */ 411530300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 411630300Sjoerg /* 411730300Sjoerg * Compute the re-challenge timeout. This will yield 411830300Sjoerg * a number between 300 and 810 seconds. 411930300Sjoerg */ 412030300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 412142064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 412230300Sjoerg } 412330300Sjoerg 412430300Sjoerg if (debug) { 412530300Sjoerg log(LOG_DEBUG, 412640008Sjoerg SPP_FMT "chap %s, ", 412740008Sjoerg SPP_ARGS(ifp), 412830300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 412930300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 413069211Sphk log(-1, "next re-challenge in %d seconds\n", i); 413130300Sjoerg else 413269211Sphk log(-1, "re-challenging supressed\n"); 413330300Sjoerg } 413430300Sjoerg 413530300Sjoerg x = splimp(); 413630300Sjoerg /* indicate to LCP that we need to be closed down */ 413730300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 413830300Sjoerg 413930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 414030300Sjoerg /* 414130300Sjoerg * Remote is authenticator, but his auth proto didn't 414230300Sjoerg * complete yet. Defer the transition to network 414330300Sjoerg * phase. 414430300Sjoerg */ 414530300Sjoerg splx(x); 414630300Sjoerg return; 414730300Sjoerg } 414830300Sjoerg splx(x); 414930300Sjoerg 415030300Sjoerg /* 415130300Sjoerg * If we are already in phase network, we are done here. This 415230300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 415330300Sjoerg */ 415430300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 415530300Sjoerg sppp_phase_network(sp); 415630300Sjoerg} 415730300Sjoerg 415830300Sjoergstatic void 415930300Sjoergsppp_chap_tld(struct sppp *sp) 416030300Sjoerg{ 416130300Sjoerg STDDCL; 416230300Sjoerg 416330300Sjoerg if (debug) 416440008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 416540008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 416630300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 416730300Sjoerg 416830300Sjoerg lcp.Close(sp); 416930300Sjoerg} 417030300Sjoerg 417130300Sjoergstatic void 417230300Sjoergsppp_chap_scr(struct sppp *sp) 417330300Sjoerg{ 417430300Sjoerg u_long *ch, seed; 417530300Sjoerg u_char clen; 417630300Sjoerg 417730300Sjoerg /* Compute random challenge. */ 417830300Sjoerg ch = (u_long *)sp->myauth.challenge; 417942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 418035064Sphk read_random(&seed, sizeof seed); 418140008Sjoerg#else 418242104Sphk { 418342104Sphk struct timeval tv; 418440008Sjoerg microtime(&tv); 418540008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 418642104Sphk } 418740008Sjoerg#endif 418830300Sjoerg ch[0] = seed ^ random(); 418930300Sjoerg ch[1] = seed ^ random(); 419030300Sjoerg ch[2] = seed ^ random(); 419130300Sjoerg ch[3] = seed ^ random(); 419230300Sjoerg clen = AUTHKEYLEN; 419330300Sjoerg 419478064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 419530300Sjoerg 419630300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 419730300Sjoerg sizeof clen, (const char *)&clen, 419840008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 419940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 420030300Sjoerg sp->myauth.name, 420130300Sjoerg 0); 420230300Sjoerg} 420370199Sjhay 420470199Sjhay/* 420530300Sjoerg *--------------------------------------------------------------------------* 420630300Sjoerg * * 420730300Sjoerg * The PAP implementation. * 420830300Sjoerg * * 420930300Sjoerg *--------------------------------------------------------------------------* 421030300Sjoerg */ 421130300Sjoerg/* 421230300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 421330300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 421430300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 421530300Sjoerg * retry counter is expired). 421630300Sjoerg */ 421730300Sjoerg 421830300Sjoerg/* 421930300Sjoerg * Handle incoming PAP packets. */ 422030300Sjoergstatic void 422130300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 422230300Sjoerg{ 422330300Sjoerg STDDCL; 422430300Sjoerg struct lcp_header *h; 422530300Sjoerg int len, x; 422630300Sjoerg u_char *name, *passwd, mlen; 422730300Sjoerg int name_len, passwd_len; 422830300Sjoerg 422930300Sjoerg len = m->m_pkthdr.len; 423030300Sjoerg if (len < 5) { 423130300Sjoerg if (debug) 423230300Sjoerg log(LOG_DEBUG, 423340008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 423440008Sjoerg SPP_ARGS(ifp), len); 423530300Sjoerg return; 423630300Sjoerg } 423730300Sjoerg h = mtod (m, struct lcp_header*); 423830300Sjoerg if (len > ntohs (h->len)) 423930300Sjoerg len = ntohs (h->len); 424030300Sjoerg switch (h->type) { 424130300Sjoerg /* PAP request is my authproto */ 424230300Sjoerg case PAP_REQ: 424330300Sjoerg name = 1 + (u_char*)(h+1); 424430300Sjoerg name_len = name[-1]; 424530300Sjoerg passwd = name + name_len + 1; 424630300Sjoerg if (name_len > len - 6 || 424730300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 424830300Sjoerg if (debug) { 424940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 425030300Sjoerg "<%s id=0x%x len=%d", 425140008Sjoerg SPP_ARGS(ifp), 425230300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 425330300Sjoerg h->ident, ntohs(h->len)); 425444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 425569211Sphk log(-1, ">\n"); 425630300Sjoerg } 425730300Sjoerg break; 425830300Sjoerg } 425930300Sjoerg if (debug) { 426040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 426130300Sjoerg "<%s id=0x%x len=%d name=", 426240008Sjoerg SPP_ARGS(ifp), 426330300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 426430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 426530300Sjoerg h->ident, ntohs(h->len)); 426630300Sjoerg sppp_print_string((char*)name, name_len); 426769211Sphk log(-1, " passwd="); 426830300Sjoerg sppp_print_string((char*)passwd, passwd_len); 426969211Sphk log(-1, ">\n"); 427030300Sjoerg } 427174774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 427274774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 427330300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 427430300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 427530300Sjoerg /* action scn, tld */ 427630300Sjoerg mlen = sizeof(FAILMSG) - 1; 427730300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 427830300Sjoerg sizeof mlen, (const char *)&mlen, 427930300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 428030300Sjoerg 0); 428130300Sjoerg pap.tld(sp); 428230300Sjoerg break; 428330300Sjoerg } 428430300Sjoerg /* action sca, perhaps tlu */ 428530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 428630300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 428730300Sjoerg mlen = sizeof(SUCCMSG) - 1; 428830300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 428930300Sjoerg sizeof mlen, (const char *)&mlen, 429030300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 429130300Sjoerg 0); 429230300Sjoerg } 429330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 429430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 429530300Sjoerg pap.tlu(sp); 429630300Sjoerg } 429730300Sjoerg break; 429830300Sjoerg 429930300Sjoerg /* ack and nak are his authproto */ 430030300Sjoerg case PAP_ACK: 430140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 430230300Sjoerg if (debug) { 430340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 430440008Sjoerg SPP_ARGS(ifp)); 430530300Sjoerg name_len = *((char *)h); 430630300Sjoerg if (len > 5 && name_len) { 430769211Sphk log(-1, ": "); 430830300Sjoerg sppp_print_string((char*)(h+1), name_len); 430930300Sjoerg } 431069211Sphk log(-1, "\n"); 431130300Sjoerg } 431230300Sjoerg x = splimp(); 431330300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 431430300Sjoerg if (sp->myauth.proto == PPP_PAP && 431532169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 431630300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 431730300Sjoerg /* 431830300Sjoerg * We are authenticator for PAP but didn't 431930300Sjoerg * complete yet. Leave it to tlu to proceed 432030300Sjoerg * to network phase. 432130300Sjoerg */ 432230300Sjoerg splx(x); 432330300Sjoerg break; 432430300Sjoerg } 432530300Sjoerg splx(x); 432630300Sjoerg sppp_phase_network(sp); 432730300Sjoerg break; 432830300Sjoerg 432930300Sjoerg case PAP_NAK: 433040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 433130300Sjoerg if (debug) { 433240008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 433340008Sjoerg SPP_ARGS(ifp)); 433430300Sjoerg name_len = *((char *)h); 433530300Sjoerg if (len > 5 && name_len) { 433669211Sphk log(-1, ": "); 433730300Sjoerg sppp_print_string((char*)(h+1), name_len); 433830300Sjoerg } 433969211Sphk log(-1, "\n"); 434030300Sjoerg } else 434140008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 434240008Sjoerg SPP_ARGS(ifp)); 434330300Sjoerg /* await LCP shutdown by authenticator */ 434430300Sjoerg break; 434530300Sjoerg 434630300Sjoerg default: 434730300Sjoerg /* Unknown PAP packet type -- ignore. */ 434830300Sjoerg if (debug) { 434940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 435030300Sjoerg "<0x%x id=0x%x len=%d", 435140008Sjoerg SPP_ARGS(ifp), 435230300Sjoerg h->type, h->ident, ntohs(h->len)); 435344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 435469211Sphk log(-1, ">\n"); 435530300Sjoerg } 435630300Sjoerg break; 435730300Sjoerg 435830300Sjoerg } 435930300Sjoerg} 436030300Sjoerg 436130300Sjoergstatic void 436230300Sjoergsppp_pap_init(struct sppp *sp) 436330300Sjoerg{ 436430300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 436530300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 436630300Sjoerg sp->fail_counter[IDX_PAP] = 0; 436778064Sume sp->pp_seq[IDX_PAP] = 0; 436878064Sume sp->pp_rseq[IDX_PAP] = 0; 436942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 437030300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 437130300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 437240008Sjoerg#endif 437330300Sjoerg} 437430300Sjoerg 437530300Sjoergstatic void 437630300Sjoergsppp_pap_open(struct sppp *sp) 437730300Sjoerg{ 437830300Sjoerg if (sp->hisauth.proto == PPP_PAP && 437930300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 438030300Sjoerg /* we are authenticator for PAP, start our timer */ 438130300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 438230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 438330300Sjoerg } 438430300Sjoerg if (sp->myauth.proto == PPP_PAP) { 438530300Sjoerg /* we are peer, send a request, and start a timer */ 438630300Sjoerg pap.scr(sp); 438742064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 438842064Sphk sp->pap_my_to_ch); 438930300Sjoerg } 439030300Sjoerg} 439130300Sjoerg 439230300Sjoergstatic void 439330300Sjoergsppp_pap_close(struct sppp *sp) 439430300Sjoerg{ 439530300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 439630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 439730300Sjoerg} 439830300Sjoerg 439930300Sjoerg/* 440030300Sjoerg * That's the timeout routine if we are authenticator. Since the 440130300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 440230300Sjoerg */ 440330300Sjoergstatic void 440430300Sjoergsppp_pap_TO(void *cookie) 440530300Sjoerg{ 440630300Sjoerg struct sppp *sp = (struct sppp *)cookie; 440730300Sjoerg STDDCL; 440830300Sjoerg int s; 440930300Sjoerg 441030300Sjoerg s = splimp(); 441130300Sjoerg if (debug) 441240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 441340008Sjoerg SPP_ARGS(ifp), 441430300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 441530300Sjoerg sp->rst_counter[IDX_PAP]); 441630300Sjoerg 441730300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 441830300Sjoerg /* TO- event */ 441930300Sjoerg switch (sp->state[IDX_PAP]) { 442030300Sjoerg case STATE_REQ_SENT: 442130300Sjoerg pap.tld(sp); 442230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 442330300Sjoerg break; 442430300Sjoerg } 442530300Sjoerg else 442630300Sjoerg /* TO+ event, not very much we could do */ 442730300Sjoerg switch (sp->state[IDX_PAP]) { 442830300Sjoerg case STATE_REQ_SENT: 442930300Sjoerg /* sppp_cp_change_state() will restart the timer */ 443030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 443130300Sjoerg break; 443230300Sjoerg } 443330300Sjoerg 443430300Sjoerg splx(s); 443530300Sjoerg} 443630300Sjoerg 443730300Sjoerg/* 443830300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 443930300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 444030300Sjoerg * XXX We should impose a max counter. 444130300Sjoerg */ 444230300Sjoergstatic void 444330300Sjoergsppp_pap_my_TO(void *cookie) 444430300Sjoerg{ 444530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 444630300Sjoerg STDDCL; 444730300Sjoerg 444830300Sjoerg if (debug) 444940008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 445040008Sjoerg SPP_ARGS(ifp)); 445130300Sjoerg 445230300Sjoerg pap.scr(sp); 445330300Sjoerg} 445430300Sjoerg 445530300Sjoergstatic void 445630300Sjoergsppp_pap_tlu(struct sppp *sp) 445730300Sjoerg{ 445830300Sjoerg STDDCL; 445930300Sjoerg int x; 446030300Sjoerg 446130300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 446230300Sjoerg 446330300Sjoerg if (debug) 446440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 446540008Sjoerg SPP_ARGS(ifp), pap.name); 446630300Sjoerg 446730300Sjoerg x = splimp(); 446830300Sjoerg /* indicate to LCP that we need to be closed down */ 446930300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 447030300Sjoerg 447130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 447230300Sjoerg /* 447330300Sjoerg * Remote is authenticator, but his auth proto didn't 447430300Sjoerg * complete yet. Defer the transition to network 447530300Sjoerg * phase. 447630300Sjoerg */ 447730300Sjoerg splx(x); 447830300Sjoerg return; 447930300Sjoerg } 448030300Sjoerg splx(x); 448130300Sjoerg sppp_phase_network(sp); 448230300Sjoerg} 448330300Sjoerg 448430300Sjoergstatic void 448530300Sjoergsppp_pap_tld(struct sppp *sp) 448630300Sjoerg{ 448730300Sjoerg STDDCL; 448830300Sjoerg 448930300Sjoerg if (debug) 449040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 449140008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 449240008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 449330300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 449430300Sjoerg 449530300Sjoerg lcp.Close(sp); 449630300Sjoerg} 449730300Sjoerg 449830300Sjoergstatic void 449930300Sjoergsppp_pap_scr(struct sppp *sp) 450030300Sjoerg{ 450130300Sjoerg u_char idlen, pwdlen; 450230300Sjoerg 450378064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 450430300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 450530300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 450630300Sjoerg 450730300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 450830300Sjoerg sizeof idlen, (const char *)&idlen, 450940008Sjoerg (size_t)idlen, sp->myauth.name, 451030300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 451140008Sjoerg (size_t)pwdlen, sp->myauth.secret, 451230300Sjoerg 0); 451330300Sjoerg} 451470199Sjhay 451570199Sjhay/* 451625944Sjoerg * Random miscellaneous functions. 451725944Sjoerg */ 451825944Sjoerg 45194910Swollman/* 452030300Sjoerg * Send a PAP or CHAP proto packet. 452130300Sjoerg * 452230300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 452340008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 452430300Sjoerg * mlen == 0. 452542104Sphk * NOTE: never declare variadic functions with types subject to type 452642104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 452742104Sphk * on the architecture you are on... 452830300Sjoerg */ 452930300Sjoerg 453030300Sjoergstatic void 453142104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 453242104Sphk unsigned int type, unsigned int id, 453330300Sjoerg ...) 453430300Sjoerg{ 453530300Sjoerg STDDCL; 453630300Sjoerg struct ppp_header *h; 453730300Sjoerg struct lcp_header *lh; 453830300Sjoerg struct mbuf *m; 453930300Sjoerg u_char *p; 454030300Sjoerg int len; 454142104Sphk unsigned int mlen; 454230300Sjoerg const char *msg; 454330300Sjoerg va_list ap; 454430300Sjoerg 454530300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 454630300Sjoerg if (! m) 454730300Sjoerg return; 454830300Sjoerg m->m_pkthdr.rcvif = 0; 454930300Sjoerg 455030300Sjoerg h = mtod (m, struct ppp_header*); 455130300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 455230300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 455330300Sjoerg h->protocol = htons(cp->proto); 455430300Sjoerg 455530300Sjoerg lh = (struct lcp_header*)(h + 1); 455630300Sjoerg lh->type = type; 455730300Sjoerg lh->ident = id; 455830300Sjoerg p = (u_char*) (lh+1); 455930300Sjoerg 456030300Sjoerg va_start(ap, id); 456130300Sjoerg len = 0; 456230300Sjoerg 456342104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 456430300Sjoerg msg = va_arg(ap, const char *); 456530300Sjoerg len += mlen; 456630300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 456730300Sjoerg va_end(ap); 456830300Sjoerg m_freem(m); 456930300Sjoerg return; 457030300Sjoerg } 457130300Sjoerg 457230300Sjoerg bcopy(msg, p, mlen); 457330300Sjoerg p += mlen; 457430300Sjoerg } 457530300Sjoerg va_end(ap); 457630300Sjoerg 457730300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 457830300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 457930300Sjoerg 458030300Sjoerg if (debug) { 458140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 458240008Sjoerg SPP_ARGS(ifp), cp->name, 458330300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 458430300Sjoerg lh->ident, ntohs(lh->len)); 458544145Sphk sppp_print_bytes((u_char*) (lh+1), len); 458669211Sphk log(-1, ">\n"); 458730300Sjoerg } 458869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 458969152Sjlemon ifp->if_oerrors++; 459030300Sjoerg} 459130300Sjoerg 459230300Sjoerg/* 459325944Sjoerg * Flush interface queue. 45944910Swollman */ 459512820Sphkstatic void 459625944Sjoergsppp_qflush(struct ifqueue *ifq) 45974910Swollman{ 459825944Sjoerg struct mbuf *m, *n; 45994910Swollman 460025944Sjoerg n = ifq->ifq_head; 460125944Sjoerg while ((m = n)) { 460225944Sjoerg n = m->m_act; 460325944Sjoerg m_freem (m); 460411189Sjkh } 460525944Sjoerg ifq->ifq_head = 0; 460625944Sjoerg ifq->ifq_tail = 0; 460725944Sjoerg ifq->ifq_len = 0; 460825944Sjoerg} 460925944Sjoerg 461025944Sjoerg/* 461125944Sjoerg * Send keepalive packets, every 10 seconds. 461225944Sjoerg */ 461325944Sjoergstatic void 461425944Sjoergsppp_keepalive(void *dummy) 461525944Sjoerg{ 461625944Sjoerg struct sppp *sp; 461725944Sjoerg int s; 461825944Sjoerg 461925944Sjoerg s = splimp(); 462025944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 462125944Sjoerg struct ifnet *ifp = &sp->pp_if; 462225944Sjoerg 462325944Sjoerg /* Keepalive mode disabled or channel down? */ 462425944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 462525944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 462625944Sjoerg continue; 462725944Sjoerg 462825944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 462945152Sphk if (sp->pp_mode != IFF_CISCO && 463025944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 463125944Sjoerg continue; 463225944Sjoerg 463325944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 463425944Sjoerg /* No keepalive packets got. Stop the interface. */ 463540008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 463625944Sjoerg if_down (ifp); 463726018Sjoerg sppp_qflush (&sp->pp_cpq); 463845152Sphk if (sp->pp_mode != IFF_CISCO) { 463925944Sjoerg /* XXX */ 464025944Sjoerg /* Shut down the PPP link. */ 464125944Sjoerg lcp.Down(sp); 464225944Sjoerg /* Initiate negotiation. XXX */ 464325944Sjoerg lcp.Up(sp); 464425944Sjoerg } 46454910Swollman } 464625944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 464725944Sjoerg ++sp->pp_alivecnt; 464845152Sphk if (sp->pp_mode == IFF_CISCO) 464978064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 465078064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 465125944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 465225944Sjoerg long nmagic = htonl (sp->lcp.magic); 465378064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 465425944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 465525944Sjoerg sp->lcp.echoid, 4, &nmagic); 465625944Sjoerg } 46574910Swollman } 465825944Sjoerg splx(s); 465942064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 46604910Swollman} 46614910Swollman 466225944Sjoerg/* 466325944Sjoerg * Get both IP addresses. 466425944Sjoerg */ 466525944Sjoergstatic void 466630300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 466725944Sjoerg{ 466825944Sjoerg struct ifnet *ifp = &sp->pp_if; 466925944Sjoerg struct ifaddr *ifa; 467030300Sjoerg struct sockaddr_in *si, *sm; 467125944Sjoerg u_long ssrc, ddst; 467225944Sjoerg 467340010Sjoerg sm = NULL; 467425944Sjoerg ssrc = ddst = 0L; 467525944Sjoerg /* 467625944Sjoerg * Pick the first AF_INET address from the list, 467725944Sjoerg * aliases don't make any sense on a p2p link anyway. 467825944Sjoerg */ 467942065Sphk si = 0; 468042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 468142065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 468242104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 468371959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 468440008Sjoerg ifa; 468571959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 468642104Sphk#else 468742104Sphk for (ifa = ifp->if_addrlist; 468842104Sphk ifa; 468942104Sphk ifa = ifa->ifa_next) 469040008Sjoerg#endif 469125944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 469225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 469330300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 469425944Sjoerg if (si) 469525944Sjoerg break; 469625944Sjoerg } 469725944Sjoerg if (ifa) { 469830300Sjoerg if (si && si->sin_addr.s_addr) { 469925944Sjoerg ssrc = si->sin_addr.s_addr; 470030300Sjoerg if (srcmask) 470130300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 470230300Sjoerg } 470325944Sjoerg 470425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 470525944Sjoerg if (si && si->sin_addr.s_addr) 470625944Sjoerg ddst = si->sin_addr.s_addr; 470725944Sjoerg } 470825944Sjoerg 470925944Sjoerg if (dst) *dst = ntohl(ddst); 471025944Sjoerg if (src) *src = ntohl(ssrc); 471125944Sjoerg} 471225944Sjoerg 471325944Sjoerg/* 471425944Sjoerg * Set my IP address. Must be called at splimp. 471525944Sjoerg */ 471625944Sjoergstatic void 471725944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 471825944Sjoerg{ 471942104Sphk STDDCL; 472025944Sjoerg struct ifaddr *ifa; 472125944Sjoerg struct sockaddr_in *si; 472284318Sjlemon struct in_ifaddr *ia; 472325944Sjoerg 472425944Sjoerg /* 472525944Sjoerg * Pick the first AF_INET address from the list, 472625944Sjoerg * aliases don't make any sense on a p2p link anyway. 472725944Sjoerg */ 472842065Sphk si = 0; 472942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 473042065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 473142104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 473271959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 473340008Sjoerg ifa; 473471959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 473542104Sphk#else 473642104Sphk for (ifa = ifp->if_addrlist; 473742104Sphk ifa; 473842104Sphk ifa = ifa->ifa_next) 473940008Sjoerg#endif 474040008Sjoerg { 474140008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 474240008Sjoerg { 474325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 474425944Sjoerg if (si) 474525944Sjoerg break; 474625944Sjoerg } 474740008Sjoerg } 474840008Sjoerg 474925944Sjoerg if (ifa && si) 475042104Sphk { 475142104Sphk int error; 475242104Sphk#if __NetBSD_Version__ >= 103080000 475342104Sphk struct sockaddr_in new_sin = *si; 475442104Sphk 475542104Sphk new_sin.sin_addr.s_addr = htonl(src); 475642104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 475742104Sphk if(debug && error) 475842104Sphk { 475942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 476042104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 476142104Sphk } 476242104Sphk#else 476342104Sphk /* delete old route */ 476442104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 476542104Sphk if(debug && error) 476642104Sphk { 476742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 476842104Sphk SPP_ARGS(ifp), error); 476942104Sphk } 477042104Sphk 477142104Sphk /* set new address */ 477225944Sjoerg si->sin_addr.s_addr = htonl(src); 477384318Sjlemon ia = ifatoia(ifa); 477484318Sjlemon LIST_REMOVE(ia, ia_hash); 477584318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 477625944Sjoerg 477742104Sphk /* add new route */ 477870199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 477942104Sphk if (debug && error) 478042104Sphk { 478142104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 478242104Sphk SPP_ARGS(ifp), error); 478342104Sphk } 478442104Sphk#endif 478542104Sphk } 478688599Sjoerg} 478778064Sume 478878064Sume#ifdef INET6 478978064Sume/* 479078064Sume * Get both IPv6 addresses. 479178064Sume */ 479278064Sumestatic void 479378064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 479478064Sume struct in6_addr *srcmask) 479578064Sume{ 479678064Sume struct ifnet *ifp = &sp->pp_if; 479778064Sume struct ifaddr *ifa; 479878064Sume struct sockaddr_in6 *si, *sm; 479978064Sume struct in6_addr ssrc, ddst; 480078064Sume 480178064Sume sm = NULL; 480278064Sume bzero(&ssrc, sizeof(ssrc)); 480378064Sume bzero(&ddst, sizeof(ddst)); 480478064Sume /* 480578064Sume * Pick the first link-local AF_INET6 address from the list, 480678064Sume * aliases don't make any sense on a p2p link anyway. 480778064Sume */ 480878064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 480978064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 481078064Sume ifa; 481178064Sume ifa = ifa->ifa_link.tqe_next) 481278064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 481378064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 481478064Sume ifa; 481578064Sume ifa = ifa->ifa_list.tqe_next) 481678064Sume#else 481778064Sume for (ifa = ifp->if_addrlist, si = 0; 481878064Sume ifa; 481978064Sume ifa = ifa->ifa_next) 482078064Sume#endif 482178064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 482278064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 482378064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 482478064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 482578064Sume break; 482678064Sume } 482778064Sume if (ifa) { 482878064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 482978064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 483078064Sume if (srcmask) { 483178064Sume bcopy(&sm->sin6_addr, srcmask, 483278064Sume sizeof(*srcmask)); 483378064Sume } 483478064Sume } 483578064Sume 483678064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 483778064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 483878064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 483978064Sume } 484078064Sume 484178064Sume if (dst) 484278064Sume bcopy(&ddst, dst, sizeof(*dst)); 484378064Sume if (src) 484478064Sume bcopy(&ssrc, src, sizeof(*src)); 484570199Sjhay} 484642104Sphk 484778064Sume#ifdef IPV6CP_MYIFID_DYN 484878064Sume/* 484978064Sume * Generate random ifid. 485078064Sume */ 485178064Sumestatic void 485278064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 485378064Sume{ 485478064Sume /* TBD */ 485578064Sume} 485678064Sume 485778064Sume/* 485878064Sume * Set my IPv6 address. Must be called at splimp. 485978064Sume */ 486078064Sumestatic void 486178064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 486278064Sume{ 486378064Sume STDDCL; 486478064Sume struct ifaddr *ifa; 486578064Sume struct sockaddr_in6 *sin6; 486678064Sume 486778064Sume /* 486878064Sume * Pick the first link-local AF_INET6 address from the list, 486978064Sume * aliases don't make any sense on a p2p link anyway. 487078064Sume */ 487178064Sume 487278064Sume sin6 = NULL; 487378064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 487478064Sume for (ifa = ifp->if_addrhead.tqh_first; 487578064Sume ifa; 487678064Sume ifa = ifa->ifa_link.tqe_next) 487778064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 487878064Sume for (ifa = ifp->if_addrlist.tqh_first; 487978064Sume ifa; 488078064Sume ifa = ifa->ifa_list.tqe_next) 488178064Sume#else 488278064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 488378064Sume#endif 488478064Sume { 488578064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 488678064Sume { 488778064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 488878064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 488978064Sume break; 489078064Sume } 489178064Sume } 489278064Sume 489378064Sume if (ifa && sin6) 489478064Sume { 489578064Sume int error; 489678064Sume struct sockaddr_in6 new_sin6 = *sin6; 489778064Sume 489878064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 489978064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 490078064Sume if (debug && error) 490178064Sume { 490278064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 490378064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 490478064Sume } 490578064Sume } 490678064Sume} 490778064Sume#endif 490878064Sume 490978064Sume/* 491078064Sume * Suggest a candidate address to be used by peer. 491178064Sume */ 491278064Sumestatic void 491378064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 491478064Sume{ 491578064Sume struct in6_addr myaddr; 491678064Sume struct timeval tv; 491778064Sume 491878064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 491978064Sume 492078064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 492178064Sume microtime(&tv); 492278064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 492378064Sume myaddr.s6_addr[14] ^= 0xff; 492478064Sume myaddr.s6_addr[15] ^= 0xff; 492578064Sume } else { 492678064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 492778064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 492878064Sume } 492978064Sume if (suggest) 493078064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 493178064Sume} 493278064Sume#endif /*INET6*/ 493378064Sume 493430300Sjoergstatic int 493538343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 493630300Sjoerg{ 493738343Sbde u_long subcmd; 493830300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 493988600Sjoerg struct spppreq *spr; 494088600Sjoerg int rv = 0; 494130300Sjoerg 494288600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 494388600Sjoerg return (EAGAIN); 494430300Sjoerg /* 494530300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 494630300Sjoerg * Check the cmd word first before attempting to fetch all the 494730300Sjoerg * data. 494830300Sjoerg */ 494988600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 495088600Sjoerg rv = EFAULT; 495188600Sjoerg goto quit; 495288600Sjoerg } 495330300Sjoerg 495488600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 495588600Sjoerg rv = EFAULT; 495688600Sjoerg goto quit; 495788600Sjoerg } 495830300Sjoerg 495930300Sjoerg switch (subcmd) { 496030300Sjoerg case SPPPIOGDEFS: 496188600Sjoerg if (cmd != SIOCGIFGENERIC) { 496288600Sjoerg rv = EINVAL; 496388600Sjoerg break; 496488600Sjoerg } 496530300Sjoerg /* 496630300Sjoerg * We copy over the entire current state, but clean 496730300Sjoerg * out some of the stuff we don't wanna pass up. 496830300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 496930300Sjoerg * called by any user. No need to ever get PAP or 497030300Sjoerg * CHAP secrets back to userland anyway. 497130300Sjoerg */ 497288600Sjoerg spr->defs.pp_phase = sp->pp_phase; 497388600Sjoerg spr->defs.enable_vj = sp->enable_vj; 497488600Sjoerg spr->defs.lcp = sp->lcp; 497588600Sjoerg spr->defs.ipcp = sp->ipcp; 497688600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 497788600Sjoerg spr->defs.myauth = sp->myauth; 497888600Sjoerg spr->defs.hisauth = sp->hisauth; 497988600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 498088600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 498188600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 498288600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 498388550Sjoerg /* 498488550Sjoerg * Fixup the LCP timeout value to milliseconds so 498588550Sjoerg * spppcontrol doesn't need to bother about the value 498688550Sjoerg * of "hz". We do the reverse calculation below when 498788550Sjoerg * setting it. 498888550Sjoerg */ 498988600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 499088600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 499188600Sjoerg sizeof(struct spppreq)); 499288600Sjoerg break; 499330300Sjoerg 499430300Sjoerg case SPPPIOSDEFS: 499588600Sjoerg if (cmd != SIOCSIFGENERIC) { 499688600Sjoerg rv = EINVAL; 499788600Sjoerg break; 499888600Sjoerg } 499930300Sjoerg /* 500088550Sjoerg * We have a very specific idea of which fields we 500188550Sjoerg * allow being passed back from userland, so to not 500288550Sjoerg * clobber our current state. For one, we only allow 500388550Sjoerg * setting anything if LCP is in dead or establish 500488550Sjoerg * phase. Once the authentication negotiations 500588550Sjoerg * started, the authentication settings must not be 500688550Sjoerg * changed again. (The administrator can force an 500730300Sjoerg * ifconfig down in order to get LCP back into dead 500830300Sjoerg * phase.) 500930300Sjoerg * 501030300Sjoerg * Also, we only allow for authentication parameters to be 501130300Sjoerg * specified. 501230300Sjoerg * 501330300Sjoerg * XXX Should allow to set or clear pp_flags. 501430300Sjoerg * 501530300Sjoerg * Finally, if the respective authentication protocol to 501630300Sjoerg * be used is set differently than 0, but the secret is 501730300Sjoerg * passed as all zeros, we don't trash the existing secret. 501830300Sjoerg * This allows an administrator to change the system name 501930300Sjoerg * only without clobbering the secret (which he didn't get 502030300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 502130300Sjoerg * secrets are cleared if the authentication protocol is 502288550Sjoerg * reset to 0. */ 502388550Sjoerg if (sp->pp_phase != PHASE_DEAD && 502488600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 502588600Sjoerg rv = EBUSY; 502688600Sjoerg break; 502788600Sjoerg } 502830300Sjoerg 502988600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 503088600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 503188600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 503288600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 503388600Sjoerg rv = EINVAL; 503488600Sjoerg break; 503588600Sjoerg } 503630300Sjoerg 503788600Sjoerg if (spr->defs.myauth.proto == 0) 503830300Sjoerg /* resetting myauth */ 503930300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 504030300Sjoerg else { 504130300Sjoerg /* setting/changing myauth */ 504288600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 504388600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 504488600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 504588600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 504630300Sjoerg AUTHKEYLEN); 504730300Sjoerg } 504888600Sjoerg if (spr->defs.hisauth.proto == 0) 504930300Sjoerg /* resetting hisauth */ 505030300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 505130300Sjoerg else { 505230300Sjoerg /* setting/changing hisauth */ 505388600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 505488600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 505588600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 505688600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 505788600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 505830300Sjoerg AUTHKEYLEN); 505930300Sjoerg } 506088550Sjoerg /* set LCP restart timer timeout */ 506188600Sjoerg if (spr->defs.lcp.timeout != 0) 506288600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 506388534Sjoerg /* set VJ enable flag */ 506488600Sjoerg sp->enable_vj = spr->defs.enable_vj; 506530300Sjoerg break; 506630300Sjoerg 506730300Sjoerg default: 506888600Sjoerg rv = EINVAL; 506930300Sjoerg } 507030300Sjoerg 507188600Sjoerg quit: 507288600Sjoerg free(spr, M_TEMP); 507388600Sjoerg 507488600Sjoerg return (rv); 507530300Sjoerg} 507630300Sjoerg 507730300Sjoergstatic void 507830300Sjoergsppp_phase_network(struct sppp *sp) 507930300Sjoerg{ 508042066Sphk STDDCL; 508130300Sjoerg int i; 508230300Sjoerg u_long mask; 508330300Sjoerg 508430300Sjoerg sp->pp_phase = PHASE_NETWORK; 508530300Sjoerg 508642066Sphk if (debug) 508742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 508842066Sphk sppp_phase_name(sp->pp_phase)); 508930300Sjoerg 509030300Sjoerg /* Notify NCPs now. */ 509130300Sjoerg for (i = 0; i < IDX_COUNT; i++) 509230300Sjoerg if ((cps[i])->flags & CP_NCP) 509330300Sjoerg (cps[i])->Open(sp); 509430300Sjoerg 509530300Sjoerg /* Send Up events to all NCPs. */ 509630300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 509730300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 509830300Sjoerg (cps[i])->Up(sp); 509930300Sjoerg 510030300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 510130300Sjoerg sppp_lcp_check_and_close(sp); 510230300Sjoerg} 510330300Sjoerg 510470199Sjhay 510525706Sjoergstatic const char * 510625944Sjoergsppp_cp_type_name(u_char type) 51074910Swollman{ 510830300Sjoerg static char buf[12]; 51094910Swollman switch (type) { 511030300Sjoerg case CONF_REQ: return "conf-req"; 511130300Sjoerg case CONF_ACK: return "conf-ack"; 511230300Sjoerg case CONF_NAK: return "conf-nak"; 511330300Sjoerg case CONF_REJ: return "conf-rej"; 511430300Sjoerg case TERM_REQ: return "term-req"; 511530300Sjoerg case TERM_ACK: return "term-ack"; 511630300Sjoerg case CODE_REJ: return "code-rej"; 511730300Sjoerg case PROTO_REJ: return "proto-rej"; 511830300Sjoerg case ECHO_REQ: return "echo-req"; 511930300Sjoerg case ECHO_REPLY: return "echo-reply"; 512030300Sjoerg case DISC_REQ: return "discard-req"; 51214910Swollman } 512244145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 512330300Sjoerg return buf; 51244910Swollman} 51254910Swollman 512625706Sjoergstatic const char * 512730300Sjoergsppp_auth_type_name(u_short proto, u_char type) 512830300Sjoerg{ 512930300Sjoerg static char buf[12]; 513030300Sjoerg switch (proto) { 513130300Sjoerg case PPP_CHAP: 513230300Sjoerg switch (type) { 513330300Sjoerg case CHAP_CHALLENGE: return "challenge"; 513430300Sjoerg case CHAP_RESPONSE: return "response"; 513530300Sjoerg case CHAP_SUCCESS: return "success"; 513630300Sjoerg case CHAP_FAILURE: return "failure"; 513730300Sjoerg } 513830300Sjoerg case PPP_PAP: 513930300Sjoerg switch (type) { 514030300Sjoerg case PAP_REQ: return "req"; 514130300Sjoerg case PAP_ACK: return "ack"; 514230300Sjoerg case PAP_NAK: return "nak"; 514330300Sjoerg } 514430300Sjoerg } 514544145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 514630300Sjoerg return buf; 514730300Sjoerg} 514830300Sjoerg 514930300Sjoergstatic const char * 515025944Sjoergsppp_lcp_opt_name(u_char opt) 51514910Swollman{ 515230300Sjoerg static char buf[12]; 515325944Sjoerg switch (opt) { 515430300Sjoerg case LCP_OPT_MRU: return "mru"; 515530300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 515630300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 515730300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 515830300Sjoerg case LCP_OPT_MAGIC: return "magic"; 515930300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 516030300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 51614910Swollman } 516244145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 516330300Sjoerg return buf; 51644910Swollman} 51654910Swollman 516625944Sjoergstatic const char * 516725944Sjoergsppp_ipcp_opt_name(u_char opt) 516825944Sjoerg{ 516930300Sjoerg static char buf[12]; 517025944Sjoerg switch (opt) { 517130300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 517230300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 517330300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 517425944Sjoerg } 517544145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 517630300Sjoerg return buf; 517725944Sjoerg} 517825944Sjoerg 517978064Sume#ifdef INET6 518025944Sjoergstatic const char * 518178064Sumesppp_ipv6cp_opt_name(u_char opt) 518278064Sume{ 518378064Sume static char buf[12]; 518478064Sume switch (opt) { 518578064Sume case IPV6CP_OPT_IFID: return "ifid"; 518678064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 518778064Sume } 518878064Sume sprintf (buf, "0x%x", opt); 518978064Sume return buf; 519078064Sume} 519178064Sume#endif 519278064Sume 519378064Sumestatic const char * 519425944Sjoergsppp_state_name(int state) 519525944Sjoerg{ 519625944Sjoerg switch (state) { 519725944Sjoerg case STATE_INITIAL: return "initial"; 519825944Sjoerg case STATE_STARTING: return "starting"; 519925944Sjoerg case STATE_CLOSED: return "closed"; 520025944Sjoerg case STATE_STOPPED: return "stopped"; 520125944Sjoerg case STATE_CLOSING: return "closing"; 520225944Sjoerg case STATE_STOPPING: return "stopping"; 520325944Sjoerg case STATE_REQ_SENT: return "req-sent"; 520425944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 520525944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 520625944Sjoerg case STATE_OPENED: return "opened"; 520725944Sjoerg } 520825944Sjoerg return "illegal"; 520925944Sjoerg} 521025944Sjoerg 521125944Sjoergstatic const char * 521225944Sjoergsppp_phase_name(enum ppp_phase phase) 521325944Sjoerg{ 521425944Sjoerg switch (phase) { 521525944Sjoerg case PHASE_DEAD: return "dead"; 521625944Sjoerg case PHASE_ESTABLISH: return "establish"; 521725944Sjoerg case PHASE_TERMINATE: return "terminate"; 521825944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 521925944Sjoerg case PHASE_NETWORK: return "network"; 522025944Sjoerg } 522125944Sjoerg return "illegal"; 522225944Sjoerg} 522325944Sjoerg 522425944Sjoergstatic const char * 522525944Sjoergsppp_proto_name(u_short proto) 522625944Sjoerg{ 522725944Sjoerg static char buf[12]; 522825944Sjoerg switch (proto) { 522925944Sjoerg case PPP_LCP: return "lcp"; 523025944Sjoerg case PPP_IPCP: return "ipcp"; 523130300Sjoerg case PPP_PAP: return "pap"; 523230300Sjoerg case PPP_CHAP: return "chap"; 523378064Sume case PPP_IPV6CP: return "ipv6cp"; 523425944Sjoerg } 523544145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 523625944Sjoerg return buf; 523725944Sjoerg} 523825944Sjoerg 523912820Sphkstatic void 524030300Sjoergsppp_print_bytes(const u_char *p, u_short len) 52414910Swollman{ 524244145Sphk if (len) 524369211Sphk log(-1, " %*D", len, p, "-"); 52444910Swollman} 524525944Sjoerg 524630300Sjoergstatic void 524730300Sjoergsppp_print_string(const char *p, u_short len) 524830300Sjoerg{ 524930300Sjoerg u_char c; 525030300Sjoerg 525130300Sjoerg while (len-- > 0) { 525230300Sjoerg c = *p++; 525330300Sjoerg /* 525430300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 525530300Sjoerg * using only them, but we don't rely on it. */ 525630300Sjoerg if (c < ' ' || c > '~') 525769211Sphk log(-1, "\\x%x", c); 525830300Sjoerg else 525969211Sphk log(-1, "%c", c); 526030300Sjoerg } 526130300Sjoerg} 526230300Sjoerg 526330300Sjoergstatic const char * 526430300Sjoergsppp_dotted_quad(u_long addr) 526530300Sjoerg{ 526630300Sjoerg static char s[16]; 526730300Sjoerg sprintf(s, "%d.%d.%d.%d", 526840008Sjoerg (int)((addr >> 24) & 0xff), 526940008Sjoerg (int)((addr >> 16) & 0xff), 527040008Sjoerg (int)((addr >> 8) & 0xff), 527138372Sbde (int)(addr & 0xff)); 527230300Sjoerg return s; 527330300Sjoerg} 527430300Sjoerg 527530300Sjoergstatic int 527630300Sjoergsppp_strnlen(u_char *p, int max) 527730300Sjoerg{ 527830300Sjoerg int len; 527930300Sjoerg 528030300Sjoerg for (len = 0; len < max && *p; ++p) 528130300Sjoerg ++len; 528230300Sjoerg return len; 528330300Sjoerg} 528430300Sjoerg 528530300Sjoerg/* a dummy, used to drop uninteresting events */ 528630300Sjoergstatic void 528730300Sjoergsppp_null(struct sppp *unused) 528830300Sjoerg{ 528930300Sjoerg /* do just nothing */ 529030300Sjoerg} 5291