if_spppsubr.c revision 88704
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 88704 2001-12-30 16:52:40Z 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; 21388704Sjoerg} __attribute__((__packed__)); 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; 22088704Sjoerg} __attribute__((__packed__)); 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; 23088704Sjoerg} __attribute__((__packed__)); 23188704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 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; 50988700Sjoerg u_char *iphdr; 51088700Sjoerg int hlen, vjlen, do_account = 0; 51125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5124910Swollman 5134910Swollman if (ifp->if_flags & IFF_UP) 5144910Swollman /* Count received bytes, add FCS and one flag */ 5154910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5164910Swollman 5174910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5184910Swollman /* Too small packet, drop it. */ 51925944Sjoerg if (debug) 52025706Sjoerg log(LOG_DEBUG, 52140008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 52240008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 52325944Sjoerg drop: 52488700Sjoerg m_freem (m); 52588700Sjoerg drop2: 52625944Sjoerg ++ifp->if_ierrors; 52725944Sjoerg ++ifp->if_iqdrops; 5284910Swollman return; 5294910Swollman } 5304910Swollman 5314910Swollman /* Get PPP header. */ 5324910Swollman h = mtod (m, struct ppp_header*); 5334910Swollman m_adj (m, PPP_HEADER_LEN); 5344910Swollman 5354910Swollman switch (h->address) { 5364910Swollman case PPP_ALLSTATIONS: 5374910Swollman if (h->control != PPP_UI) 5384910Swollman goto invalid; 53945152Sphk if (sp->pp_mode == IFF_CISCO) { 54025944Sjoerg if (debug) 54125706Sjoerg log(LOG_DEBUG, 54240008Sjoerg SPP_FMT "PPP packet in Cisco mode " 54325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 54440008Sjoerg SPP_ARGS(ifp), 54525706Sjoerg h->address, h->control, ntohs(h->protocol)); 54611189Sjkh goto drop; 54711189Sjkh } 5484910Swollman switch (ntohs (h->protocol)) { 5494910Swollman default: 55025944Sjoerg if (debug) 55125706Sjoerg log(LOG_DEBUG, 55244145Sphk SPP_FMT "rejecting protocol " 55325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55440008Sjoerg SPP_ARGS(ifp), 55525706Sjoerg h->address, h->control, ntohs(h->protocol)); 55644145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 55744145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 55878064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 55944145Sphk &h->protocol); 5604910Swollman ++ifp->if_noproto; 5614910Swollman goto drop; 5624910Swollman case PPP_LCP: 56330300Sjoerg sppp_cp_input(&lcp, sp, m); 5644910Swollman m_freem (m); 5654910Swollman return; 56630300Sjoerg case PPP_PAP: 56730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 56830300Sjoerg sppp_pap_input(sp, m); 56930300Sjoerg m_freem (m); 57030300Sjoerg return; 57130300Sjoerg case PPP_CHAP: 57230300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 57330300Sjoerg sppp_chap_input(sp, m); 57430300Sjoerg m_freem (m); 57530300Sjoerg return; 5764910Swollman#ifdef INET 5774910Swollman case PPP_IPCP: 57825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 57930300Sjoerg sppp_cp_input(&ipcp, sp, m); 5804910Swollman m_freem (m); 5814910Swollman return; 5824910Swollman case PPP_IP: 58325944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5844910Swollman schednetisr (NETISR_IP); 5854910Swollman inq = &ipintrq; 5864910Swollman } 58788577Sjoerg do_account++; 5884910Swollman break; 58988534Sjoerg case PPP_VJ_COMP: 59088534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 59188700Sjoerg if ((vjlen = 59288700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 59388700Sjoerg m->m_len, m->m_len, 59488700Sjoerg TYPE_COMPRESSED_TCP, 59588700Sjoerg sp->pp_comp, 59688700Sjoerg &iphdr, &hlen)) <= 0) { 59788700Sjoerg if (debug) 59888700Sjoerg log(LOG_INFO, 59988700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 60088700Sjoerg SPP_ARGS(ifp)); 60188534Sjoerg goto drop; 60288700Sjoerg } 60388700Sjoerg 60488700Sjoerg /* 60588700Sjoerg * Trim the VJ header off the packet, and prepend 60688700Sjoerg * the uncompressed IP header (which will usually 60788700Sjoerg * end up in two chained mbufs since there's not 60888700Sjoerg * enough leading space in the existing mbuf). 60988700Sjoerg */ 61088700Sjoerg m_adj(m, vjlen); 61188700Sjoerg M_PREPEND(m, hlen, M_DONTWAIT); 61288700Sjoerg if (m == NULL) 61388700Sjoerg goto drop2; 61488700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 61588700Sjoerg 61688534Sjoerg schednetisr (NETISR_IP); 61788534Sjoerg inq = &ipintrq; 61888534Sjoerg } 61988599Sjoerg do_account++; 62088534Sjoerg break; 62188534Sjoerg case PPP_VJ_UCOMP: 62288534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 62388700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 62488700Sjoerg m->m_len, m->m_len, 62588700Sjoerg TYPE_UNCOMPRESSED_TCP, 62688700Sjoerg sp->pp_comp, 62788700Sjoerg &iphdr, &hlen) != 0) { 62888700Sjoerg if (debug) 62988700Sjoerg log(LOG_INFO, 63088700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 63188700Sjoerg SPP_ARGS(ifp)); 63288534Sjoerg goto drop; 63388700Sjoerg } 63488534Sjoerg schednetisr (NETISR_IP); 63588534Sjoerg inq = &ipintrq; 63688534Sjoerg } 63788599Sjoerg do_account++; 63888534Sjoerg break; 63978064Sume#endif 64088599Sjoerg#ifdef INET6 64188599Sjoerg case PPP_IPV6CP: 64288599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 64388599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 64488599Sjoerg m_freem (m); 64588599Sjoerg return; 64688599Sjoerg 64788599Sjoerg case PPP_IPV6: 64888599Sjoerg if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 64988599Sjoerg schednetisr (NETISR_IPV6); 65088599Sjoerg inq = &ip6intrq; 65188599Sjoerg } 65288599Sjoerg do_account++; 65388599Sjoerg break; 65488599Sjoerg#endif 65512495Speter#ifdef IPX 65612495Speter case PPP_IPX: 65712495Speter /* IPX IPXCP not implemented yet */ 65825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 65912495Speter schednetisr (NETISR_IPX); 66012495Speter inq = &ipxintrq; 66112495Speter } 66288577Sjoerg do_account++; 66312495Speter break; 66412495Speter#endif 6654910Swollman#ifdef NS 6664910Swollman case PPP_XNS: 6674910Swollman /* XNS IDPCP not implemented yet */ 66825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6694910Swollman schednetisr (NETISR_NS); 6704910Swollman inq = &nsintrq; 6714910Swollman } 67288577Sjoerg do_account++; 6734910Swollman break; 6744910Swollman#endif 6754910Swollman } 6764910Swollman break; 6774910Swollman case CISCO_MULTICAST: 6784910Swollman case CISCO_UNICAST: 6794910Swollman /* Don't check the control field here (RFC 1547). */ 68045152Sphk if (sp->pp_mode != IFF_CISCO) { 68125944Sjoerg if (debug) 68225706Sjoerg log(LOG_DEBUG, 68340008Sjoerg SPP_FMT "Cisco packet in PPP mode " 68425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 68540008Sjoerg SPP_ARGS(ifp), 68625706Sjoerg h->address, h->control, ntohs(h->protocol)); 68711189Sjkh goto drop; 68811189Sjkh } 6894910Swollman switch (ntohs (h->protocol)) { 6904910Swollman default: 6914910Swollman ++ifp->if_noproto; 6924910Swollman goto invalid; 6934910Swollman case CISCO_KEEPALIVE: 6944910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 6954910Swollman m_freem (m); 6964910Swollman return; 6974910Swollman#ifdef INET 6984910Swollman case ETHERTYPE_IP: 6994910Swollman schednetisr (NETISR_IP); 7004910Swollman inq = &ipintrq; 70188577Sjoerg do_account++; 7024910Swollman break; 7034910Swollman#endif 70454263Sshin#ifdef INET6 70554263Sshin case ETHERTYPE_IPV6: 70654263Sshin schednetisr (NETISR_IPV6); 70754263Sshin inq = &ip6intrq; 70888577Sjoerg do_account++; 70954263Sshin break; 71054263Sshin#endif 71112495Speter#ifdef IPX 71212495Speter case ETHERTYPE_IPX: 71312495Speter schednetisr (NETISR_IPX); 71412495Speter inq = &ipxintrq; 71588577Sjoerg do_account++; 71612495Speter break; 71712495Speter#endif 7184910Swollman#ifdef NS 7194910Swollman case ETHERTYPE_NS: 7204910Swollman schednetisr (NETISR_NS); 7214910Swollman inq = &nsintrq; 72288577Sjoerg do_account++; 7234910Swollman break; 7244910Swollman#endif 7254910Swollman } 7264910Swollman break; 72725944Sjoerg default: /* Invalid PPP packet. */ 72825944Sjoerg invalid: 72925944Sjoerg if (debug) 73025944Sjoerg log(LOG_DEBUG, 73140008Sjoerg SPP_FMT "invalid input packet " 73225944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 73340008Sjoerg SPP_ARGS(ifp), 73425944Sjoerg h->address, h->control, ntohs(h->protocol)); 73525944Sjoerg goto drop; 7364910Swollman } 7374910Swollman 7384910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 7394910Swollman goto drop; 7404910Swollman 7414910Swollman /* Check queue. */ 74269152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 74325944Sjoerg if (debug) 74440008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 74540008Sjoerg SPP_ARGS(ifp)); 7464910Swollman goto drop; 7474910Swollman } 74888577Sjoerg if (do_account) 74988577Sjoerg /* 75088577Sjoerg * Do only account for network packets, not for control 75188577Sjoerg * packets. This is used by some subsystems to detect 75288577Sjoerg * idle lines. 75388577Sjoerg */ 75488577Sjoerg sp->pp_last_recv = time_second; 7554910Swollman} 7564910Swollman 7574910Swollman/* 7584910Swollman * Enqueue transmit packet. 7594910Swollman */ 76012820Sphkstatic int 76125706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 76225706Sjoerg struct sockaddr *dst, struct rtentry *rt) 7634910Swollman{ 7644910Swollman struct sppp *sp = (struct sppp*) ifp; 7654910Swollman struct ppp_header *h; 76678064Sume struct ifqueue *ifq = NULL; 76725955Sjoerg int s, rv = 0; 76888534Sjoerg int ipproto = PPP_IP; 76942066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7704910Swollman 77125944Sjoerg s = splimp(); 77225944Sjoerg 77325944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 77425944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 7754910Swollman m_freem (m); 7764910Swollman splx (s); 7774910Swollman return (ENETDOWN); 7784910Swollman } 7794910Swollman 78025944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 78125944Sjoerg /* 78225944Sjoerg * Interface is not yet running, but auto-dial. Need 78325944Sjoerg * to start LCP for it. 78425944Sjoerg */ 78525944Sjoerg ifp->if_flags |= IFF_RUNNING; 78625944Sjoerg splx(s); 78725944Sjoerg lcp.Open(sp); 78825944Sjoerg s = splimp(); 78925944Sjoerg } 79025944Sjoerg 79178134Sume ifq = &ifp->if_snd; 7924910Swollman#ifdef INET 79312436Speter if (dst->sa_family == AF_INET) { 79440008Sjoerg /* XXX Check mbuf length here? */ 79512436Speter struct ip *ip = mtod (m, struct ip*); 79612436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 7974910Swollman 79842104Sphk /* 79942104Sphk * When using dynamic local IP address assignment by using 80042104Sphk * 0.0.0.0 as a local address, the first TCP session will 80142104Sphk * not connect because the local TCP checksum is computed 80242104Sphk * using 0.0.0.0 which will later become our real IP address 80342104Sphk * so the TCP checksum computed at the remote end will 80442104Sphk * become invalid. So we 80542104Sphk * - don't let packets with src ip addr 0 thru 80642104Sphk * - we flag TCP packets with src ip 0 as an error 80770199Sjhay */ 80842104Sphk 80942104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 81042104Sphk { 81142104Sphk m_freem(m); 81242104Sphk splx(s); 81342104Sphk if(ip->ip_p == IPPROTO_TCP) 81442104Sphk return(EADDRNOTAVAIL); 81542104Sphk else 81642104Sphk return(0); 81742104Sphk } 81870199Sjhay 81942104Sphk /* 82042104Sphk * Put low delay, telnet, rlogin and ftp control packets 82142104Sphk * in front of the queue. 82242104Sphk */ 82369152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 82441686Sphk ; 82541686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 82612436Speter ifq = &sp->pp_fastq; 82741686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 82841686Sphk ; 82941686Sphk else if (ip->ip_p != IPPROTO_TCP) 83041686Sphk ; 83141686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 83241686Sphk ifq = &sp->pp_fastq; 83341686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 83441686Sphk ifq = &sp->pp_fastq; 83588534Sjoerg 83688534Sjoerg /* 83788534Sjoerg * Do IP Header compression 83888534Sjoerg */ 83988534Sjoerg if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 84088534Sjoerg ip->ip_p == IPPROTO_TCP) 84188599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 84288534Sjoerg sp->ipcp.compress_cid)) { 84388534Sjoerg case TYPE_COMPRESSED_TCP: 84488534Sjoerg ipproto = PPP_VJ_COMP; 84588534Sjoerg break; 84688534Sjoerg case TYPE_UNCOMPRESSED_TCP: 84788534Sjoerg ipproto = PPP_VJ_UCOMP; 84888534Sjoerg break; 84988534Sjoerg case TYPE_IP: 85088534Sjoerg ipproto = PPP_IP; 85188534Sjoerg break; 85288534Sjoerg default: 85388534Sjoerg m_freem(m); 85488534Sjoerg splx(s); 85588534Sjoerg return (EINVAL); 85688534Sjoerg } 8574910Swollman } 8584910Swollman#endif 8594910Swollman 86078064Sume#ifdef INET6 86178064Sume if (dst->sa_family == AF_INET6) { 86278064Sume /* XXX do something tricky here? */ 86378064Sume } 86478064Sume#endif 86578064Sume 8664910Swollman /* 8674910Swollman * Prepend general data packet PPP header. For now, IP only. 8684910Swollman */ 8694910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 8704910Swollman if (! m) { 87142066Sphk if (debug) 87240008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 87340008Sjoerg SPP_ARGS(ifp)); 87425944Sjoerg ++ifp->if_oerrors; 8754910Swollman splx (s); 8764910Swollman return (ENOBUFS); 8774910Swollman } 87840008Sjoerg /* 87940008Sjoerg * May want to check size of packet 88040008Sjoerg * (albeit due to the implementation it's always enough) 88140008Sjoerg */ 8824910Swollman h = mtod (m, struct ppp_header*); 88345152Sphk if (sp->pp_mode == IFF_CISCO) { 88428088Skjc h->address = CISCO_UNICAST; /* unicast address */ 8854910Swollman h->control = 0; 8864910Swollman } else { 8874910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 8884910Swollman h->control = PPP_UI; /* Unnumbered Info */ 8894910Swollman } 8904910Swollman 8914910Swollman switch (dst->sa_family) { 8924910Swollman#ifdef INET 8934910Swollman case AF_INET: /* Internet Protocol */ 89445152Sphk if (sp->pp_mode == IFF_CISCO) 89511189Sjkh h->protocol = htons (ETHERTYPE_IP); 89611189Sjkh else { 89725955Sjoerg /* 89825955Sjoerg * Don't choke with an ENETDOWN early. It's 89925955Sjoerg * possible that we just started dialing out, 90025955Sjoerg * so don't drop the packet immediately. If 90125955Sjoerg * we notice that we run out of buffer space 90225955Sjoerg * below, we will however remember that we are 90325955Sjoerg * not ready to carry IP packets, and return 90425955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 90525955Sjoerg */ 90688534Sjoerg h->protocol = htons(ipproto); 90725955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 90825955Sjoerg rv = ENETDOWN; 90911189Sjkh } 9104910Swollman break; 9114910Swollman#endif 91254263Sshin#ifdef INET6 91354263Sshin case AF_INET6: /* Internet Protocol */ 91454263Sshin if (sp->pp_mode == IFF_CISCO) 91554263Sshin h->protocol = htons (ETHERTYPE_IPV6); 91654263Sshin else { 91778064Sume /* 91878064Sume * Don't choke with an ENETDOWN early. It's 91978064Sume * possible that we just started dialing out, 92078064Sume * so don't drop the packet immediately. If 92178064Sume * we notice that we run out of buffer space 92278064Sume * below, we will however remember that we are 92378064Sume * not ready to carry IP packets, and return 92478064Sume * ENETDOWN, as opposed to ENOBUFS. 92578064Sume */ 92678064Sume h->protocol = htons(PPP_IPV6); 92778064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 92878064Sume rv = ENETDOWN; 92954263Sshin } 93054263Sshin break; 93154263Sshin#endif 9324910Swollman#ifdef NS 9334910Swollman case AF_NS: /* Xerox NS Protocol */ 93445152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 9354910Swollman ETHERTYPE_NS : PPP_XNS); 9364910Swollman break; 9374910Swollman#endif 93811819Sjulian#ifdef IPX 93912495Speter case AF_IPX: /* Novell IPX Protocol */ 94045152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 94112495Speter ETHERTYPE_IPX : PPP_IPX); 94211819Sjulian break; 94311819Sjulian#endif 9444910Swollman default: 9454910Swollman m_freem (m); 94625944Sjoerg ++ifp->if_oerrors; 9474910Swollman splx (s); 9484910Swollman return (EAFNOSUPPORT); 9494910Swollman } 9504910Swollman 9514910Swollman /* 9524910Swollman * Queue message on interface, and start output if interface 95388577Sjoerg * not yet active. 9544910Swollman */ 95569152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 95625944Sjoerg ++ifp->if_oerrors; 95725955Sjoerg return (rv? rv: ENOBUFS); 9584910Swollman } 95988577Sjoerg /* 96088577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 96188577Sjoerg * here since sppp_output() is only called on behalf of 96288577Sjoerg * network-layer traffic; control-layer traffic is handled 96388577Sjoerg * by sppp_cp_send(). 96488577Sjoerg */ 96588577Sjoerg sp->pp_last_sent = time_second; 9664910Swollman return (0); 9674910Swollman} 9684910Swollman 96925706Sjoergvoid 97025706Sjoergsppp_attach(struct ifnet *ifp) 9714910Swollman{ 9724910Swollman struct sppp *sp = (struct sppp*) ifp; 9734910Swollman 9744910Swollman /* Initialize keepalive handler. */ 9754910Swollman if (! spppq) 97642064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 9774910Swollman 9784910Swollman /* Insert new entry into the keepalive list. */ 9794910Swollman sp->pp_next = spppq; 9804910Swollman spppq = sp; 9814910Swollman 98242064Sphk sp->pp_if.if_mtu = PP_MTU; 98342064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 9844910Swollman sp->pp_if.if_type = IFT_PPP; 9854910Swollman sp->pp_if.if_output = sppp_output; 98642104Sphk#if 0 98742064Sphk sp->pp_flags = PP_KEEPALIVE; 98842104Sphk#endif 98970199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 99070199Sjhay sp->pp_fastq.ifq_maxlen = 32; 99170199Sjhay sp->pp_cpq.ifq_maxlen = 20; 9924910Swollman sp->pp_loopcnt = 0; 9934910Swollman sp->pp_alivecnt = 0; 99478064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 99578064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 99625944Sjoerg sp->pp_phase = PHASE_DEAD; 99725944Sjoerg sp->pp_up = lcp.Up; 99825944Sjoerg sp->pp_down = lcp.Down; 99969152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 100069152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 100188599Sjoerg sp->pp_last_recv = sp->pp_last_sent = time_second; 100288534Sjoerg sp->enable_vj = 1; 100388599Sjoerg sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAIT); 100488599Sjoerg sl_compress_init(sp->pp_comp, -1); 100525944Sjoerg sppp_lcp_init(sp); 100625944Sjoerg sppp_ipcp_init(sp); 100778064Sume sppp_ipv6cp_init(sp); 100830300Sjoerg sppp_pap_init(sp); 100930300Sjoerg sppp_chap_init(sp); 10104910Swollman} 10114910Swollman 101230300Sjoergvoid 101325706Sjoergsppp_detach(struct ifnet *ifp) 10144910Swollman{ 10154910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 101625944Sjoerg int i; 10174910Swollman 10184910Swollman /* Remove the entry from the keepalive list. */ 10194910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 10204910Swollman if (p == sp) { 10214910Swollman *q = p->pp_next; 10224910Swollman break; 10234910Swollman } 10244910Swollman 10254910Swollman /* Stop keepalive handler. */ 10264910Swollman if (! spppq) 102740008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 102825944Sjoerg 102925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 103040008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 103140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 103269152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 103369152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 10344910Swollman} 10354910Swollman 10364910Swollman/* 10374910Swollman * Flush the interface output queue. 10384910Swollman */ 103925706Sjoergvoid 104025706Sjoergsppp_flush(struct ifnet *ifp) 10414910Swollman{ 10424910Swollman struct sppp *sp = (struct sppp*) ifp; 10434910Swollman 104425944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 104525944Sjoerg sppp_qflush (&sp->pp_fastq); 104626018Sjoerg sppp_qflush (&sp->pp_cpq); 10474910Swollman} 10484910Swollman 10494910Swollman/* 105011189Sjkh * Check if the output queue is empty. 105111189Sjkh */ 105212820Sphkint 105325706Sjoergsppp_isempty(struct ifnet *ifp) 105411189Sjkh{ 105511189Sjkh struct sppp *sp = (struct sppp*) ifp; 105625944Sjoerg int empty, s; 105711189Sjkh 105825944Sjoerg s = splimp(); 105926018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 106026018Sjoerg !sp->pp_if.if_snd.ifq_head; 106125944Sjoerg splx(s); 106211189Sjkh return (empty); 106311189Sjkh} 106411189Sjkh 106511189Sjkh/* 10664910Swollman * Get next packet to send. 10674910Swollman */ 106825706Sjoergstruct mbuf * 106925706Sjoergsppp_dequeue(struct ifnet *ifp) 10704910Swollman{ 10714910Swollman struct sppp *sp = (struct sppp*) ifp; 10724910Swollman struct mbuf *m; 107325944Sjoerg int s; 10744910Swollman 107525944Sjoerg s = splimp(); 107626018Sjoerg /* 107730300Sjoerg * Process only the control protocol queue until we have at 107830300Sjoerg * least one NCP open. 107926018Sjoerg * 108026018Sjoerg * Do always serve all three queues in Cisco mode. 108126018Sjoerg */ 108226018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 108326018Sjoerg if (m == NULL && 108445152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 108526018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 108626018Sjoerg if (m == NULL) 108726018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 108826018Sjoerg } 108926018Sjoerg splx(s); 109026018Sjoerg return m; 10914910Swollman} 10924910Swollman 10934910Swollman/* 109430300Sjoerg * Pick the next packet, do not remove it from the queue. 109530300Sjoerg */ 109630300Sjoergstruct mbuf * 109730300Sjoergsppp_pick(struct ifnet *ifp) 109830300Sjoerg{ 109930300Sjoerg struct sppp *sp = (struct sppp*)ifp; 110030300Sjoerg struct mbuf *m; 110130300Sjoerg int s; 110230300Sjoerg 110330300Sjoerg s= splimp (); 110430300Sjoerg 110530300Sjoerg m = sp->pp_cpq.ifq_head; 110630300Sjoerg if (m == NULL && 110745152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 110830300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 110930300Sjoerg m = sp->pp_if.if_snd.ifq_head; 111030300Sjoerg splx (s); 111130300Sjoerg return (m); 111230300Sjoerg} 111330300Sjoerg 111430300Sjoerg/* 111525944Sjoerg * Process an ioctl request. Called on low priority level. 11164910Swollman */ 111725944Sjoergint 111842104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 11194910Swollman{ 112025944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 112125944Sjoerg struct sppp *sp = (struct sppp*) ifp; 112230300Sjoerg int s, rv, going_up, going_down, newmode; 11234910Swollman 112425944Sjoerg s = splimp(); 112530300Sjoerg rv = 0; 112625944Sjoerg switch (cmd) { 112725944Sjoerg case SIOCAIFADDR: 112825944Sjoerg case SIOCSIFDSTADDR: 112925944Sjoerg break; 11304910Swollman 113125944Sjoerg case SIOCSIFADDR: 113288503Sjoerg /* set the interface "up" when assigning an IP address */ 113388503Sjoerg ifp->if_flags |= IFF_UP; 113425944Sjoerg /* fall through... */ 113511189Sjkh 113625944Sjoerg case SIOCSIFFLAGS: 113725944Sjoerg going_up = ifp->if_flags & IFF_UP && 113825944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 113925944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 114025944Sjoerg ifp->if_flags & IFF_RUNNING; 114145152Sphk 114245152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 114345152Sphk if (!newmode) 114445152Sphk newmode = ifp->if_flags & IFF_AUTO; 114545152Sphk if (!newmode) 114645152Sphk newmode = ifp->if_flags & IFF_CISCO; 114745152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 114845152Sphk ifp->if_flags |= newmode; 114945152Sphk 115045152Sphk if (newmode != sp->pp_mode) { 115145152Sphk going_down = 1; 115245152Sphk if (!going_up) 115345152Sphk going_up = ifp->if_flags & IFF_RUNNING; 11544910Swollman } 11554910Swollman 115645152Sphk if (going_down) { 115770199Sjhay if (sp->pp_mode != IFF_CISCO) 115845152Sphk lcp.Close(sp); 115945152Sphk else if (sp->pp_tlf) 116045152Sphk (sp->pp_tlf)(sp); 116126018Sjoerg sppp_flush(ifp); 116225944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 116345152Sphk sp->pp_mode = newmode; 116426018Sjoerg } 11654910Swollman 116645152Sphk if (going_up) { 116770199Sjhay if (sp->pp_mode != IFF_CISCO) 116845152Sphk lcp.Close(sp); 116945152Sphk sp->pp_mode = newmode; 117045152Sphk if (sp->pp_mode == 0) { 117145152Sphk ifp->if_flags |= IFF_RUNNING; 117245152Sphk lcp.Open(sp); 117345152Sphk } 117445152Sphk if (sp->pp_mode == IFF_CISCO) { 117545152Sphk if (sp->pp_tls) 117645152Sphk (sp->pp_tls)(sp); 117745152Sphk ifp->if_flags |= IFF_RUNNING; 117845152Sphk } 117945152Sphk } 118045152Sphk 11814910Swollman break; 118211189Sjkh 118325944Sjoerg#ifdef SIOCSIFMTU 118425944Sjoerg#ifndef ifr_mtu 118525944Sjoerg#define ifr_mtu ifr_metric 118625944Sjoerg#endif 118725944Sjoerg case SIOCSIFMTU: 118825944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 118925944Sjoerg return (EINVAL); 119025944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 11914910Swollman break; 119225944Sjoerg#endif 119325944Sjoerg#ifdef SLIOCSETMTU 119425944Sjoerg case SLIOCSETMTU: 119525944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 119625944Sjoerg return (EINVAL); 119725944Sjoerg ifp->if_mtu = *(short*)data; 11984910Swollman break; 119925944Sjoerg#endif 120025944Sjoerg#ifdef SIOCGIFMTU 120125944Sjoerg case SIOCGIFMTU: 120225944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 120311189Sjkh break; 120425944Sjoerg#endif 120525944Sjoerg#ifdef SLIOCGETMTU 120625944Sjoerg case SLIOCGETMTU: 120725944Sjoerg *(short*)data = ifp->if_mtu; 12084910Swollman break; 120925944Sjoerg#endif 121025944Sjoerg case SIOCADDMULTI: 121125944Sjoerg case SIOCDELMULTI: 12124910Swollman break; 121311189Sjkh 121430300Sjoerg case SIOCGIFGENERIC: 121530300Sjoerg case SIOCSIFGENERIC: 121630300Sjoerg rv = sppp_params(sp, cmd, data); 121730300Sjoerg break; 121830300Sjoerg 121925944Sjoerg default: 122030300Sjoerg rv = ENOTTY; 12214910Swollman } 122225944Sjoerg splx(s); 122330300Sjoerg return rv; 12244910Swollman} 12254910Swollman 122670199Sjhay/* 122725944Sjoerg * Cisco framing implementation. 122825944Sjoerg */ 122925944Sjoerg 12304910Swollman/* 12314910Swollman * Handle incoming Cisco keepalive protocol packets. 12324910Swollman */ 123330300Sjoergstatic void 123425706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 12354910Swollman{ 123625944Sjoerg STDDCL; 12374910Swollman struct cisco_packet *h; 123830300Sjoerg u_long me, mymask; 12394910Swollman 124027929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 124125706Sjoerg if (debug) 124225706Sjoerg log(LOG_DEBUG, 124340008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 124440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 12454910Swollman return; 12464910Swollman } 12474910Swollman h = mtod (m, struct cisco_packet*); 124825706Sjoerg if (debug) 124925706Sjoerg log(LOG_DEBUG, 125040008Sjoerg SPP_FMT "cisco input: %d bytes " 125125706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 125240008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 125340008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 125440008Sjoerg (u_int)h->time0, (u_int)h->time1); 12554910Swollman switch (ntohl (h->type)) { 12564910Swollman default: 125725706Sjoerg if (debug) 125869211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 125940008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 12604910Swollman break; 12614910Swollman case CISCO_ADDR_REPLY: 12624910Swollman /* Reply on address request, ignore */ 12634910Swollman break; 12644910Swollman case CISCO_KEEPALIVE_REQ: 12654910Swollman sp->pp_alivecnt = 0; 126678064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 126778064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 12684910Swollman /* Local and remote sequence numbers are equal. 12694910Swollman * Probably, the line is in loopback mode. */ 127011189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 127140008Sjoerg printf (SPP_FMT "loopback\n", 127240008Sjoerg SPP_ARGS(ifp)); 127311189Sjkh sp->pp_loopcnt = 0; 127411189Sjkh if (ifp->if_flags & IFF_UP) { 127511189Sjkh if_down (ifp); 127626018Sjoerg sppp_qflush (&sp->pp_cpq); 127711189Sjkh } 127811189Sjkh } 12794910Swollman ++sp->pp_loopcnt; 12804910Swollman 12814910Swollman /* Generate new local sequence number */ 128242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 128378064Sume sp->pp_seq[IDX_LCP] = random(); 128440008Sjoerg#else 128578064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 128640008Sjoerg#endif 128711189Sjkh break; 128811189Sjkh } 128930300Sjoerg sp->pp_loopcnt = 0; 129011189Sjkh if (! (ifp->if_flags & IFF_UP) && 129111189Sjkh (ifp->if_flags & IFF_RUNNING)) { 129230300Sjoerg if_up(ifp); 129340008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 129411189Sjkh } 12954910Swollman break; 12964910Swollman case CISCO_ADDR_REQ: 129730300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 129830300Sjoerg if (me != 0L) 129930300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13004910Swollman break; 13014910Swollman } 13024910Swollman} 13034910Swollman 13044910Swollman/* 130525944Sjoerg * Send Cisco keepalive packet. 13064910Swollman */ 130712820Sphkstatic void 130825944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 130925944Sjoerg{ 131025944Sjoerg STDDCL; 131125944Sjoerg struct ppp_header *h; 131225944Sjoerg struct cisco_packet *ch; 131325944Sjoerg struct mbuf *m; 131442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 131535029Sphk struct timeval tv; 131640008Sjoerg#else 131740008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 131840008Sjoerg#endif 131925944Sjoerg 132042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 132136119Sphk getmicrouptime(&tv); 132240008Sjoerg#endif 132370199Sjhay 132425944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 132525944Sjoerg if (! m) 132625944Sjoerg return; 132725944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 132825944Sjoerg m->m_pkthdr.rcvif = 0; 132925944Sjoerg 133025944Sjoerg h = mtod (m, struct ppp_header*); 133125944Sjoerg h->address = CISCO_MULTICAST; 133225944Sjoerg h->control = 0; 133325944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 133425944Sjoerg 133525944Sjoerg ch = (struct cisco_packet*) (h + 1); 133625944Sjoerg ch->type = htonl (type); 133725944Sjoerg ch->par1 = htonl (par1); 133825944Sjoerg ch->par2 = htonl (par2); 133925944Sjoerg ch->rel = -1; 134040008Sjoerg 134142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 134235029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 134335029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 134440008Sjoerg#else 134540008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 134640008Sjoerg ch->time1 = htons ((u_short) t); 134740008Sjoerg#endif 134825944Sjoerg 134925944Sjoerg if (debug) 135025944Sjoerg log(LOG_DEBUG, 135140008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 135240008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 135340008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 135425944Sjoerg 135569152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 135669152Sjlemon ifp->if_oerrors++; 135725944Sjoerg} 135825944Sjoerg 135970199Sjhay/* 136025944Sjoerg * PPP protocol implementation. 136125944Sjoerg */ 136225944Sjoerg 136325944Sjoerg/* 136425944Sjoerg * Send PPP control protocol packet. 136525944Sjoerg */ 136625944Sjoergstatic void 136725706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 136825706Sjoerg u_char ident, u_short len, void *data) 13694910Swollman{ 137025944Sjoerg STDDCL; 13714910Swollman struct ppp_header *h; 13724910Swollman struct lcp_header *lh; 13734910Swollman struct mbuf *m; 13744910Swollman 13754910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 13764910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 13774910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 13784910Swollman if (! m) 13794910Swollman return; 13804910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 13814910Swollman m->m_pkthdr.rcvif = 0; 13824910Swollman 13834910Swollman h = mtod (m, struct ppp_header*); 13844910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 13854910Swollman h->control = PPP_UI; /* Unnumbered Info */ 13864910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 13874910Swollman 13884910Swollman lh = (struct lcp_header*) (h + 1); 13894910Swollman lh->type = type; 13904910Swollman lh->ident = ident; 13914910Swollman lh->len = htons (LCP_HEADER_LEN + len); 13924910Swollman if (len) 13934910Swollman bcopy (data, lh+1, len); 13944910Swollman 139525706Sjoerg if (debug) { 139640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 139740008Sjoerg SPP_ARGS(ifp), 139825944Sjoerg sppp_proto_name(proto), 139925944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 140025944Sjoerg ntohs (lh->len)); 140144145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 140269211Sphk log(-1, ">\n"); 14034910Swollman } 140469152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 140569152Sjlemon ifp->if_oerrors++; 14064910Swollman} 14074910Swollman 14084910Swollman/* 140925944Sjoerg * Handle incoming PPP control protocol packets. 14104910Swollman */ 141112820Sphkstatic void 141225944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14134910Swollman{ 141425944Sjoerg STDDCL; 141525944Sjoerg struct lcp_header *h; 141625944Sjoerg int len = m->m_pkthdr.len; 141725944Sjoerg int rv; 141825944Sjoerg u_char *p; 14194910Swollman 142025944Sjoerg if (len < 4) { 142125944Sjoerg if (debug) 142225944Sjoerg log(LOG_DEBUG, 142340008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 142440008Sjoerg SPP_ARGS(ifp), cp->name, len); 14254910Swollman return; 142625944Sjoerg } 142725944Sjoerg h = mtod (m, struct lcp_header*); 142825944Sjoerg if (debug) { 142925944Sjoerg log(LOG_DEBUG, 143040008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 143140008Sjoerg SPP_ARGS(ifp), cp->name, 143225944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 143325944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 143444145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 143569211Sphk log(-1, ">\n"); 143625944Sjoerg } 143725944Sjoerg if (len > ntohs (h->len)) 143825944Sjoerg len = ntohs (h->len); 143930300Sjoerg p = (u_char *)(h + 1); 144025944Sjoerg switch (h->type) { 144125944Sjoerg case CONF_REQ: 144225944Sjoerg if (len < 4) { 144325944Sjoerg if (debug) 144469211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 144540008Sjoerg SPP_ARGS(ifp), cp->name, 144625944Sjoerg len); 144725944Sjoerg ++ifp->if_ierrors; 144825944Sjoerg break; 144925944Sjoerg } 145030300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 145130300Sjoerg switch (sp->state[cp->protoidx]) { 145230300Sjoerg case STATE_CLOSING: 145330300Sjoerg case STATE_STOPPING: 145430300Sjoerg return; 145530300Sjoerg case STATE_CLOSED: 145630300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 145730300Sjoerg 0, 0); 145830300Sjoerg return; 145930300Sjoerg } 146025944Sjoerg rv = (cp->RCR)(sp, h, len); 146125944Sjoerg switch (sp->state[cp->protoidx]) { 146225944Sjoerg case STATE_OPENED: 146325944Sjoerg (cp->tld)(sp); 146425944Sjoerg (cp->scr)(sp); 146525944Sjoerg /* fall through... */ 146625944Sjoerg case STATE_ACK_SENT: 146725944Sjoerg case STATE_REQ_SENT: 146870199Sjhay /* 146970199Sjhay * sppp_cp_change_state() have the side effect of 147070199Sjhay * restarting the timeouts. We want to avoid that 147170199Sjhay * if the state don't change, otherwise we won't 147270199Sjhay * ever timeout and resend a configuration request 147370199Sjhay * that got lost. 147470199Sjhay */ 147570199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 147670199Sjhay STATE_REQ_SENT)) 147770199Sjhay break; 147825944Sjoerg sppp_cp_change_state(cp, sp, rv? 147925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 148025944Sjoerg break; 148125944Sjoerg case STATE_STOPPED: 148225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 148325944Sjoerg (cp->scr)(sp); 148425944Sjoerg sppp_cp_change_state(cp, sp, rv? 148525944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 148625944Sjoerg break; 148725944Sjoerg case STATE_ACK_RCVD: 148825944Sjoerg if (rv) { 148925944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 149025944Sjoerg if (debug) 149140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 149240008Sjoerg SPP_ARGS(ifp), 149326077Sjoerg cp->name); 149425944Sjoerg (cp->tlu)(sp); 149525944Sjoerg } else 149625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 149725944Sjoerg break; 149825944Sjoerg default: 149940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 150040008Sjoerg SPP_ARGS(ifp), cp->name, 150125944Sjoerg sppp_cp_type_name(h->type), 150225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 150325944Sjoerg ++ifp->if_ierrors; 150425944Sjoerg } 150525944Sjoerg break; 150625944Sjoerg case CONF_ACK: 150725944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 150825944Sjoerg if (debug) 150969211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 151040008Sjoerg SPP_ARGS(ifp), cp->name, 151125944Sjoerg h->ident, sp->confid[cp->protoidx]); 151225944Sjoerg ++ifp->if_ierrors; 151325944Sjoerg break; 151425944Sjoerg } 151525944Sjoerg switch (sp->state[cp->protoidx]) { 151625944Sjoerg case STATE_CLOSED: 151725944Sjoerg case STATE_STOPPED: 151825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 151925944Sjoerg break; 152025944Sjoerg case STATE_CLOSING: 152125944Sjoerg case STATE_STOPPING: 152225944Sjoerg break; 152325944Sjoerg case STATE_REQ_SENT: 152425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 152525944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 152625944Sjoerg break; 152725944Sjoerg case STATE_OPENED: 152825944Sjoerg (cp->tld)(sp); 152925944Sjoerg /* fall through */ 153025944Sjoerg case STATE_ACK_RCVD: 153125944Sjoerg (cp->scr)(sp); 153225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 153325944Sjoerg break; 153425944Sjoerg case STATE_ACK_SENT: 153525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 153625944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 153725944Sjoerg if (debug) 153840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 153940008Sjoerg SPP_ARGS(ifp), cp->name); 154025944Sjoerg (cp->tlu)(sp); 154125944Sjoerg break; 154225944Sjoerg default: 154340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 154440008Sjoerg SPP_ARGS(ifp), cp->name, 154525944Sjoerg sppp_cp_type_name(h->type), 154625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 154725944Sjoerg ++ifp->if_ierrors; 154825944Sjoerg } 154925944Sjoerg break; 155025944Sjoerg case CONF_NAK: 155125944Sjoerg case CONF_REJ: 155225944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 155325944Sjoerg if (debug) 155469211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 155540008Sjoerg SPP_ARGS(ifp), cp->name, 155625944Sjoerg h->ident, sp->confid[cp->protoidx]); 155725944Sjoerg ++ifp->if_ierrors; 155825944Sjoerg break; 155925944Sjoerg } 156025944Sjoerg if (h->type == CONF_NAK) 156125944Sjoerg (cp->RCN_nak)(sp, h, len); 156225944Sjoerg else /* CONF_REJ */ 156325944Sjoerg (cp->RCN_rej)(sp, h, len); 15644910Swollman 156525944Sjoerg switch (sp->state[cp->protoidx]) { 156625944Sjoerg case STATE_CLOSED: 156725944Sjoerg case STATE_STOPPED: 156825944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 156925944Sjoerg break; 157025944Sjoerg case STATE_REQ_SENT: 157125944Sjoerg case STATE_ACK_SENT: 157225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 157370199Sjhay /* 157470199Sjhay * Slow things down a bit if we think we might be 157570199Sjhay * in loopback. Depend on the timeout to send the 157670199Sjhay * next configuration request. 157770199Sjhay */ 157870199Sjhay if (sp->pp_loopcnt) 157970199Sjhay break; 158025944Sjoerg (cp->scr)(sp); 158125944Sjoerg break; 158225944Sjoerg case STATE_OPENED: 158325944Sjoerg (cp->tld)(sp); 158425944Sjoerg /* fall through */ 158525944Sjoerg case STATE_ACK_RCVD: 158652633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 158725944Sjoerg (cp->scr)(sp); 158825944Sjoerg break; 158925944Sjoerg case STATE_CLOSING: 159025944Sjoerg case STATE_STOPPING: 159125944Sjoerg break; 159225944Sjoerg default: 159340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 159440008Sjoerg SPP_ARGS(ifp), cp->name, 159525944Sjoerg sppp_cp_type_name(h->type), 159625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 159725944Sjoerg ++ifp->if_ierrors; 159825944Sjoerg } 159925944Sjoerg break; 16004910Swollman 160125944Sjoerg case TERM_REQ: 160225944Sjoerg switch (sp->state[cp->protoidx]) { 160325944Sjoerg case STATE_ACK_RCVD: 160425944Sjoerg case STATE_ACK_SENT: 160525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 160625944Sjoerg /* fall through */ 160725944Sjoerg case STATE_CLOSED: 160825944Sjoerg case STATE_STOPPED: 160925944Sjoerg case STATE_CLOSING: 161025944Sjoerg case STATE_STOPPING: 161125944Sjoerg case STATE_REQ_SENT: 161225944Sjoerg sta: 161325944Sjoerg /* Send Terminate-Ack packet. */ 161425944Sjoerg if (debug) 161540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 161640008Sjoerg SPP_ARGS(ifp), cp->name); 161725944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 161825944Sjoerg break; 161925944Sjoerg case STATE_OPENED: 162025944Sjoerg (cp->tld)(sp); 162125944Sjoerg sp->rst_counter[cp->protoidx] = 0; 162225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 162325944Sjoerg goto sta; 162425944Sjoerg break; 162525944Sjoerg default: 162640008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 162740008Sjoerg SPP_ARGS(ifp), cp->name, 162825944Sjoerg sppp_cp_type_name(h->type), 162925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163025944Sjoerg ++ifp->if_ierrors; 163125944Sjoerg } 163225944Sjoerg break; 163325944Sjoerg case TERM_ACK: 163425944Sjoerg switch (sp->state[cp->protoidx]) { 163525944Sjoerg case STATE_CLOSED: 163625944Sjoerg case STATE_STOPPED: 163725944Sjoerg case STATE_REQ_SENT: 163825944Sjoerg case STATE_ACK_SENT: 163925944Sjoerg break; 164025944Sjoerg case STATE_CLOSING: 164141881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 164225944Sjoerg (cp->tlf)(sp); 164325944Sjoerg break; 164425944Sjoerg case STATE_STOPPING: 164541881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 164625944Sjoerg (cp->tlf)(sp); 164725944Sjoerg break; 164825944Sjoerg case STATE_ACK_RCVD: 164925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 165025944Sjoerg break; 165125944Sjoerg case STATE_OPENED: 165225944Sjoerg (cp->tld)(sp); 165325944Sjoerg (cp->scr)(sp); 165425944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 165525944Sjoerg break; 165625944Sjoerg default: 165740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 165840008Sjoerg SPP_ARGS(ifp), cp->name, 165925944Sjoerg sppp_cp_type_name(h->type), 166025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166125944Sjoerg ++ifp->if_ierrors; 166225944Sjoerg } 166325944Sjoerg break; 166425944Sjoerg case CODE_REJ: 166525944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 166630300Sjoerg log(LOG_INFO, 166740008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 166830300Sjoerg "danger will robinson\n", 166940008Sjoerg SPP_ARGS(ifp), cp->name, 167030300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 167125944Sjoerg switch (sp->state[cp->protoidx]) { 167225944Sjoerg case STATE_CLOSED: 167325944Sjoerg case STATE_STOPPED: 167425944Sjoerg case STATE_REQ_SENT: 167525944Sjoerg case STATE_ACK_SENT: 167625944Sjoerg case STATE_CLOSING: 167725944Sjoerg case STATE_STOPPING: 167825944Sjoerg case STATE_OPENED: 167925944Sjoerg break; 168025944Sjoerg case STATE_ACK_RCVD: 168125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 168225944Sjoerg break; 168325944Sjoerg default: 168440008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 168540008Sjoerg SPP_ARGS(ifp), cp->name, 168625944Sjoerg sppp_cp_type_name(h->type), 168725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 168825944Sjoerg ++ifp->if_ierrors; 168925944Sjoerg } 169025944Sjoerg break; 169180715Sume case PROTO_REJ: 169280715Sume { 169380715Sume int catastrophic; 169480715Sume const struct cp *upper; 169580715Sume int i; 169680715Sume u_int16_t proto; 169780715Sume 169880715Sume catastrophic = 0; 169980715Sume upper = NULL; 170080715Sume proto = ntohs(*((u_int16_t *)p)); 170180715Sume for (i = 0; i < IDX_COUNT; i++) { 170280715Sume if (cps[i]->proto == proto) { 170380715Sume upper = cps[i]; 170480715Sume break; 170580715Sume } 170680715Sume } 170780715Sume if (upper == NULL) 170880715Sume catastrophic++; 170980715Sume 171088508Sjoerg if (catastrophic || debug) 171188508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 171288508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 171388508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 171488508Sjoerg sppp_cp_type_name(h->type), proto, 171588508Sjoerg upper ? upper->name : "unknown", 171688508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 171780715Sume 171880715Sume /* 171980715Sume * if we got RXJ+ against conf-req, the peer does not implement 172080715Sume * this particular protocol type. terminate the protocol. 172180715Sume */ 172280715Sume if (upper && !catastrophic) { 172380715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 172480715Sume upper->Close(sp); 172580715Sume break; 172680715Sume } 172780715Sume } 172880715Sume 172980715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 173080715Sume switch (sp->state[cp->protoidx]) { 173180715Sume case STATE_CLOSED: 173280715Sume case STATE_STOPPED: 173380715Sume case STATE_REQ_SENT: 173480715Sume case STATE_ACK_SENT: 173580715Sume case STATE_CLOSING: 173680715Sume case STATE_STOPPING: 173780715Sume case STATE_OPENED: 173880715Sume break; 173980715Sume case STATE_ACK_RCVD: 174080715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 174180715Sume break; 174280715Sume default: 174380715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 174480715Sume SPP_ARGS(ifp), cp->name, 174580715Sume sppp_cp_type_name(h->type), 174680715Sume sppp_state_name(sp->state[cp->protoidx])); 174780715Sume ++ifp->if_ierrors; 174880715Sume } 174980715Sume break; 175080715Sume } 175125944Sjoerg case DISC_REQ: 175225944Sjoerg if (cp->proto != PPP_LCP) 175325944Sjoerg goto illegal; 175425944Sjoerg /* Discard the packet. */ 175525944Sjoerg break; 175625944Sjoerg case ECHO_REQ: 175725944Sjoerg if (cp->proto != PPP_LCP) 175825944Sjoerg goto illegal; 175925944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 176025944Sjoerg if (debug) 176169211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 176240008Sjoerg SPP_ARGS(ifp)); 176325944Sjoerg ++ifp->if_ierrors; 176425944Sjoerg break; 176525944Sjoerg } 176625944Sjoerg if (len < 8) { 176725944Sjoerg if (debug) 176869211Sphk log(-1, SPP_FMT "invalid lcp echo request " 176925944Sjoerg "packet length: %d bytes\n", 177040008Sjoerg SPP_ARGS(ifp), len); 177125944Sjoerg break; 177225944Sjoerg } 177344145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 177444145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 177525944Sjoerg /* Line loopback mode detected. */ 177640008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 177770199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 177825944Sjoerg if_down (ifp); 177926018Sjoerg sppp_qflush (&sp->pp_cpq); 17804910Swollman 178125944Sjoerg /* Shut down the PPP link. */ 178225944Sjoerg /* XXX */ 178325944Sjoerg lcp.Down(sp); 178425944Sjoerg lcp.Up(sp); 178525944Sjoerg break; 178625944Sjoerg } 178725944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 178825944Sjoerg if (debug) 178969211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 179040008Sjoerg SPP_ARGS(ifp)); 179125944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 179225944Sjoerg break; 179325944Sjoerg case ECHO_REPLY: 179425944Sjoerg if (cp->proto != PPP_LCP) 179525944Sjoerg goto illegal; 179625944Sjoerg if (h->ident != sp->lcp.echoid) { 179725944Sjoerg ++ifp->if_ierrors; 179825944Sjoerg break; 179925944Sjoerg } 180025944Sjoerg if (len < 8) { 180125944Sjoerg if (debug) 180269211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 180325944Sjoerg "packet length: %d bytes\n", 180440008Sjoerg SPP_ARGS(ifp), len); 180525944Sjoerg break; 180625944Sjoerg } 180725944Sjoerg if (debug) 180869211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 180940008Sjoerg SPP_ARGS(ifp)); 181044145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 181144145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 181225944Sjoerg sp->pp_alivecnt = 0; 181325944Sjoerg break; 181425944Sjoerg default: 181525944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 181625944Sjoerg illegal: 181725944Sjoerg if (debug) 181869211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 181940008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 182078064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 182178064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 182225944Sjoerg ++ifp->if_ierrors; 182325944Sjoerg } 18244910Swollman} 18254910Swollman 182625944Sjoerg 18274910Swollman/* 182825944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 182925944Sjoerg * Basically, the state transition handling in the automaton. 18304910Swollman */ 183125944Sjoergstatic void 183225944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18334910Swollman{ 183425944Sjoerg STDDCL; 18354910Swollman 183625944Sjoerg if (debug) 183740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 183840008Sjoerg SPP_ARGS(ifp), cp->name, 183925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 184025944Sjoerg 184125944Sjoerg switch (sp->state[cp->protoidx]) { 184225944Sjoerg case STATE_INITIAL: 184325944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 184425944Sjoerg break; 184525944Sjoerg case STATE_STARTING: 184625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 184725944Sjoerg (cp->scr)(sp); 184825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 184925944Sjoerg break; 18504910Swollman default: 185140008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 185240008Sjoerg SPP_ARGS(ifp), cp->name, 185325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 185425944Sjoerg } 185525944Sjoerg} 18564910Swollman 185725944Sjoergstatic void 185825944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 185925944Sjoerg{ 186025944Sjoerg STDDCL; 186125944Sjoerg 186225944Sjoerg if (debug) 186340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 186440008Sjoerg SPP_ARGS(ifp), cp->name, 186525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 186625944Sjoerg 186725944Sjoerg switch (sp->state[cp->protoidx]) { 186825944Sjoerg case STATE_CLOSED: 186925944Sjoerg case STATE_CLOSING: 187025944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 18714910Swollman break; 187225944Sjoerg case STATE_STOPPED: 187341881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 187425944Sjoerg (cp->tls)(sp); 187541881Sphk break; 187625944Sjoerg case STATE_STOPPING: 187725944Sjoerg case STATE_REQ_SENT: 187825944Sjoerg case STATE_ACK_RCVD: 187925944Sjoerg case STATE_ACK_SENT: 188025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 188125944Sjoerg break; 188225944Sjoerg case STATE_OPENED: 188325944Sjoerg (cp->tld)(sp); 188425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 188525944Sjoerg break; 188625944Sjoerg default: 188740008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 188840008Sjoerg SPP_ARGS(ifp), cp->name, 188925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 189025944Sjoerg } 189125944Sjoerg} 18924910Swollman 189311189Sjkh 189425944Sjoergstatic void 189525944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 189625944Sjoerg{ 189725944Sjoerg STDDCL; 189825944Sjoerg 189925944Sjoerg if (debug) 190040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 190140008Sjoerg SPP_ARGS(ifp), cp->name, 190225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190325944Sjoerg 190425944Sjoerg switch (sp->state[cp->protoidx]) { 190525944Sjoerg case STATE_INITIAL: 190641881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 190725944Sjoerg (cp->tls)(sp); 19084910Swollman break; 190925944Sjoerg case STATE_STARTING: 191025944Sjoerg break; 191125944Sjoerg case STATE_CLOSED: 191225944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 191325944Sjoerg (cp->scr)(sp); 191425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 191525944Sjoerg break; 191625944Sjoerg case STATE_STOPPED: 191774703Sjoerg /* 191874703Sjoerg * Try escaping stopped state. This seems to bite 191974703Sjoerg * people occasionally, in particular for IPCP, 192074703Sjoerg * presumably following previous IPCP negotiation 192174703Sjoerg * aborts. Somehow, we must have missed a Down event 192274703Sjoerg * which would have caused a transition into starting 192374703Sjoerg * state, so as a bandaid we force the Down event now. 192474703Sjoerg * This effectively implements (something like the) 192574703Sjoerg * `restart' option mentioned in the state transition 192674703Sjoerg * table of RFC 1661. 192774703Sjoerg */ 192874703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 192974703Sjoerg (cp->tls)(sp); 193074703Sjoerg break; 193125944Sjoerg case STATE_STOPPING: 193225944Sjoerg case STATE_REQ_SENT: 193325944Sjoerg case STATE_ACK_RCVD: 193425944Sjoerg case STATE_ACK_SENT: 193525944Sjoerg case STATE_OPENED: 193625944Sjoerg break; 193725944Sjoerg case STATE_CLOSING: 193825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 193925944Sjoerg break; 194025944Sjoerg } 194125944Sjoerg} 19424910Swollman 194325944Sjoerg 194425944Sjoergstatic void 194525944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 194625944Sjoerg{ 194725944Sjoerg STDDCL; 194825944Sjoerg 194925944Sjoerg if (debug) 195040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 195140008Sjoerg SPP_ARGS(ifp), cp->name, 195225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 195325944Sjoerg 195425944Sjoerg switch (sp->state[cp->protoidx]) { 195525944Sjoerg case STATE_INITIAL: 195625944Sjoerg case STATE_CLOSED: 195725944Sjoerg case STATE_CLOSING: 19584910Swollman break; 195925944Sjoerg case STATE_STARTING: 196041881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 196125944Sjoerg (cp->tlf)(sp); 19624910Swollman break; 196325944Sjoerg case STATE_STOPPED: 196425944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 19654910Swollman break; 196625944Sjoerg case STATE_STOPPING: 196725944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19684910Swollman break; 196925944Sjoerg case STATE_OPENED: 197025944Sjoerg (cp->tld)(sp); 197125944Sjoerg /* fall through */ 197225944Sjoerg case STATE_REQ_SENT: 197325944Sjoerg case STATE_ACK_RCVD: 197425944Sjoerg case STATE_ACK_SENT: 197525944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 197678064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 197778064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 197825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19794910Swollman break; 19804910Swollman } 19814910Swollman} 19824910Swollman 198325944Sjoergstatic void 198425944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 198525944Sjoerg{ 198625944Sjoerg STDDCL; 198725944Sjoerg int s; 198825944Sjoerg 198925944Sjoerg s = splimp(); 199025944Sjoerg if (debug) 199140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 199240008Sjoerg SPP_ARGS(ifp), cp->name, 199325944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 199425944Sjoerg sp->rst_counter[cp->protoidx]); 199525944Sjoerg 199625944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 199725944Sjoerg /* TO- event */ 199825944Sjoerg switch (sp->state[cp->protoidx]) { 199925944Sjoerg case STATE_CLOSING: 200041881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 200125944Sjoerg (cp->tlf)(sp); 200225944Sjoerg break; 200325944Sjoerg case STATE_STOPPING: 200441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 200525944Sjoerg (cp->tlf)(sp); 200625944Sjoerg break; 200725944Sjoerg case STATE_REQ_SENT: 200825944Sjoerg case STATE_ACK_RCVD: 200925944Sjoerg case STATE_ACK_SENT: 201041881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 201125944Sjoerg (cp->tlf)(sp); 201225944Sjoerg break; 201325944Sjoerg } 201425944Sjoerg else 201525944Sjoerg /* TO+ event */ 201625944Sjoerg switch (sp->state[cp->protoidx]) { 201725944Sjoerg case STATE_CLOSING: 201825944Sjoerg case STATE_STOPPING: 201978064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 202078064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 202170199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 202242064Sphk sp->ch[cp->protoidx]); 202325944Sjoerg break; 202425944Sjoerg case STATE_REQ_SENT: 202525944Sjoerg case STATE_ACK_RCVD: 202625944Sjoerg (cp->scr)(sp); 202725944Sjoerg /* sppp_cp_change_state() will restart the timer */ 202825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 202925944Sjoerg break; 203025944Sjoerg case STATE_ACK_SENT: 203125944Sjoerg (cp->scr)(sp); 203242064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 203342064Sphk sp->ch[cp->protoidx]); 203425944Sjoerg break; 203525944Sjoerg } 203625944Sjoerg 203725944Sjoerg splx(s); 203825944Sjoerg} 203925944Sjoerg 204011189Sjkh/* 204125944Sjoerg * Change the state of a control protocol in the state automaton. 204225944Sjoerg * Takes care of starting/stopping the restart timer. 204311189Sjkh */ 204425944Sjoergvoid 204525944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 204625944Sjoerg{ 204725944Sjoerg sp->state[cp->protoidx] = newstate; 204825944Sjoerg 204940008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 205025944Sjoerg switch (newstate) { 205125944Sjoerg case STATE_INITIAL: 205225944Sjoerg case STATE_STARTING: 205325944Sjoerg case STATE_CLOSED: 205425944Sjoerg case STATE_STOPPED: 205525944Sjoerg case STATE_OPENED: 205625944Sjoerg break; 205725944Sjoerg case STATE_CLOSING: 205825944Sjoerg case STATE_STOPPING: 205925944Sjoerg case STATE_REQ_SENT: 206025944Sjoerg case STATE_ACK_RCVD: 206125944Sjoerg case STATE_ACK_SENT: 206270199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 206342064Sphk sp->ch[cp->protoidx]); 206425944Sjoerg break; 206525944Sjoerg } 206625944Sjoerg} 206770199Sjhay 206870199Sjhay/* 206925944Sjoerg *--------------------------------------------------------------------------* 207025944Sjoerg * * 207125944Sjoerg * The LCP implementation. * 207225944Sjoerg * * 207325944Sjoerg *--------------------------------------------------------------------------* 207425944Sjoerg */ 207525944Sjoergstatic void 207625944Sjoergsppp_lcp_init(struct sppp *sp) 207725944Sjoerg{ 207825944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 207925944Sjoerg sp->lcp.magic = 0; 208025944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 208125944Sjoerg sp->fail_counter[IDX_LCP] = 0; 208278064Sume sp->pp_seq[IDX_LCP] = 0; 208378064Sume sp->pp_rseq[IDX_LCP] = 0; 208425944Sjoerg sp->lcp.protos = 0; 208525944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 208630300Sjoerg 208744145Sphk /* Note that these values are relevant for all control protocols */ 208844145Sphk sp->lcp.timeout = 3 * hz; 208925944Sjoerg sp->lcp.max_terminate = 2; 209025944Sjoerg sp->lcp.max_configure = 10; 209125944Sjoerg sp->lcp.max_failure = 10; 209242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 209330300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 209440008Sjoerg#endif 209525944Sjoerg} 209625944Sjoerg 209725944Sjoergstatic void 209825944Sjoergsppp_lcp_up(struct sppp *sp) 209925944Sjoerg{ 210025944Sjoerg STDDCL; 210125944Sjoerg 210270199Sjhay sp->pp_alivecnt = 0; 210370199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 210470199Sjhay sp->lcp.magic = 0; 210570199Sjhay sp->lcp.protos = 0; 210670199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 210725944Sjoerg /* 210875321Sjoerg * If we are authenticator, negotiate LCP_AUTH 210975321Sjoerg */ 211075321Sjoerg if (sp->hisauth.proto != 0) 211175321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 211275321Sjoerg else 211375321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 211475321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 211575321Sjoerg /* 211630300Sjoerg * If this interface is passive or dial-on-demand, and we are 211730300Sjoerg * still in Initial state, it means we've got an incoming 211830300Sjoerg * call. Activate the interface. 211925944Sjoerg */ 212025944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 212125944Sjoerg if (debug) 212225944Sjoerg log(LOG_DEBUG, 212340008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 212425944Sjoerg ifp->if_flags |= IFF_RUNNING; 212530300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 212630300Sjoerg if (debug) 212769211Sphk log(-1, "(incoming call)\n"); 212830300Sjoerg sp->pp_flags |= PP_CALLIN; 212930300Sjoerg lcp.Open(sp); 213030300Sjoerg } else if (debug) 213169211Sphk log(-1, "\n"); 213225944Sjoerg } 213325944Sjoerg 213425944Sjoerg sppp_up_event(&lcp, sp); 213525944Sjoerg} 213625944Sjoerg 213725944Sjoergstatic void 213825944Sjoergsppp_lcp_down(struct sppp *sp) 213925944Sjoerg{ 214025944Sjoerg STDDCL; 214125944Sjoerg 214225944Sjoerg sppp_down_event(&lcp, sp); 214325944Sjoerg 214425944Sjoerg /* 214525944Sjoerg * If this is neither a dial-on-demand nor a passive 214625944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 214725944Sjoerg * administrator can force a redial by another ``ifconfig 214825944Sjoerg * up''. XXX For leased line operation, should we immediately 214925944Sjoerg * try to reopen the connection here? 215025944Sjoerg */ 215125944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 215225944Sjoerg log(LOG_INFO, 215342066Sphk SPP_FMT "Down event, taking interface down.\n", 215440008Sjoerg SPP_ARGS(ifp)); 215525944Sjoerg if_down(ifp); 215625944Sjoerg } else { 215725944Sjoerg if (debug) 215825944Sjoerg log(LOG_DEBUG, 215940008Sjoerg SPP_FMT "Down event (carrier loss)\n", 216040008Sjoerg SPP_ARGS(ifp)); 216170199Sjhay sp->pp_flags &= ~PP_CALLIN; 216270199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 216370199Sjhay lcp.Close(sp); 216470199Sjhay ifp->if_flags &= ~IFF_RUNNING; 216525944Sjoerg } 216625944Sjoerg} 216725944Sjoerg 216825944Sjoergstatic void 216925944Sjoergsppp_lcp_open(struct sppp *sp) 217025944Sjoerg{ 217125944Sjoerg sppp_open_event(&lcp, sp); 217225944Sjoerg} 217325944Sjoerg 217425944Sjoergstatic void 217525944Sjoergsppp_lcp_close(struct sppp *sp) 217625944Sjoerg{ 217725944Sjoerg sppp_close_event(&lcp, sp); 217825944Sjoerg} 217925944Sjoerg 218025944Sjoergstatic void 218125944Sjoergsppp_lcp_TO(void *cookie) 218225944Sjoerg{ 218325944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 218425944Sjoerg} 218525944Sjoerg 218625944Sjoerg/* 218725944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 218825944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 218925944Sjoerg * caused action scn. (The return value is used to make the state 219025944Sjoerg * transition decision in the state automaton.) 219125944Sjoerg */ 219212820Sphkstatic int 219325944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 21944910Swollman{ 219525944Sjoerg STDDCL; 219611189Sjkh u_char *buf, *r, *p; 219725944Sjoerg int origlen, rlen; 219825944Sjoerg u_long nmagic; 219930300Sjoerg u_short authproto; 22004910Swollman 220111189Sjkh len -= 4; 220225944Sjoerg origlen = len; 220311189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 220411189Sjkh if (! buf) 220511189Sjkh return (0); 22064910Swollman 220725706Sjoerg if (debug) 220840008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 220940008Sjoerg SPP_ARGS(ifp)); 221025706Sjoerg 221125944Sjoerg /* pass 1: check for things that need to be rejected */ 221211189Sjkh p = (void*) (h+1); 221311189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 221425944Sjoerg if (debug) 221569211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 221611189Sjkh switch (*p) { 221711189Sjkh case LCP_OPT_MAGIC: 221825944Sjoerg /* Magic number. */ 221970199Sjhay if (len >= 6 && p[1] == 6) 222070199Sjhay continue; 222170199Sjhay if (debug) 222270199Sjhay log(-1, "[invalid] "); 222370199Sjhay break; 222425944Sjoerg case LCP_OPT_ASYNC_MAP: 222525944Sjoerg /* Async control character map. */ 222670199Sjhay if (len >= 6 && p[1] == 6) 222725944Sjoerg continue; 222825944Sjoerg if (debug) 222969211Sphk log(-1, "[invalid] "); 223025944Sjoerg break; 223125944Sjoerg case LCP_OPT_MRU: 223225944Sjoerg /* Maximum receive unit. */ 223325944Sjoerg if (len >= 4 && p[1] == 4) 223425944Sjoerg continue; 223525944Sjoerg if (debug) 223669211Sphk log(-1, "[invalid] "); 223725944Sjoerg break; 223830300Sjoerg case LCP_OPT_AUTH_PROTO: 223930300Sjoerg if (len < 4) { 224030300Sjoerg if (debug) 224169211Sphk log(-1, "[invalid] "); 224230300Sjoerg break; 224330300Sjoerg } 224430300Sjoerg authproto = (p[2] << 8) + p[3]; 224530300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 224630300Sjoerg if (debug) 224769211Sphk log(-1, "[invalid chap len] "); 224830300Sjoerg break; 224930300Sjoerg } 225030300Sjoerg if (sp->myauth.proto == 0) { 225130300Sjoerg /* we are not configured to do auth */ 225230300Sjoerg if (debug) 225369211Sphk log(-1, "[not configured] "); 225430300Sjoerg break; 225530300Sjoerg } 225630300Sjoerg /* 225730300Sjoerg * Remote want us to authenticate, remember this, 225830300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 225930300Sjoerg * up. 226030300Sjoerg */ 226130300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 226230300Sjoerg continue; 226325944Sjoerg default: 226425944Sjoerg /* Others not supported. */ 226525944Sjoerg if (debug) 226669211Sphk log(-1, "[rej] "); 226725944Sjoerg break; 226825944Sjoerg } 226925944Sjoerg /* Add the option to rejected list. */ 227025944Sjoerg bcopy (p, r, p[1]); 227125944Sjoerg r += p[1]; 227225944Sjoerg rlen += p[1]; 227325944Sjoerg } 227425944Sjoerg if (rlen) { 227525944Sjoerg if (debug) 227669211Sphk log(-1, " send conf-rej\n"); 227725944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 227825944Sjoerg return 0; 227925944Sjoerg } else if (debug) 228069211Sphk log(-1, "\n"); 228125944Sjoerg 228225944Sjoerg /* 228325944Sjoerg * pass 2: check for option values that are unacceptable and 228425944Sjoerg * thus require to be nak'ed. 228525944Sjoerg */ 228625944Sjoerg if (debug) 228740008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 228840008Sjoerg SPP_ARGS(ifp)); 228925944Sjoerg 229025944Sjoerg p = (void*) (h+1); 229125944Sjoerg len = origlen; 229225944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 229325944Sjoerg if (debug) 229469211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 229525944Sjoerg switch (*p) { 229625944Sjoerg case LCP_OPT_MAGIC: 229711189Sjkh /* Magic number -- extract. */ 229825944Sjoerg nmagic = (u_long)p[2] << 24 | 229925944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 230025944Sjoerg if (nmagic != sp->lcp.magic) { 230170199Sjhay sp->pp_loopcnt = 0; 230225706Sjoerg if (debug) 230369211Sphk log(-1, "0x%lx ", nmagic); 230411189Sjkh continue; 230511189Sjkh } 230670199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 230769211Sphk log(-1, "[glitch] "); 230825944Sjoerg ++sp->pp_loopcnt; 230925944Sjoerg /* 231025944Sjoerg * We negate our magic here, and NAK it. If 231125944Sjoerg * we see it later in an NAK packet, we 231225944Sjoerg * suggest a new one. 231325944Sjoerg */ 231425944Sjoerg nmagic = ~sp->lcp.magic; 231525944Sjoerg /* Gonna NAK it. */ 231625944Sjoerg p[2] = nmagic >> 24; 231725944Sjoerg p[3] = nmagic >> 16; 231825944Sjoerg p[4] = nmagic >> 8; 231925944Sjoerg p[5] = nmagic; 232011189Sjkh break; 232125944Sjoerg 232211189Sjkh case LCP_OPT_ASYNC_MAP: 232388506Sjoerg /* 232488506Sjoerg * Async control character map -- just ignore it. 232588506Sjoerg * 232688506Sjoerg * Quote from RFC 1662, chapter 6: 232788506Sjoerg * To enable this functionality, synchronous PPP 232888506Sjoerg * implementations MUST always respond to the 232988506Sjoerg * Async-Control-Character-Map Configuration 233088506Sjoerg * Option with the LCP Configure-Ack. However, 233188506Sjoerg * acceptance of the Configuration Option does 233288506Sjoerg * not imply that the synchronous implementation 233388506Sjoerg * will do any ACCM mapping. Instead, all such 233488506Sjoerg * octet mapping will be performed by the 233588506Sjoerg * asynchronous-to-synchronous converter. 233688506Sjoerg */ 233788506Sjoerg continue; 233825944Sjoerg 233911189Sjkh case LCP_OPT_MRU: 234025944Sjoerg /* 234125944Sjoerg * Maximum receive unit. Always agreeable, 234225944Sjoerg * but ignored by now. 234325944Sjoerg */ 234425944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 234525706Sjoerg if (debug) 234669211Sphk log(-1, "%lu ", sp->lcp.their_mru); 234711189Sjkh continue; 234830300Sjoerg 234930300Sjoerg case LCP_OPT_AUTH_PROTO: 235030300Sjoerg authproto = (p[2] << 8) + p[3]; 235130300Sjoerg if (sp->myauth.proto != authproto) { 235230300Sjoerg /* not agreed, nak */ 235330300Sjoerg if (debug) 235469211Sphk log(-1, "[mine %s != his %s] ", 235530300Sjoerg sppp_proto_name(sp->hisauth.proto), 235630300Sjoerg sppp_proto_name(authproto)); 235730300Sjoerg p[2] = sp->myauth.proto >> 8; 235830300Sjoerg p[3] = sp->myauth.proto; 235930300Sjoerg break; 236030300Sjoerg } 236130300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 236230300Sjoerg if (debug) 236369211Sphk log(-1, "[chap not MD5] "); 236439981Sjoerg p[4] = CHAP_MD5; 236530300Sjoerg break; 236630300Sjoerg } 236730300Sjoerg continue; 236811189Sjkh } 236925944Sjoerg /* Add the option to nak'ed list. */ 237025706Sjoerg bcopy (p, r, p[1]); 237125706Sjoerg r += p[1]; 237211189Sjkh rlen += p[1]; 237312436Speter } 237425706Sjoerg if (rlen) { 237570199Sjhay /* 237670199Sjhay * Local and remote magics equal -- loopback? 237770199Sjhay */ 237870199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 237970199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 238070199Sjhay printf (SPP_FMT "loopback\n", 238170199Sjhay SPP_ARGS(ifp)); 238270199Sjhay if (ifp->if_flags & IFF_UP) { 238370199Sjhay if_down(ifp); 238470199Sjhay sppp_qflush(&sp->pp_cpq); 238570199Sjhay /* XXX ? */ 238670199Sjhay lcp.Down(sp); 238770199Sjhay lcp.Up(sp); 238870199Sjhay } 238970199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 239028036Sjoerg if (debug) 239169211Sphk log(-1, " max_failure (%d) exceeded, " 239228036Sjoerg "send conf-rej\n", 239328036Sjoerg sp->lcp.max_failure); 239428036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 239528036Sjoerg } else { 239628036Sjoerg if (debug) 239769211Sphk log(-1, " send conf-nak\n"); 239828036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 239928036Sjoerg } 240025944Sjoerg } else { 240125944Sjoerg if (debug) 240269211Sphk log(-1, " send conf-ack\n"); 240328036Sjoerg sp->fail_counter[IDX_LCP] = 0; 240425944Sjoerg sp->pp_loopcnt = 0; 240525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 240625944Sjoerg h->ident, origlen, h+1); 240725944Sjoerg } 240825944Sjoerg 240911189Sjkh free (buf, M_TEMP); 241011189Sjkh return (rlen == 0); 24114910Swollman} 24124910Swollman 241325944Sjoerg/* 241425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 241525944Sjoerg * negotiation. 241625944Sjoerg */ 241712820Sphkstatic void 241825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 24194910Swollman{ 242025944Sjoerg STDDCL; 242125944Sjoerg u_char *buf, *p; 24224910Swollman 242325944Sjoerg len -= 4; 242425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 242525944Sjoerg if (!buf) 24264910Swollman return; 242725944Sjoerg 242825944Sjoerg if (debug) 242940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 243040008Sjoerg SPP_ARGS(ifp)); 243125944Sjoerg 243225944Sjoerg p = (void*) (h+1); 243325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 243425944Sjoerg if (debug) 243569211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 243625944Sjoerg switch (*p) { 243725944Sjoerg case LCP_OPT_MAGIC: 243825944Sjoerg /* Magic number -- can't use it, use 0 */ 243925944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 244025944Sjoerg sp->lcp.magic = 0; 244125944Sjoerg break; 244225944Sjoerg case LCP_OPT_MRU: 244325944Sjoerg /* 244425944Sjoerg * Should not be rejected anyway, since we only 244525944Sjoerg * negotiate a MRU if explicitly requested by 244625944Sjoerg * peer. 244725944Sjoerg */ 244825944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 244925944Sjoerg break; 245030300Sjoerg case LCP_OPT_AUTH_PROTO: 245130300Sjoerg /* 245230300Sjoerg * Peer doesn't want to authenticate himself, 245330300Sjoerg * deny unless this is a dialout call, and 245430300Sjoerg * AUTHFLAG_NOCALLOUT is set. 245530300Sjoerg */ 245630300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 245730300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 245830300Sjoerg if (debug) 245969211Sphk log(-1, "[don't insist on auth " 246030300Sjoerg "for callout]"); 246130300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 246230300Sjoerg break; 246330300Sjoerg } 246430300Sjoerg if (debug) 246569211Sphk log(-1, "[access denied]\n"); 246630300Sjoerg lcp.Close(sp); 246730300Sjoerg break; 246825944Sjoerg } 24694910Swollman } 247025944Sjoerg if (debug) 247169211Sphk log(-1, "\n"); 247225944Sjoerg free (buf, M_TEMP); 247325944Sjoerg return; 247425944Sjoerg} 247525944Sjoerg 247625944Sjoerg/* 247725944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 247825944Sjoerg * negotiation. 247925944Sjoerg */ 248025944Sjoergstatic void 248125944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 248225944Sjoerg{ 248325944Sjoerg STDDCL; 248425944Sjoerg u_char *buf, *p; 248525944Sjoerg u_long magic; 248625944Sjoerg 248725944Sjoerg len -= 4; 248825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 248925944Sjoerg if (!buf) 249025944Sjoerg return; 249125944Sjoerg 249225944Sjoerg if (debug) 249340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 249440008Sjoerg SPP_ARGS(ifp)); 249525944Sjoerg 249625944Sjoerg p = (void*) (h+1); 249725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 249825706Sjoerg if (debug) 249969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 250025944Sjoerg switch (*p) { 250125944Sjoerg case LCP_OPT_MAGIC: 250225944Sjoerg /* Magic number -- renegotiate */ 250325944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 250425944Sjoerg len >= 6 && p[1] == 6) { 250525944Sjoerg magic = (u_long)p[2] << 24 | 250625944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 250725944Sjoerg /* 250825944Sjoerg * If the remote magic is our negated one, 250925944Sjoerg * this looks like a loopback problem. 251025944Sjoerg * Suggest a new magic to make sure. 251125944Sjoerg */ 251225944Sjoerg if (magic == ~sp->lcp.magic) { 251325944Sjoerg if (debug) 251469211Sphk log(-1, "magic glitch "); 251542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 251635064Sphk sp->lcp.magic = random(); 251740008Sjoerg#else 251840008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 251940008Sjoerg#endif 252025944Sjoerg } else { 252125944Sjoerg sp->lcp.magic = magic; 252225944Sjoerg if (debug) 252369211Sphk log(-1, "%lu ", magic); 252425944Sjoerg } 252525944Sjoerg } 252625944Sjoerg break; 252725944Sjoerg case LCP_OPT_MRU: 252825944Sjoerg /* 252925944Sjoerg * Peer wants to advise us to negotiate an MRU. 253025944Sjoerg * Agree on it if it's reasonable, or use 253125944Sjoerg * default otherwise. 253225944Sjoerg */ 253325944Sjoerg if (len >= 4 && p[1] == 4) { 253425944Sjoerg u_int mru = p[2] * 256 + p[3]; 253525944Sjoerg if (debug) 253669211Sphk log(-1, "%d ", mru); 253725944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 253825944Sjoerg mru = PP_MTU; 253925944Sjoerg sp->lcp.mru = mru; 254025944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 254125944Sjoerg } 254225944Sjoerg break; 254330300Sjoerg case LCP_OPT_AUTH_PROTO: 254430300Sjoerg /* 254530300Sjoerg * Peer doesn't like our authentication method, 254630300Sjoerg * deny. 254730300Sjoerg */ 254830300Sjoerg if (debug) 254969211Sphk log(-1, "[access denied]\n"); 255030300Sjoerg lcp.Close(sp); 255130300Sjoerg break; 25524910Swollman } 255325944Sjoerg } 255425944Sjoerg if (debug) 255569211Sphk log(-1, "\n"); 255625944Sjoerg free (buf, M_TEMP); 255725944Sjoerg return; 255825944Sjoerg} 255911189Sjkh 256025944Sjoergstatic void 256125944Sjoergsppp_lcp_tlu(struct sppp *sp) 256225944Sjoerg{ 256342066Sphk STDDCL; 256425944Sjoerg int i; 256525944Sjoerg u_long mask; 256625944Sjoerg 256725944Sjoerg /* XXX ? */ 256825944Sjoerg if (! (ifp->if_flags & IFF_UP) && 256925944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 257025944Sjoerg /* Coming out of loopback mode. */ 257125944Sjoerg if_up(ifp); 257240008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 257325944Sjoerg } 257425944Sjoerg 257525944Sjoerg for (i = 0; i < IDX_COUNT; i++) 257625944Sjoerg if ((cps[i])->flags & CP_QUAL) 257725944Sjoerg (cps[i])->Open(sp); 257825944Sjoerg 257930300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 258030300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 258125944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 258225944Sjoerg else 258325944Sjoerg sp->pp_phase = PHASE_NETWORK; 258425944Sjoerg 258542066Sphk if (debug) 258642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 258742066Sphk sppp_phase_name(sp->pp_phase)); 258825944Sjoerg 258930300Sjoerg /* 259030300Sjoerg * Open all authentication protocols. This is even required 259130300Sjoerg * if we already proceeded to network phase, since it might be 259230300Sjoerg * that remote wants us to authenticate, so we might have to 259330300Sjoerg * send a PAP request. Undesired authentication protocols 259430300Sjoerg * don't do anything when they get an Open event. 259530300Sjoerg */ 259630300Sjoerg for (i = 0; i < IDX_COUNT; i++) 259730300Sjoerg if ((cps[i])->flags & CP_AUTH) 259830300Sjoerg (cps[i])->Open(sp); 259930300Sjoerg 260030300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 260125944Sjoerg /* Notify all NCPs. */ 260225944Sjoerg for (i = 0; i < IDX_COUNT; i++) 260325944Sjoerg if ((cps[i])->flags & CP_NCP) 260425944Sjoerg (cps[i])->Open(sp); 260525944Sjoerg } 260625944Sjoerg 260725944Sjoerg /* Send Up events to all started protos. */ 260825944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 260925944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 261025944Sjoerg (cps[i])->Up(sp); 261125944Sjoerg 261242104Sphk /* notify low-level driver of state change */ 261342104Sphk if (sp->pp_chg) 261442104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 261542104Sphk 261625944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 261725944Sjoerg /* if no NCP is starting, close down */ 261830300Sjoerg sppp_lcp_check_and_close(sp); 261925944Sjoerg} 262025944Sjoerg 262125944Sjoergstatic void 262225944Sjoergsppp_lcp_tld(struct sppp *sp) 262325944Sjoerg{ 262442066Sphk STDDCL; 262525944Sjoerg int i; 262625944Sjoerg u_long mask; 262725944Sjoerg 262825944Sjoerg sp->pp_phase = PHASE_TERMINATE; 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 /* 263525944Sjoerg * Take upper layers down. We send the Down event first and 263625944Sjoerg * the Close second to prevent the upper layers from sending 263725944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 263825944Sjoerg * describes it. 263925944Sjoerg */ 264025944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 264125944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 264225944Sjoerg (cps[i])->Down(sp); 264325944Sjoerg (cps[i])->Close(sp); 264425944Sjoerg } 264525944Sjoerg} 264625944Sjoerg 264725944Sjoergstatic void 264825944Sjoergsppp_lcp_tls(struct sppp *sp) 264925944Sjoerg{ 265042066Sphk STDDCL; 265125944Sjoerg 265225944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 265325944Sjoerg 265442066Sphk if (debug) 265542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 265642066Sphk sppp_phase_name(sp->pp_phase)); 265725944Sjoerg 265825944Sjoerg /* Notify lower layer if desired. */ 265925944Sjoerg if (sp->pp_tls) 266025944Sjoerg (sp->pp_tls)(sp); 266141881Sphk else 266241881Sphk (sp->pp_up)(sp); 266325944Sjoerg} 266425944Sjoerg 266525944Sjoergstatic void 266625944Sjoergsppp_lcp_tlf(struct sppp *sp) 266725944Sjoerg{ 266842066Sphk STDDCL; 266925944Sjoerg 267025944Sjoerg sp->pp_phase = PHASE_DEAD; 267142066Sphk if (debug) 267242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 267342066Sphk sppp_phase_name(sp->pp_phase)); 267425944Sjoerg 267525944Sjoerg /* Notify lower layer if desired. */ 267625944Sjoerg if (sp->pp_tlf) 267725944Sjoerg (sp->pp_tlf)(sp); 267841881Sphk else 267941881Sphk (sp->pp_down)(sp); 268025944Sjoerg} 268125944Sjoerg 268225944Sjoergstatic void 268325944Sjoergsppp_lcp_scr(struct sppp *sp) 268425944Sjoerg{ 268530300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 268625944Sjoerg int i = 0; 268730300Sjoerg u_short authproto; 268825944Sjoerg 268925944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 269025944Sjoerg if (! sp->lcp.magic) 269142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 269235064Sphk sp->lcp.magic = random(); 269340008Sjoerg#else 269440008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 269540008Sjoerg#endif 269625944Sjoerg opt[i++] = LCP_OPT_MAGIC; 269725944Sjoerg opt[i++] = 6; 269825944Sjoerg opt[i++] = sp->lcp.magic >> 24; 269925944Sjoerg opt[i++] = sp->lcp.magic >> 16; 270025944Sjoerg opt[i++] = sp->lcp.magic >> 8; 270125944Sjoerg opt[i++] = sp->lcp.magic; 270225944Sjoerg } 270325944Sjoerg 270425944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 270525944Sjoerg opt[i++] = LCP_OPT_MRU; 270625944Sjoerg opt[i++] = 4; 270725944Sjoerg opt[i++] = sp->lcp.mru >> 8; 270825944Sjoerg opt[i++] = sp->lcp.mru; 270925944Sjoerg } 271025944Sjoerg 271130300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 271230300Sjoerg authproto = sp->hisauth.proto; 271330300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 271430300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 271530300Sjoerg opt[i++] = authproto >> 8; 271630300Sjoerg opt[i++] = authproto; 271730300Sjoerg if (authproto == PPP_CHAP) 271830300Sjoerg opt[i++] = CHAP_MD5; 271930300Sjoerg } 272030300Sjoerg 272178064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 272225944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 272325944Sjoerg} 272425944Sjoerg 272525944Sjoerg/* 272630300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 272730300Sjoerg */ 272830300Sjoergstatic int 272930300Sjoergsppp_ncp_check(struct sppp *sp) 273030300Sjoerg{ 273130300Sjoerg int i, mask; 273230300Sjoerg 273330300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 273430300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 273530300Sjoerg return 1; 273630300Sjoerg return 0; 273730300Sjoerg} 273830300Sjoerg 273930300Sjoerg/* 274025944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 274125944Sjoerg * Called by the NCPs during their tlf action handling. 274225944Sjoerg */ 274325944Sjoergstatic void 274430300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 274525944Sjoerg{ 274625944Sjoerg 274730300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 274830300Sjoerg /* don't bother, we are already going down */ 274930300Sjoerg return; 275030300Sjoerg 275130300Sjoerg if (sppp_ncp_check(sp)) 275230300Sjoerg return; 275330300Sjoerg 275425944Sjoerg lcp.Close(sp); 275525944Sjoerg} 275670199Sjhay 275770199Sjhay/* 275825944Sjoerg *--------------------------------------------------------------------------* 275925944Sjoerg * * 276025944Sjoerg * The IPCP implementation. * 276125944Sjoerg * * 276225944Sjoerg *--------------------------------------------------------------------------* 276325944Sjoerg */ 276425944Sjoerg 276525944Sjoergstatic void 276625944Sjoergsppp_ipcp_init(struct sppp *sp) 276725944Sjoerg{ 276825944Sjoerg sp->ipcp.opts = 0; 276925944Sjoerg sp->ipcp.flags = 0; 277025944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 277125944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 277278064Sume sp->pp_seq[IDX_IPCP] = 0; 277378064Sume sp->pp_rseq[IDX_IPCP] = 0; 277442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 277529681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 277640008Sjoerg#endif 277725944Sjoerg} 277825944Sjoerg 277925944Sjoergstatic void 278025944Sjoergsppp_ipcp_up(struct sppp *sp) 278125944Sjoerg{ 278225944Sjoerg sppp_up_event(&ipcp, sp); 278325944Sjoerg} 278425944Sjoerg 278525944Sjoergstatic void 278625944Sjoergsppp_ipcp_down(struct sppp *sp) 278725944Sjoerg{ 278825944Sjoerg sppp_down_event(&ipcp, sp); 278925944Sjoerg} 279025944Sjoerg 279125944Sjoergstatic void 279225944Sjoergsppp_ipcp_open(struct sppp *sp) 279325944Sjoerg{ 279425944Sjoerg STDDCL; 279525944Sjoerg u_long myaddr, hisaddr; 279625944Sjoerg 279788534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 279888534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 279988700Sjoerg sp->ipcp.opts = 0; 280042104Sphk 280130300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 280225944Sjoerg /* 280325944Sjoerg * If we don't have his address, this probably means our 280425944Sjoerg * interface doesn't want to talk IP at all. (This could 280525944Sjoerg * be the case if somebody wants to speak only IPX, for 280625944Sjoerg * example.) Don't open IPCP in this case. 280725944Sjoerg */ 280825944Sjoerg if (hisaddr == 0L) { 280925944Sjoerg /* XXX this message should go away */ 281025944Sjoerg if (debug) 281140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 281240008Sjoerg SPP_ARGS(ifp)); 281325944Sjoerg return; 281425944Sjoerg } 281525944Sjoerg if (myaddr == 0L) { 281625944Sjoerg /* 281725944Sjoerg * I don't have an assigned address, so i need to 281825944Sjoerg * negotiate my address. 281925944Sjoerg */ 282025944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 282125944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 282242104Sphk } else 282342104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 282488534Sjoerg if (sp->enable_vj) { 282588534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 282688534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 282788534Sjoerg sp->ipcp.compress_cid = 1; 282888534Sjoerg } 282925944Sjoerg sppp_open_event(&ipcp, sp); 283025944Sjoerg} 283125944Sjoerg 283225944Sjoergstatic void 283325944Sjoergsppp_ipcp_close(struct sppp *sp) 283425944Sjoerg{ 283525944Sjoerg sppp_close_event(&ipcp, sp); 283625944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 283725944Sjoerg /* 283825944Sjoerg * My address was dynamic, clear it again. 283925944Sjoerg */ 284025944Sjoerg sppp_set_ip_addr(sp, 0L); 284125944Sjoerg} 284225944Sjoerg 284325944Sjoergstatic void 284425944Sjoergsppp_ipcp_TO(void *cookie) 284525944Sjoerg{ 284625944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 284725944Sjoerg} 284825944Sjoerg 284925944Sjoerg/* 285025944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 285125944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 285225944Sjoerg * caused action scn. (The return value is used to make the state 285325944Sjoerg * transition decision in the state automaton.) 285425944Sjoerg */ 285525944Sjoergstatic int 285625944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 285725944Sjoerg{ 285825944Sjoerg u_char *buf, *r, *p; 285925944Sjoerg struct ifnet *ifp = &sp->pp_if; 286025944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 286125944Sjoerg u_long hisaddr, desiredaddr; 286242104Sphk int gotmyaddr = 0; 286388534Sjoerg int desiredcomp; 286425944Sjoerg 286525944Sjoerg len -= 4; 286625944Sjoerg origlen = len; 286725944Sjoerg /* 286825944Sjoerg * Make sure to allocate a buf that can at least hold a 286925944Sjoerg * conf-nak with an `address' option. We might need it below. 287025944Sjoerg */ 287125944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 287225944Sjoerg if (! buf) 287325944Sjoerg return (0); 287425944Sjoerg 287525944Sjoerg /* pass 1: see if we can recognize them */ 287625944Sjoerg if (debug) 287740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 287840008Sjoerg SPP_ARGS(ifp)); 287925944Sjoerg p = (void*) (h+1); 288025944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 288125944Sjoerg if (debug) 288269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 288325944Sjoerg switch (*p) { 288488534Sjoerg case IPCP_OPT_COMPRESSION: 288588534Sjoerg if (!sp->enable_vj) { 288688534Sjoerg /* VJ compression administratively disabled */ 288788534Sjoerg if (debug) 288888534Sjoerg log(-1, "[locally disabled] "); 288988534Sjoerg break; 289088534Sjoerg } 289188534Sjoerg /* 289288534Sjoerg * In theory, we should only conf-rej an 289388534Sjoerg * option that is shorter than RFC 1618 289488534Sjoerg * requires (i.e. < 4), and should conf-nak 289588534Sjoerg * anything else that is not VJ. However, 289688534Sjoerg * since our algorithm always uses the 289788534Sjoerg * original option to NAK it with new values, 289888534Sjoerg * things would become more complicated. In 289988534Sjoerg * pratice, the only commonly implemented IP 290088534Sjoerg * compression option is VJ anyway, so the 290188534Sjoerg * difference is negligible. 290288534Sjoerg */ 290388534Sjoerg if (len >= 6 && p[1] == 6) { 290488534Sjoerg /* 290588534Sjoerg * correctly formed compression option 290688534Sjoerg * that could be VJ compression 290788534Sjoerg */ 290888534Sjoerg continue; 290988534Sjoerg } 291088534Sjoerg if (debug) 291188534Sjoerg log(-1, 291288534Sjoerg "optlen %d [invalid/unsupported] ", 291388534Sjoerg p[1]); 291488534Sjoerg break; 291525944Sjoerg case IPCP_OPT_ADDRESS: 291625944Sjoerg if (len >= 6 && p[1] == 6) { 291725944Sjoerg /* correctly formed address option */ 291825944Sjoerg continue; 291925944Sjoerg } 292025706Sjoerg if (debug) 292169211Sphk log(-1, "[invalid] "); 292211189Sjkh break; 292325944Sjoerg default: 292425944Sjoerg /* Others not supported. */ 292525944Sjoerg if (debug) 292669211Sphk log(-1, "[rej] "); 29274910Swollman break; 29284910Swollman } 292925944Sjoerg /* Add the option to rejected list. */ 293025944Sjoerg bcopy (p, r, p[1]); 293125944Sjoerg r += p[1]; 293225944Sjoerg rlen += p[1]; 293325944Sjoerg } 293425944Sjoerg if (rlen) { 293525944Sjoerg if (debug) 293669211Sphk log(-1, " send conf-rej\n"); 293725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 293825944Sjoerg return 0; 293925944Sjoerg } else if (debug) 294069211Sphk log(-1, "\n"); 294125944Sjoerg 294225944Sjoerg /* pass 2: parse option values */ 294330300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 294425944Sjoerg if (debug) 294540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 294640008Sjoerg SPP_ARGS(ifp)); 294725944Sjoerg p = (void*) (h+1); 294825944Sjoerg len = origlen; 294925944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 295025944Sjoerg if (debug) 295169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 295225944Sjoerg switch (*p) { 295388534Sjoerg case IPCP_OPT_COMPRESSION: 295488534Sjoerg desiredcomp = p[2] << 8 | p[3]; 295588534Sjoerg /* We only support VJ */ 295688534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 295788534Sjoerg if (debug) 295888534Sjoerg log(-1, "VJ [ack] "); 295988534Sjoerg sp->ipcp.flags |= IPCP_VJ; 296088599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 296188534Sjoerg sp->ipcp.max_state = p[4]; 296288534Sjoerg sp->ipcp.compress_cid = p[5]; 296388534Sjoerg continue; 296488534Sjoerg } 296588534Sjoerg if (debug) 296688534Sjoerg log(-1, 296788534Sjoerg "compproto %#04x [not supported] ", 296888534Sjoerg desiredcomp); 296988534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 297088534Sjoerg p[3] = IPCP_COMP_VJ; 297188534Sjoerg p[4] = sp->ipcp.max_state; 297288534Sjoerg p[5] = sp->ipcp.compress_cid; 297388534Sjoerg break; 297425944Sjoerg case IPCP_OPT_ADDRESS: 297542104Sphk /* This is the address he wants in his end */ 297625944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 297725944Sjoerg p[4] << 8 | p[5]; 297833928Sphk if (desiredaddr == hisaddr || 297988702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 298025944Sjoerg /* 298125944Sjoerg * Peer's address is same as our value, 298288702Sjoerg * or we have set it to 0.0.0.* to 298333928Sphk * indicate that we do not really care, 298425944Sjoerg * this is agreeable. Gonna conf-ack 298525944Sjoerg * it. 298625944Sjoerg */ 298725944Sjoerg if (debug) 298869211Sphk log(-1, "%s [ack] ", 298942104Sphk sppp_dotted_quad(hisaddr)); 299025944Sjoerg /* record that we've seen it already */ 299125944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 299225944Sjoerg continue; 299325944Sjoerg } 299425944Sjoerg /* 299525944Sjoerg * The address wasn't agreeable. This is either 299625944Sjoerg * he sent us 0.0.0.0, asking to assign him an 299725944Sjoerg * address, or he send us another address not 299825944Sjoerg * matching our value. Either case, we gonna 299925944Sjoerg * conf-nak it with our value. 300042104Sphk * XXX: we should "rej" if hisaddr == 0 300125944Sjoerg */ 300225944Sjoerg if (debug) { 300325944Sjoerg if (desiredaddr == 0) 300469211Sphk log(-1, "[addr requested] "); 300525944Sjoerg else 300669211Sphk log(-1, "%s [not agreed] ", 300742104Sphk sppp_dotted_quad(desiredaddr)); 300825944Sjoerg 300925944Sjoerg } 301044235Sphk p[2] = hisaddr >> 24; 301144235Sphk p[3] = hisaddr >> 16; 301244235Sphk p[4] = hisaddr >> 8; 301344235Sphk p[5] = hisaddr; 301411189Sjkh break; 301525706Sjoerg } 301625944Sjoerg /* Add the option to nak'ed list. */ 301725944Sjoerg bcopy (p, r, p[1]); 301825944Sjoerg r += p[1]; 301925944Sjoerg rlen += p[1]; 302025944Sjoerg } 302125944Sjoerg 302225944Sjoerg /* 302325944Sjoerg * If we are about to conf-ack the request, but haven't seen 302425944Sjoerg * his address so far, gonna conf-nak it instead, with the 302525944Sjoerg * `address' option present and our idea of his address being 302625944Sjoerg * filled in there, to request negotiation of both addresses. 302725944Sjoerg * 302825944Sjoerg * XXX This can result in an endless req - nak loop if peer 302925944Sjoerg * doesn't want to send us his address. Q: What should we do 303025944Sjoerg * about it? XXX A: implement the max-failure counter. 303125944Sjoerg */ 303242104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 303325944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 303425944Sjoerg buf[1] = 6; 303525944Sjoerg buf[2] = hisaddr >> 24; 303625944Sjoerg buf[3] = hisaddr >> 16; 303725944Sjoerg buf[4] = hisaddr >> 8; 303825944Sjoerg buf[5] = hisaddr; 303925944Sjoerg rlen = 6; 304025706Sjoerg if (debug) 304169211Sphk log(-1, "still need hisaddr "); 304225944Sjoerg } 304325944Sjoerg 304425944Sjoerg if (rlen) { 304525706Sjoerg if (debug) 304669211Sphk log(-1, " send conf-nak\n"); 304725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 304825944Sjoerg } else { 304925706Sjoerg if (debug) 305069211Sphk log(-1, " send conf-ack\n"); 305125944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 305225944Sjoerg h->ident, origlen, h+1); 305325944Sjoerg } 305425944Sjoerg 305525944Sjoerg free (buf, M_TEMP); 305625944Sjoerg return (rlen == 0); 305725944Sjoerg} 305825944Sjoerg 305925944Sjoerg/* 306025944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 306125944Sjoerg * negotiation. 306225944Sjoerg */ 306325944Sjoergstatic void 306425944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 306525944Sjoerg{ 306625944Sjoerg u_char *buf, *p; 306725944Sjoerg struct ifnet *ifp = &sp->pp_if; 306825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 306925944Sjoerg 307025944Sjoerg len -= 4; 307125944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 307225944Sjoerg if (!buf) 307325944Sjoerg return; 307425944Sjoerg 307525944Sjoerg if (debug) 307640008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 307740008Sjoerg SPP_ARGS(ifp)); 307825944Sjoerg 307925944Sjoerg p = (void*) (h+1); 308025944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 308125706Sjoerg if (debug) 308269211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 308325944Sjoerg switch (*p) { 308488534Sjoerg case IPCP_OPT_COMPRESSION: 308588534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 308688534Sjoerg break; 308725944Sjoerg case IPCP_OPT_ADDRESS: 308825944Sjoerg /* 308925944Sjoerg * Peer doesn't grok address option. This is 309025944Sjoerg * bad. XXX Should we better give up here? 309142104Sphk * XXX We could try old "addresses" option... 309225944Sjoerg */ 309325944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 309425944Sjoerg break; 309525944Sjoerg } 30964910Swollman } 309725944Sjoerg if (debug) 309869211Sphk log(-1, "\n"); 309925944Sjoerg free (buf, M_TEMP); 310025944Sjoerg return; 31014910Swollman} 31024910Swollman 310325944Sjoerg/* 310425944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 310525944Sjoerg * negotiation. 310625944Sjoerg */ 310712820Sphkstatic void 310825944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 31094910Swollman{ 311025944Sjoerg u_char *buf, *p; 311125944Sjoerg struct ifnet *ifp = &sp->pp_if; 311225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 311388534Sjoerg int desiredcomp; 311425944Sjoerg u_long wantaddr; 31154910Swollman 311625944Sjoerg len -= 4; 311725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 311825944Sjoerg if (!buf) 311925944Sjoerg return; 312025944Sjoerg 312125944Sjoerg if (debug) 312240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 312340008Sjoerg SPP_ARGS(ifp)); 312425944Sjoerg 312525944Sjoerg p = (void*) (h+1); 312625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 312725944Sjoerg if (debug) 312869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 312925944Sjoerg switch (*p) { 313088534Sjoerg case IPCP_OPT_COMPRESSION: 313188534Sjoerg if (len >= 6 && p[1] == 6) { 313288534Sjoerg desiredcomp = p[2] << 8 | p[3]; 313388534Sjoerg if (debug) 313488534Sjoerg log(-1, "[wantcomp %#04x] ", 313588534Sjoerg desiredcomp); 313688534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 313788599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 313888534Sjoerg sp->ipcp.max_state = p[4]; 313988534Sjoerg sp->ipcp.compress_cid = p[5]; 314088534Sjoerg if (debug) 314188534Sjoerg log(-1, "[agree] "); 314288534Sjoerg } else 314388534Sjoerg sp->ipcp.opts &= 314488534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 314588534Sjoerg } 314688534Sjoerg break; 314725944Sjoerg case IPCP_OPT_ADDRESS: 314825944Sjoerg /* 314925944Sjoerg * Peer doesn't like our local IP address. See 315025944Sjoerg * if we can do something for him. We'll drop 315125944Sjoerg * him our address then. 315225944Sjoerg */ 315325944Sjoerg if (len >= 6 && p[1] == 6) { 315425944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 315525944Sjoerg p[4] << 8 | p[5]; 315625944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 315725944Sjoerg if (debug) 315869211Sphk log(-1, "[wantaddr %s] ", 315930300Sjoerg sppp_dotted_quad(wantaddr)); 316025944Sjoerg /* 316125944Sjoerg * When doing dynamic address assignment, 316225944Sjoerg * we accept his offer. Otherwise, we 316325944Sjoerg * ignore it and thus continue to negotiate 316425944Sjoerg * our already existing value. 316542104Sphk * XXX: Bogus, if he said no once, he'll 316642104Sphk * just say no again, might as well die. 316725944Sjoerg */ 316825944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 316925944Sjoerg sppp_set_ip_addr(sp, wantaddr); 317025944Sjoerg if (debug) 317169211Sphk log(-1, "[agree] "); 317242104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 317325944Sjoerg } 317425944Sjoerg } 317525944Sjoerg break; 317625944Sjoerg } 317725944Sjoerg } 317825944Sjoerg if (debug) 317969211Sphk log(-1, "\n"); 318025944Sjoerg free (buf, M_TEMP); 318125944Sjoerg return; 31824910Swollman} 31834910Swollman 318412820Sphkstatic void 318525944Sjoergsppp_ipcp_tlu(struct sppp *sp) 31864910Swollman{ 318742104Sphk /* we are up - notify isdn daemon */ 318842104Sphk if (sp->pp_con) 318942104Sphk sp->pp_con(sp); 31904910Swollman} 31914910Swollman 319225944Sjoergstatic void 319325944Sjoergsppp_ipcp_tld(struct sppp *sp) 319425944Sjoerg{ 319525944Sjoerg} 319625944Sjoerg 319725944Sjoergstatic void 319825944Sjoergsppp_ipcp_tls(struct sppp *sp) 319925944Sjoerg{ 320025944Sjoerg /* indicate to LCP that it must stay alive */ 320125944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 320225944Sjoerg} 320325944Sjoerg 320425944Sjoergstatic void 320525944Sjoergsppp_ipcp_tlf(struct sppp *sp) 320625944Sjoerg{ 320725944Sjoerg /* we no longer need LCP */ 320825944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 320930300Sjoerg sppp_lcp_check_and_close(sp); 321025944Sjoerg} 321125944Sjoerg 321225944Sjoergstatic void 321325944Sjoergsppp_ipcp_scr(struct sppp *sp) 321425944Sjoerg{ 321525944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 321625944Sjoerg u_long ouraddr; 321725944Sjoerg int i = 0; 321825944Sjoerg 321988534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 322088534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 322188534Sjoerg opt[i++] = 6; 322288534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 322388534Sjoerg opt[i++] = IPCP_COMP_VJ; 322488534Sjoerg opt[i++] = sp->ipcp.max_state; 322588534Sjoerg opt[i++] = sp->ipcp.compress_cid; 322688534Sjoerg } 322725944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 322830300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 322925944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 323025944Sjoerg opt[i++] = 6; 323125944Sjoerg opt[i++] = ouraddr >> 24; 323225944Sjoerg opt[i++] = ouraddr >> 16; 323325944Sjoerg opt[i++] = ouraddr >> 8; 323425944Sjoerg opt[i++] = ouraddr; 323525944Sjoerg } 323625944Sjoerg 323778064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 323825944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 323925944Sjoerg} 324025944Sjoerg 324170199Sjhay/* 324230300Sjoerg *--------------------------------------------------------------------------* 324330300Sjoerg * * 324478064Sume * The IPv6CP implementation. * 324578064Sume * * 324678064Sume *--------------------------------------------------------------------------* 324778064Sume */ 324878064Sume 324978064Sume#ifdef INET6 325078064Sumestatic void 325178064Sumesppp_ipv6cp_init(struct sppp *sp) 325278064Sume{ 325378064Sume sp->ipv6cp.opts = 0; 325478064Sume sp->ipv6cp.flags = 0; 325578064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 325678064Sume sp->fail_counter[IDX_IPV6CP] = 0; 325778064Sume sp->pp_seq[IDX_IPV6CP] = 0; 325878064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 325978064Sume#if defined(__NetBSD__) 326078064Sume callout_init(&sp->ch[IDX_IPV6CP]); 326178064Sume#endif 326278064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 326378064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 326478064Sume#endif 326578064Sume} 326678064Sume 326778064Sumestatic void 326878064Sumesppp_ipv6cp_up(struct sppp *sp) 326978064Sume{ 327078064Sume sppp_up_event(&ipv6cp, sp); 327178064Sume} 327278064Sume 327378064Sumestatic void 327478064Sumesppp_ipv6cp_down(struct sppp *sp) 327578064Sume{ 327678064Sume sppp_down_event(&ipv6cp, sp); 327778064Sume} 327878064Sume 327978064Sumestatic void 328078064Sumesppp_ipv6cp_open(struct sppp *sp) 328178064Sume{ 328278064Sume STDDCL; 328378064Sume struct in6_addr myaddr, hisaddr; 328478064Sume 328578064Sume#ifdef IPV6CP_MYIFID_DYN 328678064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 328778064Sume#else 328878064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 328978064Sume#endif 329078064Sume 329178064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 329278064Sume /* 329378064Sume * If we don't have our address, this probably means our 329478064Sume * interface doesn't want to talk IPv6 at all. (This could 329578064Sume * be the case if somebody wants to speak only IPX, for 329678064Sume * example.) Don't open IPv6CP in this case. 329778064Sume */ 329878064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 329978064Sume /* XXX this message should go away */ 330078064Sume if (debug) 330178064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 330278064Sume SPP_ARGS(ifp)); 330378064Sume return; 330478064Sume } 330578064Sume 330678064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 330778064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 330878064Sume sppp_open_event(&ipv6cp, sp); 330978064Sume} 331078064Sume 331178064Sumestatic void 331278064Sumesppp_ipv6cp_close(struct sppp *sp) 331378064Sume{ 331478064Sume sppp_close_event(&ipv6cp, sp); 331578064Sume} 331678064Sume 331778064Sumestatic void 331878064Sumesppp_ipv6cp_TO(void *cookie) 331978064Sume{ 332078064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 332178064Sume} 332278064Sume 332378064Sume/* 332478064Sume * Analyze a configure request. Return true if it was agreeable, and 332578064Sume * caused action sca, false if it has been rejected or nak'ed, and 332678064Sume * caused action scn. (The return value is used to make the state 332778064Sume * transition decision in the state automaton.) 332878064Sume */ 332978064Sumestatic int 333078064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 333178064Sume{ 333278064Sume u_char *buf, *r, *p; 333378064Sume struct ifnet *ifp = &sp->pp_if; 333478064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 333578064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 333678064Sume int ifidcount; 333778064Sume int type; 333878064Sume int collision, nohisaddr; 333978064Sume 334078064Sume len -= 4; 334178064Sume origlen = len; 334278064Sume /* 334378064Sume * Make sure to allocate a buf that can at least hold a 334478064Sume * conf-nak with an `address' option. We might need it below. 334578064Sume */ 334678064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 334778064Sume if (! buf) 334878064Sume return (0); 334978064Sume 335078064Sume /* pass 1: see if we can recognize them */ 335178064Sume if (debug) 335278064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 335378064Sume SPP_ARGS(ifp)); 335478064Sume p = (void*) (h+1); 335578064Sume ifidcount = 0; 335678064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 335778064Sume if (debug) 335878176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 335978064Sume switch (*p) { 336078064Sume case IPV6CP_OPT_IFID: 336178064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 336278064Sume /* correctly formed address option */ 336378064Sume ifidcount++; 336478064Sume continue; 336578064Sume } 336678064Sume if (debug) 336778176Sume log(-1, " [invalid]"); 336878064Sume break; 336978064Sume#ifdef notyet 337078064Sume case IPV6CP_OPT_COMPRESSION: 337178064Sume if (len >= 4 && p[1] >= 4) { 337278064Sume /* correctly formed compress option */ 337378064Sume continue; 337478064Sume } 337578064Sume if (debug) 337678176Sume log(-1, " [invalid]"); 337778064Sume break; 337878064Sume#endif 337978064Sume default: 338078064Sume /* Others not supported. */ 338178064Sume if (debug) 338278176Sume log(-1, " [rej]"); 338378064Sume break; 338478064Sume } 338578064Sume /* Add the option to rejected list. */ 338678064Sume bcopy (p, r, p[1]); 338778064Sume r += p[1]; 338878064Sume rlen += p[1]; 338978064Sume } 339078064Sume if (rlen) { 339178064Sume if (debug) 339278176Sume log(-1, " send conf-rej\n"); 339378064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 339478064Sume goto end; 339578064Sume } else if (debug) 339678176Sume log(-1, "\n"); 339778064Sume 339878064Sume /* pass 2: parse option values */ 339978064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 340078064Sume if (debug) 340178064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 340278064Sume SPP_ARGS(ifp)); 340378064Sume p = (void*) (h+1); 340478064Sume len = origlen; 340578064Sume type = CONF_ACK; 340678064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 340778064Sume if (debug) 340878176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 340978064Sume switch (*p) { 341078064Sume#ifdef notyet 341178064Sume case IPV6CP_OPT_COMPRESSION: 341278064Sume continue; 341378064Sume#endif 341478064Sume case IPV6CP_OPT_IFID: 341578064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 341678064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 341778064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 341878064Sume &myaddr.s6_addr[8], 8) == 0); 341978064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 342078064Sume 342178064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 342278064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 342378064Sume 342478064Sume if (!collision && !nohisaddr) { 342578064Sume /* no collision, hisaddr known - Conf-Ack */ 342678064Sume type = CONF_ACK; 342778064Sume 342878064Sume if (debug) { 342978176Sume log(-1, " %s [%s]", 343078064Sume ip6_sprintf(&desiredaddr), 343178064Sume sppp_cp_type_name(type)); 343278064Sume } 343378064Sume continue; 343478064Sume } 343578064Sume 343678064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 343778064Sume if (collision && nohisaddr) { 343878064Sume /* collision, hisaddr unknown - Conf-Rej */ 343978064Sume type = CONF_REJ; 344078064Sume bzero(&p[2], 8); 344178064Sume } else { 344278064Sume /* 344378064Sume * - no collision, hisaddr unknown, or 344478064Sume * - collision, hisaddr known 344578064Sume * Conf-Nak, suggest hisaddr 344678064Sume */ 344778064Sume type = CONF_NAK; 344878064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 344978064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 345078064Sume } 345178064Sume if (debug) 345278176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 345378064Sume sppp_cp_type_name(type)); 345478064Sume break; 345578064Sume } 345678064Sume /* Add the option to nak'ed list. */ 345778064Sume bcopy (p, r, p[1]); 345878064Sume r += p[1]; 345978064Sume rlen += p[1]; 346078064Sume } 346178064Sume 346278064Sume if (rlen == 0 && type == CONF_ACK) { 346378064Sume if (debug) 346478176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 346578064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 346678064Sume } else { 346778064Sume#ifdef DIAGNOSTIC 346878064Sume if (type == CONF_ACK) 346978064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 347078064Sume#endif 347178064Sume 347278064Sume if (debug) { 347378176Sume log(-1, " send %s suggest %s\n", 347478064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 347578064Sume } 347678064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 347778064Sume } 347878064Sume 347978064Sume end: 348078064Sume free (buf, M_TEMP); 348178064Sume return (rlen == 0); 348278064Sume} 348378064Sume 348478064Sume/* 348578064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 348678064Sume * negotiation. 348778064Sume */ 348878064Sumestatic void 348978064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 349078064Sume{ 349178064Sume u_char *buf, *p; 349278064Sume struct ifnet *ifp = &sp->pp_if; 349378064Sume int debug = ifp->if_flags & IFF_DEBUG; 349478064Sume 349578064Sume len -= 4; 349678064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 349778064Sume if (!buf) 349878064Sume return; 349978064Sume 350078064Sume if (debug) 350178064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 350278064Sume SPP_ARGS(ifp)); 350378064Sume 350478064Sume p = (void*) (h+1); 350578064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 350678064Sume if (debug) 350778176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 350878064Sume switch (*p) { 350978064Sume case IPV6CP_OPT_IFID: 351078064Sume /* 351178064Sume * Peer doesn't grok address option. This is 351278064Sume * bad. XXX Should we better give up here? 351378064Sume */ 351478064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 351578064Sume break; 351678064Sume#ifdef notyet 351778064Sume case IPV6CP_OPT_COMPRESS: 351878064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 351978064Sume break; 352078064Sume#endif 352178064Sume } 352278064Sume } 352378064Sume if (debug) 352478176Sume log(-1, "\n"); 352578064Sume free (buf, M_TEMP); 352678064Sume return; 352778064Sume} 352878064Sume 352978064Sume/* 353078064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 353178064Sume * negotiation. 353278064Sume */ 353378064Sumestatic void 353478064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 353578064Sume{ 353678064Sume u_char *buf, *p; 353778064Sume struct ifnet *ifp = &sp->pp_if; 353878064Sume int debug = ifp->if_flags & IFF_DEBUG; 353978064Sume struct in6_addr suggestaddr; 354078064Sume 354178064Sume len -= 4; 354278064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 354378064Sume if (!buf) 354478064Sume return; 354578064Sume 354678064Sume if (debug) 354778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 354878064Sume SPP_ARGS(ifp)); 354978064Sume 355078064Sume p = (void*) (h+1); 355178064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 355278064Sume if (debug) 355378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 355478064Sume switch (*p) { 355578064Sume case IPV6CP_OPT_IFID: 355678064Sume /* 355778064Sume * Peer doesn't like our local ifid. See 355878064Sume * if we can do something for him. We'll drop 355978064Sume * him our address then. 356078064Sume */ 356178064Sume if (len < 10 || p[1] != 10) 356278064Sume break; 356378064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 356478064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 356578064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 356678064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 356778064Sume 356878064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 356978064Sume if (debug) 357078176Sume log(-1, " [suggestaddr %s]", 357178064Sume ip6_sprintf(&suggestaddr)); 357278064Sume#ifdef IPV6CP_MYIFID_DYN 357378064Sume /* 357478064Sume * When doing dynamic address assignment, 357578064Sume * we accept his offer. 357678064Sume */ 357778064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 357878064Sume struct in6_addr lastsuggest; 357978064Sume /* 358078064Sume * If <suggested myaddr from peer> equals to 358178064Sume * <hisaddr we have suggested last time>, 358278064Sume * we have a collision. generate new random 358378064Sume * ifid. 358478064Sume */ 358578064Sume sppp_suggest_ip6_addr(&lastsuggest); 358678064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 358778064Sume lastsuggest)) { 358878064Sume if (debug) 358978176Sume log(-1, " [random]"); 359078064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 359178064Sume } 359278064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 359378064Sume if (debug) 359478176Sume log(-1, " [agree]"); 359578064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 359678064Sume } 359778064Sume#else 359878064Sume /* 359978064Sume * Since we do not do dynamic address assignment, 360078064Sume * we ignore it and thus continue to negotiate 360178064Sume * our already existing value. This can possibly 360278064Sume * go into infinite request-reject loop. 360378064Sume * 360478064Sume * This is not likely because we normally use 360578064Sume * ifid based on MAC-address. 360678064Sume * If you have no ethernet card on the node, too bad. 360778064Sume * XXX should we use fail_counter? 360878064Sume */ 360978064Sume#endif 361078064Sume break; 361178064Sume#ifdef notyet 361278064Sume case IPV6CP_OPT_COMPRESS: 361378064Sume /* 361478064Sume * Peer wants different compression parameters. 361578064Sume */ 361678064Sume break; 361778064Sume#endif 361878064Sume } 361978064Sume } 362078064Sume if (debug) 362178176Sume log(-1, "\n"); 362278064Sume free (buf, M_TEMP); 362378064Sume return; 362478064Sume} 362578064Sumestatic void 362678064Sumesppp_ipv6cp_tlu(struct sppp *sp) 362778064Sume{ 362878064Sume /* we are up - notify isdn daemon */ 362978064Sume if (sp->pp_con) 363078064Sume sp->pp_con(sp); 363178064Sume} 363278064Sume 363378064Sumestatic void 363478064Sumesppp_ipv6cp_tld(struct sppp *sp) 363578064Sume{ 363678064Sume} 363778064Sume 363878064Sumestatic void 363978064Sumesppp_ipv6cp_tls(struct sppp *sp) 364078064Sume{ 364178064Sume /* indicate to LCP that it must stay alive */ 364278064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 364378064Sume} 364478064Sume 364578064Sumestatic void 364678064Sumesppp_ipv6cp_tlf(struct sppp *sp) 364778064Sume{ 364878064Sume 364978064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 365078064Sume /* we no longer need LCP */ 365178064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 365278064Sume sppp_lcp_check_and_close(sp); 365378064Sume#endif 365478064Sume} 365578064Sume 365678064Sumestatic void 365778064Sumesppp_ipv6cp_scr(struct sppp *sp) 365878064Sume{ 365978064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 366078064Sume struct in6_addr ouraddr; 366178064Sume int i = 0; 366278064Sume 366378064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 366478064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 366578064Sume opt[i++] = IPV6CP_OPT_IFID; 366678064Sume opt[i++] = 10; 366778064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 366878064Sume i += 8; 366978064Sume } 367078064Sume 367178064Sume#ifdef notyet 367278064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 367378064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 367478064Sume opt[i++] = 4; 367578064Sume opt[i++] = 0; /* TBD */ 367678064Sume opt[i++] = 0; /* TBD */ 367778064Sume /* variable length data may follow */ 367878064Sume } 367978064Sume#endif 368078064Sume 368178064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 368278064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 368378064Sume} 368478064Sume#else /*INET6*/ 368578064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 368678064Sume{ 368778064Sume} 368878064Sume 368978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 369078064Sume{ 369178064Sume} 369278064Sume 369378064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 369478064Sume{ 369578064Sume} 369678064Sume 369778064Sume 369878064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 369978064Sume{ 370078064Sume} 370178064Sume 370278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 370378064Sume{ 370478064Sume} 370578064Sume 370678064Sumestatic void sppp_ipv6cp_TO(void *sp) 370778064Sume{ 370878064Sume} 370978064Sume 371078064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 371178064Sume{ 371278064Sume return 0; 371378064Sume} 371478064Sume 371578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 371678064Sume{ 371778064Sume} 371878064Sume 371978064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 372078064Sume{ 372178064Sume} 372278064Sume 372378064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 372478064Sume{ 372578064Sume} 372678064Sume 372778064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 372878064Sume{ 372978064Sume} 373078064Sume 373178064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 373278064Sume{ 373378064Sume} 373478064Sume 373578064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 373678064Sume{ 373778064Sume} 373878064Sume 373978064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 374078064Sume{ 374178064Sume} 374278064Sume#endif /*INET6*/ 374378064Sume 374478064Sume/* 374578064Sume *--------------------------------------------------------------------------* 374678064Sume * * 374730300Sjoerg * The CHAP implementation. * 374830300Sjoerg * * 374930300Sjoerg *--------------------------------------------------------------------------* 375030300Sjoerg */ 375130300Sjoerg 375230300Sjoerg/* 375330300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 375430300Sjoerg * the control protocols do, since they do have Open and Close events, but 375530300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 375630300Sjoerg * authentication protocols may be different in both directions (this makes 375730300Sjoerg * sense, think of a machine that never accepts incoming calls but only 375830300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 375930300Sjoerg * 376030300Sjoerg * Our state machine for the local authentication protocol (we are requesting 376130300Sjoerg * the peer to authenticate) looks like: 376230300Sjoerg * 376330300Sjoerg * RCA- 376430300Sjoerg * +--------------------------------------------+ 376530300Sjoerg * V scn,tld| 376630300Sjoerg * +--------+ Close +---------+ RCA+ 376730300Sjoerg * | |<----------------------------------| |------+ 376830300Sjoerg * +--->| Closed | TO* | Opened | sca | 376930300Sjoerg * | | |-----+ +-------| |<-----+ 377030300Sjoerg * | +--------+ irc | | +---------+ 377130300Sjoerg * | ^ | | ^ 377230300Sjoerg * | | | | | 377330300Sjoerg * | | | | | 377430300Sjoerg * | TO-| | | | 377530300Sjoerg * | |tld TO+ V | | 377630300Sjoerg * | | +------->+ | | 377730300Sjoerg * | | | | | | 377830300Sjoerg * | +--------+ V | | 377930300Sjoerg * | | |<----+<--------------------+ | 378030300Sjoerg * | | Req- | scr | 378130300Sjoerg * | | Sent | | 378230300Sjoerg * | | | | 378330300Sjoerg * | +--------+ | 378430300Sjoerg * | RCA- | | RCA+ | 378530300Sjoerg * +------+ +------------------------------------------+ 378630300Sjoerg * scn,tld sca,irc,ict,tlu 378730300Sjoerg * 378830300Sjoerg * 378930300Sjoerg * with: 379030300Sjoerg * 379130300Sjoerg * Open: LCP reached authentication phase 379230300Sjoerg * Close: LCP reached terminate phase 379330300Sjoerg * 379430300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 379530300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 379630300Sjoerg * TO+: timeout with restart counter >= 0 379730300Sjoerg * TO-: timeout with restart counter < 0 379830300Sjoerg * TO*: reschedule timeout for CHAP 379930300Sjoerg * 380030300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 380130300Sjoerg * sca: send ack packet (pap-ack, chap-success) 380230300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 380330300Sjoerg * ict: initialize re-challenge timer (CHAP only) 380430300Sjoerg * 380530300Sjoerg * tlu: this-layer-up, LCP reaches network phase 380630300Sjoerg * tld: this-layer-down, LCP enters terminate phase 380730300Sjoerg * 380830300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 380930300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 381030300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 381130300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 381230300Sjoerg * causing LCP to enter terminate phase. 381330300Sjoerg * 381430300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 381530300Sjoerg * expected to send one based on the successful negotiation of PAP as 381630300Sjoerg * the authentication protocol during the LCP option negotiation. 381730300Sjoerg * 381830300Sjoerg * Incoming authentication protocol requests (remote requests 381930300Sjoerg * authentication, we are peer) don't employ a state machine at all, 382030300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 382130300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 382230300Sjoerg * still in authentication phase (thereby violating the standard that 382330300Sjoerg * demands that these NCP packets are to be discarded), so we keep 382430300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 382530300Sjoerg * phase network once we've seen a positive acknowledge for the 382630300Sjoerg * authentication. 382730300Sjoerg */ 382830300Sjoerg 382930300Sjoerg/* 383030300Sjoerg * Handle incoming CHAP packets. 383130300Sjoerg */ 383230300Sjoergvoid 383330300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 383430300Sjoerg{ 383530300Sjoerg STDDCL; 383630300Sjoerg struct lcp_header *h; 383730300Sjoerg int len, x; 383830300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 383930300Sjoerg int value_len, name_len; 384030300Sjoerg MD5_CTX ctx; 384130300Sjoerg 384230300Sjoerg len = m->m_pkthdr.len; 384330300Sjoerg if (len < 4) { 384430300Sjoerg if (debug) 384530300Sjoerg log(LOG_DEBUG, 384640008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 384740008Sjoerg SPP_ARGS(ifp), len); 384830300Sjoerg return; 384930300Sjoerg } 385030300Sjoerg h = mtod (m, struct lcp_header*); 385130300Sjoerg if (len > ntohs (h->len)) 385230300Sjoerg len = ntohs (h->len); 385330300Sjoerg 385430300Sjoerg switch (h->type) { 385530300Sjoerg /* challenge, failure and success are his authproto */ 385630300Sjoerg case CHAP_CHALLENGE: 385730300Sjoerg value = 1 + (u_char*)(h+1); 385830300Sjoerg value_len = value[-1]; 385930300Sjoerg name = value + value_len; 386030300Sjoerg name_len = len - value_len - 5; 386130300Sjoerg if (name_len < 0) { 386230300Sjoerg if (debug) { 386330300Sjoerg log(LOG_DEBUG, 386440008Sjoerg SPP_FMT "chap corrupted challenge " 386530300Sjoerg "<%s id=0x%x len=%d", 386640008Sjoerg SPP_ARGS(ifp), 386730300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 386830300Sjoerg h->ident, ntohs(h->len)); 386944145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 387069211Sphk log(-1, ">\n"); 387130300Sjoerg } 387230300Sjoerg break; 387330300Sjoerg } 387470199Sjhay 387530300Sjoerg if (debug) { 387630300Sjoerg log(LOG_DEBUG, 387740008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 387840008Sjoerg SPP_ARGS(ifp), 387930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 388030300Sjoerg ntohs(h->len)); 388130300Sjoerg sppp_print_string((char*) name, name_len); 388269211Sphk log(-1, " value-size=%d value=", value_len); 388330300Sjoerg sppp_print_bytes(value, value_len); 388469211Sphk log(-1, ">\n"); 388530300Sjoerg } 388630300Sjoerg 388730300Sjoerg /* Compute reply value. */ 388830300Sjoerg MD5Init(&ctx); 388930300Sjoerg MD5Update(&ctx, &h->ident, 1); 389030300Sjoerg MD5Update(&ctx, sp->myauth.secret, 389130300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 389230300Sjoerg MD5Update(&ctx, value, value_len); 389330300Sjoerg MD5Final(digest, &ctx); 389430300Sjoerg dsize = sizeof digest; 389530300Sjoerg 389630300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 389730300Sjoerg sizeof dsize, (const char *)&dsize, 389830300Sjoerg sizeof digest, digest, 389940008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 390030300Sjoerg sp->myauth.name, 390130300Sjoerg 0); 390230300Sjoerg break; 390330300Sjoerg 390430300Sjoerg case CHAP_SUCCESS: 390530300Sjoerg if (debug) { 390640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 390740008Sjoerg SPP_ARGS(ifp)); 390830300Sjoerg if (len > 4) { 390969211Sphk log(-1, ": "); 391030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 391130300Sjoerg } 391269211Sphk log(-1, "\n"); 391330300Sjoerg } 391430300Sjoerg x = splimp(); 391530300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 391630300Sjoerg if (sp->myauth.proto == PPP_CHAP && 391732169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 391830300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 391930300Sjoerg /* 392030300Sjoerg * We are authenticator for CHAP but didn't 392130300Sjoerg * complete yet. Leave it to tlu to proceed 392230300Sjoerg * to network phase. 392330300Sjoerg */ 392430300Sjoerg splx(x); 392530300Sjoerg break; 392630300Sjoerg } 392730300Sjoerg splx(x); 392830300Sjoerg sppp_phase_network(sp); 392930300Sjoerg break; 393030300Sjoerg 393130300Sjoerg case CHAP_FAILURE: 393230300Sjoerg if (debug) { 393340008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 393440008Sjoerg SPP_ARGS(ifp)); 393530300Sjoerg if (len > 4) { 393669211Sphk log(-1, ": "); 393730300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 393830300Sjoerg } 393969211Sphk log(-1, "\n"); 394030300Sjoerg } else 394140008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 394240008Sjoerg SPP_ARGS(ifp)); 394330300Sjoerg /* await LCP shutdown by authenticator */ 394430300Sjoerg break; 394530300Sjoerg 394630300Sjoerg /* response is my authproto */ 394730300Sjoerg case CHAP_RESPONSE: 394830300Sjoerg value = 1 + (u_char*)(h+1); 394930300Sjoerg value_len = value[-1]; 395030300Sjoerg name = value + value_len; 395130300Sjoerg name_len = len - value_len - 5; 395230300Sjoerg if (name_len < 0) { 395330300Sjoerg if (debug) { 395430300Sjoerg log(LOG_DEBUG, 395540008Sjoerg SPP_FMT "chap corrupted response " 395630300Sjoerg "<%s id=0x%x len=%d", 395740008Sjoerg SPP_ARGS(ifp), 395830300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 395930300Sjoerg h->ident, ntohs(h->len)); 396044145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 396169211Sphk log(-1, ">\n"); 396230300Sjoerg } 396330300Sjoerg break; 396430300Sjoerg } 396530300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 396630300Sjoerg if (debug) 396730300Sjoerg log(LOG_DEBUG, 396840008Sjoerg SPP_FMT "chap dropping response for old ID " 396930300Sjoerg "(got %d, expected %d)\n", 397040008Sjoerg SPP_ARGS(ifp), 397130300Sjoerg h->ident, sp->confid[IDX_CHAP]); 397230300Sjoerg break; 397330300Sjoerg } 397430300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 397530300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 397640008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 397740008Sjoerg SPP_ARGS(ifp)); 397830300Sjoerg sppp_print_string(name, name_len); 397969211Sphk log(-1, " != expected "); 398030300Sjoerg sppp_print_string(sp->hisauth.name, 398130300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 398269211Sphk log(-1, "\n"); 398370199Sjhay } 398430300Sjoerg if (debug) { 398540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 398630300Sjoerg "<%s id=0x%x len=%d name=", 398740008Sjoerg SPP_ARGS(ifp), 398830300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 398930300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 399030300Sjoerg h->ident, ntohs (h->len)); 399130300Sjoerg sppp_print_string((char*)name, name_len); 399269211Sphk log(-1, " value-size=%d value=", value_len); 399330300Sjoerg sppp_print_bytes(value, value_len); 399469211Sphk log(-1, ">\n"); 399530300Sjoerg } 399630300Sjoerg if (value_len != AUTHKEYLEN) { 399730300Sjoerg if (debug) 399830300Sjoerg log(LOG_DEBUG, 399940008Sjoerg SPP_FMT "chap bad hash value length: " 400030300Sjoerg "%d bytes, should be %d\n", 400140008Sjoerg SPP_ARGS(ifp), value_len, 400230300Sjoerg AUTHKEYLEN); 400330300Sjoerg break; 400430300Sjoerg } 400530300Sjoerg 400630300Sjoerg MD5Init(&ctx); 400730300Sjoerg MD5Update(&ctx, &h->ident, 1); 400830300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 400930300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 401030300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 401130300Sjoerg MD5Final(digest, &ctx); 401230300Sjoerg 401330300Sjoerg#define FAILMSG "Failed..." 401430300Sjoerg#define SUCCMSG "Welcome!" 401530300Sjoerg 401630300Sjoerg if (value_len != sizeof digest || 401730300Sjoerg bcmp(digest, value, value_len) != 0) { 401830300Sjoerg /* action scn, tld */ 401930300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 402030300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 402130300Sjoerg 0); 402230300Sjoerg chap.tld(sp); 402330300Sjoerg break; 402430300Sjoerg } 402530300Sjoerg /* action sca, perhaps tlu */ 402630300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 402730300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 402830300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 402930300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 403030300Sjoerg 0); 403130300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 403230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 403330300Sjoerg chap.tlu(sp); 403430300Sjoerg } 403530300Sjoerg break; 403630300Sjoerg 403730300Sjoerg default: 403830300Sjoerg /* Unknown CHAP packet type -- ignore. */ 403930300Sjoerg if (debug) { 404040008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 404130300Sjoerg "<0x%x id=0x%xh len=%d", 404240008Sjoerg SPP_ARGS(ifp), 404330300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 404430300Sjoerg h->type, h->ident, ntohs(h->len)); 404544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 404669211Sphk log(-1, ">\n"); 404730300Sjoerg } 404830300Sjoerg break; 404930300Sjoerg 405030300Sjoerg } 405130300Sjoerg} 405230300Sjoerg 405330300Sjoergstatic void 405430300Sjoergsppp_chap_init(struct sppp *sp) 405530300Sjoerg{ 405630300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 405730300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 405830300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 405978064Sume sp->pp_seq[IDX_CHAP] = 0; 406078064Sume sp->pp_rseq[IDX_CHAP] = 0; 406142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 406230300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 406340008Sjoerg#endif 406430300Sjoerg} 406530300Sjoerg 406630300Sjoergstatic void 406730300Sjoergsppp_chap_open(struct sppp *sp) 406830300Sjoerg{ 406930300Sjoerg if (sp->myauth.proto == PPP_CHAP && 407030300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 407130300Sjoerg /* we are authenticator for CHAP, start it */ 407230300Sjoerg chap.scr(sp); 407330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 407430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 407530300Sjoerg } 407630300Sjoerg /* nothing to be done if we are peer, await a challenge */ 407730300Sjoerg} 407830300Sjoerg 407930300Sjoergstatic void 408030300Sjoergsppp_chap_close(struct sppp *sp) 408130300Sjoerg{ 408230300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 408330300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 408430300Sjoerg} 408530300Sjoerg 408630300Sjoergstatic void 408730300Sjoergsppp_chap_TO(void *cookie) 408830300Sjoerg{ 408930300Sjoerg struct sppp *sp = (struct sppp *)cookie; 409030300Sjoerg STDDCL; 409130300Sjoerg int s; 409230300Sjoerg 409330300Sjoerg s = splimp(); 409430300Sjoerg if (debug) 409540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 409640008Sjoerg SPP_ARGS(ifp), 409730300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 409830300Sjoerg sp->rst_counter[IDX_CHAP]); 409930300Sjoerg 410030300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 410130300Sjoerg /* TO- event */ 410230300Sjoerg switch (sp->state[IDX_CHAP]) { 410330300Sjoerg case STATE_REQ_SENT: 410430300Sjoerg chap.tld(sp); 410530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 410630300Sjoerg break; 410730300Sjoerg } 410830300Sjoerg else 410930300Sjoerg /* TO+ (or TO*) event */ 411030300Sjoerg switch (sp->state[IDX_CHAP]) { 411130300Sjoerg case STATE_OPENED: 411230300Sjoerg /* TO* event */ 411330300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 411430300Sjoerg /* fall through */ 411530300Sjoerg case STATE_REQ_SENT: 411630300Sjoerg chap.scr(sp); 411730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 411830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 411930300Sjoerg break; 412030300Sjoerg } 412130300Sjoerg 412230300Sjoerg splx(s); 412330300Sjoerg} 412430300Sjoerg 412530300Sjoergstatic void 412630300Sjoergsppp_chap_tlu(struct sppp *sp) 412730300Sjoerg{ 412830300Sjoerg STDDCL; 412930300Sjoerg int i, x; 413030300Sjoerg 413140010Sjoerg i = 0; 413230300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 413330300Sjoerg 413430300Sjoerg /* 413530300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 413630300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 413730300Sjoerg * initial challenge-response exchange has taken place. 413830300Sjoerg * Provide for an option to avoid rechallenges. 413930300Sjoerg */ 414030300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 414130300Sjoerg /* 414230300Sjoerg * Compute the re-challenge timeout. This will yield 414330300Sjoerg * a number between 300 and 810 seconds. 414430300Sjoerg */ 414530300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 414642064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 414730300Sjoerg } 414830300Sjoerg 414930300Sjoerg if (debug) { 415030300Sjoerg log(LOG_DEBUG, 415140008Sjoerg SPP_FMT "chap %s, ", 415240008Sjoerg SPP_ARGS(ifp), 415330300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 415430300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 415569211Sphk log(-1, "next re-challenge in %d seconds\n", i); 415630300Sjoerg else 415769211Sphk log(-1, "re-challenging supressed\n"); 415830300Sjoerg } 415930300Sjoerg 416030300Sjoerg x = splimp(); 416130300Sjoerg /* indicate to LCP that we need to be closed down */ 416230300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 416330300Sjoerg 416430300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 416530300Sjoerg /* 416630300Sjoerg * Remote is authenticator, but his auth proto didn't 416730300Sjoerg * complete yet. Defer the transition to network 416830300Sjoerg * phase. 416930300Sjoerg */ 417030300Sjoerg splx(x); 417130300Sjoerg return; 417230300Sjoerg } 417330300Sjoerg splx(x); 417430300Sjoerg 417530300Sjoerg /* 417630300Sjoerg * If we are already in phase network, we are done here. This 417730300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 417830300Sjoerg */ 417930300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 418030300Sjoerg sppp_phase_network(sp); 418130300Sjoerg} 418230300Sjoerg 418330300Sjoergstatic void 418430300Sjoergsppp_chap_tld(struct sppp *sp) 418530300Sjoerg{ 418630300Sjoerg STDDCL; 418730300Sjoerg 418830300Sjoerg if (debug) 418940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 419040008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 419130300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 419230300Sjoerg 419330300Sjoerg lcp.Close(sp); 419430300Sjoerg} 419530300Sjoerg 419630300Sjoergstatic void 419730300Sjoergsppp_chap_scr(struct sppp *sp) 419830300Sjoerg{ 419930300Sjoerg u_long *ch, seed; 420030300Sjoerg u_char clen; 420130300Sjoerg 420230300Sjoerg /* Compute random challenge. */ 420330300Sjoerg ch = (u_long *)sp->myauth.challenge; 420442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 420535064Sphk read_random(&seed, sizeof seed); 420640008Sjoerg#else 420742104Sphk { 420842104Sphk struct timeval tv; 420940008Sjoerg microtime(&tv); 421040008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 421142104Sphk } 421240008Sjoerg#endif 421330300Sjoerg ch[0] = seed ^ random(); 421430300Sjoerg ch[1] = seed ^ random(); 421530300Sjoerg ch[2] = seed ^ random(); 421630300Sjoerg ch[3] = seed ^ random(); 421730300Sjoerg clen = AUTHKEYLEN; 421830300Sjoerg 421978064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 422030300Sjoerg 422130300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 422230300Sjoerg sizeof clen, (const char *)&clen, 422340008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 422440008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 422530300Sjoerg sp->myauth.name, 422630300Sjoerg 0); 422730300Sjoerg} 422870199Sjhay 422970199Sjhay/* 423030300Sjoerg *--------------------------------------------------------------------------* 423130300Sjoerg * * 423230300Sjoerg * The PAP implementation. * 423330300Sjoerg * * 423430300Sjoerg *--------------------------------------------------------------------------* 423530300Sjoerg */ 423630300Sjoerg/* 423730300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 423830300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 423930300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 424030300Sjoerg * retry counter is expired). 424130300Sjoerg */ 424230300Sjoerg 424330300Sjoerg/* 424430300Sjoerg * Handle incoming PAP packets. */ 424530300Sjoergstatic void 424630300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 424730300Sjoerg{ 424830300Sjoerg STDDCL; 424930300Sjoerg struct lcp_header *h; 425030300Sjoerg int len, x; 425130300Sjoerg u_char *name, *passwd, mlen; 425230300Sjoerg int name_len, passwd_len; 425330300Sjoerg 425430300Sjoerg len = m->m_pkthdr.len; 425530300Sjoerg if (len < 5) { 425630300Sjoerg if (debug) 425730300Sjoerg log(LOG_DEBUG, 425840008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 425940008Sjoerg SPP_ARGS(ifp), len); 426030300Sjoerg return; 426130300Sjoerg } 426230300Sjoerg h = mtod (m, struct lcp_header*); 426330300Sjoerg if (len > ntohs (h->len)) 426430300Sjoerg len = ntohs (h->len); 426530300Sjoerg switch (h->type) { 426630300Sjoerg /* PAP request is my authproto */ 426730300Sjoerg case PAP_REQ: 426830300Sjoerg name = 1 + (u_char*)(h+1); 426930300Sjoerg name_len = name[-1]; 427030300Sjoerg passwd = name + name_len + 1; 427130300Sjoerg if (name_len > len - 6 || 427230300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 427330300Sjoerg if (debug) { 427440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 427530300Sjoerg "<%s id=0x%x len=%d", 427640008Sjoerg SPP_ARGS(ifp), 427730300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 427830300Sjoerg h->ident, ntohs(h->len)); 427944145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 428069211Sphk log(-1, ">\n"); 428130300Sjoerg } 428230300Sjoerg break; 428330300Sjoerg } 428430300Sjoerg if (debug) { 428540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 428630300Sjoerg "<%s id=0x%x len=%d name=", 428740008Sjoerg SPP_ARGS(ifp), 428830300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 428930300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 429030300Sjoerg h->ident, ntohs(h->len)); 429130300Sjoerg sppp_print_string((char*)name, name_len); 429269211Sphk log(-1, " passwd="); 429330300Sjoerg sppp_print_string((char*)passwd, passwd_len); 429469211Sphk log(-1, ">\n"); 429530300Sjoerg } 429674774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 429774774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 429830300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 429930300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 430030300Sjoerg /* action scn, tld */ 430130300Sjoerg mlen = sizeof(FAILMSG) - 1; 430230300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 430330300Sjoerg sizeof mlen, (const char *)&mlen, 430430300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 430530300Sjoerg 0); 430630300Sjoerg pap.tld(sp); 430730300Sjoerg break; 430830300Sjoerg } 430930300Sjoerg /* action sca, perhaps tlu */ 431030300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 431130300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 431230300Sjoerg mlen = sizeof(SUCCMSG) - 1; 431330300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 431430300Sjoerg sizeof mlen, (const char *)&mlen, 431530300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 431630300Sjoerg 0); 431730300Sjoerg } 431830300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 431930300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 432030300Sjoerg pap.tlu(sp); 432130300Sjoerg } 432230300Sjoerg break; 432330300Sjoerg 432430300Sjoerg /* ack and nak are his authproto */ 432530300Sjoerg case PAP_ACK: 432640008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 432730300Sjoerg if (debug) { 432840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 432940008Sjoerg SPP_ARGS(ifp)); 433030300Sjoerg name_len = *((char *)h); 433130300Sjoerg if (len > 5 && name_len) { 433269211Sphk log(-1, ": "); 433330300Sjoerg sppp_print_string((char*)(h+1), name_len); 433430300Sjoerg } 433569211Sphk log(-1, "\n"); 433630300Sjoerg } 433730300Sjoerg x = splimp(); 433830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 433930300Sjoerg if (sp->myauth.proto == PPP_PAP && 434032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 434130300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 434230300Sjoerg /* 434330300Sjoerg * We are authenticator for PAP but didn't 434430300Sjoerg * complete yet. Leave it to tlu to proceed 434530300Sjoerg * to network phase. 434630300Sjoerg */ 434730300Sjoerg splx(x); 434830300Sjoerg break; 434930300Sjoerg } 435030300Sjoerg splx(x); 435130300Sjoerg sppp_phase_network(sp); 435230300Sjoerg break; 435330300Sjoerg 435430300Sjoerg case PAP_NAK: 435540008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 435630300Sjoerg if (debug) { 435740008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 435840008Sjoerg SPP_ARGS(ifp)); 435930300Sjoerg name_len = *((char *)h); 436030300Sjoerg if (len > 5 && name_len) { 436169211Sphk log(-1, ": "); 436230300Sjoerg sppp_print_string((char*)(h+1), name_len); 436330300Sjoerg } 436469211Sphk log(-1, "\n"); 436530300Sjoerg } else 436640008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 436740008Sjoerg SPP_ARGS(ifp)); 436830300Sjoerg /* await LCP shutdown by authenticator */ 436930300Sjoerg break; 437030300Sjoerg 437130300Sjoerg default: 437230300Sjoerg /* Unknown PAP packet type -- ignore. */ 437330300Sjoerg if (debug) { 437440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 437530300Sjoerg "<0x%x id=0x%x len=%d", 437640008Sjoerg SPP_ARGS(ifp), 437730300Sjoerg h->type, h->ident, ntohs(h->len)); 437844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 437969211Sphk log(-1, ">\n"); 438030300Sjoerg } 438130300Sjoerg break; 438230300Sjoerg 438330300Sjoerg } 438430300Sjoerg} 438530300Sjoerg 438630300Sjoergstatic void 438730300Sjoergsppp_pap_init(struct sppp *sp) 438830300Sjoerg{ 438930300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 439030300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 439130300Sjoerg sp->fail_counter[IDX_PAP] = 0; 439278064Sume sp->pp_seq[IDX_PAP] = 0; 439378064Sume sp->pp_rseq[IDX_PAP] = 0; 439442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 439530300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 439630300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 439740008Sjoerg#endif 439830300Sjoerg} 439930300Sjoerg 440030300Sjoergstatic void 440130300Sjoergsppp_pap_open(struct sppp *sp) 440230300Sjoerg{ 440330300Sjoerg if (sp->hisauth.proto == PPP_PAP && 440430300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 440530300Sjoerg /* we are authenticator for PAP, start our timer */ 440630300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 440730300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 440830300Sjoerg } 440930300Sjoerg if (sp->myauth.proto == PPP_PAP) { 441030300Sjoerg /* we are peer, send a request, and start a timer */ 441130300Sjoerg pap.scr(sp); 441242064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 441342064Sphk sp->pap_my_to_ch); 441430300Sjoerg } 441530300Sjoerg} 441630300Sjoerg 441730300Sjoergstatic void 441830300Sjoergsppp_pap_close(struct sppp *sp) 441930300Sjoerg{ 442030300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 442130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 442230300Sjoerg} 442330300Sjoerg 442430300Sjoerg/* 442530300Sjoerg * That's the timeout routine if we are authenticator. Since the 442630300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 442730300Sjoerg */ 442830300Sjoergstatic void 442930300Sjoergsppp_pap_TO(void *cookie) 443030300Sjoerg{ 443130300Sjoerg struct sppp *sp = (struct sppp *)cookie; 443230300Sjoerg STDDCL; 443330300Sjoerg int s; 443430300Sjoerg 443530300Sjoerg s = splimp(); 443630300Sjoerg if (debug) 443740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 443840008Sjoerg SPP_ARGS(ifp), 443930300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 444030300Sjoerg sp->rst_counter[IDX_PAP]); 444130300Sjoerg 444230300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 444330300Sjoerg /* TO- event */ 444430300Sjoerg switch (sp->state[IDX_PAP]) { 444530300Sjoerg case STATE_REQ_SENT: 444630300Sjoerg pap.tld(sp); 444730300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 444830300Sjoerg break; 444930300Sjoerg } 445030300Sjoerg else 445130300Sjoerg /* TO+ event, not very much we could do */ 445230300Sjoerg switch (sp->state[IDX_PAP]) { 445330300Sjoerg case STATE_REQ_SENT: 445430300Sjoerg /* sppp_cp_change_state() will restart the timer */ 445530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 445630300Sjoerg break; 445730300Sjoerg } 445830300Sjoerg 445930300Sjoerg splx(s); 446030300Sjoerg} 446130300Sjoerg 446230300Sjoerg/* 446330300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 446430300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 446530300Sjoerg * XXX We should impose a max counter. 446630300Sjoerg */ 446730300Sjoergstatic void 446830300Sjoergsppp_pap_my_TO(void *cookie) 446930300Sjoerg{ 447030300Sjoerg struct sppp *sp = (struct sppp *)cookie; 447130300Sjoerg STDDCL; 447230300Sjoerg 447330300Sjoerg if (debug) 447440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 447540008Sjoerg SPP_ARGS(ifp)); 447630300Sjoerg 447730300Sjoerg pap.scr(sp); 447830300Sjoerg} 447930300Sjoerg 448030300Sjoergstatic void 448130300Sjoergsppp_pap_tlu(struct sppp *sp) 448230300Sjoerg{ 448330300Sjoerg STDDCL; 448430300Sjoerg int x; 448530300Sjoerg 448630300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 448730300Sjoerg 448830300Sjoerg if (debug) 448940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 449040008Sjoerg SPP_ARGS(ifp), pap.name); 449130300Sjoerg 449230300Sjoerg x = splimp(); 449330300Sjoerg /* indicate to LCP that we need to be closed down */ 449430300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 449530300Sjoerg 449630300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 449730300Sjoerg /* 449830300Sjoerg * Remote is authenticator, but his auth proto didn't 449930300Sjoerg * complete yet. Defer the transition to network 450030300Sjoerg * phase. 450130300Sjoerg */ 450230300Sjoerg splx(x); 450330300Sjoerg return; 450430300Sjoerg } 450530300Sjoerg splx(x); 450630300Sjoerg sppp_phase_network(sp); 450730300Sjoerg} 450830300Sjoerg 450930300Sjoergstatic void 451030300Sjoergsppp_pap_tld(struct sppp *sp) 451130300Sjoerg{ 451230300Sjoerg STDDCL; 451330300Sjoerg 451430300Sjoerg if (debug) 451540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 451640008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 451740008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 451830300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 451930300Sjoerg 452030300Sjoerg lcp.Close(sp); 452130300Sjoerg} 452230300Sjoerg 452330300Sjoergstatic void 452430300Sjoergsppp_pap_scr(struct sppp *sp) 452530300Sjoerg{ 452630300Sjoerg u_char idlen, pwdlen; 452730300Sjoerg 452878064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 452930300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 453030300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 453130300Sjoerg 453230300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 453330300Sjoerg sizeof idlen, (const char *)&idlen, 453440008Sjoerg (size_t)idlen, sp->myauth.name, 453530300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 453640008Sjoerg (size_t)pwdlen, sp->myauth.secret, 453730300Sjoerg 0); 453830300Sjoerg} 453970199Sjhay 454070199Sjhay/* 454125944Sjoerg * Random miscellaneous functions. 454225944Sjoerg */ 454325944Sjoerg 45444910Swollman/* 454530300Sjoerg * Send a PAP or CHAP proto packet. 454630300Sjoerg * 454730300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 454840008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 454930300Sjoerg * mlen == 0. 455042104Sphk * NOTE: never declare variadic functions with types subject to type 455142104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 455242104Sphk * on the architecture you are on... 455330300Sjoerg */ 455430300Sjoerg 455530300Sjoergstatic void 455642104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 455742104Sphk unsigned int type, unsigned int id, 455830300Sjoerg ...) 455930300Sjoerg{ 456030300Sjoerg STDDCL; 456130300Sjoerg struct ppp_header *h; 456230300Sjoerg struct lcp_header *lh; 456330300Sjoerg struct mbuf *m; 456430300Sjoerg u_char *p; 456530300Sjoerg int len; 456642104Sphk unsigned int mlen; 456730300Sjoerg const char *msg; 456830300Sjoerg va_list ap; 456930300Sjoerg 457030300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 457130300Sjoerg if (! m) 457230300Sjoerg return; 457330300Sjoerg m->m_pkthdr.rcvif = 0; 457430300Sjoerg 457530300Sjoerg h = mtod (m, struct ppp_header*); 457630300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 457730300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 457830300Sjoerg h->protocol = htons(cp->proto); 457930300Sjoerg 458030300Sjoerg lh = (struct lcp_header*)(h + 1); 458130300Sjoerg lh->type = type; 458230300Sjoerg lh->ident = id; 458330300Sjoerg p = (u_char*) (lh+1); 458430300Sjoerg 458530300Sjoerg va_start(ap, id); 458630300Sjoerg len = 0; 458730300Sjoerg 458842104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 458930300Sjoerg msg = va_arg(ap, const char *); 459030300Sjoerg len += mlen; 459130300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 459230300Sjoerg va_end(ap); 459330300Sjoerg m_freem(m); 459430300Sjoerg return; 459530300Sjoerg } 459630300Sjoerg 459730300Sjoerg bcopy(msg, p, mlen); 459830300Sjoerg p += mlen; 459930300Sjoerg } 460030300Sjoerg va_end(ap); 460130300Sjoerg 460230300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 460330300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 460430300Sjoerg 460530300Sjoerg if (debug) { 460640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 460740008Sjoerg SPP_ARGS(ifp), cp->name, 460830300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 460930300Sjoerg lh->ident, ntohs(lh->len)); 461044145Sphk sppp_print_bytes((u_char*) (lh+1), len); 461169211Sphk log(-1, ">\n"); 461230300Sjoerg } 461369152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 461469152Sjlemon ifp->if_oerrors++; 461530300Sjoerg} 461630300Sjoerg 461730300Sjoerg/* 461825944Sjoerg * Flush interface queue. 46194910Swollman */ 462012820Sphkstatic void 462125944Sjoergsppp_qflush(struct ifqueue *ifq) 46224910Swollman{ 462325944Sjoerg struct mbuf *m, *n; 46244910Swollman 462525944Sjoerg n = ifq->ifq_head; 462625944Sjoerg while ((m = n)) { 462725944Sjoerg n = m->m_act; 462825944Sjoerg m_freem (m); 462911189Sjkh } 463025944Sjoerg ifq->ifq_head = 0; 463125944Sjoerg ifq->ifq_tail = 0; 463225944Sjoerg ifq->ifq_len = 0; 463325944Sjoerg} 463425944Sjoerg 463525944Sjoerg/* 463625944Sjoerg * Send keepalive packets, every 10 seconds. 463725944Sjoerg */ 463825944Sjoergstatic void 463925944Sjoergsppp_keepalive(void *dummy) 464025944Sjoerg{ 464125944Sjoerg struct sppp *sp; 464225944Sjoerg int s; 464325944Sjoerg 464425944Sjoerg s = splimp(); 464525944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 464625944Sjoerg struct ifnet *ifp = &sp->pp_if; 464725944Sjoerg 464825944Sjoerg /* Keepalive mode disabled or channel down? */ 464925944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 465025944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 465125944Sjoerg continue; 465225944Sjoerg 465325944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 465445152Sphk if (sp->pp_mode != IFF_CISCO && 465525944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 465625944Sjoerg continue; 465725944Sjoerg 465825944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 465925944Sjoerg /* No keepalive packets got. Stop the interface. */ 466040008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 466125944Sjoerg if_down (ifp); 466226018Sjoerg sppp_qflush (&sp->pp_cpq); 466345152Sphk if (sp->pp_mode != IFF_CISCO) { 466425944Sjoerg /* XXX */ 466525944Sjoerg /* Shut down the PPP link. */ 466625944Sjoerg lcp.Down(sp); 466725944Sjoerg /* Initiate negotiation. XXX */ 466825944Sjoerg lcp.Up(sp); 466925944Sjoerg } 46704910Swollman } 467125944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 467225944Sjoerg ++sp->pp_alivecnt; 467345152Sphk if (sp->pp_mode == IFF_CISCO) 467478064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 467578064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 467625944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 467725944Sjoerg long nmagic = htonl (sp->lcp.magic); 467878064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 467925944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 468025944Sjoerg sp->lcp.echoid, 4, &nmagic); 468125944Sjoerg } 46824910Swollman } 468325944Sjoerg splx(s); 468442064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 46854910Swollman} 46864910Swollman 468725944Sjoerg/* 468825944Sjoerg * Get both IP addresses. 468925944Sjoerg */ 469025944Sjoergstatic void 469130300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 469225944Sjoerg{ 469325944Sjoerg struct ifnet *ifp = &sp->pp_if; 469425944Sjoerg struct ifaddr *ifa; 469530300Sjoerg struct sockaddr_in *si, *sm; 469625944Sjoerg u_long ssrc, ddst; 469725944Sjoerg 469840010Sjoerg sm = NULL; 469925944Sjoerg ssrc = ddst = 0L; 470025944Sjoerg /* 470125944Sjoerg * Pick the first AF_INET address from the list, 470225944Sjoerg * aliases don't make any sense on a p2p link anyway. 470325944Sjoerg */ 470442065Sphk si = 0; 470542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 470642065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 470742104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 470871959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 470940008Sjoerg ifa; 471071959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 471142104Sphk#else 471242104Sphk for (ifa = ifp->if_addrlist; 471342104Sphk ifa; 471442104Sphk ifa = ifa->ifa_next) 471540008Sjoerg#endif 471625944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 471725944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 471830300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 471925944Sjoerg if (si) 472025944Sjoerg break; 472125944Sjoerg } 472225944Sjoerg if (ifa) { 472330300Sjoerg if (si && si->sin_addr.s_addr) { 472425944Sjoerg ssrc = si->sin_addr.s_addr; 472530300Sjoerg if (srcmask) 472630300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 472730300Sjoerg } 472825944Sjoerg 472925944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 473025944Sjoerg if (si && si->sin_addr.s_addr) 473125944Sjoerg ddst = si->sin_addr.s_addr; 473225944Sjoerg } 473325944Sjoerg 473425944Sjoerg if (dst) *dst = ntohl(ddst); 473525944Sjoerg if (src) *src = ntohl(ssrc); 473625944Sjoerg} 473725944Sjoerg 473825944Sjoerg/* 473925944Sjoerg * Set my IP address. Must be called at splimp. 474025944Sjoerg */ 474125944Sjoergstatic void 474225944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 474325944Sjoerg{ 474442104Sphk STDDCL; 474525944Sjoerg struct ifaddr *ifa; 474625944Sjoerg struct sockaddr_in *si; 474784318Sjlemon struct in_ifaddr *ia; 474825944Sjoerg 474925944Sjoerg /* 475025944Sjoerg * Pick the first AF_INET address from the list, 475125944Sjoerg * aliases don't make any sense on a p2p link anyway. 475225944Sjoerg */ 475342065Sphk si = 0; 475442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 475542065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 475642104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 475771959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 475840008Sjoerg ifa; 475971959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 476042104Sphk#else 476142104Sphk for (ifa = ifp->if_addrlist; 476242104Sphk ifa; 476342104Sphk ifa = ifa->ifa_next) 476440008Sjoerg#endif 476540008Sjoerg { 476640008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 476740008Sjoerg { 476825944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 476925944Sjoerg if (si) 477025944Sjoerg break; 477125944Sjoerg } 477240008Sjoerg } 477340008Sjoerg 477425944Sjoerg if (ifa && si) 477542104Sphk { 477642104Sphk int error; 477742104Sphk#if __NetBSD_Version__ >= 103080000 477842104Sphk struct sockaddr_in new_sin = *si; 477942104Sphk 478042104Sphk new_sin.sin_addr.s_addr = htonl(src); 478142104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 478242104Sphk if(debug && error) 478342104Sphk { 478442104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 478542104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 478642104Sphk } 478742104Sphk#else 478842104Sphk /* delete old route */ 478942104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 479042104Sphk if(debug && error) 479142104Sphk { 479242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 479342104Sphk SPP_ARGS(ifp), error); 479442104Sphk } 479542104Sphk 479642104Sphk /* set new address */ 479725944Sjoerg si->sin_addr.s_addr = htonl(src); 479884318Sjlemon ia = ifatoia(ifa); 479984318Sjlemon LIST_REMOVE(ia, ia_hash); 480084318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 480125944Sjoerg 480242104Sphk /* add new route */ 480370199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 480442104Sphk if (debug && error) 480542104Sphk { 480642104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 480742104Sphk SPP_ARGS(ifp), error); 480842104Sphk } 480942104Sphk#endif 481042104Sphk } 481188599Sjoerg} 481278064Sume 481378064Sume#ifdef INET6 481478064Sume/* 481578064Sume * Get both IPv6 addresses. 481678064Sume */ 481778064Sumestatic void 481878064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 481978064Sume struct in6_addr *srcmask) 482078064Sume{ 482178064Sume struct ifnet *ifp = &sp->pp_if; 482278064Sume struct ifaddr *ifa; 482378064Sume struct sockaddr_in6 *si, *sm; 482478064Sume struct in6_addr ssrc, ddst; 482578064Sume 482678064Sume sm = NULL; 482778064Sume bzero(&ssrc, sizeof(ssrc)); 482878064Sume bzero(&ddst, sizeof(ddst)); 482978064Sume /* 483078064Sume * Pick the first link-local AF_INET6 address from the list, 483178064Sume * aliases don't make any sense on a p2p link anyway. 483278064Sume */ 483378064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 483478064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 483578064Sume ifa; 483678064Sume ifa = ifa->ifa_link.tqe_next) 483778064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 483878064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 483978064Sume ifa; 484078064Sume ifa = ifa->ifa_list.tqe_next) 484178064Sume#else 484278064Sume for (ifa = ifp->if_addrlist, si = 0; 484378064Sume ifa; 484478064Sume ifa = ifa->ifa_next) 484578064Sume#endif 484678064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 484778064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 484878064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 484978064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 485078064Sume break; 485178064Sume } 485278064Sume if (ifa) { 485378064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 485478064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 485578064Sume if (srcmask) { 485678064Sume bcopy(&sm->sin6_addr, srcmask, 485778064Sume sizeof(*srcmask)); 485878064Sume } 485978064Sume } 486078064Sume 486178064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 486278064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 486378064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 486478064Sume } 486578064Sume 486678064Sume if (dst) 486778064Sume bcopy(&ddst, dst, sizeof(*dst)); 486878064Sume if (src) 486978064Sume bcopy(&ssrc, src, sizeof(*src)); 487070199Sjhay} 487142104Sphk 487278064Sume#ifdef IPV6CP_MYIFID_DYN 487378064Sume/* 487478064Sume * Generate random ifid. 487578064Sume */ 487678064Sumestatic void 487778064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 487878064Sume{ 487978064Sume /* TBD */ 488078064Sume} 488178064Sume 488278064Sume/* 488378064Sume * Set my IPv6 address. Must be called at splimp. 488478064Sume */ 488578064Sumestatic void 488678064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 488778064Sume{ 488878064Sume STDDCL; 488978064Sume struct ifaddr *ifa; 489078064Sume struct sockaddr_in6 *sin6; 489178064Sume 489278064Sume /* 489378064Sume * Pick the first link-local AF_INET6 address from the list, 489478064Sume * aliases don't make any sense on a p2p link anyway. 489578064Sume */ 489678064Sume 489778064Sume sin6 = NULL; 489878064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 489978064Sume for (ifa = ifp->if_addrhead.tqh_first; 490078064Sume ifa; 490178064Sume ifa = ifa->ifa_link.tqe_next) 490278064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 490378064Sume for (ifa = ifp->if_addrlist.tqh_first; 490478064Sume ifa; 490578064Sume ifa = ifa->ifa_list.tqe_next) 490678064Sume#else 490778064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 490878064Sume#endif 490978064Sume { 491078064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 491178064Sume { 491278064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 491378064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 491478064Sume break; 491578064Sume } 491678064Sume } 491778064Sume 491878064Sume if (ifa && sin6) 491978064Sume { 492078064Sume int error; 492178064Sume struct sockaddr_in6 new_sin6 = *sin6; 492278064Sume 492378064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 492478064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 492578064Sume if (debug && error) 492678064Sume { 492778064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 492878064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 492978064Sume } 493078064Sume } 493178064Sume} 493278064Sume#endif 493378064Sume 493478064Sume/* 493578064Sume * Suggest a candidate address to be used by peer. 493678064Sume */ 493778064Sumestatic void 493878064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 493978064Sume{ 494078064Sume struct in6_addr myaddr; 494178064Sume struct timeval tv; 494278064Sume 494378064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 494478064Sume 494578064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 494678064Sume microtime(&tv); 494778064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 494878064Sume myaddr.s6_addr[14] ^= 0xff; 494978064Sume myaddr.s6_addr[15] ^= 0xff; 495078064Sume } else { 495178064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 495278064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 495378064Sume } 495478064Sume if (suggest) 495578064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 495678064Sume} 495778064Sume#endif /*INET6*/ 495878064Sume 495930300Sjoergstatic int 496038343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 496130300Sjoerg{ 496238343Sbde u_long subcmd; 496330300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 496488600Sjoerg struct spppreq *spr; 496588600Sjoerg int rv = 0; 496630300Sjoerg 496788600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 496888600Sjoerg return (EAGAIN); 496930300Sjoerg /* 497030300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 497130300Sjoerg * Check the cmd word first before attempting to fetch all the 497230300Sjoerg * data. 497330300Sjoerg */ 497488600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 497588600Sjoerg rv = EFAULT; 497688600Sjoerg goto quit; 497788600Sjoerg } 497830300Sjoerg 497988600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 498088600Sjoerg rv = EFAULT; 498188600Sjoerg goto quit; 498288600Sjoerg } 498330300Sjoerg 498430300Sjoerg switch (subcmd) { 498530300Sjoerg case SPPPIOGDEFS: 498688600Sjoerg if (cmd != SIOCGIFGENERIC) { 498788600Sjoerg rv = EINVAL; 498888600Sjoerg break; 498988600Sjoerg } 499030300Sjoerg /* 499130300Sjoerg * We copy over the entire current state, but clean 499230300Sjoerg * out some of the stuff we don't wanna pass up. 499330300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 499430300Sjoerg * called by any user. No need to ever get PAP or 499530300Sjoerg * CHAP secrets back to userland anyway. 499630300Sjoerg */ 499788600Sjoerg spr->defs.pp_phase = sp->pp_phase; 499888600Sjoerg spr->defs.enable_vj = sp->enable_vj; 499988600Sjoerg spr->defs.lcp = sp->lcp; 500088600Sjoerg spr->defs.ipcp = sp->ipcp; 500188600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 500288600Sjoerg spr->defs.myauth = sp->myauth; 500388600Sjoerg spr->defs.hisauth = sp->hisauth; 500488600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 500588600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 500688600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 500788600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 500888550Sjoerg /* 500988550Sjoerg * Fixup the LCP timeout value to milliseconds so 501088550Sjoerg * spppcontrol doesn't need to bother about the value 501188550Sjoerg * of "hz". We do the reverse calculation below when 501288550Sjoerg * setting it. 501388550Sjoerg */ 501488600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 501588600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 501688600Sjoerg sizeof(struct spppreq)); 501788600Sjoerg break; 501830300Sjoerg 501930300Sjoerg case SPPPIOSDEFS: 502088600Sjoerg if (cmd != SIOCSIFGENERIC) { 502188600Sjoerg rv = EINVAL; 502288600Sjoerg break; 502388600Sjoerg } 502430300Sjoerg /* 502588550Sjoerg * We have a very specific idea of which fields we 502688550Sjoerg * allow being passed back from userland, so to not 502788550Sjoerg * clobber our current state. For one, we only allow 502888550Sjoerg * setting anything if LCP is in dead or establish 502988550Sjoerg * phase. Once the authentication negotiations 503088550Sjoerg * started, the authentication settings must not be 503188550Sjoerg * changed again. (The administrator can force an 503230300Sjoerg * ifconfig down in order to get LCP back into dead 503330300Sjoerg * phase.) 503430300Sjoerg * 503530300Sjoerg * Also, we only allow for authentication parameters to be 503630300Sjoerg * specified. 503730300Sjoerg * 503830300Sjoerg * XXX Should allow to set or clear pp_flags. 503930300Sjoerg * 504030300Sjoerg * Finally, if the respective authentication protocol to 504130300Sjoerg * be used is set differently than 0, but the secret is 504230300Sjoerg * passed as all zeros, we don't trash the existing secret. 504330300Sjoerg * This allows an administrator to change the system name 504430300Sjoerg * only without clobbering the secret (which he didn't get 504530300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 504630300Sjoerg * secrets are cleared if the authentication protocol is 504788550Sjoerg * reset to 0. */ 504888550Sjoerg if (sp->pp_phase != PHASE_DEAD && 504988600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 505088600Sjoerg rv = EBUSY; 505188600Sjoerg break; 505288600Sjoerg } 505330300Sjoerg 505488600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 505588600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 505688600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 505788600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 505888600Sjoerg rv = EINVAL; 505988600Sjoerg break; 506088600Sjoerg } 506130300Sjoerg 506288600Sjoerg if (spr->defs.myauth.proto == 0) 506330300Sjoerg /* resetting myauth */ 506430300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 506530300Sjoerg else { 506630300Sjoerg /* setting/changing myauth */ 506788600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 506888600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 506988600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 507088600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 507130300Sjoerg AUTHKEYLEN); 507230300Sjoerg } 507388600Sjoerg if (spr->defs.hisauth.proto == 0) 507430300Sjoerg /* resetting hisauth */ 507530300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 507630300Sjoerg else { 507730300Sjoerg /* setting/changing hisauth */ 507888600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 507988600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 508088600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 508188600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 508288600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 508330300Sjoerg AUTHKEYLEN); 508430300Sjoerg } 508588550Sjoerg /* set LCP restart timer timeout */ 508688600Sjoerg if (spr->defs.lcp.timeout != 0) 508788600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 508888534Sjoerg /* set VJ enable flag */ 508988600Sjoerg sp->enable_vj = spr->defs.enable_vj; 509030300Sjoerg break; 509130300Sjoerg 509230300Sjoerg default: 509388600Sjoerg rv = EINVAL; 509430300Sjoerg } 509530300Sjoerg 509688600Sjoerg quit: 509788600Sjoerg free(spr, M_TEMP); 509888600Sjoerg 509988600Sjoerg return (rv); 510030300Sjoerg} 510130300Sjoerg 510230300Sjoergstatic void 510330300Sjoergsppp_phase_network(struct sppp *sp) 510430300Sjoerg{ 510542066Sphk STDDCL; 510630300Sjoerg int i; 510730300Sjoerg u_long mask; 510830300Sjoerg 510930300Sjoerg sp->pp_phase = PHASE_NETWORK; 511030300Sjoerg 511142066Sphk if (debug) 511242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 511342066Sphk sppp_phase_name(sp->pp_phase)); 511430300Sjoerg 511530300Sjoerg /* Notify NCPs now. */ 511630300Sjoerg for (i = 0; i < IDX_COUNT; i++) 511730300Sjoerg if ((cps[i])->flags & CP_NCP) 511830300Sjoerg (cps[i])->Open(sp); 511930300Sjoerg 512030300Sjoerg /* Send Up events to all NCPs. */ 512130300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 512230300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 512330300Sjoerg (cps[i])->Up(sp); 512430300Sjoerg 512530300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 512630300Sjoerg sppp_lcp_check_and_close(sp); 512730300Sjoerg} 512830300Sjoerg 512970199Sjhay 513025706Sjoergstatic const char * 513125944Sjoergsppp_cp_type_name(u_char type) 51324910Swollman{ 513330300Sjoerg static char buf[12]; 51344910Swollman switch (type) { 513530300Sjoerg case CONF_REQ: return "conf-req"; 513630300Sjoerg case CONF_ACK: return "conf-ack"; 513730300Sjoerg case CONF_NAK: return "conf-nak"; 513830300Sjoerg case CONF_REJ: return "conf-rej"; 513930300Sjoerg case TERM_REQ: return "term-req"; 514030300Sjoerg case TERM_ACK: return "term-ack"; 514130300Sjoerg case CODE_REJ: return "code-rej"; 514230300Sjoerg case PROTO_REJ: return "proto-rej"; 514330300Sjoerg case ECHO_REQ: return "echo-req"; 514430300Sjoerg case ECHO_REPLY: return "echo-reply"; 514530300Sjoerg case DISC_REQ: return "discard-req"; 51464910Swollman } 514744145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 514830300Sjoerg return buf; 51494910Swollman} 51504910Swollman 515125706Sjoergstatic const char * 515230300Sjoergsppp_auth_type_name(u_short proto, u_char type) 515330300Sjoerg{ 515430300Sjoerg static char buf[12]; 515530300Sjoerg switch (proto) { 515630300Sjoerg case PPP_CHAP: 515730300Sjoerg switch (type) { 515830300Sjoerg case CHAP_CHALLENGE: return "challenge"; 515930300Sjoerg case CHAP_RESPONSE: return "response"; 516030300Sjoerg case CHAP_SUCCESS: return "success"; 516130300Sjoerg case CHAP_FAILURE: return "failure"; 516230300Sjoerg } 516330300Sjoerg case PPP_PAP: 516430300Sjoerg switch (type) { 516530300Sjoerg case PAP_REQ: return "req"; 516630300Sjoerg case PAP_ACK: return "ack"; 516730300Sjoerg case PAP_NAK: return "nak"; 516830300Sjoerg } 516930300Sjoerg } 517044145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 517130300Sjoerg return buf; 517230300Sjoerg} 517330300Sjoerg 517430300Sjoergstatic const char * 517525944Sjoergsppp_lcp_opt_name(u_char opt) 51764910Swollman{ 517730300Sjoerg static char buf[12]; 517825944Sjoerg switch (opt) { 517930300Sjoerg case LCP_OPT_MRU: return "mru"; 518030300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 518130300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 518230300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 518330300Sjoerg case LCP_OPT_MAGIC: return "magic"; 518430300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 518530300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 51864910Swollman } 518744145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 518830300Sjoerg return buf; 51894910Swollman} 51904910Swollman 519125944Sjoergstatic const char * 519225944Sjoergsppp_ipcp_opt_name(u_char opt) 519325944Sjoerg{ 519430300Sjoerg static char buf[12]; 519525944Sjoerg switch (opt) { 519630300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 519730300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 519830300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 519925944Sjoerg } 520044145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 520130300Sjoerg return buf; 520225944Sjoerg} 520325944Sjoerg 520478064Sume#ifdef INET6 520525944Sjoergstatic const char * 520678064Sumesppp_ipv6cp_opt_name(u_char opt) 520778064Sume{ 520878064Sume static char buf[12]; 520978064Sume switch (opt) { 521078064Sume case IPV6CP_OPT_IFID: return "ifid"; 521178064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 521278064Sume } 521378064Sume sprintf (buf, "0x%x", opt); 521478064Sume return buf; 521578064Sume} 521678064Sume#endif 521778064Sume 521878064Sumestatic const char * 521925944Sjoergsppp_state_name(int state) 522025944Sjoerg{ 522125944Sjoerg switch (state) { 522225944Sjoerg case STATE_INITIAL: return "initial"; 522325944Sjoerg case STATE_STARTING: return "starting"; 522425944Sjoerg case STATE_CLOSED: return "closed"; 522525944Sjoerg case STATE_STOPPED: return "stopped"; 522625944Sjoerg case STATE_CLOSING: return "closing"; 522725944Sjoerg case STATE_STOPPING: return "stopping"; 522825944Sjoerg case STATE_REQ_SENT: return "req-sent"; 522925944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 523025944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 523125944Sjoerg case STATE_OPENED: return "opened"; 523225944Sjoerg } 523325944Sjoerg return "illegal"; 523425944Sjoerg} 523525944Sjoerg 523625944Sjoergstatic const char * 523725944Sjoergsppp_phase_name(enum ppp_phase phase) 523825944Sjoerg{ 523925944Sjoerg switch (phase) { 524025944Sjoerg case PHASE_DEAD: return "dead"; 524125944Sjoerg case PHASE_ESTABLISH: return "establish"; 524225944Sjoerg case PHASE_TERMINATE: return "terminate"; 524325944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 524425944Sjoerg case PHASE_NETWORK: return "network"; 524525944Sjoerg } 524625944Sjoerg return "illegal"; 524725944Sjoerg} 524825944Sjoerg 524925944Sjoergstatic const char * 525025944Sjoergsppp_proto_name(u_short proto) 525125944Sjoerg{ 525225944Sjoerg static char buf[12]; 525325944Sjoerg switch (proto) { 525425944Sjoerg case PPP_LCP: return "lcp"; 525525944Sjoerg case PPP_IPCP: return "ipcp"; 525630300Sjoerg case PPP_PAP: return "pap"; 525730300Sjoerg case PPP_CHAP: return "chap"; 525878064Sume case PPP_IPV6CP: return "ipv6cp"; 525925944Sjoerg } 526044145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 526125944Sjoerg return buf; 526225944Sjoerg} 526325944Sjoerg 526412820Sphkstatic void 526530300Sjoergsppp_print_bytes(const u_char *p, u_short len) 52664910Swollman{ 526744145Sphk if (len) 526869211Sphk log(-1, " %*D", len, p, "-"); 52694910Swollman} 527025944Sjoerg 527130300Sjoergstatic void 527230300Sjoergsppp_print_string(const char *p, u_short len) 527330300Sjoerg{ 527430300Sjoerg u_char c; 527530300Sjoerg 527630300Sjoerg while (len-- > 0) { 527730300Sjoerg c = *p++; 527830300Sjoerg /* 527930300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 528030300Sjoerg * using only them, but we don't rely on it. */ 528130300Sjoerg if (c < ' ' || c > '~') 528269211Sphk log(-1, "\\x%x", c); 528330300Sjoerg else 528469211Sphk log(-1, "%c", c); 528530300Sjoerg } 528630300Sjoerg} 528730300Sjoerg 528830300Sjoergstatic const char * 528930300Sjoergsppp_dotted_quad(u_long addr) 529030300Sjoerg{ 529130300Sjoerg static char s[16]; 529230300Sjoerg sprintf(s, "%d.%d.%d.%d", 529340008Sjoerg (int)((addr >> 24) & 0xff), 529440008Sjoerg (int)((addr >> 16) & 0xff), 529540008Sjoerg (int)((addr >> 8) & 0xff), 529638372Sbde (int)(addr & 0xff)); 529730300Sjoerg return s; 529830300Sjoerg} 529930300Sjoerg 530030300Sjoergstatic int 530130300Sjoergsppp_strnlen(u_char *p, int max) 530230300Sjoerg{ 530330300Sjoerg int len; 530430300Sjoerg 530530300Sjoerg for (len = 0; len < max && *p; ++p) 530630300Sjoerg ++len; 530730300Sjoerg return len; 530830300Sjoerg} 530930300Sjoerg 531030300Sjoerg/* a dummy, used to drop uninteresting events */ 531130300Sjoergstatic void 531230300Sjoergsppp_null(struct sppp *unused) 531330300Sjoerg{ 531430300Sjoerg /* do just nothing */ 531530300Sjoerg} 5316