if_spppsubr.c revision 88550
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 88550 2001-12-27 21:20:05Z 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 8332350Seivind#else 8440008Sjoerg# error Huh? sppp without INET? 854910Swollman#endif 864910Swollman 8711819Sjulian#ifdef IPX 8811819Sjulian#include <netipx/ipx.h> 8911819Sjulian#include <netipx/ipx_if.h> 9011819Sjulian#endif 9111819Sjulian 924910Swollman#ifdef NS 934910Swollman#include <netns/ns.h> 944910Swollman#include <netns/ns_if.h> 954910Swollman#endif 964910Swollman 974910Swollman#include <net/if_sppp.h> 984910Swollman 9942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 10042064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 10142064Sphk# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 10242104Sphk# define IOCTL_CMD_T u_long 10340008Sjoerg#else 10442064Sphk# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 10542064Sphk# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 10642104Sphk# define IOCTL_CMD_T int 10740008Sjoerg#endif 10842104Sphk 1094910Swollman#define MAXALIVECNT 3 /* max. alive packets */ 1104910Swollman 11125944Sjoerg/* 11225944Sjoerg * Interface flags that can be set in an ifconfig command. 11325944Sjoerg * 11425955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked 11525944Sjoerg * as being administrative openable, but won't be opened to begin 11625944Sjoerg * with. Incoming calls will be answered, or subsequent calls with 11725944Sjoerg * -link1 will cause the administrative open of the LCP layer. 11825955Sjoerg * 11925955Sjoerg * Setting link1 will cause the link to auto-dial only as packets 12025955Sjoerg * arrive to be sent. 12130300Sjoerg * 12230300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state 12330300Sjoerg * transitions at level kern.debug. Note: all logs consistently look 12430300Sjoerg * like 12530300Sjoerg * 12630300Sjoerg * <if-name><unit>: <proto-name> <additional info...> 12730300Sjoerg * 12830300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name> 12930300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 13025944Sjoerg */ 13125944Sjoerg 13225955Sjoerg#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 13325955Sjoerg#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 13445152Sphk#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 13525944Sjoerg 13630300Sjoerg#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 13730300Sjoerg#define PPP_UI 0x03 /* Unnumbered Information */ 13830300Sjoerg#define PPP_IP 0x0021 /* Internet Protocol */ 13930300Sjoerg#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 14030300Sjoerg#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 14130300Sjoerg#define PPP_IPX 0x002b /* Novell IPX Protocol */ 14288534Sjoerg#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 14388534Sjoerg#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 14478064Sume#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 14530300Sjoerg#define PPP_LCP 0xc021 /* Link Control Protocol */ 14630300Sjoerg#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 14730300Sjoerg#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 14830300Sjoerg#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 14978064Sume#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 1504910Swollman 15125944Sjoerg#define CONF_REQ 1 /* PPP configure request */ 15225944Sjoerg#define CONF_ACK 2 /* PPP configure acknowledge */ 15325944Sjoerg#define CONF_NAK 3 /* PPP configure negative ack */ 15425944Sjoerg#define CONF_REJ 4 /* PPP configure reject */ 15525944Sjoerg#define TERM_REQ 5 /* PPP terminate request */ 15625944Sjoerg#define TERM_ACK 6 /* PPP terminate acknowledge */ 15725944Sjoerg#define CODE_REJ 7 /* PPP code reject */ 15825944Sjoerg#define PROTO_REJ 8 /* PPP protocol reject */ 15925944Sjoerg#define ECHO_REQ 9 /* PPP echo request */ 16025944Sjoerg#define ECHO_REPLY 10 /* PPP echo reply */ 16125944Sjoerg#define DISC_REQ 11 /* PPP discard request */ 1624910Swollman 16330300Sjoerg#define LCP_OPT_MRU 1 /* maximum receive unit */ 16430300Sjoerg#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 16530300Sjoerg#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 16630300Sjoerg#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 16730300Sjoerg#define LCP_OPT_MAGIC 5 /* magic number */ 16830300Sjoerg#define LCP_OPT_RESERVED 6 /* reserved */ 16930300Sjoerg#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 17030300Sjoerg#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 1714910Swollman 17225944Sjoerg#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 17325944Sjoerg#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 17425944Sjoerg#define IPCP_OPT_ADDRESS 3 /* local IP address */ 1754910Swollman 17678064Sume#define IPV6CP_OPT_IFID 1 /* interface identifier */ 17778064Sume#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 17878064Sume 17988534Sjoerg#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 18088534Sjoerg 18130300Sjoerg#define PAP_REQ 1 /* PAP name/password request */ 18230300Sjoerg#define PAP_ACK 2 /* PAP acknowledge */ 18330300Sjoerg#define PAP_NAK 3 /* PAP fail */ 1844910Swollman 18530300Sjoerg#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 18630300Sjoerg#define CHAP_RESPONSE 2 /* CHAP challenge response */ 18730300Sjoerg#define CHAP_SUCCESS 3 /* CHAP response ok */ 18830300Sjoerg#define CHAP_FAILURE 4 /* CHAP response failed */ 18930300Sjoerg 19030300Sjoerg#define CHAP_MD5 5 /* hash algorithm - MD5 */ 19130300Sjoerg 19230300Sjoerg#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 19330300Sjoerg#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 19430300Sjoerg#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 19530300Sjoerg#define CISCO_ADDR_REQ 0 /* Cisco address request */ 19630300Sjoerg#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 19730300Sjoerg#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 19830300Sjoerg 19925944Sjoerg/* states are named and numbered according to RFC 1661 */ 20025944Sjoerg#define STATE_INITIAL 0 20125944Sjoerg#define STATE_STARTING 1 20225944Sjoerg#define STATE_CLOSED 2 20325944Sjoerg#define STATE_STOPPED 3 20425944Sjoerg#define STATE_CLOSING 4 20525944Sjoerg#define STATE_STOPPING 5 20625944Sjoerg#define STATE_REQ_SENT 6 20725944Sjoerg#define STATE_ACK_RCVD 7 20825944Sjoerg#define STATE_ACK_SENT 8 20925944Sjoerg#define STATE_OPENED 9 21025944Sjoerg 2114910Swollmanstruct ppp_header { 21211189Sjkh u_char address; 21311189Sjkh u_char control; 21411189Sjkh u_short protocol; 2154910Swollman}; 2164910Swollman#define PPP_HEADER_LEN sizeof (struct ppp_header) 2174910Swollman 2184910Swollmanstruct lcp_header { 21911189Sjkh u_char type; 22011189Sjkh u_char ident; 22111189Sjkh u_short len; 2224910Swollman}; 2234910Swollman#define LCP_HEADER_LEN sizeof (struct lcp_header) 2244910Swollman 2254910Swollmanstruct cisco_packet { 22611189Sjkh u_long type; 22711189Sjkh u_long par1; 22811189Sjkh u_long par2; 22911189Sjkh u_short rel; 23011189Sjkh u_short time0; 23111189Sjkh u_short time1; 2324910Swollman}; 2334910Swollman#define CISCO_PACKET_LEN 18 2344910Swollman 23525944Sjoerg/* 23625944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make 23725944Sjoerg * it easier comparing with the standard. Please refer to this RFC in 23825944Sjoerg * case you can't make sense out of these abbreviation; it will also 23925944Sjoerg * explain the semantics related to the various events and actions. 24025944Sjoerg */ 24125944Sjoergstruct cp { 24225944Sjoerg u_short proto; /* PPP control protocol number */ 24325944Sjoerg u_char protoidx; /* index into state table in struct sppp */ 24425944Sjoerg u_char flags; 24525944Sjoerg#define CP_LCP 0x01 /* this is the LCP */ 24625944Sjoerg#define CP_AUTH 0x02 /* this is an authentication protocol */ 24725944Sjoerg#define CP_NCP 0x04 /* this is a NCP */ 24825944Sjoerg#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 24925944Sjoerg const char *name; /* name of this control protocol */ 25025944Sjoerg /* event handlers */ 25125944Sjoerg void (*Up)(struct sppp *sp); 25225944Sjoerg void (*Down)(struct sppp *sp); 25325944Sjoerg void (*Open)(struct sppp *sp); 25425944Sjoerg void (*Close)(struct sppp *sp); 25525944Sjoerg void (*TO)(void *sp); 25625944Sjoerg int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 25725944Sjoerg void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 25825944Sjoerg void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 25925944Sjoerg /* actions */ 26025944Sjoerg void (*tlu)(struct sppp *sp); 26125944Sjoerg void (*tld)(struct sppp *sp); 26225944Sjoerg void (*tls)(struct sppp *sp); 26325944Sjoerg void (*tlf)(struct sppp *sp); 26425944Sjoerg void (*scr)(struct sppp *sp); 26525944Sjoerg}; 26625944Sjoerg 26712820Sphkstatic struct sppp *spppq; 26842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26930300Sjoergstatic struct callout_handle keepalive_ch; 27040008Sjoerg#endif 2714910Swollman 27242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 27340008Sjoerg#define SPP_FMT "%s%d: " 27440008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 27540008Sjoerg#else 27640008Sjoerg#define SPP_FMT "%s: " 27740008Sjoerg#define SPP_ARGS(ifp) (ifp)->if_xname 27840008Sjoerg#endif 27940008Sjoerg 2804910Swollman/* 2814910Swollman * The following disgusting hack gets around the problem that IP TOS 2824910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2834910Swollman * priority queue. To decide if traffic is interactive, we check that 2844910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 28530300Sjoerg * 28630300Sjoerg * XXX is this really still necessary? - joerg - 2874910Swollman */ 28811189Sjkhstatic u_short interactive_ports[8] = { 2894910Swollman 0, 513, 0, 0, 2904910Swollman 0, 21, 0, 23, 2914910Swollman}; 2924910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 2934910Swollman 29425944Sjoerg/* almost every function needs these */ 29525944Sjoerg#define STDDCL \ 29625944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 29725944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 29811189Sjkh 29930300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 30025944Sjoerg struct sockaddr *dst, struct rtentry *rt); 3014910Swollman 30225944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 30325944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 30425944Sjoerg 30525944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 30625944Sjoerg struct mbuf *m); 30725944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 30825944Sjoerg u_char ident, u_short len, void *data); 30942104Sphk/* static void sppp_cp_timeout(void *arg); */ 31025944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 31125944Sjoerg int newstate); 31230300Sjoergstatic void sppp_auth_send(const struct cp *cp, 31342104Sphk struct sppp *sp, unsigned int type, unsigned int id, 31430300Sjoerg ...); 31525944Sjoerg 31625944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 31725944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 31825944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 31925944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 32025944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 32125944Sjoerg 32230300Sjoergstatic void sppp_null(struct sppp *sp); 32330300Sjoerg 32425944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 32525944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 32625944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_TO(void *sp); 33025944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33125944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33225944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33325944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 33425944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 33525944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 33625944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 33725944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 33830300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 33930300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 34025944Sjoerg 34125944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 34225944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 34325944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_TO(void *sp); 34725944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 34825944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 34925944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 35025944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 35125944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 35225944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 35325944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 35425944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 35525944Sjoerg 35678064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 35778064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 35878064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 35978064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 36078064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 36178064Sumestatic void sppp_ipv6cp_TO(void *sp); 36278064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 36378064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 36478064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 36578064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 36678064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 36778064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 36878064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 36978064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 37078064Sume 37130300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 37230300Sjoergstatic void sppp_pap_init(struct sppp *sp); 37330300Sjoergstatic void sppp_pap_open(struct sppp *sp); 37430300Sjoergstatic void sppp_pap_close(struct sppp *sp); 37530300Sjoergstatic void sppp_pap_TO(void *sp); 37630300Sjoergstatic void sppp_pap_my_TO(void *sp); 37730300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 37830300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 37930300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 38030300Sjoerg 38130300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 38230300Sjoergstatic void sppp_chap_init(struct sppp *sp); 38330300Sjoergstatic void sppp_chap_open(struct sppp *sp); 38430300Sjoergstatic void sppp_chap_close(struct sppp *sp); 38530300Sjoergstatic void sppp_chap_TO(void *sp); 38630300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 38730300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 38830300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 38930300Sjoerg 39030300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 39125944Sjoergstatic const char *sppp_cp_type_name(u_char type); 39230300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 39330300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 39478064Sume#ifdef INET6 39578064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 39678064Sume#endif 39725944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 39825944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 39925944Sjoergstatic const char *sppp_proto_name(u_short proto); 40030300Sjoergstatic const char *sppp_state_name(int state); 40138343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 40230300Sjoergstatic int sppp_strnlen(u_char *p, int max); 40330300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 40430300Sjoerg u_long *srcmask); 40525944Sjoergstatic void sppp_keepalive(void *dummy); 40630300Sjoergstatic void sppp_phase_network(struct sppp *sp); 40730300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 40830300Sjoergstatic void sppp_print_string(const char *p, u_short len); 40925944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 41025944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 41178064Sume#ifdef INET6 41278064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 41378064Sume struct in6_addr *dst, struct in6_addr *srcmask); 41478064Sume#ifdef IPV6CP_MYIFID_DYN 41578064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41678064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41778064Sume#endif 41878064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 41978064Sume#endif 42025944Sjoerg 42125944Sjoerg/* our control protocol descriptors */ 42233181Seivindstatic const struct cp lcp = { 42325944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 42425944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 42525944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 42625944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 42725944Sjoerg sppp_lcp_scr 42825944Sjoerg}; 42925944Sjoerg 43033181Seivindstatic const struct cp ipcp = { 43125944Sjoerg PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp", 43225944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 43325944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 43425944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 43525944Sjoerg sppp_ipcp_scr 43625944Sjoerg}; 43725944Sjoerg 43878064Sumestatic const struct cp ipv6cp = { 43978064Sume PPP_IPV6CP, IDX_IPV6CP, 44078064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 44178064Sume CP_NCP, 44278064Sume#else 44378064Sume 0, 44478064Sume#endif 44578064Sume "ipv6cp", 44678064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 44778064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 44878064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 44978064Sume sppp_ipv6cp_scr 45078064Sume}; 45178064Sume 45233181Seivindstatic const struct cp pap = { 45330300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 45430300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 45530300Sjoerg sppp_pap_TO, 0, 0, 0, 45630300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 45730300Sjoerg sppp_pap_scr 45830300Sjoerg}; 45930300Sjoerg 46033181Seivindstatic const struct cp chap = { 46130300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 46230300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 46330300Sjoerg sppp_chap_TO, 0, 0, 0, 46430300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 46530300Sjoerg sppp_chap_scr 46630300Sjoerg}; 46730300Sjoerg 46833181Seivindstatic const struct cp *cps[IDX_COUNT] = { 46925944Sjoerg &lcp, /* IDX_LCP */ 47025944Sjoerg &ipcp, /* IDX_IPCP */ 47178064Sume &ipv6cp, /* IDX_IPV6CP */ 47230300Sjoerg &pap, /* IDX_PAP */ 47330300Sjoerg &chap, /* IDX_CHAP */ 47425944Sjoerg}; 47525944Sjoerg 47670199Sjhaystatic int 47770199Sjhaysppp_modevent(module_t mod, int type, void *unused) 47870199Sjhay{ 47970199Sjhay switch (type) { 48070199Sjhay case MOD_LOAD: 48170199Sjhay break; 48270199Sjhay case MOD_UNLOAD: 48370199Sjhay return EACCES; 48470199Sjhay break; 48570199Sjhay default: 48670199Sjhay break; 48770199Sjhay } 48870199Sjhay return 0; 48970199Sjhay} 49070199Sjhaystatic moduledata_t spppmod = { 49170199Sjhay "sppp", 49270199Sjhay sppp_modevent, 49370199Sjhay 0 49470199Sjhay}; 49570199SjhayMODULE_VERSION(sppp, 1); 49670199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 49725944Sjoerg 49870199Sjhay/* 49925944Sjoerg * Exported functions, comprising our interface to the lower layer. 5004910Swollman */ 5014910Swollman 5024910Swollman/* 5034910Swollman * Process the received packet. 5044910Swollman */ 50525706Sjoergvoid 50625706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5074910Swollman{ 5084910Swollman struct ppp_header *h; 5094910Swollman struct ifqueue *inq = 0; 51025944Sjoerg struct sppp *sp = (struct sppp *)ifp; 51188534Sjoerg int len; 51225944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5134910Swollman 5144910Swollman if (ifp->if_flags & IFF_UP) 5154910Swollman /* Count received bytes, add FCS and one flag */ 5164910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5174910Swollman 5184910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5194910Swollman /* Too small packet, drop it. */ 52025944Sjoerg if (debug) 52125706Sjoerg log(LOG_DEBUG, 52240008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 52340008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 52425944Sjoerg drop: 52525944Sjoerg ++ifp->if_ierrors; 52625944Sjoerg ++ifp->if_iqdrops; 5274910Swollman m_freem (m); 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 } 5874910Swollman break; 5884910Swollman#endif 58978064Sume#ifdef INET6 59078064Sume case PPP_IPV6CP: 59178064Sume if (sp->pp_phase == PHASE_NETWORK) 59278064Sume sppp_cp_input(&ipv6cp, sp, m); 59378064Sume m_freem (m); 59478064Sume return; 59578064Sume 59678064Sume case PPP_IPV6: 59778064Sume if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 59878064Sume schednetisr (NETISR_IPV6); 59978064Sume inq = &ip6intrq; 60078064Sume } 60178064Sume break; 60288534Sjoerg case PPP_VJ_COMP: 60388534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 60488534Sjoerg if ((len = 60588534Sjoerg sl_uncompress_tcp((u_char **)&m->m_data, 60688534Sjoerg m->m_len, 60788534Sjoerg TYPE_COMPRESSED_TCP, 60888534Sjoerg &sp->pp_comp)) <= 0) 60988534Sjoerg goto drop; 61088534Sjoerg m->m_len = m->m_pkthdr.len = len; 61188534Sjoerg schednetisr (NETISR_IP); 61288534Sjoerg inq = &ipintrq; 61388534Sjoerg } 61488534Sjoerg break; 61588534Sjoerg case PPP_VJ_UCOMP: 61688534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 61788534Sjoerg if ((len = 61888534Sjoerg sl_uncompress_tcp((u_char **)&m->m_data, 61988534Sjoerg m->m_len, 62088534Sjoerg TYPE_UNCOMPRESSED_TCP, 62188534Sjoerg &sp->pp_comp)) <= 0) 62288534Sjoerg goto drop; 62388534Sjoerg m->m_len = m->m_pkthdr.len = len; 62488534Sjoerg schednetisr (NETISR_IP); 62588534Sjoerg inq = &ipintrq; 62688534Sjoerg } 62788534Sjoerg break; 62878064Sume#endif 62912495Speter#ifdef IPX 63012495Speter case PPP_IPX: 63112495Speter /* IPX IPXCP not implemented yet */ 63225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 63312495Speter schednetisr (NETISR_IPX); 63412495Speter inq = &ipxintrq; 63512495Speter } 63612495Speter break; 63712495Speter#endif 6384910Swollman#ifdef NS 6394910Swollman case PPP_XNS: 6404910Swollman /* XNS IDPCP not implemented yet */ 64125944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6424910Swollman schednetisr (NETISR_NS); 6434910Swollman inq = &nsintrq; 6444910Swollman } 6454910Swollman break; 6464910Swollman#endif 6474910Swollman } 6484910Swollman break; 6494910Swollman case CISCO_MULTICAST: 6504910Swollman case CISCO_UNICAST: 6514910Swollman /* Don't check the control field here (RFC 1547). */ 65245152Sphk if (sp->pp_mode != IFF_CISCO) { 65325944Sjoerg if (debug) 65425706Sjoerg log(LOG_DEBUG, 65540008Sjoerg SPP_FMT "Cisco packet in PPP mode " 65625706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 65740008Sjoerg SPP_ARGS(ifp), 65825706Sjoerg h->address, h->control, ntohs(h->protocol)); 65911189Sjkh goto drop; 66011189Sjkh } 6614910Swollman switch (ntohs (h->protocol)) { 6624910Swollman default: 6634910Swollman ++ifp->if_noproto; 6644910Swollman goto invalid; 6654910Swollman case CISCO_KEEPALIVE: 6664910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 6674910Swollman m_freem (m); 6684910Swollman return; 6694910Swollman#ifdef INET 6704910Swollman case ETHERTYPE_IP: 6714910Swollman schednetisr (NETISR_IP); 6724910Swollman inq = &ipintrq; 6734910Swollman break; 6744910Swollman#endif 67554263Sshin#ifdef INET6 67654263Sshin case ETHERTYPE_IPV6: 67754263Sshin schednetisr (NETISR_IPV6); 67854263Sshin inq = &ip6intrq; 67954263Sshin break; 68054263Sshin#endif 68112495Speter#ifdef IPX 68212495Speter case ETHERTYPE_IPX: 68312495Speter schednetisr (NETISR_IPX); 68412495Speter inq = &ipxintrq; 68512495Speter break; 68612495Speter#endif 6874910Swollman#ifdef NS 6884910Swollman case ETHERTYPE_NS: 6894910Swollman schednetisr (NETISR_NS); 6904910Swollman inq = &nsintrq; 6914910Swollman break; 6924910Swollman#endif 6934910Swollman } 6944910Swollman break; 69525944Sjoerg default: /* Invalid PPP packet. */ 69625944Sjoerg invalid: 69725944Sjoerg if (debug) 69825944Sjoerg log(LOG_DEBUG, 69940008Sjoerg SPP_FMT "invalid input packet " 70025944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 70140008Sjoerg SPP_ARGS(ifp), 70225944Sjoerg h->address, h->control, ntohs(h->protocol)); 70325944Sjoerg goto drop; 7044910Swollman } 7054910Swollman 7064910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 7074910Swollman goto drop; 7084910Swollman 7094910Swollman /* Check queue. */ 71069152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 71125944Sjoerg if (debug) 71240008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 71340008Sjoerg SPP_ARGS(ifp)); 7144910Swollman goto drop; 7154910Swollman } 7164910Swollman} 7174910Swollman 7184910Swollman/* 7194910Swollman * Enqueue transmit packet. 7204910Swollman */ 72112820Sphkstatic int 72225706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 72325706Sjoerg struct sockaddr *dst, struct rtentry *rt) 7244910Swollman{ 7254910Swollman struct sppp *sp = (struct sppp*) ifp; 7264910Swollman struct ppp_header *h; 72778064Sume struct ifqueue *ifq = NULL; 72825955Sjoerg int s, rv = 0; 72988534Sjoerg int ipproto = PPP_IP; 73042066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7314910Swollman 73225944Sjoerg s = splimp(); 73325944Sjoerg 73425944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 73525944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 7364910Swollman m_freem (m); 7374910Swollman splx (s); 7384910Swollman return (ENETDOWN); 7394910Swollman } 7404910Swollman 74125944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 74225944Sjoerg /* 74325944Sjoerg * Interface is not yet running, but auto-dial. Need 74425944Sjoerg * to start LCP for it. 74525944Sjoerg */ 74625944Sjoerg ifp->if_flags |= IFF_RUNNING; 74725944Sjoerg splx(s); 74825944Sjoerg lcp.Open(sp); 74925944Sjoerg s = splimp(); 75025944Sjoerg } 75125944Sjoerg 75278134Sume ifq = &ifp->if_snd; 7534910Swollman#ifdef INET 75412436Speter if (dst->sa_family == AF_INET) { 75540008Sjoerg /* XXX Check mbuf length here? */ 75612436Speter struct ip *ip = mtod (m, struct ip*); 75712436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 7584910Swollman 75942104Sphk /* 76042104Sphk * When using dynamic local IP address assignment by using 76142104Sphk * 0.0.0.0 as a local address, the first TCP session will 76242104Sphk * not connect because the local TCP checksum is computed 76342104Sphk * using 0.0.0.0 which will later become our real IP address 76442104Sphk * so the TCP checksum computed at the remote end will 76542104Sphk * become invalid. So we 76642104Sphk * - don't let packets with src ip addr 0 thru 76742104Sphk * - we flag TCP packets with src ip 0 as an error 76870199Sjhay */ 76942104Sphk 77042104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 77142104Sphk { 77242104Sphk m_freem(m); 77342104Sphk splx(s); 77442104Sphk if(ip->ip_p == IPPROTO_TCP) 77542104Sphk return(EADDRNOTAVAIL); 77642104Sphk else 77742104Sphk return(0); 77842104Sphk } 77970199Sjhay 78042104Sphk /* 78142104Sphk * Put low delay, telnet, rlogin and ftp control packets 78242104Sphk * in front of the queue. 78342104Sphk */ 78469152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 78541686Sphk ; 78641686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 78712436Speter ifq = &sp->pp_fastq; 78841686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 78941686Sphk ; 79041686Sphk else if (ip->ip_p != IPPROTO_TCP) 79141686Sphk ; 79241686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 79341686Sphk ifq = &sp->pp_fastq; 79441686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 79541686Sphk ifq = &sp->pp_fastq; 79688534Sjoerg 79788534Sjoerg /* 79888534Sjoerg * Do IP Header compression 79988534Sjoerg */ 80088534Sjoerg if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 80188534Sjoerg ip->ip_p == IPPROTO_TCP) 80288534Sjoerg switch (sl_compress_tcp(m, ip, &sp->pp_comp, 80388534Sjoerg sp->ipcp.compress_cid)) { 80488534Sjoerg case TYPE_COMPRESSED_TCP: 80588534Sjoerg ipproto = PPP_VJ_COMP; 80688534Sjoerg break; 80788534Sjoerg case TYPE_UNCOMPRESSED_TCP: 80888534Sjoerg ipproto = PPP_VJ_UCOMP; 80988534Sjoerg break; 81088534Sjoerg case TYPE_IP: 81188534Sjoerg ipproto = PPP_IP; 81288534Sjoerg break; 81388534Sjoerg default: 81488534Sjoerg m_freem(m); 81588534Sjoerg splx(s); 81688534Sjoerg return (EINVAL); 81788534Sjoerg } 8184910Swollman } 8194910Swollman#endif 8204910Swollman 82178064Sume#ifdef INET6 82278064Sume if (dst->sa_family == AF_INET6) { 82378064Sume /* XXX do something tricky here? */ 82478064Sume } 82578064Sume#endif 82678064Sume 8274910Swollman /* 8284910Swollman * Prepend general data packet PPP header. For now, IP only. 8294910Swollman */ 8304910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 8314910Swollman if (! m) { 83242066Sphk if (debug) 83340008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 83440008Sjoerg SPP_ARGS(ifp)); 83525944Sjoerg ++ifp->if_oerrors; 8364910Swollman splx (s); 8374910Swollman return (ENOBUFS); 8384910Swollman } 83940008Sjoerg /* 84040008Sjoerg * May want to check size of packet 84140008Sjoerg * (albeit due to the implementation it's always enough) 84240008Sjoerg */ 8434910Swollman h = mtod (m, struct ppp_header*); 84445152Sphk if (sp->pp_mode == IFF_CISCO) { 84528088Skjc h->address = CISCO_UNICAST; /* unicast address */ 8464910Swollman h->control = 0; 8474910Swollman } else { 8484910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 8494910Swollman h->control = PPP_UI; /* Unnumbered Info */ 8504910Swollman } 8514910Swollman 8524910Swollman switch (dst->sa_family) { 8534910Swollman#ifdef INET 8544910Swollman case AF_INET: /* Internet Protocol */ 85545152Sphk if (sp->pp_mode == IFF_CISCO) 85611189Sjkh h->protocol = htons (ETHERTYPE_IP); 85711189Sjkh else { 85825955Sjoerg /* 85925955Sjoerg * Don't choke with an ENETDOWN early. It's 86025955Sjoerg * possible that we just started dialing out, 86125955Sjoerg * so don't drop the packet immediately. If 86225955Sjoerg * we notice that we run out of buffer space 86325955Sjoerg * below, we will however remember that we are 86425955Sjoerg * not ready to carry IP packets, and return 86525955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 86625955Sjoerg */ 86788534Sjoerg h->protocol = htons(ipproto); 86825955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 86925955Sjoerg rv = ENETDOWN; 87011189Sjkh } 8714910Swollman break; 8724910Swollman#endif 87354263Sshin#ifdef INET6 87454263Sshin case AF_INET6: /* Internet Protocol */ 87554263Sshin if (sp->pp_mode == IFF_CISCO) 87654263Sshin h->protocol = htons (ETHERTYPE_IPV6); 87754263Sshin else { 87878064Sume /* 87978064Sume * Don't choke with an ENETDOWN early. It's 88078064Sume * possible that we just started dialing out, 88178064Sume * so don't drop the packet immediately. If 88278064Sume * we notice that we run out of buffer space 88378064Sume * below, we will however remember that we are 88478064Sume * not ready to carry IP packets, and return 88578064Sume * ENETDOWN, as opposed to ENOBUFS. 88678064Sume */ 88778064Sume h->protocol = htons(PPP_IPV6); 88878064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 88978064Sume rv = ENETDOWN; 89054263Sshin } 89154263Sshin break; 89254263Sshin#endif 8934910Swollman#ifdef NS 8944910Swollman case AF_NS: /* Xerox NS Protocol */ 89545152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 8964910Swollman ETHERTYPE_NS : PPP_XNS); 8974910Swollman break; 8984910Swollman#endif 89911819Sjulian#ifdef IPX 90012495Speter case AF_IPX: /* Novell IPX Protocol */ 90145152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 90212495Speter ETHERTYPE_IPX : PPP_IPX); 90311819Sjulian break; 90411819Sjulian#endif 9054910Swollman default: 9064910Swollman m_freem (m); 90725944Sjoerg ++ifp->if_oerrors; 9084910Swollman splx (s); 9094910Swollman return (EAFNOSUPPORT); 9104910Swollman } 9114910Swollman 9124910Swollman /* 9134910Swollman * Queue message on interface, and start output if interface 91469152Sjlemon * not yet active. Also adjust output byte count. 91569152Sjlemon * The packet length includes header, FCS and 1 flag, 91669152Sjlemon * according to RFC 1333. 9174910Swollman */ 91869152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 91925944Sjoerg ++ifp->if_oerrors; 92025955Sjoerg return (rv? rv: ENOBUFS); 9214910Swollman } 9224910Swollman return (0); 9234910Swollman} 9244910Swollman 92525706Sjoergvoid 92625706Sjoergsppp_attach(struct ifnet *ifp) 9274910Swollman{ 9284910Swollman struct sppp *sp = (struct sppp*) ifp; 9294910Swollman 9304910Swollman /* Initialize keepalive handler. */ 9314910Swollman if (! spppq) 93242064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 9334910Swollman 9344910Swollman /* Insert new entry into the keepalive list. */ 9354910Swollman sp->pp_next = spppq; 9364910Swollman spppq = sp; 9374910Swollman 93842064Sphk sp->pp_if.if_mtu = PP_MTU; 93942064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 9404910Swollman sp->pp_if.if_type = IFT_PPP; 9414910Swollman sp->pp_if.if_output = sppp_output; 94242104Sphk#if 0 94342064Sphk sp->pp_flags = PP_KEEPALIVE; 94442104Sphk#endif 94570199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 94670199Sjhay sp->pp_fastq.ifq_maxlen = 32; 94770199Sjhay sp->pp_cpq.ifq_maxlen = 20; 9484910Swollman sp->pp_loopcnt = 0; 9494910Swollman sp->pp_alivecnt = 0; 95078064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 95178064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 95225944Sjoerg sp->pp_phase = PHASE_DEAD; 95325944Sjoerg sp->pp_up = lcp.Up; 95425944Sjoerg sp->pp_down = lcp.Down; 95569152Sjlemon mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 95669152Sjlemon mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 95788534Sjoerg sp->enable_vj = 1; 95888534Sjoerg sl_compress_init(&sp->pp_comp, -1); 95925944Sjoerg sppp_lcp_init(sp); 96025944Sjoerg sppp_ipcp_init(sp); 96178064Sume sppp_ipv6cp_init(sp); 96230300Sjoerg sppp_pap_init(sp); 96330300Sjoerg sppp_chap_init(sp); 9644910Swollman} 9654910Swollman 96630300Sjoergvoid 96725706Sjoergsppp_detach(struct ifnet *ifp) 9684910Swollman{ 9694910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 97025944Sjoerg int i; 9714910Swollman 9724910Swollman /* Remove the entry from the keepalive list. */ 9734910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 9744910Swollman if (p == sp) { 9754910Swollman *q = p->pp_next; 9764910Swollman break; 9774910Swollman } 9784910Swollman 9794910Swollman /* Stop keepalive handler. */ 9804910Swollman if (! spppq) 98140008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 98225944Sjoerg 98325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 98440008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 98540008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 98669152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 98769152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 9884910Swollman} 9894910Swollman 9904910Swollman/* 9914910Swollman * Flush the interface output queue. 9924910Swollman */ 99325706Sjoergvoid 99425706Sjoergsppp_flush(struct ifnet *ifp) 9954910Swollman{ 9964910Swollman struct sppp *sp = (struct sppp*) ifp; 9974910Swollman 99825944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 99925944Sjoerg sppp_qflush (&sp->pp_fastq); 100026018Sjoerg sppp_qflush (&sp->pp_cpq); 10014910Swollman} 10024910Swollman 10034910Swollman/* 100411189Sjkh * Check if the output queue is empty. 100511189Sjkh */ 100612820Sphkint 100725706Sjoergsppp_isempty(struct ifnet *ifp) 100811189Sjkh{ 100911189Sjkh struct sppp *sp = (struct sppp*) ifp; 101025944Sjoerg int empty, s; 101111189Sjkh 101225944Sjoerg s = splimp(); 101326018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 101426018Sjoerg !sp->pp_if.if_snd.ifq_head; 101525944Sjoerg splx(s); 101611189Sjkh return (empty); 101711189Sjkh} 101811189Sjkh 101911189Sjkh/* 10204910Swollman * Get next packet to send. 10214910Swollman */ 102225706Sjoergstruct mbuf * 102325706Sjoergsppp_dequeue(struct ifnet *ifp) 10244910Swollman{ 10254910Swollman struct sppp *sp = (struct sppp*) ifp; 10264910Swollman struct mbuf *m; 102725944Sjoerg int s; 10284910Swollman 102925944Sjoerg s = splimp(); 103026018Sjoerg /* 103130300Sjoerg * Process only the control protocol queue until we have at 103230300Sjoerg * least one NCP open. 103326018Sjoerg * 103426018Sjoerg * Do always serve all three queues in Cisco mode. 103526018Sjoerg */ 103626018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 103726018Sjoerg if (m == NULL && 103845152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 103926018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 104026018Sjoerg if (m == NULL) 104126018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 104226018Sjoerg } 104326018Sjoerg splx(s); 104426018Sjoerg return m; 10454910Swollman} 10464910Swollman 10474910Swollman/* 104830300Sjoerg * Pick the next packet, do not remove it from the queue. 104930300Sjoerg */ 105030300Sjoergstruct mbuf * 105130300Sjoergsppp_pick(struct ifnet *ifp) 105230300Sjoerg{ 105330300Sjoerg struct sppp *sp = (struct sppp*)ifp; 105430300Sjoerg struct mbuf *m; 105530300Sjoerg int s; 105630300Sjoerg 105730300Sjoerg s= splimp (); 105830300Sjoerg 105930300Sjoerg m = sp->pp_cpq.ifq_head; 106030300Sjoerg if (m == NULL && 106145152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 106230300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 106330300Sjoerg m = sp->pp_if.if_snd.ifq_head; 106430300Sjoerg splx (s); 106530300Sjoerg return (m); 106630300Sjoerg} 106730300Sjoerg 106830300Sjoerg/* 106925944Sjoerg * Process an ioctl request. Called on low priority level. 10704910Swollman */ 107125944Sjoergint 107242104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 10734910Swollman{ 107425944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 107525944Sjoerg struct sppp *sp = (struct sppp*) ifp; 107630300Sjoerg int s, rv, going_up, going_down, newmode; 10774910Swollman 107825944Sjoerg s = splimp(); 107930300Sjoerg rv = 0; 108025944Sjoerg switch (cmd) { 108125944Sjoerg case SIOCAIFADDR: 108225944Sjoerg case SIOCSIFDSTADDR: 108325944Sjoerg break; 10844910Swollman 108525944Sjoerg case SIOCSIFADDR: 108688503Sjoerg /* set the interface "up" when assigning an IP address */ 108788503Sjoerg ifp->if_flags |= IFF_UP; 108825944Sjoerg /* fall through... */ 108911189Sjkh 109025944Sjoerg case SIOCSIFFLAGS: 109125944Sjoerg going_up = ifp->if_flags & IFF_UP && 109225944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 109325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 109425944Sjoerg ifp->if_flags & IFF_RUNNING; 109545152Sphk 109645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 109745152Sphk if (!newmode) 109845152Sphk newmode = ifp->if_flags & IFF_AUTO; 109945152Sphk if (!newmode) 110045152Sphk newmode = ifp->if_flags & IFF_CISCO; 110145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 110245152Sphk ifp->if_flags |= newmode; 110345152Sphk 110445152Sphk if (newmode != sp->pp_mode) { 110545152Sphk going_down = 1; 110645152Sphk if (!going_up) 110745152Sphk going_up = ifp->if_flags & IFF_RUNNING; 11084910Swollman } 11094910Swollman 111045152Sphk if (going_down) { 111170199Sjhay if (sp->pp_mode != IFF_CISCO) 111245152Sphk lcp.Close(sp); 111345152Sphk else if (sp->pp_tlf) 111445152Sphk (sp->pp_tlf)(sp); 111526018Sjoerg sppp_flush(ifp); 111625944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 111745152Sphk sp->pp_mode = newmode; 111826018Sjoerg } 11194910Swollman 112045152Sphk if (going_up) { 112170199Sjhay if (sp->pp_mode != IFF_CISCO) 112245152Sphk lcp.Close(sp); 112345152Sphk sp->pp_mode = newmode; 112445152Sphk if (sp->pp_mode == 0) { 112545152Sphk ifp->if_flags |= IFF_RUNNING; 112645152Sphk lcp.Open(sp); 112745152Sphk } 112845152Sphk if (sp->pp_mode == IFF_CISCO) { 112945152Sphk if (sp->pp_tls) 113045152Sphk (sp->pp_tls)(sp); 113145152Sphk ifp->if_flags |= IFF_RUNNING; 113245152Sphk } 113345152Sphk } 113445152Sphk 11354910Swollman break; 113611189Sjkh 113725944Sjoerg#ifdef SIOCSIFMTU 113825944Sjoerg#ifndef ifr_mtu 113925944Sjoerg#define ifr_mtu ifr_metric 114025944Sjoerg#endif 114125944Sjoerg case SIOCSIFMTU: 114225944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 114325944Sjoerg return (EINVAL); 114425944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 11454910Swollman break; 114625944Sjoerg#endif 114725944Sjoerg#ifdef SLIOCSETMTU 114825944Sjoerg case SLIOCSETMTU: 114925944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 115025944Sjoerg return (EINVAL); 115125944Sjoerg ifp->if_mtu = *(short*)data; 11524910Swollman break; 115325944Sjoerg#endif 115425944Sjoerg#ifdef SIOCGIFMTU 115525944Sjoerg case SIOCGIFMTU: 115625944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 115711189Sjkh break; 115825944Sjoerg#endif 115925944Sjoerg#ifdef SLIOCGETMTU 116025944Sjoerg case SLIOCGETMTU: 116125944Sjoerg *(short*)data = ifp->if_mtu; 11624910Swollman break; 116325944Sjoerg#endif 116425944Sjoerg case SIOCADDMULTI: 116525944Sjoerg case SIOCDELMULTI: 11664910Swollman break; 116711189Sjkh 116830300Sjoerg case SIOCGIFGENERIC: 116930300Sjoerg case SIOCSIFGENERIC: 117030300Sjoerg rv = sppp_params(sp, cmd, data); 117130300Sjoerg break; 117230300Sjoerg 117325944Sjoerg default: 117430300Sjoerg rv = ENOTTY; 11754910Swollman } 117625944Sjoerg splx(s); 117730300Sjoerg return rv; 11784910Swollman} 11794910Swollman 118070199Sjhay/* 118125944Sjoerg * Cisco framing implementation. 118225944Sjoerg */ 118325944Sjoerg 11844910Swollman/* 11854910Swollman * Handle incoming Cisco keepalive protocol packets. 11864910Swollman */ 118730300Sjoergstatic void 118825706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 11894910Swollman{ 119025944Sjoerg STDDCL; 11914910Swollman struct cisco_packet *h; 119230300Sjoerg u_long me, mymask; 11934910Swollman 119427929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 119525706Sjoerg if (debug) 119625706Sjoerg log(LOG_DEBUG, 119740008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 119840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 11994910Swollman return; 12004910Swollman } 12014910Swollman h = mtod (m, struct cisco_packet*); 120225706Sjoerg if (debug) 120325706Sjoerg log(LOG_DEBUG, 120440008Sjoerg SPP_FMT "cisco input: %d bytes " 120525706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 120640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 120740008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 120840008Sjoerg (u_int)h->time0, (u_int)h->time1); 12094910Swollman switch (ntohl (h->type)) { 12104910Swollman default: 121125706Sjoerg if (debug) 121269211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 121340008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 12144910Swollman break; 12154910Swollman case CISCO_ADDR_REPLY: 12164910Swollman /* Reply on address request, ignore */ 12174910Swollman break; 12184910Swollman case CISCO_KEEPALIVE_REQ: 12194910Swollman sp->pp_alivecnt = 0; 122078064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 122178064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 12224910Swollman /* Local and remote sequence numbers are equal. 12234910Swollman * Probably, the line is in loopback mode. */ 122411189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 122540008Sjoerg printf (SPP_FMT "loopback\n", 122640008Sjoerg SPP_ARGS(ifp)); 122711189Sjkh sp->pp_loopcnt = 0; 122811189Sjkh if (ifp->if_flags & IFF_UP) { 122911189Sjkh if_down (ifp); 123026018Sjoerg sppp_qflush (&sp->pp_cpq); 123111189Sjkh } 123211189Sjkh } 12334910Swollman ++sp->pp_loopcnt; 12344910Swollman 12354910Swollman /* Generate new local sequence number */ 123642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 123778064Sume sp->pp_seq[IDX_LCP] = random(); 123840008Sjoerg#else 123978064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 124040008Sjoerg#endif 124111189Sjkh break; 124211189Sjkh } 124330300Sjoerg sp->pp_loopcnt = 0; 124411189Sjkh if (! (ifp->if_flags & IFF_UP) && 124511189Sjkh (ifp->if_flags & IFF_RUNNING)) { 124630300Sjoerg if_up(ifp); 124740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 124811189Sjkh } 12494910Swollman break; 12504910Swollman case CISCO_ADDR_REQ: 125130300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 125230300Sjoerg if (me != 0L) 125330300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 12544910Swollman break; 12554910Swollman } 12564910Swollman} 12574910Swollman 12584910Swollman/* 125925944Sjoerg * Send Cisco keepalive packet. 12604910Swollman */ 126112820Sphkstatic void 126225944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 126325944Sjoerg{ 126425944Sjoerg STDDCL; 126525944Sjoerg struct ppp_header *h; 126625944Sjoerg struct cisco_packet *ch; 126725944Sjoerg struct mbuf *m; 126842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 126935029Sphk struct timeval tv; 127040008Sjoerg#else 127140008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 127240008Sjoerg#endif 127325944Sjoerg 127442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 127536119Sphk getmicrouptime(&tv); 127640008Sjoerg#endif 127770199Sjhay 127825944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 127925944Sjoerg if (! m) 128025944Sjoerg return; 128125944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 128225944Sjoerg m->m_pkthdr.rcvif = 0; 128325944Sjoerg 128425944Sjoerg h = mtod (m, struct ppp_header*); 128525944Sjoerg h->address = CISCO_MULTICAST; 128625944Sjoerg h->control = 0; 128725944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 128825944Sjoerg 128925944Sjoerg ch = (struct cisco_packet*) (h + 1); 129025944Sjoerg ch->type = htonl (type); 129125944Sjoerg ch->par1 = htonl (par1); 129225944Sjoerg ch->par2 = htonl (par2); 129325944Sjoerg ch->rel = -1; 129440008Sjoerg 129542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 129635029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 129735029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 129840008Sjoerg#else 129940008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 130040008Sjoerg ch->time1 = htons ((u_short) t); 130140008Sjoerg#endif 130225944Sjoerg 130325944Sjoerg if (debug) 130425944Sjoerg log(LOG_DEBUG, 130540008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 130640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 130740008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 130825944Sjoerg 130969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 131069152Sjlemon ifp->if_oerrors++; 131125944Sjoerg} 131225944Sjoerg 131370199Sjhay/* 131425944Sjoerg * PPP protocol implementation. 131525944Sjoerg */ 131625944Sjoerg 131725944Sjoerg/* 131825944Sjoerg * Send PPP control protocol packet. 131925944Sjoerg */ 132025944Sjoergstatic void 132125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 132225706Sjoerg u_char ident, u_short len, void *data) 13234910Swollman{ 132425944Sjoerg STDDCL; 13254910Swollman struct ppp_header *h; 13264910Swollman struct lcp_header *lh; 13274910Swollman struct mbuf *m; 13284910Swollman 13294910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 13304910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 13314910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 13324910Swollman if (! m) 13334910Swollman return; 13344910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 13354910Swollman m->m_pkthdr.rcvif = 0; 13364910Swollman 13374910Swollman h = mtod (m, struct ppp_header*); 13384910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 13394910Swollman h->control = PPP_UI; /* Unnumbered Info */ 13404910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 13414910Swollman 13424910Swollman lh = (struct lcp_header*) (h + 1); 13434910Swollman lh->type = type; 13444910Swollman lh->ident = ident; 13454910Swollman lh->len = htons (LCP_HEADER_LEN + len); 13464910Swollman if (len) 13474910Swollman bcopy (data, lh+1, len); 13484910Swollman 134925706Sjoerg if (debug) { 135040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 135140008Sjoerg SPP_ARGS(ifp), 135225944Sjoerg sppp_proto_name(proto), 135325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 135425944Sjoerg ntohs (lh->len)); 135544145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 135669211Sphk log(-1, ">\n"); 13574910Swollman } 135869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 135969152Sjlemon ifp->if_oerrors++; 13604910Swollman} 13614910Swollman 13624910Swollman/* 136325944Sjoerg * Handle incoming PPP control protocol packets. 13644910Swollman */ 136512820Sphkstatic void 136625944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 13674910Swollman{ 136825944Sjoerg STDDCL; 136925944Sjoerg struct lcp_header *h; 137025944Sjoerg int len = m->m_pkthdr.len; 137125944Sjoerg int rv; 137225944Sjoerg u_char *p; 13734910Swollman 137425944Sjoerg if (len < 4) { 137525944Sjoerg if (debug) 137625944Sjoerg log(LOG_DEBUG, 137740008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 137840008Sjoerg SPP_ARGS(ifp), cp->name, len); 13794910Swollman return; 138025944Sjoerg } 138125944Sjoerg h = mtod (m, struct lcp_header*); 138225944Sjoerg if (debug) { 138325944Sjoerg log(LOG_DEBUG, 138440008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 138540008Sjoerg SPP_ARGS(ifp), cp->name, 138625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 138725944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 138844145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 138969211Sphk log(-1, ">\n"); 139025944Sjoerg } 139125944Sjoerg if (len > ntohs (h->len)) 139225944Sjoerg len = ntohs (h->len); 139330300Sjoerg p = (u_char *)(h + 1); 139425944Sjoerg switch (h->type) { 139525944Sjoerg case CONF_REQ: 139625944Sjoerg if (len < 4) { 139725944Sjoerg if (debug) 139869211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 139940008Sjoerg SPP_ARGS(ifp), cp->name, 140025944Sjoerg len); 140125944Sjoerg ++ifp->if_ierrors; 140225944Sjoerg break; 140325944Sjoerg } 140430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 140530300Sjoerg switch (sp->state[cp->protoidx]) { 140630300Sjoerg case STATE_CLOSING: 140730300Sjoerg case STATE_STOPPING: 140830300Sjoerg return; 140930300Sjoerg case STATE_CLOSED: 141030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 141130300Sjoerg 0, 0); 141230300Sjoerg return; 141330300Sjoerg } 141425944Sjoerg rv = (cp->RCR)(sp, h, len); 141525944Sjoerg switch (sp->state[cp->protoidx]) { 141625944Sjoerg case STATE_OPENED: 141725944Sjoerg (cp->tld)(sp); 141825944Sjoerg (cp->scr)(sp); 141925944Sjoerg /* fall through... */ 142025944Sjoerg case STATE_ACK_SENT: 142125944Sjoerg case STATE_REQ_SENT: 142270199Sjhay /* 142370199Sjhay * sppp_cp_change_state() have the side effect of 142470199Sjhay * restarting the timeouts. We want to avoid that 142570199Sjhay * if the state don't change, otherwise we won't 142670199Sjhay * ever timeout and resend a configuration request 142770199Sjhay * that got lost. 142870199Sjhay */ 142970199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 143070199Sjhay STATE_REQ_SENT)) 143170199Sjhay break; 143225944Sjoerg sppp_cp_change_state(cp, sp, rv? 143325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 143425944Sjoerg break; 143525944Sjoerg case STATE_STOPPED: 143625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 143725944Sjoerg (cp->scr)(sp); 143825944Sjoerg sppp_cp_change_state(cp, sp, rv? 143925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 144025944Sjoerg break; 144125944Sjoerg case STATE_ACK_RCVD: 144225944Sjoerg if (rv) { 144325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 144425944Sjoerg if (debug) 144540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 144640008Sjoerg SPP_ARGS(ifp), 144726077Sjoerg cp->name); 144825944Sjoerg (cp->tlu)(sp); 144925944Sjoerg } else 145025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 145125944Sjoerg break; 145225944Sjoerg default: 145340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 145440008Sjoerg SPP_ARGS(ifp), cp->name, 145525944Sjoerg sppp_cp_type_name(h->type), 145625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 145725944Sjoerg ++ifp->if_ierrors; 145825944Sjoerg } 145925944Sjoerg break; 146025944Sjoerg case CONF_ACK: 146125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 146225944Sjoerg if (debug) 146369211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 146440008Sjoerg SPP_ARGS(ifp), cp->name, 146525944Sjoerg h->ident, sp->confid[cp->protoidx]); 146625944Sjoerg ++ifp->if_ierrors; 146725944Sjoerg break; 146825944Sjoerg } 146925944Sjoerg switch (sp->state[cp->protoidx]) { 147025944Sjoerg case STATE_CLOSED: 147125944Sjoerg case STATE_STOPPED: 147225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 147325944Sjoerg break; 147425944Sjoerg case STATE_CLOSING: 147525944Sjoerg case STATE_STOPPING: 147625944Sjoerg break; 147725944Sjoerg case STATE_REQ_SENT: 147825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 147925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 148025944Sjoerg break; 148125944Sjoerg case STATE_OPENED: 148225944Sjoerg (cp->tld)(sp); 148325944Sjoerg /* fall through */ 148425944Sjoerg case STATE_ACK_RCVD: 148525944Sjoerg (cp->scr)(sp); 148625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 148725944Sjoerg break; 148825944Sjoerg case STATE_ACK_SENT: 148925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 149025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 149125944Sjoerg if (debug) 149240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 149340008Sjoerg SPP_ARGS(ifp), cp->name); 149425944Sjoerg (cp->tlu)(sp); 149525944Sjoerg break; 149625944Sjoerg default: 149740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 149840008Sjoerg SPP_ARGS(ifp), cp->name, 149925944Sjoerg sppp_cp_type_name(h->type), 150025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 150125944Sjoerg ++ifp->if_ierrors; 150225944Sjoerg } 150325944Sjoerg break; 150425944Sjoerg case CONF_NAK: 150525944Sjoerg case CONF_REJ: 150625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 150725944Sjoerg if (debug) 150869211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 150940008Sjoerg SPP_ARGS(ifp), cp->name, 151025944Sjoerg h->ident, sp->confid[cp->protoidx]); 151125944Sjoerg ++ifp->if_ierrors; 151225944Sjoerg break; 151325944Sjoerg } 151425944Sjoerg if (h->type == CONF_NAK) 151525944Sjoerg (cp->RCN_nak)(sp, h, len); 151625944Sjoerg else /* CONF_REJ */ 151725944Sjoerg (cp->RCN_rej)(sp, h, len); 15184910Swollman 151925944Sjoerg switch (sp->state[cp->protoidx]) { 152025944Sjoerg case STATE_CLOSED: 152125944Sjoerg case STATE_STOPPED: 152225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 152325944Sjoerg break; 152425944Sjoerg case STATE_REQ_SENT: 152525944Sjoerg case STATE_ACK_SENT: 152625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 152770199Sjhay /* 152870199Sjhay * Slow things down a bit if we think we might be 152970199Sjhay * in loopback. Depend on the timeout to send the 153070199Sjhay * next configuration request. 153170199Sjhay */ 153270199Sjhay if (sp->pp_loopcnt) 153370199Sjhay break; 153425944Sjoerg (cp->scr)(sp); 153525944Sjoerg break; 153625944Sjoerg case STATE_OPENED: 153725944Sjoerg (cp->tld)(sp); 153825944Sjoerg /* fall through */ 153925944Sjoerg case STATE_ACK_RCVD: 154052633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154125944Sjoerg (cp->scr)(sp); 154225944Sjoerg break; 154325944Sjoerg case STATE_CLOSING: 154425944Sjoerg case STATE_STOPPING: 154525944Sjoerg break; 154625944Sjoerg default: 154740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 154840008Sjoerg SPP_ARGS(ifp), cp->name, 154925944Sjoerg sppp_cp_type_name(h->type), 155025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155125944Sjoerg ++ifp->if_ierrors; 155225944Sjoerg } 155325944Sjoerg break; 15544910Swollman 155525944Sjoerg case TERM_REQ: 155625944Sjoerg switch (sp->state[cp->protoidx]) { 155725944Sjoerg case STATE_ACK_RCVD: 155825944Sjoerg case STATE_ACK_SENT: 155925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 156025944Sjoerg /* fall through */ 156125944Sjoerg case STATE_CLOSED: 156225944Sjoerg case STATE_STOPPED: 156325944Sjoerg case STATE_CLOSING: 156425944Sjoerg case STATE_STOPPING: 156525944Sjoerg case STATE_REQ_SENT: 156625944Sjoerg sta: 156725944Sjoerg /* Send Terminate-Ack packet. */ 156825944Sjoerg if (debug) 156940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 157040008Sjoerg SPP_ARGS(ifp), cp->name); 157125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 157225944Sjoerg break; 157325944Sjoerg case STATE_OPENED: 157425944Sjoerg (cp->tld)(sp); 157525944Sjoerg sp->rst_counter[cp->protoidx] = 0; 157625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 157725944Sjoerg goto sta; 157825944Sjoerg break; 157925944Sjoerg default: 158040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 158140008Sjoerg SPP_ARGS(ifp), cp->name, 158225944Sjoerg sppp_cp_type_name(h->type), 158325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158425944Sjoerg ++ifp->if_ierrors; 158525944Sjoerg } 158625944Sjoerg break; 158725944Sjoerg case TERM_ACK: 158825944Sjoerg switch (sp->state[cp->protoidx]) { 158925944Sjoerg case STATE_CLOSED: 159025944Sjoerg case STATE_STOPPED: 159125944Sjoerg case STATE_REQ_SENT: 159225944Sjoerg case STATE_ACK_SENT: 159325944Sjoerg break; 159425944Sjoerg case STATE_CLOSING: 159541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 159625944Sjoerg (cp->tlf)(sp); 159725944Sjoerg break; 159825944Sjoerg case STATE_STOPPING: 159941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 160025944Sjoerg (cp->tlf)(sp); 160125944Sjoerg break; 160225944Sjoerg case STATE_ACK_RCVD: 160325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 160425944Sjoerg break; 160525944Sjoerg case STATE_OPENED: 160625944Sjoerg (cp->tld)(sp); 160725944Sjoerg (cp->scr)(sp); 160825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 160925944Sjoerg break; 161025944Sjoerg default: 161140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 161240008Sjoerg SPP_ARGS(ifp), cp->name, 161325944Sjoerg sppp_cp_type_name(h->type), 161425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 161525944Sjoerg ++ifp->if_ierrors; 161625944Sjoerg } 161725944Sjoerg break; 161825944Sjoerg case CODE_REJ: 161925944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 162030300Sjoerg log(LOG_INFO, 162140008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 162230300Sjoerg "danger will robinson\n", 162340008Sjoerg SPP_ARGS(ifp), cp->name, 162430300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 162525944Sjoerg switch (sp->state[cp->protoidx]) { 162625944Sjoerg case STATE_CLOSED: 162725944Sjoerg case STATE_STOPPED: 162825944Sjoerg case STATE_REQ_SENT: 162925944Sjoerg case STATE_ACK_SENT: 163025944Sjoerg case STATE_CLOSING: 163125944Sjoerg case STATE_STOPPING: 163225944Sjoerg case STATE_OPENED: 163325944Sjoerg break; 163425944Sjoerg case STATE_ACK_RCVD: 163525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 163625944Sjoerg break; 163725944Sjoerg default: 163840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163940008Sjoerg SPP_ARGS(ifp), cp->name, 164025944Sjoerg sppp_cp_type_name(h->type), 164125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164225944Sjoerg ++ifp->if_ierrors; 164325944Sjoerg } 164425944Sjoerg break; 164580715Sume case PROTO_REJ: 164680715Sume { 164780715Sume int catastrophic; 164880715Sume const struct cp *upper; 164980715Sume int i; 165080715Sume u_int16_t proto; 165180715Sume 165280715Sume catastrophic = 0; 165380715Sume upper = NULL; 165480715Sume proto = ntohs(*((u_int16_t *)p)); 165580715Sume for (i = 0; i < IDX_COUNT; i++) { 165680715Sume if (cps[i]->proto == proto) { 165780715Sume upper = cps[i]; 165880715Sume break; 165980715Sume } 166080715Sume } 166180715Sume if (upper == NULL) 166280715Sume catastrophic++; 166380715Sume 166488508Sjoerg if (catastrophic || debug) 166588508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 166688508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 166788508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 166888508Sjoerg sppp_cp_type_name(h->type), proto, 166988508Sjoerg upper ? upper->name : "unknown", 167088508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 167180715Sume 167280715Sume /* 167380715Sume * if we got RXJ+ against conf-req, the peer does not implement 167480715Sume * this particular protocol type. terminate the protocol. 167580715Sume */ 167680715Sume if (upper && !catastrophic) { 167780715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 167880715Sume upper->Close(sp); 167980715Sume break; 168080715Sume } 168180715Sume } 168280715Sume 168380715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 168480715Sume switch (sp->state[cp->protoidx]) { 168580715Sume case STATE_CLOSED: 168680715Sume case STATE_STOPPED: 168780715Sume case STATE_REQ_SENT: 168880715Sume case STATE_ACK_SENT: 168980715Sume case STATE_CLOSING: 169080715Sume case STATE_STOPPING: 169180715Sume case STATE_OPENED: 169280715Sume break; 169380715Sume case STATE_ACK_RCVD: 169480715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 169580715Sume break; 169680715Sume default: 169780715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 169880715Sume SPP_ARGS(ifp), cp->name, 169980715Sume sppp_cp_type_name(h->type), 170080715Sume sppp_state_name(sp->state[cp->protoidx])); 170180715Sume ++ifp->if_ierrors; 170280715Sume } 170380715Sume break; 170480715Sume } 170525944Sjoerg case DISC_REQ: 170625944Sjoerg if (cp->proto != PPP_LCP) 170725944Sjoerg goto illegal; 170825944Sjoerg /* Discard the packet. */ 170925944Sjoerg break; 171025944Sjoerg case ECHO_REQ: 171125944Sjoerg if (cp->proto != PPP_LCP) 171225944Sjoerg goto illegal; 171325944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 171425944Sjoerg if (debug) 171569211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 171640008Sjoerg SPP_ARGS(ifp)); 171725944Sjoerg ++ifp->if_ierrors; 171825944Sjoerg break; 171925944Sjoerg } 172025944Sjoerg if (len < 8) { 172125944Sjoerg if (debug) 172269211Sphk log(-1, SPP_FMT "invalid lcp echo request " 172325944Sjoerg "packet length: %d bytes\n", 172440008Sjoerg SPP_ARGS(ifp), len); 172525944Sjoerg break; 172625944Sjoerg } 172744145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 172844145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 172925944Sjoerg /* Line loopback mode detected. */ 173040008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 173170199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 173225944Sjoerg if_down (ifp); 173326018Sjoerg sppp_qflush (&sp->pp_cpq); 17344910Swollman 173525944Sjoerg /* Shut down the PPP link. */ 173625944Sjoerg /* XXX */ 173725944Sjoerg lcp.Down(sp); 173825944Sjoerg lcp.Up(sp); 173925944Sjoerg break; 174025944Sjoerg } 174125944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 174225944Sjoerg if (debug) 174369211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 174440008Sjoerg SPP_ARGS(ifp)); 174525944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 174625944Sjoerg break; 174725944Sjoerg case ECHO_REPLY: 174825944Sjoerg if (cp->proto != PPP_LCP) 174925944Sjoerg goto illegal; 175025944Sjoerg if (h->ident != sp->lcp.echoid) { 175125944Sjoerg ++ifp->if_ierrors; 175225944Sjoerg break; 175325944Sjoerg } 175425944Sjoerg if (len < 8) { 175525944Sjoerg if (debug) 175669211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 175725944Sjoerg "packet length: %d bytes\n", 175840008Sjoerg SPP_ARGS(ifp), len); 175925944Sjoerg break; 176025944Sjoerg } 176125944Sjoerg if (debug) 176269211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 176340008Sjoerg SPP_ARGS(ifp)); 176444145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 176544145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 176625944Sjoerg sp->pp_alivecnt = 0; 176725944Sjoerg break; 176825944Sjoerg default: 176925944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 177025944Sjoerg illegal: 177125944Sjoerg if (debug) 177269211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 177340008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 177478064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 177578064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 177625944Sjoerg ++ifp->if_ierrors; 177725944Sjoerg } 17784910Swollman} 17794910Swollman 178025944Sjoerg 17814910Swollman/* 178225944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 178325944Sjoerg * Basically, the state transition handling in the automaton. 17844910Swollman */ 178525944Sjoergstatic void 178625944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 17874910Swollman{ 178825944Sjoerg STDDCL; 17894910Swollman 179025944Sjoerg if (debug) 179140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 179240008Sjoerg SPP_ARGS(ifp), cp->name, 179325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 179425944Sjoerg 179525944Sjoerg switch (sp->state[cp->protoidx]) { 179625944Sjoerg case STATE_INITIAL: 179725944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 179825944Sjoerg break; 179925944Sjoerg case STATE_STARTING: 180025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 180125944Sjoerg (cp->scr)(sp); 180225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 180325944Sjoerg break; 18044910Swollman default: 180540008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 180640008Sjoerg SPP_ARGS(ifp), cp->name, 180725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 180825944Sjoerg } 180925944Sjoerg} 18104910Swollman 181125944Sjoergstatic void 181225944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 181325944Sjoerg{ 181425944Sjoerg STDDCL; 181525944Sjoerg 181625944Sjoerg if (debug) 181740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 181840008Sjoerg SPP_ARGS(ifp), cp->name, 181925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 182025944Sjoerg 182125944Sjoerg switch (sp->state[cp->protoidx]) { 182225944Sjoerg case STATE_CLOSED: 182325944Sjoerg case STATE_CLOSING: 182425944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 18254910Swollman break; 182625944Sjoerg case STATE_STOPPED: 182741881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 182825944Sjoerg (cp->tls)(sp); 182941881Sphk break; 183025944Sjoerg case STATE_STOPPING: 183125944Sjoerg case STATE_REQ_SENT: 183225944Sjoerg case STATE_ACK_RCVD: 183325944Sjoerg case STATE_ACK_SENT: 183425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 183525944Sjoerg break; 183625944Sjoerg case STATE_OPENED: 183725944Sjoerg (cp->tld)(sp); 183825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 183925944Sjoerg break; 184025944Sjoerg default: 184140008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 184240008Sjoerg SPP_ARGS(ifp), cp->name, 184325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 184425944Sjoerg } 184525944Sjoerg} 18464910Swollman 184711189Sjkh 184825944Sjoergstatic void 184925944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 185025944Sjoerg{ 185125944Sjoerg STDDCL; 185225944Sjoerg 185325944Sjoerg if (debug) 185440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 185540008Sjoerg SPP_ARGS(ifp), cp->name, 185625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 185725944Sjoerg 185825944Sjoerg switch (sp->state[cp->protoidx]) { 185925944Sjoerg case STATE_INITIAL: 186041881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 186125944Sjoerg (cp->tls)(sp); 18624910Swollman break; 186325944Sjoerg case STATE_STARTING: 186425944Sjoerg break; 186525944Sjoerg case STATE_CLOSED: 186625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 186725944Sjoerg (cp->scr)(sp); 186825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 186925944Sjoerg break; 187025944Sjoerg case STATE_STOPPED: 187174703Sjoerg /* 187274703Sjoerg * Try escaping stopped state. This seems to bite 187374703Sjoerg * people occasionally, in particular for IPCP, 187474703Sjoerg * presumably following previous IPCP negotiation 187574703Sjoerg * aborts. Somehow, we must have missed a Down event 187674703Sjoerg * which would have caused a transition into starting 187774703Sjoerg * state, so as a bandaid we force the Down event now. 187874703Sjoerg * This effectively implements (something like the) 187974703Sjoerg * `restart' option mentioned in the state transition 188074703Sjoerg * table of RFC 1661. 188174703Sjoerg */ 188274703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 188374703Sjoerg (cp->tls)(sp); 188474703Sjoerg break; 188525944Sjoerg case STATE_STOPPING: 188625944Sjoerg case STATE_REQ_SENT: 188725944Sjoerg case STATE_ACK_RCVD: 188825944Sjoerg case STATE_ACK_SENT: 188925944Sjoerg case STATE_OPENED: 189025944Sjoerg break; 189125944Sjoerg case STATE_CLOSING: 189225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 189325944Sjoerg break; 189425944Sjoerg } 189525944Sjoerg} 18964910Swollman 189725944Sjoerg 189825944Sjoergstatic void 189925944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 190025944Sjoerg{ 190125944Sjoerg STDDCL; 190225944Sjoerg 190325944Sjoerg if (debug) 190440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 190540008Sjoerg SPP_ARGS(ifp), cp->name, 190625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190725944Sjoerg 190825944Sjoerg switch (sp->state[cp->protoidx]) { 190925944Sjoerg case STATE_INITIAL: 191025944Sjoerg case STATE_CLOSED: 191125944Sjoerg case STATE_CLOSING: 19124910Swollman break; 191325944Sjoerg case STATE_STARTING: 191441881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 191525944Sjoerg (cp->tlf)(sp); 19164910Swollman break; 191725944Sjoerg case STATE_STOPPED: 191825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 19194910Swollman break; 192025944Sjoerg case STATE_STOPPING: 192125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19224910Swollman break; 192325944Sjoerg case STATE_OPENED: 192425944Sjoerg (cp->tld)(sp); 192525944Sjoerg /* fall through */ 192625944Sjoerg case STATE_REQ_SENT: 192725944Sjoerg case STATE_ACK_RCVD: 192825944Sjoerg case STATE_ACK_SENT: 192925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 193078064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 193178064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 193225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19334910Swollman break; 19344910Swollman } 19354910Swollman} 19364910Swollman 193725944Sjoergstatic void 193825944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 193925944Sjoerg{ 194025944Sjoerg STDDCL; 194125944Sjoerg int s; 194225944Sjoerg 194325944Sjoerg s = splimp(); 194425944Sjoerg if (debug) 194540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 194640008Sjoerg SPP_ARGS(ifp), cp->name, 194725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 194825944Sjoerg sp->rst_counter[cp->protoidx]); 194925944Sjoerg 195025944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 195125944Sjoerg /* TO- event */ 195225944Sjoerg switch (sp->state[cp->protoidx]) { 195325944Sjoerg case STATE_CLOSING: 195441881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 195525944Sjoerg (cp->tlf)(sp); 195625944Sjoerg break; 195725944Sjoerg case STATE_STOPPING: 195841881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 195925944Sjoerg (cp->tlf)(sp); 196025944Sjoerg break; 196125944Sjoerg case STATE_REQ_SENT: 196225944Sjoerg case STATE_ACK_RCVD: 196325944Sjoerg case STATE_ACK_SENT: 196441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 196525944Sjoerg (cp->tlf)(sp); 196625944Sjoerg break; 196725944Sjoerg } 196825944Sjoerg else 196925944Sjoerg /* TO+ event */ 197025944Sjoerg switch (sp->state[cp->protoidx]) { 197125944Sjoerg case STATE_CLOSING: 197225944Sjoerg case STATE_STOPPING: 197378064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 197478064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 197570199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 197642064Sphk sp->ch[cp->protoidx]); 197725944Sjoerg break; 197825944Sjoerg case STATE_REQ_SENT: 197925944Sjoerg case STATE_ACK_RCVD: 198025944Sjoerg (cp->scr)(sp); 198125944Sjoerg /* sppp_cp_change_state() will restart the timer */ 198225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 198325944Sjoerg break; 198425944Sjoerg case STATE_ACK_SENT: 198525944Sjoerg (cp->scr)(sp); 198642064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 198742064Sphk sp->ch[cp->protoidx]); 198825944Sjoerg break; 198925944Sjoerg } 199025944Sjoerg 199125944Sjoerg splx(s); 199225944Sjoerg} 199325944Sjoerg 199411189Sjkh/* 199525944Sjoerg * Change the state of a control protocol in the state automaton. 199625944Sjoerg * Takes care of starting/stopping the restart timer. 199711189Sjkh */ 199825944Sjoergvoid 199925944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 200025944Sjoerg{ 200125944Sjoerg sp->state[cp->protoidx] = newstate; 200225944Sjoerg 200340008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 200425944Sjoerg switch (newstate) { 200525944Sjoerg case STATE_INITIAL: 200625944Sjoerg case STATE_STARTING: 200725944Sjoerg case STATE_CLOSED: 200825944Sjoerg case STATE_STOPPED: 200925944Sjoerg case STATE_OPENED: 201025944Sjoerg break; 201125944Sjoerg case STATE_CLOSING: 201225944Sjoerg case STATE_STOPPING: 201325944Sjoerg case STATE_REQ_SENT: 201425944Sjoerg case STATE_ACK_RCVD: 201525944Sjoerg case STATE_ACK_SENT: 201670199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 201742064Sphk sp->ch[cp->protoidx]); 201825944Sjoerg break; 201925944Sjoerg } 202025944Sjoerg} 202170199Sjhay 202270199Sjhay/* 202325944Sjoerg *--------------------------------------------------------------------------* 202425944Sjoerg * * 202525944Sjoerg * The LCP implementation. * 202625944Sjoerg * * 202725944Sjoerg *--------------------------------------------------------------------------* 202825944Sjoerg */ 202925944Sjoergstatic void 203025944Sjoergsppp_lcp_init(struct sppp *sp) 203125944Sjoerg{ 203225944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 203325944Sjoerg sp->lcp.magic = 0; 203425944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 203525944Sjoerg sp->fail_counter[IDX_LCP] = 0; 203678064Sume sp->pp_seq[IDX_LCP] = 0; 203778064Sume sp->pp_rseq[IDX_LCP] = 0; 203825944Sjoerg sp->lcp.protos = 0; 203925944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 204030300Sjoerg 204144145Sphk /* Note that these values are relevant for all control protocols */ 204244145Sphk sp->lcp.timeout = 3 * hz; 204325944Sjoerg sp->lcp.max_terminate = 2; 204425944Sjoerg sp->lcp.max_configure = 10; 204525944Sjoerg sp->lcp.max_failure = 10; 204642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 204730300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 204840008Sjoerg#endif 204925944Sjoerg} 205025944Sjoerg 205125944Sjoergstatic void 205225944Sjoergsppp_lcp_up(struct sppp *sp) 205325944Sjoerg{ 205425944Sjoerg STDDCL; 205525944Sjoerg 205670199Sjhay sp->pp_alivecnt = 0; 205770199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 205870199Sjhay sp->lcp.magic = 0; 205970199Sjhay sp->lcp.protos = 0; 206070199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 206125944Sjoerg /* 206275321Sjoerg * If we are authenticator, negotiate LCP_AUTH 206375321Sjoerg */ 206475321Sjoerg if (sp->hisauth.proto != 0) 206575321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 206675321Sjoerg else 206775321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 206875321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 206975321Sjoerg /* 207030300Sjoerg * If this interface is passive or dial-on-demand, and we are 207130300Sjoerg * still in Initial state, it means we've got an incoming 207230300Sjoerg * call. Activate the interface. 207325944Sjoerg */ 207425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 207525944Sjoerg if (debug) 207625944Sjoerg log(LOG_DEBUG, 207740008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 207825944Sjoerg ifp->if_flags |= IFF_RUNNING; 207930300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 208030300Sjoerg if (debug) 208169211Sphk log(-1, "(incoming call)\n"); 208230300Sjoerg sp->pp_flags |= PP_CALLIN; 208330300Sjoerg lcp.Open(sp); 208430300Sjoerg } else if (debug) 208569211Sphk log(-1, "\n"); 208625944Sjoerg } 208725944Sjoerg 208825944Sjoerg sppp_up_event(&lcp, sp); 208925944Sjoerg} 209025944Sjoerg 209125944Sjoergstatic void 209225944Sjoergsppp_lcp_down(struct sppp *sp) 209325944Sjoerg{ 209425944Sjoerg STDDCL; 209525944Sjoerg 209625944Sjoerg sppp_down_event(&lcp, sp); 209725944Sjoerg 209825944Sjoerg /* 209925944Sjoerg * If this is neither a dial-on-demand nor a passive 210025944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 210125944Sjoerg * administrator can force a redial by another ``ifconfig 210225944Sjoerg * up''. XXX For leased line operation, should we immediately 210325944Sjoerg * try to reopen the connection here? 210425944Sjoerg */ 210525944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 210625944Sjoerg log(LOG_INFO, 210742066Sphk SPP_FMT "Down event, taking interface down.\n", 210840008Sjoerg SPP_ARGS(ifp)); 210925944Sjoerg if_down(ifp); 211025944Sjoerg } else { 211125944Sjoerg if (debug) 211225944Sjoerg log(LOG_DEBUG, 211340008Sjoerg SPP_FMT "Down event (carrier loss)\n", 211440008Sjoerg SPP_ARGS(ifp)); 211570199Sjhay sp->pp_flags &= ~PP_CALLIN; 211670199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 211770199Sjhay lcp.Close(sp); 211870199Sjhay ifp->if_flags &= ~IFF_RUNNING; 211925944Sjoerg } 212025944Sjoerg} 212125944Sjoerg 212225944Sjoergstatic void 212325944Sjoergsppp_lcp_open(struct sppp *sp) 212425944Sjoerg{ 212525944Sjoerg sppp_open_event(&lcp, sp); 212625944Sjoerg} 212725944Sjoerg 212825944Sjoergstatic void 212925944Sjoergsppp_lcp_close(struct sppp *sp) 213025944Sjoerg{ 213125944Sjoerg sppp_close_event(&lcp, sp); 213225944Sjoerg} 213325944Sjoerg 213425944Sjoergstatic void 213525944Sjoergsppp_lcp_TO(void *cookie) 213625944Sjoerg{ 213725944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 213825944Sjoerg} 213925944Sjoerg 214025944Sjoerg/* 214125944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 214225944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 214325944Sjoerg * caused action scn. (The return value is used to make the state 214425944Sjoerg * transition decision in the state automaton.) 214525944Sjoerg */ 214612820Sphkstatic int 214725944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 21484910Swollman{ 214925944Sjoerg STDDCL; 215011189Sjkh u_char *buf, *r, *p; 215125944Sjoerg int origlen, rlen; 215225944Sjoerg u_long nmagic; 215330300Sjoerg u_short authproto; 21544910Swollman 215511189Sjkh len -= 4; 215625944Sjoerg origlen = len; 215711189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 215811189Sjkh if (! buf) 215911189Sjkh return (0); 21604910Swollman 216125706Sjoerg if (debug) 216240008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 216340008Sjoerg SPP_ARGS(ifp)); 216425706Sjoerg 216525944Sjoerg /* pass 1: check for things that need to be rejected */ 216611189Sjkh p = (void*) (h+1); 216711189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 216825944Sjoerg if (debug) 216969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 217011189Sjkh switch (*p) { 217111189Sjkh case LCP_OPT_MAGIC: 217225944Sjoerg /* Magic number. */ 217370199Sjhay if (len >= 6 && p[1] == 6) 217470199Sjhay continue; 217570199Sjhay if (debug) 217670199Sjhay log(-1, "[invalid] "); 217770199Sjhay break; 217825944Sjoerg case LCP_OPT_ASYNC_MAP: 217925944Sjoerg /* Async control character map. */ 218070199Sjhay if (len >= 6 && p[1] == 6) 218125944Sjoerg continue; 218225944Sjoerg if (debug) 218369211Sphk log(-1, "[invalid] "); 218425944Sjoerg break; 218525944Sjoerg case LCP_OPT_MRU: 218625944Sjoerg /* Maximum receive unit. */ 218725944Sjoerg if (len >= 4 && p[1] == 4) 218825944Sjoerg continue; 218925944Sjoerg if (debug) 219069211Sphk log(-1, "[invalid] "); 219125944Sjoerg break; 219230300Sjoerg case LCP_OPT_AUTH_PROTO: 219330300Sjoerg if (len < 4) { 219430300Sjoerg if (debug) 219569211Sphk log(-1, "[invalid] "); 219630300Sjoerg break; 219730300Sjoerg } 219830300Sjoerg authproto = (p[2] << 8) + p[3]; 219930300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 220030300Sjoerg if (debug) 220169211Sphk log(-1, "[invalid chap len] "); 220230300Sjoerg break; 220330300Sjoerg } 220430300Sjoerg if (sp->myauth.proto == 0) { 220530300Sjoerg /* we are not configured to do auth */ 220630300Sjoerg if (debug) 220769211Sphk log(-1, "[not configured] "); 220830300Sjoerg break; 220930300Sjoerg } 221030300Sjoerg /* 221130300Sjoerg * Remote want us to authenticate, remember this, 221230300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 221330300Sjoerg * up. 221430300Sjoerg */ 221530300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 221630300Sjoerg continue; 221725944Sjoerg default: 221825944Sjoerg /* Others not supported. */ 221925944Sjoerg if (debug) 222069211Sphk log(-1, "[rej] "); 222125944Sjoerg break; 222225944Sjoerg } 222325944Sjoerg /* Add the option to rejected list. */ 222425944Sjoerg bcopy (p, r, p[1]); 222525944Sjoerg r += p[1]; 222625944Sjoerg rlen += p[1]; 222725944Sjoerg } 222825944Sjoerg if (rlen) { 222925944Sjoerg if (debug) 223069211Sphk log(-1, " send conf-rej\n"); 223125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 223225944Sjoerg return 0; 223325944Sjoerg } else if (debug) 223469211Sphk log(-1, "\n"); 223525944Sjoerg 223625944Sjoerg /* 223725944Sjoerg * pass 2: check for option values that are unacceptable and 223825944Sjoerg * thus require to be nak'ed. 223925944Sjoerg */ 224025944Sjoerg if (debug) 224140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 224240008Sjoerg SPP_ARGS(ifp)); 224325944Sjoerg 224425944Sjoerg p = (void*) (h+1); 224525944Sjoerg len = origlen; 224625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 224725944Sjoerg if (debug) 224869211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 224925944Sjoerg switch (*p) { 225025944Sjoerg case LCP_OPT_MAGIC: 225111189Sjkh /* Magic number -- extract. */ 225225944Sjoerg nmagic = (u_long)p[2] << 24 | 225325944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 225425944Sjoerg if (nmagic != sp->lcp.magic) { 225570199Sjhay sp->pp_loopcnt = 0; 225625706Sjoerg if (debug) 225769211Sphk log(-1, "0x%lx ", nmagic); 225811189Sjkh continue; 225911189Sjkh } 226070199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 226169211Sphk log(-1, "[glitch] "); 226225944Sjoerg ++sp->pp_loopcnt; 226325944Sjoerg /* 226425944Sjoerg * We negate our magic here, and NAK it. If 226525944Sjoerg * we see it later in an NAK packet, we 226625944Sjoerg * suggest a new one. 226725944Sjoerg */ 226825944Sjoerg nmagic = ~sp->lcp.magic; 226925944Sjoerg /* Gonna NAK it. */ 227025944Sjoerg p[2] = nmagic >> 24; 227125944Sjoerg p[3] = nmagic >> 16; 227225944Sjoerg p[4] = nmagic >> 8; 227325944Sjoerg p[5] = nmagic; 227411189Sjkh break; 227525944Sjoerg 227611189Sjkh case LCP_OPT_ASYNC_MAP: 227788506Sjoerg /* 227888506Sjoerg * Async control character map -- just ignore it. 227988506Sjoerg * 228088506Sjoerg * Quote from RFC 1662, chapter 6: 228188506Sjoerg * To enable this functionality, synchronous PPP 228288506Sjoerg * implementations MUST always respond to the 228388506Sjoerg * Async-Control-Character-Map Configuration 228488506Sjoerg * Option with the LCP Configure-Ack. However, 228588506Sjoerg * acceptance of the Configuration Option does 228688506Sjoerg * not imply that the synchronous implementation 228788506Sjoerg * will do any ACCM mapping. Instead, all such 228888506Sjoerg * octet mapping will be performed by the 228988506Sjoerg * asynchronous-to-synchronous converter. 229088506Sjoerg */ 229188506Sjoerg continue; 229225944Sjoerg 229311189Sjkh case LCP_OPT_MRU: 229425944Sjoerg /* 229525944Sjoerg * Maximum receive unit. Always agreeable, 229625944Sjoerg * but ignored by now. 229725944Sjoerg */ 229825944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 229925706Sjoerg if (debug) 230069211Sphk log(-1, "%lu ", sp->lcp.their_mru); 230111189Sjkh continue; 230230300Sjoerg 230330300Sjoerg case LCP_OPT_AUTH_PROTO: 230430300Sjoerg authproto = (p[2] << 8) + p[3]; 230530300Sjoerg if (sp->myauth.proto != authproto) { 230630300Sjoerg /* not agreed, nak */ 230730300Sjoerg if (debug) 230869211Sphk log(-1, "[mine %s != his %s] ", 230930300Sjoerg sppp_proto_name(sp->hisauth.proto), 231030300Sjoerg sppp_proto_name(authproto)); 231130300Sjoerg p[2] = sp->myauth.proto >> 8; 231230300Sjoerg p[3] = sp->myauth.proto; 231330300Sjoerg break; 231430300Sjoerg } 231530300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 231630300Sjoerg if (debug) 231769211Sphk log(-1, "[chap not MD5] "); 231839981Sjoerg p[4] = CHAP_MD5; 231930300Sjoerg break; 232030300Sjoerg } 232130300Sjoerg continue; 232211189Sjkh } 232325944Sjoerg /* Add the option to nak'ed list. */ 232425706Sjoerg bcopy (p, r, p[1]); 232525706Sjoerg r += p[1]; 232611189Sjkh rlen += p[1]; 232712436Speter } 232825706Sjoerg if (rlen) { 232970199Sjhay /* 233070199Sjhay * Local and remote magics equal -- loopback? 233170199Sjhay */ 233270199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 233370199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 233470199Sjhay printf (SPP_FMT "loopback\n", 233570199Sjhay SPP_ARGS(ifp)); 233670199Sjhay if (ifp->if_flags & IFF_UP) { 233770199Sjhay if_down(ifp); 233870199Sjhay sppp_qflush(&sp->pp_cpq); 233970199Sjhay /* XXX ? */ 234070199Sjhay lcp.Down(sp); 234170199Sjhay lcp.Up(sp); 234270199Sjhay } 234370199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 234428036Sjoerg if (debug) 234569211Sphk log(-1, " max_failure (%d) exceeded, " 234628036Sjoerg "send conf-rej\n", 234728036Sjoerg sp->lcp.max_failure); 234828036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 234928036Sjoerg } else { 235028036Sjoerg if (debug) 235169211Sphk log(-1, " send conf-nak\n"); 235228036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 235328036Sjoerg } 235425944Sjoerg } else { 235525944Sjoerg if (debug) 235669211Sphk log(-1, " send conf-ack\n"); 235728036Sjoerg sp->fail_counter[IDX_LCP] = 0; 235825944Sjoerg sp->pp_loopcnt = 0; 235925944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 236025944Sjoerg h->ident, origlen, h+1); 236125944Sjoerg } 236225944Sjoerg 236311189Sjkh free (buf, M_TEMP); 236411189Sjkh return (rlen == 0); 23654910Swollman} 23664910Swollman 236725944Sjoerg/* 236825944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 236925944Sjoerg * negotiation. 237025944Sjoerg */ 237112820Sphkstatic void 237225944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 23734910Swollman{ 237425944Sjoerg STDDCL; 237525944Sjoerg u_char *buf, *p; 23764910Swollman 237725944Sjoerg len -= 4; 237825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 237925944Sjoerg if (!buf) 23804910Swollman return; 238125944Sjoerg 238225944Sjoerg if (debug) 238340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 238440008Sjoerg SPP_ARGS(ifp)); 238525944Sjoerg 238625944Sjoerg p = (void*) (h+1); 238725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 238825944Sjoerg if (debug) 238969211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 239025944Sjoerg switch (*p) { 239125944Sjoerg case LCP_OPT_MAGIC: 239225944Sjoerg /* Magic number -- can't use it, use 0 */ 239325944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 239425944Sjoerg sp->lcp.magic = 0; 239525944Sjoerg break; 239625944Sjoerg case LCP_OPT_MRU: 239725944Sjoerg /* 239825944Sjoerg * Should not be rejected anyway, since we only 239925944Sjoerg * negotiate a MRU if explicitly requested by 240025944Sjoerg * peer. 240125944Sjoerg */ 240225944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 240325944Sjoerg break; 240430300Sjoerg case LCP_OPT_AUTH_PROTO: 240530300Sjoerg /* 240630300Sjoerg * Peer doesn't want to authenticate himself, 240730300Sjoerg * deny unless this is a dialout call, and 240830300Sjoerg * AUTHFLAG_NOCALLOUT is set. 240930300Sjoerg */ 241030300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 241130300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 241230300Sjoerg if (debug) 241369211Sphk log(-1, "[don't insist on auth " 241430300Sjoerg "for callout]"); 241530300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 241630300Sjoerg break; 241730300Sjoerg } 241830300Sjoerg if (debug) 241969211Sphk log(-1, "[access denied]\n"); 242030300Sjoerg lcp.Close(sp); 242130300Sjoerg break; 242225944Sjoerg } 24234910Swollman } 242425944Sjoerg if (debug) 242569211Sphk log(-1, "\n"); 242625944Sjoerg free (buf, M_TEMP); 242725944Sjoerg return; 242825944Sjoerg} 242925944Sjoerg 243025944Sjoerg/* 243125944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 243225944Sjoerg * negotiation. 243325944Sjoerg */ 243425944Sjoergstatic void 243525944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 243625944Sjoerg{ 243725944Sjoerg STDDCL; 243825944Sjoerg u_char *buf, *p; 243925944Sjoerg u_long magic; 244025944Sjoerg 244125944Sjoerg len -= 4; 244225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 244325944Sjoerg if (!buf) 244425944Sjoerg return; 244525944Sjoerg 244625944Sjoerg if (debug) 244740008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 244840008Sjoerg SPP_ARGS(ifp)); 244925944Sjoerg 245025944Sjoerg p = (void*) (h+1); 245125944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 245225706Sjoerg if (debug) 245369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 245425944Sjoerg switch (*p) { 245525944Sjoerg case LCP_OPT_MAGIC: 245625944Sjoerg /* Magic number -- renegotiate */ 245725944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 245825944Sjoerg len >= 6 && p[1] == 6) { 245925944Sjoerg magic = (u_long)p[2] << 24 | 246025944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 246125944Sjoerg /* 246225944Sjoerg * If the remote magic is our negated one, 246325944Sjoerg * this looks like a loopback problem. 246425944Sjoerg * Suggest a new magic to make sure. 246525944Sjoerg */ 246625944Sjoerg if (magic == ~sp->lcp.magic) { 246725944Sjoerg if (debug) 246869211Sphk log(-1, "magic glitch "); 246942065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 247035064Sphk sp->lcp.magic = random(); 247140008Sjoerg#else 247240008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 247340008Sjoerg#endif 247425944Sjoerg } else { 247525944Sjoerg sp->lcp.magic = magic; 247625944Sjoerg if (debug) 247769211Sphk log(-1, "%lu ", magic); 247825944Sjoerg } 247925944Sjoerg } 248025944Sjoerg break; 248125944Sjoerg case LCP_OPT_MRU: 248225944Sjoerg /* 248325944Sjoerg * Peer wants to advise us to negotiate an MRU. 248425944Sjoerg * Agree on it if it's reasonable, or use 248525944Sjoerg * default otherwise. 248625944Sjoerg */ 248725944Sjoerg if (len >= 4 && p[1] == 4) { 248825944Sjoerg u_int mru = p[2] * 256 + p[3]; 248925944Sjoerg if (debug) 249069211Sphk log(-1, "%d ", mru); 249125944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 249225944Sjoerg mru = PP_MTU; 249325944Sjoerg sp->lcp.mru = mru; 249425944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 249525944Sjoerg } 249625944Sjoerg break; 249730300Sjoerg case LCP_OPT_AUTH_PROTO: 249830300Sjoerg /* 249930300Sjoerg * Peer doesn't like our authentication method, 250030300Sjoerg * deny. 250130300Sjoerg */ 250230300Sjoerg if (debug) 250369211Sphk log(-1, "[access denied]\n"); 250430300Sjoerg lcp.Close(sp); 250530300Sjoerg break; 25064910Swollman } 250725944Sjoerg } 250825944Sjoerg if (debug) 250969211Sphk log(-1, "\n"); 251025944Sjoerg free (buf, M_TEMP); 251125944Sjoerg return; 251225944Sjoerg} 251311189Sjkh 251425944Sjoergstatic void 251525944Sjoergsppp_lcp_tlu(struct sppp *sp) 251625944Sjoerg{ 251742066Sphk STDDCL; 251825944Sjoerg int i; 251925944Sjoerg u_long mask; 252025944Sjoerg 252125944Sjoerg /* XXX ? */ 252225944Sjoerg if (! (ifp->if_flags & IFF_UP) && 252325944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 252425944Sjoerg /* Coming out of loopback mode. */ 252525944Sjoerg if_up(ifp); 252640008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 252725944Sjoerg } 252825944Sjoerg 252925944Sjoerg for (i = 0; i < IDX_COUNT; i++) 253025944Sjoerg if ((cps[i])->flags & CP_QUAL) 253125944Sjoerg (cps[i])->Open(sp); 253225944Sjoerg 253330300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 253430300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 253525944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 253625944Sjoerg else 253725944Sjoerg sp->pp_phase = PHASE_NETWORK; 253825944Sjoerg 253942066Sphk if (debug) 254042066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 254142066Sphk sppp_phase_name(sp->pp_phase)); 254225944Sjoerg 254330300Sjoerg /* 254430300Sjoerg * Open all authentication protocols. This is even required 254530300Sjoerg * if we already proceeded to network phase, since it might be 254630300Sjoerg * that remote wants us to authenticate, so we might have to 254730300Sjoerg * send a PAP request. Undesired authentication protocols 254830300Sjoerg * don't do anything when they get an Open event. 254930300Sjoerg */ 255030300Sjoerg for (i = 0; i < IDX_COUNT; i++) 255130300Sjoerg if ((cps[i])->flags & CP_AUTH) 255230300Sjoerg (cps[i])->Open(sp); 255330300Sjoerg 255430300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 255525944Sjoerg /* Notify all NCPs. */ 255625944Sjoerg for (i = 0; i < IDX_COUNT; i++) 255725944Sjoerg if ((cps[i])->flags & CP_NCP) 255825944Sjoerg (cps[i])->Open(sp); 255925944Sjoerg } 256025944Sjoerg 256125944Sjoerg /* Send Up events to all started protos. */ 256225944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 256325944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) 256425944Sjoerg (cps[i])->Up(sp); 256525944Sjoerg 256642104Sphk /* notify low-level driver of state change */ 256742104Sphk if (sp->pp_chg) 256842104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 256942104Sphk 257025944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 257125944Sjoerg /* if no NCP is starting, close down */ 257230300Sjoerg sppp_lcp_check_and_close(sp); 257325944Sjoerg} 257425944Sjoerg 257525944Sjoergstatic void 257625944Sjoergsppp_lcp_tld(struct sppp *sp) 257725944Sjoerg{ 257842066Sphk STDDCL; 257925944Sjoerg int i; 258025944Sjoerg u_long mask; 258125944Sjoerg 258225944Sjoerg sp->pp_phase = PHASE_TERMINATE; 258325944Sjoerg 258442066Sphk if (debug) 258542066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 258642066Sphk sppp_phase_name(sp->pp_phase)); 258725944Sjoerg 258825944Sjoerg /* 258925944Sjoerg * Take upper layers down. We send the Down event first and 259025944Sjoerg * the Close second to prevent the upper layers from sending 259125944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 259225944Sjoerg * describes it. 259325944Sjoerg */ 259425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 259525944Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) { 259625944Sjoerg (cps[i])->Down(sp); 259725944Sjoerg (cps[i])->Close(sp); 259825944Sjoerg } 259925944Sjoerg} 260025944Sjoerg 260125944Sjoergstatic void 260225944Sjoergsppp_lcp_tls(struct sppp *sp) 260325944Sjoerg{ 260442066Sphk STDDCL; 260525944Sjoerg 260625944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 260725944Sjoerg 260842066Sphk if (debug) 260942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 261042066Sphk sppp_phase_name(sp->pp_phase)); 261125944Sjoerg 261225944Sjoerg /* Notify lower layer if desired. */ 261325944Sjoerg if (sp->pp_tls) 261425944Sjoerg (sp->pp_tls)(sp); 261541881Sphk else 261641881Sphk (sp->pp_up)(sp); 261725944Sjoerg} 261825944Sjoerg 261925944Sjoergstatic void 262025944Sjoergsppp_lcp_tlf(struct sppp *sp) 262125944Sjoerg{ 262242066Sphk STDDCL; 262325944Sjoerg 262425944Sjoerg sp->pp_phase = PHASE_DEAD; 262542066Sphk if (debug) 262642066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 262742066Sphk sppp_phase_name(sp->pp_phase)); 262825944Sjoerg 262925944Sjoerg /* Notify lower layer if desired. */ 263025944Sjoerg if (sp->pp_tlf) 263125944Sjoerg (sp->pp_tlf)(sp); 263241881Sphk else 263341881Sphk (sp->pp_down)(sp); 263425944Sjoerg} 263525944Sjoerg 263625944Sjoergstatic void 263725944Sjoergsppp_lcp_scr(struct sppp *sp) 263825944Sjoerg{ 263930300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 264025944Sjoerg int i = 0; 264130300Sjoerg u_short authproto; 264225944Sjoerg 264325944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 264425944Sjoerg if (! sp->lcp.magic) 264542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 264635064Sphk sp->lcp.magic = random(); 264740008Sjoerg#else 264840008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 264940008Sjoerg#endif 265025944Sjoerg opt[i++] = LCP_OPT_MAGIC; 265125944Sjoerg opt[i++] = 6; 265225944Sjoerg opt[i++] = sp->lcp.magic >> 24; 265325944Sjoerg opt[i++] = sp->lcp.magic >> 16; 265425944Sjoerg opt[i++] = sp->lcp.magic >> 8; 265525944Sjoerg opt[i++] = sp->lcp.magic; 265625944Sjoerg } 265725944Sjoerg 265825944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 265925944Sjoerg opt[i++] = LCP_OPT_MRU; 266025944Sjoerg opt[i++] = 4; 266125944Sjoerg opt[i++] = sp->lcp.mru >> 8; 266225944Sjoerg opt[i++] = sp->lcp.mru; 266325944Sjoerg } 266425944Sjoerg 266530300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 266630300Sjoerg authproto = sp->hisauth.proto; 266730300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 266830300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 266930300Sjoerg opt[i++] = authproto >> 8; 267030300Sjoerg opt[i++] = authproto; 267130300Sjoerg if (authproto == PPP_CHAP) 267230300Sjoerg opt[i++] = CHAP_MD5; 267330300Sjoerg } 267430300Sjoerg 267578064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 267625944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 267725944Sjoerg} 267825944Sjoerg 267925944Sjoerg/* 268030300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 268130300Sjoerg */ 268230300Sjoergstatic int 268330300Sjoergsppp_ncp_check(struct sppp *sp) 268430300Sjoerg{ 268530300Sjoerg int i, mask; 268630300Sjoerg 268730300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 268830300Sjoerg if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP) 268930300Sjoerg return 1; 269030300Sjoerg return 0; 269130300Sjoerg} 269230300Sjoerg 269330300Sjoerg/* 269425944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 269525944Sjoerg * Called by the NCPs during their tlf action handling. 269625944Sjoerg */ 269725944Sjoergstatic void 269830300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 269925944Sjoerg{ 270025944Sjoerg 270130300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 270230300Sjoerg /* don't bother, we are already going down */ 270330300Sjoerg return; 270430300Sjoerg 270530300Sjoerg if (sppp_ncp_check(sp)) 270630300Sjoerg return; 270730300Sjoerg 270825944Sjoerg lcp.Close(sp); 270925944Sjoerg} 271070199Sjhay 271170199Sjhay/* 271225944Sjoerg *--------------------------------------------------------------------------* 271325944Sjoerg * * 271425944Sjoerg * The IPCP implementation. * 271525944Sjoerg * * 271625944Sjoerg *--------------------------------------------------------------------------* 271725944Sjoerg */ 271825944Sjoerg 271925944Sjoergstatic void 272025944Sjoergsppp_ipcp_init(struct sppp *sp) 272125944Sjoerg{ 272225944Sjoerg sp->ipcp.opts = 0; 272325944Sjoerg sp->ipcp.flags = 0; 272425944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 272525944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 272678064Sume sp->pp_seq[IDX_IPCP] = 0; 272778064Sume sp->pp_rseq[IDX_IPCP] = 0; 272842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 272929681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 273040008Sjoerg#endif 273125944Sjoerg} 273225944Sjoerg 273325944Sjoergstatic void 273425944Sjoergsppp_ipcp_up(struct sppp *sp) 273525944Sjoerg{ 273625944Sjoerg sppp_up_event(&ipcp, sp); 273725944Sjoerg} 273825944Sjoerg 273925944Sjoergstatic void 274025944Sjoergsppp_ipcp_down(struct sppp *sp) 274125944Sjoerg{ 274225944Sjoerg sppp_down_event(&ipcp, sp); 274325944Sjoerg} 274425944Sjoerg 274525944Sjoergstatic void 274625944Sjoergsppp_ipcp_open(struct sppp *sp) 274725944Sjoerg{ 274825944Sjoerg STDDCL; 274925944Sjoerg u_long myaddr, hisaddr; 275025944Sjoerg 275188534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 275288534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 275342104Sphk 275430300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 275525944Sjoerg /* 275625944Sjoerg * If we don't have his address, this probably means our 275725944Sjoerg * interface doesn't want to talk IP at all. (This could 275825944Sjoerg * be the case if somebody wants to speak only IPX, for 275925944Sjoerg * example.) Don't open IPCP in this case. 276025944Sjoerg */ 276125944Sjoerg if (hisaddr == 0L) { 276225944Sjoerg /* XXX this message should go away */ 276325944Sjoerg if (debug) 276440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 276540008Sjoerg SPP_ARGS(ifp)); 276625944Sjoerg return; 276725944Sjoerg } 276825944Sjoerg if (myaddr == 0L) { 276925944Sjoerg /* 277025944Sjoerg * I don't have an assigned address, so i need to 277125944Sjoerg * negotiate my address. 277225944Sjoerg */ 277325944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 277425944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 277542104Sphk } else 277642104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 277788534Sjoerg if (sp->enable_vj) { 277888534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 277988534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 278088534Sjoerg sp->ipcp.compress_cid = 1; 278188534Sjoerg } 278225944Sjoerg sppp_open_event(&ipcp, sp); 278325944Sjoerg} 278425944Sjoerg 278525944Sjoergstatic void 278625944Sjoergsppp_ipcp_close(struct sppp *sp) 278725944Sjoerg{ 278825944Sjoerg sppp_close_event(&ipcp, sp); 278925944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 279025944Sjoerg /* 279125944Sjoerg * My address was dynamic, clear it again. 279225944Sjoerg */ 279325944Sjoerg sppp_set_ip_addr(sp, 0L); 279425944Sjoerg} 279525944Sjoerg 279625944Sjoergstatic void 279725944Sjoergsppp_ipcp_TO(void *cookie) 279825944Sjoerg{ 279925944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 280025944Sjoerg} 280125944Sjoerg 280225944Sjoerg/* 280325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 280425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 280525944Sjoerg * caused action scn. (The return value is used to make the state 280625944Sjoerg * transition decision in the state automaton.) 280725944Sjoerg */ 280825944Sjoergstatic int 280925944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 281025944Sjoerg{ 281125944Sjoerg u_char *buf, *r, *p; 281225944Sjoerg struct ifnet *ifp = &sp->pp_if; 281325944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 281425944Sjoerg u_long hisaddr, desiredaddr; 281542104Sphk int gotmyaddr = 0; 281688534Sjoerg int desiredcomp; 281725944Sjoerg 281825944Sjoerg len -= 4; 281925944Sjoerg origlen = len; 282025944Sjoerg /* 282125944Sjoerg * Make sure to allocate a buf that can at least hold a 282225944Sjoerg * conf-nak with an `address' option. We might need it below. 282325944Sjoerg */ 282425944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 282525944Sjoerg if (! buf) 282625944Sjoerg return (0); 282725944Sjoerg 282825944Sjoerg /* pass 1: see if we can recognize them */ 282925944Sjoerg if (debug) 283040008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 283140008Sjoerg SPP_ARGS(ifp)); 283225944Sjoerg p = (void*) (h+1); 283325944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 283425944Sjoerg if (debug) 283569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 283625944Sjoerg switch (*p) { 283788534Sjoerg case IPCP_OPT_COMPRESSION: 283888534Sjoerg if (!sp->enable_vj) { 283988534Sjoerg /* VJ compression administratively disabled */ 284088534Sjoerg if (debug) 284188534Sjoerg log(-1, "[locally disabled] "); 284288534Sjoerg break; 284388534Sjoerg } 284488534Sjoerg /* 284588534Sjoerg * In theory, we should only conf-rej an 284688534Sjoerg * option that is shorter than RFC 1618 284788534Sjoerg * requires (i.e. < 4), and should conf-nak 284888534Sjoerg * anything else that is not VJ. However, 284988534Sjoerg * since our algorithm always uses the 285088534Sjoerg * original option to NAK it with new values, 285188534Sjoerg * things would become more complicated. In 285288534Sjoerg * pratice, the only commonly implemented IP 285388534Sjoerg * compression option is VJ anyway, so the 285488534Sjoerg * difference is negligible. 285588534Sjoerg */ 285688534Sjoerg if (len >= 6 && p[1] == 6) { 285788534Sjoerg /* 285888534Sjoerg * correctly formed compression option 285988534Sjoerg * that could be VJ compression 286088534Sjoerg */ 286188534Sjoerg continue; 286288534Sjoerg } 286388534Sjoerg if (debug) 286488534Sjoerg log(-1, 286588534Sjoerg "optlen %d [invalid/unsupported] ", 286688534Sjoerg p[1]); 286788534Sjoerg break; 286825944Sjoerg case IPCP_OPT_ADDRESS: 286925944Sjoerg if (len >= 6 && p[1] == 6) { 287025944Sjoerg /* correctly formed address option */ 287125944Sjoerg continue; 287225944Sjoerg } 287325706Sjoerg if (debug) 287469211Sphk log(-1, "[invalid] "); 287511189Sjkh break; 287625944Sjoerg default: 287725944Sjoerg /* Others not supported. */ 287825944Sjoerg if (debug) 287969211Sphk log(-1, "[rej] "); 28804910Swollman break; 28814910Swollman } 288225944Sjoerg /* Add the option to rejected list. */ 288325944Sjoerg bcopy (p, r, p[1]); 288425944Sjoerg r += p[1]; 288525944Sjoerg rlen += p[1]; 288625944Sjoerg } 288725944Sjoerg if (rlen) { 288825944Sjoerg if (debug) 288969211Sphk log(-1, " send conf-rej\n"); 289025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 289125944Sjoerg return 0; 289225944Sjoerg } else if (debug) 289369211Sphk log(-1, "\n"); 289425944Sjoerg 289525944Sjoerg /* pass 2: parse option values */ 289630300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 289725944Sjoerg if (debug) 289840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 289940008Sjoerg SPP_ARGS(ifp)); 290025944Sjoerg p = (void*) (h+1); 290125944Sjoerg len = origlen; 290225944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 290325944Sjoerg if (debug) 290469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 290525944Sjoerg switch (*p) { 290688534Sjoerg case IPCP_OPT_COMPRESSION: 290788534Sjoerg desiredcomp = p[2] << 8 | p[3]; 290888534Sjoerg /* We only support VJ */ 290988534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 291088534Sjoerg if (debug) 291188534Sjoerg log(-1, "VJ [ack] "); 291288534Sjoerg sp->ipcp.flags |= IPCP_VJ; 291388534Sjoerg sl_compress_init(&sp->pp_comp, p[4]); 291488534Sjoerg sp->ipcp.max_state = p[4]; 291588534Sjoerg sp->ipcp.compress_cid = p[5]; 291688534Sjoerg continue; 291788534Sjoerg } 291888534Sjoerg if (debug) 291988534Sjoerg log(-1, 292088534Sjoerg "compproto %#04x [not supported] ", 292188534Sjoerg desiredcomp); 292288534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 292388534Sjoerg p[3] = IPCP_COMP_VJ; 292488534Sjoerg p[4] = sp->ipcp.max_state; 292588534Sjoerg p[5] = sp->ipcp.compress_cid; 292688534Sjoerg break; 292725944Sjoerg case IPCP_OPT_ADDRESS: 292842104Sphk /* This is the address he wants in his end */ 292925944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 293025944Sjoerg p[4] << 8 | p[5]; 293133928Sphk if (desiredaddr == hisaddr || 293242104Sphk (hisaddr == 1 && desiredaddr != 0)) { 293325944Sjoerg /* 293425944Sjoerg * Peer's address is same as our value, 293570199Sjhay * or we have set it to 0.0.0.1 to 293633928Sphk * indicate that we do not really care, 293725944Sjoerg * this is agreeable. Gonna conf-ack 293825944Sjoerg * it. 293925944Sjoerg */ 294025944Sjoerg if (debug) 294169211Sphk log(-1, "%s [ack] ", 294242104Sphk sppp_dotted_quad(hisaddr)); 294325944Sjoerg /* record that we've seen it already */ 294425944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 294525944Sjoerg continue; 294625944Sjoerg } 294725944Sjoerg /* 294825944Sjoerg * The address wasn't agreeable. This is either 294925944Sjoerg * he sent us 0.0.0.0, asking to assign him an 295025944Sjoerg * address, or he send us another address not 295125944Sjoerg * matching our value. Either case, we gonna 295225944Sjoerg * conf-nak it with our value. 295342104Sphk * XXX: we should "rej" if hisaddr == 0 295425944Sjoerg */ 295525944Sjoerg if (debug) { 295625944Sjoerg if (desiredaddr == 0) 295769211Sphk log(-1, "[addr requested] "); 295825944Sjoerg else 295969211Sphk log(-1, "%s [not agreed] ", 296042104Sphk sppp_dotted_quad(desiredaddr)); 296125944Sjoerg 296225944Sjoerg } 296344235Sphk p[2] = hisaddr >> 24; 296444235Sphk p[3] = hisaddr >> 16; 296544235Sphk p[4] = hisaddr >> 8; 296644235Sphk p[5] = hisaddr; 296711189Sjkh break; 296825706Sjoerg } 296925944Sjoerg /* Add the option to nak'ed list. */ 297025944Sjoerg bcopy (p, r, p[1]); 297125944Sjoerg r += p[1]; 297225944Sjoerg rlen += p[1]; 297325944Sjoerg } 297425944Sjoerg 297525944Sjoerg /* 297625944Sjoerg * If we are about to conf-ack the request, but haven't seen 297725944Sjoerg * his address so far, gonna conf-nak it instead, with the 297825944Sjoerg * `address' option present and our idea of his address being 297925944Sjoerg * filled in there, to request negotiation of both addresses. 298025944Sjoerg * 298125944Sjoerg * XXX This can result in an endless req - nak loop if peer 298225944Sjoerg * doesn't want to send us his address. Q: What should we do 298325944Sjoerg * about it? XXX A: implement the max-failure counter. 298425944Sjoerg */ 298542104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 298625944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 298725944Sjoerg buf[1] = 6; 298825944Sjoerg buf[2] = hisaddr >> 24; 298925944Sjoerg buf[3] = hisaddr >> 16; 299025944Sjoerg buf[4] = hisaddr >> 8; 299125944Sjoerg buf[5] = hisaddr; 299225944Sjoerg rlen = 6; 299325706Sjoerg if (debug) 299469211Sphk log(-1, "still need hisaddr "); 299525944Sjoerg } 299625944Sjoerg 299725944Sjoerg if (rlen) { 299825706Sjoerg if (debug) 299969211Sphk log(-1, " send conf-nak\n"); 300025944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 300125944Sjoerg } else { 300225706Sjoerg if (debug) 300369211Sphk log(-1, " send conf-ack\n"); 300425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 300525944Sjoerg h->ident, origlen, h+1); 300625944Sjoerg } 300725944Sjoerg 300825944Sjoerg free (buf, M_TEMP); 300925944Sjoerg return (rlen == 0); 301025944Sjoerg} 301125944Sjoerg 301225944Sjoerg/* 301325944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 301425944Sjoerg * negotiation. 301525944Sjoerg */ 301625944Sjoergstatic void 301725944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 301825944Sjoerg{ 301925944Sjoerg u_char *buf, *p; 302025944Sjoerg struct ifnet *ifp = &sp->pp_if; 302125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 302225944Sjoerg 302325944Sjoerg len -= 4; 302425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 302525944Sjoerg if (!buf) 302625944Sjoerg return; 302725944Sjoerg 302825944Sjoerg if (debug) 302940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 303040008Sjoerg SPP_ARGS(ifp)); 303125944Sjoerg 303225944Sjoerg p = (void*) (h+1); 303325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 303425706Sjoerg if (debug) 303569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 303625944Sjoerg switch (*p) { 303788534Sjoerg case IPCP_OPT_COMPRESSION: 303888534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 303988534Sjoerg break; 304025944Sjoerg case IPCP_OPT_ADDRESS: 304125944Sjoerg /* 304225944Sjoerg * Peer doesn't grok address option. This is 304325944Sjoerg * bad. XXX Should we better give up here? 304442104Sphk * XXX We could try old "addresses" option... 304525944Sjoerg */ 304625944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 304725944Sjoerg break; 304825944Sjoerg } 30494910Swollman } 305025944Sjoerg if (debug) 305169211Sphk log(-1, "\n"); 305225944Sjoerg free (buf, M_TEMP); 305325944Sjoerg return; 30544910Swollman} 30554910Swollman 305625944Sjoerg/* 305725944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 305825944Sjoerg * negotiation. 305925944Sjoerg */ 306012820Sphkstatic void 306125944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 30624910Swollman{ 306325944Sjoerg u_char *buf, *p; 306425944Sjoerg struct ifnet *ifp = &sp->pp_if; 306525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 306688534Sjoerg int desiredcomp; 306725944Sjoerg u_long wantaddr; 30684910Swollman 306925944Sjoerg len -= 4; 307025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 307125944Sjoerg if (!buf) 307225944Sjoerg return; 307325944Sjoerg 307425944Sjoerg if (debug) 307540008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 307640008Sjoerg SPP_ARGS(ifp)); 307725944Sjoerg 307825944Sjoerg p = (void*) (h+1); 307925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 308025944Sjoerg if (debug) 308169211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 308225944Sjoerg switch (*p) { 308388534Sjoerg case IPCP_OPT_COMPRESSION: 308488534Sjoerg if (len >= 6 && p[1] == 6) { 308588534Sjoerg desiredcomp = p[2] << 8 | p[3]; 308688534Sjoerg if (debug) 308788534Sjoerg log(-1, "[wantcomp %#04x] ", 308888534Sjoerg desiredcomp); 308988534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 309088534Sjoerg sl_compress_init(&sp->pp_comp, p[4]); 309188534Sjoerg sp->ipcp.max_state = p[4]; 309288534Sjoerg sp->ipcp.compress_cid = p[5]; 309388534Sjoerg if (debug) 309488534Sjoerg log(-1, "[agree] "); 309588534Sjoerg } else 309688534Sjoerg sp->ipcp.opts &= 309788534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 309888534Sjoerg } 309988534Sjoerg break; 310025944Sjoerg case IPCP_OPT_ADDRESS: 310125944Sjoerg /* 310225944Sjoerg * Peer doesn't like our local IP address. See 310325944Sjoerg * if we can do something for him. We'll drop 310425944Sjoerg * him our address then. 310525944Sjoerg */ 310625944Sjoerg if (len >= 6 && p[1] == 6) { 310725944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 310825944Sjoerg p[4] << 8 | p[5]; 310925944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 311025944Sjoerg if (debug) 311169211Sphk log(-1, "[wantaddr %s] ", 311230300Sjoerg sppp_dotted_quad(wantaddr)); 311325944Sjoerg /* 311425944Sjoerg * When doing dynamic address assignment, 311525944Sjoerg * we accept his offer. Otherwise, we 311625944Sjoerg * ignore it and thus continue to negotiate 311725944Sjoerg * our already existing value. 311842104Sphk * XXX: Bogus, if he said no once, he'll 311942104Sphk * just say no again, might as well die. 312025944Sjoerg */ 312125944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 312225944Sjoerg sppp_set_ip_addr(sp, wantaddr); 312325944Sjoerg if (debug) 312469211Sphk log(-1, "[agree] "); 312542104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 312625944Sjoerg } 312725944Sjoerg } 312825944Sjoerg break; 312925944Sjoerg } 313025944Sjoerg } 313125944Sjoerg if (debug) 313269211Sphk log(-1, "\n"); 313325944Sjoerg free (buf, M_TEMP); 313425944Sjoerg return; 31354910Swollman} 31364910Swollman 313712820Sphkstatic void 313825944Sjoergsppp_ipcp_tlu(struct sppp *sp) 31394910Swollman{ 314042104Sphk /* we are up - notify isdn daemon */ 314142104Sphk if (sp->pp_con) 314242104Sphk sp->pp_con(sp); 31434910Swollman} 31444910Swollman 314525944Sjoergstatic void 314625944Sjoergsppp_ipcp_tld(struct sppp *sp) 314725944Sjoerg{ 314825944Sjoerg} 314925944Sjoerg 315025944Sjoergstatic void 315125944Sjoergsppp_ipcp_tls(struct sppp *sp) 315225944Sjoerg{ 315325944Sjoerg /* indicate to LCP that it must stay alive */ 315425944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 315525944Sjoerg} 315625944Sjoerg 315725944Sjoergstatic void 315825944Sjoergsppp_ipcp_tlf(struct sppp *sp) 315925944Sjoerg{ 316025944Sjoerg /* we no longer need LCP */ 316125944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 316230300Sjoerg sppp_lcp_check_and_close(sp); 316325944Sjoerg} 316425944Sjoerg 316525944Sjoergstatic void 316625944Sjoergsppp_ipcp_scr(struct sppp *sp) 316725944Sjoerg{ 316825944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 316925944Sjoerg u_long ouraddr; 317025944Sjoerg int i = 0; 317125944Sjoerg 317288534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 317388534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 317488534Sjoerg opt[i++] = 6; 317588534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 317688534Sjoerg opt[i++] = IPCP_COMP_VJ; 317788534Sjoerg opt[i++] = sp->ipcp.max_state; 317888534Sjoerg opt[i++] = sp->ipcp.compress_cid; 317988534Sjoerg } 318025944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 318130300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 318225944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 318325944Sjoerg opt[i++] = 6; 318425944Sjoerg opt[i++] = ouraddr >> 24; 318525944Sjoerg opt[i++] = ouraddr >> 16; 318625944Sjoerg opt[i++] = ouraddr >> 8; 318725944Sjoerg opt[i++] = ouraddr; 318825944Sjoerg } 318925944Sjoerg 319078064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 319125944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 319225944Sjoerg} 319325944Sjoerg 319470199Sjhay/* 319530300Sjoerg *--------------------------------------------------------------------------* 319630300Sjoerg * * 319778064Sume * The IPv6CP implementation. * 319878064Sume * * 319978064Sume *--------------------------------------------------------------------------* 320078064Sume */ 320178064Sume 320278064Sume#ifdef INET6 320378064Sumestatic void 320478064Sumesppp_ipv6cp_init(struct sppp *sp) 320578064Sume{ 320678064Sume sp->ipv6cp.opts = 0; 320778064Sume sp->ipv6cp.flags = 0; 320878064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 320978064Sume sp->fail_counter[IDX_IPV6CP] = 0; 321078064Sume sp->pp_seq[IDX_IPV6CP] = 0; 321178064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 321278064Sume#if defined(__NetBSD__) 321378064Sume callout_init(&sp->ch[IDX_IPV6CP]); 321478064Sume#endif 321578064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 321678064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 321778064Sume#endif 321878064Sume} 321978064Sume 322078064Sumestatic void 322178064Sumesppp_ipv6cp_up(struct sppp *sp) 322278064Sume{ 322378064Sume sppp_up_event(&ipv6cp, sp); 322478064Sume} 322578064Sume 322678064Sumestatic void 322778064Sumesppp_ipv6cp_down(struct sppp *sp) 322878064Sume{ 322978064Sume sppp_down_event(&ipv6cp, sp); 323078064Sume} 323178064Sume 323278064Sumestatic void 323378064Sumesppp_ipv6cp_open(struct sppp *sp) 323478064Sume{ 323578064Sume STDDCL; 323678064Sume struct in6_addr myaddr, hisaddr; 323778064Sume 323878064Sume#ifdef IPV6CP_MYIFID_DYN 323978064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 324078064Sume#else 324178064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 324278064Sume#endif 324378064Sume 324478064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 324578064Sume /* 324678064Sume * If we don't have our address, this probably means our 324778064Sume * interface doesn't want to talk IPv6 at all. (This could 324878064Sume * be the case if somebody wants to speak only IPX, for 324978064Sume * example.) Don't open IPv6CP in this case. 325078064Sume */ 325178064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 325278064Sume /* XXX this message should go away */ 325378064Sume if (debug) 325478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 325578064Sume SPP_ARGS(ifp)); 325678064Sume return; 325778064Sume } 325878064Sume 325978064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 326078064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 326178064Sume sppp_open_event(&ipv6cp, sp); 326278064Sume} 326378064Sume 326478064Sumestatic void 326578064Sumesppp_ipv6cp_close(struct sppp *sp) 326678064Sume{ 326778064Sume sppp_close_event(&ipv6cp, sp); 326878064Sume} 326978064Sume 327078064Sumestatic void 327178064Sumesppp_ipv6cp_TO(void *cookie) 327278064Sume{ 327378064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 327478064Sume} 327578064Sume 327678064Sume/* 327778064Sume * Analyze a configure request. Return true if it was agreeable, and 327878064Sume * caused action sca, false if it has been rejected or nak'ed, and 327978064Sume * caused action scn. (The return value is used to make the state 328078064Sume * transition decision in the state automaton.) 328178064Sume */ 328278064Sumestatic int 328378064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 328478064Sume{ 328578064Sume u_char *buf, *r, *p; 328678064Sume struct ifnet *ifp = &sp->pp_if; 328778064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 328878064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 328978064Sume int ifidcount; 329078064Sume int type; 329178064Sume int collision, nohisaddr; 329278064Sume 329378064Sume len -= 4; 329478064Sume origlen = len; 329578064Sume /* 329678064Sume * Make sure to allocate a buf that can at least hold a 329778064Sume * conf-nak with an `address' option. We might need it below. 329878064Sume */ 329978064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 330078064Sume if (! buf) 330178064Sume return (0); 330278064Sume 330378064Sume /* pass 1: see if we can recognize them */ 330478064Sume if (debug) 330578064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 330678064Sume SPP_ARGS(ifp)); 330778064Sume p = (void*) (h+1); 330878064Sume ifidcount = 0; 330978064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 331078064Sume if (debug) 331178176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 331278064Sume switch (*p) { 331378064Sume case IPV6CP_OPT_IFID: 331478064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 331578064Sume /* correctly formed address option */ 331678064Sume ifidcount++; 331778064Sume continue; 331878064Sume } 331978064Sume if (debug) 332078176Sume log(-1, " [invalid]"); 332178064Sume break; 332278064Sume#ifdef notyet 332378064Sume case IPV6CP_OPT_COMPRESSION: 332478064Sume if (len >= 4 && p[1] >= 4) { 332578064Sume /* correctly formed compress option */ 332678064Sume continue; 332778064Sume } 332878064Sume if (debug) 332978176Sume log(-1, " [invalid]"); 333078064Sume break; 333178064Sume#endif 333278064Sume default: 333378064Sume /* Others not supported. */ 333478064Sume if (debug) 333578176Sume log(-1, " [rej]"); 333678064Sume break; 333778064Sume } 333878064Sume /* Add the option to rejected list. */ 333978064Sume bcopy (p, r, p[1]); 334078064Sume r += p[1]; 334178064Sume rlen += p[1]; 334278064Sume } 334378064Sume if (rlen) { 334478064Sume if (debug) 334578176Sume log(-1, " send conf-rej\n"); 334678064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 334778064Sume goto end; 334878064Sume } else if (debug) 334978176Sume log(-1, "\n"); 335078064Sume 335178064Sume /* pass 2: parse option values */ 335278064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 335378064Sume if (debug) 335478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 335578064Sume SPP_ARGS(ifp)); 335678064Sume p = (void*) (h+1); 335778064Sume len = origlen; 335878064Sume type = CONF_ACK; 335978064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 336078064Sume if (debug) 336178176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 336278064Sume switch (*p) { 336378064Sume#ifdef notyet 336478064Sume case IPV6CP_OPT_COMPRESSION: 336578064Sume continue; 336678064Sume#endif 336778064Sume case IPV6CP_OPT_IFID: 336878064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 336978064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 337078064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 337178064Sume &myaddr.s6_addr[8], 8) == 0); 337278064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 337378064Sume 337478064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 337578064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 337678064Sume 337778064Sume if (!collision && !nohisaddr) { 337878064Sume /* no collision, hisaddr known - Conf-Ack */ 337978064Sume type = CONF_ACK; 338078064Sume 338178064Sume if (debug) { 338278176Sume log(-1, " %s [%s]", 338378064Sume ip6_sprintf(&desiredaddr), 338478064Sume sppp_cp_type_name(type)); 338578064Sume } 338678064Sume continue; 338778064Sume } 338878064Sume 338978064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 339078064Sume if (collision && nohisaddr) { 339178064Sume /* collision, hisaddr unknown - Conf-Rej */ 339278064Sume type = CONF_REJ; 339378064Sume bzero(&p[2], 8); 339478064Sume } else { 339578064Sume /* 339678064Sume * - no collision, hisaddr unknown, or 339778064Sume * - collision, hisaddr known 339878064Sume * Conf-Nak, suggest hisaddr 339978064Sume */ 340078064Sume type = CONF_NAK; 340178064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 340278064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 340378064Sume } 340478064Sume if (debug) 340578176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 340678064Sume sppp_cp_type_name(type)); 340778064Sume break; 340878064Sume } 340978064Sume /* Add the option to nak'ed list. */ 341078064Sume bcopy (p, r, p[1]); 341178064Sume r += p[1]; 341278064Sume rlen += p[1]; 341378064Sume } 341478064Sume 341578064Sume if (rlen == 0 && type == CONF_ACK) { 341678064Sume if (debug) 341778176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 341878064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 341978064Sume } else { 342078064Sume#ifdef DIAGNOSTIC 342178064Sume if (type == CONF_ACK) 342278064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 342378064Sume#endif 342478064Sume 342578064Sume if (debug) { 342678176Sume log(-1, " send %s suggest %s\n", 342778064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 342878064Sume } 342978064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 343078064Sume } 343178064Sume 343278064Sume end: 343378064Sume free (buf, M_TEMP); 343478064Sume return (rlen == 0); 343578064Sume} 343678064Sume 343778064Sume/* 343878064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 343978064Sume * negotiation. 344078064Sume */ 344178064Sumestatic void 344278064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 344378064Sume{ 344478064Sume u_char *buf, *p; 344578064Sume struct ifnet *ifp = &sp->pp_if; 344678064Sume int debug = ifp->if_flags & IFF_DEBUG; 344778064Sume 344878064Sume len -= 4; 344978064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 345078064Sume if (!buf) 345178064Sume return; 345278064Sume 345378064Sume if (debug) 345478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 345578064Sume SPP_ARGS(ifp)); 345678064Sume 345778064Sume p = (void*) (h+1); 345878064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 345978064Sume if (debug) 346078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 346178064Sume switch (*p) { 346278064Sume case IPV6CP_OPT_IFID: 346378064Sume /* 346478064Sume * Peer doesn't grok address option. This is 346578064Sume * bad. XXX Should we better give up here? 346678064Sume */ 346778064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 346878064Sume break; 346978064Sume#ifdef notyet 347078064Sume case IPV6CP_OPT_COMPRESS: 347178064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 347278064Sume break; 347378064Sume#endif 347478064Sume } 347578064Sume } 347678064Sume if (debug) 347778176Sume log(-1, "\n"); 347878064Sume free (buf, M_TEMP); 347978064Sume return; 348078064Sume} 348178064Sume 348278064Sume/* 348378064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 348478064Sume * negotiation. 348578064Sume */ 348678064Sumestatic void 348778064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 348878064Sume{ 348978064Sume u_char *buf, *p; 349078064Sume struct ifnet *ifp = &sp->pp_if; 349178064Sume int debug = ifp->if_flags & IFF_DEBUG; 349278064Sume struct in6_addr suggestaddr; 349378064Sume 349478064Sume len -= 4; 349578064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 349678064Sume if (!buf) 349778064Sume return; 349878064Sume 349978064Sume if (debug) 350078064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 350178064Sume SPP_ARGS(ifp)); 350278064Sume 350378064Sume p = (void*) (h+1); 350478064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 350578064Sume if (debug) 350678176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 350778064Sume switch (*p) { 350878064Sume case IPV6CP_OPT_IFID: 350978064Sume /* 351078064Sume * Peer doesn't like our local ifid. See 351178064Sume * if we can do something for him. We'll drop 351278064Sume * him our address then. 351378064Sume */ 351478064Sume if (len < 10 || p[1] != 10) 351578064Sume break; 351678064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 351778064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 351878064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 351978064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 352078064Sume 352178064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 352278064Sume if (debug) 352378176Sume log(-1, " [suggestaddr %s]", 352478064Sume ip6_sprintf(&suggestaddr)); 352578064Sume#ifdef IPV6CP_MYIFID_DYN 352678064Sume /* 352778064Sume * When doing dynamic address assignment, 352878064Sume * we accept his offer. 352978064Sume */ 353078064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 353178064Sume struct in6_addr lastsuggest; 353278064Sume /* 353378064Sume * If <suggested myaddr from peer> equals to 353478064Sume * <hisaddr we have suggested last time>, 353578064Sume * we have a collision. generate new random 353678064Sume * ifid. 353778064Sume */ 353878064Sume sppp_suggest_ip6_addr(&lastsuggest); 353978064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 354078064Sume lastsuggest)) { 354178064Sume if (debug) 354278176Sume log(-1, " [random]"); 354378064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 354478064Sume } 354578064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 354678064Sume if (debug) 354778176Sume log(-1, " [agree]"); 354878064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 354978064Sume } 355078064Sume#else 355178064Sume /* 355278064Sume * Since we do not do dynamic address assignment, 355378064Sume * we ignore it and thus continue to negotiate 355478064Sume * our already existing value. This can possibly 355578064Sume * go into infinite request-reject loop. 355678064Sume * 355778064Sume * This is not likely because we normally use 355878064Sume * ifid based on MAC-address. 355978064Sume * If you have no ethernet card on the node, too bad. 356078064Sume * XXX should we use fail_counter? 356178064Sume */ 356278064Sume#endif 356378064Sume break; 356478064Sume#ifdef notyet 356578064Sume case IPV6CP_OPT_COMPRESS: 356678064Sume /* 356778064Sume * Peer wants different compression parameters. 356878064Sume */ 356978064Sume break; 357078064Sume#endif 357178064Sume } 357278064Sume } 357378064Sume if (debug) 357478176Sume log(-1, "\n"); 357578064Sume free (buf, M_TEMP); 357678064Sume return; 357778064Sume} 357878064Sumestatic void 357978064Sumesppp_ipv6cp_tlu(struct sppp *sp) 358078064Sume{ 358178064Sume /* we are up - notify isdn daemon */ 358278064Sume if (sp->pp_con) 358378064Sume sp->pp_con(sp); 358478064Sume} 358578064Sume 358678064Sumestatic void 358778064Sumesppp_ipv6cp_tld(struct sppp *sp) 358878064Sume{ 358978064Sume} 359078064Sume 359178064Sumestatic void 359278064Sumesppp_ipv6cp_tls(struct sppp *sp) 359378064Sume{ 359478064Sume /* indicate to LCP that it must stay alive */ 359578064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 359678064Sume} 359778064Sume 359878064Sumestatic void 359978064Sumesppp_ipv6cp_tlf(struct sppp *sp) 360078064Sume{ 360178064Sume 360278064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 360378064Sume /* we no longer need LCP */ 360478064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 360578064Sume sppp_lcp_check_and_close(sp); 360678064Sume#endif 360778064Sume} 360878064Sume 360978064Sumestatic void 361078064Sumesppp_ipv6cp_scr(struct sppp *sp) 361178064Sume{ 361278064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 361378064Sume struct in6_addr ouraddr; 361478064Sume int i = 0; 361578064Sume 361678064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 361778064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 361878064Sume opt[i++] = IPV6CP_OPT_IFID; 361978064Sume opt[i++] = 10; 362078064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 362178064Sume i += 8; 362278064Sume } 362378064Sume 362478064Sume#ifdef notyet 362578064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 362678064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 362778064Sume opt[i++] = 4; 362878064Sume opt[i++] = 0; /* TBD */ 362978064Sume opt[i++] = 0; /* TBD */ 363078064Sume /* variable length data may follow */ 363178064Sume } 363278064Sume#endif 363378064Sume 363478064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 363578064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 363678064Sume} 363778064Sume#else /*INET6*/ 363878064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 363978064Sume{ 364078064Sume} 364178064Sume 364278064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 364378064Sume{ 364478064Sume} 364578064Sume 364678064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 364778064Sume{ 364878064Sume} 364978064Sume 365078064Sume 365178064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 365278064Sume{ 365378064Sume} 365478064Sume 365578064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 365678064Sume{ 365778064Sume} 365878064Sume 365978064Sumestatic void sppp_ipv6cp_TO(void *sp) 366078064Sume{ 366178064Sume} 366278064Sume 366378064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 366478064Sume{ 366578064Sume return 0; 366678064Sume} 366778064Sume 366878064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 366978064Sume{ 367078064Sume} 367178064Sume 367278064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 367378064Sume{ 367478064Sume} 367578064Sume 367678064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 367778064Sume{ 367878064Sume} 367978064Sume 368078064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 368178064Sume{ 368278064Sume} 368378064Sume 368478064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 368578064Sume{ 368678064Sume} 368778064Sume 368878064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 368978064Sume{ 369078064Sume} 369178064Sume 369278064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 369378064Sume{ 369478064Sume} 369578064Sume#endif /*INET6*/ 369678064Sume 369778064Sume/* 369878064Sume *--------------------------------------------------------------------------* 369978064Sume * * 370030300Sjoerg * The CHAP implementation. * 370130300Sjoerg * * 370230300Sjoerg *--------------------------------------------------------------------------* 370330300Sjoerg */ 370430300Sjoerg 370530300Sjoerg/* 370630300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 370730300Sjoerg * the control protocols do, since they do have Open and Close events, but 370830300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 370930300Sjoerg * authentication protocols may be different in both directions (this makes 371030300Sjoerg * sense, think of a machine that never accepts incoming calls but only 371130300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 371230300Sjoerg * 371330300Sjoerg * Our state machine for the local authentication protocol (we are requesting 371430300Sjoerg * the peer to authenticate) looks like: 371530300Sjoerg * 371630300Sjoerg * RCA- 371730300Sjoerg * +--------------------------------------------+ 371830300Sjoerg * V scn,tld| 371930300Sjoerg * +--------+ Close +---------+ RCA+ 372030300Sjoerg * | |<----------------------------------| |------+ 372130300Sjoerg * +--->| Closed | TO* | Opened | sca | 372230300Sjoerg * | | |-----+ +-------| |<-----+ 372330300Sjoerg * | +--------+ irc | | +---------+ 372430300Sjoerg * | ^ | | ^ 372530300Sjoerg * | | | | | 372630300Sjoerg * | | | | | 372730300Sjoerg * | TO-| | | | 372830300Sjoerg * | |tld TO+ V | | 372930300Sjoerg * | | +------->+ | | 373030300Sjoerg * | | | | | | 373130300Sjoerg * | +--------+ V | | 373230300Sjoerg * | | |<----+<--------------------+ | 373330300Sjoerg * | | Req- | scr | 373430300Sjoerg * | | Sent | | 373530300Sjoerg * | | | | 373630300Sjoerg * | +--------+ | 373730300Sjoerg * | RCA- | | RCA+ | 373830300Sjoerg * +------+ +------------------------------------------+ 373930300Sjoerg * scn,tld sca,irc,ict,tlu 374030300Sjoerg * 374130300Sjoerg * 374230300Sjoerg * with: 374330300Sjoerg * 374430300Sjoerg * Open: LCP reached authentication phase 374530300Sjoerg * Close: LCP reached terminate phase 374630300Sjoerg * 374730300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 374830300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 374930300Sjoerg * TO+: timeout with restart counter >= 0 375030300Sjoerg * TO-: timeout with restart counter < 0 375130300Sjoerg * TO*: reschedule timeout for CHAP 375230300Sjoerg * 375330300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 375430300Sjoerg * sca: send ack packet (pap-ack, chap-success) 375530300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 375630300Sjoerg * ict: initialize re-challenge timer (CHAP only) 375730300Sjoerg * 375830300Sjoerg * tlu: this-layer-up, LCP reaches network phase 375930300Sjoerg * tld: this-layer-down, LCP enters terminate phase 376030300Sjoerg * 376130300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 376230300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 376330300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 376430300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 376530300Sjoerg * causing LCP to enter terminate phase. 376630300Sjoerg * 376730300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 376830300Sjoerg * expected to send one based on the successful negotiation of PAP as 376930300Sjoerg * the authentication protocol during the LCP option negotiation. 377030300Sjoerg * 377130300Sjoerg * Incoming authentication protocol requests (remote requests 377230300Sjoerg * authentication, we are peer) don't employ a state machine at all, 377330300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 377430300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 377530300Sjoerg * still in authentication phase (thereby violating the standard that 377630300Sjoerg * demands that these NCP packets are to be discarded), so we keep 377730300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 377830300Sjoerg * phase network once we've seen a positive acknowledge for the 377930300Sjoerg * authentication. 378030300Sjoerg */ 378130300Sjoerg 378230300Sjoerg/* 378330300Sjoerg * Handle incoming CHAP packets. 378430300Sjoerg */ 378530300Sjoergvoid 378630300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 378730300Sjoerg{ 378830300Sjoerg STDDCL; 378930300Sjoerg struct lcp_header *h; 379030300Sjoerg int len, x; 379130300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 379230300Sjoerg int value_len, name_len; 379330300Sjoerg MD5_CTX ctx; 379430300Sjoerg 379530300Sjoerg len = m->m_pkthdr.len; 379630300Sjoerg if (len < 4) { 379730300Sjoerg if (debug) 379830300Sjoerg log(LOG_DEBUG, 379940008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 380040008Sjoerg SPP_ARGS(ifp), len); 380130300Sjoerg return; 380230300Sjoerg } 380330300Sjoerg h = mtod (m, struct lcp_header*); 380430300Sjoerg if (len > ntohs (h->len)) 380530300Sjoerg len = ntohs (h->len); 380630300Sjoerg 380730300Sjoerg switch (h->type) { 380830300Sjoerg /* challenge, failure and success are his authproto */ 380930300Sjoerg case CHAP_CHALLENGE: 381030300Sjoerg value = 1 + (u_char*)(h+1); 381130300Sjoerg value_len = value[-1]; 381230300Sjoerg name = value + value_len; 381330300Sjoerg name_len = len - value_len - 5; 381430300Sjoerg if (name_len < 0) { 381530300Sjoerg if (debug) { 381630300Sjoerg log(LOG_DEBUG, 381740008Sjoerg SPP_FMT "chap corrupted challenge " 381830300Sjoerg "<%s id=0x%x len=%d", 381940008Sjoerg SPP_ARGS(ifp), 382030300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 382130300Sjoerg h->ident, ntohs(h->len)); 382244145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 382369211Sphk log(-1, ">\n"); 382430300Sjoerg } 382530300Sjoerg break; 382630300Sjoerg } 382770199Sjhay 382830300Sjoerg if (debug) { 382930300Sjoerg log(LOG_DEBUG, 383040008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 383140008Sjoerg SPP_ARGS(ifp), 383230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 383330300Sjoerg ntohs(h->len)); 383430300Sjoerg sppp_print_string((char*) name, name_len); 383569211Sphk log(-1, " value-size=%d value=", value_len); 383630300Sjoerg sppp_print_bytes(value, value_len); 383769211Sphk log(-1, ">\n"); 383830300Sjoerg } 383930300Sjoerg 384030300Sjoerg /* Compute reply value. */ 384130300Sjoerg MD5Init(&ctx); 384230300Sjoerg MD5Update(&ctx, &h->ident, 1); 384330300Sjoerg MD5Update(&ctx, sp->myauth.secret, 384430300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 384530300Sjoerg MD5Update(&ctx, value, value_len); 384630300Sjoerg MD5Final(digest, &ctx); 384730300Sjoerg dsize = sizeof digest; 384830300Sjoerg 384930300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 385030300Sjoerg sizeof dsize, (const char *)&dsize, 385130300Sjoerg sizeof digest, digest, 385240008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 385330300Sjoerg sp->myauth.name, 385430300Sjoerg 0); 385530300Sjoerg break; 385630300Sjoerg 385730300Sjoerg case CHAP_SUCCESS: 385830300Sjoerg if (debug) { 385940008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 386040008Sjoerg SPP_ARGS(ifp)); 386130300Sjoerg if (len > 4) { 386269211Sphk log(-1, ": "); 386330300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 386430300Sjoerg } 386569211Sphk log(-1, "\n"); 386630300Sjoerg } 386730300Sjoerg x = splimp(); 386830300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 386930300Sjoerg if (sp->myauth.proto == PPP_CHAP && 387032169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 387130300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 387230300Sjoerg /* 387330300Sjoerg * We are authenticator for CHAP but didn't 387430300Sjoerg * complete yet. Leave it to tlu to proceed 387530300Sjoerg * to network phase. 387630300Sjoerg */ 387730300Sjoerg splx(x); 387830300Sjoerg break; 387930300Sjoerg } 388030300Sjoerg splx(x); 388130300Sjoerg sppp_phase_network(sp); 388230300Sjoerg break; 388330300Sjoerg 388430300Sjoerg case CHAP_FAILURE: 388530300Sjoerg if (debug) { 388640008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 388740008Sjoerg SPP_ARGS(ifp)); 388830300Sjoerg if (len > 4) { 388969211Sphk log(-1, ": "); 389030300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 389130300Sjoerg } 389269211Sphk log(-1, "\n"); 389330300Sjoerg } else 389440008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 389540008Sjoerg SPP_ARGS(ifp)); 389630300Sjoerg /* await LCP shutdown by authenticator */ 389730300Sjoerg break; 389830300Sjoerg 389930300Sjoerg /* response is my authproto */ 390030300Sjoerg case CHAP_RESPONSE: 390130300Sjoerg value = 1 + (u_char*)(h+1); 390230300Sjoerg value_len = value[-1]; 390330300Sjoerg name = value + value_len; 390430300Sjoerg name_len = len - value_len - 5; 390530300Sjoerg if (name_len < 0) { 390630300Sjoerg if (debug) { 390730300Sjoerg log(LOG_DEBUG, 390840008Sjoerg SPP_FMT "chap corrupted response " 390930300Sjoerg "<%s id=0x%x len=%d", 391040008Sjoerg SPP_ARGS(ifp), 391130300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 391230300Sjoerg h->ident, ntohs(h->len)); 391344145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 391469211Sphk log(-1, ">\n"); 391530300Sjoerg } 391630300Sjoerg break; 391730300Sjoerg } 391830300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 391930300Sjoerg if (debug) 392030300Sjoerg log(LOG_DEBUG, 392140008Sjoerg SPP_FMT "chap dropping response for old ID " 392230300Sjoerg "(got %d, expected %d)\n", 392340008Sjoerg SPP_ARGS(ifp), 392430300Sjoerg h->ident, sp->confid[IDX_CHAP]); 392530300Sjoerg break; 392630300Sjoerg } 392730300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 392830300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 392940008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 393040008Sjoerg SPP_ARGS(ifp)); 393130300Sjoerg sppp_print_string(name, name_len); 393269211Sphk log(-1, " != expected "); 393330300Sjoerg sppp_print_string(sp->hisauth.name, 393430300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 393569211Sphk log(-1, "\n"); 393670199Sjhay } 393730300Sjoerg if (debug) { 393840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 393930300Sjoerg "<%s id=0x%x len=%d name=", 394040008Sjoerg SPP_ARGS(ifp), 394130300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 394230300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 394330300Sjoerg h->ident, ntohs (h->len)); 394430300Sjoerg sppp_print_string((char*)name, name_len); 394569211Sphk log(-1, " value-size=%d value=", value_len); 394630300Sjoerg sppp_print_bytes(value, value_len); 394769211Sphk log(-1, ">\n"); 394830300Sjoerg } 394930300Sjoerg if (value_len != AUTHKEYLEN) { 395030300Sjoerg if (debug) 395130300Sjoerg log(LOG_DEBUG, 395240008Sjoerg SPP_FMT "chap bad hash value length: " 395330300Sjoerg "%d bytes, should be %d\n", 395440008Sjoerg SPP_ARGS(ifp), value_len, 395530300Sjoerg AUTHKEYLEN); 395630300Sjoerg break; 395730300Sjoerg } 395830300Sjoerg 395930300Sjoerg MD5Init(&ctx); 396030300Sjoerg MD5Update(&ctx, &h->ident, 1); 396130300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 396230300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 396330300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 396430300Sjoerg MD5Final(digest, &ctx); 396530300Sjoerg 396630300Sjoerg#define FAILMSG "Failed..." 396730300Sjoerg#define SUCCMSG "Welcome!" 396830300Sjoerg 396930300Sjoerg if (value_len != sizeof digest || 397030300Sjoerg bcmp(digest, value, value_len) != 0) { 397130300Sjoerg /* action scn, tld */ 397230300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 397330300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 397430300Sjoerg 0); 397530300Sjoerg chap.tld(sp); 397630300Sjoerg break; 397730300Sjoerg } 397830300Sjoerg /* action sca, perhaps tlu */ 397930300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 398030300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 398130300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 398230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 398330300Sjoerg 0); 398430300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 398530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 398630300Sjoerg chap.tlu(sp); 398730300Sjoerg } 398830300Sjoerg break; 398930300Sjoerg 399030300Sjoerg default: 399130300Sjoerg /* Unknown CHAP packet type -- ignore. */ 399230300Sjoerg if (debug) { 399340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 399430300Sjoerg "<0x%x id=0x%xh len=%d", 399540008Sjoerg SPP_ARGS(ifp), 399630300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 399730300Sjoerg h->type, h->ident, ntohs(h->len)); 399844145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 399969211Sphk log(-1, ">\n"); 400030300Sjoerg } 400130300Sjoerg break; 400230300Sjoerg 400330300Sjoerg } 400430300Sjoerg} 400530300Sjoerg 400630300Sjoergstatic void 400730300Sjoergsppp_chap_init(struct sppp *sp) 400830300Sjoerg{ 400930300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 401030300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 401130300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 401278064Sume sp->pp_seq[IDX_CHAP] = 0; 401378064Sume sp->pp_rseq[IDX_CHAP] = 0; 401442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 401530300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 401640008Sjoerg#endif 401730300Sjoerg} 401830300Sjoerg 401930300Sjoergstatic void 402030300Sjoergsppp_chap_open(struct sppp *sp) 402130300Sjoerg{ 402230300Sjoerg if (sp->myauth.proto == PPP_CHAP && 402330300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 402430300Sjoerg /* we are authenticator for CHAP, start it */ 402530300Sjoerg chap.scr(sp); 402630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 402730300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 402830300Sjoerg } 402930300Sjoerg /* nothing to be done if we are peer, await a challenge */ 403030300Sjoerg} 403130300Sjoerg 403230300Sjoergstatic void 403330300Sjoergsppp_chap_close(struct sppp *sp) 403430300Sjoerg{ 403530300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 403630300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 403730300Sjoerg} 403830300Sjoerg 403930300Sjoergstatic void 404030300Sjoergsppp_chap_TO(void *cookie) 404130300Sjoerg{ 404230300Sjoerg struct sppp *sp = (struct sppp *)cookie; 404330300Sjoerg STDDCL; 404430300Sjoerg int s; 404530300Sjoerg 404630300Sjoerg s = splimp(); 404730300Sjoerg if (debug) 404840008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 404940008Sjoerg SPP_ARGS(ifp), 405030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 405130300Sjoerg sp->rst_counter[IDX_CHAP]); 405230300Sjoerg 405330300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 405430300Sjoerg /* TO- event */ 405530300Sjoerg switch (sp->state[IDX_CHAP]) { 405630300Sjoerg case STATE_REQ_SENT: 405730300Sjoerg chap.tld(sp); 405830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 405930300Sjoerg break; 406030300Sjoerg } 406130300Sjoerg else 406230300Sjoerg /* TO+ (or TO*) event */ 406330300Sjoerg switch (sp->state[IDX_CHAP]) { 406430300Sjoerg case STATE_OPENED: 406530300Sjoerg /* TO* event */ 406630300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 406730300Sjoerg /* fall through */ 406830300Sjoerg case STATE_REQ_SENT: 406930300Sjoerg chap.scr(sp); 407030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 407130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 407230300Sjoerg break; 407330300Sjoerg } 407430300Sjoerg 407530300Sjoerg splx(s); 407630300Sjoerg} 407730300Sjoerg 407830300Sjoergstatic void 407930300Sjoergsppp_chap_tlu(struct sppp *sp) 408030300Sjoerg{ 408130300Sjoerg STDDCL; 408230300Sjoerg int i, x; 408330300Sjoerg 408440010Sjoerg i = 0; 408530300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 408630300Sjoerg 408730300Sjoerg /* 408830300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 408930300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 409030300Sjoerg * initial challenge-response exchange has taken place. 409130300Sjoerg * Provide for an option to avoid rechallenges. 409230300Sjoerg */ 409330300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 409430300Sjoerg /* 409530300Sjoerg * Compute the re-challenge timeout. This will yield 409630300Sjoerg * a number between 300 and 810 seconds. 409730300Sjoerg */ 409830300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 409942064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 410030300Sjoerg } 410130300Sjoerg 410230300Sjoerg if (debug) { 410330300Sjoerg log(LOG_DEBUG, 410440008Sjoerg SPP_FMT "chap %s, ", 410540008Sjoerg SPP_ARGS(ifp), 410630300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 410730300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 410869211Sphk log(-1, "next re-challenge in %d seconds\n", i); 410930300Sjoerg else 411069211Sphk log(-1, "re-challenging supressed\n"); 411130300Sjoerg } 411230300Sjoerg 411330300Sjoerg x = splimp(); 411430300Sjoerg /* indicate to LCP that we need to be closed down */ 411530300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 411630300Sjoerg 411730300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 411830300Sjoerg /* 411930300Sjoerg * Remote is authenticator, but his auth proto didn't 412030300Sjoerg * complete yet. Defer the transition to network 412130300Sjoerg * phase. 412230300Sjoerg */ 412330300Sjoerg splx(x); 412430300Sjoerg return; 412530300Sjoerg } 412630300Sjoerg splx(x); 412730300Sjoerg 412830300Sjoerg /* 412930300Sjoerg * If we are already in phase network, we are done here. This 413030300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 413130300Sjoerg */ 413230300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 413330300Sjoerg sppp_phase_network(sp); 413430300Sjoerg} 413530300Sjoerg 413630300Sjoergstatic void 413730300Sjoergsppp_chap_tld(struct sppp *sp) 413830300Sjoerg{ 413930300Sjoerg STDDCL; 414030300Sjoerg 414130300Sjoerg if (debug) 414240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 414340008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 414430300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 414530300Sjoerg 414630300Sjoerg lcp.Close(sp); 414730300Sjoerg} 414830300Sjoerg 414930300Sjoergstatic void 415030300Sjoergsppp_chap_scr(struct sppp *sp) 415130300Sjoerg{ 415230300Sjoerg u_long *ch, seed; 415330300Sjoerg u_char clen; 415430300Sjoerg 415530300Sjoerg /* Compute random challenge. */ 415630300Sjoerg ch = (u_long *)sp->myauth.challenge; 415742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 415835064Sphk read_random(&seed, sizeof seed); 415940008Sjoerg#else 416042104Sphk { 416142104Sphk struct timeval tv; 416240008Sjoerg microtime(&tv); 416340008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 416442104Sphk } 416540008Sjoerg#endif 416630300Sjoerg ch[0] = seed ^ random(); 416730300Sjoerg ch[1] = seed ^ random(); 416830300Sjoerg ch[2] = seed ^ random(); 416930300Sjoerg ch[3] = seed ^ random(); 417030300Sjoerg clen = AUTHKEYLEN; 417130300Sjoerg 417278064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 417330300Sjoerg 417430300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 417530300Sjoerg sizeof clen, (const char *)&clen, 417640008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 417740008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 417830300Sjoerg sp->myauth.name, 417930300Sjoerg 0); 418030300Sjoerg} 418170199Sjhay 418270199Sjhay/* 418330300Sjoerg *--------------------------------------------------------------------------* 418430300Sjoerg * * 418530300Sjoerg * The PAP implementation. * 418630300Sjoerg * * 418730300Sjoerg *--------------------------------------------------------------------------* 418830300Sjoerg */ 418930300Sjoerg/* 419030300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 419130300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 419230300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 419330300Sjoerg * retry counter is expired). 419430300Sjoerg */ 419530300Sjoerg 419630300Sjoerg/* 419730300Sjoerg * Handle incoming PAP packets. */ 419830300Sjoergstatic void 419930300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 420030300Sjoerg{ 420130300Sjoerg STDDCL; 420230300Sjoerg struct lcp_header *h; 420330300Sjoerg int len, x; 420430300Sjoerg u_char *name, *passwd, mlen; 420530300Sjoerg int name_len, passwd_len; 420630300Sjoerg 420730300Sjoerg len = m->m_pkthdr.len; 420830300Sjoerg if (len < 5) { 420930300Sjoerg if (debug) 421030300Sjoerg log(LOG_DEBUG, 421140008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 421240008Sjoerg SPP_ARGS(ifp), len); 421330300Sjoerg return; 421430300Sjoerg } 421530300Sjoerg h = mtod (m, struct lcp_header*); 421630300Sjoerg if (len > ntohs (h->len)) 421730300Sjoerg len = ntohs (h->len); 421830300Sjoerg switch (h->type) { 421930300Sjoerg /* PAP request is my authproto */ 422030300Sjoerg case PAP_REQ: 422130300Sjoerg name = 1 + (u_char*)(h+1); 422230300Sjoerg name_len = name[-1]; 422330300Sjoerg passwd = name + name_len + 1; 422430300Sjoerg if (name_len > len - 6 || 422530300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 422630300Sjoerg if (debug) { 422740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 422830300Sjoerg "<%s id=0x%x len=%d", 422940008Sjoerg SPP_ARGS(ifp), 423030300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 423130300Sjoerg h->ident, ntohs(h->len)); 423244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 423369211Sphk log(-1, ">\n"); 423430300Sjoerg } 423530300Sjoerg break; 423630300Sjoerg } 423730300Sjoerg if (debug) { 423840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 423930300Sjoerg "<%s id=0x%x len=%d name=", 424040008Sjoerg SPP_ARGS(ifp), 424130300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 424230300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 424330300Sjoerg h->ident, ntohs(h->len)); 424430300Sjoerg sppp_print_string((char*)name, name_len); 424569211Sphk log(-1, " passwd="); 424630300Sjoerg sppp_print_string((char*)passwd, passwd_len); 424769211Sphk log(-1, ">\n"); 424830300Sjoerg } 424974774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 425074774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 425130300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 425230300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 425330300Sjoerg /* action scn, tld */ 425430300Sjoerg mlen = sizeof(FAILMSG) - 1; 425530300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 425630300Sjoerg sizeof mlen, (const char *)&mlen, 425730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 425830300Sjoerg 0); 425930300Sjoerg pap.tld(sp); 426030300Sjoerg break; 426130300Sjoerg } 426230300Sjoerg /* action sca, perhaps tlu */ 426330300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 426430300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 426530300Sjoerg mlen = sizeof(SUCCMSG) - 1; 426630300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 426730300Sjoerg sizeof mlen, (const char *)&mlen, 426830300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 426930300Sjoerg 0); 427030300Sjoerg } 427130300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 427230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 427330300Sjoerg pap.tlu(sp); 427430300Sjoerg } 427530300Sjoerg break; 427630300Sjoerg 427730300Sjoerg /* ack and nak are his authproto */ 427830300Sjoerg case PAP_ACK: 427940008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 428030300Sjoerg if (debug) { 428140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 428240008Sjoerg SPP_ARGS(ifp)); 428330300Sjoerg name_len = *((char *)h); 428430300Sjoerg if (len > 5 && name_len) { 428569211Sphk log(-1, ": "); 428630300Sjoerg sppp_print_string((char*)(h+1), name_len); 428730300Sjoerg } 428869211Sphk log(-1, "\n"); 428930300Sjoerg } 429030300Sjoerg x = splimp(); 429130300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 429230300Sjoerg if (sp->myauth.proto == PPP_PAP && 429332169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 429430300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 429530300Sjoerg /* 429630300Sjoerg * We are authenticator for PAP but didn't 429730300Sjoerg * complete yet. Leave it to tlu to proceed 429830300Sjoerg * to network phase. 429930300Sjoerg */ 430030300Sjoerg splx(x); 430130300Sjoerg break; 430230300Sjoerg } 430330300Sjoerg splx(x); 430430300Sjoerg sppp_phase_network(sp); 430530300Sjoerg break; 430630300Sjoerg 430730300Sjoerg case PAP_NAK: 430840008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 430930300Sjoerg if (debug) { 431040008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 431140008Sjoerg SPP_ARGS(ifp)); 431230300Sjoerg name_len = *((char *)h); 431330300Sjoerg if (len > 5 && name_len) { 431469211Sphk log(-1, ": "); 431530300Sjoerg sppp_print_string((char*)(h+1), name_len); 431630300Sjoerg } 431769211Sphk log(-1, "\n"); 431830300Sjoerg } else 431940008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 432040008Sjoerg SPP_ARGS(ifp)); 432130300Sjoerg /* await LCP shutdown by authenticator */ 432230300Sjoerg break; 432330300Sjoerg 432430300Sjoerg default: 432530300Sjoerg /* Unknown PAP packet type -- ignore. */ 432630300Sjoerg if (debug) { 432740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 432830300Sjoerg "<0x%x id=0x%x len=%d", 432940008Sjoerg SPP_ARGS(ifp), 433030300Sjoerg h->type, h->ident, ntohs(h->len)); 433144145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 433269211Sphk log(-1, ">\n"); 433330300Sjoerg } 433430300Sjoerg break; 433530300Sjoerg 433630300Sjoerg } 433730300Sjoerg} 433830300Sjoerg 433930300Sjoergstatic void 434030300Sjoergsppp_pap_init(struct sppp *sp) 434130300Sjoerg{ 434230300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 434330300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 434430300Sjoerg sp->fail_counter[IDX_PAP] = 0; 434578064Sume sp->pp_seq[IDX_PAP] = 0; 434678064Sume sp->pp_rseq[IDX_PAP] = 0; 434742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 434830300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 434930300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 435040008Sjoerg#endif 435130300Sjoerg} 435230300Sjoerg 435330300Sjoergstatic void 435430300Sjoergsppp_pap_open(struct sppp *sp) 435530300Sjoerg{ 435630300Sjoerg if (sp->hisauth.proto == PPP_PAP && 435730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 435830300Sjoerg /* we are authenticator for PAP, start our timer */ 435930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 436030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 436130300Sjoerg } 436230300Sjoerg if (sp->myauth.proto == PPP_PAP) { 436330300Sjoerg /* we are peer, send a request, and start a timer */ 436430300Sjoerg pap.scr(sp); 436542064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 436642064Sphk sp->pap_my_to_ch); 436730300Sjoerg } 436830300Sjoerg} 436930300Sjoerg 437030300Sjoergstatic void 437130300Sjoergsppp_pap_close(struct sppp *sp) 437230300Sjoerg{ 437330300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 437430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 437530300Sjoerg} 437630300Sjoerg 437730300Sjoerg/* 437830300Sjoerg * That's the timeout routine if we are authenticator. Since the 437930300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 438030300Sjoerg */ 438130300Sjoergstatic void 438230300Sjoergsppp_pap_TO(void *cookie) 438330300Sjoerg{ 438430300Sjoerg struct sppp *sp = (struct sppp *)cookie; 438530300Sjoerg STDDCL; 438630300Sjoerg int s; 438730300Sjoerg 438830300Sjoerg s = splimp(); 438930300Sjoerg if (debug) 439040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 439140008Sjoerg SPP_ARGS(ifp), 439230300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 439330300Sjoerg sp->rst_counter[IDX_PAP]); 439430300Sjoerg 439530300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 439630300Sjoerg /* TO- event */ 439730300Sjoerg switch (sp->state[IDX_PAP]) { 439830300Sjoerg case STATE_REQ_SENT: 439930300Sjoerg pap.tld(sp); 440030300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 440130300Sjoerg break; 440230300Sjoerg } 440330300Sjoerg else 440430300Sjoerg /* TO+ event, not very much we could do */ 440530300Sjoerg switch (sp->state[IDX_PAP]) { 440630300Sjoerg case STATE_REQ_SENT: 440730300Sjoerg /* sppp_cp_change_state() will restart the timer */ 440830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 440930300Sjoerg break; 441030300Sjoerg } 441130300Sjoerg 441230300Sjoerg splx(s); 441330300Sjoerg} 441430300Sjoerg 441530300Sjoerg/* 441630300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 441730300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 441830300Sjoerg * XXX We should impose a max counter. 441930300Sjoerg */ 442030300Sjoergstatic void 442130300Sjoergsppp_pap_my_TO(void *cookie) 442230300Sjoerg{ 442330300Sjoerg struct sppp *sp = (struct sppp *)cookie; 442430300Sjoerg STDDCL; 442530300Sjoerg 442630300Sjoerg if (debug) 442740008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 442840008Sjoerg SPP_ARGS(ifp)); 442930300Sjoerg 443030300Sjoerg pap.scr(sp); 443130300Sjoerg} 443230300Sjoerg 443330300Sjoergstatic void 443430300Sjoergsppp_pap_tlu(struct sppp *sp) 443530300Sjoerg{ 443630300Sjoerg STDDCL; 443730300Sjoerg int x; 443830300Sjoerg 443930300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 444030300Sjoerg 444130300Sjoerg if (debug) 444240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 444340008Sjoerg SPP_ARGS(ifp), pap.name); 444430300Sjoerg 444530300Sjoerg x = splimp(); 444630300Sjoerg /* indicate to LCP that we need to be closed down */ 444730300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 444830300Sjoerg 444930300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 445030300Sjoerg /* 445130300Sjoerg * Remote is authenticator, but his auth proto didn't 445230300Sjoerg * complete yet. Defer the transition to network 445330300Sjoerg * phase. 445430300Sjoerg */ 445530300Sjoerg splx(x); 445630300Sjoerg return; 445730300Sjoerg } 445830300Sjoerg splx(x); 445930300Sjoerg sppp_phase_network(sp); 446030300Sjoerg} 446130300Sjoerg 446230300Sjoergstatic void 446330300Sjoergsppp_pap_tld(struct sppp *sp) 446430300Sjoerg{ 446530300Sjoerg STDDCL; 446630300Sjoerg 446730300Sjoerg if (debug) 446840008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 446940008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 447040008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 447130300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 447230300Sjoerg 447330300Sjoerg lcp.Close(sp); 447430300Sjoerg} 447530300Sjoerg 447630300Sjoergstatic void 447730300Sjoergsppp_pap_scr(struct sppp *sp) 447830300Sjoerg{ 447930300Sjoerg u_char idlen, pwdlen; 448030300Sjoerg 448178064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 448230300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 448330300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 448430300Sjoerg 448530300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 448630300Sjoerg sizeof idlen, (const char *)&idlen, 448740008Sjoerg (size_t)idlen, sp->myauth.name, 448830300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 448940008Sjoerg (size_t)pwdlen, sp->myauth.secret, 449030300Sjoerg 0); 449130300Sjoerg} 449270199Sjhay 449370199Sjhay/* 449425944Sjoerg * Random miscellaneous functions. 449525944Sjoerg */ 449625944Sjoerg 44974910Swollman/* 449830300Sjoerg * Send a PAP or CHAP proto packet. 449930300Sjoerg * 450030300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 450140008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 450230300Sjoerg * mlen == 0. 450342104Sphk * NOTE: never declare variadic functions with types subject to type 450442104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 450542104Sphk * on the architecture you are on... 450630300Sjoerg */ 450730300Sjoerg 450830300Sjoergstatic void 450942104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 451042104Sphk unsigned int type, unsigned int id, 451130300Sjoerg ...) 451230300Sjoerg{ 451330300Sjoerg STDDCL; 451430300Sjoerg struct ppp_header *h; 451530300Sjoerg struct lcp_header *lh; 451630300Sjoerg struct mbuf *m; 451730300Sjoerg u_char *p; 451830300Sjoerg int len; 451942104Sphk unsigned int mlen; 452030300Sjoerg const char *msg; 452130300Sjoerg va_list ap; 452230300Sjoerg 452330300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 452430300Sjoerg if (! m) 452530300Sjoerg return; 452630300Sjoerg m->m_pkthdr.rcvif = 0; 452730300Sjoerg 452830300Sjoerg h = mtod (m, struct ppp_header*); 452930300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 453030300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 453130300Sjoerg h->protocol = htons(cp->proto); 453230300Sjoerg 453330300Sjoerg lh = (struct lcp_header*)(h + 1); 453430300Sjoerg lh->type = type; 453530300Sjoerg lh->ident = id; 453630300Sjoerg p = (u_char*) (lh+1); 453730300Sjoerg 453830300Sjoerg va_start(ap, id); 453930300Sjoerg len = 0; 454030300Sjoerg 454142104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 454230300Sjoerg msg = va_arg(ap, const char *); 454330300Sjoerg len += mlen; 454430300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 454530300Sjoerg va_end(ap); 454630300Sjoerg m_freem(m); 454730300Sjoerg return; 454830300Sjoerg } 454930300Sjoerg 455030300Sjoerg bcopy(msg, p, mlen); 455130300Sjoerg p += mlen; 455230300Sjoerg } 455330300Sjoerg va_end(ap); 455430300Sjoerg 455530300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 455630300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 455730300Sjoerg 455830300Sjoerg if (debug) { 455940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 456040008Sjoerg SPP_ARGS(ifp), cp->name, 456130300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 456230300Sjoerg lh->ident, ntohs(lh->len)); 456344145Sphk sppp_print_bytes((u_char*) (lh+1), len); 456469211Sphk log(-1, ">\n"); 456530300Sjoerg } 456669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 456769152Sjlemon ifp->if_oerrors++; 456830300Sjoerg} 456930300Sjoerg 457030300Sjoerg/* 457125944Sjoerg * Flush interface queue. 45724910Swollman */ 457312820Sphkstatic void 457425944Sjoergsppp_qflush(struct ifqueue *ifq) 45754910Swollman{ 457625944Sjoerg struct mbuf *m, *n; 45774910Swollman 457825944Sjoerg n = ifq->ifq_head; 457925944Sjoerg while ((m = n)) { 458025944Sjoerg n = m->m_act; 458125944Sjoerg m_freem (m); 458211189Sjkh } 458325944Sjoerg ifq->ifq_head = 0; 458425944Sjoerg ifq->ifq_tail = 0; 458525944Sjoerg ifq->ifq_len = 0; 458625944Sjoerg} 458725944Sjoerg 458825944Sjoerg/* 458925944Sjoerg * Send keepalive packets, every 10 seconds. 459025944Sjoerg */ 459125944Sjoergstatic void 459225944Sjoergsppp_keepalive(void *dummy) 459325944Sjoerg{ 459425944Sjoerg struct sppp *sp; 459525944Sjoerg int s; 459625944Sjoerg 459725944Sjoerg s = splimp(); 459825944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 459925944Sjoerg struct ifnet *ifp = &sp->pp_if; 460025944Sjoerg 460125944Sjoerg /* Keepalive mode disabled or channel down? */ 460225944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 460325944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 460425944Sjoerg continue; 460525944Sjoerg 460625944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 460745152Sphk if (sp->pp_mode != IFF_CISCO && 460825944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 460925944Sjoerg continue; 461025944Sjoerg 461125944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 461225944Sjoerg /* No keepalive packets got. Stop the interface. */ 461340008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 461425944Sjoerg if_down (ifp); 461526018Sjoerg sppp_qflush (&sp->pp_cpq); 461645152Sphk if (sp->pp_mode != IFF_CISCO) { 461725944Sjoerg /* XXX */ 461825944Sjoerg /* Shut down the PPP link. */ 461925944Sjoerg lcp.Down(sp); 462025944Sjoerg /* Initiate negotiation. XXX */ 462125944Sjoerg lcp.Up(sp); 462225944Sjoerg } 46234910Swollman } 462425944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 462525944Sjoerg ++sp->pp_alivecnt; 462645152Sphk if (sp->pp_mode == IFF_CISCO) 462778064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 462878064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 462925944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 463025944Sjoerg long nmagic = htonl (sp->lcp.magic); 463178064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 463225944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 463325944Sjoerg sp->lcp.echoid, 4, &nmagic); 463425944Sjoerg } 46354910Swollman } 463625944Sjoerg splx(s); 463742064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 46384910Swollman} 46394910Swollman 464025944Sjoerg/* 464125944Sjoerg * Get both IP addresses. 464225944Sjoerg */ 464325944Sjoergstatic void 464430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 464525944Sjoerg{ 464625944Sjoerg struct ifnet *ifp = &sp->pp_if; 464725944Sjoerg struct ifaddr *ifa; 464830300Sjoerg struct sockaddr_in *si, *sm; 464925944Sjoerg u_long ssrc, ddst; 465025944Sjoerg 465140010Sjoerg sm = NULL; 465225944Sjoerg ssrc = ddst = 0L; 465325944Sjoerg /* 465425944Sjoerg * Pick the first AF_INET address from the list, 465525944Sjoerg * aliases don't make any sense on a p2p link anyway. 465625944Sjoerg */ 465742065Sphk si = 0; 465842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 465942065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 466042104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 466171959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 466240008Sjoerg ifa; 466371959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 466442104Sphk#else 466542104Sphk for (ifa = ifp->if_addrlist; 466642104Sphk ifa; 466742104Sphk ifa = ifa->ifa_next) 466840008Sjoerg#endif 466925944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 467025944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 467130300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 467225944Sjoerg if (si) 467325944Sjoerg break; 467425944Sjoerg } 467525944Sjoerg if (ifa) { 467630300Sjoerg if (si && si->sin_addr.s_addr) { 467725944Sjoerg ssrc = si->sin_addr.s_addr; 467830300Sjoerg if (srcmask) 467930300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 468030300Sjoerg } 468125944Sjoerg 468225944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 468325944Sjoerg if (si && si->sin_addr.s_addr) 468425944Sjoerg ddst = si->sin_addr.s_addr; 468525944Sjoerg } 468625944Sjoerg 468725944Sjoerg if (dst) *dst = ntohl(ddst); 468825944Sjoerg if (src) *src = ntohl(ssrc); 468925944Sjoerg} 469025944Sjoerg 469125944Sjoerg/* 469225944Sjoerg * Set my IP address. Must be called at splimp. 469325944Sjoerg */ 469425944Sjoergstatic void 469525944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 469625944Sjoerg{ 469742104Sphk STDDCL; 469825944Sjoerg struct ifaddr *ifa; 469925944Sjoerg struct sockaddr_in *si; 470084318Sjlemon struct in_ifaddr *ia; 470125944Sjoerg 470225944Sjoerg /* 470325944Sjoerg * Pick the first AF_INET address from the list, 470425944Sjoerg * aliases don't make any sense on a p2p link anyway. 470525944Sjoerg */ 470642065Sphk si = 0; 470742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 470842065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 470942104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 471071959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 471140008Sjoerg ifa; 471271959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 471342104Sphk#else 471442104Sphk for (ifa = ifp->if_addrlist; 471542104Sphk ifa; 471642104Sphk ifa = ifa->ifa_next) 471740008Sjoerg#endif 471840008Sjoerg { 471940008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 472040008Sjoerg { 472125944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 472225944Sjoerg if (si) 472325944Sjoerg break; 472425944Sjoerg } 472540008Sjoerg } 472640008Sjoerg 472725944Sjoerg if (ifa && si) 472842104Sphk { 472942104Sphk int error; 473042104Sphk#if __NetBSD_Version__ >= 103080000 473142104Sphk struct sockaddr_in new_sin = *si; 473242104Sphk 473342104Sphk new_sin.sin_addr.s_addr = htonl(src); 473442104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 473542104Sphk if(debug && error) 473642104Sphk { 473742104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 473842104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 473942104Sphk } 474042104Sphk#else 474142104Sphk /* delete old route */ 474242104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 474342104Sphk if(debug && error) 474442104Sphk { 474542104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 474642104Sphk SPP_ARGS(ifp), error); 474742104Sphk } 474842104Sphk 474942104Sphk /* set new address */ 475025944Sjoerg si->sin_addr.s_addr = htonl(src); 475184318Sjlemon ia = ifatoia(ifa); 475284318Sjlemon LIST_REMOVE(ia, ia_hash); 475384318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 475425944Sjoerg 475542104Sphk /* add new route */ 475670199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 475742104Sphk if (debug && error) 475842104Sphk { 475942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 476042104Sphk SPP_ARGS(ifp), error); 476142104Sphk } 476242104Sphk#endif 476342104Sphk } 476478064Sume} 476578064Sume 476678064Sume#ifdef INET6 476778064Sume/* 476878064Sume * Get both IPv6 addresses. 476978064Sume */ 477078064Sumestatic void 477178064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 477278064Sume struct in6_addr *srcmask) 477378064Sume{ 477478064Sume struct ifnet *ifp = &sp->pp_if; 477578064Sume struct ifaddr *ifa; 477678064Sume struct sockaddr_in6 *si, *sm; 477778064Sume struct in6_addr ssrc, ddst; 477878064Sume 477978064Sume sm = NULL; 478078064Sume bzero(&ssrc, sizeof(ssrc)); 478178064Sume bzero(&ddst, sizeof(ddst)); 478278064Sume /* 478378064Sume * Pick the first link-local AF_INET6 address from the list, 478478064Sume * aliases don't make any sense on a p2p link anyway. 478578064Sume */ 478678064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 478778064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 478878064Sume ifa; 478978064Sume ifa = ifa->ifa_link.tqe_next) 479078064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 479178064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 479278064Sume ifa; 479378064Sume ifa = ifa->ifa_list.tqe_next) 479478064Sume#else 479578064Sume for (ifa = ifp->if_addrlist, si = 0; 479678064Sume ifa; 479778064Sume ifa = ifa->ifa_next) 479878064Sume#endif 479978064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 480078064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 480178064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 480278064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 480378064Sume break; 480478064Sume } 480578064Sume if (ifa) { 480678064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 480778064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 480878064Sume if (srcmask) { 480978064Sume bcopy(&sm->sin6_addr, srcmask, 481078064Sume sizeof(*srcmask)); 481178064Sume } 481278064Sume } 481378064Sume 481478064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 481578064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 481678064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 481778064Sume } 481878064Sume 481978064Sume if (dst) 482078064Sume bcopy(&ddst, dst, sizeof(*dst)); 482178064Sume if (src) 482278064Sume bcopy(&ssrc, src, sizeof(*src)); 482370199Sjhay} 482442104Sphk 482578064Sume#ifdef IPV6CP_MYIFID_DYN 482678064Sume/* 482778064Sume * Generate random ifid. 482878064Sume */ 482978064Sumestatic void 483078064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 483178064Sume{ 483278064Sume /* TBD */ 483378064Sume} 483478064Sume 483578064Sume/* 483678064Sume * Set my IPv6 address. Must be called at splimp. 483778064Sume */ 483878064Sumestatic void 483978064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 484078064Sume{ 484178064Sume STDDCL; 484278064Sume struct ifaddr *ifa; 484378064Sume struct sockaddr_in6 *sin6; 484478064Sume 484578064Sume /* 484678064Sume * Pick the first link-local AF_INET6 address from the list, 484778064Sume * aliases don't make any sense on a p2p link anyway. 484878064Sume */ 484978064Sume 485078064Sume sin6 = NULL; 485178064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 485278064Sume for (ifa = ifp->if_addrhead.tqh_first; 485378064Sume ifa; 485478064Sume ifa = ifa->ifa_link.tqe_next) 485578064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 485678064Sume for (ifa = ifp->if_addrlist.tqh_first; 485778064Sume ifa; 485878064Sume ifa = ifa->ifa_list.tqe_next) 485978064Sume#else 486078064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 486178064Sume#endif 486278064Sume { 486378064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 486478064Sume { 486578064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 486678064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 486778064Sume break; 486878064Sume } 486978064Sume } 487078064Sume 487178064Sume if (ifa && sin6) 487278064Sume { 487378064Sume int error; 487478064Sume struct sockaddr_in6 new_sin6 = *sin6; 487578064Sume 487678064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 487778064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 487878064Sume if (debug && error) 487978064Sume { 488078064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 488178064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 488278064Sume } 488378064Sume } 488478064Sume} 488578064Sume#endif 488678064Sume 488778064Sume/* 488878064Sume * Suggest a candidate address to be used by peer. 488978064Sume */ 489078064Sumestatic void 489178064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 489278064Sume{ 489378064Sume struct in6_addr myaddr; 489478064Sume struct timeval tv; 489578064Sume 489678064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 489778064Sume 489878064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 489978064Sume microtime(&tv); 490078064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 490178064Sume myaddr.s6_addr[14] ^= 0xff; 490278064Sume myaddr.s6_addr[15] ^= 0xff; 490378064Sume } else { 490478064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 490578064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 490678064Sume } 490778064Sume if (suggest) 490878064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 490978064Sume} 491078064Sume#endif /*INET6*/ 491178064Sume 491230300Sjoergstatic int 491338343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 491430300Sjoerg{ 491538343Sbde u_long subcmd; 491630300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 491730300Sjoerg struct spppreq spr; 491830300Sjoerg 491930300Sjoerg /* 492030300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 492130300Sjoerg * Check the cmd word first before attempting to fetch all the 492230300Sjoerg * data. 492330300Sjoerg */ 492430300Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) 492530300Sjoerg return EFAULT; 492630300Sjoerg 492730300Sjoerg if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0) 492830300Sjoerg return EFAULT; 492930300Sjoerg 493030300Sjoerg switch (subcmd) { 493130300Sjoerg case SPPPIOGDEFS: 493230300Sjoerg if (cmd != SIOCGIFGENERIC) 493330300Sjoerg return EINVAL; 493430300Sjoerg /* 493530300Sjoerg * We copy over the entire current state, but clean 493630300Sjoerg * out some of the stuff we don't wanna pass up. 493730300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 493830300Sjoerg * called by any user. No need to ever get PAP or 493930300Sjoerg * CHAP secrets back to userland anyway. 494030300Sjoerg */ 494130300Sjoerg bcopy(sp, &spr.defs, sizeof(struct sppp)); 494230300Sjoerg bzero(spr.defs.myauth.secret, AUTHKEYLEN); 494330300Sjoerg bzero(spr.defs.myauth.challenge, AUTHKEYLEN); 494430300Sjoerg bzero(spr.defs.hisauth.secret, AUTHKEYLEN); 494530300Sjoerg bzero(spr.defs.hisauth.challenge, AUTHKEYLEN); 494688550Sjoerg /* 494788550Sjoerg * Fixup the LCP timeout value to milliseconds so 494888550Sjoerg * spppcontrol doesn't need to bother about the value 494988550Sjoerg * of "hz". We do the reverse calculation below when 495088550Sjoerg * setting it. 495188550Sjoerg */ 495288550Sjoerg spr.defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 495330300Sjoerg return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr); 495430300Sjoerg 495530300Sjoerg case SPPPIOSDEFS: 495630300Sjoerg if (cmd != SIOCSIFGENERIC) 495730300Sjoerg return EINVAL; 495830300Sjoerg /* 495988550Sjoerg * We have a very specific idea of which fields we 496088550Sjoerg * allow being passed back from userland, so to not 496188550Sjoerg * clobber our current state. For one, we only allow 496288550Sjoerg * setting anything if LCP is in dead or establish 496388550Sjoerg * phase. Once the authentication negotiations 496488550Sjoerg * started, the authentication settings must not be 496588550Sjoerg * changed again. (The administrator can force an 496630300Sjoerg * ifconfig down in order to get LCP back into dead 496730300Sjoerg * phase.) 496830300Sjoerg * 496930300Sjoerg * Also, we only allow for authentication parameters to be 497030300Sjoerg * specified. 497130300Sjoerg * 497230300Sjoerg * XXX Should allow to set or clear pp_flags. 497330300Sjoerg * 497430300Sjoerg * Finally, if the respective authentication protocol to 497530300Sjoerg * be used is set differently than 0, but the secret is 497630300Sjoerg * passed as all zeros, we don't trash the existing secret. 497730300Sjoerg * This allows an administrator to change the system name 497830300Sjoerg * only without clobbering the secret (which he didn't get 497930300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 498030300Sjoerg * secrets are cleared if the authentication protocol is 498188550Sjoerg * reset to 0. */ 498288550Sjoerg if (sp->pp_phase != PHASE_DEAD && 498388550Sjoerg sp->pp_phase != PHASE_ESTABLISH) 498430300Sjoerg return EBUSY; 498530300Sjoerg 498630300Sjoerg if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP && 498730300Sjoerg spr.defs.myauth.proto != PPP_CHAP) || 498830300Sjoerg (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP && 498930300Sjoerg spr.defs.hisauth.proto != PPP_CHAP)) 499030300Sjoerg return EINVAL; 499130300Sjoerg 499230300Sjoerg if (spr.defs.myauth.proto == 0) 499330300Sjoerg /* resetting myauth */ 499430300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 499530300Sjoerg else { 499630300Sjoerg /* setting/changing myauth */ 499730300Sjoerg sp->myauth.proto = spr.defs.myauth.proto; 499830300Sjoerg bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 499930300Sjoerg if (spr.defs.myauth.secret[0] != '\0') 500030300Sjoerg bcopy(spr.defs.myauth.secret, sp->myauth.secret, 500130300Sjoerg AUTHKEYLEN); 500230300Sjoerg } 500330300Sjoerg if (spr.defs.hisauth.proto == 0) 500430300Sjoerg /* resetting hisauth */ 500530300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 500630300Sjoerg else { 500730300Sjoerg /* setting/changing hisauth */ 500830300Sjoerg sp->hisauth.proto = spr.defs.hisauth.proto; 500930300Sjoerg sp->hisauth.flags = spr.defs.hisauth.flags; 501030300Sjoerg bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 501130300Sjoerg if (spr.defs.hisauth.secret[0] != '\0') 501230300Sjoerg bcopy(spr.defs.hisauth.secret, sp->hisauth.secret, 501330300Sjoerg AUTHKEYLEN); 501430300Sjoerg } 501588550Sjoerg /* set LCP restart timer timeout */ 501688550Sjoerg if (spr.defs.lcp.timeout != 0) 501788550Sjoerg sp->lcp.timeout = spr.defs.lcp.timeout * hz / 1000; 501888534Sjoerg /* set VJ enable flag */ 501988534Sjoerg sp->enable_vj = spr.defs.enable_vj; 502030300Sjoerg break; 502130300Sjoerg 502230300Sjoerg default: 502330300Sjoerg return EINVAL; 502430300Sjoerg } 502530300Sjoerg 502630300Sjoerg return 0; 502730300Sjoerg} 502830300Sjoerg 502930300Sjoergstatic void 503030300Sjoergsppp_phase_network(struct sppp *sp) 503130300Sjoerg{ 503242066Sphk STDDCL; 503330300Sjoerg int i; 503430300Sjoerg u_long mask; 503530300Sjoerg 503630300Sjoerg sp->pp_phase = PHASE_NETWORK; 503730300Sjoerg 503842066Sphk if (debug) 503942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 504042066Sphk sppp_phase_name(sp->pp_phase)); 504130300Sjoerg 504230300Sjoerg /* Notify NCPs now. */ 504330300Sjoerg for (i = 0; i < IDX_COUNT; i++) 504430300Sjoerg if ((cps[i])->flags & CP_NCP) 504530300Sjoerg (cps[i])->Open(sp); 504630300Sjoerg 504730300Sjoerg /* Send Up events to all NCPs. */ 504830300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 504930300Sjoerg if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP)) 505030300Sjoerg (cps[i])->Up(sp); 505130300Sjoerg 505230300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 505330300Sjoerg sppp_lcp_check_and_close(sp); 505430300Sjoerg} 505530300Sjoerg 505670199Sjhay 505725706Sjoergstatic const char * 505825944Sjoergsppp_cp_type_name(u_char type) 50594910Swollman{ 506030300Sjoerg static char buf[12]; 50614910Swollman switch (type) { 506230300Sjoerg case CONF_REQ: return "conf-req"; 506330300Sjoerg case CONF_ACK: return "conf-ack"; 506430300Sjoerg case CONF_NAK: return "conf-nak"; 506530300Sjoerg case CONF_REJ: return "conf-rej"; 506630300Sjoerg case TERM_REQ: return "term-req"; 506730300Sjoerg case TERM_ACK: return "term-ack"; 506830300Sjoerg case CODE_REJ: return "code-rej"; 506930300Sjoerg case PROTO_REJ: return "proto-rej"; 507030300Sjoerg case ECHO_REQ: return "echo-req"; 507130300Sjoerg case ECHO_REPLY: return "echo-reply"; 507230300Sjoerg case DISC_REQ: return "discard-req"; 50734910Swollman } 507444145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 507530300Sjoerg return buf; 50764910Swollman} 50774910Swollman 507825706Sjoergstatic const char * 507930300Sjoergsppp_auth_type_name(u_short proto, u_char type) 508030300Sjoerg{ 508130300Sjoerg static char buf[12]; 508230300Sjoerg switch (proto) { 508330300Sjoerg case PPP_CHAP: 508430300Sjoerg switch (type) { 508530300Sjoerg case CHAP_CHALLENGE: return "challenge"; 508630300Sjoerg case CHAP_RESPONSE: return "response"; 508730300Sjoerg case CHAP_SUCCESS: return "success"; 508830300Sjoerg case CHAP_FAILURE: return "failure"; 508930300Sjoerg } 509030300Sjoerg case PPP_PAP: 509130300Sjoerg switch (type) { 509230300Sjoerg case PAP_REQ: return "req"; 509330300Sjoerg case PAP_ACK: return "ack"; 509430300Sjoerg case PAP_NAK: return "nak"; 509530300Sjoerg } 509630300Sjoerg } 509744145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 509830300Sjoerg return buf; 509930300Sjoerg} 510030300Sjoerg 510130300Sjoergstatic const char * 510225944Sjoergsppp_lcp_opt_name(u_char opt) 51034910Swollman{ 510430300Sjoerg static char buf[12]; 510525944Sjoerg switch (opt) { 510630300Sjoerg case LCP_OPT_MRU: return "mru"; 510730300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 510830300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 510930300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 511030300Sjoerg case LCP_OPT_MAGIC: return "magic"; 511130300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 511230300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 51134910Swollman } 511444145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 511530300Sjoerg return buf; 51164910Swollman} 51174910Swollman 511825944Sjoergstatic const char * 511925944Sjoergsppp_ipcp_opt_name(u_char opt) 512025944Sjoerg{ 512130300Sjoerg static char buf[12]; 512225944Sjoerg switch (opt) { 512330300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 512430300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 512530300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 512625944Sjoerg } 512744145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 512830300Sjoerg return buf; 512925944Sjoerg} 513025944Sjoerg 513178064Sume#ifdef INET6 513225944Sjoergstatic const char * 513378064Sumesppp_ipv6cp_opt_name(u_char opt) 513478064Sume{ 513578064Sume static char buf[12]; 513678064Sume switch (opt) { 513778064Sume case IPV6CP_OPT_IFID: return "ifid"; 513878064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 513978064Sume } 514078064Sume sprintf (buf, "0x%x", opt); 514178064Sume return buf; 514278064Sume} 514378064Sume#endif 514478064Sume 514578064Sumestatic const char * 514625944Sjoergsppp_state_name(int state) 514725944Sjoerg{ 514825944Sjoerg switch (state) { 514925944Sjoerg case STATE_INITIAL: return "initial"; 515025944Sjoerg case STATE_STARTING: return "starting"; 515125944Sjoerg case STATE_CLOSED: return "closed"; 515225944Sjoerg case STATE_STOPPED: return "stopped"; 515325944Sjoerg case STATE_CLOSING: return "closing"; 515425944Sjoerg case STATE_STOPPING: return "stopping"; 515525944Sjoerg case STATE_REQ_SENT: return "req-sent"; 515625944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 515725944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 515825944Sjoerg case STATE_OPENED: return "opened"; 515925944Sjoerg } 516025944Sjoerg return "illegal"; 516125944Sjoerg} 516225944Sjoerg 516325944Sjoergstatic const char * 516425944Sjoergsppp_phase_name(enum ppp_phase phase) 516525944Sjoerg{ 516625944Sjoerg switch (phase) { 516725944Sjoerg case PHASE_DEAD: return "dead"; 516825944Sjoerg case PHASE_ESTABLISH: return "establish"; 516925944Sjoerg case PHASE_TERMINATE: return "terminate"; 517025944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 517125944Sjoerg case PHASE_NETWORK: return "network"; 517225944Sjoerg } 517325944Sjoerg return "illegal"; 517425944Sjoerg} 517525944Sjoerg 517625944Sjoergstatic const char * 517725944Sjoergsppp_proto_name(u_short proto) 517825944Sjoerg{ 517925944Sjoerg static char buf[12]; 518025944Sjoerg switch (proto) { 518125944Sjoerg case PPP_LCP: return "lcp"; 518225944Sjoerg case PPP_IPCP: return "ipcp"; 518330300Sjoerg case PPP_PAP: return "pap"; 518430300Sjoerg case PPP_CHAP: return "chap"; 518578064Sume case PPP_IPV6CP: return "ipv6cp"; 518625944Sjoerg } 518744145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 518825944Sjoerg return buf; 518925944Sjoerg} 519025944Sjoerg 519112820Sphkstatic void 519230300Sjoergsppp_print_bytes(const u_char *p, u_short len) 51934910Swollman{ 519444145Sphk if (len) 519569211Sphk log(-1, " %*D", len, p, "-"); 51964910Swollman} 519725944Sjoerg 519830300Sjoergstatic void 519930300Sjoergsppp_print_string(const char *p, u_short len) 520030300Sjoerg{ 520130300Sjoerg u_char c; 520230300Sjoerg 520330300Sjoerg while (len-- > 0) { 520430300Sjoerg c = *p++; 520530300Sjoerg /* 520630300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 520730300Sjoerg * using only them, but we don't rely on it. */ 520830300Sjoerg if (c < ' ' || c > '~') 520969211Sphk log(-1, "\\x%x", c); 521030300Sjoerg else 521169211Sphk log(-1, "%c", c); 521230300Sjoerg } 521330300Sjoerg} 521430300Sjoerg 521530300Sjoergstatic const char * 521630300Sjoergsppp_dotted_quad(u_long addr) 521730300Sjoerg{ 521830300Sjoerg static char s[16]; 521930300Sjoerg sprintf(s, "%d.%d.%d.%d", 522040008Sjoerg (int)((addr >> 24) & 0xff), 522140008Sjoerg (int)((addr >> 16) & 0xff), 522240008Sjoerg (int)((addr >> 8) & 0xff), 522338372Sbde (int)(addr & 0xff)); 522430300Sjoerg return s; 522530300Sjoerg} 522630300Sjoerg 522730300Sjoergstatic int 522830300Sjoergsppp_strnlen(u_char *p, int max) 522930300Sjoerg{ 523030300Sjoerg int len; 523130300Sjoerg 523230300Sjoerg for (len = 0; len < max && *p; ++p) 523330300Sjoerg ++len; 523430300Sjoerg return len; 523530300Sjoerg} 523630300Sjoerg 523730300Sjoerg/* a dummy, used to drop uninteresting events */ 523830300Sjoergstatic void 523930300Sjoergsppp_null(struct sppp *unused) 524030300Sjoerg{ 524130300Sjoerg /* do just nothing */ 524230300Sjoerg} 5243