if_spppsubr.c revision 93818
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 93818 2002-04-04 21:03:38Z jhb $ 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#include <netinet/in.h> 734910Swollman#include <netinet/in_systm.h> 744910Swollman#include <netinet/in_var.h> 7588705Sjoerg 7688705Sjoerg#ifdef INET 774910Swollman#include <netinet/ip.h> 784910Swollman#include <netinet/tcp.h> 794910Swollman#endif 804910Swollman 8188705Sjoerg#if defined (__FreeBSD__) || defined (__OpenBSD__) 8288705Sjoerg# include <netinet/if_ether.h> 8388705Sjoerg#else 8488705Sjoerg# include <net/ethertypes.h> 8588705Sjoerg#endif 8688705Sjoerg 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; 21588704Sjoerg} __attribute__((__packed__)); 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; 22288704Sjoerg} __attribute__((__packed__)); 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; 23288704Sjoerg} __attribute__((__packed__)); 23388704Sjoerg#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 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 28088705Sjoerg#ifdef INET 2814910Swollman/* 2824910Swollman * The following disgusting hack gets around the problem that IP TOS 2834910Swollman * can't be set yet. We want to put "interactive" traffic on a high 2844910Swollman * priority queue. To decide if traffic is interactive, we check that 2854910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 28630300Sjoerg * 28730300Sjoerg * XXX is this really still necessary? - joerg - 2884910Swollman */ 28911189Sjkhstatic u_short interactive_ports[8] = { 2904910Swollman 0, 513, 0, 0, 2914910Swollman 0, 21, 0, 23, 2924910Swollman}; 2934910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 29488705Sjoerg#endif 2954910Swollman 29625944Sjoerg/* almost every function needs these */ 29725944Sjoerg#define STDDCL \ 29825944Sjoerg struct ifnet *ifp = &sp->pp_if; \ 29925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG 30011189Sjkh 30130300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 30225944Sjoerg struct sockaddr *dst, struct rtentry *rt); 3034910Swollman 30425944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 30525944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 30625944Sjoerg 30725944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 30825944Sjoerg struct mbuf *m); 30925944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 31025944Sjoerg u_char ident, u_short len, void *data); 31142104Sphk/* static void sppp_cp_timeout(void *arg); */ 31225944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 31325944Sjoerg int newstate); 31430300Sjoergstatic void sppp_auth_send(const struct cp *cp, 31542104Sphk struct sppp *sp, unsigned int type, unsigned int id, 31630300Sjoerg ...); 31725944Sjoerg 31825944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 31925944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 32025944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 32125944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 32225944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 32325944Sjoerg 32430300Sjoergstatic void sppp_null(struct sppp *sp); 32530300Sjoerg 32625944Sjoergstatic void sppp_lcp_init(struct sppp *sp); 32725944Sjoergstatic void sppp_lcp_up(struct sppp *sp); 32825944Sjoergstatic void sppp_lcp_down(struct sppp *sp); 32925944Sjoergstatic void sppp_lcp_open(struct sppp *sp); 33025944Sjoergstatic void sppp_lcp_close(struct sppp *sp); 33125944Sjoergstatic void sppp_lcp_TO(void *sp); 33225944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 33325944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 33425944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 33525944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp); 33625944Sjoergstatic void sppp_lcp_tld(struct sppp *sp); 33725944Sjoergstatic void sppp_lcp_tls(struct sppp *sp); 33825944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp); 33925944Sjoergstatic void sppp_lcp_scr(struct sppp *sp); 34030300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp); 34130300Sjoergstatic int sppp_ncp_check(struct sppp *sp); 34225944Sjoerg 34325944Sjoergstatic void sppp_ipcp_init(struct sppp *sp); 34425944Sjoergstatic void sppp_ipcp_up(struct sppp *sp); 34525944Sjoergstatic void sppp_ipcp_down(struct sppp *sp); 34625944Sjoergstatic void sppp_ipcp_open(struct sppp *sp); 34725944Sjoergstatic void sppp_ipcp_close(struct sppp *sp); 34825944Sjoergstatic void sppp_ipcp_TO(void *sp); 34925944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 35025944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 35125944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 35225944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp); 35325944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp); 35425944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp); 35525944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp); 35625944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp); 35725944Sjoerg 35878064Sumestatic void sppp_ipv6cp_init(struct sppp *sp); 35978064Sumestatic void sppp_ipv6cp_up(struct sppp *sp); 36078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp); 36178064Sumestatic void sppp_ipv6cp_open(struct sppp *sp); 36278064Sumestatic void sppp_ipv6cp_close(struct sppp *sp); 36378064Sumestatic void sppp_ipv6cp_TO(void *sp); 36478064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 36578064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 36678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 36778064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp); 36878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp); 36978064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp); 37078064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp); 37178064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp); 37278064Sume 37330300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 37430300Sjoergstatic void sppp_pap_init(struct sppp *sp); 37530300Sjoergstatic void sppp_pap_open(struct sppp *sp); 37630300Sjoergstatic void sppp_pap_close(struct sppp *sp); 37730300Sjoergstatic void sppp_pap_TO(void *sp); 37830300Sjoergstatic void sppp_pap_my_TO(void *sp); 37930300Sjoergstatic void sppp_pap_tlu(struct sppp *sp); 38030300Sjoergstatic void sppp_pap_tld(struct sppp *sp); 38130300Sjoergstatic void sppp_pap_scr(struct sppp *sp); 38230300Sjoerg 38330300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 38430300Sjoergstatic void sppp_chap_init(struct sppp *sp); 38530300Sjoergstatic void sppp_chap_open(struct sppp *sp); 38630300Sjoergstatic void sppp_chap_close(struct sppp *sp); 38730300Sjoergstatic void sppp_chap_TO(void *sp); 38830300Sjoergstatic void sppp_chap_tlu(struct sppp *sp); 38930300Sjoergstatic void sppp_chap_tld(struct sppp *sp); 39030300Sjoergstatic void sppp_chap_scr(struct sppp *sp); 39130300Sjoerg 39230300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type); 39325944Sjoergstatic const char *sppp_cp_type_name(u_char type); 39430300Sjoergstatic const char *sppp_dotted_quad(u_long addr); 39530300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt); 39678064Sume#ifdef INET6 39778064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt); 39878064Sume#endif 39925944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt); 40025944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase); 40125944Sjoergstatic const char *sppp_proto_name(u_short proto); 40230300Sjoergstatic const char *sppp_state_name(int state); 40338343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 40430300Sjoergstatic int sppp_strnlen(u_char *p, int max); 40530300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 40630300Sjoerg u_long *srcmask); 40725944Sjoergstatic void sppp_keepalive(void *dummy); 40830300Sjoergstatic void sppp_phase_network(struct sppp *sp); 40930300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len); 41030300Sjoergstatic void sppp_print_string(const char *p, u_short len); 41125944Sjoergstatic void sppp_qflush(struct ifqueue *ifq); 41225944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 41378064Sume#ifdef INET6 41478064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 41578064Sume struct in6_addr *dst, struct in6_addr *srcmask); 41678064Sume#ifdef IPV6CP_MYIFID_DYN 41778064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41878064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 41978064Sume#endif 42078064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 42178064Sume#endif 42225944Sjoerg 42325944Sjoerg/* our control protocol descriptors */ 42433181Seivindstatic const struct cp lcp = { 42525944Sjoerg PPP_LCP, IDX_LCP, CP_LCP, "lcp", 42625944Sjoerg sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 42725944Sjoerg sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 42825944Sjoerg sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 42925944Sjoerg sppp_lcp_scr 43025944Sjoerg}; 43125944Sjoerg 43233181Seivindstatic const struct cp ipcp = { 43388709Sjoerg PPP_IPCP, IDX_IPCP, 43488709Sjoerg#ifdef INET /* don't run IPCP if there's no IPv4 support */ 43588709Sjoerg CP_NCP, 43688709Sjoerg#else 43788709Sjoerg 0, 43888709Sjoerg#endif 43988709Sjoerg "ipcp", 44025944Sjoerg sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 44125944Sjoerg sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 44225944Sjoerg sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 44325944Sjoerg sppp_ipcp_scr 44425944Sjoerg}; 44525944Sjoerg 44678064Sumestatic const struct cp ipv6cp = { 44778064Sume PPP_IPV6CP, IDX_IPV6CP, 44878064Sume#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 44978064Sume CP_NCP, 45078064Sume#else 45178064Sume 0, 45278064Sume#endif 45378064Sume "ipv6cp", 45478064Sume sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 45578064Sume sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 45678064Sume sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 45778064Sume sppp_ipv6cp_scr 45878064Sume}; 45978064Sume 46033181Seivindstatic const struct cp pap = { 46130300Sjoerg PPP_PAP, IDX_PAP, CP_AUTH, "pap", 46230300Sjoerg sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 46330300Sjoerg sppp_pap_TO, 0, 0, 0, 46430300Sjoerg sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 46530300Sjoerg sppp_pap_scr 46630300Sjoerg}; 46730300Sjoerg 46833181Seivindstatic const struct cp chap = { 46930300Sjoerg PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 47030300Sjoerg sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 47130300Sjoerg sppp_chap_TO, 0, 0, 0, 47230300Sjoerg sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 47330300Sjoerg sppp_chap_scr 47430300Sjoerg}; 47530300Sjoerg 47633181Seivindstatic const struct cp *cps[IDX_COUNT] = { 47725944Sjoerg &lcp, /* IDX_LCP */ 47825944Sjoerg &ipcp, /* IDX_IPCP */ 47978064Sume &ipv6cp, /* IDX_IPV6CP */ 48030300Sjoerg &pap, /* IDX_PAP */ 48130300Sjoerg &chap, /* IDX_CHAP */ 48225944Sjoerg}; 48325944Sjoerg 48470199Sjhaystatic int 48570199Sjhaysppp_modevent(module_t mod, int type, void *unused) 48670199Sjhay{ 48770199Sjhay switch (type) { 48870199Sjhay case MOD_LOAD: 48970199Sjhay break; 49070199Sjhay case MOD_UNLOAD: 49170199Sjhay return EACCES; 49270199Sjhay break; 49370199Sjhay default: 49470199Sjhay break; 49570199Sjhay } 49670199Sjhay return 0; 49770199Sjhay} 49870199Sjhaystatic moduledata_t spppmod = { 49970199Sjhay "sppp", 50070199Sjhay sppp_modevent, 50170199Sjhay 0 50270199Sjhay}; 50370199SjhayMODULE_VERSION(sppp, 1); 50470199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 50525944Sjoerg 50670199Sjhay/* 50725944Sjoerg * Exported functions, comprising our interface to the lower layer. 5084910Swollman */ 5094910Swollman 5104910Swollman/* 5114910Swollman * Process the received packet. 5124910Swollman */ 51325706Sjoergvoid 51425706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m) 5154910Swollman{ 5164910Swollman struct ppp_header *h; 5174910Swollman struct ifqueue *inq = 0; 51825944Sjoerg struct sppp *sp = (struct sppp *)ifp; 51988700Sjoerg u_char *iphdr; 52088700Sjoerg int hlen, vjlen, do_account = 0; 52125944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 5224910Swollman 5234910Swollman if (ifp->if_flags & IFF_UP) 5244910Swollman /* Count received bytes, add FCS and one flag */ 5254910Swollman ifp->if_ibytes += m->m_pkthdr.len + 3; 5264910Swollman 5274910Swollman if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 5284910Swollman /* Too small packet, drop it. */ 52925944Sjoerg if (debug) 53025706Sjoerg log(LOG_DEBUG, 53140008Sjoerg SPP_FMT "input packet is too small, %d bytes\n", 53240008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 53325944Sjoerg drop: 53488700Sjoerg m_freem (m); 53588700Sjoerg drop2: 53625944Sjoerg ++ifp->if_ierrors; 53725944Sjoerg ++ifp->if_iqdrops; 5384910Swollman return; 5394910Swollman } 5404910Swollman 5414910Swollman /* Get PPP header. */ 5424910Swollman h = mtod (m, struct ppp_header*); 5434910Swollman m_adj (m, PPP_HEADER_LEN); 5444910Swollman 5454910Swollman switch (h->address) { 5464910Swollman case PPP_ALLSTATIONS: 5474910Swollman if (h->control != PPP_UI) 5484910Swollman goto invalid; 54945152Sphk if (sp->pp_mode == IFF_CISCO) { 55025944Sjoerg if (debug) 55125706Sjoerg log(LOG_DEBUG, 55240008Sjoerg SPP_FMT "PPP packet in Cisco mode " 55325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 55440008Sjoerg SPP_ARGS(ifp), 55525706Sjoerg h->address, h->control, ntohs(h->protocol)); 55611189Sjkh goto drop; 55711189Sjkh } 5584910Swollman switch (ntohs (h->protocol)) { 5594910Swollman default: 56025944Sjoerg if (debug) 56125706Sjoerg log(LOG_DEBUG, 56244145Sphk SPP_FMT "rejecting protocol " 56325706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 56440008Sjoerg SPP_ARGS(ifp), 56525706Sjoerg h->address, h->control, ntohs(h->protocol)); 56644145Sphk if (sp->state[IDX_LCP] == STATE_OPENED) 56744145Sphk sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 56878064Sume ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 56944145Sphk &h->protocol); 5704910Swollman ++ifp->if_noproto; 5714910Swollman goto drop; 5724910Swollman case PPP_LCP: 57330300Sjoerg sppp_cp_input(&lcp, sp, m); 5744910Swollman m_freem (m); 5754910Swollman return; 57630300Sjoerg case PPP_PAP: 57730300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 57830300Sjoerg sppp_pap_input(sp, m); 57930300Sjoerg m_freem (m); 58030300Sjoerg return; 58130300Sjoerg case PPP_CHAP: 58230300Sjoerg if (sp->pp_phase >= PHASE_AUTHENTICATE) 58330300Sjoerg sppp_chap_input(sp, m); 58430300Sjoerg m_freem (m); 58530300Sjoerg return; 5864910Swollman#ifdef INET 5874910Swollman case PPP_IPCP: 58825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 58930300Sjoerg sppp_cp_input(&ipcp, sp, m); 5904910Swollman m_freem (m); 5914910Swollman return; 5924910Swollman case PPP_IP: 59325944Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 5944910Swollman schednetisr (NETISR_IP); 5954910Swollman inq = &ipintrq; 5964910Swollman } 59788577Sjoerg do_account++; 5984910Swollman break; 59988534Sjoerg case PPP_VJ_COMP: 60088534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 60188700Sjoerg if ((vjlen = 60288700Sjoerg sl_uncompress_tcp_core(mtod(m, u_char *), 60388700Sjoerg m->m_len, m->m_len, 60488700Sjoerg TYPE_COMPRESSED_TCP, 60588700Sjoerg sp->pp_comp, 60688700Sjoerg &iphdr, &hlen)) <= 0) { 60788700Sjoerg if (debug) 60888700Sjoerg log(LOG_INFO, 60988700Sjoerg SPP_FMT "VJ uncompress failed on compressed packet\n", 61088700Sjoerg SPP_ARGS(ifp)); 61188534Sjoerg goto drop; 61288700Sjoerg } 61388700Sjoerg 61488700Sjoerg /* 61588700Sjoerg * Trim the VJ header off the packet, and prepend 61688700Sjoerg * the uncompressed IP header (which will usually 61788700Sjoerg * end up in two chained mbufs since there's not 61888700Sjoerg * enough leading space in the existing mbuf). 61988700Sjoerg */ 62088700Sjoerg m_adj(m, vjlen); 62188700Sjoerg M_PREPEND(m, hlen, M_DONTWAIT); 62288700Sjoerg if (m == NULL) 62388700Sjoerg goto drop2; 62488700Sjoerg bcopy(iphdr, mtod(m, u_char *), hlen); 62588700Sjoerg 62688534Sjoerg schednetisr (NETISR_IP); 62788534Sjoerg inq = &ipintrq; 62888534Sjoerg } 62988599Sjoerg do_account++; 63088534Sjoerg break; 63188534Sjoerg case PPP_VJ_UCOMP: 63288534Sjoerg if (sp->state[IDX_IPCP] == STATE_OPENED) { 63388700Sjoerg if (sl_uncompress_tcp_core(mtod(m, u_char *), 63488700Sjoerg m->m_len, m->m_len, 63588700Sjoerg TYPE_UNCOMPRESSED_TCP, 63688700Sjoerg sp->pp_comp, 63788700Sjoerg &iphdr, &hlen) != 0) { 63888700Sjoerg if (debug) 63988700Sjoerg log(LOG_INFO, 64088700Sjoerg SPP_FMT "VJ uncompress failed on uncompressed packet\n", 64188700Sjoerg SPP_ARGS(ifp)); 64288534Sjoerg goto drop; 64388700Sjoerg } 64488534Sjoerg schednetisr (NETISR_IP); 64588534Sjoerg inq = &ipintrq; 64688534Sjoerg } 64788599Sjoerg do_account++; 64888534Sjoerg break; 64978064Sume#endif 65088599Sjoerg#ifdef INET6 65188599Sjoerg case PPP_IPV6CP: 65288599Sjoerg if (sp->pp_phase == PHASE_NETWORK) 65388599Sjoerg sppp_cp_input(&ipv6cp, sp, m); 65488599Sjoerg m_freem (m); 65588599Sjoerg return; 65688599Sjoerg 65788599Sjoerg case PPP_IPV6: 65888599Sjoerg if (sp->state[IDX_IPV6CP] == STATE_OPENED) { 65988599Sjoerg schednetisr (NETISR_IPV6); 66088599Sjoerg inq = &ip6intrq; 66188599Sjoerg } 66288599Sjoerg do_account++; 66388599Sjoerg break; 66488599Sjoerg#endif 66512495Speter#ifdef IPX 66612495Speter case PPP_IPX: 66712495Speter /* IPX IPXCP not implemented yet */ 66825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 66912495Speter schednetisr (NETISR_IPX); 67012495Speter inq = &ipxintrq; 67112495Speter } 67288577Sjoerg do_account++; 67312495Speter break; 67412495Speter#endif 6754910Swollman#ifdef NS 6764910Swollman case PPP_XNS: 6774910Swollman /* XNS IDPCP not implemented yet */ 67825944Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 6794910Swollman schednetisr (NETISR_NS); 6804910Swollman inq = &nsintrq; 6814910Swollman } 68288577Sjoerg do_account++; 6834910Swollman break; 6844910Swollman#endif 6854910Swollman } 6864910Swollman break; 6874910Swollman case CISCO_MULTICAST: 6884910Swollman case CISCO_UNICAST: 6894910Swollman /* Don't check the control field here (RFC 1547). */ 69045152Sphk if (sp->pp_mode != IFF_CISCO) { 69125944Sjoerg if (debug) 69225706Sjoerg log(LOG_DEBUG, 69340008Sjoerg SPP_FMT "Cisco packet in PPP mode " 69425706Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 69540008Sjoerg SPP_ARGS(ifp), 69625706Sjoerg h->address, h->control, ntohs(h->protocol)); 69711189Sjkh goto drop; 69811189Sjkh } 6994910Swollman switch (ntohs (h->protocol)) { 7004910Swollman default: 7014910Swollman ++ifp->if_noproto; 7024910Swollman goto invalid; 7034910Swollman case CISCO_KEEPALIVE: 7044910Swollman sppp_cisco_input ((struct sppp*) ifp, m); 7054910Swollman m_freem (m); 7064910Swollman return; 7074910Swollman#ifdef INET 7084910Swollman case ETHERTYPE_IP: 7094910Swollman schednetisr (NETISR_IP); 7104910Swollman inq = &ipintrq; 71188577Sjoerg do_account++; 7124910Swollman break; 7134910Swollman#endif 71454263Sshin#ifdef INET6 71554263Sshin case ETHERTYPE_IPV6: 71654263Sshin schednetisr (NETISR_IPV6); 71754263Sshin inq = &ip6intrq; 71888577Sjoerg do_account++; 71954263Sshin break; 72054263Sshin#endif 72112495Speter#ifdef IPX 72212495Speter case ETHERTYPE_IPX: 72312495Speter schednetisr (NETISR_IPX); 72412495Speter inq = &ipxintrq; 72588577Sjoerg do_account++; 72612495Speter break; 72712495Speter#endif 7284910Swollman#ifdef NS 7294910Swollman case ETHERTYPE_NS: 7304910Swollman schednetisr (NETISR_NS); 7314910Swollman inq = &nsintrq; 73288577Sjoerg do_account++; 7334910Swollman break; 7344910Swollman#endif 7354910Swollman } 7364910Swollman break; 73725944Sjoerg default: /* Invalid PPP packet. */ 73825944Sjoerg invalid: 73925944Sjoerg if (debug) 74025944Sjoerg log(LOG_DEBUG, 74140008Sjoerg SPP_FMT "invalid input packet " 74225944Sjoerg "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 74340008Sjoerg SPP_ARGS(ifp), 74425944Sjoerg h->address, h->control, ntohs(h->protocol)); 74525944Sjoerg goto drop; 7464910Swollman } 7474910Swollman 7484910Swollman if (! (ifp->if_flags & IFF_UP) || ! inq) 7494910Swollman goto drop; 7504910Swollman 7514910Swollman /* Check queue. */ 75269152Sjlemon if (! IF_HANDOFF(inq, m, NULL)) { 75325944Sjoerg if (debug) 75440008Sjoerg log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 75540008Sjoerg SPP_ARGS(ifp)); 7564910Swollman goto drop; 7574910Swollman } 75888577Sjoerg if (do_account) 75988577Sjoerg /* 76088577Sjoerg * Do only account for network packets, not for control 76188577Sjoerg * packets. This is used by some subsystems to detect 76288577Sjoerg * idle lines. 76388577Sjoerg */ 76488577Sjoerg sp->pp_last_recv = time_second; 7654910Swollman} 7664910Swollman 7674910Swollman/* 7684910Swollman * Enqueue transmit packet. 7694910Swollman */ 77012820Sphkstatic int 77125706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m, 77225706Sjoerg struct sockaddr *dst, struct rtentry *rt) 7734910Swollman{ 7744910Swollman struct sppp *sp = (struct sppp*) ifp; 7754910Swollman struct ppp_header *h; 77678064Sume struct ifqueue *ifq = NULL; 77725955Sjoerg int s, rv = 0; 77888534Sjoerg int ipproto = PPP_IP; 77942066Sphk int debug = ifp->if_flags & IFF_DEBUG; 7804910Swollman 78125944Sjoerg s = splimp(); 78225944Sjoerg 78325944Sjoerg if ((ifp->if_flags & IFF_UP) == 0 || 78425944Sjoerg (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 78588723Sjoerg#ifdef INET6 78688723Sjoerg drop: 78788723Sjoerg#endif 7884910Swollman m_freem (m); 7894910Swollman splx (s); 7904910Swollman return (ENETDOWN); 7914910Swollman } 7924910Swollman 79325944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 79488723Sjoerg#ifdef INET6 79525944Sjoerg /* 79688723Sjoerg * XXX 79788723Sjoerg * 79888723Sjoerg * Hack to prevent the initialization-time generated 79988723Sjoerg * IPv6 multicast packet to erroneously cause a 80088723Sjoerg * dialout event in case IPv6 has been 80188723Sjoerg * administratively disabled on that interface. 80288723Sjoerg */ 80388723Sjoerg if (dst->sa_family == AF_INET6 && 80488723Sjoerg !(sp->confflags & CONF_ENABLE_IPV6)) 80588723Sjoerg goto drop; 80688723Sjoerg#endif 80788723Sjoerg /* 80825944Sjoerg * Interface is not yet running, but auto-dial. Need 80925944Sjoerg * to start LCP for it. 81025944Sjoerg */ 81125944Sjoerg ifp->if_flags |= IFF_RUNNING; 81225944Sjoerg splx(s); 81325944Sjoerg lcp.Open(sp); 81425944Sjoerg s = splimp(); 81525944Sjoerg } 81625944Sjoerg 81778134Sume ifq = &ifp->if_snd; 8184910Swollman#ifdef INET 81912436Speter if (dst->sa_family == AF_INET) { 82040008Sjoerg /* XXX Check mbuf length here? */ 82112436Speter struct ip *ip = mtod (m, struct ip*); 82212436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8234910Swollman 82442104Sphk /* 82542104Sphk * When using dynamic local IP address assignment by using 82642104Sphk * 0.0.0.0 as a local address, the first TCP session will 82742104Sphk * not connect because the local TCP checksum is computed 82842104Sphk * using 0.0.0.0 which will later become our real IP address 82942104Sphk * so the TCP checksum computed at the remote end will 83042104Sphk * become invalid. So we 83142104Sphk * - don't let packets with src ip addr 0 thru 83242104Sphk * - we flag TCP packets with src ip 0 as an error 83370199Sjhay */ 83442104Sphk 83542104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 83642104Sphk { 83742104Sphk m_freem(m); 83842104Sphk splx(s); 83942104Sphk if(ip->ip_p == IPPROTO_TCP) 84042104Sphk return(EADDRNOTAVAIL); 84142104Sphk else 84242104Sphk return(0); 84342104Sphk } 84470199Sjhay 84542104Sphk /* 84642104Sphk * Put low delay, telnet, rlogin and ftp control packets 84742104Sphk * in front of the queue. 84842104Sphk */ 84969152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 85041686Sphk ; 85141686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 85212436Speter ifq = &sp->pp_fastq; 85341686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 85441686Sphk ; 85541686Sphk else if (ip->ip_p != IPPROTO_TCP) 85641686Sphk ; 85741686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 85841686Sphk ifq = &sp->pp_fastq; 85941686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 86041686Sphk ifq = &sp->pp_fastq; 86188534Sjoerg 86288534Sjoerg /* 86388534Sjoerg * Do IP Header compression 86488534Sjoerg */ 86588534Sjoerg if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 86688534Sjoerg ip->ip_p == IPPROTO_TCP) 86788599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 86888534Sjoerg sp->ipcp.compress_cid)) { 86988534Sjoerg case TYPE_COMPRESSED_TCP: 87088534Sjoerg ipproto = PPP_VJ_COMP; 87188534Sjoerg break; 87288534Sjoerg case TYPE_UNCOMPRESSED_TCP: 87388534Sjoerg ipproto = PPP_VJ_UCOMP; 87488534Sjoerg break; 87588534Sjoerg case TYPE_IP: 87688534Sjoerg ipproto = PPP_IP; 87788534Sjoerg break; 87888534Sjoerg default: 87988534Sjoerg m_freem(m); 88088534Sjoerg splx(s); 88188534Sjoerg return (EINVAL); 88288534Sjoerg } 8834910Swollman } 8844910Swollman#endif 8854910Swollman 88678064Sume#ifdef INET6 88778064Sume if (dst->sa_family == AF_INET6) { 88878064Sume /* XXX do something tricky here? */ 88978064Sume } 89078064Sume#endif 89178064Sume 8924910Swollman /* 8934910Swollman * Prepend general data packet PPP header. For now, IP only. 8944910Swollman */ 8954910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 8964910Swollman if (! m) { 89742066Sphk if (debug) 89840008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 89940008Sjoerg SPP_ARGS(ifp)); 90025944Sjoerg ++ifp->if_oerrors; 9014910Swollman splx (s); 9024910Swollman return (ENOBUFS); 9034910Swollman } 90440008Sjoerg /* 90540008Sjoerg * May want to check size of packet 90640008Sjoerg * (albeit due to the implementation it's always enough) 90740008Sjoerg */ 9084910Swollman h = mtod (m, struct ppp_header*); 90945152Sphk if (sp->pp_mode == IFF_CISCO) { 91028088Skjc h->address = CISCO_UNICAST; /* unicast address */ 9114910Swollman h->control = 0; 9124910Swollman } else { 9134910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 9144910Swollman h->control = PPP_UI; /* Unnumbered Info */ 9154910Swollman } 9164910Swollman 9174910Swollman switch (dst->sa_family) { 9184910Swollman#ifdef INET 9194910Swollman case AF_INET: /* Internet Protocol */ 92045152Sphk if (sp->pp_mode == IFF_CISCO) 92111189Sjkh h->protocol = htons (ETHERTYPE_IP); 92211189Sjkh else { 92325955Sjoerg /* 92425955Sjoerg * Don't choke with an ENETDOWN early. It's 92525955Sjoerg * possible that we just started dialing out, 92625955Sjoerg * so don't drop the packet immediately. If 92725955Sjoerg * we notice that we run out of buffer space 92825955Sjoerg * below, we will however remember that we are 92925955Sjoerg * not ready to carry IP packets, and return 93025955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 93125955Sjoerg */ 93288534Sjoerg h->protocol = htons(ipproto); 93325955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 93425955Sjoerg rv = ENETDOWN; 93511189Sjkh } 9364910Swollman break; 9374910Swollman#endif 93854263Sshin#ifdef INET6 93954263Sshin case AF_INET6: /* Internet Protocol */ 94054263Sshin if (sp->pp_mode == IFF_CISCO) 94154263Sshin h->protocol = htons (ETHERTYPE_IPV6); 94254263Sshin else { 94378064Sume /* 94478064Sume * Don't choke with an ENETDOWN early. It's 94578064Sume * possible that we just started dialing out, 94678064Sume * so don't drop the packet immediately. If 94778064Sume * we notice that we run out of buffer space 94878064Sume * below, we will however remember that we are 94978064Sume * not ready to carry IP packets, and return 95078064Sume * ENETDOWN, as opposed to ENOBUFS. 95178064Sume */ 95278064Sume h->protocol = htons(PPP_IPV6); 95378064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 95478064Sume rv = ENETDOWN; 95554263Sshin } 95654263Sshin break; 95754263Sshin#endif 9584910Swollman#ifdef NS 9594910Swollman case AF_NS: /* Xerox NS Protocol */ 96045152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 9614910Swollman ETHERTYPE_NS : PPP_XNS); 9624910Swollman break; 9634910Swollman#endif 96411819Sjulian#ifdef IPX 96512495Speter case AF_IPX: /* Novell IPX Protocol */ 96645152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 96712495Speter ETHERTYPE_IPX : PPP_IPX); 96811819Sjulian break; 96911819Sjulian#endif 9704910Swollman default: 9714910Swollman m_freem (m); 97225944Sjoerg ++ifp->if_oerrors; 9734910Swollman splx (s); 9744910Swollman return (EAFNOSUPPORT); 9754910Swollman } 9764910Swollman 9774910Swollman /* 9784910Swollman * Queue message on interface, and start output if interface 97988577Sjoerg * not yet active. 9804910Swollman */ 98169152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 98225944Sjoerg ++ifp->if_oerrors; 98325955Sjoerg return (rv? rv: ENOBUFS); 9844910Swollman } 98588577Sjoerg /* 98688577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 98788577Sjoerg * here since sppp_output() is only called on behalf of 98888577Sjoerg * network-layer traffic; control-layer traffic is handled 98988577Sjoerg * by sppp_cp_send(). 99088577Sjoerg */ 99188577Sjoerg sp->pp_last_sent = time_second; 9924910Swollman return (0); 9934910Swollman} 9944910Swollman 99525706Sjoergvoid 99625706Sjoergsppp_attach(struct ifnet *ifp) 9974910Swollman{ 9984910Swollman struct sppp *sp = (struct sppp*) ifp; 9994910Swollman 10004910Swollman /* Initialize keepalive handler. */ 10014910Swollman if (! spppq) 100242064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 10034910Swollman 10044910Swollman /* Insert new entry into the keepalive list. */ 10054910Swollman sp->pp_next = spppq; 10064910Swollman spppq = sp; 10074910Swollman 100842064Sphk sp->pp_if.if_mtu = PP_MTU; 100942064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 10104910Swollman sp->pp_if.if_type = IFT_PPP; 10114910Swollman sp->pp_if.if_output = sppp_output; 101242104Sphk#if 0 101342064Sphk sp->pp_flags = PP_KEEPALIVE; 101442104Sphk#endif 101570199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 101670199Sjhay sp->pp_fastq.ifq_maxlen = 32; 101770199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10184910Swollman sp->pp_loopcnt = 0; 10194910Swollman sp->pp_alivecnt = 0; 102078064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 102178064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 102225944Sjoerg sp->pp_phase = PHASE_DEAD; 102325944Sjoerg sp->pp_up = lcp.Up; 102425944Sjoerg sp->pp_down = lcp.Down; 102588716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 102693818Sjhb mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 102788716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 102893818Sjhb mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 102988599Sjoerg sp->pp_last_recv = sp->pp_last_sent = time_second; 103088723Sjoerg sp->confflags = 0; 103188723Sjoerg#ifdef INET 103288723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 103388723Sjoerg#endif 103488723Sjoerg#ifdef INET6 103588723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 103688723Sjoerg#endif 103788599Sjoerg sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAIT); 103888599Sjoerg sl_compress_init(sp->pp_comp, -1); 103925944Sjoerg sppp_lcp_init(sp); 104025944Sjoerg sppp_ipcp_init(sp); 104178064Sume sppp_ipv6cp_init(sp); 104230300Sjoerg sppp_pap_init(sp); 104330300Sjoerg sppp_chap_init(sp); 10444910Swollman} 10454910Swollman 104630300Sjoergvoid 104725706Sjoergsppp_detach(struct ifnet *ifp) 10484910Swollman{ 10494910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 105025944Sjoerg int i; 10514910Swollman 10524910Swollman /* Remove the entry from the keepalive list. */ 10534910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 10544910Swollman if (p == sp) { 10554910Swollman *q = p->pp_next; 10564910Swollman break; 10574910Swollman } 10584910Swollman 10594910Swollman /* Stop keepalive handler. */ 10604910Swollman if (! spppq) 106140008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 106225944Sjoerg 106325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 106440008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 106540008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 106669152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 106769152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 10684910Swollman} 10694910Swollman 10704910Swollman/* 10714910Swollman * Flush the interface output queue. 10724910Swollman */ 107325706Sjoergvoid 107425706Sjoergsppp_flush(struct ifnet *ifp) 10754910Swollman{ 10764910Swollman struct sppp *sp = (struct sppp*) ifp; 10774910Swollman 107825944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 107925944Sjoerg sppp_qflush (&sp->pp_fastq); 108026018Sjoerg sppp_qflush (&sp->pp_cpq); 10814910Swollman} 10824910Swollman 10834910Swollman/* 108411189Sjkh * Check if the output queue is empty. 108511189Sjkh */ 108612820Sphkint 108725706Sjoergsppp_isempty(struct ifnet *ifp) 108811189Sjkh{ 108911189Sjkh struct sppp *sp = (struct sppp*) ifp; 109025944Sjoerg int empty, s; 109111189Sjkh 109225944Sjoerg s = splimp(); 109326018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 109426018Sjoerg !sp->pp_if.if_snd.ifq_head; 109525944Sjoerg splx(s); 109611189Sjkh return (empty); 109711189Sjkh} 109811189Sjkh 109911189Sjkh/* 11004910Swollman * Get next packet to send. 11014910Swollman */ 110225706Sjoergstruct mbuf * 110325706Sjoergsppp_dequeue(struct ifnet *ifp) 11044910Swollman{ 11054910Swollman struct sppp *sp = (struct sppp*) ifp; 11064910Swollman struct mbuf *m; 110725944Sjoerg int s; 11084910Swollman 110925944Sjoerg s = splimp(); 111026018Sjoerg /* 111130300Sjoerg * Process only the control protocol queue until we have at 111230300Sjoerg * least one NCP open. 111326018Sjoerg * 111426018Sjoerg * Do always serve all three queues in Cisco mode. 111526018Sjoerg */ 111626018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 111726018Sjoerg if (m == NULL && 111845152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 111926018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 112026018Sjoerg if (m == NULL) 112126018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 112226018Sjoerg } 112326018Sjoerg splx(s); 112426018Sjoerg return m; 11254910Swollman} 11264910Swollman 11274910Swollman/* 112830300Sjoerg * Pick the next packet, do not remove it from the queue. 112930300Sjoerg */ 113030300Sjoergstruct mbuf * 113130300Sjoergsppp_pick(struct ifnet *ifp) 113230300Sjoerg{ 113330300Sjoerg struct sppp *sp = (struct sppp*)ifp; 113430300Sjoerg struct mbuf *m; 113530300Sjoerg int s; 113630300Sjoerg 113730300Sjoerg s= splimp (); 113830300Sjoerg 113930300Sjoerg m = sp->pp_cpq.ifq_head; 114030300Sjoerg if (m == NULL && 114145152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 114230300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 114330300Sjoerg m = sp->pp_if.if_snd.ifq_head; 114430300Sjoerg splx (s); 114530300Sjoerg return (m); 114630300Sjoerg} 114730300Sjoerg 114830300Sjoerg/* 114925944Sjoerg * Process an ioctl request. Called on low priority level. 11504910Swollman */ 115125944Sjoergint 115242104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 11534910Swollman{ 115425944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 115525944Sjoerg struct sppp *sp = (struct sppp*) ifp; 115630300Sjoerg int s, rv, going_up, going_down, newmode; 11574910Swollman 115825944Sjoerg s = splimp(); 115930300Sjoerg rv = 0; 116025944Sjoerg switch (cmd) { 116125944Sjoerg case SIOCAIFADDR: 116225944Sjoerg case SIOCSIFDSTADDR: 116325944Sjoerg break; 11644910Swollman 116525944Sjoerg case SIOCSIFADDR: 116688503Sjoerg /* set the interface "up" when assigning an IP address */ 116788503Sjoerg ifp->if_flags |= IFF_UP; 116825944Sjoerg /* fall through... */ 116911189Sjkh 117025944Sjoerg case SIOCSIFFLAGS: 117125944Sjoerg going_up = ifp->if_flags & IFF_UP && 117225944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 117325944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 117425944Sjoerg ifp->if_flags & IFF_RUNNING; 117545152Sphk 117645152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 117745152Sphk if (!newmode) 117845152Sphk newmode = ifp->if_flags & IFF_AUTO; 117945152Sphk if (!newmode) 118045152Sphk newmode = ifp->if_flags & IFF_CISCO; 118145152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 118245152Sphk ifp->if_flags |= newmode; 118345152Sphk 118445152Sphk if (newmode != sp->pp_mode) { 118545152Sphk going_down = 1; 118645152Sphk if (!going_up) 118745152Sphk going_up = ifp->if_flags & IFF_RUNNING; 11884910Swollman } 11894910Swollman 119045152Sphk if (going_down) { 119170199Sjhay if (sp->pp_mode != IFF_CISCO) 119245152Sphk lcp.Close(sp); 119345152Sphk else if (sp->pp_tlf) 119445152Sphk (sp->pp_tlf)(sp); 119526018Sjoerg sppp_flush(ifp); 119625944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 119745152Sphk sp->pp_mode = newmode; 119826018Sjoerg } 11994910Swollman 120045152Sphk if (going_up) { 120170199Sjhay if (sp->pp_mode != IFF_CISCO) 120245152Sphk lcp.Close(sp); 120345152Sphk sp->pp_mode = newmode; 120445152Sphk if (sp->pp_mode == 0) { 120545152Sphk ifp->if_flags |= IFF_RUNNING; 120645152Sphk lcp.Open(sp); 120745152Sphk } 120845152Sphk if (sp->pp_mode == IFF_CISCO) { 120945152Sphk if (sp->pp_tls) 121045152Sphk (sp->pp_tls)(sp); 121145152Sphk ifp->if_flags |= IFF_RUNNING; 121245152Sphk } 121345152Sphk } 121445152Sphk 12154910Swollman break; 121611189Sjkh 121725944Sjoerg#ifdef SIOCSIFMTU 121825944Sjoerg#ifndef ifr_mtu 121925944Sjoerg#define ifr_mtu ifr_metric 122025944Sjoerg#endif 122125944Sjoerg case SIOCSIFMTU: 122225944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 122325944Sjoerg return (EINVAL); 122425944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12254910Swollman break; 122625944Sjoerg#endif 122725944Sjoerg#ifdef SLIOCSETMTU 122825944Sjoerg case SLIOCSETMTU: 122925944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 123025944Sjoerg return (EINVAL); 123125944Sjoerg ifp->if_mtu = *(short*)data; 12324910Swollman break; 123325944Sjoerg#endif 123425944Sjoerg#ifdef SIOCGIFMTU 123525944Sjoerg case SIOCGIFMTU: 123625944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 123711189Sjkh break; 123825944Sjoerg#endif 123925944Sjoerg#ifdef SLIOCGETMTU 124025944Sjoerg case SLIOCGETMTU: 124125944Sjoerg *(short*)data = ifp->if_mtu; 12424910Swollman break; 124325944Sjoerg#endif 124425944Sjoerg case SIOCADDMULTI: 124525944Sjoerg case SIOCDELMULTI: 12464910Swollman break; 124711189Sjkh 124830300Sjoerg case SIOCGIFGENERIC: 124930300Sjoerg case SIOCSIFGENERIC: 125030300Sjoerg rv = sppp_params(sp, cmd, data); 125130300Sjoerg break; 125230300Sjoerg 125325944Sjoerg default: 125430300Sjoerg rv = ENOTTY; 12554910Swollman } 125625944Sjoerg splx(s); 125730300Sjoerg return rv; 12584910Swollman} 12594910Swollman 126070199Sjhay/* 126125944Sjoerg * Cisco framing implementation. 126225944Sjoerg */ 126325944Sjoerg 12644910Swollman/* 12654910Swollman * Handle incoming Cisco keepalive protocol packets. 12664910Swollman */ 126730300Sjoergstatic void 126825706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 12694910Swollman{ 127025944Sjoerg STDDCL; 12714910Swollman struct cisco_packet *h; 127230300Sjoerg u_long me, mymask; 12734910Swollman 127427929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 127525706Sjoerg if (debug) 127625706Sjoerg log(LOG_DEBUG, 127740008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 127840008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 12794910Swollman return; 12804910Swollman } 12814910Swollman h = mtod (m, struct cisco_packet*); 128225706Sjoerg if (debug) 128325706Sjoerg log(LOG_DEBUG, 128440008Sjoerg SPP_FMT "cisco input: %d bytes " 128525706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 128640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 128740008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 128840008Sjoerg (u_int)h->time0, (u_int)h->time1); 12894910Swollman switch (ntohl (h->type)) { 12904910Swollman default: 129125706Sjoerg if (debug) 129269211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 129340008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 12944910Swollman break; 12954910Swollman case CISCO_ADDR_REPLY: 12964910Swollman /* Reply on address request, ignore */ 12974910Swollman break; 12984910Swollman case CISCO_KEEPALIVE_REQ: 12994910Swollman sp->pp_alivecnt = 0; 130078064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 130178064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 13024910Swollman /* Local and remote sequence numbers are equal. 13034910Swollman * Probably, the line is in loopback mode. */ 130411189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 130540008Sjoerg printf (SPP_FMT "loopback\n", 130640008Sjoerg SPP_ARGS(ifp)); 130711189Sjkh sp->pp_loopcnt = 0; 130811189Sjkh if (ifp->if_flags & IFF_UP) { 130911189Sjkh if_down (ifp); 131026018Sjoerg sppp_qflush (&sp->pp_cpq); 131111189Sjkh } 131211189Sjkh } 13134910Swollman ++sp->pp_loopcnt; 13144910Swollman 13154910Swollman /* Generate new local sequence number */ 131642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 131778064Sume sp->pp_seq[IDX_LCP] = random(); 131840008Sjoerg#else 131978064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 132040008Sjoerg#endif 132111189Sjkh break; 132211189Sjkh } 132330300Sjoerg sp->pp_loopcnt = 0; 132411189Sjkh if (! (ifp->if_flags & IFF_UP) && 132511189Sjkh (ifp->if_flags & IFF_RUNNING)) { 132630300Sjoerg if_up(ifp); 132740008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 132811189Sjkh } 13294910Swollman break; 13304910Swollman case CISCO_ADDR_REQ: 133130300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 133230300Sjoerg if (me != 0L) 133330300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13344910Swollman break; 13354910Swollman } 13364910Swollman} 13374910Swollman 13384910Swollman/* 133925944Sjoerg * Send Cisco keepalive packet. 13404910Swollman */ 134112820Sphkstatic void 134225944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 134325944Sjoerg{ 134425944Sjoerg STDDCL; 134525944Sjoerg struct ppp_header *h; 134625944Sjoerg struct cisco_packet *ch; 134725944Sjoerg struct mbuf *m; 134842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 134935029Sphk struct timeval tv; 135040008Sjoerg#else 135140008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 135240008Sjoerg#endif 135325944Sjoerg 135442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 135536119Sphk getmicrouptime(&tv); 135640008Sjoerg#endif 135770199Sjhay 135825944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 135925944Sjoerg if (! m) 136025944Sjoerg return; 136125944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 136225944Sjoerg m->m_pkthdr.rcvif = 0; 136325944Sjoerg 136425944Sjoerg h = mtod (m, struct ppp_header*); 136525944Sjoerg h->address = CISCO_MULTICAST; 136625944Sjoerg h->control = 0; 136725944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 136825944Sjoerg 136925944Sjoerg ch = (struct cisco_packet*) (h + 1); 137025944Sjoerg ch->type = htonl (type); 137125944Sjoerg ch->par1 = htonl (par1); 137225944Sjoerg ch->par2 = htonl (par2); 137325944Sjoerg ch->rel = -1; 137440008Sjoerg 137542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 137635029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 137735029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 137840008Sjoerg#else 137940008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 138040008Sjoerg ch->time1 = htons ((u_short) t); 138140008Sjoerg#endif 138225944Sjoerg 138325944Sjoerg if (debug) 138425944Sjoerg log(LOG_DEBUG, 138540008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 138640008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 138740008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 138825944Sjoerg 138969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 139069152Sjlemon ifp->if_oerrors++; 139125944Sjoerg} 139225944Sjoerg 139370199Sjhay/* 139425944Sjoerg * PPP protocol implementation. 139525944Sjoerg */ 139625944Sjoerg 139725944Sjoerg/* 139825944Sjoerg * Send PPP control protocol packet. 139925944Sjoerg */ 140025944Sjoergstatic void 140125706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 140225706Sjoerg u_char ident, u_short len, void *data) 14034910Swollman{ 140425944Sjoerg STDDCL; 14054910Swollman struct ppp_header *h; 14064910Swollman struct lcp_header *lh; 14074910Swollman struct mbuf *m; 14084910Swollman 14094910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 14104910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 14114910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 14124910Swollman if (! m) 14134910Swollman return; 14144910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 14154910Swollman m->m_pkthdr.rcvif = 0; 14164910Swollman 14174910Swollman h = mtod (m, struct ppp_header*); 14184910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 14194910Swollman h->control = PPP_UI; /* Unnumbered Info */ 14204910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 14214910Swollman 14224910Swollman lh = (struct lcp_header*) (h + 1); 14234910Swollman lh->type = type; 14244910Swollman lh->ident = ident; 14254910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14264910Swollman if (len) 14274910Swollman bcopy (data, lh+1, len); 14284910Swollman 142925706Sjoerg if (debug) { 143040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 143140008Sjoerg SPP_ARGS(ifp), 143225944Sjoerg sppp_proto_name(proto), 143325944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 143425944Sjoerg ntohs (lh->len)); 143544145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 143669211Sphk log(-1, ">\n"); 14374910Swollman } 143869152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 143969152Sjlemon ifp->if_oerrors++; 14404910Swollman} 14414910Swollman 14424910Swollman/* 144325944Sjoerg * Handle incoming PPP control protocol packets. 14444910Swollman */ 144512820Sphkstatic void 144625944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14474910Swollman{ 144825944Sjoerg STDDCL; 144925944Sjoerg struct lcp_header *h; 145025944Sjoerg int len = m->m_pkthdr.len; 145125944Sjoerg int rv; 145225944Sjoerg u_char *p; 14534910Swollman 145425944Sjoerg if (len < 4) { 145525944Sjoerg if (debug) 145625944Sjoerg log(LOG_DEBUG, 145740008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 145840008Sjoerg SPP_ARGS(ifp), cp->name, len); 14594910Swollman return; 146025944Sjoerg } 146125944Sjoerg h = mtod (m, struct lcp_header*); 146225944Sjoerg if (debug) { 146325944Sjoerg log(LOG_DEBUG, 146440008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 146540008Sjoerg SPP_ARGS(ifp), cp->name, 146625944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 146725944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 146844145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 146969211Sphk log(-1, ">\n"); 147025944Sjoerg } 147125944Sjoerg if (len > ntohs (h->len)) 147225944Sjoerg len = ntohs (h->len); 147330300Sjoerg p = (u_char *)(h + 1); 147425944Sjoerg switch (h->type) { 147525944Sjoerg case CONF_REQ: 147625944Sjoerg if (len < 4) { 147725944Sjoerg if (debug) 147869211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 147940008Sjoerg SPP_ARGS(ifp), cp->name, 148025944Sjoerg len); 148125944Sjoerg ++ifp->if_ierrors; 148225944Sjoerg break; 148325944Sjoerg } 148430300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 148530300Sjoerg switch (sp->state[cp->protoidx]) { 148630300Sjoerg case STATE_CLOSING: 148730300Sjoerg case STATE_STOPPING: 148830300Sjoerg return; 148930300Sjoerg case STATE_CLOSED: 149030300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 149130300Sjoerg 0, 0); 149230300Sjoerg return; 149330300Sjoerg } 149425944Sjoerg rv = (cp->RCR)(sp, h, len); 149525944Sjoerg switch (sp->state[cp->protoidx]) { 149625944Sjoerg case STATE_OPENED: 149725944Sjoerg (cp->tld)(sp); 149825944Sjoerg (cp->scr)(sp); 149925944Sjoerg /* fall through... */ 150025944Sjoerg case STATE_ACK_SENT: 150125944Sjoerg case STATE_REQ_SENT: 150270199Sjhay /* 150370199Sjhay * sppp_cp_change_state() have the side effect of 150470199Sjhay * restarting the timeouts. We want to avoid that 150570199Sjhay * if the state don't change, otherwise we won't 150670199Sjhay * ever timeout and resend a configuration request 150770199Sjhay * that got lost. 150870199Sjhay */ 150970199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 151070199Sjhay STATE_REQ_SENT)) 151170199Sjhay break; 151225944Sjoerg sppp_cp_change_state(cp, sp, rv? 151325944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 151425944Sjoerg break; 151525944Sjoerg case STATE_STOPPED: 151625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 151725944Sjoerg (cp->scr)(sp); 151825944Sjoerg sppp_cp_change_state(cp, sp, rv? 151925944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 152025944Sjoerg break; 152125944Sjoerg case STATE_ACK_RCVD: 152225944Sjoerg if (rv) { 152325944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 152425944Sjoerg if (debug) 152540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 152640008Sjoerg SPP_ARGS(ifp), 152726077Sjoerg cp->name); 152825944Sjoerg (cp->tlu)(sp); 152925944Sjoerg } else 153025944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 153125944Sjoerg break; 153225944Sjoerg default: 153340008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 153440008Sjoerg SPP_ARGS(ifp), cp->name, 153525944Sjoerg sppp_cp_type_name(h->type), 153625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 153725944Sjoerg ++ifp->if_ierrors; 153825944Sjoerg } 153925944Sjoerg break; 154025944Sjoerg case CONF_ACK: 154125944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 154225944Sjoerg if (debug) 154369211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 154440008Sjoerg SPP_ARGS(ifp), cp->name, 154525944Sjoerg h->ident, sp->confid[cp->protoidx]); 154625944Sjoerg ++ifp->if_ierrors; 154725944Sjoerg break; 154825944Sjoerg } 154925944Sjoerg switch (sp->state[cp->protoidx]) { 155025944Sjoerg case STATE_CLOSED: 155125944Sjoerg case STATE_STOPPED: 155225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 155325944Sjoerg break; 155425944Sjoerg case STATE_CLOSING: 155525944Sjoerg case STATE_STOPPING: 155625944Sjoerg break; 155725944Sjoerg case STATE_REQ_SENT: 155825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 155925944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 156025944Sjoerg break; 156125944Sjoerg case STATE_OPENED: 156225944Sjoerg (cp->tld)(sp); 156325944Sjoerg /* fall through */ 156425944Sjoerg case STATE_ACK_RCVD: 156525944Sjoerg (cp->scr)(sp); 156625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 156725944Sjoerg break; 156825944Sjoerg case STATE_ACK_SENT: 156925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 157025944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 157125944Sjoerg if (debug) 157240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 157340008Sjoerg SPP_ARGS(ifp), cp->name); 157425944Sjoerg (cp->tlu)(sp); 157525944Sjoerg break; 157625944Sjoerg default: 157740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 157840008Sjoerg SPP_ARGS(ifp), cp->name, 157925944Sjoerg sppp_cp_type_name(h->type), 158025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 158125944Sjoerg ++ifp->if_ierrors; 158225944Sjoerg } 158325944Sjoerg break; 158425944Sjoerg case CONF_NAK: 158525944Sjoerg case CONF_REJ: 158625944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 158725944Sjoerg if (debug) 158869211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 158940008Sjoerg SPP_ARGS(ifp), cp->name, 159025944Sjoerg h->ident, sp->confid[cp->protoidx]); 159125944Sjoerg ++ifp->if_ierrors; 159225944Sjoerg break; 159325944Sjoerg } 159425944Sjoerg if (h->type == CONF_NAK) 159525944Sjoerg (cp->RCN_nak)(sp, h, len); 159625944Sjoerg else /* CONF_REJ */ 159725944Sjoerg (cp->RCN_rej)(sp, h, len); 15984910Swollman 159925944Sjoerg switch (sp->state[cp->protoidx]) { 160025944Sjoerg case STATE_CLOSED: 160125944Sjoerg case STATE_STOPPED: 160225944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 160325944Sjoerg break; 160425944Sjoerg case STATE_REQ_SENT: 160525944Sjoerg case STATE_ACK_SENT: 160625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 160770199Sjhay /* 160870199Sjhay * Slow things down a bit if we think we might be 160970199Sjhay * in loopback. Depend on the timeout to send the 161070199Sjhay * next configuration request. 161170199Sjhay */ 161270199Sjhay if (sp->pp_loopcnt) 161370199Sjhay break; 161425944Sjoerg (cp->scr)(sp); 161525944Sjoerg break; 161625944Sjoerg case STATE_OPENED: 161725944Sjoerg (cp->tld)(sp); 161825944Sjoerg /* fall through */ 161925944Sjoerg case STATE_ACK_RCVD: 162052633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 162125944Sjoerg (cp->scr)(sp); 162225944Sjoerg break; 162325944Sjoerg case STATE_CLOSING: 162425944Sjoerg case STATE_STOPPING: 162525944Sjoerg break; 162625944Sjoerg default: 162740008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 162840008Sjoerg SPP_ARGS(ifp), cp->name, 162925944Sjoerg sppp_cp_type_name(h->type), 163025944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 163125944Sjoerg ++ifp->if_ierrors; 163225944Sjoerg } 163325944Sjoerg break; 16344910Swollman 163525944Sjoerg case TERM_REQ: 163625944Sjoerg switch (sp->state[cp->protoidx]) { 163725944Sjoerg case STATE_ACK_RCVD: 163825944Sjoerg case STATE_ACK_SENT: 163925944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 164025944Sjoerg /* fall through */ 164125944Sjoerg case STATE_CLOSED: 164225944Sjoerg case STATE_STOPPED: 164325944Sjoerg case STATE_CLOSING: 164425944Sjoerg case STATE_STOPPING: 164525944Sjoerg case STATE_REQ_SENT: 164625944Sjoerg sta: 164725944Sjoerg /* Send Terminate-Ack packet. */ 164825944Sjoerg if (debug) 164940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 165040008Sjoerg SPP_ARGS(ifp), cp->name); 165125944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 165225944Sjoerg break; 165325944Sjoerg case STATE_OPENED: 165425944Sjoerg (cp->tld)(sp); 165525944Sjoerg sp->rst_counter[cp->protoidx] = 0; 165625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 165725944Sjoerg goto sta; 165825944Sjoerg break; 165925944Sjoerg default: 166040008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 166140008Sjoerg SPP_ARGS(ifp), cp->name, 166225944Sjoerg sppp_cp_type_name(h->type), 166325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 166425944Sjoerg ++ifp->if_ierrors; 166525944Sjoerg } 166625944Sjoerg break; 166725944Sjoerg case TERM_ACK: 166825944Sjoerg switch (sp->state[cp->protoidx]) { 166925944Sjoerg case STATE_CLOSED: 167025944Sjoerg case STATE_STOPPED: 167125944Sjoerg case STATE_REQ_SENT: 167225944Sjoerg case STATE_ACK_SENT: 167325944Sjoerg break; 167425944Sjoerg case STATE_CLOSING: 167541881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 167625944Sjoerg (cp->tlf)(sp); 167725944Sjoerg break; 167825944Sjoerg case STATE_STOPPING: 167941881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 168025944Sjoerg (cp->tlf)(sp); 168125944Sjoerg break; 168225944Sjoerg case STATE_ACK_RCVD: 168325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 168425944Sjoerg break; 168525944Sjoerg case STATE_OPENED: 168625944Sjoerg (cp->tld)(sp); 168725944Sjoerg (cp->scr)(sp); 168825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 168925944Sjoerg break; 169025944Sjoerg default: 169140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169240008Sjoerg SPP_ARGS(ifp), cp->name, 169325944Sjoerg sppp_cp_type_name(h->type), 169425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 169525944Sjoerg ++ifp->if_ierrors; 169625944Sjoerg } 169725944Sjoerg break; 169825944Sjoerg case CODE_REJ: 169925944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 170030300Sjoerg log(LOG_INFO, 170140008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 170230300Sjoerg "danger will robinson\n", 170340008Sjoerg SPP_ARGS(ifp), cp->name, 170430300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 170525944Sjoerg switch (sp->state[cp->protoidx]) { 170625944Sjoerg case STATE_CLOSED: 170725944Sjoerg case STATE_STOPPED: 170825944Sjoerg case STATE_REQ_SENT: 170925944Sjoerg case STATE_ACK_SENT: 171025944Sjoerg case STATE_CLOSING: 171125944Sjoerg case STATE_STOPPING: 171225944Sjoerg case STATE_OPENED: 171325944Sjoerg break; 171425944Sjoerg case STATE_ACK_RCVD: 171525944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 171625944Sjoerg break; 171725944Sjoerg default: 171840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 171940008Sjoerg SPP_ARGS(ifp), cp->name, 172025944Sjoerg sppp_cp_type_name(h->type), 172125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 172225944Sjoerg ++ifp->if_ierrors; 172325944Sjoerg } 172425944Sjoerg break; 172580715Sume case PROTO_REJ: 172680715Sume { 172780715Sume int catastrophic; 172880715Sume const struct cp *upper; 172980715Sume int i; 173080715Sume u_int16_t proto; 173180715Sume 173280715Sume catastrophic = 0; 173380715Sume upper = NULL; 173480715Sume proto = ntohs(*((u_int16_t *)p)); 173580715Sume for (i = 0; i < IDX_COUNT; i++) { 173680715Sume if (cps[i]->proto == proto) { 173780715Sume upper = cps[i]; 173880715Sume break; 173980715Sume } 174080715Sume } 174180715Sume if (upper == NULL) 174280715Sume catastrophic++; 174380715Sume 174488508Sjoerg if (catastrophic || debug) 174588508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 174688508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 174788508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 174888508Sjoerg sppp_cp_type_name(h->type), proto, 174988508Sjoerg upper ? upper->name : "unknown", 175088508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 175180715Sume 175280715Sume /* 175380715Sume * if we got RXJ+ against conf-req, the peer does not implement 175480715Sume * this particular protocol type. terminate the protocol. 175580715Sume */ 175680715Sume if (upper && !catastrophic) { 175780715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 175880715Sume upper->Close(sp); 175980715Sume break; 176080715Sume } 176180715Sume } 176280715Sume 176380715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 176480715Sume switch (sp->state[cp->protoidx]) { 176580715Sume case STATE_CLOSED: 176680715Sume case STATE_STOPPED: 176780715Sume case STATE_REQ_SENT: 176880715Sume case STATE_ACK_SENT: 176980715Sume case STATE_CLOSING: 177080715Sume case STATE_STOPPING: 177180715Sume case STATE_OPENED: 177280715Sume break; 177380715Sume case STATE_ACK_RCVD: 177480715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 177580715Sume break; 177680715Sume default: 177780715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 177880715Sume SPP_ARGS(ifp), cp->name, 177980715Sume sppp_cp_type_name(h->type), 178080715Sume sppp_state_name(sp->state[cp->protoidx])); 178180715Sume ++ifp->if_ierrors; 178280715Sume } 178380715Sume break; 178480715Sume } 178525944Sjoerg case DISC_REQ: 178625944Sjoerg if (cp->proto != PPP_LCP) 178725944Sjoerg goto illegal; 178825944Sjoerg /* Discard the packet. */ 178925944Sjoerg break; 179025944Sjoerg case ECHO_REQ: 179125944Sjoerg if (cp->proto != PPP_LCP) 179225944Sjoerg goto illegal; 179325944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 179425944Sjoerg if (debug) 179569211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 179640008Sjoerg SPP_ARGS(ifp)); 179725944Sjoerg ++ifp->if_ierrors; 179825944Sjoerg break; 179925944Sjoerg } 180025944Sjoerg if (len < 8) { 180125944Sjoerg if (debug) 180269211Sphk log(-1, SPP_FMT "invalid lcp echo request " 180325944Sjoerg "packet length: %d bytes\n", 180440008Sjoerg SPP_ARGS(ifp), len); 180525944Sjoerg break; 180625944Sjoerg } 180744145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 180844145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 180925944Sjoerg /* Line loopback mode detected. */ 181040008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 181170199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 181225944Sjoerg if_down (ifp); 181326018Sjoerg sppp_qflush (&sp->pp_cpq); 18144910Swollman 181525944Sjoerg /* Shut down the PPP link. */ 181625944Sjoerg /* XXX */ 181725944Sjoerg lcp.Down(sp); 181825944Sjoerg lcp.Up(sp); 181925944Sjoerg break; 182025944Sjoerg } 182125944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 182225944Sjoerg if (debug) 182369211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 182440008Sjoerg SPP_ARGS(ifp)); 182525944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 182625944Sjoerg break; 182725944Sjoerg case ECHO_REPLY: 182825944Sjoerg if (cp->proto != PPP_LCP) 182925944Sjoerg goto illegal; 183025944Sjoerg if (h->ident != sp->lcp.echoid) { 183125944Sjoerg ++ifp->if_ierrors; 183225944Sjoerg break; 183325944Sjoerg } 183425944Sjoerg if (len < 8) { 183525944Sjoerg if (debug) 183669211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 183725944Sjoerg "packet length: %d bytes\n", 183840008Sjoerg SPP_ARGS(ifp), len); 183925944Sjoerg break; 184025944Sjoerg } 184125944Sjoerg if (debug) 184269211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 184340008Sjoerg SPP_ARGS(ifp)); 184444145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 184544145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 184625944Sjoerg sp->pp_alivecnt = 0; 184725944Sjoerg break; 184825944Sjoerg default: 184925944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 185025944Sjoerg illegal: 185125944Sjoerg if (debug) 185269211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 185340008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 185478064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 185578064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 185625944Sjoerg ++ifp->if_ierrors; 185725944Sjoerg } 18584910Swollman} 18594910Swollman 186025944Sjoerg 18614910Swollman/* 186225944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 186325944Sjoerg * Basically, the state transition handling in the automaton. 18644910Swollman */ 186525944Sjoergstatic void 186625944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18674910Swollman{ 186825944Sjoerg STDDCL; 18694910Swollman 187025944Sjoerg if (debug) 187140008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 187240008Sjoerg SPP_ARGS(ifp), cp->name, 187325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 187425944Sjoerg 187525944Sjoerg switch (sp->state[cp->protoidx]) { 187625944Sjoerg case STATE_INITIAL: 187725944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 187825944Sjoerg break; 187925944Sjoerg case STATE_STARTING: 188025944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 188125944Sjoerg (cp->scr)(sp); 188225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 188325944Sjoerg break; 18844910Swollman default: 188540008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 188640008Sjoerg SPP_ARGS(ifp), cp->name, 188725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 188825944Sjoerg } 188925944Sjoerg} 18904910Swollman 189125944Sjoergstatic void 189225944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 189325944Sjoerg{ 189425944Sjoerg STDDCL; 189525944Sjoerg 189625944Sjoerg if (debug) 189740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 189840008Sjoerg SPP_ARGS(ifp), cp->name, 189925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190025944Sjoerg 190125944Sjoerg switch (sp->state[cp->protoidx]) { 190225944Sjoerg case STATE_CLOSED: 190325944Sjoerg case STATE_CLOSING: 190425944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 19054910Swollman break; 190625944Sjoerg case STATE_STOPPED: 190741881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 190825944Sjoerg (cp->tls)(sp); 190941881Sphk break; 191025944Sjoerg case STATE_STOPPING: 191125944Sjoerg case STATE_REQ_SENT: 191225944Sjoerg case STATE_ACK_RCVD: 191325944Sjoerg case STATE_ACK_SENT: 191425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 191525944Sjoerg break; 191625944Sjoerg case STATE_OPENED: 191725944Sjoerg (cp->tld)(sp); 191825944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 191925944Sjoerg break; 192025944Sjoerg default: 192140008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 192240008Sjoerg SPP_ARGS(ifp), cp->name, 192325944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 192425944Sjoerg } 192525944Sjoerg} 19264910Swollman 192711189Sjkh 192825944Sjoergstatic void 192925944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 193025944Sjoerg{ 193125944Sjoerg STDDCL; 193225944Sjoerg 193325944Sjoerg if (debug) 193440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 193540008Sjoerg SPP_ARGS(ifp), cp->name, 193625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 193725944Sjoerg 193825944Sjoerg switch (sp->state[cp->protoidx]) { 193925944Sjoerg case STATE_INITIAL: 194041881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 194125944Sjoerg (cp->tls)(sp); 19424910Swollman break; 194325944Sjoerg case STATE_STARTING: 194425944Sjoerg break; 194525944Sjoerg case STATE_CLOSED: 194625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 194725944Sjoerg (cp->scr)(sp); 194825944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 194925944Sjoerg break; 195025944Sjoerg case STATE_STOPPED: 195174703Sjoerg /* 195274703Sjoerg * Try escaping stopped state. This seems to bite 195374703Sjoerg * people occasionally, in particular for IPCP, 195474703Sjoerg * presumably following previous IPCP negotiation 195574703Sjoerg * aborts. Somehow, we must have missed a Down event 195674703Sjoerg * which would have caused a transition into starting 195774703Sjoerg * state, so as a bandaid we force the Down event now. 195874703Sjoerg * This effectively implements (something like the) 195974703Sjoerg * `restart' option mentioned in the state transition 196074703Sjoerg * table of RFC 1661. 196174703Sjoerg */ 196274703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 196374703Sjoerg (cp->tls)(sp); 196474703Sjoerg break; 196525944Sjoerg case STATE_STOPPING: 196625944Sjoerg case STATE_REQ_SENT: 196725944Sjoerg case STATE_ACK_RCVD: 196825944Sjoerg case STATE_ACK_SENT: 196925944Sjoerg case STATE_OPENED: 197025944Sjoerg break; 197125944Sjoerg case STATE_CLOSING: 197225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 197325944Sjoerg break; 197425944Sjoerg } 197525944Sjoerg} 19764910Swollman 197725944Sjoerg 197825944Sjoergstatic void 197925944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 198025944Sjoerg{ 198125944Sjoerg STDDCL; 198225944Sjoerg 198325944Sjoerg if (debug) 198440008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 198540008Sjoerg SPP_ARGS(ifp), cp->name, 198625944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 198725944Sjoerg 198825944Sjoerg switch (sp->state[cp->protoidx]) { 198925944Sjoerg case STATE_INITIAL: 199025944Sjoerg case STATE_CLOSED: 199125944Sjoerg case STATE_CLOSING: 19924910Swollman break; 199325944Sjoerg case STATE_STARTING: 199441881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 199525944Sjoerg (cp->tlf)(sp); 19964910Swollman break; 199725944Sjoerg case STATE_STOPPED: 199825944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 19994910Swollman break; 200025944Sjoerg case STATE_STOPPING: 200125944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20024910Swollman break; 200325944Sjoerg case STATE_OPENED: 200425944Sjoerg (cp->tld)(sp); 200525944Sjoerg /* fall through */ 200625944Sjoerg case STATE_REQ_SENT: 200725944Sjoerg case STATE_ACK_RCVD: 200825944Sjoerg case STATE_ACK_SENT: 200925944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 201078064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 201178064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 201225944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 20134910Swollman break; 20144910Swollman } 20154910Swollman} 20164910Swollman 201725944Sjoergstatic void 201825944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 201925944Sjoerg{ 202025944Sjoerg STDDCL; 202125944Sjoerg int s; 202225944Sjoerg 202325944Sjoerg s = splimp(); 202425944Sjoerg if (debug) 202540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 202640008Sjoerg SPP_ARGS(ifp), cp->name, 202725944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 202825944Sjoerg sp->rst_counter[cp->protoidx]); 202925944Sjoerg 203025944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 203125944Sjoerg /* TO- event */ 203225944Sjoerg switch (sp->state[cp->protoidx]) { 203325944Sjoerg case STATE_CLOSING: 203441881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 203525944Sjoerg (cp->tlf)(sp); 203625944Sjoerg break; 203725944Sjoerg case STATE_STOPPING: 203841881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 203925944Sjoerg (cp->tlf)(sp); 204025944Sjoerg break; 204125944Sjoerg case STATE_REQ_SENT: 204225944Sjoerg case STATE_ACK_RCVD: 204325944Sjoerg case STATE_ACK_SENT: 204441881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 204525944Sjoerg (cp->tlf)(sp); 204625944Sjoerg break; 204725944Sjoerg } 204825944Sjoerg else 204925944Sjoerg /* TO+ event */ 205025944Sjoerg switch (sp->state[cp->protoidx]) { 205125944Sjoerg case STATE_CLOSING: 205225944Sjoerg case STATE_STOPPING: 205378064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 205478064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 205570199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 205642064Sphk sp->ch[cp->protoidx]); 205725944Sjoerg break; 205825944Sjoerg case STATE_REQ_SENT: 205925944Sjoerg case STATE_ACK_RCVD: 206025944Sjoerg (cp->scr)(sp); 206125944Sjoerg /* sppp_cp_change_state() will restart the timer */ 206225944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 206325944Sjoerg break; 206425944Sjoerg case STATE_ACK_SENT: 206525944Sjoerg (cp->scr)(sp); 206642064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 206742064Sphk sp->ch[cp->protoidx]); 206825944Sjoerg break; 206925944Sjoerg } 207025944Sjoerg 207125944Sjoerg splx(s); 207225944Sjoerg} 207325944Sjoerg 207411189Sjkh/* 207525944Sjoerg * Change the state of a control protocol in the state automaton. 207625944Sjoerg * Takes care of starting/stopping the restart timer. 207711189Sjkh */ 207825944Sjoergvoid 207925944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 208025944Sjoerg{ 208125944Sjoerg sp->state[cp->protoidx] = newstate; 208225944Sjoerg 208340008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 208425944Sjoerg switch (newstate) { 208525944Sjoerg case STATE_INITIAL: 208625944Sjoerg case STATE_STARTING: 208725944Sjoerg case STATE_CLOSED: 208825944Sjoerg case STATE_STOPPED: 208925944Sjoerg case STATE_OPENED: 209025944Sjoerg break; 209125944Sjoerg case STATE_CLOSING: 209225944Sjoerg case STATE_STOPPING: 209325944Sjoerg case STATE_REQ_SENT: 209425944Sjoerg case STATE_ACK_RCVD: 209525944Sjoerg case STATE_ACK_SENT: 209670199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 209742064Sphk sp->ch[cp->protoidx]); 209825944Sjoerg break; 209925944Sjoerg } 210025944Sjoerg} 210170199Sjhay 210270199Sjhay/* 210325944Sjoerg *--------------------------------------------------------------------------* 210425944Sjoerg * * 210525944Sjoerg * The LCP implementation. * 210625944Sjoerg * * 210725944Sjoerg *--------------------------------------------------------------------------* 210825944Sjoerg */ 210925944Sjoergstatic void 211025944Sjoergsppp_lcp_init(struct sppp *sp) 211125944Sjoerg{ 211225944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 211325944Sjoerg sp->lcp.magic = 0; 211425944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 211525944Sjoerg sp->fail_counter[IDX_LCP] = 0; 211678064Sume sp->pp_seq[IDX_LCP] = 0; 211778064Sume sp->pp_rseq[IDX_LCP] = 0; 211825944Sjoerg sp->lcp.protos = 0; 211925944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 212030300Sjoerg 212144145Sphk /* Note that these values are relevant for all control protocols */ 212244145Sphk sp->lcp.timeout = 3 * hz; 212325944Sjoerg sp->lcp.max_terminate = 2; 212425944Sjoerg sp->lcp.max_configure = 10; 212525944Sjoerg sp->lcp.max_failure = 10; 212642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 212730300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 212840008Sjoerg#endif 212925944Sjoerg} 213025944Sjoerg 213125944Sjoergstatic void 213225944Sjoergsppp_lcp_up(struct sppp *sp) 213325944Sjoerg{ 213425944Sjoerg STDDCL; 213525944Sjoerg 213670199Sjhay sp->pp_alivecnt = 0; 213770199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 213870199Sjhay sp->lcp.magic = 0; 213970199Sjhay sp->lcp.protos = 0; 214070199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 214125944Sjoerg /* 214275321Sjoerg * If we are authenticator, negotiate LCP_AUTH 214375321Sjoerg */ 214475321Sjoerg if (sp->hisauth.proto != 0) 214575321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 214675321Sjoerg else 214775321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 214875321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 214975321Sjoerg /* 215030300Sjoerg * If this interface is passive or dial-on-demand, and we are 215130300Sjoerg * still in Initial state, it means we've got an incoming 215230300Sjoerg * call. Activate the interface. 215325944Sjoerg */ 215425944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 215525944Sjoerg if (debug) 215625944Sjoerg log(LOG_DEBUG, 215740008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 215825944Sjoerg ifp->if_flags |= IFF_RUNNING; 215930300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 216030300Sjoerg if (debug) 216169211Sphk log(-1, "(incoming call)\n"); 216230300Sjoerg sp->pp_flags |= PP_CALLIN; 216330300Sjoerg lcp.Open(sp); 216430300Sjoerg } else if (debug) 216569211Sphk log(-1, "\n"); 216688710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 216788710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 216888710Sjoerg ifp->if_flags |= IFF_RUNNING; 216988710Sjoerg lcp.Open(sp); 217025944Sjoerg } 217125944Sjoerg 217225944Sjoerg sppp_up_event(&lcp, sp); 217325944Sjoerg} 217425944Sjoerg 217525944Sjoergstatic void 217625944Sjoergsppp_lcp_down(struct sppp *sp) 217725944Sjoerg{ 217825944Sjoerg STDDCL; 217925944Sjoerg 218025944Sjoerg sppp_down_event(&lcp, sp); 218125944Sjoerg 218225944Sjoerg /* 218325944Sjoerg * If this is neither a dial-on-demand nor a passive 218425944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 218525944Sjoerg * administrator can force a redial by another ``ifconfig 218625944Sjoerg * up''. XXX For leased line operation, should we immediately 218725944Sjoerg * try to reopen the connection here? 218825944Sjoerg */ 218925944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 219025944Sjoerg log(LOG_INFO, 219142066Sphk SPP_FMT "Down event, taking interface down.\n", 219240008Sjoerg SPP_ARGS(ifp)); 219325944Sjoerg if_down(ifp); 219425944Sjoerg } else { 219525944Sjoerg if (debug) 219625944Sjoerg log(LOG_DEBUG, 219740008Sjoerg SPP_FMT "Down event (carrier loss)\n", 219840008Sjoerg SPP_ARGS(ifp)); 219970199Sjhay sp->pp_flags &= ~PP_CALLIN; 220070199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 220170199Sjhay lcp.Close(sp); 220270199Sjhay ifp->if_flags &= ~IFF_RUNNING; 220325944Sjoerg } 220425944Sjoerg} 220525944Sjoerg 220625944Sjoergstatic void 220725944Sjoergsppp_lcp_open(struct sppp *sp) 220825944Sjoerg{ 220925944Sjoerg sppp_open_event(&lcp, sp); 221025944Sjoerg} 221125944Sjoerg 221225944Sjoergstatic void 221325944Sjoergsppp_lcp_close(struct sppp *sp) 221425944Sjoerg{ 221525944Sjoerg sppp_close_event(&lcp, sp); 221625944Sjoerg} 221725944Sjoerg 221825944Sjoergstatic void 221925944Sjoergsppp_lcp_TO(void *cookie) 222025944Sjoerg{ 222125944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 222225944Sjoerg} 222325944Sjoerg 222425944Sjoerg/* 222525944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 222625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 222725944Sjoerg * caused action scn. (The return value is used to make the state 222825944Sjoerg * transition decision in the state automaton.) 222925944Sjoerg */ 223012820Sphkstatic int 223125944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 22324910Swollman{ 223325944Sjoerg STDDCL; 223411189Sjkh u_char *buf, *r, *p; 223525944Sjoerg int origlen, rlen; 223625944Sjoerg u_long nmagic; 223730300Sjoerg u_short authproto; 22384910Swollman 223911189Sjkh len -= 4; 224025944Sjoerg origlen = len; 224111189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 224211189Sjkh if (! buf) 224311189Sjkh return (0); 22444910Swollman 224525706Sjoerg if (debug) 224640008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 224740008Sjoerg SPP_ARGS(ifp)); 224825706Sjoerg 224925944Sjoerg /* pass 1: check for things that need to be rejected */ 225011189Sjkh p = (void*) (h+1); 225111189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 225225944Sjoerg if (debug) 225369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 225411189Sjkh switch (*p) { 225511189Sjkh case LCP_OPT_MAGIC: 225625944Sjoerg /* Magic number. */ 225770199Sjhay if (len >= 6 && p[1] == 6) 225870199Sjhay continue; 225970199Sjhay if (debug) 226070199Sjhay log(-1, "[invalid] "); 226170199Sjhay break; 226225944Sjoerg case LCP_OPT_ASYNC_MAP: 226325944Sjoerg /* Async control character map. */ 226470199Sjhay if (len >= 6 && p[1] == 6) 226525944Sjoerg continue; 226625944Sjoerg if (debug) 226769211Sphk log(-1, "[invalid] "); 226825944Sjoerg break; 226925944Sjoerg case LCP_OPT_MRU: 227025944Sjoerg /* Maximum receive unit. */ 227125944Sjoerg if (len >= 4 && p[1] == 4) 227225944Sjoerg continue; 227325944Sjoerg if (debug) 227469211Sphk log(-1, "[invalid] "); 227525944Sjoerg break; 227630300Sjoerg case LCP_OPT_AUTH_PROTO: 227730300Sjoerg if (len < 4) { 227830300Sjoerg if (debug) 227969211Sphk log(-1, "[invalid] "); 228030300Sjoerg break; 228130300Sjoerg } 228230300Sjoerg authproto = (p[2] << 8) + p[3]; 228330300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 228430300Sjoerg if (debug) 228569211Sphk log(-1, "[invalid chap len] "); 228630300Sjoerg break; 228730300Sjoerg } 228830300Sjoerg if (sp->myauth.proto == 0) { 228930300Sjoerg /* we are not configured to do auth */ 229030300Sjoerg if (debug) 229169211Sphk log(-1, "[not configured] "); 229230300Sjoerg break; 229330300Sjoerg } 229430300Sjoerg /* 229530300Sjoerg * Remote want us to authenticate, remember this, 229630300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 229730300Sjoerg * up. 229830300Sjoerg */ 229930300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 230030300Sjoerg continue; 230125944Sjoerg default: 230225944Sjoerg /* Others not supported. */ 230325944Sjoerg if (debug) 230469211Sphk log(-1, "[rej] "); 230525944Sjoerg break; 230625944Sjoerg } 230725944Sjoerg /* Add the option to rejected list. */ 230825944Sjoerg bcopy (p, r, p[1]); 230925944Sjoerg r += p[1]; 231025944Sjoerg rlen += p[1]; 231125944Sjoerg } 231225944Sjoerg if (rlen) { 231325944Sjoerg if (debug) 231469211Sphk log(-1, " send conf-rej\n"); 231525944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 231625944Sjoerg return 0; 231725944Sjoerg } else if (debug) 231869211Sphk log(-1, "\n"); 231925944Sjoerg 232025944Sjoerg /* 232125944Sjoerg * pass 2: check for option values that are unacceptable and 232225944Sjoerg * thus require to be nak'ed. 232325944Sjoerg */ 232425944Sjoerg if (debug) 232540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 232640008Sjoerg SPP_ARGS(ifp)); 232725944Sjoerg 232825944Sjoerg p = (void*) (h+1); 232925944Sjoerg len = origlen; 233025944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 233125944Sjoerg if (debug) 233269211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 233325944Sjoerg switch (*p) { 233425944Sjoerg case LCP_OPT_MAGIC: 233511189Sjkh /* Magic number -- extract. */ 233625944Sjoerg nmagic = (u_long)p[2] << 24 | 233725944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 233825944Sjoerg if (nmagic != sp->lcp.magic) { 233970199Sjhay sp->pp_loopcnt = 0; 234025706Sjoerg if (debug) 234169211Sphk log(-1, "0x%lx ", nmagic); 234211189Sjkh continue; 234311189Sjkh } 234470199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 234569211Sphk log(-1, "[glitch] "); 234625944Sjoerg ++sp->pp_loopcnt; 234725944Sjoerg /* 234825944Sjoerg * We negate our magic here, and NAK it. If 234925944Sjoerg * we see it later in an NAK packet, we 235025944Sjoerg * suggest a new one. 235125944Sjoerg */ 235225944Sjoerg nmagic = ~sp->lcp.magic; 235325944Sjoerg /* Gonna NAK it. */ 235425944Sjoerg p[2] = nmagic >> 24; 235525944Sjoerg p[3] = nmagic >> 16; 235625944Sjoerg p[4] = nmagic >> 8; 235725944Sjoerg p[5] = nmagic; 235811189Sjkh break; 235925944Sjoerg 236011189Sjkh case LCP_OPT_ASYNC_MAP: 236188506Sjoerg /* 236288506Sjoerg * Async control character map -- just ignore it. 236388506Sjoerg * 236488506Sjoerg * Quote from RFC 1662, chapter 6: 236588506Sjoerg * To enable this functionality, synchronous PPP 236688506Sjoerg * implementations MUST always respond to the 236788506Sjoerg * Async-Control-Character-Map Configuration 236888506Sjoerg * Option with the LCP Configure-Ack. However, 236988506Sjoerg * acceptance of the Configuration Option does 237088506Sjoerg * not imply that the synchronous implementation 237188506Sjoerg * will do any ACCM mapping. Instead, all such 237288506Sjoerg * octet mapping will be performed by the 237388506Sjoerg * asynchronous-to-synchronous converter. 237488506Sjoerg */ 237588506Sjoerg continue; 237625944Sjoerg 237711189Sjkh case LCP_OPT_MRU: 237825944Sjoerg /* 237925944Sjoerg * Maximum receive unit. Always agreeable, 238025944Sjoerg * but ignored by now. 238125944Sjoerg */ 238225944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 238325706Sjoerg if (debug) 238469211Sphk log(-1, "%lu ", sp->lcp.their_mru); 238511189Sjkh continue; 238630300Sjoerg 238730300Sjoerg case LCP_OPT_AUTH_PROTO: 238830300Sjoerg authproto = (p[2] << 8) + p[3]; 238930300Sjoerg if (sp->myauth.proto != authproto) { 239030300Sjoerg /* not agreed, nak */ 239130300Sjoerg if (debug) 239269211Sphk log(-1, "[mine %s != his %s] ", 239330300Sjoerg sppp_proto_name(sp->hisauth.proto), 239430300Sjoerg sppp_proto_name(authproto)); 239530300Sjoerg p[2] = sp->myauth.proto >> 8; 239630300Sjoerg p[3] = sp->myauth.proto; 239730300Sjoerg break; 239830300Sjoerg } 239930300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 240030300Sjoerg if (debug) 240169211Sphk log(-1, "[chap not MD5] "); 240239981Sjoerg p[4] = CHAP_MD5; 240330300Sjoerg break; 240430300Sjoerg } 240530300Sjoerg continue; 240611189Sjkh } 240725944Sjoerg /* Add the option to nak'ed list. */ 240825706Sjoerg bcopy (p, r, p[1]); 240925706Sjoerg r += p[1]; 241011189Sjkh rlen += p[1]; 241112436Speter } 241225706Sjoerg if (rlen) { 241370199Sjhay /* 241470199Sjhay * Local and remote magics equal -- loopback? 241570199Sjhay */ 241670199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 241770199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 241870199Sjhay printf (SPP_FMT "loopback\n", 241970199Sjhay SPP_ARGS(ifp)); 242070199Sjhay if (ifp->if_flags & IFF_UP) { 242170199Sjhay if_down(ifp); 242270199Sjhay sppp_qflush(&sp->pp_cpq); 242370199Sjhay /* XXX ? */ 242470199Sjhay lcp.Down(sp); 242570199Sjhay lcp.Up(sp); 242670199Sjhay } 242770199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 242828036Sjoerg if (debug) 242969211Sphk log(-1, " max_failure (%d) exceeded, " 243028036Sjoerg "send conf-rej\n", 243128036Sjoerg sp->lcp.max_failure); 243228036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 243328036Sjoerg } else { 243428036Sjoerg if (debug) 243569211Sphk log(-1, " send conf-nak\n"); 243628036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 243728036Sjoerg } 243825944Sjoerg } else { 243925944Sjoerg if (debug) 244069211Sphk log(-1, " send conf-ack\n"); 244128036Sjoerg sp->fail_counter[IDX_LCP] = 0; 244225944Sjoerg sp->pp_loopcnt = 0; 244325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 244425944Sjoerg h->ident, origlen, h+1); 244525944Sjoerg } 244625944Sjoerg 244711189Sjkh free (buf, M_TEMP); 244811189Sjkh return (rlen == 0); 24494910Swollman} 24504910Swollman 245125944Sjoerg/* 245225944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 245325944Sjoerg * negotiation. 245425944Sjoerg */ 245512820Sphkstatic void 245625944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 24574910Swollman{ 245825944Sjoerg STDDCL; 245925944Sjoerg u_char *buf, *p; 24604910Swollman 246125944Sjoerg len -= 4; 246225944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 246325944Sjoerg if (!buf) 24644910Swollman return; 246525944Sjoerg 246625944Sjoerg if (debug) 246740008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 246840008Sjoerg SPP_ARGS(ifp)); 246925944Sjoerg 247025944Sjoerg p = (void*) (h+1); 247125944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 247225944Sjoerg if (debug) 247369211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 247425944Sjoerg switch (*p) { 247525944Sjoerg case LCP_OPT_MAGIC: 247625944Sjoerg /* Magic number -- can't use it, use 0 */ 247725944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 247825944Sjoerg sp->lcp.magic = 0; 247925944Sjoerg break; 248025944Sjoerg case LCP_OPT_MRU: 248125944Sjoerg /* 248225944Sjoerg * Should not be rejected anyway, since we only 248325944Sjoerg * negotiate a MRU if explicitly requested by 248425944Sjoerg * peer. 248525944Sjoerg */ 248625944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 248725944Sjoerg break; 248830300Sjoerg case LCP_OPT_AUTH_PROTO: 248930300Sjoerg /* 249030300Sjoerg * Peer doesn't want to authenticate himself, 249130300Sjoerg * deny unless this is a dialout call, and 249230300Sjoerg * AUTHFLAG_NOCALLOUT is set. 249330300Sjoerg */ 249430300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 249530300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 249630300Sjoerg if (debug) 249769211Sphk log(-1, "[don't insist on auth " 249830300Sjoerg "for callout]"); 249930300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 250030300Sjoerg break; 250130300Sjoerg } 250230300Sjoerg if (debug) 250369211Sphk log(-1, "[access denied]\n"); 250430300Sjoerg lcp.Close(sp); 250530300Sjoerg break; 250625944Sjoerg } 25074910Swollman } 250825944Sjoerg if (debug) 250969211Sphk log(-1, "\n"); 251025944Sjoerg free (buf, M_TEMP); 251125944Sjoerg return; 251225944Sjoerg} 251325944Sjoerg 251425944Sjoerg/* 251525944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 251625944Sjoerg * negotiation. 251725944Sjoerg */ 251825944Sjoergstatic void 251925944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 252025944Sjoerg{ 252125944Sjoerg STDDCL; 252225944Sjoerg u_char *buf, *p; 252325944Sjoerg u_long magic; 252425944Sjoerg 252525944Sjoerg len -= 4; 252625944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 252725944Sjoerg if (!buf) 252825944Sjoerg return; 252925944Sjoerg 253025944Sjoerg if (debug) 253140008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 253240008Sjoerg SPP_ARGS(ifp)); 253325944Sjoerg 253425944Sjoerg p = (void*) (h+1); 253525944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 253625706Sjoerg if (debug) 253769211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 253825944Sjoerg switch (*p) { 253925944Sjoerg case LCP_OPT_MAGIC: 254025944Sjoerg /* Magic number -- renegotiate */ 254125944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 254225944Sjoerg len >= 6 && p[1] == 6) { 254325944Sjoerg magic = (u_long)p[2] << 24 | 254425944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 254525944Sjoerg /* 254625944Sjoerg * If the remote magic is our negated one, 254725944Sjoerg * this looks like a loopback problem. 254825944Sjoerg * Suggest a new magic to make sure. 254925944Sjoerg */ 255025944Sjoerg if (magic == ~sp->lcp.magic) { 255125944Sjoerg if (debug) 255269211Sphk log(-1, "magic glitch "); 255342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 255435064Sphk sp->lcp.magic = random(); 255540008Sjoerg#else 255640008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 255740008Sjoerg#endif 255825944Sjoerg } else { 255925944Sjoerg sp->lcp.magic = magic; 256025944Sjoerg if (debug) 256169211Sphk log(-1, "%lu ", magic); 256225944Sjoerg } 256325944Sjoerg } 256425944Sjoerg break; 256525944Sjoerg case LCP_OPT_MRU: 256625944Sjoerg /* 256725944Sjoerg * Peer wants to advise us to negotiate an MRU. 256825944Sjoerg * Agree on it if it's reasonable, or use 256925944Sjoerg * default otherwise. 257025944Sjoerg */ 257125944Sjoerg if (len >= 4 && p[1] == 4) { 257225944Sjoerg u_int mru = p[2] * 256 + p[3]; 257325944Sjoerg if (debug) 257469211Sphk log(-1, "%d ", mru); 257525944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 257625944Sjoerg mru = PP_MTU; 257725944Sjoerg sp->lcp.mru = mru; 257825944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 257925944Sjoerg } 258025944Sjoerg break; 258130300Sjoerg case LCP_OPT_AUTH_PROTO: 258230300Sjoerg /* 258330300Sjoerg * Peer doesn't like our authentication method, 258430300Sjoerg * deny. 258530300Sjoerg */ 258630300Sjoerg if (debug) 258769211Sphk log(-1, "[access denied]\n"); 258830300Sjoerg lcp.Close(sp); 258930300Sjoerg break; 25904910Swollman } 259125944Sjoerg } 259225944Sjoerg if (debug) 259369211Sphk log(-1, "\n"); 259425944Sjoerg free (buf, M_TEMP); 259525944Sjoerg return; 259625944Sjoerg} 259711189Sjkh 259825944Sjoergstatic void 259925944Sjoergsppp_lcp_tlu(struct sppp *sp) 260025944Sjoerg{ 260142066Sphk STDDCL; 260225944Sjoerg int i; 260325944Sjoerg u_long mask; 260425944Sjoerg 260525944Sjoerg /* XXX ? */ 260625944Sjoerg if (! (ifp->if_flags & IFF_UP) && 260725944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 260825944Sjoerg /* Coming out of loopback mode. */ 260925944Sjoerg if_up(ifp); 261040008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 261125944Sjoerg } 261225944Sjoerg 261325944Sjoerg for (i = 0; i < IDX_COUNT; i++) 261425944Sjoerg if ((cps[i])->flags & CP_QUAL) 261525944Sjoerg (cps[i])->Open(sp); 261625944Sjoerg 261730300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 261830300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 261925944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 262025944Sjoerg else 262125944Sjoerg sp->pp_phase = PHASE_NETWORK; 262225944Sjoerg 262342066Sphk if (debug) 262442066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 262542066Sphk sppp_phase_name(sp->pp_phase)); 262625944Sjoerg 262730300Sjoerg /* 262830300Sjoerg * Open all authentication protocols. This is even required 262930300Sjoerg * if we already proceeded to network phase, since it might be 263030300Sjoerg * that remote wants us to authenticate, so we might have to 263130300Sjoerg * send a PAP request. Undesired authentication protocols 263230300Sjoerg * don't do anything when they get an Open event. 263330300Sjoerg */ 263430300Sjoerg for (i = 0; i < IDX_COUNT; i++) 263530300Sjoerg if ((cps[i])->flags & CP_AUTH) 263630300Sjoerg (cps[i])->Open(sp); 263730300Sjoerg 263830300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 263925944Sjoerg /* Notify all NCPs. */ 264025944Sjoerg for (i = 0; i < IDX_COUNT; i++) 264188723Sjoerg if (((cps[i])->flags & CP_NCP) && 264288723Sjoerg /* 264388723Sjoerg * XXX 264488723Sjoerg * Hack to administratively disable IPv6 if 264588723Sjoerg * not desired. Perhaps we should have another 264688723Sjoerg * flag for this, but right now, we can make 264788723Sjoerg * all struct cp's read/only. 264888723Sjoerg */ 264988723Sjoerg (cps[i] != &ipv6cp || 265088723Sjoerg (sp->confflags & CONF_ENABLE_IPV6))) 265125944Sjoerg (cps[i])->Open(sp); 265225944Sjoerg } 265325944Sjoerg 265425944Sjoerg /* Send Up events to all started protos. */ 265525944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 265688706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 265725944Sjoerg (cps[i])->Up(sp); 265825944Sjoerg 265942104Sphk /* notify low-level driver of state change */ 266042104Sphk if (sp->pp_chg) 266142104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 266242104Sphk 266325944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 266425944Sjoerg /* if no NCP is starting, close down */ 266530300Sjoerg sppp_lcp_check_and_close(sp); 266625944Sjoerg} 266725944Sjoerg 266825944Sjoergstatic void 266925944Sjoergsppp_lcp_tld(struct sppp *sp) 267025944Sjoerg{ 267142066Sphk STDDCL; 267225944Sjoerg int i; 267325944Sjoerg u_long mask; 267425944Sjoerg 267525944Sjoerg sp->pp_phase = PHASE_TERMINATE; 267625944Sjoerg 267742066Sphk if (debug) 267842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 267942066Sphk sppp_phase_name(sp->pp_phase)); 268025944Sjoerg 268125944Sjoerg /* 268225944Sjoerg * Take upper layers down. We send the Down event first and 268325944Sjoerg * the Close second to prevent the upper layers from sending 268425944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 268525944Sjoerg * describes it. 268625944Sjoerg */ 268725944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 268888706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 268925944Sjoerg (cps[i])->Down(sp); 269025944Sjoerg (cps[i])->Close(sp); 269125944Sjoerg } 269225944Sjoerg} 269325944Sjoerg 269425944Sjoergstatic void 269525944Sjoergsppp_lcp_tls(struct sppp *sp) 269625944Sjoerg{ 269742066Sphk STDDCL; 269825944Sjoerg 269925944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 270025944Sjoerg 270142066Sphk if (debug) 270242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 270342066Sphk sppp_phase_name(sp->pp_phase)); 270425944Sjoerg 270525944Sjoerg /* Notify lower layer if desired. */ 270625944Sjoerg if (sp->pp_tls) 270725944Sjoerg (sp->pp_tls)(sp); 270841881Sphk else 270941881Sphk (sp->pp_up)(sp); 271025944Sjoerg} 271125944Sjoerg 271225944Sjoergstatic void 271325944Sjoergsppp_lcp_tlf(struct sppp *sp) 271425944Sjoerg{ 271542066Sphk STDDCL; 271625944Sjoerg 271725944Sjoerg sp->pp_phase = PHASE_DEAD; 271842066Sphk if (debug) 271942066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 272042066Sphk sppp_phase_name(sp->pp_phase)); 272125944Sjoerg 272225944Sjoerg /* Notify lower layer if desired. */ 272325944Sjoerg if (sp->pp_tlf) 272425944Sjoerg (sp->pp_tlf)(sp); 272541881Sphk else 272641881Sphk (sp->pp_down)(sp); 272725944Sjoerg} 272825944Sjoerg 272925944Sjoergstatic void 273025944Sjoergsppp_lcp_scr(struct sppp *sp) 273125944Sjoerg{ 273230300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 273325944Sjoerg int i = 0; 273430300Sjoerg u_short authproto; 273525944Sjoerg 273625944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 273725944Sjoerg if (! sp->lcp.magic) 273842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 273935064Sphk sp->lcp.magic = random(); 274040008Sjoerg#else 274140008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 274240008Sjoerg#endif 274325944Sjoerg opt[i++] = LCP_OPT_MAGIC; 274425944Sjoerg opt[i++] = 6; 274525944Sjoerg opt[i++] = sp->lcp.magic >> 24; 274625944Sjoerg opt[i++] = sp->lcp.magic >> 16; 274725944Sjoerg opt[i++] = sp->lcp.magic >> 8; 274825944Sjoerg opt[i++] = sp->lcp.magic; 274925944Sjoerg } 275025944Sjoerg 275125944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 275225944Sjoerg opt[i++] = LCP_OPT_MRU; 275325944Sjoerg opt[i++] = 4; 275425944Sjoerg opt[i++] = sp->lcp.mru >> 8; 275525944Sjoerg opt[i++] = sp->lcp.mru; 275625944Sjoerg } 275725944Sjoerg 275830300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 275930300Sjoerg authproto = sp->hisauth.proto; 276030300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 276130300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 276230300Sjoerg opt[i++] = authproto >> 8; 276330300Sjoerg opt[i++] = authproto; 276430300Sjoerg if (authproto == PPP_CHAP) 276530300Sjoerg opt[i++] = CHAP_MD5; 276630300Sjoerg } 276730300Sjoerg 276878064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 276925944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 277025944Sjoerg} 277125944Sjoerg 277225944Sjoerg/* 277330300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 277430300Sjoerg */ 277530300Sjoergstatic int 277630300Sjoergsppp_ncp_check(struct sppp *sp) 277730300Sjoerg{ 277830300Sjoerg int i, mask; 277930300Sjoerg 278030300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 278188706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 278230300Sjoerg return 1; 278330300Sjoerg return 0; 278430300Sjoerg} 278530300Sjoerg 278630300Sjoerg/* 278725944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 278825944Sjoerg * Called by the NCPs during their tlf action handling. 278925944Sjoerg */ 279025944Sjoergstatic void 279130300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 279225944Sjoerg{ 279325944Sjoerg 279430300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 279530300Sjoerg /* don't bother, we are already going down */ 279630300Sjoerg return; 279730300Sjoerg 279830300Sjoerg if (sppp_ncp_check(sp)) 279930300Sjoerg return; 280030300Sjoerg 280125944Sjoerg lcp.Close(sp); 280225944Sjoerg} 280370199Sjhay 280470199Sjhay/* 280525944Sjoerg *--------------------------------------------------------------------------* 280625944Sjoerg * * 280725944Sjoerg * The IPCP implementation. * 280825944Sjoerg * * 280925944Sjoerg *--------------------------------------------------------------------------* 281025944Sjoerg */ 281125944Sjoerg 281225944Sjoergstatic void 281325944Sjoergsppp_ipcp_init(struct sppp *sp) 281425944Sjoerg{ 281525944Sjoerg sp->ipcp.opts = 0; 281625944Sjoerg sp->ipcp.flags = 0; 281725944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 281825944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 281978064Sume sp->pp_seq[IDX_IPCP] = 0; 282078064Sume sp->pp_rseq[IDX_IPCP] = 0; 282142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 282229681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 282340008Sjoerg#endif 282425944Sjoerg} 282525944Sjoerg 282625944Sjoergstatic void 282725944Sjoergsppp_ipcp_up(struct sppp *sp) 282825944Sjoerg{ 282925944Sjoerg sppp_up_event(&ipcp, sp); 283025944Sjoerg} 283125944Sjoerg 283225944Sjoergstatic void 283325944Sjoergsppp_ipcp_down(struct sppp *sp) 283425944Sjoerg{ 283525944Sjoerg sppp_down_event(&ipcp, sp); 283625944Sjoerg} 283725944Sjoerg 283825944Sjoergstatic void 283925944Sjoergsppp_ipcp_open(struct sppp *sp) 284025944Sjoerg{ 284125944Sjoerg STDDCL; 284225944Sjoerg u_long myaddr, hisaddr; 284325944Sjoerg 284488534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 284588534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 284688700Sjoerg sp->ipcp.opts = 0; 284742104Sphk 284830300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 284925944Sjoerg /* 285025944Sjoerg * If we don't have his address, this probably means our 285125944Sjoerg * interface doesn't want to talk IP at all. (This could 285225944Sjoerg * be the case if somebody wants to speak only IPX, for 285325944Sjoerg * example.) Don't open IPCP in this case. 285425944Sjoerg */ 285525944Sjoerg if (hisaddr == 0L) { 285625944Sjoerg /* XXX this message should go away */ 285725944Sjoerg if (debug) 285840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 285940008Sjoerg SPP_ARGS(ifp)); 286025944Sjoerg return; 286125944Sjoerg } 286225944Sjoerg if (myaddr == 0L) { 286325944Sjoerg /* 286425944Sjoerg * I don't have an assigned address, so i need to 286525944Sjoerg * negotiate my address. 286625944Sjoerg */ 286725944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 286825944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 286942104Sphk } else 287042104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 287188723Sjoerg if (sp->confflags & CONF_ENABLE_VJ) { 287288534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 287388534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 287488534Sjoerg sp->ipcp.compress_cid = 1; 287588534Sjoerg } 287625944Sjoerg sppp_open_event(&ipcp, sp); 287725944Sjoerg} 287825944Sjoerg 287925944Sjoergstatic void 288025944Sjoergsppp_ipcp_close(struct sppp *sp) 288125944Sjoerg{ 288225944Sjoerg sppp_close_event(&ipcp, sp); 288325944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 288425944Sjoerg /* 288525944Sjoerg * My address was dynamic, clear it again. 288625944Sjoerg */ 288725944Sjoerg sppp_set_ip_addr(sp, 0L); 288825944Sjoerg} 288925944Sjoerg 289025944Sjoergstatic void 289125944Sjoergsppp_ipcp_TO(void *cookie) 289225944Sjoerg{ 289325944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 289425944Sjoerg} 289525944Sjoerg 289625944Sjoerg/* 289725944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 289825944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 289925944Sjoerg * caused action scn. (The return value is used to make the state 290025944Sjoerg * transition decision in the state automaton.) 290125944Sjoerg */ 290225944Sjoergstatic int 290325944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 290425944Sjoerg{ 290525944Sjoerg u_char *buf, *r, *p; 290625944Sjoerg struct ifnet *ifp = &sp->pp_if; 290725944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 290825944Sjoerg u_long hisaddr, desiredaddr; 290942104Sphk int gotmyaddr = 0; 291088534Sjoerg int desiredcomp; 291125944Sjoerg 291225944Sjoerg len -= 4; 291325944Sjoerg origlen = len; 291425944Sjoerg /* 291525944Sjoerg * Make sure to allocate a buf that can at least hold a 291625944Sjoerg * conf-nak with an `address' option. We might need it below. 291725944Sjoerg */ 291825944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 291925944Sjoerg if (! buf) 292025944Sjoerg return (0); 292125944Sjoerg 292225944Sjoerg /* pass 1: see if we can recognize them */ 292325944Sjoerg if (debug) 292440008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 292540008Sjoerg SPP_ARGS(ifp)); 292625944Sjoerg p = (void*) (h+1); 292725944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 292825944Sjoerg if (debug) 292969211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 293025944Sjoerg switch (*p) { 293188534Sjoerg case IPCP_OPT_COMPRESSION: 293288723Sjoerg if (!(sp->confflags & CONF_ENABLE_VJ)) { 293388534Sjoerg /* VJ compression administratively disabled */ 293488534Sjoerg if (debug) 293588534Sjoerg log(-1, "[locally disabled] "); 293688534Sjoerg break; 293788534Sjoerg } 293888534Sjoerg /* 293988534Sjoerg * In theory, we should only conf-rej an 294088534Sjoerg * option that is shorter than RFC 1618 294188534Sjoerg * requires (i.e. < 4), and should conf-nak 294288534Sjoerg * anything else that is not VJ. However, 294388534Sjoerg * since our algorithm always uses the 294488534Sjoerg * original option to NAK it with new values, 294588534Sjoerg * things would become more complicated. In 294688534Sjoerg * pratice, the only commonly implemented IP 294788534Sjoerg * compression option is VJ anyway, so the 294888534Sjoerg * difference is negligible. 294988534Sjoerg */ 295088534Sjoerg if (len >= 6 && p[1] == 6) { 295188534Sjoerg /* 295288534Sjoerg * correctly formed compression option 295388534Sjoerg * that could be VJ compression 295488534Sjoerg */ 295588534Sjoerg continue; 295688534Sjoerg } 295788534Sjoerg if (debug) 295888534Sjoerg log(-1, 295988534Sjoerg "optlen %d [invalid/unsupported] ", 296088534Sjoerg p[1]); 296188534Sjoerg break; 296225944Sjoerg case IPCP_OPT_ADDRESS: 296325944Sjoerg if (len >= 6 && p[1] == 6) { 296425944Sjoerg /* correctly formed address option */ 296525944Sjoerg continue; 296625944Sjoerg } 296725706Sjoerg if (debug) 296869211Sphk log(-1, "[invalid] "); 296911189Sjkh break; 297025944Sjoerg default: 297125944Sjoerg /* Others not supported. */ 297225944Sjoerg if (debug) 297369211Sphk log(-1, "[rej] "); 29744910Swollman break; 29754910Swollman } 297625944Sjoerg /* Add the option to rejected list. */ 297725944Sjoerg bcopy (p, r, p[1]); 297825944Sjoerg r += p[1]; 297925944Sjoerg rlen += p[1]; 298025944Sjoerg } 298125944Sjoerg if (rlen) { 298225944Sjoerg if (debug) 298369211Sphk log(-1, " send conf-rej\n"); 298425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 298525944Sjoerg return 0; 298625944Sjoerg } else if (debug) 298769211Sphk log(-1, "\n"); 298825944Sjoerg 298925944Sjoerg /* pass 2: parse option values */ 299030300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 299125944Sjoerg if (debug) 299240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 299340008Sjoerg SPP_ARGS(ifp)); 299425944Sjoerg p = (void*) (h+1); 299525944Sjoerg len = origlen; 299625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 299725944Sjoerg if (debug) 299869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 299925944Sjoerg switch (*p) { 300088534Sjoerg case IPCP_OPT_COMPRESSION: 300188534Sjoerg desiredcomp = p[2] << 8 | p[3]; 300288534Sjoerg /* We only support VJ */ 300388534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 300488534Sjoerg if (debug) 300588534Sjoerg log(-1, "VJ [ack] "); 300688534Sjoerg sp->ipcp.flags |= IPCP_VJ; 300788599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 300888534Sjoerg sp->ipcp.max_state = p[4]; 300988534Sjoerg sp->ipcp.compress_cid = p[5]; 301088534Sjoerg continue; 301188534Sjoerg } 301288534Sjoerg if (debug) 301388534Sjoerg log(-1, 301488534Sjoerg "compproto %#04x [not supported] ", 301588534Sjoerg desiredcomp); 301688534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 301788534Sjoerg p[3] = IPCP_COMP_VJ; 301888534Sjoerg p[4] = sp->ipcp.max_state; 301988534Sjoerg p[5] = sp->ipcp.compress_cid; 302088534Sjoerg break; 302125944Sjoerg case IPCP_OPT_ADDRESS: 302242104Sphk /* This is the address he wants in his end */ 302325944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 302425944Sjoerg p[4] << 8 | p[5]; 302533928Sphk if (desiredaddr == hisaddr || 302688702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 302725944Sjoerg /* 302825944Sjoerg * Peer's address is same as our value, 302988702Sjoerg * or we have set it to 0.0.0.* to 303033928Sphk * indicate that we do not really care, 303125944Sjoerg * this is agreeable. Gonna conf-ack 303225944Sjoerg * it. 303325944Sjoerg */ 303425944Sjoerg if (debug) 303569211Sphk log(-1, "%s [ack] ", 303642104Sphk sppp_dotted_quad(hisaddr)); 303725944Sjoerg /* record that we've seen it already */ 303825944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 303925944Sjoerg continue; 304025944Sjoerg } 304125944Sjoerg /* 304225944Sjoerg * The address wasn't agreeable. This is either 304325944Sjoerg * he sent us 0.0.0.0, asking to assign him an 304425944Sjoerg * address, or he send us another address not 304525944Sjoerg * matching our value. Either case, we gonna 304625944Sjoerg * conf-nak it with our value. 304742104Sphk * XXX: we should "rej" if hisaddr == 0 304825944Sjoerg */ 304925944Sjoerg if (debug) { 305025944Sjoerg if (desiredaddr == 0) 305169211Sphk log(-1, "[addr requested] "); 305225944Sjoerg else 305369211Sphk log(-1, "%s [not agreed] ", 305442104Sphk sppp_dotted_quad(desiredaddr)); 305525944Sjoerg 305625944Sjoerg } 305744235Sphk p[2] = hisaddr >> 24; 305844235Sphk p[3] = hisaddr >> 16; 305944235Sphk p[4] = hisaddr >> 8; 306044235Sphk p[5] = hisaddr; 306111189Sjkh break; 306225706Sjoerg } 306325944Sjoerg /* Add the option to nak'ed list. */ 306425944Sjoerg bcopy (p, r, p[1]); 306525944Sjoerg r += p[1]; 306625944Sjoerg rlen += p[1]; 306725944Sjoerg } 306825944Sjoerg 306925944Sjoerg /* 307025944Sjoerg * If we are about to conf-ack the request, but haven't seen 307125944Sjoerg * his address so far, gonna conf-nak it instead, with the 307225944Sjoerg * `address' option present and our idea of his address being 307325944Sjoerg * filled in there, to request negotiation of both addresses. 307425944Sjoerg * 307525944Sjoerg * XXX This can result in an endless req - nak loop if peer 307625944Sjoerg * doesn't want to send us his address. Q: What should we do 307725944Sjoerg * about it? XXX A: implement the max-failure counter. 307825944Sjoerg */ 307942104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 308025944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 308125944Sjoerg buf[1] = 6; 308225944Sjoerg buf[2] = hisaddr >> 24; 308325944Sjoerg buf[3] = hisaddr >> 16; 308425944Sjoerg buf[4] = hisaddr >> 8; 308525944Sjoerg buf[5] = hisaddr; 308625944Sjoerg rlen = 6; 308725706Sjoerg if (debug) 308869211Sphk log(-1, "still need hisaddr "); 308925944Sjoerg } 309025944Sjoerg 309125944Sjoerg if (rlen) { 309225706Sjoerg if (debug) 309369211Sphk log(-1, " send conf-nak\n"); 309425944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 309525944Sjoerg } else { 309625706Sjoerg if (debug) 309769211Sphk log(-1, " send conf-ack\n"); 309825944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 309925944Sjoerg h->ident, origlen, h+1); 310025944Sjoerg } 310125944Sjoerg 310225944Sjoerg free (buf, M_TEMP); 310325944Sjoerg return (rlen == 0); 310425944Sjoerg} 310525944Sjoerg 310625944Sjoerg/* 310725944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 310825944Sjoerg * negotiation. 310925944Sjoerg */ 311025944Sjoergstatic void 311125944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 311225944Sjoerg{ 311325944Sjoerg u_char *buf, *p; 311425944Sjoerg struct ifnet *ifp = &sp->pp_if; 311525944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 311625944Sjoerg 311725944Sjoerg len -= 4; 311825944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 311925944Sjoerg if (!buf) 312025944Sjoerg return; 312125944Sjoerg 312225944Sjoerg if (debug) 312340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 312440008Sjoerg SPP_ARGS(ifp)); 312525944Sjoerg 312625944Sjoerg p = (void*) (h+1); 312725944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 312825706Sjoerg if (debug) 312969211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 313025944Sjoerg switch (*p) { 313188534Sjoerg case IPCP_OPT_COMPRESSION: 313288534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 313388534Sjoerg break; 313425944Sjoerg case IPCP_OPT_ADDRESS: 313525944Sjoerg /* 313625944Sjoerg * Peer doesn't grok address option. This is 313725944Sjoerg * bad. XXX Should we better give up here? 313842104Sphk * XXX We could try old "addresses" option... 313925944Sjoerg */ 314025944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 314125944Sjoerg break; 314225944Sjoerg } 31434910Swollman } 314425944Sjoerg if (debug) 314569211Sphk log(-1, "\n"); 314625944Sjoerg free (buf, M_TEMP); 314725944Sjoerg return; 31484910Swollman} 31494910Swollman 315025944Sjoerg/* 315125944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 315225944Sjoerg * negotiation. 315325944Sjoerg */ 315412820Sphkstatic void 315525944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 31564910Swollman{ 315725944Sjoerg u_char *buf, *p; 315825944Sjoerg struct ifnet *ifp = &sp->pp_if; 315925944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 316088534Sjoerg int desiredcomp; 316125944Sjoerg u_long wantaddr; 31624910Swollman 316325944Sjoerg len -= 4; 316425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 316525944Sjoerg if (!buf) 316625944Sjoerg return; 316725944Sjoerg 316825944Sjoerg if (debug) 316940008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 317040008Sjoerg SPP_ARGS(ifp)); 317125944Sjoerg 317225944Sjoerg p = (void*) (h+1); 317325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 317425944Sjoerg if (debug) 317569211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 317625944Sjoerg switch (*p) { 317788534Sjoerg case IPCP_OPT_COMPRESSION: 317888534Sjoerg if (len >= 6 && p[1] == 6) { 317988534Sjoerg desiredcomp = p[2] << 8 | p[3]; 318088534Sjoerg if (debug) 318188534Sjoerg log(-1, "[wantcomp %#04x] ", 318288534Sjoerg desiredcomp); 318388534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 318488599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 318588534Sjoerg sp->ipcp.max_state = p[4]; 318688534Sjoerg sp->ipcp.compress_cid = p[5]; 318788534Sjoerg if (debug) 318888534Sjoerg log(-1, "[agree] "); 318988534Sjoerg } else 319088534Sjoerg sp->ipcp.opts &= 319188534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 319288534Sjoerg } 319388534Sjoerg break; 319425944Sjoerg case IPCP_OPT_ADDRESS: 319525944Sjoerg /* 319625944Sjoerg * Peer doesn't like our local IP address. See 319725944Sjoerg * if we can do something for him. We'll drop 319825944Sjoerg * him our address then. 319925944Sjoerg */ 320025944Sjoerg if (len >= 6 && p[1] == 6) { 320125944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 320225944Sjoerg p[4] << 8 | p[5]; 320325944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 320425944Sjoerg if (debug) 320569211Sphk log(-1, "[wantaddr %s] ", 320630300Sjoerg sppp_dotted_quad(wantaddr)); 320725944Sjoerg /* 320825944Sjoerg * When doing dynamic address assignment, 320925944Sjoerg * we accept his offer. Otherwise, we 321025944Sjoerg * ignore it and thus continue to negotiate 321125944Sjoerg * our already existing value. 321242104Sphk * XXX: Bogus, if he said no once, he'll 321342104Sphk * just say no again, might as well die. 321425944Sjoerg */ 321525944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 321625944Sjoerg sppp_set_ip_addr(sp, wantaddr); 321725944Sjoerg if (debug) 321869211Sphk log(-1, "[agree] "); 321942104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 322025944Sjoerg } 322125944Sjoerg } 322225944Sjoerg break; 322325944Sjoerg } 322425944Sjoerg } 322525944Sjoerg if (debug) 322669211Sphk log(-1, "\n"); 322725944Sjoerg free (buf, M_TEMP); 322825944Sjoerg return; 32294910Swollman} 32304910Swollman 323112820Sphkstatic void 323225944Sjoergsppp_ipcp_tlu(struct sppp *sp) 32334910Swollman{ 323442104Sphk /* we are up - notify isdn daemon */ 323542104Sphk if (sp->pp_con) 323642104Sphk sp->pp_con(sp); 32374910Swollman} 32384910Swollman 323925944Sjoergstatic void 324025944Sjoergsppp_ipcp_tld(struct sppp *sp) 324125944Sjoerg{ 324225944Sjoerg} 324325944Sjoerg 324425944Sjoergstatic void 324525944Sjoergsppp_ipcp_tls(struct sppp *sp) 324625944Sjoerg{ 324725944Sjoerg /* indicate to LCP that it must stay alive */ 324825944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 324925944Sjoerg} 325025944Sjoerg 325125944Sjoergstatic void 325225944Sjoergsppp_ipcp_tlf(struct sppp *sp) 325325944Sjoerg{ 325425944Sjoerg /* we no longer need LCP */ 325525944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 325630300Sjoerg sppp_lcp_check_and_close(sp); 325725944Sjoerg} 325825944Sjoerg 325925944Sjoergstatic void 326025944Sjoergsppp_ipcp_scr(struct sppp *sp) 326125944Sjoerg{ 326225944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 326325944Sjoerg u_long ouraddr; 326425944Sjoerg int i = 0; 326525944Sjoerg 326688534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 326788534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 326888534Sjoerg opt[i++] = 6; 326988534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 327088534Sjoerg opt[i++] = IPCP_COMP_VJ; 327188534Sjoerg opt[i++] = sp->ipcp.max_state; 327288534Sjoerg opt[i++] = sp->ipcp.compress_cid; 327388534Sjoerg } 327425944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 327530300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 327625944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 327725944Sjoerg opt[i++] = 6; 327825944Sjoerg opt[i++] = ouraddr >> 24; 327925944Sjoerg opt[i++] = ouraddr >> 16; 328025944Sjoerg opt[i++] = ouraddr >> 8; 328125944Sjoerg opt[i++] = ouraddr; 328225944Sjoerg } 328325944Sjoerg 328478064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 328525944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 328625944Sjoerg} 328725944Sjoerg 328870199Sjhay/* 328930300Sjoerg *--------------------------------------------------------------------------* 329030300Sjoerg * * 329178064Sume * The IPv6CP implementation. * 329278064Sume * * 329378064Sume *--------------------------------------------------------------------------* 329478064Sume */ 329578064Sume 329678064Sume#ifdef INET6 329778064Sumestatic void 329878064Sumesppp_ipv6cp_init(struct sppp *sp) 329978064Sume{ 330078064Sume sp->ipv6cp.opts = 0; 330178064Sume sp->ipv6cp.flags = 0; 330278064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 330378064Sume sp->fail_counter[IDX_IPV6CP] = 0; 330478064Sume sp->pp_seq[IDX_IPV6CP] = 0; 330578064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 330678064Sume#if defined(__NetBSD__) 330778064Sume callout_init(&sp->ch[IDX_IPV6CP]); 330878064Sume#endif 330978064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 331078064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 331178064Sume#endif 331278064Sume} 331378064Sume 331478064Sumestatic void 331578064Sumesppp_ipv6cp_up(struct sppp *sp) 331678064Sume{ 331778064Sume sppp_up_event(&ipv6cp, sp); 331878064Sume} 331978064Sume 332078064Sumestatic void 332178064Sumesppp_ipv6cp_down(struct sppp *sp) 332278064Sume{ 332378064Sume sppp_down_event(&ipv6cp, sp); 332478064Sume} 332578064Sume 332678064Sumestatic void 332778064Sumesppp_ipv6cp_open(struct sppp *sp) 332878064Sume{ 332978064Sume STDDCL; 333078064Sume struct in6_addr myaddr, hisaddr; 333178064Sume 333278064Sume#ifdef IPV6CP_MYIFID_DYN 333378064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 333478064Sume#else 333578064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 333678064Sume#endif 333778064Sume 333878064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 333978064Sume /* 334078064Sume * If we don't have our address, this probably means our 334178064Sume * interface doesn't want to talk IPv6 at all. (This could 334278064Sume * be the case if somebody wants to speak only IPX, for 334378064Sume * example.) Don't open IPv6CP in this case. 334478064Sume */ 334578064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 334678064Sume /* XXX this message should go away */ 334778064Sume if (debug) 334878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 334978064Sume SPP_ARGS(ifp)); 335078064Sume return; 335178064Sume } 335278064Sume 335378064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 335478064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 335578064Sume sppp_open_event(&ipv6cp, sp); 335678064Sume} 335778064Sume 335878064Sumestatic void 335978064Sumesppp_ipv6cp_close(struct sppp *sp) 336078064Sume{ 336178064Sume sppp_close_event(&ipv6cp, sp); 336278064Sume} 336378064Sume 336478064Sumestatic void 336578064Sumesppp_ipv6cp_TO(void *cookie) 336678064Sume{ 336778064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 336878064Sume} 336978064Sume 337078064Sume/* 337178064Sume * Analyze a configure request. Return true if it was agreeable, and 337278064Sume * caused action sca, false if it has been rejected or nak'ed, and 337378064Sume * caused action scn. (The return value is used to make the state 337478064Sume * transition decision in the state automaton.) 337578064Sume */ 337678064Sumestatic int 337778064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 337878064Sume{ 337978064Sume u_char *buf, *r, *p; 338078064Sume struct ifnet *ifp = &sp->pp_if; 338178064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 338278064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 338378064Sume int ifidcount; 338478064Sume int type; 338578064Sume int collision, nohisaddr; 338678064Sume 338778064Sume len -= 4; 338878064Sume origlen = len; 338978064Sume /* 339078064Sume * Make sure to allocate a buf that can at least hold a 339178064Sume * conf-nak with an `address' option. We might need it below. 339278064Sume */ 339378064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 339478064Sume if (! buf) 339578064Sume return (0); 339678064Sume 339778064Sume /* pass 1: see if we can recognize them */ 339878064Sume if (debug) 339978064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 340078064Sume SPP_ARGS(ifp)); 340178064Sume p = (void*) (h+1); 340278064Sume ifidcount = 0; 340378064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 340478064Sume if (debug) 340578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 340678064Sume switch (*p) { 340778064Sume case IPV6CP_OPT_IFID: 340878064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 340978064Sume /* correctly formed address option */ 341078064Sume ifidcount++; 341178064Sume continue; 341278064Sume } 341378064Sume if (debug) 341478176Sume log(-1, " [invalid]"); 341578064Sume break; 341678064Sume#ifdef notyet 341778064Sume case IPV6CP_OPT_COMPRESSION: 341878064Sume if (len >= 4 && p[1] >= 4) { 341978064Sume /* correctly formed compress option */ 342078064Sume continue; 342178064Sume } 342278064Sume if (debug) 342378176Sume log(-1, " [invalid]"); 342478064Sume break; 342578064Sume#endif 342678064Sume default: 342778064Sume /* Others not supported. */ 342878064Sume if (debug) 342978176Sume log(-1, " [rej]"); 343078064Sume break; 343178064Sume } 343278064Sume /* Add the option to rejected list. */ 343378064Sume bcopy (p, r, p[1]); 343478064Sume r += p[1]; 343578064Sume rlen += p[1]; 343678064Sume } 343778064Sume if (rlen) { 343878064Sume if (debug) 343978176Sume log(-1, " send conf-rej\n"); 344078064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 344178064Sume goto end; 344278064Sume } else if (debug) 344378176Sume log(-1, "\n"); 344478064Sume 344578064Sume /* pass 2: parse option values */ 344678064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 344778064Sume if (debug) 344878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 344978064Sume SPP_ARGS(ifp)); 345078064Sume p = (void*) (h+1); 345178064Sume len = origlen; 345278064Sume type = CONF_ACK; 345378064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 345478064Sume if (debug) 345578176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 345678064Sume switch (*p) { 345778064Sume#ifdef notyet 345878064Sume case IPV6CP_OPT_COMPRESSION: 345978064Sume continue; 346078064Sume#endif 346178064Sume case IPV6CP_OPT_IFID: 346278064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 346378064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 346478064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 346578064Sume &myaddr.s6_addr[8], 8) == 0); 346678064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 346778064Sume 346878064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 346978064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 347078064Sume 347178064Sume if (!collision && !nohisaddr) { 347278064Sume /* no collision, hisaddr known - Conf-Ack */ 347378064Sume type = CONF_ACK; 347478064Sume 347578064Sume if (debug) { 347678176Sume log(-1, " %s [%s]", 347778064Sume ip6_sprintf(&desiredaddr), 347878064Sume sppp_cp_type_name(type)); 347978064Sume } 348078064Sume continue; 348178064Sume } 348278064Sume 348378064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 348478064Sume if (collision && nohisaddr) { 348578064Sume /* collision, hisaddr unknown - Conf-Rej */ 348678064Sume type = CONF_REJ; 348778064Sume bzero(&p[2], 8); 348878064Sume } else { 348978064Sume /* 349078064Sume * - no collision, hisaddr unknown, or 349178064Sume * - collision, hisaddr known 349278064Sume * Conf-Nak, suggest hisaddr 349378064Sume */ 349478064Sume type = CONF_NAK; 349578064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 349678064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 349778064Sume } 349878064Sume if (debug) 349978176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 350078064Sume sppp_cp_type_name(type)); 350178064Sume break; 350278064Sume } 350378064Sume /* Add the option to nak'ed list. */ 350478064Sume bcopy (p, r, p[1]); 350578064Sume r += p[1]; 350678064Sume rlen += p[1]; 350778064Sume } 350878064Sume 350978064Sume if (rlen == 0 && type == CONF_ACK) { 351078064Sume if (debug) 351178176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 351278064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 351378064Sume } else { 351478064Sume#ifdef DIAGNOSTIC 351578064Sume if (type == CONF_ACK) 351678064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 351778064Sume#endif 351878064Sume 351978064Sume if (debug) { 352078176Sume log(-1, " send %s suggest %s\n", 352178064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 352278064Sume } 352378064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 352478064Sume } 352578064Sume 352678064Sume end: 352778064Sume free (buf, M_TEMP); 352878064Sume return (rlen == 0); 352978064Sume} 353078064Sume 353178064Sume/* 353278064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 353378064Sume * negotiation. 353478064Sume */ 353578064Sumestatic void 353678064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 353778064Sume{ 353878064Sume u_char *buf, *p; 353978064Sume struct ifnet *ifp = &sp->pp_if; 354078064Sume int debug = ifp->if_flags & IFF_DEBUG; 354178064Sume 354278064Sume len -= 4; 354378064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 354478064Sume if (!buf) 354578064Sume return; 354678064Sume 354778064Sume if (debug) 354878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 354978064Sume SPP_ARGS(ifp)); 355078064Sume 355178064Sume p = (void*) (h+1); 355278064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 355378064Sume if (debug) 355478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 355578064Sume switch (*p) { 355678064Sume case IPV6CP_OPT_IFID: 355778064Sume /* 355878064Sume * Peer doesn't grok address option. This is 355978064Sume * bad. XXX Should we better give up here? 356078064Sume */ 356178064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 356278064Sume break; 356378064Sume#ifdef notyet 356478064Sume case IPV6CP_OPT_COMPRESS: 356578064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 356678064Sume break; 356778064Sume#endif 356878064Sume } 356978064Sume } 357078064Sume if (debug) 357178176Sume log(-1, "\n"); 357278064Sume free (buf, M_TEMP); 357378064Sume return; 357478064Sume} 357578064Sume 357678064Sume/* 357778064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 357878064Sume * negotiation. 357978064Sume */ 358078064Sumestatic void 358178064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 358278064Sume{ 358378064Sume u_char *buf, *p; 358478064Sume struct ifnet *ifp = &sp->pp_if; 358578064Sume int debug = ifp->if_flags & IFF_DEBUG; 358678064Sume struct in6_addr suggestaddr; 358778064Sume 358878064Sume len -= 4; 358978064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 359078064Sume if (!buf) 359178064Sume return; 359278064Sume 359378064Sume if (debug) 359478064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 359578064Sume SPP_ARGS(ifp)); 359678064Sume 359778064Sume p = (void*) (h+1); 359878064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 359978064Sume if (debug) 360078176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 360178064Sume switch (*p) { 360278064Sume case IPV6CP_OPT_IFID: 360378064Sume /* 360478064Sume * Peer doesn't like our local ifid. See 360578064Sume * if we can do something for him. We'll drop 360678064Sume * him our address then. 360778064Sume */ 360878064Sume if (len < 10 || p[1] != 10) 360978064Sume break; 361078064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 361178064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 361278064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 361378064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 361478064Sume 361578064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 361678064Sume if (debug) 361778176Sume log(-1, " [suggestaddr %s]", 361878064Sume ip6_sprintf(&suggestaddr)); 361978064Sume#ifdef IPV6CP_MYIFID_DYN 362078064Sume /* 362178064Sume * When doing dynamic address assignment, 362278064Sume * we accept his offer. 362378064Sume */ 362478064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 362578064Sume struct in6_addr lastsuggest; 362678064Sume /* 362778064Sume * If <suggested myaddr from peer> equals to 362878064Sume * <hisaddr we have suggested last time>, 362978064Sume * we have a collision. generate new random 363078064Sume * ifid. 363178064Sume */ 363278064Sume sppp_suggest_ip6_addr(&lastsuggest); 363378064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 363478064Sume lastsuggest)) { 363578064Sume if (debug) 363678176Sume log(-1, " [random]"); 363778064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 363878064Sume } 363978064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 364078064Sume if (debug) 364178176Sume log(-1, " [agree]"); 364278064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 364378064Sume } 364478064Sume#else 364578064Sume /* 364678064Sume * Since we do not do dynamic address assignment, 364778064Sume * we ignore it and thus continue to negotiate 364878064Sume * our already existing value. This can possibly 364978064Sume * go into infinite request-reject loop. 365078064Sume * 365178064Sume * This is not likely because we normally use 365278064Sume * ifid based on MAC-address. 365378064Sume * If you have no ethernet card on the node, too bad. 365478064Sume * XXX should we use fail_counter? 365578064Sume */ 365678064Sume#endif 365778064Sume break; 365878064Sume#ifdef notyet 365978064Sume case IPV6CP_OPT_COMPRESS: 366078064Sume /* 366178064Sume * Peer wants different compression parameters. 366278064Sume */ 366378064Sume break; 366478064Sume#endif 366578064Sume } 366678064Sume } 366778064Sume if (debug) 366878176Sume log(-1, "\n"); 366978064Sume free (buf, M_TEMP); 367078064Sume return; 367178064Sume} 367278064Sumestatic void 367378064Sumesppp_ipv6cp_tlu(struct sppp *sp) 367478064Sume{ 367578064Sume /* we are up - notify isdn daemon */ 367678064Sume if (sp->pp_con) 367778064Sume sp->pp_con(sp); 367878064Sume} 367978064Sume 368078064Sumestatic void 368178064Sumesppp_ipv6cp_tld(struct sppp *sp) 368278064Sume{ 368378064Sume} 368478064Sume 368578064Sumestatic void 368678064Sumesppp_ipv6cp_tls(struct sppp *sp) 368778064Sume{ 368878064Sume /* indicate to LCP that it must stay alive */ 368978064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 369078064Sume} 369178064Sume 369278064Sumestatic void 369378064Sumesppp_ipv6cp_tlf(struct sppp *sp) 369478064Sume{ 369578064Sume 369678064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 369778064Sume /* we no longer need LCP */ 369878064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 369978064Sume sppp_lcp_check_and_close(sp); 370078064Sume#endif 370178064Sume} 370278064Sume 370378064Sumestatic void 370478064Sumesppp_ipv6cp_scr(struct sppp *sp) 370578064Sume{ 370678064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 370778064Sume struct in6_addr ouraddr; 370878064Sume int i = 0; 370978064Sume 371078064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 371178064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 371278064Sume opt[i++] = IPV6CP_OPT_IFID; 371378064Sume opt[i++] = 10; 371478064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 371578064Sume i += 8; 371678064Sume } 371778064Sume 371878064Sume#ifdef notyet 371978064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 372078064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 372178064Sume opt[i++] = 4; 372278064Sume opt[i++] = 0; /* TBD */ 372378064Sume opt[i++] = 0; /* TBD */ 372478064Sume /* variable length data may follow */ 372578064Sume } 372678064Sume#endif 372778064Sume 372878064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 372978064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 373078064Sume} 373178064Sume#else /*INET6*/ 373278064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 373378064Sume{ 373478064Sume} 373578064Sume 373678064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 373778064Sume{ 373878064Sume} 373978064Sume 374078064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 374178064Sume{ 374278064Sume} 374378064Sume 374478064Sume 374578064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 374678064Sume{ 374778064Sume} 374878064Sume 374978064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 375078064Sume{ 375178064Sume} 375278064Sume 375378064Sumestatic void sppp_ipv6cp_TO(void *sp) 375478064Sume{ 375578064Sume} 375678064Sume 375778064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 375878064Sume{ 375978064Sume return 0; 376078064Sume} 376178064Sume 376278064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 376378064Sume{ 376478064Sume} 376578064Sume 376678064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 376778064Sume{ 376878064Sume} 376978064Sume 377078064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 377178064Sume{ 377278064Sume} 377378064Sume 377478064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 377578064Sume{ 377678064Sume} 377778064Sume 377878064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 377978064Sume{ 378078064Sume} 378178064Sume 378278064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 378378064Sume{ 378478064Sume} 378578064Sume 378678064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 378778064Sume{ 378878064Sume} 378978064Sume#endif /*INET6*/ 379078064Sume 379178064Sume/* 379278064Sume *--------------------------------------------------------------------------* 379378064Sume * * 379430300Sjoerg * The CHAP implementation. * 379530300Sjoerg * * 379630300Sjoerg *--------------------------------------------------------------------------* 379730300Sjoerg */ 379830300Sjoerg 379930300Sjoerg/* 380030300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 380130300Sjoerg * the control protocols do, since they do have Open and Close events, but 380230300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 380330300Sjoerg * authentication protocols may be different in both directions (this makes 380430300Sjoerg * sense, think of a machine that never accepts incoming calls but only 380530300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 380630300Sjoerg * 380730300Sjoerg * Our state machine for the local authentication protocol (we are requesting 380830300Sjoerg * the peer to authenticate) looks like: 380930300Sjoerg * 381030300Sjoerg * RCA- 381130300Sjoerg * +--------------------------------------------+ 381230300Sjoerg * V scn,tld| 381330300Sjoerg * +--------+ Close +---------+ RCA+ 381430300Sjoerg * | |<----------------------------------| |------+ 381530300Sjoerg * +--->| Closed | TO* | Opened | sca | 381630300Sjoerg * | | |-----+ +-------| |<-----+ 381730300Sjoerg * | +--------+ irc | | +---------+ 381830300Sjoerg * | ^ | | ^ 381930300Sjoerg * | | | | | 382030300Sjoerg * | | | | | 382130300Sjoerg * | TO-| | | | 382230300Sjoerg * | |tld TO+ V | | 382330300Sjoerg * | | +------->+ | | 382430300Sjoerg * | | | | | | 382530300Sjoerg * | +--------+ V | | 382630300Sjoerg * | | |<----+<--------------------+ | 382730300Sjoerg * | | Req- | scr | 382830300Sjoerg * | | Sent | | 382930300Sjoerg * | | | | 383030300Sjoerg * | +--------+ | 383130300Sjoerg * | RCA- | | RCA+ | 383230300Sjoerg * +------+ +------------------------------------------+ 383330300Sjoerg * scn,tld sca,irc,ict,tlu 383430300Sjoerg * 383530300Sjoerg * 383630300Sjoerg * with: 383730300Sjoerg * 383830300Sjoerg * Open: LCP reached authentication phase 383930300Sjoerg * Close: LCP reached terminate phase 384030300Sjoerg * 384130300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 384230300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 384330300Sjoerg * TO+: timeout with restart counter >= 0 384430300Sjoerg * TO-: timeout with restart counter < 0 384530300Sjoerg * TO*: reschedule timeout for CHAP 384630300Sjoerg * 384730300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 384830300Sjoerg * sca: send ack packet (pap-ack, chap-success) 384930300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 385030300Sjoerg * ict: initialize re-challenge timer (CHAP only) 385130300Sjoerg * 385230300Sjoerg * tlu: this-layer-up, LCP reaches network phase 385330300Sjoerg * tld: this-layer-down, LCP enters terminate phase 385430300Sjoerg * 385530300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 385630300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 385730300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 385830300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 385930300Sjoerg * causing LCP to enter terminate phase. 386030300Sjoerg * 386130300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 386230300Sjoerg * expected to send one based on the successful negotiation of PAP as 386330300Sjoerg * the authentication protocol during the LCP option negotiation. 386430300Sjoerg * 386530300Sjoerg * Incoming authentication protocol requests (remote requests 386630300Sjoerg * authentication, we are peer) don't employ a state machine at all, 386730300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 386830300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 386930300Sjoerg * still in authentication phase (thereby violating the standard that 387030300Sjoerg * demands that these NCP packets are to be discarded), so we keep 387130300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 387230300Sjoerg * phase network once we've seen a positive acknowledge for the 387330300Sjoerg * authentication. 387430300Sjoerg */ 387530300Sjoerg 387630300Sjoerg/* 387730300Sjoerg * Handle incoming CHAP packets. 387830300Sjoerg */ 387930300Sjoergvoid 388030300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 388130300Sjoerg{ 388230300Sjoerg STDDCL; 388330300Sjoerg struct lcp_header *h; 388430300Sjoerg int len, x; 388530300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 388630300Sjoerg int value_len, name_len; 388730300Sjoerg MD5_CTX ctx; 388830300Sjoerg 388930300Sjoerg len = m->m_pkthdr.len; 389030300Sjoerg if (len < 4) { 389130300Sjoerg if (debug) 389230300Sjoerg log(LOG_DEBUG, 389340008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 389440008Sjoerg SPP_ARGS(ifp), len); 389530300Sjoerg return; 389630300Sjoerg } 389730300Sjoerg h = mtod (m, struct lcp_header*); 389830300Sjoerg if (len > ntohs (h->len)) 389930300Sjoerg len = ntohs (h->len); 390030300Sjoerg 390130300Sjoerg switch (h->type) { 390230300Sjoerg /* challenge, failure and success are his authproto */ 390330300Sjoerg case CHAP_CHALLENGE: 390430300Sjoerg value = 1 + (u_char*)(h+1); 390530300Sjoerg value_len = value[-1]; 390630300Sjoerg name = value + value_len; 390730300Sjoerg name_len = len - value_len - 5; 390830300Sjoerg if (name_len < 0) { 390930300Sjoerg if (debug) { 391030300Sjoerg log(LOG_DEBUG, 391140008Sjoerg SPP_FMT "chap corrupted challenge " 391230300Sjoerg "<%s id=0x%x len=%d", 391340008Sjoerg SPP_ARGS(ifp), 391430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 391530300Sjoerg h->ident, ntohs(h->len)); 391644145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 391769211Sphk log(-1, ">\n"); 391830300Sjoerg } 391930300Sjoerg break; 392030300Sjoerg } 392170199Sjhay 392230300Sjoerg if (debug) { 392330300Sjoerg log(LOG_DEBUG, 392440008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 392540008Sjoerg SPP_ARGS(ifp), 392630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 392730300Sjoerg ntohs(h->len)); 392830300Sjoerg sppp_print_string((char*) name, name_len); 392969211Sphk log(-1, " value-size=%d value=", value_len); 393030300Sjoerg sppp_print_bytes(value, value_len); 393169211Sphk log(-1, ">\n"); 393230300Sjoerg } 393330300Sjoerg 393430300Sjoerg /* Compute reply value. */ 393530300Sjoerg MD5Init(&ctx); 393630300Sjoerg MD5Update(&ctx, &h->ident, 1); 393730300Sjoerg MD5Update(&ctx, sp->myauth.secret, 393830300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 393930300Sjoerg MD5Update(&ctx, value, value_len); 394030300Sjoerg MD5Final(digest, &ctx); 394130300Sjoerg dsize = sizeof digest; 394230300Sjoerg 394330300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 394430300Sjoerg sizeof dsize, (const char *)&dsize, 394530300Sjoerg sizeof digest, digest, 394640008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 394730300Sjoerg sp->myauth.name, 394830300Sjoerg 0); 394930300Sjoerg break; 395030300Sjoerg 395130300Sjoerg case CHAP_SUCCESS: 395230300Sjoerg if (debug) { 395340008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 395440008Sjoerg SPP_ARGS(ifp)); 395530300Sjoerg if (len > 4) { 395669211Sphk log(-1, ": "); 395730300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 395830300Sjoerg } 395969211Sphk log(-1, "\n"); 396030300Sjoerg } 396130300Sjoerg x = splimp(); 396230300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 396330300Sjoerg if (sp->myauth.proto == PPP_CHAP && 396432169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 396530300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 396630300Sjoerg /* 396730300Sjoerg * We are authenticator for CHAP but didn't 396830300Sjoerg * complete yet. Leave it to tlu to proceed 396930300Sjoerg * to network phase. 397030300Sjoerg */ 397130300Sjoerg splx(x); 397230300Sjoerg break; 397330300Sjoerg } 397430300Sjoerg splx(x); 397530300Sjoerg sppp_phase_network(sp); 397630300Sjoerg break; 397730300Sjoerg 397830300Sjoerg case CHAP_FAILURE: 397930300Sjoerg if (debug) { 398040008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 398140008Sjoerg SPP_ARGS(ifp)); 398230300Sjoerg if (len > 4) { 398369211Sphk log(-1, ": "); 398430300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 398530300Sjoerg } 398669211Sphk log(-1, "\n"); 398730300Sjoerg } else 398840008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 398940008Sjoerg SPP_ARGS(ifp)); 399030300Sjoerg /* await LCP shutdown by authenticator */ 399130300Sjoerg break; 399230300Sjoerg 399330300Sjoerg /* response is my authproto */ 399430300Sjoerg case CHAP_RESPONSE: 399530300Sjoerg value = 1 + (u_char*)(h+1); 399630300Sjoerg value_len = value[-1]; 399730300Sjoerg name = value + value_len; 399830300Sjoerg name_len = len - value_len - 5; 399930300Sjoerg if (name_len < 0) { 400030300Sjoerg if (debug) { 400130300Sjoerg log(LOG_DEBUG, 400240008Sjoerg SPP_FMT "chap corrupted response " 400330300Sjoerg "<%s id=0x%x len=%d", 400440008Sjoerg SPP_ARGS(ifp), 400530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 400630300Sjoerg h->ident, ntohs(h->len)); 400744145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 400869211Sphk log(-1, ">\n"); 400930300Sjoerg } 401030300Sjoerg break; 401130300Sjoerg } 401230300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 401330300Sjoerg if (debug) 401430300Sjoerg log(LOG_DEBUG, 401540008Sjoerg SPP_FMT "chap dropping response for old ID " 401630300Sjoerg "(got %d, expected %d)\n", 401740008Sjoerg SPP_ARGS(ifp), 401830300Sjoerg h->ident, sp->confid[IDX_CHAP]); 401930300Sjoerg break; 402030300Sjoerg } 402130300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 402230300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 402340008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 402440008Sjoerg SPP_ARGS(ifp)); 402530300Sjoerg sppp_print_string(name, name_len); 402669211Sphk log(-1, " != expected "); 402730300Sjoerg sppp_print_string(sp->hisauth.name, 402830300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 402969211Sphk log(-1, "\n"); 403070199Sjhay } 403130300Sjoerg if (debug) { 403240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 403330300Sjoerg "<%s id=0x%x len=%d name=", 403440008Sjoerg SPP_ARGS(ifp), 403530300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 403630300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 403730300Sjoerg h->ident, ntohs (h->len)); 403830300Sjoerg sppp_print_string((char*)name, name_len); 403969211Sphk log(-1, " value-size=%d value=", value_len); 404030300Sjoerg sppp_print_bytes(value, value_len); 404169211Sphk log(-1, ">\n"); 404230300Sjoerg } 404330300Sjoerg if (value_len != AUTHKEYLEN) { 404430300Sjoerg if (debug) 404530300Sjoerg log(LOG_DEBUG, 404640008Sjoerg SPP_FMT "chap bad hash value length: " 404730300Sjoerg "%d bytes, should be %d\n", 404840008Sjoerg SPP_ARGS(ifp), value_len, 404930300Sjoerg AUTHKEYLEN); 405030300Sjoerg break; 405130300Sjoerg } 405230300Sjoerg 405330300Sjoerg MD5Init(&ctx); 405430300Sjoerg MD5Update(&ctx, &h->ident, 1); 405530300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 405630300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 405730300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 405830300Sjoerg MD5Final(digest, &ctx); 405930300Sjoerg 406030300Sjoerg#define FAILMSG "Failed..." 406130300Sjoerg#define SUCCMSG "Welcome!" 406230300Sjoerg 406330300Sjoerg if (value_len != sizeof digest || 406430300Sjoerg bcmp(digest, value, value_len) != 0) { 406530300Sjoerg /* action scn, tld */ 406630300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 406730300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 406830300Sjoerg 0); 406930300Sjoerg chap.tld(sp); 407030300Sjoerg break; 407130300Sjoerg } 407230300Sjoerg /* action sca, perhaps tlu */ 407330300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 407430300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 407530300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 407630300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 407730300Sjoerg 0); 407830300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 407930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 408030300Sjoerg chap.tlu(sp); 408130300Sjoerg } 408230300Sjoerg break; 408330300Sjoerg 408430300Sjoerg default: 408530300Sjoerg /* Unknown CHAP packet type -- ignore. */ 408630300Sjoerg if (debug) { 408740008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 408830300Sjoerg "<0x%x id=0x%xh len=%d", 408940008Sjoerg SPP_ARGS(ifp), 409030300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 409130300Sjoerg h->type, h->ident, ntohs(h->len)); 409244145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 409369211Sphk log(-1, ">\n"); 409430300Sjoerg } 409530300Sjoerg break; 409630300Sjoerg 409730300Sjoerg } 409830300Sjoerg} 409930300Sjoerg 410030300Sjoergstatic void 410130300Sjoergsppp_chap_init(struct sppp *sp) 410230300Sjoerg{ 410330300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 410430300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 410530300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 410678064Sume sp->pp_seq[IDX_CHAP] = 0; 410778064Sume sp->pp_rseq[IDX_CHAP] = 0; 410842065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 410930300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 411040008Sjoerg#endif 411130300Sjoerg} 411230300Sjoerg 411330300Sjoergstatic void 411430300Sjoergsppp_chap_open(struct sppp *sp) 411530300Sjoerg{ 411630300Sjoerg if (sp->myauth.proto == PPP_CHAP && 411730300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 411830300Sjoerg /* we are authenticator for CHAP, start it */ 411930300Sjoerg chap.scr(sp); 412030300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 412130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 412230300Sjoerg } 412330300Sjoerg /* nothing to be done if we are peer, await a challenge */ 412430300Sjoerg} 412530300Sjoerg 412630300Sjoergstatic void 412730300Sjoergsppp_chap_close(struct sppp *sp) 412830300Sjoerg{ 412930300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 413030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 413130300Sjoerg} 413230300Sjoerg 413330300Sjoergstatic void 413430300Sjoergsppp_chap_TO(void *cookie) 413530300Sjoerg{ 413630300Sjoerg struct sppp *sp = (struct sppp *)cookie; 413730300Sjoerg STDDCL; 413830300Sjoerg int s; 413930300Sjoerg 414030300Sjoerg s = splimp(); 414130300Sjoerg if (debug) 414240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 414340008Sjoerg SPP_ARGS(ifp), 414430300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 414530300Sjoerg sp->rst_counter[IDX_CHAP]); 414630300Sjoerg 414730300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 414830300Sjoerg /* TO- event */ 414930300Sjoerg switch (sp->state[IDX_CHAP]) { 415030300Sjoerg case STATE_REQ_SENT: 415130300Sjoerg chap.tld(sp); 415230300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 415330300Sjoerg break; 415430300Sjoerg } 415530300Sjoerg else 415630300Sjoerg /* TO+ (or TO*) event */ 415730300Sjoerg switch (sp->state[IDX_CHAP]) { 415830300Sjoerg case STATE_OPENED: 415930300Sjoerg /* TO* event */ 416030300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 416130300Sjoerg /* fall through */ 416230300Sjoerg case STATE_REQ_SENT: 416330300Sjoerg chap.scr(sp); 416430300Sjoerg /* sppp_cp_change_state() will restart the timer */ 416530300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 416630300Sjoerg break; 416730300Sjoerg } 416830300Sjoerg 416930300Sjoerg splx(s); 417030300Sjoerg} 417130300Sjoerg 417230300Sjoergstatic void 417330300Sjoergsppp_chap_tlu(struct sppp *sp) 417430300Sjoerg{ 417530300Sjoerg STDDCL; 417630300Sjoerg int i, x; 417730300Sjoerg 417840010Sjoerg i = 0; 417930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 418030300Sjoerg 418130300Sjoerg /* 418230300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 418330300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 418430300Sjoerg * initial challenge-response exchange has taken place. 418530300Sjoerg * Provide for an option to avoid rechallenges. 418630300Sjoerg */ 418730300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 418830300Sjoerg /* 418930300Sjoerg * Compute the re-challenge timeout. This will yield 419030300Sjoerg * a number between 300 and 810 seconds. 419130300Sjoerg */ 419230300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 419342064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 419430300Sjoerg } 419530300Sjoerg 419630300Sjoerg if (debug) { 419730300Sjoerg log(LOG_DEBUG, 419840008Sjoerg SPP_FMT "chap %s, ", 419940008Sjoerg SPP_ARGS(ifp), 420030300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 420130300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 420269211Sphk log(-1, "next re-challenge in %d seconds\n", i); 420330300Sjoerg else 420469211Sphk log(-1, "re-challenging supressed\n"); 420530300Sjoerg } 420630300Sjoerg 420730300Sjoerg x = splimp(); 420830300Sjoerg /* indicate to LCP that we need to be closed down */ 420930300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 421030300Sjoerg 421130300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 421230300Sjoerg /* 421330300Sjoerg * Remote is authenticator, but his auth proto didn't 421430300Sjoerg * complete yet. Defer the transition to network 421530300Sjoerg * phase. 421630300Sjoerg */ 421730300Sjoerg splx(x); 421830300Sjoerg return; 421930300Sjoerg } 422030300Sjoerg splx(x); 422130300Sjoerg 422230300Sjoerg /* 422330300Sjoerg * If we are already in phase network, we are done here. This 422430300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 422530300Sjoerg */ 422630300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 422730300Sjoerg sppp_phase_network(sp); 422830300Sjoerg} 422930300Sjoerg 423030300Sjoergstatic void 423130300Sjoergsppp_chap_tld(struct sppp *sp) 423230300Sjoerg{ 423330300Sjoerg STDDCL; 423430300Sjoerg 423530300Sjoerg if (debug) 423640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 423740008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 423830300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 423930300Sjoerg 424030300Sjoerg lcp.Close(sp); 424130300Sjoerg} 424230300Sjoerg 424330300Sjoergstatic void 424430300Sjoergsppp_chap_scr(struct sppp *sp) 424530300Sjoerg{ 424630300Sjoerg u_long *ch, seed; 424730300Sjoerg u_char clen; 424830300Sjoerg 424930300Sjoerg /* Compute random challenge. */ 425030300Sjoerg ch = (u_long *)sp->myauth.challenge; 425142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 425235064Sphk read_random(&seed, sizeof seed); 425340008Sjoerg#else 425442104Sphk { 425542104Sphk struct timeval tv; 425640008Sjoerg microtime(&tv); 425740008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 425842104Sphk } 425940008Sjoerg#endif 426030300Sjoerg ch[0] = seed ^ random(); 426130300Sjoerg ch[1] = seed ^ random(); 426230300Sjoerg ch[2] = seed ^ random(); 426330300Sjoerg ch[3] = seed ^ random(); 426430300Sjoerg clen = AUTHKEYLEN; 426530300Sjoerg 426678064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 426730300Sjoerg 426830300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 426930300Sjoerg sizeof clen, (const char *)&clen, 427040008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 427140008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 427230300Sjoerg sp->myauth.name, 427330300Sjoerg 0); 427430300Sjoerg} 427570199Sjhay 427670199Sjhay/* 427730300Sjoerg *--------------------------------------------------------------------------* 427830300Sjoerg * * 427930300Sjoerg * The PAP implementation. * 428030300Sjoerg * * 428130300Sjoerg *--------------------------------------------------------------------------* 428230300Sjoerg */ 428330300Sjoerg/* 428430300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 428530300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 428630300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 428730300Sjoerg * retry counter is expired). 428830300Sjoerg */ 428930300Sjoerg 429030300Sjoerg/* 429130300Sjoerg * Handle incoming PAP packets. */ 429230300Sjoergstatic void 429330300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 429430300Sjoerg{ 429530300Sjoerg STDDCL; 429630300Sjoerg struct lcp_header *h; 429730300Sjoerg int len, x; 429830300Sjoerg u_char *name, *passwd, mlen; 429930300Sjoerg int name_len, passwd_len; 430030300Sjoerg 430130300Sjoerg len = m->m_pkthdr.len; 430230300Sjoerg if (len < 5) { 430330300Sjoerg if (debug) 430430300Sjoerg log(LOG_DEBUG, 430540008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 430640008Sjoerg SPP_ARGS(ifp), len); 430730300Sjoerg return; 430830300Sjoerg } 430930300Sjoerg h = mtod (m, struct lcp_header*); 431030300Sjoerg if (len > ntohs (h->len)) 431130300Sjoerg len = ntohs (h->len); 431230300Sjoerg switch (h->type) { 431330300Sjoerg /* PAP request is my authproto */ 431430300Sjoerg case PAP_REQ: 431530300Sjoerg name = 1 + (u_char*)(h+1); 431630300Sjoerg name_len = name[-1]; 431730300Sjoerg passwd = name + name_len + 1; 431830300Sjoerg if (name_len > len - 6 || 431930300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 432030300Sjoerg if (debug) { 432140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 432230300Sjoerg "<%s id=0x%x len=%d", 432340008Sjoerg SPP_ARGS(ifp), 432430300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 432530300Sjoerg h->ident, ntohs(h->len)); 432644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 432769211Sphk log(-1, ">\n"); 432830300Sjoerg } 432930300Sjoerg break; 433030300Sjoerg } 433130300Sjoerg if (debug) { 433240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 433330300Sjoerg "<%s id=0x%x len=%d name=", 433440008Sjoerg SPP_ARGS(ifp), 433530300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 433630300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 433730300Sjoerg h->ident, ntohs(h->len)); 433830300Sjoerg sppp_print_string((char*)name, name_len); 433969211Sphk log(-1, " passwd="); 434030300Sjoerg sppp_print_string((char*)passwd, passwd_len); 434169211Sphk log(-1, ">\n"); 434230300Sjoerg } 434374774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 434474774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 434530300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 434630300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 434730300Sjoerg /* action scn, tld */ 434830300Sjoerg mlen = sizeof(FAILMSG) - 1; 434930300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 435030300Sjoerg sizeof mlen, (const char *)&mlen, 435130300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 435230300Sjoerg 0); 435330300Sjoerg pap.tld(sp); 435430300Sjoerg break; 435530300Sjoerg } 435630300Sjoerg /* action sca, perhaps tlu */ 435730300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 435830300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 435930300Sjoerg mlen = sizeof(SUCCMSG) - 1; 436030300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 436130300Sjoerg sizeof mlen, (const char *)&mlen, 436230300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 436330300Sjoerg 0); 436430300Sjoerg } 436530300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 436630300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 436730300Sjoerg pap.tlu(sp); 436830300Sjoerg } 436930300Sjoerg break; 437030300Sjoerg 437130300Sjoerg /* ack and nak are his authproto */ 437230300Sjoerg case PAP_ACK: 437340008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 437430300Sjoerg if (debug) { 437540008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 437640008Sjoerg SPP_ARGS(ifp)); 437730300Sjoerg name_len = *((char *)h); 437830300Sjoerg if (len > 5 && name_len) { 437969211Sphk log(-1, ": "); 438030300Sjoerg sppp_print_string((char*)(h+1), name_len); 438130300Sjoerg } 438269211Sphk log(-1, "\n"); 438330300Sjoerg } 438430300Sjoerg x = splimp(); 438530300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 438630300Sjoerg if (sp->myauth.proto == PPP_PAP && 438732169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 438830300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 438930300Sjoerg /* 439030300Sjoerg * We are authenticator for PAP but didn't 439130300Sjoerg * complete yet. Leave it to tlu to proceed 439230300Sjoerg * to network phase. 439330300Sjoerg */ 439430300Sjoerg splx(x); 439530300Sjoerg break; 439630300Sjoerg } 439730300Sjoerg splx(x); 439830300Sjoerg sppp_phase_network(sp); 439930300Sjoerg break; 440030300Sjoerg 440130300Sjoerg case PAP_NAK: 440240008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 440330300Sjoerg if (debug) { 440440008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 440540008Sjoerg SPP_ARGS(ifp)); 440630300Sjoerg name_len = *((char *)h); 440730300Sjoerg if (len > 5 && name_len) { 440869211Sphk log(-1, ": "); 440930300Sjoerg sppp_print_string((char*)(h+1), name_len); 441030300Sjoerg } 441169211Sphk log(-1, "\n"); 441230300Sjoerg } else 441340008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 441440008Sjoerg SPP_ARGS(ifp)); 441530300Sjoerg /* await LCP shutdown by authenticator */ 441630300Sjoerg break; 441730300Sjoerg 441830300Sjoerg default: 441930300Sjoerg /* Unknown PAP packet type -- ignore. */ 442030300Sjoerg if (debug) { 442140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 442230300Sjoerg "<0x%x id=0x%x len=%d", 442340008Sjoerg SPP_ARGS(ifp), 442430300Sjoerg h->type, h->ident, ntohs(h->len)); 442544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 442669211Sphk log(-1, ">\n"); 442730300Sjoerg } 442830300Sjoerg break; 442930300Sjoerg 443030300Sjoerg } 443130300Sjoerg} 443230300Sjoerg 443330300Sjoergstatic void 443430300Sjoergsppp_pap_init(struct sppp *sp) 443530300Sjoerg{ 443630300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 443730300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 443830300Sjoerg sp->fail_counter[IDX_PAP] = 0; 443978064Sume sp->pp_seq[IDX_PAP] = 0; 444078064Sume sp->pp_rseq[IDX_PAP] = 0; 444142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 444230300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 444330300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 444440008Sjoerg#endif 444530300Sjoerg} 444630300Sjoerg 444730300Sjoergstatic void 444830300Sjoergsppp_pap_open(struct sppp *sp) 444930300Sjoerg{ 445030300Sjoerg if (sp->hisauth.proto == PPP_PAP && 445130300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 445230300Sjoerg /* we are authenticator for PAP, start our timer */ 445330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 445430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 445530300Sjoerg } 445630300Sjoerg if (sp->myauth.proto == PPP_PAP) { 445730300Sjoerg /* we are peer, send a request, and start a timer */ 445830300Sjoerg pap.scr(sp); 445942064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 446042064Sphk sp->pap_my_to_ch); 446130300Sjoerg } 446230300Sjoerg} 446330300Sjoerg 446430300Sjoergstatic void 446530300Sjoergsppp_pap_close(struct sppp *sp) 446630300Sjoerg{ 446730300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 446830300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 446930300Sjoerg} 447030300Sjoerg 447130300Sjoerg/* 447230300Sjoerg * That's the timeout routine if we are authenticator. Since the 447330300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 447430300Sjoerg */ 447530300Sjoergstatic void 447630300Sjoergsppp_pap_TO(void *cookie) 447730300Sjoerg{ 447830300Sjoerg struct sppp *sp = (struct sppp *)cookie; 447930300Sjoerg STDDCL; 448030300Sjoerg int s; 448130300Sjoerg 448230300Sjoerg s = splimp(); 448330300Sjoerg if (debug) 448440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 448540008Sjoerg SPP_ARGS(ifp), 448630300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 448730300Sjoerg sp->rst_counter[IDX_PAP]); 448830300Sjoerg 448930300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 449030300Sjoerg /* TO- event */ 449130300Sjoerg switch (sp->state[IDX_PAP]) { 449230300Sjoerg case STATE_REQ_SENT: 449330300Sjoerg pap.tld(sp); 449430300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 449530300Sjoerg break; 449630300Sjoerg } 449730300Sjoerg else 449830300Sjoerg /* TO+ event, not very much we could do */ 449930300Sjoerg switch (sp->state[IDX_PAP]) { 450030300Sjoerg case STATE_REQ_SENT: 450130300Sjoerg /* sppp_cp_change_state() will restart the timer */ 450230300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 450330300Sjoerg break; 450430300Sjoerg } 450530300Sjoerg 450630300Sjoerg splx(s); 450730300Sjoerg} 450830300Sjoerg 450930300Sjoerg/* 451030300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 451130300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 451230300Sjoerg * XXX We should impose a max counter. 451330300Sjoerg */ 451430300Sjoergstatic void 451530300Sjoergsppp_pap_my_TO(void *cookie) 451630300Sjoerg{ 451730300Sjoerg struct sppp *sp = (struct sppp *)cookie; 451830300Sjoerg STDDCL; 451930300Sjoerg 452030300Sjoerg if (debug) 452140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 452240008Sjoerg SPP_ARGS(ifp)); 452330300Sjoerg 452430300Sjoerg pap.scr(sp); 452530300Sjoerg} 452630300Sjoerg 452730300Sjoergstatic void 452830300Sjoergsppp_pap_tlu(struct sppp *sp) 452930300Sjoerg{ 453030300Sjoerg STDDCL; 453130300Sjoerg int x; 453230300Sjoerg 453330300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 453430300Sjoerg 453530300Sjoerg if (debug) 453640008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 453740008Sjoerg SPP_ARGS(ifp), pap.name); 453830300Sjoerg 453930300Sjoerg x = splimp(); 454030300Sjoerg /* indicate to LCP that we need to be closed down */ 454130300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 454230300Sjoerg 454330300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 454430300Sjoerg /* 454530300Sjoerg * Remote is authenticator, but his auth proto didn't 454630300Sjoerg * complete yet. Defer the transition to network 454730300Sjoerg * phase. 454830300Sjoerg */ 454930300Sjoerg splx(x); 455030300Sjoerg return; 455130300Sjoerg } 455230300Sjoerg splx(x); 455330300Sjoerg sppp_phase_network(sp); 455430300Sjoerg} 455530300Sjoerg 455630300Sjoergstatic void 455730300Sjoergsppp_pap_tld(struct sppp *sp) 455830300Sjoerg{ 455930300Sjoerg STDDCL; 456030300Sjoerg 456130300Sjoerg if (debug) 456240008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 456340008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 456440008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 456530300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 456630300Sjoerg 456730300Sjoerg lcp.Close(sp); 456830300Sjoerg} 456930300Sjoerg 457030300Sjoergstatic void 457130300Sjoergsppp_pap_scr(struct sppp *sp) 457230300Sjoerg{ 457330300Sjoerg u_char idlen, pwdlen; 457430300Sjoerg 457578064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 457630300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 457730300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 457830300Sjoerg 457930300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 458030300Sjoerg sizeof idlen, (const char *)&idlen, 458140008Sjoerg (size_t)idlen, sp->myauth.name, 458230300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 458340008Sjoerg (size_t)pwdlen, sp->myauth.secret, 458430300Sjoerg 0); 458530300Sjoerg} 458670199Sjhay 458770199Sjhay/* 458825944Sjoerg * Random miscellaneous functions. 458925944Sjoerg */ 459025944Sjoerg 45914910Swollman/* 459230300Sjoerg * Send a PAP or CHAP proto packet. 459330300Sjoerg * 459430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 459540008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 459630300Sjoerg * mlen == 0. 459742104Sphk * NOTE: never declare variadic functions with types subject to type 459842104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 459942104Sphk * on the architecture you are on... 460030300Sjoerg */ 460130300Sjoerg 460230300Sjoergstatic void 460342104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 460442104Sphk unsigned int type, unsigned int id, 460530300Sjoerg ...) 460630300Sjoerg{ 460730300Sjoerg STDDCL; 460830300Sjoerg struct ppp_header *h; 460930300Sjoerg struct lcp_header *lh; 461030300Sjoerg struct mbuf *m; 461130300Sjoerg u_char *p; 461230300Sjoerg int len; 461342104Sphk unsigned int mlen; 461430300Sjoerg const char *msg; 461530300Sjoerg va_list ap; 461630300Sjoerg 461730300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 461830300Sjoerg if (! m) 461930300Sjoerg return; 462030300Sjoerg m->m_pkthdr.rcvif = 0; 462130300Sjoerg 462230300Sjoerg h = mtod (m, struct ppp_header*); 462330300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 462430300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 462530300Sjoerg h->protocol = htons(cp->proto); 462630300Sjoerg 462730300Sjoerg lh = (struct lcp_header*)(h + 1); 462830300Sjoerg lh->type = type; 462930300Sjoerg lh->ident = id; 463030300Sjoerg p = (u_char*) (lh+1); 463130300Sjoerg 463230300Sjoerg va_start(ap, id); 463330300Sjoerg len = 0; 463430300Sjoerg 463542104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 463630300Sjoerg msg = va_arg(ap, const char *); 463730300Sjoerg len += mlen; 463830300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 463930300Sjoerg va_end(ap); 464030300Sjoerg m_freem(m); 464130300Sjoerg return; 464230300Sjoerg } 464330300Sjoerg 464430300Sjoerg bcopy(msg, p, mlen); 464530300Sjoerg p += mlen; 464630300Sjoerg } 464730300Sjoerg va_end(ap); 464830300Sjoerg 464930300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 465030300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 465130300Sjoerg 465230300Sjoerg if (debug) { 465340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 465440008Sjoerg SPP_ARGS(ifp), cp->name, 465530300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 465630300Sjoerg lh->ident, ntohs(lh->len)); 465744145Sphk sppp_print_bytes((u_char*) (lh+1), len); 465869211Sphk log(-1, ">\n"); 465930300Sjoerg } 466069152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 466169152Sjlemon ifp->if_oerrors++; 466230300Sjoerg} 466330300Sjoerg 466430300Sjoerg/* 466525944Sjoerg * Flush interface queue. 46664910Swollman */ 466712820Sphkstatic void 466825944Sjoergsppp_qflush(struct ifqueue *ifq) 46694910Swollman{ 467025944Sjoerg struct mbuf *m, *n; 46714910Swollman 467225944Sjoerg n = ifq->ifq_head; 467325944Sjoerg while ((m = n)) { 467425944Sjoerg n = m->m_act; 467525944Sjoerg m_freem (m); 467611189Sjkh } 467725944Sjoerg ifq->ifq_head = 0; 467825944Sjoerg ifq->ifq_tail = 0; 467925944Sjoerg ifq->ifq_len = 0; 468025944Sjoerg} 468125944Sjoerg 468225944Sjoerg/* 468325944Sjoerg * Send keepalive packets, every 10 seconds. 468425944Sjoerg */ 468525944Sjoergstatic void 468625944Sjoergsppp_keepalive(void *dummy) 468725944Sjoerg{ 468825944Sjoerg struct sppp *sp; 468925944Sjoerg int s; 469025944Sjoerg 469125944Sjoerg s = splimp(); 469225944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 469325944Sjoerg struct ifnet *ifp = &sp->pp_if; 469425944Sjoerg 469525944Sjoerg /* Keepalive mode disabled or channel down? */ 469625944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 469725944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 469825944Sjoerg continue; 469925944Sjoerg 470025944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 470145152Sphk if (sp->pp_mode != IFF_CISCO && 470225944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 470325944Sjoerg continue; 470425944Sjoerg 470525944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 470625944Sjoerg /* No keepalive packets got. Stop the interface. */ 470740008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 470825944Sjoerg if_down (ifp); 470926018Sjoerg sppp_qflush (&sp->pp_cpq); 471045152Sphk if (sp->pp_mode != IFF_CISCO) { 471125944Sjoerg /* XXX */ 471225944Sjoerg /* Shut down the PPP link. */ 471325944Sjoerg lcp.Down(sp); 471425944Sjoerg /* Initiate negotiation. XXX */ 471525944Sjoerg lcp.Up(sp); 471625944Sjoerg } 47174910Swollman } 471825944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 471925944Sjoerg ++sp->pp_alivecnt; 472045152Sphk if (sp->pp_mode == IFF_CISCO) 472178064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 472278064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 472325944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 472425944Sjoerg long nmagic = htonl (sp->lcp.magic); 472578064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 472625944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 472725944Sjoerg sp->lcp.echoid, 4, &nmagic); 472825944Sjoerg } 47294910Swollman } 473025944Sjoerg splx(s); 473142064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 47324910Swollman} 47334910Swollman 473425944Sjoerg/* 473525944Sjoerg * Get both IP addresses. 473625944Sjoerg */ 473725944Sjoergstatic void 473830300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 473925944Sjoerg{ 474025944Sjoerg struct ifnet *ifp = &sp->pp_if; 474125944Sjoerg struct ifaddr *ifa; 474230300Sjoerg struct sockaddr_in *si, *sm; 474325944Sjoerg u_long ssrc, ddst; 474425944Sjoerg 474540010Sjoerg sm = NULL; 474625944Sjoerg ssrc = ddst = 0L; 474725944Sjoerg /* 474825944Sjoerg * Pick the first AF_INET address from the list, 474925944Sjoerg * aliases don't make any sense on a p2p link anyway. 475025944Sjoerg */ 475142065Sphk si = 0; 475242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 475342065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 475442104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 475571959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 475640008Sjoerg ifa; 475771959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 475842104Sphk#else 475942104Sphk for (ifa = ifp->if_addrlist; 476042104Sphk ifa; 476142104Sphk ifa = ifa->ifa_next) 476240008Sjoerg#endif 476325944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 476425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 476530300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 476625944Sjoerg if (si) 476725944Sjoerg break; 476825944Sjoerg } 476925944Sjoerg if (ifa) { 477030300Sjoerg if (si && si->sin_addr.s_addr) { 477125944Sjoerg ssrc = si->sin_addr.s_addr; 477230300Sjoerg if (srcmask) 477330300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 477430300Sjoerg } 477525944Sjoerg 477625944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 477725944Sjoerg if (si && si->sin_addr.s_addr) 477825944Sjoerg ddst = si->sin_addr.s_addr; 477925944Sjoerg } 478025944Sjoerg 478125944Sjoerg if (dst) *dst = ntohl(ddst); 478225944Sjoerg if (src) *src = ntohl(ssrc); 478325944Sjoerg} 478425944Sjoerg 478525944Sjoerg/* 478625944Sjoerg * Set my IP address. Must be called at splimp. 478725944Sjoerg */ 478825944Sjoergstatic void 478925944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 479025944Sjoerg{ 479142104Sphk STDDCL; 479225944Sjoerg struct ifaddr *ifa; 479325944Sjoerg struct sockaddr_in *si; 479484318Sjlemon struct in_ifaddr *ia; 479525944Sjoerg 479625944Sjoerg /* 479725944Sjoerg * Pick the first AF_INET address from the list, 479825944Sjoerg * aliases don't make any sense on a p2p link anyway. 479925944Sjoerg */ 480042065Sphk si = 0; 480142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 480242065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 480342104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 480471959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 480540008Sjoerg ifa; 480671959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 480742104Sphk#else 480842104Sphk for (ifa = ifp->if_addrlist; 480942104Sphk ifa; 481042104Sphk ifa = ifa->ifa_next) 481140008Sjoerg#endif 481240008Sjoerg { 481340008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 481440008Sjoerg { 481525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 481625944Sjoerg if (si) 481725944Sjoerg break; 481825944Sjoerg } 481940008Sjoerg } 482040008Sjoerg 482125944Sjoerg if (ifa && si) 482242104Sphk { 482342104Sphk int error; 482442104Sphk#if __NetBSD_Version__ >= 103080000 482542104Sphk struct sockaddr_in new_sin = *si; 482642104Sphk 482742104Sphk new_sin.sin_addr.s_addr = htonl(src); 482842104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 482942104Sphk if(debug && error) 483042104Sphk { 483142104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 483242104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 483342104Sphk } 483442104Sphk#else 483542104Sphk /* delete old route */ 483642104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 483742104Sphk if(debug && error) 483842104Sphk { 483942104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 484042104Sphk SPP_ARGS(ifp), error); 484142104Sphk } 484242104Sphk 484342104Sphk /* set new address */ 484425944Sjoerg si->sin_addr.s_addr = htonl(src); 484584318Sjlemon ia = ifatoia(ifa); 484684318Sjlemon LIST_REMOVE(ia, ia_hash); 484784318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 484825944Sjoerg 484942104Sphk /* add new route */ 485070199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 485142104Sphk if (debug && error) 485242104Sphk { 485342104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 485442104Sphk SPP_ARGS(ifp), error); 485542104Sphk } 485642104Sphk#endif 485742104Sphk } 485888599Sjoerg} 485978064Sume 486078064Sume#ifdef INET6 486178064Sume/* 486278064Sume * Get both IPv6 addresses. 486378064Sume */ 486478064Sumestatic void 486578064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 486678064Sume struct in6_addr *srcmask) 486778064Sume{ 486878064Sume struct ifnet *ifp = &sp->pp_if; 486978064Sume struct ifaddr *ifa; 487078064Sume struct sockaddr_in6 *si, *sm; 487178064Sume struct in6_addr ssrc, ddst; 487278064Sume 487378064Sume sm = NULL; 487478064Sume bzero(&ssrc, sizeof(ssrc)); 487578064Sume bzero(&ddst, sizeof(ddst)); 487678064Sume /* 487778064Sume * Pick the first link-local AF_INET6 address from the list, 487878064Sume * aliases don't make any sense on a p2p link anyway. 487978064Sume */ 488078064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 488178064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 488278064Sume ifa; 488378064Sume ifa = ifa->ifa_link.tqe_next) 488478064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 488578064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 488678064Sume ifa; 488778064Sume ifa = ifa->ifa_list.tqe_next) 488878064Sume#else 488978064Sume for (ifa = ifp->if_addrlist, si = 0; 489078064Sume ifa; 489178064Sume ifa = ifa->ifa_next) 489278064Sume#endif 489378064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 489478064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 489578064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 489678064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 489778064Sume break; 489878064Sume } 489978064Sume if (ifa) { 490078064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 490178064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 490278064Sume if (srcmask) { 490378064Sume bcopy(&sm->sin6_addr, srcmask, 490478064Sume sizeof(*srcmask)); 490578064Sume } 490678064Sume } 490778064Sume 490878064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 490978064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 491078064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 491178064Sume } 491278064Sume 491378064Sume if (dst) 491478064Sume bcopy(&ddst, dst, sizeof(*dst)); 491578064Sume if (src) 491678064Sume bcopy(&ssrc, src, sizeof(*src)); 491770199Sjhay} 491842104Sphk 491978064Sume#ifdef IPV6CP_MYIFID_DYN 492078064Sume/* 492178064Sume * Generate random ifid. 492278064Sume */ 492378064Sumestatic void 492478064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 492578064Sume{ 492678064Sume /* TBD */ 492778064Sume} 492878064Sume 492978064Sume/* 493078064Sume * Set my IPv6 address. Must be called at splimp. 493178064Sume */ 493278064Sumestatic void 493378064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 493478064Sume{ 493578064Sume STDDCL; 493678064Sume struct ifaddr *ifa; 493778064Sume struct sockaddr_in6 *sin6; 493878064Sume 493978064Sume /* 494078064Sume * Pick the first link-local AF_INET6 address from the list, 494178064Sume * aliases don't make any sense on a p2p link anyway. 494278064Sume */ 494378064Sume 494478064Sume sin6 = NULL; 494578064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 494678064Sume for (ifa = ifp->if_addrhead.tqh_first; 494778064Sume ifa; 494878064Sume ifa = ifa->ifa_link.tqe_next) 494978064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 495078064Sume for (ifa = ifp->if_addrlist.tqh_first; 495178064Sume ifa; 495278064Sume ifa = ifa->ifa_list.tqe_next) 495378064Sume#else 495478064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 495578064Sume#endif 495678064Sume { 495778064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 495878064Sume { 495978064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 496078064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 496178064Sume break; 496278064Sume } 496378064Sume } 496478064Sume 496578064Sume if (ifa && sin6) 496678064Sume { 496778064Sume int error; 496878064Sume struct sockaddr_in6 new_sin6 = *sin6; 496978064Sume 497078064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 497178064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 497278064Sume if (debug && error) 497378064Sume { 497478064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 497578064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 497678064Sume } 497778064Sume } 497878064Sume} 497978064Sume#endif 498078064Sume 498178064Sume/* 498278064Sume * Suggest a candidate address to be used by peer. 498378064Sume */ 498478064Sumestatic void 498578064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 498678064Sume{ 498778064Sume struct in6_addr myaddr; 498878064Sume struct timeval tv; 498978064Sume 499078064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 499178064Sume 499278064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 499378064Sume microtime(&tv); 499478064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 499578064Sume myaddr.s6_addr[14] ^= 0xff; 499678064Sume myaddr.s6_addr[15] ^= 0xff; 499778064Sume } else { 499878064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 499978064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 500078064Sume } 500178064Sume if (suggest) 500278064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 500378064Sume} 500478064Sume#endif /*INET6*/ 500578064Sume 500630300Sjoergstatic int 500738343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 500830300Sjoerg{ 500938343Sbde u_long subcmd; 501030300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 501188600Sjoerg struct spppreq *spr; 501288600Sjoerg int rv = 0; 501330300Sjoerg 501488600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 501588600Sjoerg return (EAGAIN); 501630300Sjoerg /* 501730300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 501830300Sjoerg * Check the cmd word first before attempting to fetch all the 501930300Sjoerg * data. 502030300Sjoerg */ 502188600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 502288600Sjoerg rv = EFAULT; 502388600Sjoerg goto quit; 502488600Sjoerg } 502530300Sjoerg 502688600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 502788600Sjoerg rv = EFAULT; 502888600Sjoerg goto quit; 502988600Sjoerg } 503030300Sjoerg 503130300Sjoerg switch (subcmd) { 503230300Sjoerg case SPPPIOGDEFS: 503388600Sjoerg if (cmd != SIOCGIFGENERIC) { 503488600Sjoerg rv = EINVAL; 503588600Sjoerg break; 503688600Sjoerg } 503730300Sjoerg /* 503830300Sjoerg * We copy over the entire current state, but clean 503930300Sjoerg * out some of the stuff we don't wanna pass up. 504030300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 504130300Sjoerg * called by any user. No need to ever get PAP or 504230300Sjoerg * CHAP secrets back to userland anyway. 504330300Sjoerg */ 504488600Sjoerg spr->defs.pp_phase = sp->pp_phase; 504588723Sjoerg spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 504688723Sjoerg spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 504788600Sjoerg spr->defs.lcp = sp->lcp; 504888600Sjoerg spr->defs.ipcp = sp->ipcp; 504988600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 505088600Sjoerg spr->defs.myauth = sp->myauth; 505188600Sjoerg spr->defs.hisauth = sp->hisauth; 505288600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 505388600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 505488600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 505588600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 505688550Sjoerg /* 505788550Sjoerg * Fixup the LCP timeout value to milliseconds so 505888550Sjoerg * spppcontrol doesn't need to bother about the value 505988550Sjoerg * of "hz". We do the reverse calculation below when 506088550Sjoerg * setting it. 506188550Sjoerg */ 506288600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 506388600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 506488600Sjoerg sizeof(struct spppreq)); 506588600Sjoerg break; 506630300Sjoerg 506730300Sjoerg case SPPPIOSDEFS: 506888600Sjoerg if (cmd != SIOCSIFGENERIC) { 506988600Sjoerg rv = EINVAL; 507088600Sjoerg break; 507188600Sjoerg } 507230300Sjoerg /* 507388550Sjoerg * We have a very specific idea of which fields we 507488550Sjoerg * allow being passed back from userland, so to not 507588550Sjoerg * clobber our current state. For one, we only allow 507688550Sjoerg * setting anything if LCP is in dead or establish 507788550Sjoerg * phase. Once the authentication negotiations 507888550Sjoerg * started, the authentication settings must not be 507988550Sjoerg * changed again. (The administrator can force an 508030300Sjoerg * ifconfig down in order to get LCP back into dead 508130300Sjoerg * phase.) 508230300Sjoerg * 508330300Sjoerg * Also, we only allow for authentication parameters to be 508430300Sjoerg * specified. 508530300Sjoerg * 508630300Sjoerg * XXX Should allow to set or clear pp_flags. 508730300Sjoerg * 508830300Sjoerg * Finally, if the respective authentication protocol to 508930300Sjoerg * be used is set differently than 0, but the secret is 509030300Sjoerg * passed as all zeros, we don't trash the existing secret. 509130300Sjoerg * This allows an administrator to change the system name 509230300Sjoerg * only without clobbering the secret (which he didn't get 509330300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 509430300Sjoerg * secrets are cleared if the authentication protocol is 509588550Sjoerg * reset to 0. */ 509688550Sjoerg if (sp->pp_phase != PHASE_DEAD && 509788600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 509888600Sjoerg rv = EBUSY; 509988600Sjoerg break; 510088600Sjoerg } 510130300Sjoerg 510288600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 510388600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 510488600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 510588600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 510688600Sjoerg rv = EINVAL; 510788600Sjoerg break; 510888600Sjoerg } 510930300Sjoerg 511088600Sjoerg if (spr->defs.myauth.proto == 0) 511130300Sjoerg /* resetting myauth */ 511230300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 511330300Sjoerg else { 511430300Sjoerg /* setting/changing myauth */ 511588600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 511688600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 511788600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 511888600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 511930300Sjoerg AUTHKEYLEN); 512030300Sjoerg } 512188600Sjoerg if (spr->defs.hisauth.proto == 0) 512230300Sjoerg /* resetting hisauth */ 512330300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 512430300Sjoerg else { 512530300Sjoerg /* setting/changing hisauth */ 512688600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 512788600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 512888600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 512988600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 513088600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 513130300Sjoerg AUTHKEYLEN); 513230300Sjoerg } 513388550Sjoerg /* set LCP restart timer timeout */ 513488600Sjoerg if (spr->defs.lcp.timeout != 0) 513588600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 513688723Sjoerg /* set VJ enable and IPv6 disable flags */ 513788723Sjoerg#ifdef INET 513888723Sjoerg if (spr->defs.enable_vj) 513988723Sjoerg sp->confflags |= CONF_ENABLE_VJ; 514088723Sjoerg else 514188723Sjoerg sp->confflags &= ~CONF_ENABLE_VJ; 514288723Sjoerg#endif 514388723Sjoerg#ifdef INET6 514488723Sjoerg if (spr->defs.enable_ipv6) 514588723Sjoerg sp->confflags |= CONF_ENABLE_IPV6; 514688723Sjoerg else 514788723Sjoerg sp->confflags &= ~CONF_ENABLE_IPV6; 514830300Sjoerg break; 514988723Sjoerg#endif 515030300Sjoerg 515130300Sjoerg default: 515288600Sjoerg rv = EINVAL; 515330300Sjoerg } 515430300Sjoerg 515588600Sjoerg quit: 515688600Sjoerg free(spr, M_TEMP); 515788600Sjoerg 515888600Sjoerg return (rv); 515930300Sjoerg} 516030300Sjoerg 516130300Sjoergstatic void 516230300Sjoergsppp_phase_network(struct sppp *sp) 516330300Sjoerg{ 516442066Sphk STDDCL; 516530300Sjoerg int i; 516630300Sjoerg u_long mask; 516730300Sjoerg 516830300Sjoerg sp->pp_phase = PHASE_NETWORK; 516930300Sjoerg 517042066Sphk if (debug) 517142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 517242066Sphk sppp_phase_name(sp->pp_phase)); 517330300Sjoerg 517430300Sjoerg /* Notify NCPs now. */ 517530300Sjoerg for (i = 0; i < IDX_COUNT; i++) 517630300Sjoerg if ((cps[i])->flags & CP_NCP) 517730300Sjoerg (cps[i])->Open(sp); 517830300Sjoerg 517930300Sjoerg /* Send Up events to all NCPs. */ 518030300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 518188706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 518230300Sjoerg (cps[i])->Up(sp); 518330300Sjoerg 518430300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 518530300Sjoerg sppp_lcp_check_and_close(sp); 518630300Sjoerg} 518730300Sjoerg 518870199Sjhay 518925706Sjoergstatic const char * 519025944Sjoergsppp_cp_type_name(u_char type) 51914910Swollman{ 519230300Sjoerg static char buf[12]; 51934910Swollman switch (type) { 519430300Sjoerg case CONF_REQ: return "conf-req"; 519530300Sjoerg case CONF_ACK: return "conf-ack"; 519630300Sjoerg case CONF_NAK: return "conf-nak"; 519730300Sjoerg case CONF_REJ: return "conf-rej"; 519830300Sjoerg case TERM_REQ: return "term-req"; 519930300Sjoerg case TERM_ACK: return "term-ack"; 520030300Sjoerg case CODE_REJ: return "code-rej"; 520130300Sjoerg case PROTO_REJ: return "proto-rej"; 520230300Sjoerg case ECHO_REQ: return "echo-req"; 520330300Sjoerg case ECHO_REPLY: return "echo-reply"; 520430300Sjoerg case DISC_REQ: return "discard-req"; 52054910Swollman } 520644145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 520730300Sjoerg return buf; 52084910Swollman} 52094910Swollman 521025706Sjoergstatic const char * 521130300Sjoergsppp_auth_type_name(u_short proto, u_char type) 521230300Sjoerg{ 521330300Sjoerg static char buf[12]; 521430300Sjoerg switch (proto) { 521530300Sjoerg case PPP_CHAP: 521630300Sjoerg switch (type) { 521730300Sjoerg case CHAP_CHALLENGE: return "challenge"; 521830300Sjoerg case CHAP_RESPONSE: return "response"; 521930300Sjoerg case CHAP_SUCCESS: return "success"; 522030300Sjoerg case CHAP_FAILURE: return "failure"; 522130300Sjoerg } 522230300Sjoerg case PPP_PAP: 522330300Sjoerg switch (type) { 522430300Sjoerg case PAP_REQ: return "req"; 522530300Sjoerg case PAP_ACK: return "ack"; 522630300Sjoerg case PAP_NAK: return "nak"; 522730300Sjoerg } 522830300Sjoerg } 522944145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 523030300Sjoerg return buf; 523130300Sjoerg} 523230300Sjoerg 523330300Sjoergstatic const char * 523425944Sjoergsppp_lcp_opt_name(u_char opt) 52354910Swollman{ 523630300Sjoerg static char buf[12]; 523725944Sjoerg switch (opt) { 523830300Sjoerg case LCP_OPT_MRU: return "mru"; 523930300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 524030300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 524130300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 524230300Sjoerg case LCP_OPT_MAGIC: return "magic"; 524330300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 524430300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 52454910Swollman } 524644145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 524730300Sjoerg return buf; 52484910Swollman} 52494910Swollman 525025944Sjoergstatic const char * 525125944Sjoergsppp_ipcp_opt_name(u_char opt) 525225944Sjoerg{ 525330300Sjoerg static char buf[12]; 525425944Sjoerg switch (opt) { 525530300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 525630300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 525730300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 525825944Sjoerg } 525944145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 526030300Sjoerg return buf; 526125944Sjoerg} 526225944Sjoerg 526378064Sume#ifdef INET6 526425944Sjoergstatic const char * 526578064Sumesppp_ipv6cp_opt_name(u_char opt) 526678064Sume{ 526778064Sume static char buf[12]; 526878064Sume switch (opt) { 526978064Sume case IPV6CP_OPT_IFID: return "ifid"; 527078064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 527178064Sume } 527278064Sume sprintf (buf, "0x%x", opt); 527378064Sume return buf; 527478064Sume} 527578064Sume#endif 527678064Sume 527778064Sumestatic const char * 527825944Sjoergsppp_state_name(int state) 527925944Sjoerg{ 528025944Sjoerg switch (state) { 528125944Sjoerg case STATE_INITIAL: return "initial"; 528225944Sjoerg case STATE_STARTING: return "starting"; 528325944Sjoerg case STATE_CLOSED: return "closed"; 528425944Sjoerg case STATE_STOPPED: return "stopped"; 528525944Sjoerg case STATE_CLOSING: return "closing"; 528625944Sjoerg case STATE_STOPPING: return "stopping"; 528725944Sjoerg case STATE_REQ_SENT: return "req-sent"; 528825944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 528925944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 529025944Sjoerg case STATE_OPENED: return "opened"; 529125944Sjoerg } 529225944Sjoerg return "illegal"; 529325944Sjoerg} 529425944Sjoerg 529525944Sjoergstatic const char * 529625944Sjoergsppp_phase_name(enum ppp_phase phase) 529725944Sjoerg{ 529825944Sjoerg switch (phase) { 529925944Sjoerg case PHASE_DEAD: return "dead"; 530025944Sjoerg case PHASE_ESTABLISH: return "establish"; 530125944Sjoerg case PHASE_TERMINATE: return "terminate"; 530225944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 530325944Sjoerg case PHASE_NETWORK: return "network"; 530425944Sjoerg } 530525944Sjoerg return "illegal"; 530625944Sjoerg} 530725944Sjoerg 530825944Sjoergstatic const char * 530925944Sjoergsppp_proto_name(u_short proto) 531025944Sjoerg{ 531125944Sjoerg static char buf[12]; 531225944Sjoerg switch (proto) { 531325944Sjoerg case PPP_LCP: return "lcp"; 531425944Sjoerg case PPP_IPCP: return "ipcp"; 531530300Sjoerg case PPP_PAP: return "pap"; 531630300Sjoerg case PPP_CHAP: return "chap"; 531778064Sume case PPP_IPV6CP: return "ipv6cp"; 531825944Sjoerg } 531944145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 532025944Sjoerg return buf; 532125944Sjoerg} 532225944Sjoerg 532312820Sphkstatic void 532430300Sjoergsppp_print_bytes(const u_char *p, u_short len) 53254910Swollman{ 532644145Sphk if (len) 532769211Sphk log(-1, " %*D", len, p, "-"); 53284910Swollman} 532925944Sjoerg 533030300Sjoergstatic void 533130300Sjoergsppp_print_string(const char *p, u_short len) 533230300Sjoerg{ 533330300Sjoerg u_char c; 533430300Sjoerg 533530300Sjoerg while (len-- > 0) { 533630300Sjoerg c = *p++; 533730300Sjoerg /* 533830300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 533930300Sjoerg * using only them, but we don't rely on it. */ 534030300Sjoerg if (c < ' ' || c > '~') 534169211Sphk log(-1, "\\x%x", c); 534230300Sjoerg else 534369211Sphk log(-1, "%c", c); 534430300Sjoerg } 534530300Sjoerg} 534630300Sjoerg 534730300Sjoergstatic const char * 534830300Sjoergsppp_dotted_quad(u_long addr) 534930300Sjoerg{ 535030300Sjoerg static char s[16]; 535130300Sjoerg sprintf(s, "%d.%d.%d.%d", 535240008Sjoerg (int)((addr >> 24) & 0xff), 535340008Sjoerg (int)((addr >> 16) & 0xff), 535440008Sjoerg (int)((addr >> 8) & 0xff), 535538372Sbde (int)(addr & 0xff)); 535630300Sjoerg return s; 535730300Sjoerg} 535830300Sjoerg 535930300Sjoergstatic int 536030300Sjoergsppp_strnlen(u_char *p, int max) 536130300Sjoerg{ 536230300Sjoerg int len; 536330300Sjoerg 536430300Sjoerg for (len = 0; len < max && *p; ++p) 536530300Sjoerg ++len; 536630300Sjoerg return len; 536730300Sjoerg} 536830300Sjoerg 536930300Sjoerg/* a dummy, used to drop uninteresting events */ 537030300Sjoergstatic void 537130300Sjoergsppp_null(struct sppp *unused) 537230300Sjoerg{ 537330300Sjoerg /* do just nothing */ 537430300Sjoerg} 5375