if_spppsubr.c revision 88716
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 88716 2001-12-30 19:02:27Z joerg $ 214910Swollman */ 224910Swollman 2340008Sjoerg#include <sys/param.h> 2440008Sjoerg 2542065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2632350Seivind#include "opt_inet.h" 2754263Sshin#include "opt_inet6.h" 2831742Seivind#include "opt_ipx.h" 2940008Sjoerg#endif 3031742Seivind 3140008Sjoerg#ifdef NetBSD1_3 3240008Sjoerg# if NetBSD1_3 > 6 3340008Sjoerg# include "opt_inet.h" 3454263Sshin# include "opt_inet6.h" 3540008Sjoerg# include "opt_iso.h" 3640008Sjoerg# endif 3740008Sjoerg#endif 3840008Sjoerg 394952Sbde#include <sys/systm.h> 404952Sbde#include <sys/kernel.h> 4170199Sjhay#include <sys/module.h> 4224204Sbde#include <sys/sockio.h> 434910Swollman#include <sys/socket.h> 4425706Sjoerg#include <sys/syslog.h> 4542104Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4659604Sobrien#include <sys/random.h> 4742104Sphk#endif 4829024Sbde#include <sys/malloc.h> 494910Swollman#include <sys/mbuf.h> 5040008Sjoerg 5140008Sjoerg#if defined (__OpenBSD__) 5240008Sjoerg#include <sys/md5k.h> 5340008Sjoerg#else 5430300Sjoerg#include <sys/md5.h> 5540008Sjoerg#endif 564910Swollman 574910Swollman#include <net/if.h> 584910Swollman#include <net/netisr.h> 594910Swollman#include <net/if_types.h> 6042104Sphk#include <net/route.h> 6188534Sjoerg#include <netinet/in.h> 6288534Sjoerg#include <netinet/in_systm.h> 6388534Sjoerg#include <netinet/ip.h> 6488534Sjoerg#include <net/slcompress.h> 654910Swollman 6640008Sjoerg#if defined (__NetBSD__) || defined (__OpenBSD__) 6740008Sjoerg#include <machine/cpu.h> /* XXX for softnet */ 6840008Sjoerg#endif 6942104Sphk 7030300Sjoerg#include <machine/stdarg.h> 7130300Sjoerg 724910Swollman#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) { 7854910Swollman m_freem (m); 7864910Swollman splx (s); 7874910Swollman return (ENETDOWN); 7884910Swollman } 7894910Swollman 79025944Sjoerg if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 79125944Sjoerg /* 79225944Sjoerg * Interface is not yet running, but auto-dial. Need 79325944Sjoerg * to start LCP for it. 79425944Sjoerg */ 79525944Sjoerg ifp->if_flags |= IFF_RUNNING; 79625944Sjoerg splx(s); 79725944Sjoerg lcp.Open(sp); 79825944Sjoerg s = splimp(); 79925944Sjoerg } 80025944Sjoerg 80178134Sume ifq = &ifp->if_snd; 8024910Swollman#ifdef INET 80312436Speter if (dst->sa_family == AF_INET) { 80440008Sjoerg /* XXX Check mbuf length here? */ 80512436Speter struct ip *ip = mtod (m, struct ip*); 80612436Speter struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 8074910Swollman 80842104Sphk /* 80942104Sphk * When using dynamic local IP address assignment by using 81042104Sphk * 0.0.0.0 as a local address, the first TCP session will 81142104Sphk * not connect because the local TCP checksum is computed 81242104Sphk * using 0.0.0.0 which will later become our real IP address 81342104Sphk * so the TCP checksum computed at the remote end will 81442104Sphk * become invalid. So we 81542104Sphk * - don't let packets with src ip addr 0 thru 81642104Sphk * - we flag TCP packets with src ip 0 as an error 81770199Sjhay */ 81842104Sphk 81942104Sphk if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 82042104Sphk { 82142104Sphk m_freem(m); 82242104Sphk splx(s); 82342104Sphk if(ip->ip_p == IPPROTO_TCP) 82442104Sphk return(EADDRNOTAVAIL); 82542104Sphk else 82642104Sphk return(0); 82742104Sphk } 82870199Sjhay 82942104Sphk /* 83042104Sphk * Put low delay, telnet, rlogin and ftp control packets 83142104Sphk * in front of the queue. 83242104Sphk */ 83369152Sjlemon if (_IF_QFULL(&sp->pp_fastq)) 83441686Sphk ; 83541686Sphk else if (ip->ip_tos & IPTOS_LOWDELAY) 83612436Speter ifq = &sp->pp_fastq; 83741686Sphk else if (m->m_len < sizeof *ip + sizeof *tcp) 83841686Sphk ; 83941686Sphk else if (ip->ip_p != IPPROTO_TCP) 84041686Sphk ; 84141686Sphk else if (INTERACTIVE (ntohs (tcp->th_sport))) 84241686Sphk ifq = &sp->pp_fastq; 84341686Sphk else if (INTERACTIVE (ntohs (tcp->th_dport))) 84441686Sphk ifq = &sp->pp_fastq; 84588534Sjoerg 84688534Sjoerg /* 84788534Sjoerg * Do IP Header compression 84888534Sjoerg */ 84988534Sjoerg if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 85088534Sjoerg ip->ip_p == IPPROTO_TCP) 85188599Sjoerg switch (sl_compress_tcp(m, ip, sp->pp_comp, 85288534Sjoerg sp->ipcp.compress_cid)) { 85388534Sjoerg case TYPE_COMPRESSED_TCP: 85488534Sjoerg ipproto = PPP_VJ_COMP; 85588534Sjoerg break; 85688534Sjoerg case TYPE_UNCOMPRESSED_TCP: 85788534Sjoerg ipproto = PPP_VJ_UCOMP; 85888534Sjoerg break; 85988534Sjoerg case TYPE_IP: 86088534Sjoerg ipproto = PPP_IP; 86188534Sjoerg break; 86288534Sjoerg default: 86388534Sjoerg m_freem(m); 86488534Sjoerg splx(s); 86588534Sjoerg return (EINVAL); 86688534Sjoerg } 8674910Swollman } 8684910Swollman#endif 8694910Swollman 87078064Sume#ifdef INET6 87178064Sume if (dst->sa_family == AF_INET6) { 87278064Sume /* XXX do something tricky here? */ 87378064Sume } 87478064Sume#endif 87578064Sume 8764910Swollman /* 8774910Swollman * Prepend general data packet PPP header. For now, IP only. 8784910Swollman */ 8794910Swollman M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 8804910Swollman if (! m) { 88142066Sphk if (debug) 88240008Sjoerg log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 88340008Sjoerg SPP_ARGS(ifp)); 88425944Sjoerg ++ifp->if_oerrors; 8854910Swollman splx (s); 8864910Swollman return (ENOBUFS); 8874910Swollman } 88840008Sjoerg /* 88940008Sjoerg * May want to check size of packet 89040008Sjoerg * (albeit due to the implementation it's always enough) 89140008Sjoerg */ 8924910Swollman h = mtod (m, struct ppp_header*); 89345152Sphk if (sp->pp_mode == IFF_CISCO) { 89428088Skjc h->address = CISCO_UNICAST; /* unicast address */ 8954910Swollman h->control = 0; 8964910Swollman } else { 8974910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 8984910Swollman h->control = PPP_UI; /* Unnumbered Info */ 8994910Swollman } 9004910Swollman 9014910Swollman switch (dst->sa_family) { 9024910Swollman#ifdef INET 9034910Swollman case AF_INET: /* Internet Protocol */ 90445152Sphk if (sp->pp_mode == IFF_CISCO) 90511189Sjkh h->protocol = htons (ETHERTYPE_IP); 90611189Sjkh else { 90725955Sjoerg /* 90825955Sjoerg * Don't choke with an ENETDOWN early. It's 90925955Sjoerg * possible that we just started dialing out, 91025955Sjoerg * so don't drop the packet immediately. If 91125955Sjoerg * we notice that we run out of buffer space 91225955Sjoerg * below, we will however remember that we are 91325955Sjoerg * not ready to carry IP packets, and return 91425955Sjoerg * ENETDOWN, as opposed to ENOBUFS. 91525955Sjoerg */ 91688534Sjoerg h->protocol = htons(ipproto); 91725955Sjoerg if (sp->state[IDX_IPCP] != STATE_OPENED) 91825955Sjoerg rv = ENETDOWN; 91911189Sjkh } 9204910Swollman break; 9214910Swollman#endif 92254263Sshin#ifdef INET6 92354263Sshin case AF_INET6: /* Internet Protocol */ 92454263Sshin if (sp->pp_mode == IFF_CISCO) 92554263Sshin h->protocol = htons (ETHERTYPE_IPV6); 92654263Sshin else { 92778064Sume /* 92878064Sume * Don't choke with an ENETDOWN early. It's 92978064Sume * possible that we just started dialing out, 93078064Sume * so don't drop the packet immediately. If 93178064Sume * we notice that we run out of buffer space 93278064Sume * below, we will however remember that we are 93378064Sume * not ready to carry IP packets, and return 93478064Sume * ENETDOWN, as opposed to ENOBUFS. 93578064Sume */ 93678064Sume h->protocol = htons(PPP_IPV6); 93778064Sume if (sp->state[IDX_IPV6CP] != STATE_OPENED) 93878064Sume rv = ENETDOWN; 93954263Sshin } 94054263Sshin break; 94154263Sshin#endif 9424910Swollman#ifdef NS 9434910Swollman case AF_NS: /* Xerox NS Protocol */ 94445152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 9454910Swollman ETHERTYPE_NS : PPP_XNS); 9464910Swollman break; 9474910Swollman#endif 94811819Sjulian#ifdef IPX 94912495Speter case AF_IPX: /* Novell IPX Protocol */ 95045152Sphk h->protocol = htons (sp->pp_mode == IFF_CISCO ? 95112495Speter ETHERTYPE_IPX : PPP_IPX); 95211819Sjulian break; 95311819Sjulian#endif 9544910Swollman default: 9554910Swollman m_freem (m); 95625944Sjoerg ++ifp->if_oerrors; 9574910Swollman splx (s); 9584910Swollman return (EAFNOSUPPORT); 9594910Swollman } 9604910Swollman 9614910Swollman /* 9624910Swollman * Queue message on interface, and start output if interface 96388577Sjoerg * not yet active. 9644910Swollman */ 96569152Sjlemon if (! IF_HANDOFF_ADJ(ifq, m, ifp, 3)) { 96625944Sjoerg ++ifp->if_oerrors; 96725955Sjoerg return (rv? rv: ENOBUFS); 9684910Swollman } 96988577Sjoerg /* 97088577Sjoerg * Unlike in sppp_input(), we can always bump the timestamp 97188577Sjoerg * here since sppp_output() is only called on behalf of 97288577Sjoerg * network-layer traffic; control-layer traffic is handled 97388577Sjoerg * by sppp_cp_send(). 97488577Sjoerg */ 97588577Sjoerg sp->pp_last_sent = time_second; 9764910Swollman return (0); 9774910Swollman} 9784910Swollman 97925706Sjoergvoid 98025706Sjoergsppp_attach(struct ifnet *ifp) 9814910Swollman{ 9824910Swollman struct sppp *sp = (struct sppp*) ifp; 9834910Swollman 9844910Swollman /* Initialize keepalive handler. */ 9854910Swollman if (! spppq) 98642064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 9874910Swollman 9884910Swollman /* Insert new entry into the keepalive list. */ 9894910Swollman sp->pp_next = spppq; 9904910Swollman spppq = sp; 9914910Swollman 99242064Sphk sp->pp_if.if_mtu = PP_MTU; 99342064Sphk sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 9944910Swollman sp->pp_if.if_type = IFT_PPP; 9954910Swollman sp->pp_if.if_output = sppp_output; 99642104Sphk#if 0 99742064Sphk sp->pp_flags = PP_KEEPALIVE; 99842104Sphk#endif 99970199Sjhay sp->pp_if.if_snd.ifq_maxlen = 32; 100070199Sjhay sp->pp_fastq.ifq_maxlen = 32; 100170199Sjhay sp->pp_cpq.ifq_maxlen = 20; 10024910Swollman sp->pp_loopcnt = 0; 10034910Swollman sp->pp_alivecnt = 0; 100478064Sume bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 100578064Sume bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 100625944Sjoerg sp->pp_phase = PHASE_DEAD; 100725944Sjoerg sp->pp_up = lcp.Up; 100825944Sjoerg sp->pp_down = lcp.Down; 100988716Sjoerg if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 101088716Sjoerg mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", MTX_DEF); 101188716Sjoerg if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 101288716Sjoerg mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", MTX_DEF); 101388599Sjoerg sp->pp_last_recv = sp->pp_last_sent = time_second; 101488534Sjoerg sp->enable_vj = 1; 101588599Sjoerg sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAIT); 101688599Sjoerg sl_compress_init(sp->pp_comp, -1); 101725944Sjoerg sppp_lcp_init(sp); 101825944Sjoerg sppp_ipcp_init(sp); 101978064Sume sppp_ipv6cp_init(sp); 102030300Sjoerg sppp_pap_init(sp); 102130300Sjoerg sppp_chap_init(sp); 10224910Swollman} 10234910Swollman 102430300Sjoergvoid 102525706Sjoergsppp_detach(struct ifnet *ifp) 10264910Swollman{ 10274910Swollman struct sppp **q, *p, *sp = (struct sppp*) ifp; 102825944Sjoerg int i; 10294910Swollman 10304910Swollman /* Remove the entry from the keepalive list. */ 10314910Swollman for (q = &spppq; (p = *q); q = &p->pp_next) 10324910Swollman if (p == sp) { 10334910Swollman *q = p->pp_next; 10344910Swollman break; 10354910Swollman } 10364910Swollman 10374910Swollman /* Stop keepalive handler. */ 10384910Swollman if (! spppq) 103940008Sjoerg UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 104025944Sjoerg 104125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 104240008Sjoerg UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 104340008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 104469152Sjlemon mtx_destroy(&sp->pp_cpq.ifq_mtx); 104569152Sjlemon mtx_destroy(&sp->pp_fastq.ifq_mtx); 10464910Swollman} 10474910Swollman 10484910Swollman/* 10494910Swollman * Flush the interface output queue. 10504910Swollman */ 105125706Sjoergvoid 105225706Sjoergsppp_flush(struct ifnet *ifp) 10534910Swollman{ 10544910Swollman struct sppp *sp = (struct sppp*) ifp; 10554910Swollman 105625944Sjoerg sppp_qflush (&sp->pp_if.if_snd); 105725944Sjoerg sppp_qflush (&sp->pp_fastq); 105826018Sjoerg sppp_qflush (&sp->pp_cpq); 10594910Swollman} 10604910Swollman 10614910Swollman/* 106211189Sjkh * Check if the output queue is empty. 106311189Sjkh */ 106412820Sphkint 106525706Sjoergsppp_isempty(struct ifnet *ifp) 106611189Sjkh{ 106711189Sjkh struct sppp *sp = (struct sppp*) ifp; 106825944Sjoerg int empty, s; 106911189Sjkh 107025944Sjoerg s = splimp(); 107126018Sjoerg empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 107226018Sjoerg !sp->pp_if.if_snd.ifq_head; 107325944Sjoerg splx(s); 107411189Sjkh return (empty); 107511189Sjkh} 107611189Sjkh 107711189Sjkh/* 10784910Swollman * Get next packet to send. 10794910Swollman */ 108025706Sjoergstruct mbuf * 108125706Sjoergsppp_dequeue(struct ifnet *ifp) 10824910Swollman{ 10834910Swollman struct sppp *sp = (struct sppp*) ifp; 10844910Swollman struct mbuf *m; 108525944Sjoerg int s; 10864910Swollman 108725944Sjoerg s = splimp(); 108826018Sjoerg /* 108930300Sjoerg * Process only the control protocol queue until we have at 109030300Sjoerg * least one NCP open. 109126018Sjoerg * 109226018Sjoerg * Do always serve all three queues in Cisco mode. 109326018Sjoerg */ 109426018Sjoerg IF_DEQUEUE(&sp->pp_cpq, m); 109526018Sjoerg if (m == NULL && 109645152Sphk (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 109726018Sjoerg IF_DEQUEUE(&sp->pp_fastq, m); 109826018Sjoerg if (m == NULL) 109926018Sjoerg IF_DEQUEUE (&sp->pp_if.if_snd, m); 110026018Sjoerg } 110126018Sjoerg splx(s); 110226018Sjoerg return m; 11034910Swollman} 11044910Swollman 11054910Swollman/* 110630300Sjoerg * Pick the next packet, do not remove it from the queue. 110730300Sjoerg */ 110830300Sjoergstruct mbuf * 110930300Sjoergsppp_pick(struct ifnet *ifp) 111030300Sjoerg{ 111130300Sjoerg struct sppp *sp = (struct sppp*)ifp; 111230300Sjoerg struct mbuf *m; 111330300Sjoerg int s; 111430300Sjoerg 111530300Sjoerg s= splimp (); 111630300Sjoerg 111730300Sjoerg m = sp->pp_cpq.ifq_head; 111830300Sjoerg if (m == NULL && 111945152Sphk (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 112030300Sjoerg if ((m = sp->pp_fastq.ifq_head) == NULL) 112130300Sjoerg m = sp->pp_if.if_snd.ifq_head; 112230300Sjoerg splx (s); 112330300Sjoerg return (m); 112430300Sjoerg} 112530300Sjoerg 112630300Sjoerg/* 112725944Sjoerg * Process an ioctl request. Called on low priority level. 11284910Swollman */ 112925944Sjoergint 113042104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 11314910Swollman{ 113225944Sjoerg struct ifreq *ifr = (struct ifreq*) data; 113325944Sjoerg struct sppp *sp = (struct sppp*) ifp; 113430300Sjoerg int s, rv, going_up, going_down, newmode; 11354910Swollman 113625944Sjoerg s = splimp(); 113730300Sjoerg rv = 0; 113825944Sjoerg switch (cmd) { 113925944Sjoerg case SIOCAIFADDR: 114025944Sjoerg case SIOCSIFDSTADDR: 114125944Sjoerg break; 11424910Swollman 114325944Sjoerg case SIOCSIFADDR: 114488503Sjoerg /* set the interface "up" when assigning an IP address */ 114588503Sjoerg ifp->if_flags |= IFF_UP; 114625944Sjoerg /* fall through... */ 114711189Sjkh 114825944Sjoerg case SIOCSIFFLAGS: 114925944Sjoerg going_up = ifp->if_flags & IFF_UP && 115025944Sjoerg (ifp->if_flags & IFF_RUNNING) == 0; 115125944Sjoerg going_down = (ifp->if_flags & IFF_UP) == 0 && 115225944Sjoerg ifp->if_flags & IFF_RUNNING; 115345152Sphk 115445152Sphk newmode = ifp->if_flags & IFF_PASSIVE; 115545152Sphk if (!newmode) 115645152Sphk newmode = ifp->if_flags & IFF_AUTO; 115745152Sphk if (!newmode) 115845152Sphk newmode = ifp->if_flags & IFF_CISCO; 115945152Sphk ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 116045152Sphk ifp->if_flags |= newmode; 116145152Sphk 116245152Sphk if (newmode != sp->pp_mode) { 116345152Sphk going_down = 1; 116445152Sphk if (!going_up) 116545152Sphk going_up = ifp->if_flags & IFF_RUNNING; 11664910Swollman } 11674910Swollman 116845152Sphk if (going_down) { 116970199Sjhay if (sp->pp_mode != IFF_CISCO) 117045152Sphk lcp.Close(sp); 117145152Sphk else if (sp->pp_tlf) 117245152Sphk (sp->pp_tlf)(sp); 117326018Sjoerg sppp_flush(ifp); 117425944Sjoerg ifp->if_flags &= ~IFF_RUNNING; 117545152Sphk sp->pp_mode = newmode; 117626018Sjoerg } 11774910Swollman 117845152Sphk if (going_up) { 117970199Sjhay if (sp->pp_mode != IFF_CISCO) 118045152Sphk lcp.Close(sp); 118145152Sphk sp->pp_mode = newmode; 118245152Sphk if (sp->pp_mode == 0) { 118345152Sphk ifp->if_flags |= IFF_RUNNING; 118445152Sphk lcp.Open(sp); 118545152Sphk } 118645152Sphk if (sp->pp_mode == IFF_CISCO) { 118745152Sphk if (sp->pp_tls) 118845152Sphk (sp->pp_tls)(sp); 118945152Sphk ifp->if_flags |= IFF_RUNNING; 119045152Sphk } 119145152Sphk } 119245152Sphk 11934910Swollman break; 119411189Sjkh 119525944Sjoerg#ifdef SIOCSIFMTU 119625944Sjoerg#ifndef ifr_mtu 119725944Sjoerg#define ifr_mtu ifr_metric 119825944Sjoerg#endif 119925944Sjoerg case SIOCSIFMTU: 120025944Sjoerg if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 120125944Sjoerg return (EINVAL); 120225944Sjoerg ifp->if_mtu = ifr->ifr_mtu; 12034910Swollman break; 120425944Sjoerg#endif 120525944Sjoerg#ifdef SLIOCSETMTU 120625944Sjoerg case SLIOCSETMTU: 120725944Sjoerg if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 120825944Sjoerg return (EINVAL); 120925944Sjoerg ifp->if_mtu = *(short*)data; 12104910Swollman break; 121125944Sjoerg#endif 121225944Sjoerg#ifdef SIOCGIFMTU 121325944Sjoerg case SIOCGIFMTU: 121425944Sjoerg ifr->ifr_mtu = ifp->if_mtu; 121511189Sjkh break; 121625944Sjoerg#endif 121725944Sjoerg#ifdef SLIOCGETMTU 121825944Sjoerg case SLIOCGETMTU: 121925944Sjoerg *(short*)data = ifp->if_mtu; 12204910Swollman break; 122125944Sjoerg#endif 122225944Sjoerg case SIOCADDMULTI: 122325944Sjoerg case SIOCDELMULTI: 12244910Swollman break; 122511189Sjkh 122630300Sjoerg case SIOCGIFGENERIC: 122730300Sjoerg case SIOCSIFGENERIC: 122830300Sjoerg rv = sppp_params(sp, cmd, data); 122930300Sjoerg break; 123030300Sjoerg 123125944Sjoerg default: 123230300Sjoerg rv = ENOTTY; 12334910Swollman } 123425944Sjoerg splx(s); 123530300Sjoerg return rv; 12364910Swollman} 12374910Swollman 123870199Sjhay/* 123925944Sjoerg * Cisco framing implementation. 124025944Sjoerg */ 124125944Sjoerg 12424910Swollman/* 12434910Swollman * Handle incoming Cisco keepalive protocol packets. 12444910Swollman */ 124530300Sjoergstatic void 124625706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m) 12474910Swollman{ 124825944Sjoerg STDDCL; 12494910Swollman struct cisco_packet *h; 125030300Sjoerg u_long me, mymask; 12514910Swollman 125227929Sitojun if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 125325706Sjoerg if (debug) 125425706Sjoerg log(LOG_DEBUG, 125540008Sjoerg SPP_FMT "cisco invalid packet length: %d bytes\n", 125640008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len); 12574910Swollman return; 12584910Swollman } 12594910Swollman h = mtod (m, struct cisco_packet*); 126025706Sjoerg if (debug) 126125706Sjoerg log(LOG_DEBUG, 126240008Sjoerg SPP_FMT "cisco input: %d bytes " 126325706Sjoerg "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 126440008Sjoerg SPP_ARGS(ifp), m->m_pkthdr.len, 126540008Sjoerg (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 126640008Sjoerg (u_int)h->time0, (u_int)h->time1); 12674910Swollman switch (ntohl (h->type)) { 12684910Swollman default: 126925706Sjoerg if (debug) 127069211Sphk log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 127140008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (h->type)); 12724910Swollman break; 12734910Swollman case CISCO_ADDR_REPLY: 12744910Swollman /* Reply on address request, ignore */ 12754910Swollman break; 12764910Swollman case CISCO_KEEPALIVE_REQ: 12774910Swollman sp->pp_alivecnt = 0; 127878064Sume sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 127978064Sume if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 12804910Swollman /* Local and remote sequence numbers are equal. 12814910Swollman * Probably, the line is in loopback mode. */ 128211189Sjkh if (sp->pp_loopcnt >= MAXALIVECNT) { 128340008Sjoerg printf (SPP_FMT "loopback\n", 128440008Sjoerg SPP_ARGS(ifp)); 128511189Sjkh sp->pp_loopcnt = 0; 128611189Sjkh if (ifp->if_flags & IFF_UP) { 128711189Sjkh if_down (ifp); 128826018Sjoerg sppp_qflush (&sp->pp_cpq); 128911189Sjkh } 129011189Sjkh } 12914910Swollman ++sp->pp_loopcnt; 12924910Swollman 12934910Swollman /* Generate new local sequence number */ 129442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 129578064Sume sp->pp_seq[IDX_LCP] = random(); 129640008Sjoerg#else 129778064Sume sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 129840008Sjoerg#endif 129911189Sjkh break; 130011189Sjkh } 130130300Sjoerg sp->pp_loopcnt = 0; 130211189Sjkh if (! (ifp->if_flags & IFF_UP) && 130311189Sjkh (ifp->if_flags & IFF_RUNNING)) { 130430300Sjoerg if_up(ifp); 130540008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 130611189Sjkh } 13074910Swollman break; 13084910Swollman case CISCO_ADDR_REQ: 130930300Sjoerg sppp_get_ip_addrs(sp, &me, 0, &mymask); 131030300Sjoerg if (me != 0L) 131130300Sjoerg sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 13124910Swollman break; 13134910Swollman } 13144910Swollman} 13154910Swollman 13164910Swollman/* 131725944Sjoerg * Send Cisco keepalive packet. 13184910Swollman */ 131912820Sphkstatic void 132025944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 132125944Sjoerg{ 132225944Sjoerg STDDCL; 132325944Sjoerg struct ppp_header *h; 132425944Sjoerg struct cisco_packet *ch; 132525944Sjoerg struct mbuf *m; 132642065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 132735029Sphk struct timeval tv; 132840008Sjoerg#else 132940008Sjoerg u_long t = (time.tv_sec - boottime.tv_sec) * 1000; 133040008Sjoerg#endif 133125944Sjoerg 133242065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 133336119Sphk getmicrouptime(&tv); 133440008Sjoerg#endif 133570199Sjhay 133625944Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 133725944Sjoerg if (! m) 133825944Sjoerg return; 133925944Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 134025944Sjoerg m->m_pkthdr.rcvif = 0; 134125944Sjoerg 134225944Sjoerg h = mtod (m, struct ppp_header*); 134325944Sjoerg h->address = CISCO_MULTICAST; 134425944Sjoerg h->control = 0; 134525944Sjoerg h->protocol = htons (CISCO_KEEPALIVE); 134625944Sjoerg 134725944Sjoerg ch = (struct cisco_packet*) (h + 1); 134825944Sjoerg ch->type = htonl (type); 134925944Sjoerg ch->par1 = htonl (par1); 135025944Sjoerg ch->par2 = htonl (par2); 135125944Sjoerg ch->rel = -1; 135240008Sjoerg 135342065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 135435029Sphk ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 135535029Sphk ch->time1 = htons ((u_short) tv.tv_sec); 135640008Sjoerg#else 135740008Sjoerg ch->time0 = htons ((u_short) (t >> 16)); 135840008Sjoerg ch->time1 = htons ((u_short) t); 135940008Sjoerg#endif 136025944Sjoerg 136125944Sjoerg if (debug) 136225944Sjoerg log(LOG_DEBUG, 136340008Sjoerg SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 136440008Sjoerg SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 136540008Sjoerg (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 136625944Sjoerg 136769152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 136869152Sjlemon ifp->if_oerrors++; 136925944Sjoerg} 137025944Sjoerg 137170199Sjhay/* 137225944Sjoerg * PPP protocol implementation. 137325944Sjoerg */ 137425944Sjoerg 137525944Sjoerg/* 137625944Sjoerg * Send PPP control protocol packet. 137725944Sjoerg */ 137825944Sjoergstatic void 137925706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type, 138025706Sjoerg u_char ident, u_short len, void *data) 13814910Swollman{ 138225944Sjoerg STDDCL; 13834910Swollman struct ppp_header *h; 13844910Swollman struct lcp_header *lh; 13854910Swollman struct mbuf *m; 13864910Swollman 13874910Swollman if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 13884910Swollman len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 13894910Swollman MGETHDR (m, M_DONTWAIT, MT_DATA); 13904910Swollman if (! m) 13914910Swollman return; 13924910Swollman m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 13934910Swollman m->m_pkthdr.rcvif = 0; 13944910Swollman 13954910Swollman h = mtod (m, struct ppp_header*); 13964910Swollman h->address = PPP_ALLSTATIONS; /* broadcast address */ 13974910Swollman h->control = PPP_UI; /* Unnumbered Info */ 13984910Swollman h->protocol = htons (proto); /* Link Control Protocol */ 13994910Swollman 14004910Swollman lh = (struct lcp_header*) (h + 1); 14014910Swollman lh->type = type; 14024910Swollman lh->ident = ident; 14034910Swollman lh->len = htons (LCP_HEADER_LEN + len); 14044910Swollman if (len) 14054910Swollman bcopy (data, lh+1, len); 14064910Swollman 140725706Sjoerg if (debug) { 140840008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 140940008Sjoerg SPP_ARGS(ifp), 141025944Sjoerg sppp_proto_name(proto), 141125944Sjoerg sppp_cp_type_name (lh->type), lh->ident, 141225944Sjoerg ntohs (lh->len)); 141344145Sphk sppp_print_bytes ((u_char*) (lh+1), len); 141469211Sphk log(-1, ">\n"); 14154910Swollman } 141669152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 141769152Sjlemon ifp->if_oerrors++; 14184910Swollman} 14194910Swollman 14204910Swollman/* 142125944Sjoerg * Handle incoming PPP control protocol packets. 14224910Swollman */ 142312820Sphkstatic void 142425944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 14254910Swollman{ 142625944Sjoerg STDDCL; 142725944Sjoerg struct lcp_header *h; 142825944Sjoerg int len = m->m_pkthdr.len; 142925944Sjoerg int rv; 143025944Sjoerg u_char *p; 14314910Swollman 143225944Sjoerg if (len < 4) { 143325944Sjoerg if (debug) 143425944Sjoerg log(LOG_DEBUG, 143540008Sjoerg SPP_FMT "%s invalid packet length: %d bytes\n", 143640008Sjoerg SPP_ARGS(ifp), cp->name, len); 14374910Swollman return; 143825944Sjoerg } 143925944Sjoerg h = mtod (m, struct lcp_header*); 144025944Sjoerg if (debug) { 144125944Sjoerg log(LOG_DEBUG, 144240008Sjoerg SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 144340008Sjoerg SPP_ARGS(ifp), cp->name, 144425944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 144525944Sjoerg sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 144644145Sphk sppp_print_bytes ((u_char*) (h+1), len-4); 144769211Sphk log(-1, ">\n"); 144825944Sjoerg } 144925944Sjoerg if (len > ntohs (h->len)) 145025944Sjoerg len = ntohs (h->len); 145130300Sjoerg p = (u_char *)(h + 1); 145225944Sjoerg switch (h->type) { 145325944Sjoerg case CONF_REQ: 145425944Sjoerg if (len < 4) { 145525944Sjoerg if (debug) 145669211Sphk log(-1, SPP_FMT "%s invalid conf-req length %d\n", 145740008Sjoerg SPP_ARGS(ifp), cp->name, 145825944Sjoerg len); 145925944Sjoerg ++ifp->if_ierrors; 146025944Sjoerg break; 146125944Sjoerg } 146230300Sjoerg /* handle states where RCR doesn't get a SCA/SCN */ 146330300Sjoerg switch (sp->state[cp->protoidx]) { 146430300Sjoerg case STATE_CLOSING: 146530300Sjoerg case STATE_STOPPING: 146630300Sjoerg return; 146730300Sjoerg case STATE_CLOSED: 146830300Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 146930300Sjoerg 0, 0); 147030300Sjoerg return; 147130300Sjoerg } 147225944Sjoerg rv = (cp->RCR)(sp, h, len); 147325944Sjoerg switch (sp->state[cp->protoidx]) { 147425944Sjoerg case STATE_OPENED: 147525944Sjoerg (cp->tld)(sp); 147625944Sjoerg (cp->scr)(sp); 147725944Sjoerg /* fall through... */ 147825944Sjoerg case STATE_ACK_SENT: 147925944Sjoerg case STATE_REQ_SENT: 148070199Sjhay /* 148170199Sjhay * sppp_cp_change_state() have the side effect of 148270199Sjhay * restarting the timeouts. We want to avoid that 148370199Sjhay * if the state don't change, otherwise we won't 148470199Sjhay * ever timeout and resend a configuration request 148570199Sjhay * that got lost. 148670199Sjhay */ 148770199Sjhay if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 148870199Sjhay STATE_REQ_SENT)) 148970199Sjhay break; 149025944Sjoerg sppp_cp_change_state(cp, sp, rv? 149125944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 149225944Sjoerg break; 149325944Sjoerg case STATE_STOPPED: 149425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 149525944Sjoerg (cp->scr)(sp); 149625944Sjoerg sppp_cp_change_state(cp, sp, rv? 149725944Sjoerg STATE_ACK_SENT: STATE_REQ_SENT); 149825944Sjoerg break; 149925944Sjoerg case STATE_ACK_RCVD: 150025944Sjoerg if (rv) { 150125944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 150225944Sjoerg if (debug) 150340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 150440008Sjoerg SPP_ARGS(ifp), 150526077Sjoerg cp->name); 150625944Sjoerg (cp->tlu)(sp); 150725944Sjoerg } else 150825944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 150925944Sjoerg break; 151025944Sjoerg default: 151140008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 151240008Sjoerg SPP_ARGS(ifp), cp->name, 151325944Sjoerg sppp_cp_type_name(h->type), 151425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 151525944Sjoerg ++ifp->if_ierrors; 151625944Sjoerg } 151725944Sjoerg break; 151825944Sjoerg case CONF_ACK: 151925944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 152025944Sjoerg if (debug) 152169211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 152240008Sjoerg SPP_ARGS(ifp), cp->name, 152325944Sjoerg h->ident, sp->confid[cp->protoidx]); 152425944Sjoerg ++ifp->if_ierrors; 152525944Sjoerg break; 152625944Sjoerg } 152725944Sjoerg switch (sp->state[cp->protoidx]) { 152825944Sjoerg case STATE_CLOSED: 152925944Sjoerg case STATE_STOPPED: 153025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 153125944Sjoerg break; 153225944Sjoerg case STATE_CLOSING: 153325944Sjoerg case STATE_STOPPING: 153425944Sjoerg break; 153525944Sjoerg case STATE_REQ_SENT: 153625944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 153725944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 153825944Sjoerg break; 153925944Sjoerg case STATE_OPENED: 154025944Sjoerg (cp->tld)(sp); 154125944Sjoerg /* fall through */ 154225944Sjoerg case STATE_ACK_RCVD: 154325944Sjoerg (cp->scr)(sp); 154425944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 154525944Sjoerg break; 154625944Sjoerg case STATE_ACK_SENT: 154725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 154825944Sjoerg sppp_cp_change_state(cp, sp, STATE_OPENED); 154925944Sjoerg if (debug) 155040008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 155140008Sjoerg SPP_ARGS(ifp), cp->name); 155225944Sjoerg (cp->tlu)(sp); 155325944Sjoerg break; 155425944Sjoerg default: 155540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 155640008Sjoerg SPP_ARGS(ifp), cp->name, 155725944Sjoerg sppp_cp_type_name(h->type), 155825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 155925944Sjoerg ++ifp->if_ierrors; 156025944Sjoerg } 156125944Sjoerg break; 156225944Sjoerg case CONF_NAK: 156325944Sjoerg case CONF_REJ: 156425944Sjoerg if (h->ident != sp->confid[cp->protoidx]) { 156525944Sjoerg if (debug) 156669211Sphk log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 156740008Sjoerg SPP_ARGS(ifp), cp->name, 156825944Sjoerg h->ident, sp->confid[cp->protoidx]); 156925944Sjoerg ++ifp->if_ierrors; 157025944Sjoerg break; 157125944Sjoerg } 157225944Sjoerg if (h->type == CONF_NAK) 157325944Sjoerg (cp->RCN_nak)(sp, h, len); 157425944Sjoerg else /* CONF_REJ */ 157525944Sjoerg (cp->RCN_rej)(sp, h, len); 15764910Swollman 157725944Sjoerg switch (sp->state[cp->protoidx]) { 157825944Sjoerg case STATE_CLOSED: 157925944Sjoerg case STATE_STOPPED: 158025944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 158125944Sjoerg break; 158225944Sjoerg case STATE_REQ_SENT: 158325944Sjoerg case STATE_ACK_SENT: 158425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 158570199Sjhay /* 158670199Sjhay * Slow things down a bit if we think we might be 158770199Sjhay * in loopback. Depend on the timeout to send the 158870199Sjhay * next configuration request. 158970199Sjhay */ 159070199Sjhay if (sp->pp_loopcnt) 159170199Sjhay break; 159225944Sjoerg (cp->scr)(sp); 159325944Sjoerg break; 159425944Sjoerg case STATE_OPENED: 159525944Sjoerg (cp->tld)(sp); 159625944Sjoerg /* fall through */ 159725944Sjoerg case STATE_ACK_RCVD: 159852633Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 159925944Sjoerg (cp->scr)(sp); 160025944Sjoerg break; 160125944Sjoerg case STATE_CLOSING: 160225944Sjoerg case STATE_STOPPING: 160325944Sjoerg break; 160425944Sjoerg default: 160540008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 160640008Sjoerg SPP_ARGS(ifp), cp->name, 160725944Sjoerg sppp_cp_type_name(h->type), 160825944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 160925944Sjoerg ++ifp->if_ierrors; 161025944Sjoerg } 161125944Sjoerg break; 16124910Swollman 161325944Sjoerg case TERM_REQ: 161425944Sjoerg switch (sp->state[cp->protoidx]) { 161525944Sjoerg case STATE_ACK_RCVD: 161625944Sjoerg case STATE_ACK_SENT: 161725944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 161825944Sjoerg /* fall through */ 161925944Sjoerg case STATE_CLOSED: 162025944Sjoerg case STATE_STOPPED: 162125944Sjoerg case STATE_CLOSING: 162225944Sjoerg case STATE_STOPPING: 162325944Sjoerg case STATE_REQ_SENT: 162425944Sjoerg sta: 162525944Sjoerg /* Send Terminate-Ack packet. */ 162625944Sjoerg if (debug) 162740008Sjoerg log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 162840008Sjoerg SPP_ARGS(ifp), cp->name); 162925944Sjoerg sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 163025944Sjoerg break; 163125944Sjoerg case STATE_OPENED: 163225944Sjoerg (cp->tld)(sp); 163325944Sjoerg sp->rst_counter[cp->protoidx] = 0; 163425944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 163525944Sjoerg goto sta; 163625944Sjoerg break; 163725944Sjoerg default: 163840008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 163940008Sjoerg SPP_ARGS(ifp), cp->name, 164025944Sjoerg sppp_cp_type_name(h->type), 164125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 164225944Sjoerg ++ifp->if_ierrors; 164325944Sjoerg } 164425944Sjoerg break; 164525944Sjoerg case TERM_ACK: 164625944Sjoerg switch (sp->state[cp->protoidx]) { 164725944Sjoerg case STATE_CLOSED: 164825944Sjoerg case STATE_STOPPED: 164925944Sjoerg case STATE_REQ_SENT: 165025944Sjoerg case STATE_ACK_SENT: 165125944Sjoerg break; 165225944Sjoerg case STATE_CLOSING: 165341881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 165425944Sjoerg (cp->tlf)(sp); 165525944Sjoerg break; 165625944Sjoerg case STATE_STOPPING: 165741881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 165825944Sjoerg (cp->tlf)(sp); 165925944Sjoerg break; 166025944Sjoerg case STATE_ACK_RCVD: 166125944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 166225944Sjoerg break; 166325944Sjoerg case STATE_OPENED: 166425944Sjoerg (cp->tld)(sp); 166525944Sjoerg (cp->scr)(sp); 166625944Sjoerg sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 166725944Sjoerg break; 166825944Sjoerg default: 166940008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 167040008Sjoerg SPP_ARGS(ifp), cp->name, 167125944Sjoerg sppp_cp_type_name(h->type), 167225944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 167325944Sjoerg ++ifp->if_ierrors; 167425944Sjoerg } 167525944Sjoerg break; 167625944Sjoerg case CODE_REJ: 167725944Sjoerg /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 167830300Sjoerg log(LOG_INFO, 167940008Sjoerg SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 168030300Sjoerg "danger will robinson\n", 168140008Sjoerg SPP_ARGS(ifp), cp->name, 168230300Sjoerg sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 168325944Sjoerg switch (sp->state[cp->protoidx]) { 168425944Sjoerg case STATE_CLOSED: 168525944Sjoerg case STATE_STOPPED: 168625944Sjoerg case STATE_REQ_SENT: 168725944Sjoerg case STATE_ACK_SENT: 168825944Sjoerg case STATE_CLOSING: 168925944Sjoerg case STATE_STOPPING: 169025944Sjoerg case STATE_OPENED: 169125944Sjoerg break; 169225944Sjoerg case STATE_ACK_RCVD: 169325944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 169425944Sjoerg break; 169525944Sjoerg default: 169640008Sjoerg printf(SPP_FMT "%s illegal %s in state %s\n", 169740008Sjoerg SPP_ARGS(ifp), cp->name, 169825944Sjoerg sppp_cp_type_name(h->type), 169925944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 170025944Sjoerg ++ifp->if_ierrors; 170125944Sjoerg } 170225944Sjoerg break; 170380715Sume case PROTO_REJ: 170480715Sume { 170580715Sume int catastrophic; 170680715Sume const struct cp *upper; 170780715Sume int i; 170880715Sume u_int16_t proto; 170980715Sume 171080715Sume catastrophic = 0; 171180715Sume upper = NULL; 171280715Sume proto = ntohs(*((u_int16_t *)p)); 171380715Sume for (i = 0; i < IDX_COUNT; i++) { 171480715Sume if (cps[i]->proto == proto) { 171580715Sume upper = cps[i]; 171680715Sume break; 171780715Sume } 171880715Sume } 171980715Sume if (upper == NULL) 172080715Sume catastrophic++; 172180715Sume 172288508Sjoerg if (catastrophic || debug) 172388508Sjoerg log(catastrophic? LOG_INFO: LOG_DEBUG, 172488508Sjoerg SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 172588508Sjoerg SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 172688508Sjoerg sppp_cp_type_name(h->type), proto, 172788508Sjoerg upper ? upper->name : "unknown", 172888508Sjoerg upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 172980715Sume 173080715Sume /* 173180715Sume * if we got RXJ+ against conf-req, the peer does not implement 173280715Sume * this particular protocol type. terminate the protocol. 173380715Sume */ 173480715Sume if (upper && !catastrophic) { 173580715Sume if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 173680715Sume upper->Close(sp); 173780715Sume break; 173880715Sume } 173980715Sume } 174080715Sume 174180715Sume /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 174280715Sume switch (sp->state[cp->protoidx]) { 174380715Sume case STATE_CLOSED: 174480715Sume case STATE_STOPPED: 174580715Sume case STATE_REQ_SENT: 174680715Sume case STATE_ACK_SENT: 174780715Sume case STATE_CLOSING: 174880715Sume case STATE_STOPPING: 174980715Sume case STATE_OPENED: 175080715Sume break; 175180715Sume case STATE_ACK_RCVD: 175280715Sume sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 175380715Sume break; 175480715Sume default: 175580715Sume printf(SPP_FMT "%s illegal %s in state %s\n", 175680715Sume SPP_ARGS(ifp), cp->name, 175780715Sume sppp_cp_type_name(h->type), 175880715Sume sppp_state_name(sp->state[cp->protoidx])); 175980715Sume ++ifp->if_ierrors; 176080715Sume } 176180715Sume break; 176280715Sume } 176325944Sjoerg case DISC_REQ: 176425944Sjoerg if (cp->proto != PPP_LCP) 176525944Sjoerg goto illegal; 176625944Sjoerg /* Discard the packet. */ 176725944Sjoerg break; 176825944Sjoerg case ECHO_REQ: 176925944Sjoerg if (cp->proto != PPP_LCP) 177025944Sjoerg goto illegal; 177125944Sjoerg if (sp->state[cp->protoidx] != STATE_OPENED) { 177225944Sjoerg if (debug) 177369211Sphk log(-1, SPP_FMT "lcp echo req but lcp closed\n", 177440008Sjoerg SPP_ARGS(ifp)); 177525944Sjoerg ++ifp->if_ierrors; 177625944Sjoerg break; 177725944Sjoerg } 177825944Sjoerg if (len < 8) { 177925944Sjoerg if (debug) 178069211Sphk log(-1, SPP_FMT "invalid lcp echo request " 178125944Sjoerg "packet length: %d bytes\n", 178240008Sjoerg SPP_ARGS(ifp), len); 178325944Sjoerg break; 178425944Sjoerg } 178544145Sphk if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 178644145Sphk ntohl (*(long*)(h+1)) == sp->lcp.magic) { 178725944Sjoerg /* Line loopback mode detected. */ 178840008Sjoerg printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 178970199Sjhay sp->pp_loopcnt = MAXALIVECNT * 5; 179025944Sjoerg if_down (ifp); 179126018Sjoerg sppp_qflush (&sp->pp_cpq); 17924910Swollman 179325944Sjoerg /* Shut down the PPP link. */ 179425944Sjoerg /* XXX */ 179525944Sjoerg lcp.Down(sp); 179625944Sjoerg lcp.Up(sp); 179725944Sjoerg break; 179825944Sjoerg } 179925944Sjoerg *(long*)(h+1) = htonl (sp->lcp.magic); 180025944Sjoerg if (debug) 180169211Sphk log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 180240008Sjoerg SPP_ARGS(ifp)); 180325944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 180425944Sjoerg break; 180525944Sjoerg case ECHO_REPLY: 180625944Sjoerg if (cp->proto != PPP_LCP) 180725944Sjoerg goto illegal; 180825944Sjoerg if (h->ident != sp->lcp.echoid) { 180925944Sjoerg ++ifp->if_ierrors; 181025944Sjoerg break; 181125944Sjoerg } 181225944Sjoerg if (len < 8) { 181325944Sjoerg if (debug) 181469211Sphk log(-1, SPP_FMT "lcp invalid echo reply " 181525944Sjoerg "packet length: %d bytes\n", 181640008Sjoerg SPP_ARGS(ifp), len); 181725944Sjoerg break; 181825944Sjoerg } 181925944Sjoerg if (debug) 182069211Sphk log(-1, SPP_FMT "lcp got echo rep\n", 182140008Sjoerg SPP_ARGS(ifp)); 182244145Sphk if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 182344145Sphk ntohl (*(long*)(h+1)) != sp->lcp.magic) 182425944Sjoerg sp->pp_alivecnt = 0; 182525944Sjoerg break; 182625944Sjoerg default: 182725944Sjoerg /* Unknown packet type -- send Code-Reject packet. */ 182825944Sjoerg illegal: 182925944Sjoerg if (debug) 183069211Sphk log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 183140008Sjoerg SPP_ARGS(ifp), cp->name, h->type); 183278064Sume sppp_cp_send(sp, cp->proto, CODE_REJ, 183378064Sume ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 183425944Sjoerg ++ifp->if_ierrors; 183525944Sjoerg } 18364910Swollman} 18374910Swollman 183825944Sjoerg 18394910Swollman/* 184025944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers. 184125944Sjoerg * Basically, the state transition handling in the automaton. 18424910Swollman */ 184325944Sjoergstatic void 184425944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp) 18454910Swollman{ 184625944Sjoerg STDDCL; 18474910Swollman 184825944Sjoerg if (debug) 184940008Sjoerg log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 185040008Sjoerg SPP_ARGS(ifp), cp->name, 185125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 185225944Sjoerg 185325944Sjoerg switch (sp->state[cp->protoidx]) { 185425944Sjoerg case STATE_INITIAL: 185525944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 185625944Sjoerg break; 185725944Sjoerg case STATE_STARTING: 185825944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 185925944Sjoerg (cp->scr)(sp); 186025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 186125944Sjoerg break; 18624910Swollman default: 186340008Sjoerg printf(SPP_FMT "%s illegal up in state %s\n", 186440008Sjoerg SPP_ARGS(ifp), cp->name, 186525944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 186625944Sjoerg } 186725944Sjoerg} 18684910Swollman 186925944Sjoergstatic void 187025944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp) 187125944Sjoerg{ 187225944Sjoerg STDDCL; 187325944Sjoerg 187425944Sjoerg if (debug) 187540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 187640008Sjoerg SPP_ARGS(ifp), cp->name, 187725944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 187825944Sjoerg 187925944Sjoerg switch (sp->state[cp->protoidx]) { 188025944Sjoerg case STATE_CLOSED: 188125944Sjoerg case STATE_CLOSING: 188225944Sjoerg sppp_cp_change_state(cp, sp, STATE_INITIAL); 18834910Swollman break; 188425944Sjoerg case STATE_STOPPED: 188541881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 188625944Sjoerg (cp->tls)(sp); 188741881Sphk break; 188825944Sjoerg case STATE_STOPPING: 188925944Sjoerg case STATE_REQ_SENT: 189025944Sjoerg case STATE_ACK_RCVD: 189125944Sjoerg case STATE_ACK_SENT: 189225944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 189325944Sjoerg break; 189425944Sjoerg case STATE_OPENED: 189525944Sjoerg (cp->tld)(sp); 189625944Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 189725944Sjoerg break; 189825944Sjoerg default: 189940008Sjoerg printf(SPP_FMT "%s illegal down in state %s\n", 190040008Sjoerg SPP_ARGS(ifp), cp->name, 190125944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 190225944Sjoerg } 190325944Sjoerg} 19044910Swollman 190511189Sjkh 190625944Sjoergstatic void 190725944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp) 190825944Sjoerg{ 190925944Sjoerg STDDCL; 191025944Sjoerg 191125944Sjoerg if (debug) 191240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 191340008Sjoerg SPP_ARGS(ifp), cp->name, 191425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 191525944Sjoerg 191625944Sjoerg switch (sp->state[cp->protoidx]) { 191725944Sjoerg case STATE_INITIAL: 191841881Sphk sppp_cp_change_state(cp, sp, STATE_STARTING); 191925944Sjoerg (cp->tls)(sp); 19204910Swollman break; 192125944Sjoerg case STATE_STARTING: 192225944Sjoerg break; 192325944Sjoerg case STATE_CLOSED: 192425944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 192525944Sjoerg (cp->scr)(sp); 192625944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 192725944Sjoerg break; 192825944Sjoerg case STATE_STOPPED: 192974703Sjoerg /* 193074703Sjoerg * Try escaping stopped state. This seems to bite 193174703Sjoerg * people occasionally, in particular for IPCP, 193274703Sjoerg * presumably following previous IPCP negotiation 193374703Sjoerg * aborts. Somehow, we must have missed a Down event 193474703Sjoerg * which would have caused a transition into starting 193574703Sjoerg * state, so as a bandaid we force the Down event now. 193674703Sjoerg * This effectively implements (something like the) 193774703Sjoerg * `restart' option mentioned in the state transition 193874703Sjoerg * table of RFC 1661. 193974703Sjoerg */ 194074703Sjoerg sppp_cp_change_state(cp, sp, STATE_STARTING); 194174703Sjoerg (cp->tls)(sp); 194274703Sjoerg break; 194325944Sjoerg case STATE_STOPPING: 194425944Sjoerg case STATE_REQ_SENT: 194525944Sjoerg case STATE_ACK_RCVD: 194625944Sjoerg case STATE_ACK_SENT: 194725944Sjoerg case STATE_OPENED: 194825944Sjoerg break; 194925944Sjoerg case STATE_CLOSING: 195025944Sjoerg sppp_cp_change_state(cp, sp, STATE_STOPPING); 195125944Sjoerg break; 195225944Sjoerg } 195325944Sjoerg} 19544910Swollman 195525944Sjoerg 195625944Sjoergstatic void 195725944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp) 195825944Sjoerg{ 195925944Sjoerg STDDCL; 196025944Sjoerg 196125944Sjoerg if (debug) 196240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 196340008Sjoerg SPP_ARGS(ifp), cp->name, 196425944Sjoerg sppp_state_name(sp->state[cp->protoidx])); 196525944Sjoerg 196625944Sjoerg switch (sp->state[cp->protoidx]) { 196725944Sjoerg case STATE_INITIAL: 196825944Sjoerg case STATE_CLOSED: 196925944Sjoerg case STATE_CLOSING: 19704910Swollman break; 197125944Sjoerg case STATE_STARTING: 197241881Sphk sppp_cp_change_state(cp, sp, STATE_INITIAL); 197325944Sjoerg (cp->tlf)(sp); 19744910Swollman break; 197525944Sjoerg case STATE_STOPPED: 197625944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSED); 19774910Swollman break; 197825944Sjoerg case STATE_STOPPING: 197925944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19804910Swollman break; 198125944Sjoerg case STATE_OPENED: 198225944Sjoerg (cp->tld)(sp); 198325944Sjoerg /* fall through */ 198425944Sjoerg case STATE_REQ_SENT: 198525944Sjoerg case STATE_ACK_RCVD: 198625944Sjoerg case STATE_ACK_SENT: 198725944Sjoerg sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 198878064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 198978064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 199025944Sjoerg sppp_cp_change_state(cp, sp, STATE_CLOSING); 19914910Swollman break; 19924910Swollman } 19934910Swollman} 19944910Swollman 199525944Sjoergstatic void 199625944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp) 199725944Sjoerg{ 199825944Sjoerg STDDCL; 199925944Sjoerg int s; 200025944Sjoerg 200125944Sjoerg s = splimp(); 200225944Sjoerg if (debug) 200340008Sjoerg log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 200440008Sjoerg SPP_ARGS(ifp), cp->name, 200525944Sjoerg sppp_state_name(sp->state[cp->protoidx]), 200625944Sjoerg sp->rst_counter[cp->protoidx]); 200725944Sjoerg 200825944Sjoerg if (--sp->rst_counter[cp->protoidx] < 0) 200925944Sjoerg /* TO- event */ 201025944Sjoerg switch (sp->state[cp->protoidx]) { 201125944Sjoerg case STATE_CLOSING: 201241881Sphk sppp_cp_change_state(cp, sp, STATE_CLOSED); 201325944Sjoerg (cp->tlf)(sp); 201425944Sjoerg break; 201525944Sjoerg case STATE_STOPPING: 201641881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 201725944Sjoerg (cp->tlf)(sp); 201825944Sjoerg break; 201925944Sjoerg case STATE_REQ_SENT: 202025944Sjoerg case STATE_ACK_RCVD: 202125944Sjoerg case STATE_ACK_SENT: 202241881Sphk sppp_cp_change_state(cp, sp, STATE_STOPPED); 202325944Sjoerg (cp->tlf)(sp); 202425944Sjoerg break; 202525944Sjoerg } 202625944Sjoerg else 202725944Sjoerg /* TO+ event */ 202825944Sjoerg switch (sp->state[cp->protoidx]) { 202925944Sjoerg case STATE_CLOSING: 203025944Sjoerg case STATE_STOPPING: 203178064Sume sppp_cp_send(sp, cp->proto, TERM_REQ, 203278064Sume ++sp->pp_seq[cp->protoidx], 0, 0); 203370199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 203442064Sphk sp->ch[cp->protoidx]); 203525944Sjoerg break; 203625944Sjoerg case STATE_REQ_SENT: 203725944Sjoerg case STATE_ACK_RCVD: 203825944Sjoerg (cp->scr)(sp); 203925944Sjoerg /* sppp_cp_change_state() will restart the timer */ 204025944Sjoerg sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 204125944Sjoerg break; 204225944Sjoerg case STATE_ACK_SENT: 204325944Sjoerg (cp->scr)(sp); 204442064Sphk TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 204542064Sphk sp->ch[cp->protoidx]); 204625944Sjoerg break; 204725944Sjoerg } 204825944Sjoerg 204925944Sjoerg splx(s); 205025944Sjoerg} 205125944Sjoerg 205211189Sjkh/* 205325944Sjoerg * Change the state of a control protocol in the state automaton. 205425944Sjoerg * Takes care of starting/stopping the restart timer. 205511189Sjkh */ 205625944Sjoergvoid 205725944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 205825944Sjoerg{ 205925944Sjoerg sp->state[cp->protoidx] = newstate; 206025944Sjoerg 206140008Sjoerg UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 206225944Sjoerg switch (newstate) { 206325944Sjoerg case STATE_INITIAL: 206425944Sjoerg case STATE_STARTING: 206525944Sjoerg case STATE_CLOSED: 206625944Sjoerg case STATE_STOPPED: 206725944Sjoerg case STATE_OPENED: 206825944Sjoerg break; 206925944Sjoerg case STATE_CLOSING: 207025944Sjoerg case STATE_STOPPING: 207125944Sjoerg case STATE_REQ_SENT: 207225944Sjoerg case STATE_ACK_RCVD: 207325944Sjoerg case STATE_ACK_SENT: 207470199Sjhay TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 207542064Sphk sp->ch[cp->protoidx]); 207625944Sjoerg break; 207725944Sjoerg } 207825944Sjoerg} 207970199Sjhay 208070199Sjhay/* 208125944Sjoerg *--------------------------------------------------------------------------* 208225944Sjoerg * * 208325944Sjoerg * The LCP implementation. * 208425944Sjoerg * * 208525944Sjoerg *--------------------------------------------------------------------------* 208625944Sjoerg */ 208725944Sjoergstatic void 208825944Sjoergsppp_lcp_init(struct sppp *sp) 208925944Sjoerg{ 209025944Sjoerg sp->lcp.opts = (1 << LCP_OPT_MAGIC); 209125944Sjoerg sp->lcp.magic = 0; 209225944Sjoerg sp->state[IDX_LCP] = STATE_INITIAL; 209325944Sjoerg sp->fail_counter[IDX_LCP] = 0; 209478064Sume sp->pp_seq[IDX_LCP] = 0; 209578064Sume sp->pp_rseq[IDX_LCP] = 0; 209625944Sjoerg sp->lcp.protos = 0; 209725944Sjoerg sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 209830300Sjoerg 209944145Sphk /* Note that these values are relevant for all control protocols */ 210044145Sphk sp->lcp.timeout = 3 * hz; 210125944Sjoerg sp->lcp.max_terminate = 2; 210225944Sjoerg sp->lcp.max_configure = 10; 210325944Sjoerg sp->lcp.max_failure = 10; 210442065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 210530300Sjoerg callout_handle_init(&sp->ch[IDX_LCP]); 210640008Sjoerg#endif 210725944Sjoerg} 210825944Sjoerg 210925944Sjoergstatic void 211025944Sjoergsppp_lcp_up(struct sppp *sp) 211125944Sjoerg{ 211225944Sjoerg STDDCL; 211325944Sjoerg 211470199Sjhay sp->pp_alivecnt = 0; 211570199Sjhay sp->lcp.opts = (1 << LCP_OPT_MAGIC); 211670199Sjhay sp->lcp.magic = 0; 211770199Sjhay sp->lcp.protos = 0; 211870199Sjhay sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 211925944Sjoerg /* 212075321Sjoerg * If we are authenticator, negotiate LCP_AUTH 212175321Sjoerg */ 212275321Sjoerg if (sp->hisauth.proto != 0) 212375321Sjoerg sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 212475321Sjoerg else 212575321Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 212675321Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 212775321Sjoerg /* 212830300Sjoerg * If this interface is passive or dial-on-demand, and we are 212930300Sjoerg * still in Initial state, it means we've got an incoming 213030300Sjoerg * call. Activate the interface. 213125944Sjoerg */ 213225944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 213325944Sjoerg if (debug) 213425944Sjoerg log(LOG_DEBUG, 213540008Sjoerg SPP_FMT "Up event", SPP_ARGS(ifp)); 213625944Sjoerg ifp->if_flags |= IFF_RUNNING; 213730300Sjoerg if (sp->state[IDX_LCP] == STATE_INITIAL) { 213830300Sjoerg if (debug) 213969211Sphk log(-1, "(incoming call)\n"); 214030300Sjoerg sp->pp_flags |= PP_CALLIN; 214130300Sjoerg lcp.Open(sp); 214230300Sjoerg } else if (debug) 214369211Sphk log(-1, "\n"); 214488710Sjoerg } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 214588710Sjoerg (sp->state[IDX_LCP] == STATE_INITIAL)) { 214688710Sjoerg ifp->if_flags |= IFF_RUNNING; 214788710Sjoerg lcp.Open(sp); 214825944Sjoerg } 214925944Sjoerg 215025944Sjoerg sppp_up_event(&lcp, sp); 215125944Sjoerg} 215225944Sjoerg 215325944Sjoergstatic void 215425944Sjoergsppp_lcp_down(struct sppp *sp) 215525944Sjoerg{ 215625944Sjoerg STDDCL; 215725944Sjoerg 215825944Sjoerg sppp_down_event(&lcp, sp); 215925944Sjoerg 216025944Sjoerg /* 216125944Sjoerg * If this is neither a dial-on-demand nor a passive 216225944Sjoerg * interface, simulate an ``ifconfig down'' action, so the 216325944Sjoerg * administrator can force a redial by another ``ifconfig 216425944Sjoerg * up''. XXX For leased line operation, should we immediately 216525944Sjoerg * try to reopen the connection here? 216625944Sjoerg */ 216725944Sjoerg if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 216825944Sjoerg log(LOG_INFO, 216942066Sphk SPP_FMT "Down event, taking interface down.\n", 217040008Sjoerg SPP_ARGS(ifp)); 217125944Sjoerg if_down(ifp); 217225944Sjoerg } else { 217325944Sjoerg if (debug) 217425944Sjoerg log(LOG_DEBUG, 217540008Sjoerg SPP_FMT "Down event (carrier loss)\n", 217640008Sjoerg SPP_ARGS(ifp)); 217770199Sjhay sp->pp_flags &= ~PP_CALLIN; 217870199Sjhay if (sp->state[IDX_LCP] != STATE_INITIAL) 217970199Sjhay lcp.Close(sp); 218070199Sjhay ifp->if_flags &= ~IFF_RUNNING; 218125944Sjoerg } 218225944Sjoerg} 218325944Sjoerg 218425944Sjoergstatic void 218525944Sjoergsppp_lcp_open(struct sppp *sp) 218625944Sjoerg{ 218725944Sjoerg sppp_open_event(&lcp, sp); 218825944Sjoerg} 218925944Sjoerg 219025944Sjoergstatic void 219125944Sjoergsppp_lcp_close(struct sppp *sp) 219225944Sjoerg{ 219325944Sjoerg sppp_close_event(&lcp, sp); 219425944Sjoerg} 219525944Sjoerg 219625944Sjoergstatic void 219725944Sjoergsppp_lcp_TO(void *cookie) 219825944Sjoerg{ 219925944Sjoerg sppp_to_event(&lcp, (struct sppp *)cookie); 220025944Sjoerg} 220125944Sjoerg 220225944Sjoerg/* 220325944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 220425944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 220525944Sjoerg * caused action scn. (The return value is used to make the state 220625944Sjoerg * transition decision in the state automaton.) 220725944Sjoerg */ 220812820Sphkstatic int 220925944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 22104910Swollman{ 221125944Sjoerg STDDCL; 221211189Sjkh u_char *buf, *r, *p; 221325944Sjoerg int origlen, rlen; 221425944Sjoerg u_long nmagic; 221530300Sjoerg u_short authproto; 22164910Swollman 221711189Sjkh len -= 4; 221825944Sjoerg origlen = len; 221911189Sjkh buf = r = malloc (len, M_TEMP, M_NOWAIT); 222011189Sjkh if (! buf) 222111189Sjkh return (0); 22224910Swollman 222325706Sjoerg if (debug) 222440008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 222540008Sjoerg SPP_ARGS(ifp)); 222625706Sjoerg 222725944Sjoerg /* pass 1: check for things that need to be rejected */ 222811189Sjkh p = (void*) (h+1); 222911189Sjkh for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 223025944Sjoerg if (debug) 223169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 223211189Sjkh switch (*p) { 223311189Sjkh case LCP_OPT_MAGIC: 223425944Sjoerg /* Magic number. */ 223570199Sjhay if (len >= 6 && p[1] == 6) 223670199Sjhay continue; 223770199Sjhay if (debug) 223870199Sjhay log(-1, "[invalid] "); 223970199Sjhay break; 224025944Sjoerg case LCP_OPT_ASYNC_MAP: 224125944Sjoerg /* Async control character map. */ 224270199Sjhay if (len >= 6 && p[1] == 6) 224325944Sjoerg continue; 224425944Sjoerg if (debug) 224569211Sphk log(-1, "[invalid] "); 224625944Sjoerg break; 224725944Sjoerg case LCP_OPT_MRU: 224825944Sjoerg /* Maximum receive unit. */ 224925944Sjoerg if (len >= 4 && p[1] == 4) 225025944Sjoerg continue; 225125944Sjoerg if (debug) 225269211Sphk log(-1, "[invalid] "); 225325944Sjoerg break; 225430300Sjoerg case LCP_OPT_AUTH_PROTO: 225530300Sjoerg if (len < 4) { 225630300Sjoerg if (debug) 225769211Sphk log(-1, "[invalid] "); 225830300Sjoerg break; 225930300Sjoerg } 226030300Sjoerg authproto = (p[2] << 8) + p[3]; 226130300Sjoerg if (authproto == PPP_CHAP && p[1] != 5) { 226230300Sjoerg if (debug) 226369211Sphk log(-1, "[invalid chap len] "); 226430300Sjoerg break; 226530300Sjoerg } 226630300Sjoerg if (sp->myauth.proto == 0) { 226730300Sjoerg /* we are not configured to do auth */ 226830300Sjoerg if (debug) 226969211Sphk log(-1, "[not configured] "); 227030300Sjoerg break; 227130300Sjoerg } 227230300Sjoerg /* 227330300Sjoerg * Remote want us to authenticate, remember this, 227430300Sjoerg * so we stay in PHASE_AUTHENTICATE after LCP got 227530300Sjoerg * up. 227630300Sjoerg */ 227730300Sjoerg sp->pp_flags |= PP_NEEDAUTH; 227830300Sjoerg continue; 227925944Sjoerg default: 228025944Sjoerg /* Others not supported. */ 228125944Sjoerg if (debug) 228269211Sphk log(-1, "[rej] "); 228325944Sjoerg break; 228425944Sjoerg } 228525944Sjoerg /* Add the option to rejected list. */ 228625944Sjoerg bcopy (p, r, p[1]); 228725944Sjoerg r += p[1]; 228825944Sjoerg rlen += p[1]; 228925944Sjoerg } 229025944Sjoerg if (rlen) { 229125944Sjoerg if (debug) 229269211Sphk log(-1, " send conf-rej\n"); 229325944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 229425944Sjoerg return 0; 229525944Sjoerg } else if (debug) 229669211Sphk log(-1, "\n"); 229725944Sjoerg 229825944Sjoerg /* 229925944Sjoerg * pass 2: check for option values that are unacceptable and 230025944Sjoerg * thus require to be nak'ed. 230125944Sjoerg */ 230225944Sjoerg if (debug) 230340008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 230440008Sjoerg SPP_ARGS(ifp)); 230525944Sjoerg 230625944Sjoerg p = (void*) (h+1); 230725944Sjoerg len = origlen; 230825944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 230925944Sjoerg if (debug) 231069211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 231125944Sjoerg switch (*p) { 231225944Sjoerg case LCP_OPT_MAGIC: 231311189Sjkh /* Magic number -- extract. */ 231425944Sjoerg nmagic = (u_long)p[2] << 24 | 231525944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 231625944Sjoerg if (nmagic != sp->lcp.magic) { 231770199Sjhay sp->pp_loopcnt = 0; 231825706Sjoerg if (debug) 231969211Sphk log(-1, "0x%lx ", nmagic); 232011189Sjkh continue; 232111189Sjkh } 232270199Sjhay if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 232369211Sphk log(-1, "[glitch] "); 232425944Sjoerg ++sp->pp_loopcnt; 232525944Sjoerg /* 232625944Sjoerg * We negate our magic here, and NAK it. If 232725944Sjoerg * we see it later in an NAK packet, we 232825944Sjoerg * suggest a new one. 232925944Sjoerg */ 233025944Sjoerg nmagic = ~sp->lcp.magic; 233125944Sjoerg /* Gonna NAK it. */ 233225944Sjoerg p[2] = nmagic >> 24; 233325944Sjoerg p[3] = nmagic >> 16; 233425944Sjoerg p[4] = nmagic >> 8; 233525944Sjoerg p[5] = nmagic; 233611189Sjkh break; 233725944Sjoerg 233811189Sjkh case LCP_OPT_ASYNC_MAP: 233988506Sjoerg /* 234088506Sjoerg * Async control character map -- just ignore it. 234188506Sjoerg * 234288506Sjoerg * Quote from RFC 1662, chapter 6: 234388506Sjoerg * To enable this functionality, synchronous PPP 234488506Sjoerg * implementations MUST always respond to the 234588506Sjoerg * Async-Control-Character-Map Configuration 234688506Sjoerg * Option with the LCP Configure-Ack. However, 234788506Sjoerg * acceptance of the Configuration Option does 234888506Sjoerg * not imply that the synchronous implementation 234988506Sjoerg * will do any ACCM mapping. Instead, all such 235088506Sjoerg * octet mapping will be performed by the 235188506Sjoerg * asynchronous-to-synchronous converter. 235288506Sjoerg */ 235388506Sjoerg continue; 235425944Sjoerg 235511189Sjkh case LCP_OPT_MRU: 235625944Sjoerg /* 235725944Sjoerg * Maximum receive unit. Always agreeable, 235825944Sjoerg * but ignored by now. 235925944Sjoerg */ 236025944Sjoerg sp->lcp.their_mru = p[2] * 256 + p[3]; 236125706Sjoerg if (debug) 236269211Sphk log(-1, "%lu ", sp->lcp.their_mru); 236311189Sjkh continue; 236430300Sjoerg 236530300Sjoerg case LCP_OPT_AUTH_PROTO: 236630300Sjoerg authproto = (p[2] << 8) + p[3]; 236730300Sjoerg if (sp->myauth.proto != authproto) { 236830300Sjoerg /* not agreed, nak */ 236930300Sjoerg if (debug) 237069211Sphk log(-1, "[mine %s != his %s] ", 237130300Sjoerg sppp_proto_name(sp->hisauth.proto), 237230300Sjoerg sppp_proto_name(authproto)); 237330300Sjoerg p[2] = sp->myauth.proto >> 8; 237430300Sjoerg p[3] = sp->myauth.proto; 237530300Sjoerg break; 237630300Sjoerg } 237730300Sjoerg if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 237830300Sjoerg if (debug) 237969211Sphk log(-1, "[chap not MD5] "); 238039981Sjoerg p[4] = CHAP_MD5; 238130300Sjoerg break; 238230300Sjoerg } 238330300Sjoerg continue; 238411189Sjkh } 238525944Sjoerg /* Add the option to nak'ed list. */ 238625706Sjoerg bcopy (p, r, p[1]); 238725706Sjoerg r += p[1]; 238811189Sjkh rlen += p[1]; 238912436Speter } 239025706Sjoerg if (rlen) { 239170199Sjhay /* 239270199Sjhay * Local and remote magics equal -- loopback? 239370199Sjhay */ 239470199Sjhay if (sp->pp_loopcnt >= MAXALIVECNT*5) { 239570199Sjhay if (sp->pp_loopcnt == MAXALIVECNT*5) 239670199Sjhay printf (SPP_FMT "loopback\n", 239770199Sjhay SPP_ARGS(ifp)); 239870199Sjhay if (ifp->if_flags & IFF_UP) { 239970199Sjhay if_down(ifp); 240070199Sjhay sppp_qflush(&sp->pp_cpq); 240170199Sjhay /* XXX ? */ 240270199Sjhay lcp.Down(sp); 240370199Sjhay lcp.Up(sp); 240470199Sjhay } 240570199Sjhay } else if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 240628036Sjoerg if (debug) 240769211Sphk log(-1, " max_failure (%d) exceeded, " 240828036Sjoerg "send conf-rej\n", 240928036Sjoerg sp->lcp.max_failure); 241028036Sjoerg sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 241128036Sjoerg } else { 241228036Sjoerg if (debug) 241369211Sphk log(-1, " send conf-nak\n"); 241428036Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 241528036Sjoerg } 241625944Sjoerg } else { 241725944Sjoerg if (debug) 241869211Sphk log(-1, " send conf-ack\n"); 241928036Sjoerg sp->fail_counter[IDX_LCP] = 0; 242025944Sjoerg sp->pp_loopcnt = 0; 242125944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_ACK, 242225944Sjoerg h->ident, origlen, h+1); 242325944Sjoerg } 242425944Sjoerg 242511189Sjkh free (buf, M_TEMP); 242611189Sjkh return (rlen == 0); 24274910Swollman} 24284910Swollman 242925944Sjoerg/* 243025944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our 243125944Sjoerg * negotiation. 243225944Sjoerg */ 243312820Sphkstatic void 243425944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 24354910Swollman{ 243625944Sjoerg STDDCL; 243725944Sjoerg u_char *buf, *p; 24384910Swollman 243925944Sjoerg len -= 4; 244025944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 244125944Sjoerg if (!buf) 24424910Swollman return; 244325944Sjoerg 244425944Sjoerg if (debug) 244540008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 244640008Sjoerg SPP_ARGS(ifp)); 244725944Sjoerg 244825944Sjoerg p = (void*) (h+1); 244925944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 245025944Sjoerg if (debug) 245169211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 245225944Sjoerg switch (*p) { 245325944Sjoerg case LCP_OPT_MAGIC: 245425944Sjoerg /* Magic number -- can't use it, use 0 */ 245525944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 245625944Sjoerg sp->lcp.magic = 0; 245725944Sjoerg break; 245825944Sjoerg case LCP_OPT_MRU: 245925944Sjoerg /* 246025944Sjoerg * Should not be rejected anyway, since we only 246125944Sjoerg * negotiate a MRU if explicitly requested by 246225944Sjoerg * peer. 246325944Sjoerg */ 246425944Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 246525944Sjoerg break; 246630300Sjoerg case LCP_OPT_AUTH_PROTO: 246730300Sjoerg /* 246830300Sjoerg * Peer doesn't want to authenticate himself, 246930300Sjoerg * deny unless this is a dialout call, and 247030300Sjoerg * AUTHFLAG_NOCALLOUT is set. 247130300Sjoerg */ 247230300Sjoerg if ((sp->pp_flags & PP_CALLIN) == 0 && 247330300Sjoerg (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 247430300Sjoerg if (debug) 247569211Sphk log(-1, "[don't insist on auth " 247630300Sjoerg "for callout]"); 247730300Sjoerg sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 247830300Sjoerg break; 247930300Sjoerg } 248030300Sjoerg if (debug) 248169211Sphk log(-1, "[access denied]\n"); 248230300Sjoerg lcp.Close(sp); 248330300Sjoerg break; 248425944Sjoerg } 24854910Swollman } 248625944Sjoerg if (debug) 248769211Sphk log(-1, "\n"); 248825944Sjoerg free (buf, M_TEMP); 248925944Sjoerg return; 249025944Sjoerg} 249125944Sjoerg 249225944Sjoerg/* 249325944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our 249425944Sjoerg * negotiation. 249525944Sjoerg */ 249625944Sjoergstatic void 249725944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 249825944Sjoerg{ 249925944Sjoerg STDDCL; 250025944Sjoerg u_char *buf, *p; 250125944Sjoerg u_long magic; 250225944Sjoerg 250325944Sjoerg len -= 4; 250425944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 250525944Sjoerg if (!buf) 250625944Sjoerg return; 250725944Sjoerg 250825944Sjoerg if (debug) 250940008Sjoerg log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 251040008Sjoerg SPP_ARGS(ifp)); 251125944Sjoerg 251225944Sjoerg p = (void*) (h+1); 251325944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 251425706Sjoerg if (debug) 251569211Sphk log(-1, " %s ", sppp_lcp_opt_name(*p)); 251625944Sjoerg switch (*p) { 251725944Sjoerg case LCP_OPT_MAGIC: 251825944Sjoerg /* Magic number -- renegotiate */ 251925944Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 252025944Sjoerg len >= 6 && p[1] == 6) { 252125944Sjoerg magic = (u_long)p[2] << 24 | 252225944Sjoerg (u_long)p[3] << 16 | p[4] << 8 | p[5]; 252325944Sjoerg /* 252425944Sjoerg * If the remote magic is our negated one, 252525944Sjoerg * this looks like a loopback problem. 252625944Sjoerg * Suggest a new magic to make sure. 252725944Sjoerg */ 252825944Sjoerg if (magic == ~sp->lcp.magic) { 252925944Sjoerg if (debug) 253069211Sphk log(-1, "magic glitch "); 253142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 253235064Sphk sp->lcp.magic = random(); 253340008Sjoerg#else 253440008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 253540008Sjoerg#endif 253625944Sjoerg } else { 253725944Sjoerg sp->lcp.magic = magic; 253825944Sjoerg if (debug) 253969211Sphk log(-1, "%lu ", magic); 254025944Sjoerg } 254125944Sjoerg } 254225944Sjoerg break; 254325944Sjoerg case LCP_OPT_MRU: 254425944Sjoerg /* 254525944Sjoerg * Peer wants to advise us to negotiate an MRU. 254625944Sjoerg * Agree on it if it's reasonable, or use 254725944Sjoerg * default otherwise. 254825944Sjoerg */ 254925944Sjoerg if (len >= 4 && p[1] == 4) { 255025944Sjoerg u_int mru = p[2] * 256 + p[3]; 255125944Sjoerg if (debug) 255269211Sphk log(-1, "%d ", mru); 255325944Sjoerg if (mru < PP_MTU || mru > PP_MAX_MRU) 255425944Sjoerg mru = PP_MTU; 255525944Sjoerg sp->lcp.mru = mru; 255625944Sjoerg sp->lcp.opts |= (1 << LCP_OPT_MRU); 255725944Sjoerg } 255825944Sjoerg break; 255930300Sjoerg case LCP_OPT_AUTH_PROTO: 256030300Sjoerg /* 256130300Sjoerg * Peer doesn't like our authentication method, 256230300Sjoerg * deny. 256330300Sjoerg */ 256430300Sjoerg if (debug) 256569211Sphk log(-1, "[access denied]\n"); 256630300Sjoerg lcp.Close(sp); 256730300Sjoerg break; 25684910Swollman } 256925944Sjoerg } 257025944Sjoerg if (debug) 257169211Sphk log(-1, "\n"); 257225944Sjoerg free (buf, M_TEMP); 257325944Sjoerg return; 257425944Sjoerg} 257511189Sjkh 257625944Sjoergstatic void 257725944Sjoergsppp_lcp_tlu(struct sppp *sp) 257825944Sjoerg{ 257942066Sphk STDDCL; 258025944Sjoerg int i; 258125944Sjoerg u_long mask; 258225944Sjoerg 258325944Sjoerg /* XXX ? */ 258425944Sjoerg if (! (ifp->if_flags & IFF_UP) && 258525944Sjoerg (ifp->if_flags & IFF_RUNNING)) { 258625944Sjoerg /* Coming out of loopback mode. */ 258725944Sjoerg if_up(ifp); 258840008Sjoerg printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 258925944Sjoerg } 259025944Sjoerg 259125944Sjoerg for (i = 0; i < IDX_COUNT; i++) 259225944Sjoerg if ((cps[i])->flags & CP_QUAL) 259325944Sjoerg (cps[i])->Open(sp); 259425944Sjoerg 259530300Sjoerg if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 259630300Sjoerg (sp->pp_flags & PP_NEEDAUTH) != 0) 259725944Sjoerg sp->pp_phase = PHASE_AUTHENTICATE; 259825944Sjoerg else 259925944Sjoerg sp->pp_phase = PHASE_NETWORK; 260025944Sjoerg 260142066Sphk if (debug) 260242066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 260342066Sphk sppp_phase_name(sp->pp_phase)); 260425944Sjoerg 260530300Sjoerg /* 260630300Sjoerg * Open all authentication protocols. This is even required 260730300Sjoerg * if we already proceeded to network phase, since it might be 260830300Sjoerg * that remote wants us to authenticate, so we might have to 260930300Sjoerg * send a PAP request. Undesired authentication protocols 261030300Sjoerg * don't do anything when they get an Open event. 261130300Sjoerg */ 261230300Sjoerg for (i = 0; i < IDX_COUNT; i++) 261330300Sjoerg if ((cps[i])->flags & CP_AUTH) 261430300Sjoerg (cps[i])->Open(sp); 261530300Sjoerg 261630300Sjoerg if (sp->pp_phase == PHASE_NETWORK) { 261725944Sjoerg /* Notify all NCPs. */ 261825944Sjoerg for (i = 0; i < IDX_COUNT; i++) 261925944Sjoerg if ((cps[i])->flags & CP_NCP) 262025944Sjoerg (cps[i])->Open(sp); 262125944Sjoerg } 262225944Sjoerg 262325944Sjoerg /* Send Up events to all started protos. */ 262425944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 262588706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 262625944Sjoerg (cps[i])->Up(sp); 262725944Sjoerg 262842104Sphk /* notify low-level driver of state change */ 262942104Sphk if (sp->pp_chg) 263042104Sphk sp->pp_chg(sp, (int)sp->pp_phase); 263142104Sphk 263225944Sjoerg if (sp->pp_phase == PHASE_NETWORK) 263325944Sjoerg /* if no NCP is starting, close down */ 263430300Sjoerg sppp_lcp_check_and_close(sp); 263525944Sjoerg} 263625944Sjoerg 263725944Sjoergstatic void 263825944Sjoergsppp_lcp_tld(struct sppp *sp) 263925944Sjoerg{ 264042066Sphk STDDCL; 264125944Sjoerg int i; 264225944Sjoerg u_long mask; 264325944Sjoerg 264425944Sjoerg sp->pp_phase = PHASE_TERMINATE; 264525944Sjoerg 264642066Sphk if (debug) 264742066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 264842066Sphk sppp_phase_name(sp->pp_phase)); 264925944Sjoerg 265025944Sjoerg /* 265125944Sjoerg * Take upper layers down. We send the Down event first and 265225944Sjoerg * the Close second to prevent the upper layers from sending 265325944Sjoerg * ``a flurry of terminate-request packets'', as the RFC 265425944Sjoerg * describes it. 265525944Sjoerg */ 265625944Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 265788706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 265825944Sjoerg (cps[i])->Down(sp); 265925944Sjoerg (cps[i])->Close(sp); 266025944Sjoerg } 266125944Sjoerg} 266225944Sjoerg 266325944Sjoergstatic void 266425944Sjoergsppp_lcp_tls(struct sppp *sp) 266525944Sjoerg{ 266642066Sphk STDDCL; 266725944Sjoerg 266825944Sjoerg sp->pp_phase = PHASE_ESTABLISH; 266925944Sjoerg 267042066Sphk if (debug) 267142066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 267242066Sphk sppp_phase_name(sp->pp_phase)); 267325944Sjoerg 267425944Sjoerg /* Notify lower layer if desired. */ 267525944Sjoerg if (sp->pp_tls) 267625944Sjoerg (sp->pp_tls)(sp); 267741881Sphk else 267841881Sphk (sp->pp_up)(sp); 267925944Sjoerg} 268025944Sjoerg 268125944Sjoergstatic void 268225944Sjoergsppp_lcp_tlf(struct sppp *sp) 268325944Sjoerg{ 268442066Sphk STDDCL; 268525944Sjoerg 268625944Sjoerg sp->pp_phase = PHASE_DEAD; 268742066Sphk if (debug) 268842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 268942066Sphk sppp_phase_name(sp->pp_phase)); 269025944Sjoerg 269125944Sjoerg /* Notify lower layer if desired. */ 269225944Sjoerg if (sp->pp_tlf) 269325944Sjoerg (sp->pp_tlf)(sp); 269441881Sphk else 269541881Sphk (sp->pp_down)(sp); 269625944Sjoerg} 269725944Sjoerg 269825944Sjoergstatic void 269925944Sjoergsppp_lcp_scr(struct sppp *sp) 270025944Sjoerg{ 270130300Sjoerg char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 270225944Sjoerg int i = 0; 270330300Sjoerg u_short authproto; 270425944Sjoerg 270525944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 270625944Sjoerg if (! sp->lcp.magic) 270742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 270835064Sphk sp->lcp.magic = random(); 270940008Sjoerg#else 271040008Sjoerg sp->lcp.magic = time.tv_sec + time.tv_usec; 271140008Sjoerg#endif 271225944Sjoerg opt[i++] = LCP_OPT_MAGIC; 271325944Sjoerg opt[i++] = 6; 271425944Sjoerg opt[i++] = sp->lcp.magic >> 24; 271525944Sjoerg opt[i++] = sp->lcp.magic >> 16; 271625944Sjoerg opt[i++] = sp->lcp.magic >> 8; 271725944Sjoerg opt[i++] = sp->lcp.magic; 271825944Sjoerg } 271925944Sjoerg 272025944Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 272125944Sjoerg opt[i++] = LCP_OPT_MRU; 272225944Sjoerg opt[i++] = 4; 272325944Sjoerg opt[i++] = sp->lcp.mru >> 8; 272425944Sjoerg opt[i++] = sp->lcp.mru; 272525944Sjoerg } 272625944Sjoerg 272730300Sjoerg if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 272830300Sjoerg authproto = sp->hisauth.proto; 272930300Sjoerg opt[i++] = LCP_OPT_AUTH_PROTO; 273030300Sjoerg opt[i++] = authproto == PPP_CHAP? 5: 4; 273130300Sjoerg opt[i++] = authproto >> 8; 273230300Sjoerg opt[i++] = authproto; 273330300Sjoerg if (authproto == PPP_CHAP) 273430300Sjoerg opt[i++] = CHAP_MD5; 273530300Sjoerg } 273630300Sjoerg 273778064Sume sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 273825944Sjoerg sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 273925944Sjoerg} 274025944Sjoerg 274125944Sjoerg/* 274230300Sjoerg * Check the open NCPs, return true if at least one NCP is open. 274330300Sjoerg */ 274430300Sjoergstatic int 274530300Sjoergsppp_ncp_check(struct sppp *sp) 274630300Sjoerg{ 274730300Sjoerg int i, mask; 274830300Sjoerg 274930300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 275088706Sjoerg if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 275130300Sjoerg return 1; 275230300Sjoerg return 0; 275330300Sjoerg} 275430300Sjoerg 275530300Sjoerg/* 275625944Sjoerg * Re-check the open NCPs and see if we should terminate the link. 275725944Sjoerg * Called by the NCPs during their tlf action handling. 275825944Sjoerg */ 275925944Sjoergstatic void 276030300Sjoergsppp_lcp_check_and_close(struct sppp *sp) 276125944Sjoerg{ 276225944Sjoerg 276330300Sjoerg if (sp->pp_phase < PHASE_NETWORK) 276430300Sjoerg /* don't bother, we are already going down */ 276530300Sjoerg return; 276630300Sjoerg 276730300Sjoerg if (sppp_ncp_check(sp)) 276830300Sjoerg return; 276930300Sjoerg 277025944Sjoerg lcp.Close(sp); 277125944Sjoerg} 277270199Sjhay 277370199Sjhay/* 277425944Sjoerg *--------------------------------------------------------------------------* 277525944Sjoerg * * 277625944Sjoerg * The IPCP implementation. * 277725944Sjoerg * * 277825944Sjoerg *--------------------------------------------------------------------------* 277925944Sjoerg */ 278025944Sjoerg 278125944Sjoergstatic void 278225944Sjoergsppp_ipcp_init(struct sppp *sp) 278325944Sjoerg{ 278425944Sjoerg sp->ipcp.opts = 0; 278525944Sjoerg sp->ipcp.flags = 0; 278625944Sjoerg sp->state[IDX_IPCP] = STATE_INITIAL; 278725944Sjoerg sp->fail_counter[IDX_IPCP] = 0; 278878064Sume sp->pp_seq[IDX_IPCP] = 0; 278978064Sume sp->pp_rseq[IDX_IPCP] = 0; 279042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 279129681Sgibbs callout_handle_init(&sp->ch[IDX_IPCP]); 279240008Sjoerg#endif 279325944Sjoerg} 279425944Sjoerg 279525944Sjoergstatic void 279625944Sjoergsppp_ipcp_up(struct sppp *sp) 279725944Sjoerg{ 279825944Sjoerg sppp_up_event(&ipcp, sp); 279925944Sjoerg} 280025944Sjoerg 280125944Sjoergstatic void 280225944Sjoergsppp_ipcp_down(struct sppp *sp) 280325944Sjoerg{ 280425944Sjoerg sppp_down_event(&ipcp, sp); 280525944Sjoerg} 280625944Sjoerg 280725944Sjoergstatic void 280825944Sjoergsppp_ipcp_open(struct sppp *sp) 280925944Sjoerg{ 281025944Sjoerg STDDCL; 281125944Sjoerg u_long myaddr, hisaddr; 281225944Sjoerg 281388534Sjoerg sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 281488534Sjoerg IPCP_MYADDR_DYN | IPCP_VJ); 281588700Sjoerg sp->ipcp.opts = 0; 281642104Sphk 281730300Sjoerg sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 281825944Sjoerg /* 281925944Sjoerg * If we don't have his address, this probably means our 282025944Sjoerg * interface doesn't want to talk IP at all. (This could 282125944Sjoerg * be the case if somebody wants to speak only IPX, for 282225944Sjoerg * example.) Don't open IPCP in this case. 282325944Sjoerg */ 282425944Sjoerg if (hisaddr == 0L) { 282525944Sjoerg /* XXX this message should go away */ 282625944Sjoerg if (debug) 282740008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 282840008Sjoerg SPP_ARGS(ifp)); 282925944Sjoerg return; 283025944Sjoerg } 283125944Sjoerg if (myaddr == 0L) { 283225944Sjoerg /* 283325944Sjoerg * I don't have an assigned address, so i need to 283425944Sjoerg * negotiate my address. 283525944Sjoerg */ 283625944Sjoerg sp->ipcp.flags |= IPCP_MYADDR_DYN; 283725944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 283842104Sphk } else 283942104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 284088534Sjoerg if (sp->enable_vj) { 284188534Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 284288534Sjoerg sp->ipcp.max_state = MAX_STATES - 1; 284388534Sjoerg sp->ipcp.compress_cid = 1; 284488534Sjoerg } 284525944Sjoerg sppp_open_event(&ipcp, sp); 284625944Sjoerg} 284725944Sjoerg 284825944Sjoergstatic void 284925944Sjoergsppp_ipcp_close(struct sppp *sp) 285025944Sjoerg{ 285125944Sjoerg sppp_close_event(&ipcp, sp); 285225944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) 285325944Sjoerg /* 285425944Sjoerg * My address was dynamic, clear it again. 285525944Sjoerg */ 285625944Sjoerg sppp_set_ip_addr(sp, 0L); 285725944Sjoerg} 285825944Sjoerg 285925944Sjoergstatic void 286025944Sjoergsppp_ipcp_TO(void *cookie) 286125944Sjoerg{ 286225944Sjoerg sppp_to_event(&ipcp, (struct sppp *)cookie); 286325944Sjoerg} 286425944Sjoerg 286525944Sjoerg/* 286625944Sjoerg * Analyze a configure request. Return true if it was agreeable, and 286725944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and 286825944Sjoerg * caused action scn. (The return value is used to make the state 286925944Sjoerg * transition decision in the state automaton.) 287025944Sjoerg */ 287125944Sjoergstatic int 287225944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 287325944Sjoerg{ 287425944Sjoerg u_char *buf, *r, *p; 287525944Sjoerg struct ifnet *ifp = &sp->pp_if; 287625944Sjoerg int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 287725944Sjoerg u_long hisaddr, desiredaddr; 287842104Sphk int gotmyaddr = 0; 287988534Sjoerg int desiredcomp; 288025944Sjoerg 288125944Sjoerg len -= 4; 288225944Sjoerg origlen = len; 288325944Sjoerg /* 288425944Sjoerg * Make sure to allocate a buf that can at least hold a 288525944Sjoerg * conf-nak with an `address' option. We might need it below. 288625944Sjoerg */ 288725944Sjoerg buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 288825944Sjoerg if (! buf) 288925944Sjoerg return (0); 289025944Sjoerg 289125944Sjoerg /* pass 1: see if we can recognize them */ 289225944Sjoerg if (debug) 289340008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 289440008Sjoerg SPP_ARGS(ifp)); 289525944Sjoerg p = (void*) (h+1); 289625944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 289725944Sjoerg if (debug) 289869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 289925944Sjoerg switch (*p) { 290088534Sjoerg case IPCP_OPT_COMPRESSION: 290188534Sjoerg if (!sp->enable_vj) { 290288534Sjoerg /* VJ compression administratively disabled */ 290388534Sjoerg if (debug) 290488534Sjoerg log(-1, "[locally disabled] "); 290588534Sjoerg break; 290688534Sjoerg } 290788534Sjoerg /* 290888534Sjoerg * In theory, we should only conf-rej an 290988534Sjoerg * option that is shorter than RFC 1618 291088534Sjoerg * requires (i.e. < 4), and should conf-nak 291188534Sjoerg * anything else that is not VJ. However, 291288534Sjoerg * since our algorithm always uses the 291388534Sjoerg * original option to NAK it with new values, 291488534Sjoerg * things would become more complicated. In 291588534Sjoerg * pratice, the only commonly implemented IP 291688534Sjoerg * compression option is VJ anyway, so the 291788534Sjoerg * difference is negligible. 291888534Sjoerg */ 291988534Sjoerg if (len >= 6 && p[1] == 6) { 292088534Sjoerg /* 292188534Sjoerg * correctly formed compression option 292288534Sjoerg * that could be VJ compression 292388534Sjoerg */ 292488534Sjoerg continue; 292588534Sjoerg } 292688534Sjoerg if (debug) 292788534Sjoerg log(-1, 292888534Sjoerg "optlen %d [invalid/unsupported] ", 292988534Sjoerg p[1]); 293088534Sjoerg break; 293125944Sjoerg case IPCP_OPT_ADDRESS: 293225944Sjoerg if (len >= 6 && p[1] == 6) { 293325944Sjoerg /* correctly formed address option */ 293425944Sjoerg continue; 293525944Sjoerg } 293625706Sjoerg if (debug) 293769211Sphk log(-1, "[invalid] "); 293811189Sjkh break; 293925944Sjoerg default: 294025944Sjoerg /* Others not supported. */ 294125944Sjoerg if (debug) 294269211Sphk log(-1, "[rej] "); 29434910Swollman break; 29444910Swollman } 294525944Sjoerg /* Add the option to rejected list. */ 294625944Sjoerg bcopy (p, r, p[1]); 294725944Sjoerg r += p[1]; 294825944Sjoerg rlen += p[1]; 294925944Sjoerg } 295025944Sjoerg if (rlen) { 295125944Sjoerg if (debug) 295269211Sphk log(-1, " send conf-rej\n"); 295325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 295425944Sjoerg return 0; 295525944Sjoerg } else if (debug) 295669211Sphk log(-1, "\n"); 295725944Sjoerg 295825944Sjoerg /* pass 2: parse option values */ 295930300Sjoerg sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 296025944Sjoerg if (debug) 296140008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 296240008Sjoerg SPP_ARGS(ifp)); 296325944Sjoerg p = (void*) (h+1); 296425944Sjoerg len = origlen; 296525944Sjoerg for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 296625944Sjoerg if (debug) 296769211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 296825944Sjoerg switch (*p) { 296988534Sjoerg case IPCP_OPT_COMPRESSION: 297088534Sjoerg desiredcomp = p[2] << 8 | p[3]; 297188534Sjoerg /* We only support VJ */ 297288534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 297388534Sjoerg if (debug) 297488534Sjoerg log(-1, "VJ [ack] "); 297588534Sjoerg sp->ipcp.flags |= IPCP_VJ; 297688599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 297788534Sjoerg sp->ipcp.max_state = p[4]; 297888534Sjoerg sp->ipcp.compress_cid = p[5]; 297988534Sjoerg continue; 298088534Sjoerg } 298188534Sjoerg if (debug) 298288534Sjoerg log(-1, 298388534Sjoerg "compproto %#04x [not supported] ", 298488534Sjoerg desiredcomp); 298588534Sjoerg p[2] = IPCP_COMP_VJ >> 8; 298688534Sjoerg p[3] = IPCP_COMP_VJ; 298788534Sjoerg p[4] = sp->ipcp.max_state; 298888534Sjoerg p[5] = sp->ipcp.compress_cid; 298988534Sjoerg break; 299025944Sjoerg case IPCP_OPT_ADDRESS: 299142104Sphk /* This is the address he wants in his end */ 299225944Sjoerg desiredaddr = p[2] << 24 | p[3] << 16 | 299325944Sjoerg p[4] << 8 | p[5]; 299433928Sphk if (desiredaddr == hisaddr || 299588702Sjoerg (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 299625944Sjoerg /* 299725944Sjoerg * Peer's address is same as our value, 299888702Sjoerg * or we have set it to 0.0.0.* to 299933928Sphk * indicate that we do not really care, 300025944Sjoerg * this is agreeable. Gonna conf-ack 300125944Sjoerg * it. 300225944Sjoerg */ 300325944Sjoerg if (debug) 300469211Sphk log(-1, "%s [ack] ", 300542104Sphk sppp_dotted_quad(hisaddr)); 300625944Sjoerg /* record that we've seen it already */ 300725944Sjoerg sp->ipcp.flags |= IPCP_HISADDR_SEEN; 300825944Sjoerg continue; 300925944Sjoerg } 301025944Sjoerg /* 301125944Sjoerg * The address wasn't agreeable. This is either 301225944Sjoerg * he sent us 0.0.0.0, asking to assign him an 301325944Sjoerg * address, or he send us another address not 301425944Sjoerg * matching our value. Either case, we gonna 301525944Sjoerg * conf-nak it with our value. 301642104Sphk * XXX: we should "rej" if hisaddr == 0 301725944Sjoerg */ 301825944Sjoerg if (debug) { 301925944Sjoerg if (desiredaddr == 0) 302069211Sphk log(-1, "[addr requested] "); 302125944Sjoerg else 302269211Sphk log(-1, "%s [not agreed] ", 302342104Sphk sppp_dotted_quad(desiredaddr)); 302425944Sjoerg 302525944Sjoerg } 302644235Sphk p[2] = hisaddr >> 24; 302744235Sphk p[3] = hisaddr >> 16; 302844235Sphk p[4] = hisaddr >> 8; 302944235Sphk p[5] = hisaddr; 303011189Sjkh break; 303125706Sjoerg } 303225944Sjoerg /* Add the option to nak'ed list. */ 303325944Sjoerg bcopy (p, r, p[1]); 303425944Sjoerg r += p[1]; 303525944Sjoerg rlen += p[1]; 303625944Sjoerg } 303725944Sjoerg 303825944Sjoerg /* 303925944Sjoerg * If we are about to conf-ack the request, but haven't seen 304025944Sjoerg * his address so far, gonna conf-nak it instead, with the 304125944Sjoerg * `address' option present and our idea of his address being 304225944Sjoerg * filled in there, to request negotiation of both addresses. 304325944Sjoerg * 304425944Sjoerg * XXX This can result in an endless req - nak loop if peer 304525944Sjoerg * doesn't want to send us his address. Q: What should we do 304625944Sjoerg * about it? XXX A: implement the max-failure counter. 304725944Sjoerg */ 304842104Sphk if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 304925944Sjoerg buf[0] = IPCP_OPT_ADDRESS; 305025944Sjoerg buf[1] = 6; 305125944Sjoerg buf[2] = hisaddr >> 24; 305225944Sjoerg buf[3] = hisaddr >> 16; 305325944Sjoerg buf[4] = hisaddr >> 8; 305425944Sjoerg buf[5] = hisaddr; 305525944Sjoerg rlen = 6; 305625706Sjoerg if (debug) 305769211Sphk log(-1, "still need hisaddr "); 305825944Sjoerg } 305925944Sjoerg 306025944Sjoerg if (rlen) { 306125706Sjoerg if (debug) 306269211Sphk log(-1, " send conf-nak\n"); 306325944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 306425944Sjoerg } else { 306525706Sjoerg if (debug) 306669211Sphk log(-1, " send conf-ack\n"); 306725944Sjoerg sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 306825944Sjoerg h->ident, origlen, h+1); 306925944Sjoerg } 307025944Sjoerg 307125944Sjoerg free (buf, M_TEMP); 307225944Sjoerg return (rlen == 0); 307325944Sjoerg} 307425944Sjoerg 307525944Sjoerg/* 307625944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our 307725944Sjoerg * negotiation. 307825944Sjoerg */ 307925944Sjoergstatic void 308025944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 308125944Sjoerg{ 308225944Sjoerg u_char *buf, *p; 308325944Sjoerg struct ifnet *ifp = &sp->pp_if; 308425944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 308525944Sjoerg 308625944Sjoerg len -= 4; 308725944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 308825944Sjoerg if (!buf) 308925944Sjoerg return; 309025944Sjoerg 309125944Sjoerg if (debug) 309240008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 309340008Sjoerg SPP_ARGS(ifp)); 309425944Sjoerg 309525944Sjoerg p = (void*) (h+1); 309625944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 309725706Sjoerg if (debug) 309869211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 309925944Sjoerg switch (*p) { 310088534Sjoerg case IPCP_OPT_COMPRESSION: 310188534Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 310288534Sjoerg break; 310325944Sjoerg case IPCP_OPT_ADDRESS: 310425944Sjoerg /* 310525944Sjoerg * Peer doesn't grok address option. This is 310625944Sjoerg * bad. XXX Should we better give up here? 310742104Sphk * XXX We could try old "addresses" option... 310825944Sjoerg */ 310925944Sjoerg sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 311025944Sjoerg break; 311125944Sjoerg } 31124910Swollman } 311325944Sjoerg if (debug) 311469211Sphk log(-1, "\n"); 311525944Sjoerg free (buf, M_TEMP); 311625944Sjoerg return; 31174910Swollman} 31184910Swollman 311925944Sjoerg/* 312025944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our 312125944Sjoerg * negotiation. 312225944Sjoerg */ 312312820Sphkstatic void 312425944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 31254910Swollman{ 312625944Sjoerg u_char *buf, *p; 312725944Sjoerg struct ifnet *ifp = &sp->pp_if; 312825944Sjoerg int debug = ifp->if_flags & IFF_DEBUG; 312988534Sjoerg int desiredcomp; 313025944Sjoerg u_long wantaddr; 31314910Swollman 313225944Sjoerg len -= 4; 313325944Sjoerg buf = malloc (len, M_TEMP, M_NOWAIT); 313425944Sjoerg if (!buf) 313525944Sjoerg return; 313625944Sjoerg 313725944Sjoerg if (debug) 313840008Sjoerg log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 313940008Sjoerg SPP_ARGS(ifp)); 314025944Sjoerg 314125944Sjoerg p = (void*) (h+1); 314225944Sjoerg for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 314325944Sjoerg if (debug) 314469211Sphk log(-1, " %s ", sppp_ipcp_opt_name(*p)); 314525944Sjoerg switch (*p) { 314688534Sjoerg case IPCP_OPT_COMPRESSION: 314788534Sjoerg if (len >= 6 && p[1] == 6) { 314888534Sjoerg desiredcomp = p[2] << 8 | p[3]; 314988534Sjoerg if (debug) 315088534Sjoerg log(-1, "[wantcomp %#04x] ", 315188534Sjoerg desiredcomp); 315288534Sjoerg if (desiredcomp == IPCP_COMP_VJ) { 315388599Sjoerg sl_compress_init(sp->pp_comp, p[4]); 315488534Sjoerg sp->ipcp.max_state = p[4]; 315588534Sjoerg sp->ipcp.compress_cid = p[5]; 315688534Sjoerg if (debug) 315788534Sjoerg log(-1, "[agree] "); 315888534Sjoerg } else 315988534Sjoerg sp->ipcp.opts &= 316088534Sjoerg ~(1 << IPCP_OPT_COMPRESSION); 316188534Sjoerg } 316288534Sjoerg break; 316325944Sjoerg case IPCP_OPT_ADDRESS: 316425944Sjoerg /* 316525944Sjoerg * Peer doesn't like our local IP address. See 316625944Sjoerg * if we can do something for him. We'll drop 316725944Sjoerg * him our address then. 316825944Sjoerg */ 316925944Sjoerg if (len >= 6 && p[1] == 6) { 317025944Sjoerg wantaddr = p[2] << 24 | p[3] << 16 | 317125944Sjoerg p[4] << 8 | p[5]; 317225944Sjoerg sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 317325944Sjoerg if (debug) 317469211Sphk log(-1, "[wantaddr %s] ", 317530300Sjoerg sppp_dotted_quad(wantaddr)); 317625944Sjoerg /* 317725944Sjoerg * When doing dynamic address assignment, 317825944Sjoerg * we accept his offer. Otherwise, we 317925944Sjoerg * ignore it and thus continue to negotiate 318025944Sjoerg * our already existing value. 318142104Sphk * XXX: Bogus, if he said no once, he'll 318242104Sphk * just say no again, might as well die. 318325944Sjoerg */ 318425944Sjoerg if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 318525944Sjoerg sppp_set_ip_addr(sp, wantaddr); 318625944Sjoerg if (debug) 318769211Sphk log(-1, "[agree] "); 318842104Sphk sp->ipcp.flags |= IPCP_MYADDR_SEEN; 318925944Sjoerg } 319025944Sjoerg } 319125944Sjoerg break; 319225944Sjoerg } 319325944Sjoerg } 319425944Sjoerg if (debug) 319569211Sphk log(-1, "\n"); 319625944Sjoerg free (buf, M_TEMP); 319725944Sjoerg return; 31984910Swollman} 31994910Swollman 320012820Sphkstatic void 320125944Sjoergsppp_ipcp_tlu(struct sppp *sp) 32024910Swollman{ 320342104Sphk /* we are up - notify isdn daemon */ 320442104Sphk if (sp->pp_con) 320542104Sphk sp->pp_con(sp); 32064910Swollman} 32074910Swollman 320825944Sjoergstatic void 320925944Sjoergsppp_ipcp_tld(struct sppp *sp) 321025944Sjoerg{ 321125944Sjoerg} 321225944Sjoerg 321325944Sjoergstatic void 321425944Sjoergsppp_ipcp_tls(struct sppp *sp) 321525944Sjoerg{ 321625944Sjoerg /* indicate to LCP that it must stay alive */ 321725944Sjoerg sp->lcp.protos |= (1 << IDX_IPCP); 321825944Sjoerg} 321925944Sjoerg 322025944Sjoergstatic void 322125944Sjoergsppp_ipcp_tlf(struct sppp *sp) 322225944Sjoerg{ 322325944Sjoerg /* we no longer need LCP */ 322425944Sjoerg sp->lcp.protos &= ~(1 << IDX_IPCP); 322530300Sjoerg sppp_lcp_check_and_close(sp); 322625944Sjoerg} 322725944Sjoerg 322825944Sjoergstatic void 322925944Sjoergsppp_ipcp_scr(struct sppp *sp) 323025944Sjoerg{ 323125944Sjoerg char opt[6 /* compression */ + 6 /* address */]; 323225944Sjoerg u_long ouraddr; 323325944Sjoerg int i = 0; 323425944Sjoerg 323588534Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 323688534Sjoerg opt[i++] = IPCP_OPT_COMPRESSION; 323788534Sjoerg opt[i++] = 6; 323888534Sjoerg opt[i++] = IPCP_COMP_VJ >> 8; 323988534Sjoerg opt[i++] = IPCP_COMP_VJ; 324088534Sjoerg opt[i++] = sp->ipcp.max_state; 324188534Sjoerg opt[i++] = sp->ipcp.compress_cid; 324288534Sjoerg } 324325944Sjoerg if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 324430300Sjoerg sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 324525944Sjoerg opt[i++] = IPCP_OPT_ADDRESS; 324625944Sjoerg opt[i++] = 6; 324725944Sjoerg opt[i++] = ouraddr >> 24; 324825944Sjoerg opt[i++] = ouraddr >> 16; 324925944Sjoerg opt[i++] = ouraddr >> 8; 325025944Sjoerg opt[i++] = ouraddr; 325125944Sjoerg } 325225944Sjoerg 325378064Sume sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 325425944Sjoerg sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 325525944Sjoerg} 325625944Sjoerg 325770199Sjhay/* 325830300Sjoerg *--------------------------------------------------------------------------* 325930300Sjoerg * * 326078064Sume * The IPv6CP implementation. * 326178064Sume * * 326278064Sume *--------------------------------------------------------------------------* 326378064Sume */ 326478064Sume 326578064Sume#ifdef INET6 326678064Sumestatic void 326778064Sumesppp_ipv6cp_init(struct sppp *sp) 326878064Sume{ 326978064Sume sp->ipv6cp.opts = 0; 327078064Sume sp->ipv6cp.flags = 0; 327178064Sume sp->state[IDX_IPV6CP] = STATE_INITIAL; 327278064Sume sp->fail_counter[IDX_IPV6CP] = 0; 327378064Sume sp->pp_seq[IDX_IPV6CP] = 0; 327478064Sume sp->pp_rseq[IDX_IPV6CP] = 0; 327578064Sume#if defined(__NetBSD__) 327678064Sume callout_init(&sp->ch[IDX_IPV6CP]); 327778064Sume#endif 327878064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 327978064Sume callout_handle_init(&sp->ch[IDX_IPV6CP]); 328078064Sume#endif 328178064Sume} 328278064Sume 328378064Sumestatic void 328478064Sumesppp_ipv6cp_up(struct sppp *sp) 328578064Sume{ 328678064Sume sppp_up_event(&ipv6cp, sp); 328778064Sume} 328878064Sume 328978064Sumestatic void 329078064Sumesppp_ipv6cp_down(struct sppp *sp) 329178064Sume{ 329278064Sume sppp_down_event(&ipv6cp, sp); 329378064Sume} 329478064Sume 329578064Sumestatic void 329678064Sumesppp_ipv6cp_open(struct sppp *sp) 329778064Sume{ 329878064Sume STDDCL; 329978064Sume struct in6_addr myaddr, hisaddr; 330078064Sume 330178064Sume#ifdef IPV6CP_MYIFID_DYN 330278064Sume sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 330378064Sume#else 330478064Sume sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 330578064Sume#endif 330678064Sume 330778064Sume sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 330878064Sume /* 330978064Sume * If we don't have our address, this probably means our 331078064Sume * interface doesn't want to talk IPv6 at all. (This could 331178064Sume * be the case if somebody wants to speak only IPX, for 331278064Sume * example.) Don't open IPv6CP in this case. 331378064Sume */ 331478064Sume if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 331578064Sume /* XXX this message should go away */ 331678064Sume if (debug) 331778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 331878064Sume SPP_ARGS(ifp)); 331978064Sume return; 332078064Sume } 332178064Sume 332278064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 332378064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 332478064Sume sppp_open_event(&ipv6cp, sp); 332578064Sume} 332678064Sume 332778064Sumestatic void 332878064Sumesppp_ipv6cp_close(struct sppp *sp) 332978064Sume{ 333078064Sume sppp_close_event(&ipv6cp, sp); 333178064Sume} 333278064Sume 333378064Sumestatic void 333478064Sumesppp_ipv6cp_TO(void *cookie) 333578064Sume{ 333678064Sume sppp_to_event(&ipv6cp, (struct sppp *)cookie); 333778064Sume} 333878064Sume 333978064Sume/* 334078064Sume * Analyze a configure request. Return true if it was agreeable, and 334178064Sume * caused action sca, false if it has been rejected or nak'ed, and 334278064Sume * caused action scn. (The return value is used to make the state 334378064Sume * transition decision in the state automaton.) 334478064Sume */ 334578064Sumestatic int 334678064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 334778064Sume{ 334878064Sume u_char *buf, *r, *p; 334978064Sume struct ifnet *ifp = &sp->pp_if; 335078064Sume int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 335178064Sume struct in6_addr myaddr, desiredaddr, suggestaddr; 335278064Sume int ifidcount; 335378064Sume int type; 335478064Sume int collision, nohisaddr; 335578064Sume 335678064Sume len -= 4; 335778064Sume origlen = len; 335878064Sume /* 335978064Sume * Make sure to allocate a buf that can at least hold a 336078064Sume * conf-nak with an `address' option. We might need it below. 336178064Sume */ 336278064Sume buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 336378064Sume if (! buf) 336478064Sume return (0); 336578064Sume 336678064Sume /* pass 1: see if we can recognize them */ 336778064Sume if (debug) 336878064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 336978064Sume SPP_ARGS(ifp)); 337078064Sume p = (void*) (h+1); 337178064Sume ifidcount = 0; 337278064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 337378064Sume if (debug) 337478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 337578064Sume switch (*p) { 337678064Sume case IPV6CP_OPT_IFID: 337778064Sume if (len >= 10 && p[1] == 10 && ifidcount == 0) { 337878064Sume /* correctly formed address option */ 337978064Sume ifidcount++; 338078064Sume continue; 338178064Sume } 338278064Sume if (debug) 338378176Sume log(-1, " [invalid]"); 338478064Sume break; 338578064Sume#ifdef notyet 338678064Sume case IPV6CP_OPT_COMPRESSION: 338778064Sume if (len >= 4 && p[1] >= 4) { 338878064Sume /* correctly formed compress option */ 338978064Sume continue; 339078064Sume } 339178064Sume if (debug) 339278176Sume log(-1, " [invalid]"); 339378064Sume break; 339478064Sume#endif 339578064Sume default: 339678064Sume /* Others not supported. */ 339778064Sume if (debug) 339878176Sume log(-1, " [rej]"); 339978064Sume break; 340078064Sume } 340178064Sume /* Add the option to rejected list. */ 340278064Sume bcopy (p, r, p[1]); 340378064Sume r += p[1]; 340478064Sume rlen += p[1]; 340578064Sume } 340678064Sume if (rlen) { 340778064Sume if (debug) 340878176Sume log(-1, " send conf-rej\n"); 340978064Sume sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 341078064Sume goto end; 341178064Sume } else if (debug) 341278176Sume log(-1, "\n"); 341378064Sume 341478064Sume /* pass 2: parse option values */ 341578064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 341678064Sume if (debug) 341778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 341878064Sume SPP_ARGS(ifp)); 341978064Sume p = (void*) (h+1); 342078064Sume len = origlen; 342178064Sume type = CONF_ACK; 342278064Sume for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 342378064Sume if (debug) 342478176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 342578064Sume switch (*p) { 342678064Sume#ifdef notyet 342778064Sume case IPV6CP_OPT_COMPRESSION: 342878064Sume continue; 342978064Sume#endif 343078064Sume case IPV6CP_OPT_IFID: 343178064Sume bzero(&desiredaddr, sizeof(desiredaddr)); 343278064Sume bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 343378064Sume collision = (bcmp(&desiredaddr.s6_addr[8], 343478064Sume &myaddr.s6_addr[8], 8) == 0); 343578064Sume nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 343678064Sume 343778064Sume desiredaddr.s6_addr16[0] = htons(0xfe80); 343878064Sume desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 343978064Sume 344078064Sume if (!collision && !nohisaddr) { 344178064Sume /* no collision, hisaddr known - Conf-Ack */ 344278064Sume type = CONF_ACK; 344378064Sume 344478064Sume if (debug) { 344578176Sume log(-1, " %s [%s]", 344678064Sume ip6_sprintf(&desiredaddr), 344778064Sume sppp_cp_type_name(type)); 344878064Sume } 344978064Sume continue; 345078064Sume } 345178064Sume 345278064Sume bzero(&suggestaddr, sizeof(&suggestaddr)); 345378064Sume if (collision && nohisaddr) { 345478064Sume /* collision, hisaddr unknown - Conf-Rej */ 345578064Sume type = CONF_REJ; 345678064Sume bzero(&p[2], 8); 345778064Sume } else { 345878064Sume /* 345978064Sume * - no collision, hisaddr unknown, or 346078064Sume * - collision, hisaddr known 346178064Sume * Conf-Nak, suggest hisaddr 346278064Sume */ 346378064Sume type = CONF_NAK; 346478064Sume sppp_suggest_ip6_addr(sp, &suggestaddr); 346578064Sume bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 346678064Sume } 346778064Sume if (debug) 346878176Sume log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 346978064Sume sppp_cp_type_name(type)); 347078064Sume break; 347178064Sume } 347278064Sume /* Add the option to nak'ed list. */ 347378064Sume bcopy (p, r, p[1]); 347478064Sume r += p[1]; 347578064Sume rlen += p[1]; 347678064Sume } 347778064Sume 347878064Sume if (rlen == 0 && type == CONF_ACK) { 347978064Sume if (debug) 348078176Sume log(-1, " send %s\n", sppp_cp_type_name(type)); 348178064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 348278064Sume } else { 348378064Sume#ifdef DIAGNOSTIC 348478064Sume if (type == CONF_ACK) 348578064Sume panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 348678064Sume#endif 348778064Sume 348878064Sume if (debug) { 348978176Sume log(-1, " send %s suggest %s\n", 349078064Sume sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 349178064Sume } 349278064Sume sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 349378064Sume } 349478064Sume 349578064Sume end: 349678064Sume free (buf, M_TEMP); 349778064Sume return (rlen == 0); 349878064Sume} 349978064Sume 350078064Sume/* 350178064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our 350278064Sume * negotiation. 350378064Sume */ 350478064Sumestatic void 350578064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 350678064Sume{ 350778064Sume u_char *buf, *p; 350878064Sume struct ifnet *ifp = &sp->pp_if; 350978064Sume int debug = ifp->if_flags & IFF_DEBUG; 351078064Sume 351178064Sume len -= 4; 351278064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 351378064Sume if (!buf) 351478064Sume return; 351578064Sume 351678064Sume if (debug) 351778064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 351878064Sume SPP_ARGS(ifp)); 351978064Sume 352078064Sume p = (void*) (h+1); 352178064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 352278064Sume if (debug) 352378176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 352478064Sume switch (*p) { 352578064Sume case IPV6CP_OPT_IFID: 352678064Sume /* 352778064Sume * Peer doesn't grok address option. This is 352878064Sume * bad. XXX Should we better give up here? 352978064Sume */ 353078064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 353178064Sume break; 353278064Sume#ifdef notyet 353378064Sume case IPV6CP_OPT_COMPRESS: 353478064Sume sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 353578064Sume break; 353678064Sume#endif 353778064Sume } 353878064Sume } 353978064Sume if (debug) 354078176Sume log(-1, "\n"); 354178064Sume free (buf, M_TEMP); 354278064Sume return; 354378064Sume} 354478064Sume 354578064Sume/* 354678064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our 354778064Sume * negotiation. 354878064Sume */ 354978064Sumestatic void 355078064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 355178064Sume{ 355278064Sume u_char *buf, *p; 355378064Sume struct ifnet *ifp = &sp->pp_if; 355478064Sume int debug = ifp->if_flags & IFF_DEBUG; 355578064Sume struct in6_addr suggestaddr; 355678064Sume 355778064Sume len -= 4; 355878064Sume buf = malloc (len, M_TEMP, M_NOWAIT); 355978064Sume if (!buf) 356078064Sume return; 356178064Sume 356278064Sume if (debug) 356378064Sume log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 356478064Sume SPP_ARGS(ifp)); 356578064Sume 356678064Sume p = (void*) (h+1); 356778064Sume for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 356878064Sume if (debug) 356978176Sume log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 357078064Sume switch (*p) { 357178064Sume case IPV6CP_OPT_IFID: 357278064Sume /* 357378064Sume * Peer doesn't like our local ifid. See 357478064Sume * if we can do something for him. We'll drop 357578064Sume * him our address then. 357678064Sume */ 357778064Sume if (len < 10 || p[1] != 10) 357878064Sume break; 357978064Sume bzero(&suggestaddr, sizeof(suggestaddr)); 358078064Sume suggestaddr.s6_addr16[0] = htons(0xfe80); 358178064Sume suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 358278064Sume bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 358378064Sume 358478064Sume sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 358578064Sume if (debug) 358678176Sume log(-1, " [suggestaddr %s]", 358778064Sume ip6_sprintf(&suggestaddr)); 358878064Sume#ifdef IPV6CP_MYIFID_DYN 358978064Sume /* 359078064Sume * When doing dynamic address assignment, 359178064Sume * we accept his offer. 359278064Sume */ 359378064Sume if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 359478064Sume struct in6_addr lastsuggest; 359578064Sume /* 359678064Sume * If <suggested myaddr from peer> equals to 359778064Sume * <hisaddr we have suggested last time>, 359878064Sume * we have a collision. generate new random 359978064Sume * ifid. 360078064Sume */ 360178064Sume sppp_suggest_ip6_addr(&lastsuggest); 360278064Sume if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 360378064Sume lastsuggest)) { 360478064Sume if (debug) 360578176Sume log(-1, " [random]"); 360678064Sume sppp_gen_ip6_addr(sp, &suggestaddr); 360778064Sume } 360878064Sume sppp_set_ip6_addr(sp, &suggestaddr, 0); 360978064Sume if (debug) 361078176Sume log(-1, " [agree]"); 361178064Sume sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 361278064Sume } 361378064Sume#else 361478064Sume /* 361578064Sume * Since we do not do dynamic address assignment, 361678064Sume * we ignore it and thus continue to negotiate 361778064Sume * our already existing value. This can possibly 361878064Sume * go into infinite request-reject loop. 361978064Sume * 362078064Sume * This is not likely because we normally use 362178064Sume * ifid based on MAC-address. 362278064Sume * If you have no ethernet card on the node, too bad. 362378064Sume * XXX should we use fail_counter? 362478064Sume */ 362578064Sume#endif 362678064Sume break; 362778064Sume#ifdef notyet 362878064Sume case IPV6CP_OPT_COMPRESS: 362978064Sume /* 363078064Sume * Peer wants different compression parameters. 363178064Sume */ 363278064Sume break; 363378064Sume#endif 363478064Sume } 363578064Sume } 363678064Sume if (debug) 363778176Sume log(-1, "\n"); 363878064Sume free (buf, M_TEMP); 363978064Sume return; 364078064Sume} 364178064Sumestatic void 364278064Sumesppp_ipv6cp_tlu(struct sppp *sp) 364378064Sume{ 364478064Sume /* we are up - notify isdn daemon */ 364578064Sume if (sp->pp_con) 364678064Sume sp->pp_con(sp); 364778064Sume} 364878064Sume 364978064Sumestatic void 365078064Sumesppp_ipv6cp_tld(struct sppp *sp) 365178064Sume{ 365278064Sume} 365378064Sume 365478064Sumestatic void 365578064Sumesppp_ipv6cp_tls(struct sppp *sp) 365678064Sume{ 365778064Sume /* indicate to LCP that it must stay alive */ 365878064Sume sp->lcp.protos |= (1 << IDX_IPV6CP); 365978064Sume} 366078064Sume 366178064Sumestatic void 366278064Sumesppp_ipv6cp_tlf(struct sppp *sp) 366378064Sume{ 366478064Sume 366578064Sume#if 0 /* need #if 0 to close IPv6CP properly */ 366678064Sume /* we no longer need LCP */ 366778064Sume sp->lcp.protos &= ~(1 << IDX_IPV6CP); 366878064Sume sppp_lcp_check_and_close(sp); 366978064Sume#endif 367078064Sume} 367178064Sume 367278064Sumestatic void 367378064Sumesppp_ipv6cp_scr(struct sppp *sp) 367478064Sume{ 367578064Sume char opt[10 /* ifid */ + 4 /* compression, minimum */]; 367678064Sume struct in6_addr ouraddr; 367778064Sume int i = 0; 367878064Sume 367978064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 368078064Sume sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 368178064Sume opt[i++] = IPV6CP_OPT_IFID; 368278064Sume opt[i++] = 10; 368378064Sume bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 368478064Sume i += 8; 368578064Sume } 368678064Sume 368778064Sume#ifdef notyet 368878064Sume if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 368978064Sume opt[i++] = IPV6CP_OPT_COMPRESSION; 369078064Sume opt[i++] = 4; 369178064Sume opt[i++] = 0; /* TBD */ 369278064Sume opt[i++] = 0; /* TBD */ 369378064Sume /* variable length data may follow */ 369478064Sume } 369578064Sume#endif 369678064Sume 369778064Sume sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 369878064Sume sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 369978064Sume} 370078064Sume#else /*INET6*/ 370178064Sumestatic void sppp_ipv6cp_init(struct sppp *sp) 370278064Sume{ 370378064Sume} 370478064Sume 370578064Sumestatic void sppp_ipv6cp_up(struct sppp *sp) 370678064Sume{ 370778064Sume} 370878064Sume 370978064Sumestatic void sppp_ipv6cp_down(struct sppp *sp) 371078064Sume{ 371178064Sume} 371278064Sume 371378064Sume 371478064Sumestatic void sppp_ipv6cp_open(struct sppp *sp) 371578064Sume{ 371678064Sume} 371778064Sume 371878064Sumestatic void sppp_ipv6cp_close(struct sppp *sp) 371978064Sume{ 372078064Sume} 372178064Sume 372278064Sumestatic void sppp_ipv6cp_TO(void *sp) 372378064Sume{ 372478064Sume} 372578064Sume 372678064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 372778064Sume{ 372878064Sume return 0; 372978064Sume} 373078064Sume 373178064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 373278064Sume{ 373378064Sume} 373478064Sume 373578064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 373678064Sume{ 373778064Sume} 373878064Sume 373978064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp) 374078064Sume{ 374178064Sume} 374278064Sume 374378064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp) 374478064Sume{ 374578064Sume} 374678064Sume 374778064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp) 374878064Sume{ 374978064Sume} 375078064Sume 375178064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp) 375278064Sume{ 375378064Sume} 375478064Sume 375578064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp) 375678064Sume{ 375778064Sume} 375878064Sume#endif /*INET6*/ 375978064Sume 376078064Sume/* 376178064Sume *--------------------------------------------------------------------------* 376278064Sume * * 376330300Sjoerg * The CHAP implementation. * 376430300Sjoerg * * 376530300Sjoerg *--------------------------------------------------------------------------* 376630300Sjoerg */ 376730300Sjoerg 376830300Sjoerg/* 376930300Sjoerg * The authentication protocols don't employ a full-fledged state machine as 377030300Sjoerg * the control protocols do, since they do have Open and Close events, but 377130300Sjoerg * not Up and Down, nor are they explicitly terminated. Also, use of the 377230300Sjoerg * authentication protocols may be different in both directions (this makes 377330300Sjoerg * sense, think of a machine that never accepts incoming calls but only 377430300Sjoerg * calls out, it doesn't require the called party to authenticate itself). 377530300Sjoerg * 377630300Sjoerg * Our state machine for the local authentication protocol (we are requesting 377730300Sjoerg * the peer to authenticate) looks like: 377830300Sjoerg * 377930300Sjoerg * RCA- 378030300Sjoerg * +--------------------------------------------+ 378130300Sjoerg * V scn,tld| 378230300Sjoerg * +--------+ Close +---------+ RCA+ 378330300Sjoerg * | |<----------------------------------| |------+ 378430300Sjoerg * +--->| Closed | TO* | Opened | sca | 378530300Sjoerg * | | |-----+ +-------| |<-----+ 378630300Sjoerg * | +--------+ irc | | +---------+ 378730300Sjoerg * | ^ | | ^ 378830300Sjoerg * | | | | | 378930300Sjoerg * | | | | | 379030300Sjoerg * | TO-| | | | 379130300Sjoerg * | |tld TO+ V | | 379230300Sjoerg * | | +------->+ | | 379330300Sjoerg * | | | | | | 379430300Sjoerg * | +--------+ V | | 379530300Sjoerg * | | |<----+<--------------------+ | 379630300Sjoerg * | | Req- | scr | 379730300Sjoerg * | | Sent | | 379830300Sjoerg * | | | | 379930300Sjoerg * | +--------+ | 380030300Sjoerg * | RCA- | | RCA+ | 380130300Sjoerg * +------+ +------------------------------------------+ 380230300Sjoerg * scn,tld sca,irc,ict,tlu 380330300Sjoerg * 380430300Sjoerg * 380530300Sjoerg * with: 380630300Sjoerg * 380730300Sjoerg * Open: LCP reached authentication phase 380830300Sjoerg * Close: LCP reached terminate phase 380930300Sjoerg * 381030300Sjoerg * RCA+: received reply (pap-req, chap-response), acceptable 381130300Sjoerg * RCN: received reply (pap-req, chap-response), not acceptable 381230300Sjoerg * TO+: timeout with restart counter >= 0 381330300Sjoerg * TO-: timeout with restart counter < 0 381430300Sjoerg * TO*: reschedule timeout for CHAP 381530300Sjoerg * 381630300Sjoerg * scr: send request packet (none for PAP, chap-challenge) 381730300Sjoerg * sca: send ack packet (pap-ack, chap-success) 381830300Sjoerg * scn: send nak packet (pap-nak, chap-failure) 381930300Sjoerg * ict: initialize re-challenge timer (CHAP only) 382030300Sjoerg * 382130300Sjoerg * tlu: this-layer-up, LCP reaches network phase 382230300Sjoerg * tld: this-layer-down, LCP enters terminate phase 382330300Sjoerg * 382430300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state 382530300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld 382630300Sjoerg * event to LCP, so LCP remains in network phase. Only after not getting 382730300Sjoerg * any response (or after getting an unacceptable response), CHAP closes, 382830300Sjoerg * causing LCP to enter terminate phase. 382930300Sjoerg * 383030300Sjoerg * With PAP, there is no initial request that can be sent. The peer is 383130300Sjoerg * expected to send one based on the successful negotiation of PAP as 383230300Sjoerg * the authentication protocol during the LCP option negotiation. 383330300Sjoerg * 383430300Sjoerg * Incoming authentication protocol requests (remote requests 383530300Sjoerg * authentication, we are peer) don't employ a state machine at all, 383630300Sjoerg * they are simply answered. Some peers [Ascend P50 firmware rev 383730300Sjoerg * 4.50] react allergically when sending IPCP requests while they are 383830300Sjoerg * still in authentication phase (thereby violating the standard that 383930300Sjoerg * demands that these NCP packets are to be discarded), so we keep 384030300Sjoerg * track of the peer demanding us to authenticate, and only proceed to 384130300Sjoerg * phase network once we've seen a positive acknowledge for the 384230300Sjoerg * authentication. 384330300Sjoerg */ 384430300Sjoerg 384530300Sjoerg/* 384630300Sjoerg * Handle incoming CHAP packets. 384730300Sjoerg */ 384830300Sjoergvoid 384930300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m) 385030300Sjoerg{ 385130300Sjoerg STDDCL; 385230300Sjoerg struct lcp_header *h; 385330300Sjoerg int len, x; 385430300Sjoerg u_char *value, *name, digest[AUTHKEYLEN], dsize; 385530300Sjoerg int value_len, name_len; 385630300Sjoerg MD5_CTX ctx; 385730300Sjoerg 385830300Sjoerg len = m->m_pkthdr.len; 385930300Sjoerg if (len < 4) { 386030300Sjoerg if (debug) 386130300Sjoerg log(LOG_DEBUG, 386240008Sjoerg SPP_FMT "chap invalid packet length: %d bytes\n", 386340008Sjoerg SPP_ARGS(ifp), len); 386430300Sjoerg return; 386530300Sjoerg } 386630300Sjoerg h = mtod (m, struct lcp_header*); 386730300Sjoerg if (len > ntohs (h->len)) 386830300Sjoerg len = ntohs (h->len); 386930300Sjoerg 387030300Sjoerg switch (h->type) { 387130300Sjoerg /* challenge, failure and success are his authproto */ 387230300Sjoerg case CHAP_CHALLENGE: 387330300Sjoerg value = 1 + (u_char*)(h+1); 387430300Sjoerg value_len = value[-1]; 387530300Sjoerg name = value + value_len; 387630300Sjoerg name_len = len - value_len - 5; 387730300Sjoerg if (name_len < 0) { 387830300Sjoerg if (debug) { 387930300Sjoerg log(LOG_DEBUG, 388040008Sjoerg SPP_FMT "chap corrupted challenge " 388130300Sjoerg "<%s id=0x%x len=%d", 388240008Sjoerg SPP_ARGS(ifp), 388330300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 388430300Sjoerg h->ident, ntohs(h->len)); 388544145Sphk sppp_print_bytes((u_char*) (h+1), len-4); 388669211Sphk log(-1, ">\n"); 388730300Sjoerg } 388830300Sjoerg break; 388930300Sjoerg } 389070199Sjhay 389130300Sjoerg if (debug) { 389230300Sjoerg log(LOG_DEBUG, 389340008Sjoerg SPP_FMT "chap input <%s id=0x%x len=%d name=", 389440008Sjoerg SPP_ARGS(ifp), 389530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 389630300Sjoerg ntohs(h->len)); 389730300Sjoerg sppp_print_string((char*) name, name_len); 389869211Sphk log(-1, " value-size=%d value=", value_len); 389930300Sjoerg sppp_print_bytes(value, value_len); 390069211Sphk log(-1, ">\n"); 390130300Sjoerg } 390230300Sjoerg 390330300Sjoerg /* Compute reply value. */ 390430300Sjoerg MD5Init(&ctx); 390530300Sjoerg MD5Update(&ctx, &h->ident, 1); 390630300Sjoerg MD5Update(&ctx, sp->myauth.secret, 390730300Sjoerg sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 390830300Sjoerg MD5Update(&ctx, value, value_len); 390930300Sjoerg MD5Final(digest, &ctx); 391030300Sjoerg dsize = sizeof digest; 391130300Sjoerg 391230300Sjoerg sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 391330300Sjoerg sizeof dsize, (const char *)&dsize, 391430300Sjoerg sizeof digest, digest, 391540008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 391630300Sjoerg sp->myauth.name, 391730300Sjoerg 0); 391830300Sjoerg break; 391930300Sjoerg 392030300Sjoerg case CHAP_SUCCESS: 392130300Sjoerg if (debug) { 392240008Sjoerg log(LOG_DEBUG, SPP_FMT "chap success", 392340008Sjoerg SPP_ARGS(ifp)); 392430300Sjoerg if (len > 4) { 392569211Sphk log(-1, ": "); 392630300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 392730300Sjoerg } 392869211Sphk log(-1, "\n"); 392930300Sjoerg } 393030300Sjoerg x = splimp(); 393130300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 393230300Sjoerg if (sp->myauth.proto == PPP_CHAP && 393332169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 393430300Sjoerg (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 393530300Sjoerg /* 393630300Sjoerg * We are authenticator for CHAP but didn't 393730300Sjoerg * complete yet. Leave it to tlu to proceed 393830300Sjoerg * to network phase. 393930300Sjoerg */ 394030300Sjoerg splx(x); 394130300Sjoerg break; 394230300Sjoerg } 394330300Sjoerg splx(x); 394430300Sjoerg sppp_phase_network(sp); 394530300Sjoerg break; 394630300Sjoerg 394730300Sjoerg case CHAP_FAILURE: 394830300Sjoerg if (debug) { 394940008Sjoerg log(LOG_INFO, SPP_FMT "chap failure", 395040008Sjoerg SPP_ARGS(ifp)); 395130300Sjoerg if (len > 4) { 395269211Sphk log(-1, ": "); 395330300Sjoerg sppp_print_string((char*)(h + 1), len - 4); 395430300Sjoerg } 395569211Sphk log(-1, "\n"); 395630300Sjoerg } else 395740008Sjoerg log(LOG_INFO, SPP_FMT "chap failure\n", 395840008Sjoerg SPP_ARGS(ifp)); 395930300Sjoerg /* await LCP shutdown by authenticator */ 396030300Sjoerg break; 396130300Sjoerg 396230300Sjoerg /* response is my authproto */ 396330300Sjoerg case CHAP_RESPONSE: 396430300Sjoerg value = 1 + (u_char*)(h+1); 396530300Sjoerg value_len = value[-1]; 396630300Sjoerg name = value + value_len; 396730300Sjoerg name_len = len - value_len - 5; 396830300Sjoerg if (name_len < 0) { 396930300Sjoerg if (debug) { 397030300Sjoerg log(LOG_DEBUG, 397140008Sjoerg SPP_FMT "chap corrupted response " 397230300Sjoerg "<%s id=0x%x len=%d", 397340008Sjoerg SPP_ARGS(ifp), 397430300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 397530300Sjoerg h->ident, ntohs(h->len)); 397644145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 397769211Sphk log(-1, ">\n"); 397830300Sjoerg } 397930300Sjoerg break; 398030300Sjoerg } 398130300Sjoerg if (h->ident != sp->confid[IDX_CHAP]) { 398230300Sjoerg if (debug) 398330300Sjoerg log(LOG_DEBUG, 398440008Sjoerg SPP_FMT "chap dropping response for old ID " 398530300Sjoerg "(got %d, expected %d)\n", 398640008Sjoerg SPP_ARGS(ifp), 398730300Sjoerg h->ident, sp->confid[IDX_CHAP]); 398830300Sjoerg break; 398930300Sjoerg } 399030300Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 399130300Sjoerg || bcmp(name, sp->hisauth.name, name_len) != 0) { 399240008Sjoerg log(LOG_INFO, SPP_FMT "chap response, his name ", 399340008Sjoerg SPP_ARGS(ifp)); 399430300Sjoerg sppp_print_string(name, name_len); 399569211Sphk log(-1, " != expected "); 399630300Sjoerg sppp_print_string(sp->hisauth.name, 399730300Sjoerg sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 399869211Sphk log(-1, "\n"); 399970199Sjhay } 400030300Sjoerg if (debug) { 400140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap input(%s) " 400230300Sjoerg "<%s id=0x%x len=%d name=", 400340008Sjoerg SPP_ARGS(ifp), 400430300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 400530300Sjoerg sppp_auth_type_name(PPP_CHAP, h->type), 400630300Sjoerg h->ident, ntohs (h->len)); 400730300Sjoerg sppp_print_string((char*)name, name_len); 400869211Sphk log(-1, " value-size=%d value=", value_len); 400930300Sjoerg sppp_print_bytes(value, value_len); 401069211Sphk log(-1, ">\n"); 401130300Sjoerg } 401230300Sjoerg if (value_len != AUTHKEYLEN) { 401330300Sjoerg if (debug) 401430300Sjoerg log(LOG_DEBUG, 401540008Sjoerg SPP_FMT "chap bad hash value length: " 401630300Sjoerg "%d bytes, should be %d\n", 401740008Sjoerg SPP_ARGS(ifp), value_len, 401830300Sjoerg AUTHKEYLEN); 401930300Sjoerg break; 402030300Sjoerg } 402130300Sjoerg 402230300Sjoerg MD5Init(&ctx); 402330300Sjoerg MD5Update(&ctx, &h->ident, 1); 402430300Sjoerg MD5Update(&ctx, sp->hisauth.secret, 402530300Sjoerg sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 402630300Sjoerg MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 402730300Sjoerg MD5Final(digest, &ctx); 402830300Sjoerg 402930300Sjoerg#define FAILMSG "Failed..." 403030300Sjoerg#define SUCCMSG "Welcome!" 403130300Sjoerg 403230300Sjoerg if (value_len != sizeof digest || 403330300Sjoerg bcmp(digest, value, value_len) != 0) { 403430300Sjoerg /* action scn, tld */ 403530300Sjoerg sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 403630300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 403730300Sjoerg 0); 403830300Sjoerg chap.tld(sp); 403930300Sjoerg break; 404030300Sjoerg } 404130300Sjoerg /* action sca, perhaps tlu */ 404230300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 404330300Sjoerg sp->state[IDX_CHAP] == STATE_OPENED) 404430300Sjoerg sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 404530300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 404630300Sjoerg 0); 404730300Sjoerg if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 404830300Sjoerg sppp_cp_change_state(&chap, sp, STATE_OPENED); 404930300Sjoerg chap.tlu(sp); 405030300Sjoerg } 405130300Sjoerg break; 405230300Sjoerg 405330300Sjoerg default: 405430300Sjoerg /* Unknown CHAP packet type -- ignore. */ 405530300Sjoerg if (debug) { 405640008Sjoerg log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 405730300Sjoerg "<0x%x id=0x%xh len=%d", 405840008Sjoerg SPP_ARGS(ifp), 405930300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 406030300Sjoerg h->type, h->ident, ntohs(h->len)); 406144145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 406269211Sphk log(-1, ">\n"); 406330300Sjoerg } 406430300Sjoerg break; 406530300Sjoerg 406630300Sjoerg } 406730300Sjoerg} 406830300Sjoerg 406930300Sjoergstatic void 407030300Sjoergsppp_chap_init(struct sppp *sp) 407130300Sjoerg{ 407230300Sjoerg /* Chap doesn't have STATE_INITIAL at all. */ 407330300Sjoerg sp->state[IDX_CHAP] = STATE_CLOSED; 407430300Sjoerg sp->fail_counter[IDX_CHAP] = 0; 407578064Sume sp->pp_seq[IDX_CHAP] = 0; 407678064Sume sp->pp_rseq[IDX_CHAP] = 0; 407742065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 407830300Sjoerg callout_handle_init(&sp->ch[IDX_CHAP]); 407940008Sjoerg#endif 408030300Sjoerg} 408130300Sjoerg 408230300Sjoergstatic void 408330300Sjoergsppp_chap_open(struct sppp *sp) 408430300Sjoerg{ 408530300Sjoerg if (sp->myauth.proto == PPP_CHAP && 408630300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 408730300Sjoerg /* we are authenticator for CHAP, start it */ 408830300Sjoerg chap.scr(sp); 408930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 409030300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 409130300Sjoerg } 409230300Sjoerg /* nothing to be done if we are peer, await a challenge */ 409330300Sjoerg} 409430300Sjoerg 409530300Sjoergstatic void 409630300Sjoergsppp_chap_close(struct sppp *sp) 409730300Sjoerg{ 409830300Sjoerg if (sp->state[IDX_CHAP] != STATE_CLOSED) 409930300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 410030300Sjoerg} 410130300Sjoerg 410230300Sjoergstatic void 410330300Sjoergsppp_chap_TO(void *cookie) 410430300Sjoerg{ 410530300Sjoerg struct sppp *sp = (struct sppp *)cookie; 410630300Sjoerg STDDCL; 410730300Sjoerg int s; 410830300Sjoerg 410930300Sjoerg s = splimp(); 411030300Sjoerg if (debug) 411140008Sjoerg log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 411240008Sjoerg SPP_ARGS(ifp), 411330300Sjoerg sppp_state_name(sp->state[IDX_CHAP]), 411430300Sjoerg sp->rst_counter[IDX_CHAP]); 411530300Sjoerg 411630300Sjoerg if (--sp->rst_counter[IDX_CHAP] < 0) 411730300Sjoerg /* TO- event */ 411830300Sjoerg switch (sp->state[IDX_CHAP]) { 411930300Sjoerg case STATE_REQ_SENT: 412030300Sjoerg chap.tld(sp); 412130300Sjoerg sppp_cp_change_state(&chap, sp, STATE_CLOSED); 412230300Sjoerg break; 412330300Sjoerg } 412430300Sjoerg else 412530300Sjoerg /* TO+ (or TO*) event */ 412630300Sjoerg switch (sp->state[IDX_CHAP]) { 412730300Sjoerg case STATE_OPENED: 412830300Sjoerg /* TO* event */ 412930300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 413030300Sjoerg /* fall through */ 413130300Sjoerg case STATE_REQ_SENT: 413230300Sjoerg chap.scr(sp); 413330300Sjoerg /* sppp_cp_change_state() will restart the timer */ 413430300Sjoerg sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 413530300Sjoerg break; 413630300Sjoerg } 413730300Sjoerg 413830300Sjoerg splx(s); 413930300Sjoerg} 414030300Sjoerg 414130300Sjoergstatic void 414230300Sjoergsppp_chap_tlu(struct sppp *sp) 414330300Sjoerg{ 414430300Sjoerg STDDCL; 414530300Sjoerg int i, x; 414630300Sjoerg 414740010Sjoerg i = 0; 414830300Sjoerg sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 414930300Sjoerg 415030300Sjoerg /* 415130300Sjoerg * Some broken CHAP implementations (Conware CoNet, firmware 415230300Sjoerg * 4.0.?) don't want to re-authenticate their CHAP once the 415330300Sjoerg * initial challenge-response exchange has taken place. 415430300Sjoerg * Provide for an option to avoid rechallenges. 415530300Sjoerg */ 415630300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 415730300Sjoerg /* 415830300Sjoerg * Compute the re-challenge timeout. This will yield 415930300Sjoerg * a number between 300 and 810 seconds. 416030300Sjoerg */ 416130300Sjoerg i = 300 + ((unsigned)(random() & 0xff00) >> 7); 416242064Sphk TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 416330300Sjoerg } 416430300Sjoerg 416530300Sjoerg if (debug) { 416630300Sjoerg log(LOG_DEBUG, 416740008Sjoerg SPP_FMT "chap %s, ", 416840008Sjoerg SPP_ARGS(ifp), 416930300Sjoerg sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 417030300Sjoerg if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 417169211Sphk log(-1, "next re-challenge in %d seconds\n", i); 417230300Sjoerg else 417369211Sphk log(-1, "re-challenging supressed\n"); 417430300Sjoerg } 417530300Sjoerg 417630300Sjoerg x = splimp(); 417730300Sjoerg /* indicate to LCP that we need to be closed down */ 417830300Sjoerg sp->lcp.protos |= (1 << IDX_CHAP); 417930300Sjoerg 418030300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 418130300Sjoerg /* 418230300Sjoerg * Remote is authenticator, but his auth proto didn't 418330300Sjoerg * complete yet. Defer the transition to network 418430300Sjoerg * phase. 418530300Sjoerg */ 418630300Sjoerg splx(x); 418730300Sjoerg return; 418830300Sjoerg } 418930300Sjoerg splx(x); 419030300Sjoerg 419130300Sjoerg /* 419230300Sjoerg * If we are already in phase network, we are done here. This 419330300Sjoerg * is the case if this is a dummy tlu event after a re-challenge. 419430300Sjoerg */ 419530300Sjoerg if (sp->pp_phase != PHASE_NETWORK) 419630300Sjoerg sppp_phase_network(sp); 419730300Sjoerg} 419830300Sjoerg 419930300Sjoergstatic void 420030300Sjoergsppp_chap_tld(struct sppp *sp) 420130300Sjoerg{ 420230300Sjoerg STDDCL; 420330300Sjoerg 420430300Sjoerg if (debug) 420540008Sjoerg log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 420640008Sjoerg UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 420730300Sjoerg sp->lcp.protos &= ~(1 << IDX_CHAP); 420830300Sjoerg 420930300Sjoerg lcp.Close(sp); 421030300Sjoerg} 421130300Sjoerg 421230300Sjoergstatic void 421330300Sjoergsppp_chap_scr(struct sppp *sp) 421430300Sjoerg{ 421530300Sjoerg u_long *ch, seed; 421630300Sjoerg u_char clen; 421730300Sjoerg 421830300Sjoerg /* Compute random challenge. */ 421930300Sjoerg ch = (u_long *)sp->myauth.challenge; 422042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 422135064Sphk read_random(&seed, sizeof seed); 422240008Sjoerg#else 422342104Sphk { 422442104Sphk struct timeval tv; 422540008Sjoerg microtime(&tv); 422640008Sjoerg seed = tv.tv_sec ^ tv.tv_usec; 422742104Sphk } 422840008Sjoerg#endif 422930300Sjoerg ch[0] = seed ^ random(); 423030300Sjoerg ch[1] = seed ^ random(); 423130300Sjoerg ch[2] = seed ^ random(); 423230300Sjoerg ch[3] = seed ^ random(); 423330300Sjoerg clen = AUTHKEYLEN; 423430300Sjoerg 423578064Sume sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 423630300Sjoerg 423730300Sjoerg sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 423830300Sjoerg sizeof clen, (const char *)&clen, 423940008Sjoerg (size_t)AUTHKEYLEN, sp->myauth.challenge, 424040008Sjoerg (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 424130300Sjoerg sp->myauth.name, 424230300Sjoerg 0); 424330300Sjoerg} 424470199Sjhay 424570199Sjhay/* 424630300Sjoerg *--------------------------------------------------------------------------* 424730300Sjoerg * * 424830300Sjoerg * The PAP implementation. * 424930300Sjoerg * * 425030300Sjoerg *--------------------------------------------------------------------------* 425130300Sjoerg */ 425230300Sjoerg/* 425330300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the 425430300Sjoerg * authenticator. This is since we don't get a request to authenticate, but 425530300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the 425630300Sjoerg * retry counter is expired). 425730300Sjoerg */ 425830300Sjoerg 425930300Sjoerg/* 426030300Sjoerg * Handle incoming PAP packets. */ 426130300Sjoergstatic void 426230300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m) 426330300Sjoerg{ 426430300Sjoerg STDDCL; 426530300Sjoerg struct lcp_header *h; 426630300Sjoerg int len, x; 426730300Sjoerg u_char *name, *passwd, mlen; 426830300Sjoerg int name_len, passwd_len; 426930300Sjoerg 427030300Sjoerg len = m->m_pkthdr.len; 427130300Sjoerg if (len < 5) { 427230300Sjoerg if (debug) 427330300Sjoerg log(LOG_DEBUG, 427440008Sjoerg SPP_FMT "pap invalid packet length: %d bytes\n", 427540008Sjoerg SPP_ARGS(ifp), len); 427630300Sjoerg return; 427730300Sjoerg } 427830300Sjoerg h = mtod (m, struct lcp_header*); 427930300Sjoerg if (len > ntohs (h->len)) 428030300Sjoerg len = ntohs (h->len); 428130300Sjoerg switch (h->type) { 428230300Sjoerg /* PAP request is my authproto */ 428330300Sjoerg case PAP_REQ: 428430300Sjoerg name = 1 + (u_char*)(h+1); 428530300Sjoerg name_len = name[-1]; 428630300Sjoerg passwd = name + name_len + 1; 428730300Sjoerg if (name_len > len - 6 || 428830300Sjoerg (passwd_len = passwd[-1]) > len - 6 - name_len) { 428930300Sjoerg if (debug) { 429040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 429130300Sjoerg "<%s id=0x%x len=%d", 429240008Sjoerg SPP_ARGS(ifp), 429330300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 429430300Sjoerg h->ident, ntohs(h->len)); 429544145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 429669211Sphk log(-1, ">\n"); 429730300Sjoerg } 429830300Sjoerg break; 429930300Sjoerg } 430030300Sjoerg if (debug) { 430140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap input(%s) " 430230300Sjoerg "<%s id=0x%x len=%d name=", 430340008Sjoerg SPP_ARGS(ifp), 430430300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 430530300Sjoerg sppp_auth_type_name(PPP_PAP, h->type), 430630300Sjoerg h->ident, ntohs(h->len)); 430730300Sjoerg sppp_print_string((char*)name, name_len); 430869211Sphk log(-1, " passwd="); 430930300Sjoerg sppp_print_string((char*)passwd, passwd_len); 431069211Sphk log(-1, ">\n"); 431130300Sjoerg } 431274774Sjoerg if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 431374774Sjoerg passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 431430300Sjoerg bcmp(name, sp->hisauth.name, name_len) != 0 || 431530300Sjoerg bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 431630300Sjoerg /* action scn, tld */ 431730300Sjoerg mlen = sizeof(FAILMSG) - 1; 431830300Sjoerg sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 431930300Sjoerg sizeof mlen, (const char *)&mlen, 432030300Sjoerg sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 432130300Sjoerg 0); 432230300Sjoerg pap.tld(sp); 432330300Sjoerg break; 432430300Sjoerg } 432530300Sjoerg /* action sca, perhaps tlu */ 432630300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT || 432730300Sjoerg sp->state[IDX_PAP] == STATE_OPENED) { 432830300Sjoerg mlen = sizeof(SUCCMSG) - 1; 432930300Sjoerg sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 433030300Sjoerg sizeof mlen, (const char *)&mlen, 433130300Sjoerg sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 433230300Sjoerg 0); 433330300Sjoerg } 433430300Sjoerg if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 433530300Sjoerg sppp_cp_change_state(&pap, sp, STATE_OPENED); 433630300Sjoerg pap.tlu(sp); 433730300Sjoerg } 433830300Sjoerg break; 433930300Sjoerg 434030300Sjoerg /* ack and nak are his authproto */ 434130300Sjoerg case PAP_ACK: 434240008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 434330300Sjoerg if (debug) { 434440008Sjoerg log(LOG_DEBUG, SPP_FMT "pap success", 434540008Sjoerg SPP_ARGS(ifp)); 434630300Sjoerg name_len = *((char *)h); 434730300Sjoerg if (len > 5 && name_len) { 434869211Sphk log(-1, ": "); 434930300Sjoerg sppp_print_string((char*)(h+1), name_len); 435030300Sjoerg } 435169211Sphk log(-1, "\n"); 435230300Sjoerg } 435330300Sjoerg x = splimp(); 435430300Sjoerg sp->pp_flags &= ~PP_NEEDAUTH; 435530300Sjoerg if (sp->myauth.proto == PPP_PAP && 435632169Sgj (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 435730300Sjoerg (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 435830300Sjoerg /* 435930300Sjoerg * We are authenticator for PAP but didn't 436030300Sjoerg * complete yet. Leave it to tlu to proceed 436130300Sjoerg * to network phase. 436230300Sjoerg */ 436330300Sjoerg splx(x); 436430300Sjoerg break; 436530300Sjoerg } 436630300Sjoerg splx(x); 436730300Sjoerg sppp_phase_network(sp); 436830300Sjoerg break; 436930300Sjoerg 437030300Sjoerg case PAP_NAK: 437140008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 437230300Sjoerg if (debug) { 437340008Sjoerg log(LOG_INFO, SPP_FMT "pap failure", 437440008Sjoerg SPP_ARGS(ifp)); 437530300Sjoerg name_len = *((char *)h); 437630300Sjoerg if (len > 5 && name_len) { 437769211Sphk log(-1, ": "); 437830300Sjoerg sppp_print_string((char*)(h+1), name_len); 437930300Sjoerg } 438069211Sphk log(-1, "\n"); 438130300Sjoerg } else 438240008Sjoerg log(LOG_INFO, SPP_FMT "pap failure\n", 438340008Sjoerg SPP_ARGS(ifp)); 438430300Sjoerg /* await LCP shutdown by authenticator */ 438530300Sjoerg break; 438630300Sjoerg 438730300Sjoerg default: 438830300Sjoerg /* Unknown PAP packet type -- ignore. */ 438930300Sjoerg if (debug) { 439040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap corrupted input " 439130300Sjoerg "<0x%x id=0x%x len=%d", 439240008Sjoerg SPP_ARGS(ifp), 439330300Sjoerg h->type, h->ident, ntohs(h->len)); 439444145Sphk sppp_print_bytes((u_char*)(h+1), len-4); 439569211Sphk log(-1, ">\n"); 439630300Sjoerg } 439730300Sjoerg break; 439830300Sjoerg 439930300Sjoerg } 440030300Sjoerg} 440130300Sjoerg 440230300Sjoergstatic void 440330300Sjoergsppp_pap_init(struct sppp *sp) 440430300Sjoerg{ 440530300Sjoerg /* PAP doesn't have STATE_INITIAL at all. */ 440630300Sjoerg sp->state[IDX_PAP] = STATE_CLOSED; 440730300Sjoerg sp->fail_counter[IDX_PAP] = 0; 440878064Sume sp->pp_seq[IDX_PAP] = 0; 440978064Sume sp->pp_rseq[IDX_PAP] = 0; 441042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 441130300Sjoerg callout_handle_init(&sp->ch[IDX_PAP]); 441230300Sjoerg callout_handle_init(&sp->pap_my_to_ch); 441340008Sjoerg#endif 441430300Sjoerg} 441530300Sjoerg 441630300Sjoergstatic void 441730300Sjoergsppp_pap_open(struct sppp *sp) 441830300Sjoerg{ 441930300Sjoerg if (sp->hisauth.proto == PPP_PAP && 442030300Sjoerg (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 442130300Sjoerg /* we are authenticator for PAP, start our timer */ 442230300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 442330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 442430300Sjoerg } 442530300Sjoerg if (sp->myauth.proto == PPP_PAP) { 442630300Sjoerg /* we are peer, send a request, and start a timer */ 442730300Sjoerg pap.scr(sp); 442842064Sphk TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 442942064Sphk sp->pap_my_to_ch); 443030300Sjoerg } 443130300Sjoerg} 443230300Sjoerg 443330300Sjoergstatic void 443430300Sjoergsppp_pap_close(struct sppp *sp) 443530300Sjoerg{ 443630300Sjoerg if (sp->state[IDX_PAP] != STATE_CLOSED) 443730300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 443830300Sjoerg} 443930300Sjoerg 444030300Sjoerg/* 444130300Sjoerg * That's the timeout routine if we are authenticator. Since the 444230300Sjoerg * authenticator is basically passive in PAP, we can't do much here. 444330300Sjoerg */ 444430300Sjoergstatic void 444530300Sjoergsppp_pap_TO(void *cookie) 444630300Sjoerg{ 444730300Sjoerg struct sppp *sp = (struct sppp *)cookie; 444830300Sjoerg STDDCL; 444930300Sjoerg int s; 445030300Sjoerg 445130300Sjoerg s = splimp(); 445230300Sjoerg if (debug) 445340008Sjoerg log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 445440008Sjoerg SPP_ARGS(ifp), 445530300Sjoerg sppp_state_name(sp->state[IDX_PAP]), 445630300Sjoerg sp->rst_counter[IDX_PAP]); 445730300Sjoerg 445830300Sjoerg if (--sp->rst_counter[IDX_PAP] < 0) 445930300Sjoerg /* TO- event */ 446030300Sjoerg switch (sp->state[IDX_PAP]) { 446130300Sjoerg case STATE_REQ_SENT: 446230300Sjoerg pap.tld(sp); 446330300Sjoerg sppp_cp_change_state(&pap, sp, STATE_CLOSED); 446430300Sjoerg break; 446530300Sjoerg } 446630300Sjoerg else 446730300Sjoerg /* TO+ event, not very much we could do */ 446830300Sjoerg switch (sp->state[IDX_PAP]) { 446930300Sjoerg case STATE_REQ_SENT: 447030300Sjoerg /* sppp_cp_change_state() will restart the timer */ 447130300Sjoerg sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 447230300Sjoerg break; 447330300Sjoerg } 447430300Sjoerg 447530300Sjoerg splx(s); 447630300Sjoerg} 447730300Sjoerg 447830300Sjoerg/* 447930300Sjoerg * That's the timeout handler if we are peer. Since the peer is active, 448030300Sjoerg * we need to retransmit our PAP request since it is apparently lost. 448130300Sjoerg * XXX We should impose a max counter. 448230300Sjoerg */ 448330300Sjoergstatic void 448430300Sjoergsppp_pap_my_TO(void *cookie) 448530300Sjoerg{ 448630300Sjoerg struct sppp *sp = (struct sppp *)cookie; 448730300Sjoerg STDDCL; 448830300Sjoerg 448930300Sjoerg if (debug) 449040008Sjoerg log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 449140008Sjoerg SPP_ARGS(ifp)); 449230300Sjoerg 449330300Sjoerg pap.scr(sp); 449430300Sjoerg} 449530300Sjoerg 449630300Sjoergstatic void 449730300Sjoergsppp_pap_tlu(struct sppp *sp) 449830300Sjoerg{ 449930300Sjoerg STDDCL; 450030300Sjoerg int x; 450130300Sjoerg 450230300Sjoerg sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 450330300Sjoerg 450430300Sjoerg if (debug) 450540008Sjoerg log(LOG_DEBUG, SPP_FMT "%s tlu\n", 450640008Sjoerg SPP_ARGS(ifp), pap.name); 450730300Sjoerg 450830300Sjoerg x = splimp(); 450930300Sjoerg /* indicate to LCP that we need to be closed down */ 451030300Sjoerg sp->lcp.protos |= (1 << IDX_PAP); 451130300Sjoerg 451230300Sjoerg if (sp->pp_flags & PP_NEEDAUTH) { 451330300Sjoerg /* 451430300Sjoerg * Remote is authenticator, but his auth proto didn't 451530300Sjoerg * complete yet. Defer the transition to network 451630300Sjoerg * phase. 451730300Sjoerg */ 451830300Sjoerg splx(x); 451930300Sjoerg return; 452030300Sjoerg } 452130300Sjoerg splx(x); 452230300Sjoerg sppp_phase_network(sp); 452330300Sjoerg} 452430300Sjoerg 452530300Sjoergstatic void 452630300Sjoergsppp_pap_tld(struct sppp *sp) 452730300Sjoerg{ 452830300Sjoerg STDDCL; 452930300Sjoerg 453030300Sjoerg if (debug) 453140008Sjoerg log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 453240008Sjoerg UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 453340008Sjoerg UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 453430300Sjoerg sp->lcp.protos &= ~(1 << IDX_PAP); 453530300Sjoerg 453630300Sjoerg lcp.Close(sp); 453730300Sjoerg} 453830300Sjoerg 453930300Sjoergstatic void 454030300Sjoergsppp_pap_scr(struct sppp *sp) 454130300Sjoerg{ 454230300Sjoerg u_char idlen, pwdlen; 454330300Sjoerg 454478064Sume sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 454530300Sjoerg pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 454630300Sjoerg idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 454730300Sjoerg 454830300Sjoerg sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 454930300Sjoerg sizeof idlen, (const char *)&idlen, 455040008Sjoerg (size_t)idlen, sp->myauth.name, 455130300Sjoerg sizeof pwdlen, (const char *)&pwdlen, 455240008Sjoerg (size_t)pwdlen, sp->myauth.secret, 455330300Sjoerg 0); 455430300Sjoerg} 455570199Sjhay 455670199Sjhay/* 455725944Sjoerg * Random miscellaneous functions. 455825944Sjoerg */ 455925944Sjoerg 45604910Swollman/* 456130300Sjoerg * Send a PAP or CHAP proto packet. 456230300Sjoerg * 456330300Sjoerg * Varadic function, each of the elements for the ellipsis is of type 456440008Sjoerg * ``size_t mlen, const u_char *msg''. Processing will stop iff 456530300Sjoerg * mlen == 0. 456642104Sphk * NOTE: never declare variadic functions with types subject to type 456742104Sphk * promotion (i.e. u_char). This is asking for big trouble depending 456842104Sphk * on the architecture you are on... 456930300Sjoerg */ 457030300Sjoerg 457130300Sjoergstatic void 457242104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp, 457342104Sphk unsigned int type, unsigned int id, 457430300Sjoerg ...) 457530300Sjoerg{ 457630300Sjoerg STDDCL; 457730300Sjoerg struct ppp_header *h; 457830300Sjoerg struct lcp_header *lh; 457930300Sjoerg struct mbuf *m; 458030300Sjoerg u_char *p; 458130300Sjoerg int len; 458242104Sphk unsigned int mlen; 458330300Sjoerg const char *msg; 458430300Sjoerg va_list ap; 458530300Sjoerg 458630300Sjoerg MGETHDR (m, M_DONTWAIT, MT_DATA); 458730300Sjoerg if (! m) 458830300Sjoerg return; 458930300Sjoerg m->m_pkthdr.rcvif = 0; 459030300Sjoerg 459130300Sjoerg h = mtod (m, struct ppp_header*); 459230300Sjoerg h->address = PPP_ALLSTATIONS; /* broadcast address */ 459330300Sjoerg h->control = PPP_UI; /* Unnumbered Info */ 459430300Sjoerg h->protocol = htons(cp->proto); 459530300Sjoerg 459630300Sjoerg lh = (struct lcp_header*)(h + 1); 459730300Sjoerg lh->type = type; 459830300Sjoerg lh->ident = id; 459930300Sjoerg p = (u_char*) (lh+1); 460030300Sjoerg 460130300Sjoerg va_start(ap, id); 460230300Sjoerg len = 0; 460330300Sjoerg 460442104Sphk while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 460530300Sjoerg msg = va_arg(ap, const char *); 460630300Sjoerg len += mlen; 460730300Sjoerg if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 460830300Sjoerg va_end(ap); 460930300Sjoerg m_freem(m); 461030300Sjoerg return; 461130300Sjoerg } 461230300Sjoerg 461330300Sjoerg bcopy(msg, p, mlen); 461430300Sjoerg p += mlen; 461530300Sjoerg } 461630300Sjoerg va_end(ap); 461730300Sjoerg 461830300Sjoerg m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 461930300Sjoerg lh->len = htons (LCP_HEADER_LEN + len); 462030300Sjoerg 462130300Sjoerg if (debug) { 462240008Sjoerg log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 462340008Sjoerg SPP_ARGS(ifp), cp->name, 462430300Sjoerg sppp_auth_type_name(cp->proto, lh->type), 462530300Sjoerg lh->ident, ntohs(lh->len)); 462644145Sphk sppp_print_bytes((u_char*) (lh+1), len); 462769211Sphk log(-1, ">\n"); 462830300Sjoerg } 462969152Sjlemon if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 463069152Sjlemon ifp->if_oerrors++; 463130300Sjoerg} 463230300Sjoerg 463330300Sjoerg/* 463425944Sjoerg * Flush interface queue. 46354910Swollman */ 463612820Sphkstatic void 463725944Sjoergsppp_qflush(struct ifqueue *ifq) 46384910Swollman{ 463925944Sjoerg struct mbuf *m, *n; 46404910Swollman 464125944Sjoerg n = ifq->ifq_head; 464225944Sjoerg while ((m = n)) { 464325944Sjoerg n = m->m_act; 464425944Sjoerg m_freem (m); 464511189Sjkh } 464625944Sjoerg ifq->ifq_head = 0; 464725944Sjoerg ifq->ifq_tail = 0; 464825944Sjoerg ifq->ifq_len = 0; 464925944Sjoerg} 465025944Sjoerg 465125944Sjoerg/* 465225944Sjoerg * Send keepalive packets, every 10 seconds. 465325944Sjoerg */ 465425944Sjoergstatic void 465525944Sjoergsppp_keepalive(void *dummy) 465625944Sjoerg{ 465725944Sjoerg struct sppp *sp; 465825944Sjoerg int s; 465925944Sjoerg 466025944Sjoerg s = splimp(); 466125944Sjoerg for (sp=spppq; sp; sp=sp->pp_next) { 466225944Sjoerg struct ifnet *ifp = &sp->pp_if; 466325944Sjoerg 466425944Sjoerg /* Keepalive mode disabled or channel down? */ 466525944Sjoerg if (! (sp->pp_flags & PP_KEEPALIVE) || 466625944Sjoerg ! (ifp->if_flags & IFF_RUNNING)) 466725944Sjoerg continue; 466825944Sjoerg 466925944Sjoerg /* No keepalive in PPP mode if LCP not opened yet. */ 467045152Sphk if (sp->pp_mode != IFF_CISCO && 467125944Sjoerg sp->pp_phase < PHASE_AUTHENTICATE) 467225944Sjoerg continue; 467325944Sjoerg 467425944Sjoerg if (sp->pp_alivecnt == MAXALIVECNT) { 467525944Sjoerg /* No keepalive packets got. Stop the interface. */ 467640008Sjoerg printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 467725944Sjoerg if_down (ifp); 467826018Sjoerg sppp_qflush (&sp->pp_cpq); 467945152Sphk if (sp->pp_mode != IFF_CISCO) { 468025944Sjoerg /* XXX */ 468125944Sjoerg /* Shut down the PPP link. */ 468225944Sjoerg lcp.Down(sp); 468325944Sjoerg /* Initiate negotiation. XXX */ 468425944Sjoerg lcp.Up(sp); 468525944Sjoerg } 46864910Swollman } 468725944Sjoerg if (sp->pp_alivecnt <= MAXALIVECNT) 468825944Sjoerg ++sp->pp_alivecnt; 468945152Sphk if (sp->pp_mode == IFF_CISCO) 469078064Sume sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 469178064Sume ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 469225944Sjoerg else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 469325944Sjoerg long nmagic = htonl (sp->lcp.magic); 469478064Sume sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 469525944Sjoerg sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 469625944Sjoerg sp->lcp.echoid, 4, &nmagic); 469725944Sjoerg } 46984910Swollman } 469925944Sjoerg splx(s); 470042064Sphk TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 47014910Swollman} 47024910Swollman 470325944Sjoerg/* 470425944Sjoerg * Get both IP addresses. 470525944Sjoerg */ 470625944Sjoergstatic void 470730300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 470825944Sjoerg{ 470925944Sjoerg struct ifnet *ifp = &sp->pp_if; 471025944Sjoerg struct ifaddr *ifa; 471130300Sjoerg struct sockaddr_in *si, *sm; 471225944Sjoerg u_long ssrc, ddst; 471325944Sjoerg 471440010Sjoerg sm = NULL; 471525944Sjoerg ssrc = ddst = 0L; 471625944Sjoerg /* 471725944Sjoerg * Pick the first AF_INET address from the list, 471825944Sjoerg * aliases don't make any sense on a p2p link anyway. 471925944Sjoerg */ 472042065Sphk si = 0; 472142065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 472242065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 472342104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 472471959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 472540008Sjoerg ifa; 472671959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 472742104Sphk#else 472842104Sphk for (ifa = ifp->if_addrlist; 472942104Sphk ifa; 473042104Sphk ifa = ifa->ifa_next) 473140008Sjoerg#endif 473225944Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) { 473325944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 473430300Sjoerg sm = (struct sockaddr_in *)ifa->ifa_netmask; 473525944Sjoerg if (si) 473625944Sjoerg break; 473725944Sjoerg } 473825944Sjoerg if (ifa) { 473930300Sjoerg if (si && si->sin_addr.s_addr) { 474025944Sjoerg ssrc = si->sin_addr.s_addr; 474130300Sjoerg if (srcmask) 474230300Sjoerg *srcmask = ntohl(sm->sin_addr.s_addr); 474330300Sjoerg } 474425944Sjoerg 474525944Sjoerg si = (struct sockaddr_in *)ifa->ifa_dstaddr; 474625944Sjoerg if (si && si->sin_addr.s_addr) 474725944Sjoerg ddst = si->sin_addr.s_addr; 474825944Sjoerg } 474925944Sjoerg 475025944Sjoerg if (dst) *dst = ntohl(ddst); 475125944Sjoerg if (src) *src = ntohl(ssrc); 475225944Sjoerg} 475325944Sjoerg 475425944Sjoerg/* 475525944Sjoerg * Set my IP address. Must be called at splimp. 475625944Sjoerg */ 475725944Sjoergstatic void 475825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src) 475925944Sjoerg{ 476042104Sphk STDDCL; 476125944Sjoerg struct ifaddr *ifa; 476225944Sjoerg struct sockaddr_in *si; 476384318Sjlemon struct in_ifaddr *ia; 476425944Sjoerg 476525944Sjoerg /* 476625944Sjoerg * Pick the first AF_INET address from the list, 476725944Sjoerg * aliases don't make any sense on a p2p link anyway. 476825944Sjoerg */ 476942065Sphk si = 0; 477042065Sphk#if defined(__FreeBSD__) && __FreeBSD__ >= 3 477142065Sphk TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 477242104Sphk#elif defined(__NetBSD__) || defined (__OpenBSD__) 477371959Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 477440008Sjoerg ifa; 477571959Sphk ifa = TAILQ_NEXT(ifa, ifa_list)) 477642104Sphk#else 477742104Sphk for (ifa = ifp->if_addrlist; 477842104Sphk ifa; 477942104Sphk ifa = ifa->ifa_next) 478040008Sjoerg#endif 478140008Sjoerg { 478240008Sjoerg if (ifa->ifa_addr->sa_family == AF_INET) 478340008Sjoerg { 478425944Sjoerg si = (struct sockaddr_in *)ifa->ifa_addr; 478525944Sjoerg if (si) 478625944Sjoerg break; 478725944Sjoerg } 478840008Sjoerg } 478940008Sjoerg 479025944Sjoerg if (ifa && si) 479142104Sphk { 479242104Sphk int error; 479342104Sphk#if __NetBSD_Version__ >= 103080000 479442104Sphk struct sockaddr_in new_sin = *si; 479542104Sphk 479642104Sphk new_sin.sin_addr.s_addr = htonl(src); 479742104Sphk error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 479842104Sphk if(debug && error) 479942104Sphk { 480042104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 480142104Sphk " failed, error=%d\n", SPP_ARGS(ifp), error); 480242104Sphk } 480342104Sphk#else 480442104Sphk /* delete old route */ 480542104Sphk error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 480642104Sphk if(debug && error) 480742104Sphk { 480842104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 480942104Sphk SPP_ARGS(ifp), error); 481042104Sphk } 481142104Sphk 481242104Sphk /* set new address */ 481325944Sjoerg si->sin_addr.s_addr = htonl(src); 481484318Sjlemon ia = ifatoia(ifa); 481584318Sjlemon LIST_REMOVE(ia, ia_hash); 481684318Sjlemon LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 481725944Sjoerg 481842104Sphk /* add new route */ 481970199Sjhay error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 482042104Sphk if (debug && error) 482142104Sphk { 482242104Sphk log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 482342104Sphk SPP_ARGS(ifp), error); 482442104Sphk } 482542104Sphk#endif 482642104Sphk } 482788599Sjoerg} 482878064Sume 482978064Sume#ifdef INET6 483078064Sume/* 483178064Sume * Get both IPv6 addresses. 483278064Sume */ 483378064Sumestatic void 483478064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 483578064Sume struct in6_addr *srcmask) 483678064Sume{ 483778064Sume struct ifnet *ifp = &sp->pp_if; 483878064Sume struct ifaddr *ifa; 483978064Sume struct sockaddr_in6 *si, *sm; 484078064Sume struct in6_addr ssrc, ddst; 484178064Sume 484278064Sume sm = NULL; 484378064Sume bzero(&ssrc, sizeof(ssrc)); 484478064Sume bzero(&ddst, sizeof(ddst)); 484578064Sume /* 484678064Sume * Pick the first link-local AF_INET6 address from the list, 484778064Sume * aliases don't make any sense on a p2p link anyway. 484878064Sume */ 484978064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 485078064Sume for (ifa = ifp->if_addrhead.tqh_first, si = 0; 485178064Sume ifa; 485278064Sume ifa = ifa->ifa_link.tqe_next) 485378064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 485478064Sume for (ifa = ifp->if_addrlist.tqh_first, si = 0; 485578064Sume ifa; 485678064Sume ifa = ifa->ifa_list.tqe_next) 485778064Sume#else 485878064Sume for (ifa = ifp->if_addrlist, si = 0; 485978064Sume ifa; 486078064Sume ifa = ifa->ifa_next) 486178064Sume#endif 486278064Sume if (ifa->ifa_addr->sa_family == AF_INET6) { 486378064Sume si = (struct sockaddr_in6 *)ifa->ifa_addr; 486478064Sume sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 486578064Sume if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 486678064Sume break; 486778064Sume } 486878064Sume if (ifa) { 486978064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 487078064Sume bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 487178064Sume if (srcmask) { 487278064Sume bcopy(&sm->sin6_addr, srcmask, 487378064Sume sizeof(*srcmask)); 487478064Sume } 487578064Sume } 487678064Sume 487778064Sume si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 487878064Sume if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 487978064Sume bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 488078064Sume } 488178064Sume 488278064Sume if (dst) 488378064Sume bcopy(&ddst, dst, sizeof(*dst)); 488478064Sume if (src) 488578064Sume bcopy(&ssrc, src, sizeof(*src)); 488670199Sjhay} 488742104Sphk 488878064Sume#ifdef IPV6CP_MYIFID_DYN 488978064Sume/* 489078064Sume * Generate random ifid. 489178064Sume */ 489278064Sumestatic void 489378064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 489478064Sume{ 489578064Sume /* TBD */ 489678064Sume} 489778064Sume 489878064Sume/* 489978064Sume * Set my IPv6 address. Must be called at splimp. 490078064Sume */ 490178064Sumestatic void 490278064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 490378064Sume{ 490478064Sume STDDCL; 490578064Sume struct ifaddr *ifa; 490678064Sume struct sockaddr_in6 *sin6; 490778064Sume 490878064Sume /* 490978064Sume * Pick the first link-local AF_INET6 address from the list, 491078064Sume * aliases don't make any sense on a p2p link anyway. 491178064Sume */ 491278064Sume 491378064Sume sin6 = NULL; 491478064Sume#if defined(__FreeBSD__) && __FreeBSD__ >= 3 491578064Sume for (ifa = ifp->if_addrhead.tqh_first; 491678064Sume ifa; 491778064Sume ifa = ifa->ifa_link.tqe_next) 491878064Sume#elif defined(__NetBSD__) || defined (__OpenBSD__) 491978064Sume for (ifa = ifp->if_addrlist.tqh_first; 492078064Sume ifa; 492178064Sume ifa = ifa->ifa_list.tqe_next) 492278064Sume#else 492378064Sume for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 492478064Sume#endif 492578064Sume { 492678064Sume if (ifa->ifa_addr->sa_family == AF_INET6) 492778064Sume { 492878064Sume sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 492978064Sume if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 493078064Sume break; 493178064Sume } 493278064Sume } 493378064Sume 493478064Sume if (ifa && sin6) 493578064Sume { 493678064Sume int error; 493778064Sume struct sockaddr_in6 new_sin6 = *sin6; 493878064Sume 493978064Sume bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 494078064Sume error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 494178064Sume if (debug && error) 494278064Sume { 494378064Sume log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 494478064Sume " failed, error=%d\n", SPP_ARGS(ifp), error); 494578064Sume } 494678064Sume } 494778064Sume} 494878064Sume#endif 494978064Sume 495078064Sume/* 495178064Sume * Suggest a candidate address to be used by peer. 495278064Sume */ 495378064Sumestatic void 495478064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 495578064Sume{ 495678064Sume struct in6_addr myaddr; 495778064Sume struct timeval tv; 495878064Sume 495978064Sume sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 496078064Sume 496178064Sume myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 496278064Sume microtime(&tv); 496378064Sume if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 496478064Sume myaddr.s6_addr[14] ^= 0xff; 496578064Sume myaddr.s6_addr[15] ^= 0xff; 496678064Sume } else { 496778064Sume myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 496878064Sume myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 496978064Sume } 497078064Sume if (suggest) 497178064Sume bcopy(&myaddr, suggest, sizeof(myaddr)); 497278064Sume} 497378064Sume#endif /*INET6*/ 497478064Sume 497530300Sjoergstatic int 497638343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data) 497730300Sjoerg{ 497838343Sbde u_long subcmd; 497930300Sjoerg struct ifreq *ifr = (struct ifreq *)data; 498088600Sjoerg struct spppreq *spr; 498188600Sjoerg int rv = 0; 498230300Sjoerg 498388600Sjoerg if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 498488600Sjoerg return (EAGAIN); 498530300Sjoerg /* 498630300Sjoerg * ifr->ifr_data is supposed to point to a struct spppreq. 498730300Sjoerg * Check the cmd word first before attempting to fetch all the 498830300Sjoerg * data. 498930300Sjoerg */ 499088600Sjoerg if ((subcmd = fuword(ifr->ifr_data)) == -1) { 499188600Sjoerg rv = EFAULT; 499288600Sjoerg goto quit; 499388600Sjoerg } 499430300Sjoerg 499588600Sjoerg if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 499688600Sjoerg rv = EFAULT; 499788600Sjoerg goto quit; 499888600Sjoerg } 499930300Sjoerg 500030300Sjoerg switch (subcmd) { 500130300Sjoerg case SPPPIOGDEFS: 500288600Sjoerg if (cmd != SIOCGIFGENERIC) { 500388600Sjoerg rv = EINVAL; 500488600Sjoerg break; 500588600Sjoerg } 500630300Sjoerg /* 500730300Sjoerg * We copy over the entire current state, but clean 500830300Sjoerg * out some of the stuff we don't wanna pass up. 500930300Sjoerg * Remember, SIOCGIFGENERIC is unprotected, and can be 501030300Sjoerg * called by any user. No need to ever get PAP or 501130300Sjoerg * CHAP secrets back to userland anyway. 501230300Sjoerg */ 501388600Sjoerg spr->defs.pp_phase = sp->pp_phase; 501488600Sjoerg spr->defs.enable_vj = sp->enable_vj; 501588600Sjoerg spr->defs.lcp = sp->lcp; 501688600Sjoerg spr->defs.ipcp = sp->ipcp; 501788600Sjoerg spr->defs.ipv6cp = sp->ipv6cp; 501888600Sjoerg spr->defs.myauth = sp->myauth; 501988600Sjoerg spr->defs.hisauth = sp->hisauth; 502088600Sjoerg bzero(spr->defs.myauth.secret, AUTHKEYLEN); 502188600Sjoerg bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 502288600Sjoerg bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 502388600Sjoerg bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 502488550Sjoerg /* 502588550Sjoerg * Fixup the LCP timeout value to milliseconds so 502688550Sjoerg * spppcontrol doesn't need to bother about the value 502788550Sjoerg * of "hz". We do the reverse calculation below when 502888550Sjoerg * setting it. 502988550Sjoerg */ 503088600Sjoerg spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 503188600Sjoerg rv = copyout(spr, (caddr_t)ifr->ifr_data, 503288600Sjoerg sizeof(struct spppreq)); 503388600Sjoerg break; 503430300Sjoerg 503530300Sjoerg case SPPPIOSDEFS: 503688600Sjoerg if (cmd != SIOCSIFGENERIC) { 503788600Sjoerg rv = EINVAL; 503888600Sjoerg break; 503988600Sjoerg } 504030300Sjoerg /* 504188550Sjoerg * We have a very specific idea of which fields we 504288550Sjoerg * allow being passed back from userland, so to not 504388550Sjoerg * clobber our current state. For one, we only allow 504488550Sjoerg * setting anything if LCP is in dead or establish 504588550Sjoerg * phase. Once the authentication negotiations 504688550Sjoerg * started, the authentication settings must not be 504788550Sjoerg * changed again. (The administrator can force an 504830300Sjoerg * ifconfig down in order to get LCP back into dead 504930300Sjoerg * phase.) 505030300Sjoerg * 505130300Sjoerg * Also, we only allow for authentication parameters to be 505230300Sjoerg * specified. 505330300Sjoerg * 505430300Sjoerg * XXX Should allow to set or clear pp_flags. 505530300Sjoerg * 505630300Sjoerg * Finally, if the respective authentication protocol to 505730300Sjoerg * be used is set differently than 0, but the secret is 505830300Sjoerg * passed as all zeros, we don't trash the existing secret. 505930300Sjoerg * This allows an administrator to change the system name 506030300Sjoerg * only without clobbering the secret (which he didn't get 506130300Sjoerg * back in a previous SPPPIOGDEFS call). However, the 506230300Sjoerg * secrets are cleared if the authentication protocol is 506388550Sjoerg * reset to 0. */ 506488550Sjoerg if (sp->pp_phase != PHASE_DEAD && 506588600Sjoerg sp->pp_phase != PHASE_ESTABLISH) { 506688600Sjoerg rv = EBUSY; 506788600Sjoerg break; 506888600Sjoerg } 506930300Sjoerg 507088600Sjoerg if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 507188600Sjoerg spr->defs.myauth.proto != PPP_CHAP) || 507288600Sjoerg (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 507388600Sjoerg spr->defs.hisauth.proto != PPP_CHAP)) { 507488600Sjoerg rv = EINVAL; 507588600Sjoerg break; 507688600Sjoerg } 507730300Sjoerg 507888600Sjoerg if (spr->defs.myauth.proto == 0) 507930300Sjoerg /* resetting myauth */ 508030300Sjoerg bzero(&sp->myauth, sizeof sp->myauth); 508130300Sjoerg else { 508230300Sjoerg /* setting/changing myauth */ 508388600Sjoerg sp->myauth.proto = spr->defs.myauth.proto; 508488600Sjoerg bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 508588600Sjoerg if (spr->defs.myauth.secret[0] != '\0') 508688600Sjoerg bcopy(spr->defs.myauth.secret, sp->myauth.secret, 508730300Sjoerg AUTHKEYLEN); 508830300Sjoerg } 508988600Sjoerg if (spr->defs.hisauth.proto == 0) 509030300Sjoerg /* resetting hisauth */ 509130300Sjoerg bzero(&sp->hisauth, sizeof sp->hisauth); 509230300Sjoerg else { 509330300Sjoerg /* setting/changing hisauth */ 509488600Sjoerg sp->hisauth.proto = spr->defs.hisauth.proto; 509588600Sjoerg sp->hisauth.flags = spr->defs.hisauth.flags; 509688600Sjoerg bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 509788600Sjoerg if (spr->defs.hisauth.secret[0] != '\0') 509888600Sjoerg bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 509930300Sjoerg AUTHKEYLEN); 510030300Sjoerg } 510188550Sjoerg /* set LCP restart timer timeout */ 510288600Sjoerg if (spr->defs.lcp.timeout != 0) 510388600Sjoerg sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 510488534Sjoerg /* set VJ enable flag */ 510588600Sjoerg sp->enable_vj = spr->defs.enable_vj; 510630300Sjoerg break; 510730300Sjoerg 510830300Sjoerg default: 510988600Sjoerg rv = EINVAL; 511030300Sjoerg } 511130300Sjoerg 511288600Sjoerg quit: 511388600Sjoerg free(spr, M_TEMP); 511488600Sjoerg 511588600Sjoerg return (rv); 511630300Sjoerg} 511730300Sjoerg 511830300Sjoergstatic void 511930300Sjoergsppp_phase_network(struct sppp *sp) 512030300Sjoerg{ 512142066Sphk STDDCL; 512230300Sjoerg int i; 512330300Sjoerg u_long mask; 512430300Sjoerg 512530300Sjoerg sp->pp_phase = PHASE_NETWORK; 512630300Sjoerg 512742066Sphk if (debug) 512842066Sphk log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 512942066Sphk sppp_phase_name(sp->pp_phase)); 513030300Sjoerg 513130300Sjoerg /* Notify NCPs now. */ 513230300Sjoerg for (i = 0; i < IDX_COUNT; i++) 513330300Sjoerg if ((cps[i])->flags & CP_NCP) 513430300Sjoerg (cps[i])->Open(sp); 513530300Sjoerg 513630300Sjoerg /* Send Up events to all NCPs. */ 513730300Sjoerg for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 513888706Sjoerg if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 513930300Sjoerg (cps[i])->Up(sp); 514030300Sjoerg 514130300Sjoerg /* if no NCP is starting, all this was in vain, close down */ 514230300Sjoerg sppp_lcp_check_and_close(sp); 514330300Sjoerg} 514430300Sjoerg 514570199Sjhay 514625706Sjoergstatic const char * 514725944Sjoergsppp_cp_type_name(u_char type) 51484910Swollman{ 514930300Sjoerg static char buf[12]; 51504910Swollman switch (type) { 515130300Sjoerg case CONF_REQ: return "conf-req"; 515230300Sjoerg case CONF_ACK: return "conf-ack"; 515330300Sjoerg case CONF_NAK: return "conf-nak"; 515430300Sjoerg case CONF_REJ: return "conf-rej"; 515530300Sjoerg case TERM_REQ: return "term-req"; 515630300Sjoerg case TERM_ACK: return "term-ack"; 515730300Sjoerg case CODE_REJ: return "code-rej"; 515830300Sjoerg case PROTO_REJ: return "proto-rej"; 515930300Sjoerg case ECHO_REQ: return "echo-req"; 516030300Sjoerg case ECHO_REPLY: return "echo-reply"; 516130300Sjoerg case DISC_REQ: return "discard-req"; 51624910Swollman } 516344145Sphk snprintf (buf, sizeof(buf), "cp/0x%x", type); 516430300Sjoerg return buf; 51654910Swollman} 51664910Swollman 516725706Sjoergstatic const char * 516830300Sjoergsppp_auth_type_name(u_short proto, u_char type) 516930300Sjoerg{ 517030300Sjoerg static char buf[12]; 517130300Sjoerg switch (proto) { 517230300Sjoerg case PPP_CHAP: 517330300Sjoerg switch (type) { 517430300Sjoerg case CHAP_CHALLENGE: return "challenge"; 517530300Sjoerg case CHAP_RESPONSE: return "response"; 517630300Sjoerg case CHAP_SUCCESS: return "success"; 517730300Sjoerg case CHAP_FAILURE: return "failure"; 517830300Sjoerg } 517930300Sjoerg case PPP_PAP: 518030300Sjoerg switch (type) { 518130300Sjoerg case PAP_REQ: return "req"; 518230300Sjoerg case PAP_ACK: return "ack"; 518330300Sjoerg case PAP_NAK: return "nak"; 518430300Sjoerg } 518530300Sjoerg } 518644145Sphk snprintf (buf, sizeof(buf), "auth/0x%x", type); 518730300Sjoerg return buf; 518830300Sjoerg} 518930300Sjoerg 519030300Sjoergstatic const char * 519125944Sjoergsppp_lcp_opt_name(u_char opt) 51924910Swollman{ 519330300Sjoerg static char buf[12]; 519425944Sjoerg switch (opt) { 519530300Sjoerg case LCP_OPT_MRU: return "mru"; 519630300Sjoerg case LCP_OPT_ASYNC_MAP: return "async-map"; 519730300Sjoerg case LCP_OPT_AUTH_PROTO: return "auth-proto"; 519830300Sjoerg case LCP_OPT_QUAL_PROTO: return "qual-proto"; 519930300Sjoerg case LCP_OPT_MAGIC: return "magic"; 520030300Sjoerg case LCP_OPT_PROTO_COMP: return "proto-comp"; 520130300Sjoerg case LCP_OPT_ADDR_COMP: return "addr-comp"; 52024910Swollman } 520344145Sphk snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 520430300Sjoerg return buf; 52054910Swollman} 52064910Swollman 520725944Sjoergstatic const char * 520825944Sjoergsppp_ipcp_opt_name(u_char opt) 520925944Sjoerg{ 521030300Sjoerg static char buf[12]; 521125944Sjoerg switch (opt) { 521230300Sjoerg case IPCP_OPT_ADDRESSES: return "addresses"; 521330300Sjoerg case IPCP_OPT_COMPRESSION: return "compression"; 521430300Sjoerg case IPCP_OPT_ADDRESS: return "address"; 521525944Sjoerg } 521644145Sphk snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 521730300Sjoerg return buf; 521825944Sjoerg} 521925944Sjoerg 522078064Sume#ifdef INET6 522125944Sjoergstatic const char * 522278064Sumesppp_ipv6cp_opt_name(u_char opt) 522378064Sume{ 522478064Sume static char buf[12]; 522578064Sume switch (opt) { 522678064Sume case IPV6CP_OPT_IFID: return "ifid"; 522778064Sume case IPV6CP_OPT_COMPRESSION: return "compression"; 522878064Sume } 522978064Sume sprintf (buf, "0x%x", opt); 523078064Sume return buf; 523178064Sume} 523278064Sume#endif 523378064Sume 523478064Sumestatic const char * 523525944Sjoergsppp_state_name(int state) 523625944Sjoerg{ 523725944Sjoerg switch (state) { 523825944Sjoerg case STATE_INITIAL: return "initial"; 523925944Sjoerg case STATE_STARTING: return "starting"; 524025944Sjoerg case STATE_CLOSED: return "closed"; 524125944Sjoerg case STATE_STOPPED: return "stopped"; 524225944Sjoerg case STATE_CLOSING: return "closing"; 524325944Sjoerg case STATE_STOPPING: return "stopping"; 524425944Sjoerg case STATE_REQ_SENT: return "req-sent"; 524525944Sjoerg case STATE_ACK_RCVD: return "ack-rcvd"; 524625944Sjoerg case STATE_ACK_SENT: return "ack-sent"; 524725944Sjoerg case STATE_OPENED: return "opened"; 524825944Sjoerg } 524925944Sjoerg return "illegal"; 525025944Sjoerg} 525125944Sjoerg 525225944Sjoergstatic const char * 525325944Sjoergsppp_phase_name(enum ppp_phase phase) 525425944Sjoerg{ 525525944Sjoerg switch (phase) { 525625944Sjoerg case PHASE_DEAD: return "dead"; 525725944Sjoerg case PHASE_ESTABLISH: return "establish"; 525825944Sjoerg case PHASE_TERMINATE: return "terminate"; 525925944Sjoerg case PHASE_AUTHENTICATE: return "authenticate"; 526025944Sjoerg case PHASE_NETWORK: return "network"; 526125944Sjoerg } 526225944Sjoerg return "illegal"; 526325944Sjoerg} 526425944Sjoerg 526525944Sjoergstatic const char * 526625944Sjoergsppp_proto_name(u_short proto) 526725944Sjoerg{ 526825944Sjoerg static char buf[12]; 526925944Sjoerg switch (proto) { 527025944Sjoerg case PPP_LCP: return "lcp"; 527125944Sjoerg case PPP_IPCP: return "ipcp"; 527230300Sjoerg case PPP_PAP: return "pap"; 527330300Sjoerg case PPP_CHAP: return "chap"; 527478064Sume case PPP_IPV6CP: return "ipv6cp"; 527525944Sjoerg } 527644145Sphk snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 527725944Sjoerg return buf; 527825944Sjoerg} 527925944Sjoerg 528012820Sphkstatic void 528130300Sjoergsppp_print_bytes(const u_char *p, u_short len) 52824910Swollman{ 528344145Sphk if (len) 528469211Sphk log(-1, " %*D", len, p, "-"); 52854910Swollman} 528625944Sjoerg 528730300Sjoergstatic void 528830300Sjoergsppp_print_string(const char *p, u_short len) 528930300Sjoerg{ 529030300Sjoerg u_char c; 529130300Sjoerg 529230300Sjoerg while (len-- > 0) { 529330300Sjoerg c = *p++; 529430300Sjoerg /* 529530300Sjoerg * Print only ASCII chars directly. RFC 1994 recommends 529630300Sjoerg * using only them, but we don't rely on it. */ 529730300Sjoerg if (c < ' ' || c > '~') 529869211Sphk log(-1, "\\x%x", c); 529930300Sjoerg else 530069211Sphk log(-1, "%c", c); 530130300Sjoerg } 530230300Sjoerg} 530330300Sjoerg 530430300Sjoergstatic const char * 530530300Sjoergsppp_dotted_quad(u_long addr) 530630300Sjoerg{ 530730300Sjoerg static char s[16]; 530830300Sjoerg sprintf(s, "%d.%d.%d.%d", 530940008Sjoerg (int)((addr >> 24) & 0xff), 531040008Sjoerg (int)((addr >> 16) & 0xff), 531140008Sjoerg (int)((addr >> 8) & 0xff), 531238372Sbde (int)(addr & 0xff)); 531330300Sjoerg return s; 531430300Sjoerg} 531530300Sjoerg 531630300Sjoergstatic int 531730300Sjoergsppp_strnlen(u_char *p, int max) 531830300Sjoerg{ 531930300Sjoerg int len; 532030300Sjoerg 532130300Sjoerg for (len = 0; len < max && *p; ++p) 532230300Sjoerg ++len; 532330300Sjoerg return len; 532430300Sjoerg} 532530300Sjoerg 532630300Sjoerg/* a dummy, used to drop uninteresting events */ 532730300Sjoergstatic void 532830300Sjoergsppp_null(struct sppp *unused) 532930300Sjoerg{ 533030300Sjoerg /* do just nothing */ 533130300Sjoerg} 5332