if_spppsubr.c revision 131241
1163953Srrs/* 2185694Srrs * Synchronous PPP/Cisco link level subroutines. 3235828Stuexen * Keepalive protocol implemented in both Cisco and PPP modes. 4235828Stuexen * 5163953Srrs * Copyright (C) 1994-1996 Cronyx Engineering Ltd. 6163953Srrs * Author: Serge Vakulenko, <vak@cronyx.ru> 7163953Srrs * 8163953Srrs * Heavily revamped to conform to RFC 1661. 9163953Srrs * Copyright (C) 1997, 2001 Joerg Wunsch. 10228653Stuexen * 11163953Srrs * This software is distributed with NO WARRANTIES, not even the implied 12163953Srrs * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13163953Srrs * 14228653Stuexen * Authors grant any other persons or organisations permission to use 15163953Srrs * or modify this software as long as this message is kept with the software, 16163953Srrs * all derivative works or modified versions. 17163953Srrs * 18163953Srrs * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 19163953Srrs * 20163953Srrs * $FreeBSD: head/sys/net/if_spppsubr.c 131241 2004-06-28 15:32:24Z rik $ 21163953Srrs */ 22163953Srrs 23163953Srrs#include <sys/param.h> 24163953Srrs 25163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26163953Srrs#include "opt_inet.h" 27163953Srrs#include "opt_inet6.h" 28163953Srrs#include "opt_ipx.h" 29163953Srrs#endif 30163953Srrs 31163953Srrs#ifdef NetBSD1_3 32163953Srrs# if NetBSD1_3 > 6 33163953Srrs# include "opt_inet.h" 34163953Srrs# include "opt_inet6.h" 35163953Srrs# include "opt_iso.h" 36163953Srrs# endif 37163953Srrs#endif 38167598Srrs 39163953Srrs#include <sys/systm.h> 40163953Srrs#include <sys/kernel.h> 41163953Srrs#include <sys/module.h> 42163953Srrs#include <sys/sockio.h> 43163953Srrs#include <sys/socket.h> 44163953Srrs#include <sys/syslog.h> 45163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 46163953Srrs#include <sys/random.h> 47170091Srrs#endif 48172091Srrs#include <sys/malloc.h> 49188067Srrs#include <sys/mbuf.h> 50179157Srrs 51218211Srrs#if defined (__OpenBSD__) 52163953Srrs#include <sys/md5k.h> 53163953Srrs#else 54163953Srrs#include <sys/md5.h> 55163953Srrs#endif 56163953Srrs 57163953Srrs#include <net/if.h> 58163953Srrs#include <net/netisr.h> 59163953Srrs#include <net/if_types.h> 60165220Srrs#include <net/route.h> 61165220Srrs#include <netinet/in.h> 62165220Srrs#include <netinet/in_systm.h> 63165220Srrs#include <netinet/ip.h> 64165220Srrs#include <net/slcompress.h> 65163953Srrs 66163953Srrs#if defined (__NetBSD__) || defined (__OpenBSD__) 67165220Srrs#include <machine/cpu.h> /* XXX for softnet */ 68163953Srrs#endif 69163953Srrs 70163953Srrs#include <machine/stdarg.h> 71165220Srrs 72165220Srrs#include <netinet/in.h> 73165220Srrs#include <netinet/in_systm.h> 74165220Srrs#include <netinet/in_var.h> 75165220Srrs 76165220Srrs#ifdef INET 77163953Srrs#include <netinet/ip.h> 78163953Srrs#include <netinet/tcp.h> 79163953Srrs#endif 80163953Srrs 81163953Srrs#if defined (__FreeBSD__) || defined (__OpenBSD__) 82163953Srrs# include <netinet/if_ether.h> 83237715Stuexen#else 84237715Stuexen# include <net/ethertypes.h> 85237049Stuexen#endif 86237049Stuexen 87237049Stuexen#ifdef IPX 88237049Stuexen#include <netipx/ipx.h> 89163953Srrs#include <netipx/ipx_if.h> 90163953Srrs#endif 91163953Srrs 92163953Srrs#include <net/if_sppp.h> 93169420Srrs 94169420Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 95172396Srrs# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) 96172396Srrs# define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) 97172396Srrs# define IOCTL_CMD_T u_long 98229774Stuexen#else 99163953Srrs# define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) 100163953Srrs# define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) 101237715Stuexen# define IOCTL_CMD_T int 102237049Stuexen#endif 103179157Srrs 104168299Srrs#define MAXALIVECNT 3 /* max. alive packets */ 105168299Srrs 106172396Srrs/* 107163953Srrs * Interface flags that can be set in an ifconfig command. 108163953Srrs * 109229774Stuexen * Setting link0 will make the link passive, i.e. it will be marked 110163953Srrs * as being administrative openable, but won't be opened to begin 111163953Srrs * with. Incoming calls will be answered, or subsequent calls with 112163953Srrs * -link1 will cause the administrative open of the LCP layer. 113237715Stuexen * 114237049Stuexen * Setting link1 will cause the link to auto-dial only as packets 115179157Srrs * arrive to be sent. 116168299Srrs * 117168299Srrs * Setting IFF_DEBUG will syslog the option negotiation and state 118172396Srrs * transitions at level kern.debug. Note: all logs consistently look 119163953Srrs * like 120163953Srrs * 121163953Srrs * <if-name><unit>: <proto-name> <additional info...> 122163953Srrs * 123237715Stuexen * with <if-name><unit> being something like "bppp0", and <proto-name> 124237049Stuexen * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc. 125179157Srrs */ 126171440Srrs 127171440Srrs#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ 128172396Srrs#define IFF_AUTO IFF_LINK1 /* auto-dial on output */ 129163953Srrs#define IFF_CISCO IFF_LINK2 /* auto-dial on output */ 130163953Srrs 131163953Srrs#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ 132163953Srrs#define PPP_UI 0x03 /* Unnumbered Information */ 133237715Stuexen#define PPP_IP 0x0021 /* Internet Protocol */ 134237049Stuexen#define PPP_ISO 0x0023 /* ISO OSI Protocol */ 135179157Srrs#define PPP_XNS 0x0025 /* Xerox NS Protocol */ 136168299Srrs#define PPP_IPX 0x002b /* Novell IPX Protocol */ 137168299Srrs#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */ 138172396Srrs#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */ 139163953Srrs#define PPP_IPV6 0x0057 /* Internet Protocol Version 6 */ 140163953Srrs#define PPP_LCP 0xc021 /* Link Control Protocol */ 141163953Srrs#define PPP_PAP 0xc023 /* Password Authentication Protocol */ 142163953Srrs#define PPP_CHAP 0xc223 /* Challenge-Handshake Auth Protocol */ 143237715Stuexen#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ 144237049Stuexen#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ 145179157Srrs 146168299Srrs#define CONF_REQ 1 /* PPP configure request */ 147168299Srrs#define CONF_ACK 2 /* PPP configure acknowledge */ 148172396Srrs#define CONF_NAK 3 /* PPP configure negative ack */ 149163953Srrs#define CONF_REJ 4 /* PPP configure reject */ 150163953Srrs#define TERM_REQ 5 /* PPP terminate request */ 151229774Stuexen#define TERM_ACK 6 /* PPP terminate acknowledge */ 152163953Srrs#define CODE_REJ 7 /* PPP code reject */ 153237715Stuexen#define PROTO_REJ 8 /* PPP protocol reject */ 154237049Stuexen#define ECHO_REQ 9 /* PPP echo request */ 155237049Stuexen#define ECHO_REPLY 10 /* PPP echo reply */ 156168299Srrs#define DISC_REQ 11 /* PPP discard request */ 157168299Srrs 158172396Srrs#define LCP_OPT_MRU 1 /* maximum receive unit */ 159163953Srrs#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ 160229774Stuexen#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ 161229774Stuexen#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ 162229774Stuexen#define LCP_OPT_MAGIC 5 /* magic number */ 163229774Stuexen#define LCP_OPT_RESERVED 6 /* reserved */ 164229774Stuexen#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ 165229774Stuexen#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ 166229774Stuexen 167229774Stuexen#define IPCP_OPT_ADDRESSES 1 /* both IP addresses; deprecated */ 168229774Stuexen#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */ 169229774Stuexen#define IPCP_OPT_ADDRESS 3 /* local IP address */ 170229774Stuexen 171229774Stuexen#define IPV6CP_OPT_IFID 1 /* interface identifier */ 172229774Stuexen#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */ 173229774Stuexen 174229774Stuexen#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */ 175229774Stuexen 176229774Stuexen#define PAP_REQ 1 /* PAP name/password request */ 177229774Stuexen#define PAP_ACK 2 /* PAP acknowledge */ 178229774Stuexen#define PAP_NAK 3 /* PAP fail */ 179229774Stuexen 180229774Stuexen#define CHAP_CHALLENGE 1 /* CHAP challenge request */ 181229805Stuexen#define CHAP_RESPONSE 2 /* CHAP challenge response */ 182237715Stuexen#define CHAP_SUCCESS 3 /* CHAP response ok */ 183237049Stuexen#define CHAP_FAILURE 4 /* CHAP response failed */ 184237049Stuexen 185229805Stuexen#define CHAP_MD5 5 /* hash algorithm - MD5 */ 186229774Stuexen 187229774Stuexen#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 188229774Stuexen#define CISCO_UNICAST 0x0f /* Cisco unicast address */ 189229774Stuexen#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 190229774Stuexen#define CISCO_ADDR_REQ 0 /* Cisco address request */ 191229774Stuexen#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ 192229774Stuexen#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ 193229774Stuexen 194229774Stuexen/* states are named and numbered according to RFC 1661 */ 195237715Stuexen#define STATE_INITIAL 0 196237715Stuexen#define STATE_STARTING 1 197237049Stuexen#define STATE_CLOSED 2 198237049Stuexen#define STATE_STOPPED 3 199229774Stuexen#define STATE_CLOSING 4 200229774Stuexen#define STATE_STOPPING 5 201172396Srrs#define STATE_REQ_SENT 6 202172396Srrs#define STATE_ACK_RCVD 7 203172396Srrs#define STATE_ACK_SENT 8 204172396Srrs#define STATE_OPENED 9 205163953Srrs 206163953Srrsstruct ppp_header { 207163953Srrs u_char address; 208163953Srrs u_char control; 209163953Srrs u_short protocol; 210171158Srrs} __packed; 211171158Srrs#define PPP_HEADER_LEN sizeof (struct ppp_header) 212221627Stuexen 213221627Stuexenstruct lcp_header { 214221627Stuexen u_char type; 215221627Stuexen u_char ident; 216221627Stuexen u_short len; 217171158Srrs} __packed; 218171158Srrs#define LCP_HEADER_LEN sizeof (struct lcp_header) 219217760Stuexen 220217760Stuexenstruct cisco_packet { 221171158Srrs u_long type; 222171158Srrs u_long par1; 223171158Srrs u_long par2; 224171158Srrs u_short rel; 225171158Srrs u_short time0; 226171158Srrs u_short time1; 227171158Srrs} __packed; 228171158Srrs#define CISCO_PACKET_LEN sizeof (struct cisco_packet) 229171158Srrs 230171158Srrs/* 231217760Stuexen * We follow the spelling and capitalization of RFC 1661 here, to make 232217760Stuexen * it easier comparing with the standard. Please refer to this RFC in 233217760Stuexen * case you can't make sense out of these abbreviation; it will also 234217760Stuexen * explain the semantics related to the various events and actions. 235217760Stuexen */ 236217760Stuexenstruct cp { 237217760Stuexen u_short proto; /* PPP control protocol number */ 238217760Stuexen u_char protoidx; /* index into state table in struct sppp */ 239171158Srrs u_char flags; 240171158Srrs#define CP_LCP 0x01 /* this is the LCP */ 241171158Srrs#define CP_AUTH 0x02 /* this is an authentication protocol */ 242171158Srrs#define CP_NCP 0x04 /* this is a NCP */ 243171158Srrs#define CP_QUAL 0x08 /* this is a quality reporting protocol */ 244171158Srrs const char *name; /* name of this control protocol */ 245171158Srrs /* event handlers */ 246171158Srrs void (*Up)(struct sppp *sp); 247171158Srrs void (*Down)(struct sppp *sp); 248171158Srrs void (*Open)(struct sppp *sp); 249171158Srrs void (*Close)(struct sppp *sp); 250171158Srrs void (*TO)(void *sp); 251171158Srrs int (*RCR)(struct sppp *sp, struct lcp_header *h, int len); 252171158Srrs void (*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len); 253171158Srrs void (*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len); 254171158Srrs /* actions */ 255217760Stuexen void (*tlu)(struct sppp *sp); 256217760Stuexen void (*tld)(struct sppp *sp); 257212712Stuexen void (*tls)(struct sppp *sp); 258212712Stuexen void (*tlf)(struct sppp *sp); 259212712Stuexen void (*scr)(struct sppp *sp); 260212712Stuexen}; 261171158Srrs 262171158Srrsstatic struct sppp *spppq; 263171158Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 264171158Srrsstatic struct callout_handle keepalive_ch; 265221627Stuexen#endif 266171158Srrs 267171158Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 && __FreeBSD_version < 501113 268216822Stuexen#define SPP_FMT "%s%d: " 269171158Srrs#define SPP_ARGS(ifp) (ifp)->if_name, (ifp)->if_unit 270171158Srrs#else 271171158Srrs#define SPP_FMT "%s: " 272171158Srrs#define SPP_ARGS(ifp) (ifp)->if_xname 273171158Srrs#endif 274171158Srrs 275171158Srrs#ifdef INET 276163953Srrs/* 277228653Stuexen * The following disgusting hack gets around the problem that IP TOS 278163953Srrs * can't be set yet. We want to put "interactive" traffic on a high 279163953Srrs * priority queue. To decide if traffic is interactive, we check that 280163953Srrs * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control. 281163953Srrs * 282163953Srrs * XXX is this really still necessary? - joerg - 283163953Srrs */ 284163953Srrsstatic const u_short interactive_ports[8] = { 285163953Srrs 0, 513, 0, 0, 286163953Srrs 0, 21, 0, 23, 287163953Srrs}; 288163953Srrs#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 289218129Srrs#endif 290218129Srrs 291218129Srrs/* almost every function needs these */ 292212712Stuexen#define STDDCL \ 293163953Srrs struct ifnet *ifp = &sp->pp_if; \ 294163953Srrs int debug = ifp->if_flags & IFF_DEBUG 295163953Srrs 296179783Srrsstatic int sppp_output(struct ifnet *ifp, struct mbuf *m, 297170744Srrs struct sockaddr *dst, struct rtentry *rt); 298170744Srrs 299163953Srrsstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2); 300163953Srrsstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m); 301164181Srrs 302163953Srrsstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp, 303163953Srrs struct mbuf *m); 304163953Srrsstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, 305216822Stuexen u_char ident, u_short len, void *data); 306216822Stuexen/* static void sppp_cp_timeout(void *arg); */ 307163953Srrsstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, 308196260Stuexen int newstate); 309163953Srrsstatic void sppp_auth_send(const struct cp *cp, 310216822Stuexen struct sppp *sp, unsigned int type, unsigned int id, 311216822Stuexen ...); 312216822Stuexen 313216822Stuexenstatic void sppp_up_event(const struct cp *cp, struct sppp *sp); 314216822Stuexenstatic void sppp_down_event(const struct cp *cp, struct sppp *sp); 315216822Stuexenstatic void sppp_open_event(const struct cp *cp, struct sppp *sp); 316235416Stuexenstatic void sppp_close_event(const struct cp *cp, struct sppp *sp); 317235416Stuexenstatic void sppp_to_event(const struct cp *cp, struct sppp *sp); 318216822Stuexen 319216822Stuexenstatic void sppp_null(struct sppp *sp); 320216822Stuexen 321196260Stuexenstatic void sppp_lcp_init(struct sppp *sp); 322196260Stuexenstatic void sppp_lcp_up(struct sppp *sp); 323221627Stuexenstatic void sppp_lcp_down(struct sppp *sp); 324216822Stuexenstatic void sppp_lcp_open(struct sppp *sp); 325196260Stuexenstatic void sppp_lcp_close(struct sppp *sp); 326196260Stuexenstatic void sppp_lcp_TO(void *sp); 327163953Srrsstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 328163953Srrsstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 329163953Srrsstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 330216822Stuexenstatic void sppp_lcp_tlu(struct sppp *sp); 331196260Stuexenstatic void sppp_lcp_tld(struct sppp *sp); 332163953Srrsstatic void sppp_lcp_tls(struct sppp *sp); 333163953Srrsstatic void sppp_lcp_tlf(struct sppp *sp); 334235416Stuexenstatic void sppp_lcp_scr(struct sppp *sp); 335163953Srrsstatic void sppp_lcp_check_and_close(struct sppp *sp); 336163953Srrsstatic int sppp_ncp_check(struct sppp *sp); 337163953Srrs 338163953Srrsstatic void sppp_ipcp_init(struct sppp *sp); 339212712Stuexenstatic void sppp_ipcp_up(struct sppp *sp); 340212712Stuexenstatic void sppp_ipcp_down(struct sppp *sp); 341212712Stuexenstatic void sppp_ipcp_open(struct sppp *sp); 342212712Stuexenstatic void sppp_ipcp_close(struct sppp *sp); 343163953Srrsstatic void sppp_ipcp_TO(void *sp); 344221627Stuexenstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len); 345169655Srrsstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 346163953Srrsstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 347163953Srrsstatic void sppp_ipcp_tlu(struct sppp *sp); 348163953Srrsstatic void sppp_ipcp_tld(struct sppp *sp); 349196260Stuexenstatic void sppp_ipcp_tls(struct sppp *sp); 350163953Srrsstatic void sppp_ipcp_tlf(struct sppp *sp); 351163953Srrsstatic void sppp_ipcp_scr(struct sppp *sp); 352164181Srrs 353188854Srrsstatic void sppp_ipv6cp_init(struct sppp *sp); 354218129Srrsstatic void sppp_ipv6cp_up(struct sppp *sp); 355185694Srrsstatic void sppp_ipv6cp_down(struct sppp *sp); 356185694Srrsstatic void sppp_ipv6cp_open(struct sppp *sp); 357179783Srrsstatic void sppp_ipv6cp_close(struct sppp *sp); 358170744Srrsstatic void sppp_ipv6cp_TO(void *sp); 359170744Srrsstatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len); 360163953Srrsstatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len); 361163953Srrsstatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len); 362163953Srrsstatic void sppp_ipv6cp_tlu(struct sppp *sp); 363163953Srrsstatic void sppp_ipv6cp_tld(struct sppp *sp); 364180955Srrsstatic void sppp_ipv6cp_tls(struct sppp *sp); 365218129Srrsstatic void sppp_ipv6cp_tlf(struct sppp *sp); 366163953Srrsstatic void sppp_ipv6cp_scr(struct sppp *sp); 367163953Srrs 368170091Srrsstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m); 369163953Srrsstatic void sppp_pap_init(struct sppp *sp); 370163953Srrsstatic void sppp_pap_open(struct sppp *sp); 371216822Stuexenstatic void sppp_pap_close(struct sppp *sp); 372164181Srrsstatic void sppp_pap_TO(void *sp); 373164181Srrsstatic void sppp_pap_my_TO(void *sp); 374216822Stuexenstatic void sppp_pap_tlu(struct sppp *sp); 375164181Srrsstatic void sppp_pap_tld(struct sppp *sp); 376164181Srrsstatic void sppp_pap_scr(struct sppp *sp); 377171158Srrs 378164181Srrsstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m); 379164181Srrsstatic void sppp_chap_init(struct sppp *sp); 380164181Srrsstatic void sppp_chap_open(struct sppp *sp); 381164181Srrsstatic void sppp_chap_close(struct sppp *sp); 382164181Srrsstatic void sppp_chap_TO(void *sp); 383170091Srrsstatic void sppp_chap_tlu(struct sppp *sp); 384163953Srrsstatic void sppp_chap_tld(struct sppp *sp); 385164181Srrsstatic void sppp_chap_scr(struct sppp *sp); 386164181Srrs 387164181Srrsstatic const char *sppp_auth_type_name(u_short proto, u_char type); 388164181Srrsstatic const char *sppp_cp_type_name(u_char type); 389163953Srrsstatic const char *sppp_dotted_quad(u_long addr); 390170091Srrsstatic const char *sppp_ipcp_opt_name(u_char opt); 391163953Srrs#ifdef INET6 392163953Srrsstatic const char *sppp_ipv6cp_opt_name(u_char opt); 393169420Srrs#endif 394163953Srrsstatic const char *sppp_lcp_opt_name(u_char opt); 395163953Srrsstatic const char *sppp_phase_name(enum ppp_phase phase); 396163953Srrsstatic const char *sppp_proto_name(u_short proto); 397163953Srrsstatic const char *sppp_state_name(int state); 398163953Srrsstatic int sppp_params(struct sppp *sp, u_long cmd, void *data); 399163953Srrsstatic int sppp_strnlen(u_char *p, int max); 400163953Srrsstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, 401163953Srrs u_long *srcmask); 402163953Srrsstatic void sppp_keepalive(void *dummy); 403163953Srrsstatic void sppp_phase_network(struct sppp *sp); 404163953Srrsstatic void sppp_print_bytes(const u_char *p, u_short len); 405168943Srrsstatic void sppp_print_string(const char *p, u_short len); 406163953Srrsstatic void sppp_qflush(struct ifqueue *ifq); 407163953Srrsstatic void sppp_set_ip_addr(struct sppp *sp, u_long src); 408163953Srrs#ifdef INET6 409163953Srrsstatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, 410163953Srrs struct in6_addr *dst, struct in6_addr *srcmask); 411163953Srrs#ifdef IPV6CP_MYIFID_DYN 412163953Srrsstatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src); 413163953Srrsstatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src); 414163953Srrs#endif 415163953Srrsstatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src); 416169655Srrs#endif 417163953Srrs 418163953Srrs/* our control protocol descriptors */ 419163953Srrsstatic const struct cp lcp = { 420163953Srrs PPP_LCP, IDX_LCP, CP_LCP, "lcp", 421163953Srrs sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close, 422163953Srrs sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak, 423163953Srrs sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf, 424237715Stuexen sppp_lcp_scr 425237715Stuexen}; 426237049Stuexen 427237049Stuexenstatic const struct cp ipcp = { 428237049Stuexen PPP_IPCP, IDX_IPCP, 429237049Stuexen#ifdef INET /* don't run IPCP if there's no IPv4 support */ 430163953Srrs CP_NCP, 431163953Srrs#else 432163953Srrs 0, 433163953Srrs#endif 434163953Srrs "ipcp", 435185694Srrs sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close, 436163953Srrs sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak, 437163953Srrs sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf, 438163953Srrs sppp_ipcp_scr 439163953Srrs}; 440163953Srrs 441163953Srrsstatic const struct cp ipv6cp = { 442163953Srrs PPP_IPV6CP, IDX_IPV6CP, 443185694Srrs#ifdef INET6 /*don't run IPv6CP if there's no IPv6 support*/ 444163953Srrs CP_NCP, 445163953Srrs#else 446235360Stuexen 0, 447170056Srrs#endif 448163953Srrs "ipv6cp", 449163953Srrs sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close, 450163953Srrs sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak, 451185694Srrs sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf, 452163953Srrs sppp_ipv6cp_scr 453228653Stuexen}; 454163953Srrs 455163953Srrsstatic const struct cp pap = { 456163953Srrs PPP_PAP, IDX_PAP, CP_AUTH, "pap", 457163953Srrs sppp_null, sppp_null, sppp_pap_open, sppp_pap_close, 458163953Srrs sppp_pap_TO, 0, 0, 0, 459228653Stuexen sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null, 460237715Stuexen sppp_pap_scr 461237715Stuexen}; 462163953Srrs 463169420Srrsstatic const struct cp chap = { 464169420Srrs PPP_CHAP, IDX_CHAP, CP_AUTH, "chap", 465169420Srrs sppp_null, sppp_null, sppp_chap_open, sppp_chap_close, 466237715Stuexen sppp_chap_TO, 0, 0, 0, 467237715Stuexen sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null, 468237049Stuexen sppp_chap_scr 469237049Stuexen}; 470168299Srrs 471163953Srrsstatic const struct cp *cps[IDX_COUNT] = { 472163953Srrs &lcp, /* IDX_LCP */ 473171477Srrs &ipcp, /* IDX_IPCP */ 474171477Srrs &ipv6cp, /* IDX_IPV6CP */ 475216822Stuexen &pap, /* IDX_PAP */ 476171477Srrs &chap, /* IDX_CHAP */ 477216822Stuexen}; 478216822Stuexen 479216822Stuexenstatic int 480171477Srrssppp_modevent(module_t mod, int type, void *unused) 481171477Srrs{ 482163953Srrs switch (type) { 483163953Srrs case MOD_LOAD: 484163953Srrs break; 485163953Srrs case MOD_UNLOAD: 486163953Srrs return EACCES; 487163953Srrs break; 488163953Srrs default: 489163953Srrs break; 490179783Srrs } 491171943Srrs return 0; 492171943Srrs} 493171943Srrsstatic moduledata_t spppmod = { 494171943Srrs "sppp", 495171943Srrs sppp_modevent, 496171943Srrs 0 497163953Srrs}; 498163953SrrsMODULE_VERSION(sppp, 1); 499163953SrrsDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY); 500163953Srrs 501163953Srrs/* 502163953Srrs * Exported functions, comprising our interface to the lower layer. 503163953Srrs */ 504163953Srrs 505163953Srrs/* 506163953Srrs * Process the received packet. 507165220Srrs */ 508163953Srrsvoid 509165220Srrssppp_input(struct ifnet *ifp, struct mbuf *m) 510218186Srrs{ 511219397Srrs struct ppp_header *h; 512165220Srrs int isr = -1; 513163953Srrs struct sppp *sp = (struct sppp *)ifp; 514163953Srrs u_char *iphdr; 515163953Srrs int hlen, vjlen, do_account = 0; 516163953Srrs int debug = ifp->if_flags & IFF_DEBUG; 517163953Srrs 518163953Srrs if (ifp->if_flags & IFF_UP) 519163953Srrs /* Count received bytes, add FCS and one flag */ 520163953Srrs ifp->if_ibytes += m->m_pkthdr.len + 3; 521163953Srrs 522163953Srrs if (m->m_pkthdr.len <= PPP_HEADER_LEN) { 523163953Srrs /* Too small packet, drop it. */ 524163953Srrs if (debug) 525163953Srrs log(LOG_DEBUG, 526163953Srrs SPP_FMT "input packet is too small, %d bytes\n", 527163953Srrs SPP_ARGS(ifp), m->m_pkthdr.len); 528163953Srrs drop: 529163953Srrs m_freem (m); 530163953Srrs drop2: 531165647Srrs ++ifp->if_ierrors; 532163953Srrs ++ifp->if_iqdrops; 533163953Srrs return; 534163953Srrs } 535163953Srrs 536163953Srrs /* Get PPP header. */ 537163953Srrs h = mtod (m, struct ppp_header*); 538163953Srrs m_adj (m, PPP_HEADER_LEN); 539163953Srrs 540163953Srrs switch (h->address) { 541163953Srrs case PPP_ALLSTATIONS: 542163953Srrs if (h->control != PPP_UI) 543237715Stuexen goto invalid; 544237049Stuexen if (sp->pp_mode == IFF_CISCO) { 545237049Stuexen if (debug) 546168299Srrs log(LOG_DEBUG, 547163953Srrs SPP_FMT "PPP packet in Cisco mode " 548163953Srrs "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 549163953Srrs SPP_ARGS(ifp), 550163953Srrs h->address, h->control, ntohs(h->protocol)); 551163953Srrs goto drop; 552163953Srrs } 553163953Srrs switch (ntohs (h->protocol)) { 554163953Srrs default: 555163953Srrs if (debug) 556163953Srrs log(LOG_DEBUG, 557163953Srrs SPP_FMT "rejecting protocol " 558212225Srrs "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 559163953Srrs SPP_ARGS(ifp), 560172396Srrs h->address, h->control, ntohs(h->protocol)); 561224641Stuexen if (sp->state[IDX_LCP] == STATE_OPENED) 562163953Srrs sppp_cp_send (sp, PPP_LCP, PROTO_REJ, 563221249Stuexen ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2, 564221249Stuexen &h->protocol); 565221249Stuexen ++ifp->if_noproto; 566221249Stuexen goto drop; 567221249Stuexen case PPP_LCP: 568221249Stuexen sppp_cp_input(&lcp, sp, m); 569221249Stuexen m_freem (m); 570221249Stuexen return; 571221249Stuexen case PPP_PAP: 572163953Srrs if (sp->pp_phase >= PHASE_AUTHENTICATE) 573163953Srrs sppp_pap_input(sp, m); 574163953Srrs m_freem (m); 575163953Srrs return; 576163953Srrs case PPP_CHAP: 577221249Stuexen if (sp->pp_phase >= PHASE_AUTHENTICATE) 578221249Stuexen sppp_chap_input(sp, m); 579221249Stuexen m_freem (m); 580221249Stuexen return; 581221249Stuexen#ifdef INET 582221249Stuexen case PPP_IPCP: 583221249Stuexen if (sp->pp_phase == PHASE_NETWORK) 584221249Stuexen sppp_cp_input(&ipcp, sp, m); 585221249Stuexen m_freem (m); 586221249Stuexen return; 587221249Stuexen case PPP_IP: 588221249Stuexen if (sp->state[IDX_IPCP] == STATE_OPENED) { 589221249Stuexen isr = NETISR_IP; 590221249Stuexen } 591221249Stuexen do_account++; 592221249Stuexen break; 593221249Stuexen case PPP_VJ_COMP: 594221249Stuexen if (sp->state[IDX_IPCP] == STATE_OPENED) { 595221249Stuexen if ((vjlen = 596221249Stuexen sl_uncompress_tcp_core(mtod(m, u_char *), 597221249Stuexen m->m_len, m->m_len, 598221249Stuexen TYPE_COMPRESSED_TCP, 599221249Stuexen sp->pp_comp, 600221249Stuexen &iphdr, &hlen)) <= 0) { 601221249Stuexen if (debug) 602221249Stuexen log(LOG_INFO, 603221249Stuexen SPP_FMT "VJ uncompress failed on compressed packet\n", 604221249Stuexen SPP_ARGS(ifp)); 605221249Stuexen goto drop; 606221249Stuexen } 607163953Srrs 608163953Srrs /* 609221249Stuexen * Trim the VJ header off the packet, and prepend 610163953Srrs * the uncompressed IP header (which will usually 611169420Srrs * end up in two chained mbufs since there's not 612163953Srrs * enough leading space in the existing mbuf). 613163953Srrs */ 614163953Srrs m_adj(m, vjlen); 615163953Srrs M_PREPEND(m, hlen, M_DONTWAIT); 616163953Srrs if (m == NULL) 617163953Srrs goto drop2; 618163953Srrs bcopy(iphdr, mtod(m, u_char *), hlen); 619163953Srrs isr = NETISR_IP; 620163953Srrs } 621163953Srrs do_account++; 622167598Srrs break; 623167598Srrs case PPP_VJ_UCOMP: 624167598Srrs if (sp->state[IDX_IPCP] == STATE_OPENED) { 625212225Srrs if (sl_uncompress_tcp_core(mtod(m, u_char *), 626212225Srrs m->m_len, m->m_len, 627167598Srrs TYPE_UNCOMPRESSED_TCP, 628167598Srrs sp->pp_comp, 629167598Srrs &iphdr, &hlen) != 0) { 630167598Srrs if (debug) 631167598Srrs log(LOG_INFO, 632167598Srrs SPP_FMT "VJ uncompress failed on uncompressed packet\n", 633212225Srrs SPP_ARGS(ifp)); 634212225Srrs goto drop; 635167598Srrs } 636172396Srrs isr = NETISR_IP; 637167598Srrs } 638163953Srrs do_account++; 639172090Srrs break; 640224641Stuexen#endif 641224641Stuexen#ifdef INET6 642163953Srrs case PPP_IPV6CP: 643224641Stuexen if (sp->pp_phase == PHASE_NETWORK) 644163953Srrs sppp_cp_input(&ipv6cp, sp, m); 645163953Srrs m_freem (m); 646163953Srrs return; 647163953Srrs 648224641Stuexen case PPP_IPV6: 649224641Stuexen if (sp->state[IDX_IPV6CP] == STATE_OPENED) 650224641Stuexen isr = NETISR_IPV6; 651224641Stuexen do_account++; 652163953Srrs break; 653163953Srrs#endif 654235414Stuexen#ifdef IPX 655163953Srrs case PPP_IPX: 656224641Stuexen /* IPX IPXCP not implemented yet */ 657224641Stuexen if (sp->pp_phase == PHASE_NETWORK) 658224641Stuexen isr = NETISR_IPX; 659224641Stuexen do_account++; 660224641Stuexen break; 661224641Stuexen#endif 662224641Stuexen } 663224641Stuexen break; 664224641Stuexen case CISCO_MULTICAST: 665224641Stuexen case CISCO_UNICAST: 666224641Stuexen /* Don't check the control field here (RFC 1547). */ 667224641Stuexen if (sp->pp_mode != IFF_CISCO) { 668224641Stuexen if (debug) 669171440Srrs log(LOG_DEBUG, 670171440Srrs SPP_FMT "Cisco packet in PPP mode " 671172396Srrs "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 672172396Srrs SPP_ARGS(ifp), 673172396Srrs h->address, h->control, ntohs(h->protocol)); 674172396Srrs goto drop; 675172396Srrs } 676172396Srrs switch (ntohs (h->protocol)) { 677172396Srrs default: 678172396Srrs ++ifp->if_noproto; 679172396Srrs goto invalid; 680172396Srrs case CISCO_KEEPALIVE: 681172396Srrs sppp_cisco_input ((struct sppp*) ifp, m); 682172396Srrs m_freem (m); 683172396Srrs return; 684172396Srrs#ifdef INET 685172396Srrs case ETHERTYPE_IP: 686172396Srrs isr = NETISR_IP; 687172396Srrs do_account++; 688212712Stuexen break; 689212712Stuexen#endif 690172396Srrs#ifdef INET6 691172396Srrs case ETHERTYPE_IPV6: 692172396Srrs isr = NETISR_IPV6; 693172396Srrs do_account++; 694172396Srrs break; 695163953Srrs#endif 696163953Srrs#ifdef IPX 697185694Srrs case ETHERTYPE_IPX: 698185694Srrs isr = NETISR_IPX; 699185694Srrs do_account++; 700185694Srrs break; 701185694Srrs#endif 702185694Srrs } 703185694Srrs break; 704185694Srrs default: /* Invalid PPP packet. */ 705185694Srrs invalid: 706185694Srrs if (debug) 707185694Srrs log(LOG_DEBUG, 708185694Srrs SPP_FMT "invalid input packet " 709185694Srrs "<addr=0x%x ctrl=0x%x proto=0x%x>\n", 710185694Srrs SPP_ARGS(ifp), 711185694Srrs h->address, h->control, ntohs(h->protocol)); 712185694Srrs goto drop; 713185694Srrs } 714185694Srrs 715185694Srrs if (! (ifp->if_flags & IFF_UP) || isr == -1) 716185694Srrs goto drop; 717185694Srrs 718185694Srrs /* Check queue. */ 719185694Srrs if (! netisr_queue(isr, m)) { 720185694Srrs if (debug) 721185694Srrs log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", 722185694Srrs SPP_ARGS(ifp)); 723185694Srrs goto drop2; 724185694Srrs } 725185694Srrs if (do_account) 726185694Srrs /* 727185694Srrs * Do only account for network packets, not for control 728185694Srrs * packets. This is used by some subsystems to detect 729185694Srrs * idle lines. 730185694Srrs */ 731185694Srrs sp->pp_last_recv = time_second; 732185694Srrs} 733185694Srrs 734185694Srrs/* 735185694Srrs * Enqueue transmit packet. 736185694Srrs */ 737185694Srrsstatic int 738185694Srrssppp_output(struct ifnet *ifp, struct mbuf *m, 739185694Srrs struct sockaddr *dst, struct rtentry *rt) 740185694Srrs{ 741185694Srrs struct sppp *sp = (struct sppp*) ifp; 742185694Srrs struct ppp_header *h; 743185694Srrs struct ifqueue *ifq = NULL; 744185694Srrs int s, error, rv = 0; 745185694Srrs int ipproto = PPP_IP; 746185694Srrs int debug = ifp->if_flags & IFF_DEBUG; 747185694Srrs 748185694Srrs s = splimp(); 749185694Srrs 750185694Srrs if ((ifp->if_flags & IFF_UP) == 0 || 751185694Srrs (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) { 752185694Srrs#ifdef INET6 753185694Srrs drop: 754185694Srrs#endif 755185694Srrs m_freem (m); 756185694Srrs splx (s); 757185694Srrs return (ENETDOWN); 758185694Srrs } 759185694Srrs 760163953Srrs if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) { 761235360Stuexen#ifdef INET6 762163953Srrs /* 763163953Srrs * XXX 764237565Stuexen * 765172090Srrs * Hack to prevent the initialization-time generated 766172090Srrs * IPv6 multicast packet to erroneously cause a 767172090Srrs * dialout event in case IPv6 has been 768185694Srrs * administratively disabled on that interface. 769235360Stuexen */ 770172090Srrs if (dst->sa_family == AF_INET6 && 771169420Srrs !(sp->confflags & CONF_ENABLE_IPV6)) 772163953Srrs goto drop; 773163953Srrs#endif 774163953Srrs /* 775235360Stuexen * Interface is not yet running, but auto-dial. Need 776185694Srrs * to start LCP for it. 777185694Srrs */ 778185694Srrs ifp->if_flags |= IFF_RUNNING; 779185694Srrs splx(s); 780185694Srrs lcp.Open(sp); 781185694Srrs s = splimp(); 782185694Srrs } 783235360Stuexen 784235360Stuexen#ifdef INET 785235360Stuexen if (dst->sa_family == AF_INET) { 786185694Srrs /* XXX Check mbuf length here? */ 787235360Stuexen struct ip *ip = mtod (m, struct ip*); 788185694Srrs struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); 789185694Srrs 790185694Srrs /* 791235360Stuexen * When using dynamic local IP address assignment by using 792185694Srrs * 0.0.0.0 as a local address, the first TCP session will 793235360Stuexen * not connect because the local TCP checksum is computed 794185694Srrs * using 0.0.0.0 which will later become our real IP address 795185694Srrs * so the TCP checksum computed at the remote end will 796185694Srrs * become invalid. So we 797185694Srrs * - don't let packets with src ip addr 0 thru 798235360Stuexen * - we flag TCP packets with src ip 0 as an error 799235360Stuexen */ 800185694Srrs 801163953Srrs if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ 802171440Srrs { 803163953Srrs m_freem(m); 804235403Stuexen splx(s); 805163953Srrs if(ip->ip_p == IPPROTO_TCP) 806163953Srrs return(EADDRNOTAVAIL); 807163953Srrs else 808163953Srrs return(0); 809163953Srrs } 810163953Srrs 811168859Srrs /* 812168859Srrs * Put low delay, telnet, rlogin and ftp control packets 813168859Srrs * in front of the queue or let ALTQ take care. 814237565Stuexen */ 815172090Srrs if (ALTQ_IS_ENABLED(&ifp->if_snd)) 816172090Srrs ; 817172090Srrs else if (_IF_QFULL(&sp->pp_fastq)) 818172090Srrs ; 819172090Srrs else if (ip->ip_tos & IPTOS_LOWDELAY) 820172090Srrs ifq = &sp->pp_fastq; 821172090Srrs else if (m->m_len < sizeof *ip + sizeof *tcp) 822171990Srrs ; 823171943Srrs else if (ip->ip_p != IPPROTO_TCP) 824171943Srrs ; 825237565Stuexen else if (INTERACTIVE (ntohs (tcp->th_sport))) 826172090Srrs ifq = &sp->pp_fastq; 827172090Srrs else if (INTERACTIVE (ntohs (tcp->th_dport))) 828169420Srrs ifq = &sp->pp_fastq; 829163953Srrs 830163953Srrs /* 831163953Srrs * Do IP Header compression 832224641Stuexen */ 833224641Stuexen if (sp->pp_mode != IFF_CISCO && (sp->ipcp.flags & IPCP_VJ) && 834224641Stuexen ip->ip_p == IPPROTO_TCP) 835224641Stuexen switch (sl_compress_tcp(m, ip, sp->pp_comp, 836224641Stuexen sp->ipcp.compress_cid)) { 837224641Stuexen case TYPE_COMPRESSED_TCP: 838224641Stuexen ipproto = PPP_VJ_COMP; 839224641Stuexen break; 840224641Stuexen case TYPE_UNCOMPRESSED_TCP: 841224641Stuexen ipproto = PPP_VJ_UCOMP; 842224641Stuexen break; 843224641Stuexen case TYPE_IP: 844224641Stuexen ipproto = PPP_IP; 845224641Stuexen break; 846224641Stuexen default: 847224641Stuexen m_freem(m); 848224641Stuexen splx(s); 849224641Stuexen return (EINVAL); 850224641Stuexen } 851224641Stuexen } 852224641Stuexen#endif 853224641Stuexen 854224641Stuexen#ifdef INET6 855224641Stuexen if (dst->sa_family == AF_INET6) { 856224641Stuexen /* XXX do something tricky here? */ 857224641Stuexen } 858224641Stuexen#endif 859224641Stuexen 860224641Stuexen /* 861163953Srrs * Prepend general data packet PPP header. For now, IP only. 862163953Srrs */ 863163953Srrs M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT); 864163953Srrs if (! m) { 865163953Srrs if (debug) 866163953Srrs log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n", 867237565Stuexen SPP_ARGS(ifp)); 868172090Srrs ++ifp->if_oerrors; 869172090Srrs splx (s); 870172090Srrs return (ENOBUFS); 871172090Srrs } 872169420Srrs /* 873169420Srrs * May want to check size of packet 874163953Srrs * (albeit due to the implementation it's always enough) 875163953Srrs */ 876165220Srrs h = mtod (m, struct ppp_header*); 877165220Srrs if (sp->pp_mode == IFF_CISCO) { 878165220Srrs h->address = CISCO_UNICAST; /* unicast address */ 879163953Srrs h->control = 0; 880163953Srrs } else { 881163953Srrs h->address = PPP_ALLSTATIONS; /* broadcast address */ 882163953Srrs h->control = PPP_UI; /* Unnumbered Info */ 883163953Srrs } 884163953Srrs 885228653Stuexen switch (dst->sa_family) { 886199477Stuexen#ifdef INET 887199477Stuexen case AF_INET: /* Internet Protocol */ 888199477Stuexen if (sp->pp_mode == IFF_CISCO) 889163953Srrs h->protocol = htons (ETHERTYPE_IP); 890165220Srrs else { 891163953Srrs /* 892163953Srrs * Don't choke with an ENETDOWN early. It's 893163953Srrs * possible that we just started dialing out, 894163953Srrs * so don't drop the packet immediately. If 895165220Srrs * we notice that we run out of buffer space 896165220Srrs * below, we will however remember that we are 897165220Srrs * not ready to carry IP packets, and return 898163953Srrs * ENETDOWN, as opposed to ENOBUFS. 899237565Stuexen */ 900172090Srrs h->protocol = htons(ipproto); 901172090Srrs if (sp->state[IDX_IPCP] != STATE_OPENED) 902172090Srrs rv = ENETDOWN; 903172090Srrs } 904172090Srrs break; 905172090Srrs#endif 906172090Srrs#ifdef INET6 907172090Srrs case AF_INET6: /* Internet Protocol */ 908172090Srrs if (sp->pp_mode == IFF_CISCO) 909172090Srrs h->protocol = htons (ETHERTYPE_IPV6); 910172090Srrs else { 911172090Srrs /* 912163996Srrs * Don't choke with an ENETDOWN early. It's 913237565Stuexen * possible that we just started dialing out, 914172090Srrs * so don't drop the packet immediately. If 915172090Srrs * we notice that we run out of buffer space 916163953Srrs * below, we will however remember that we are 917163953Srrs * not ready to carry IP packets, and return 918163953Srrs * ENETDOWN, as opposed to ENOBUFS. 919163953Srrs */ 920170056Srrs h->protocol = htons(PPP_IPV6); 921163953Srrs if (sp->state[IDX_IPV6CP] != STATE_OPENED) 922171943Srrs rv = ENETDOWN; 923172703Srrs } 924163953Srrs break; 925163953Srrs#endif 926163953Srrs#ifdef IPX 927163953Srrs case AF_IPX: /* Novell IPX Protocol */ 928172090Srrs h->protocol = htons (sp->pp_mode == IFF_CISCO ? 929163953Srrs ETHERTYPE_IPX : PPP_IPX); 930163953Srrs break; 931169378Srrs#endif 932163953Srrs default: 933163953Srrs m_freem (m); 934163953Srrs ++ifp->if_oerrors; 935163953Srrs splx (s); 936163953Srrs return (EAFNOSUPPORT); 937163953Srrs } 938163953Srrs 939171440Srrs /* 940163953Srrs * Queue message on interface, and start output if interface 941171158Srrs * not yet active. 942221627Stuexen */ 943163953Srrs if (ifq != NULL) 944163953Srrs error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3)); 945163953Srrs else 946163953Srrs IFQ_HANDOFF_ADJ(ifp, m, 3, error); 947163953Srrs if (error) { 948163953Srrs ++ifp->if_oerrors; 949163953Srrs splx (s); 950163953Srrs return (rv? rv: ENOBUFS); 951163953Srrs } 952224641Stuexen splx (s); 953163953Srrs /* 954166675Srrs * Unlike in sppp_input(), we can always bump the timestamp 955166675Srrs * here since sppp_output() is only called on behalf of 956163953Srrs * network-layer traffic; control-layer traffic is handled 957163953Srrs * by sppp_cp_send(). 958171943Srrs */ 959172703Srrs sp->pp_last_sent = time_second; 960214918Stuexen return (0); 961163953Srrs} 962163953Srrs 963163953Srrsvoid 964163953Srrssppp_attach(struct ifnet *ifp) 965163953Srrs{ 966163953Srrs struct sppp *sp = (struct sppp*) ifp; 967228653Stuexen 968204141Stuexen /* Initialize keepalive handler. */ 969204141Stuexen if (spppq == NULL) 970163953Srrs TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 971163953Srrs 972163953Srrs /* Insert new entry into the keepalive list. */ 973237565Stuexen sp->pp_next = spppq; 974172090Srrs spppq = sp; 975172090Srrs 976172090Srrs sp->pp_if.if_mtu = PP_MTU; 977172090Srrs sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 978169420Srrs sp->pp_if.if_type = IFT_PPP; 979169420Srrs sp->pp_if.if_output = sppp_output; 980163953Srrs#if 0 981163953Srrs sp->pp_flags = PP_KEEPALIVE; 982163953Srrs#endif 983163953Srrs sp->pp_if.if_snd.ifq_maxlen = 32; 984163953Srrs sp->pp_fastq.ifq_maxlen = 32; 985204141Stuexen sp->pp_cpq.ifq_maxlen = 20; 986204141Stuexen sp->pp_loopcnt = 0; 987204141Stuexen sp->pp_alivecnt = 0; 988204141Stuexen bzero(&sp->pp_seq[0], sizeof(sp->pp_seq)); 989204141Stuexen bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq)); 990204141Stuexen sp->pp_phase = PHASE_DEAD; 991204141Stuexen sp->pp_up = lcp.Up; 992163953Srrs sp->pp_down = lcp.Down; 993163953Srrs if(!mtx_initialized(&sp->pp_cpq.ifq_mtx)) 994163953Srrs mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF); 995163953Srrs if(!mtx_initialized(&sp->pp_fastq.ifq_mtx)) 996163953Srrs mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF); 997163953Srrs sp->pp_last_recv = sp->pp_last_sent = time_second; 998165220Srrs sp->confflags = 0; 999163953Srrs#ifdef INET 1000163953Srrs sp->confflags |= CONF_ENABLE_VJ; 1001163953Srrs#endif 1002163953Srrs#ifdef INET6 1003165220Srrs sp->confflags |= CONF_ENABLE_IPV6; 1004165220Srrs#endif 1005165220Srrs sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK); 1006163953Srrs sl_compress_init(sp->pp_comp, -1); 1007237565Stuexen sppp_lcp_init(sp); 1008172090Srrs sppp_ipcp_init(sp); 1009172090Srrs sppp_ipv6cp_init(sp); 1010172090Srrs sppp_pap_init(sp); 1011172090Srrs sppp_chap_init(sp); 1012172090Srrs} 1013172090Srrs 1014172090Srrsvoid 1015172090Srrssppp_detach(struct ifnet *ifp) 1016172090Srrs{ 1017172090Srrs struct sppp **q, *p, *sp = (struct sppp*) ifp; 1018172090Srrs int i; 1019163996Srrs 1020237565Stuexen /* Remove the entry from the keepalive list. */ 1021172090Srrs for (q = &spppq; (p = *q); q = &p->pp_next) 1022172090Srrs if (p == sp) { 1023163953Srrs *q = p->pp_next; 1024163953Srrs break; 1025163953Srrs } 1026163953Srrs 1027217760Stuexen /* Stop keepalive handler. */ 1028235416Stuexen if (spppq == NULL) 1029163953Srrs UNTIMEOUT(sppp_keepalive, 0, keepalive_ch); 1030163953Srrs 1031171440Srrs for (i = 0; i < IDX_COUNT; i++) 1032163953Srrs UNTIMEOUT((cps[i])->TO, (void *)sp, sp->ch[i]); 1033204141Stuexen UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 1034163953Srrs mtx_destroy(&sp->pp_cpq.ifq_mtx); 1035163953Srrs mtx_destroy(&sp->pp_fastq.ifq_mtx); 1036163953Srrs} 1037163953Srrs 1038229774Stuexen/* 1039163953Srrs * Flush the interface output queue. 1040230379Stuexen */ 1041163953Srrsvoid 1042163953Srrssppp_flush(struct ifnet *ifp) 1043163953Srrs{ 1044237565Stuexen struct sppp *sp = (struct sppp*) ifp; 1045172090Srrs 1046172090Srrs sppp_qflush ((struct ifqueue *)&sp->pp_if.if_snd); 1047172090Srrs sppp_qflush (&sp->pp_fastq); 1048172090Srrs sppp_qflush (&sp->pp_cpq); 1049172090Srrs} 1050172090Srrs 1051171943Srrs/* 1052171440Srrs * Check if the output queue is empty. 1053237565Stuexen */ 1054172090Srrsint 1055172090Srrssppp_isempty(struct ifnet *ifp) 1056163953Srrs{ 1057163953Srrs struct sppp *sp = (struct sppp*) ifp; 1058163953Srrs int empty, s; 1059163953Srrs 1060163953Srrs s = splimp(); 1061163953Srrs empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head && 1062163953Srrs !sp->pp_if.if_snd.ifq_head; 1063163953Srrs splx(s); 1064163953Srrs return (empty); 1065163953Srrs} 1066163953Srrs 1067163953Srrs/* 1068163953Srrs * Get next packet to send. 1069163953Srrs */ 1070163953Srrsstruct mbuf * 1071163953Srrssppp_dequeue(struct ifnet *ifp) 1072163953Srrs{ 1073163953Srrs struct sppp *sp = (struct sppp*) ifp; 1074163953Srrs struct mbuf *m; 1075163953Srrs int s; 1076163953Srrs 1077163953Srrs s = splimp(); 1078163953Srrs /* 1079169420Srrs * Process only the control protocol queue until we have at 1080169420Srrs * least one NCP open. 1081169420Srrs * 1082163953Srrs * Do always serve all three queues in Cisco mode. 1083163953Srrs */ 1084163953Srrs IF_DEQUEUE(&sp->pp_cpq, m); 1085163953Srrs if (m == NULL && 1086163953Srrs (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO)) { 1087163953Srrs IF_DEQUEUE(&sp->pp_fastq, m); 1088163953Srrs if (m == NULL) 1089163953Srrs IF_DEQUEUE (&sp->pp_if.if_snd, m); 1090163953Srrs } 1091163953Srrs splx(s); 1092163953Srrs return m; 1093163953Srrs} 1094163953Srrs 1095163953Srrs/* 1096163953Srrs * Pick the next packet, do not remove it from the queue. 1097163953Srrs */ 1098163953Srrsstruct mbuf * 1099163953Srrssppp_pick(struct ifnet *ifp) 1100163953Srrs{ 1101163953Srrs struct sppp *sp = (struct sppp*)ifp; 1102163953Srrs struct mbuf *m; 1103163953Srrs int s; 1104163953Srrs 1105185694Srrs s= splimp (); 1106185694Srrs 1107185694Srrs m = sp->pp_cpq.ifq_head; 1108163953Srrs if (m == NULL && 1109163953Srrs (sp->pp_phase == PHASE_NETWORK || sp->pp_mode == IFF_CISCO)) 1110163953Srrs if ((m = sp->pp_fastq.ifq_head) == NULL) 1111163953Srrs m = sp->pp_if.if_snd.ifq_head; 1112163953Srrs splx (s); 1113163953Srrs return (m); 1114163953Srrs} 1115169420Srrs 1116169420Srrs/* 1117169420Srrs * Process an ioctl request. Called on low priority level. 1118163953Srrs */ 1119163953Srrsint 1120163953Srrssppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) 1121169420Srrs{ 1122169420Srrs struct ifreq *ifr = (struct ifreq*) data; 1123169420Srrs struct sppp *sp = (struct sppp*) ifp; 1124163953Srrs int s, rv, going_up, going_down, newmode; 1125163953Srrs 1126163953Srrs s = splimp(); 1127163953Srrs rv = 0; 1128163953Srrs switch (cmd) { 1129163953Srrs case SIOCAIFADDR: 1130163953Srrs case SIOCSIFDSTADDR: 1131163953Srrs break; 1132163953Srrs 1133163953Srrs case SIOCSIFADDR: 1134235418Stuexen /* set the interface "up" when assigning an IP address */ 1135163953Srrs ifp->if_flags |= IFF_UP; 1136163953Srrs /* FALLTHROUGH */ 1137163953Srrs 1138163953Srrs case SIOCSIFFLAGS: 1139237565Stuexen going_up = ifp->if_flags & IFF_UP && 1140172090Srrs (ifp->if_flags & IFF_RUNNING) == 0; 1141172090Srrs going_down = (ifp->if_flags & IFF_UP) == 0 && 1142172090Srrs ifp->if_flags & IFF_RUNNING; 1143172090Srrs 1144163953Srrs newmode = ifp->if_flags & IFF_PASSIVE; 1145163953Srrs if (!newmode) 1146163953Srrs newmode = ifp->if_flags & IFF_AUTO; 1147163953Srrs if (!newmode) 1148163953Srrs newmode = ifp->if_flags & IFF_CISCO; 1149235418Stuexen ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO); 1150163953Srrs ifp->if_flags |= newmode; 1151163953Srrs 1152163953Srrs if (newmode != sp->pp_mode) { 1153163953Srrs going_down = 1; 1154163953Srrs if (!going_up) 1155163953Srrs going_up = ifp->if_flags & IFF_RUNNING; 1156169420Srrs } 1157169420Srrs 1158163953Srrs if (going_down) { 1159163953Srrs if (sp->pp_mode != IFF_CISCO) 1160235418Stuexen lcp.Close(sp); 1161235418Stuexen else if (sp->pp_tlf) 1162235418Stuexen (sp->pp_tlf)(sp); 1163235418Stuexen sppp_flush(ifp); 1164163953Srrs ifp->if_flags &= ~IFF_RUNNING; 1165163953Srrs sp->pp_mode = newmode; 1166163953Srrs } 1167163953Srrs 1168163953Srrs if (going_up) { 1169169420Srrs if (sp->pp_mode != IFF_CISCO) 1170169420Srrs lcp.Close(sp); 1171163953Srrs sp->pp_mode = newmode; 1172185694Srrs if (sp->pp_mode == 0) { 1173185694Srrs ifp->if_flags |= IFF_RUNNING; 1174185694Srrs lcp.Open(sp); 1175185694Srrs } 1176185694Srrs if (sp->pp_mode == IFF_CISCO) { 1177185694Srrs if (sp->pp_tls) 1178185694Srrs (sp->pp_tls)(sp); 1179185694Srrs ifp->if_flags |= IFF_RUNNING; 1180185694Srrs } 1181185694Srrs } 1182185694Srrs 1183185694Srrs break; 1184185694Srrs 1185185694Srrs#ifdef SIOCSIFMTU 1186163953Srrs#ifndef ifr_mtu 1187163953Srrs#define ifr_mtu ifr_metric 1188163953Srrs#endif 1189163953Srrs case SIOCSIFMTU: 1190163953Srrs if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru) 1191163953Srrs return (EINVAL); 1192163953Srrs ifp->if_mtu = ifr->ifr_mtu; 1193163953Srrs break; 1194163953Srrs#endif 1195163953Srrs#ifdef SLIOCSETMTU 1196163953Srrs case SLIOCSETMTU: 1197163953Srrs if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru) 1198163953Srrs return (EINVAL); 1199163953Srrs ifp->if_mtu = *(short*)data; 1200235403Stuexen break; 1201163953Srrs#endif 1202237565Stuexen#ifdef SIOCGIFMTU 1203172090Srrs case SIOCGIFMTU: 1204172090Srrs ifr->ifr_mtu = ifp->if_mtu; 1205172090Srrs break; 1206172090Srrs#endif 1207172090Srrs#ifdef SLIOCGETMTU 1208172090Srrs case SLIOCGETMTU: 1209172090Srrs *(short*)data = ifp->if_mtu; 1210171943Srrs break; 1211171943Srrs#endif 1212237565Stuexen case SIOCADDMULTI: 1213172090Srrs case SIOCDELMULTI: 1214172090Srrs break; 1215163953Srrs 1216163953Srrs case SIOCGIFGENERIC: 1217163953Srrs case SIOCSIFGENERIC: 1218185694Srrs rv = sppp_params(sp, cmd, data); 1219163953Srrs break; 1220163953Srrs 1221163953Srrs default: 1222172090Srrs rv = ENOTTY; 1223163953Srrs } 1224163953Srrs splx(s); 1225163953Srrs return rv; 1226163953Srrs} 1227163953Srrs 1228163953Srrs/* 1229163953Srrs * Cisco framing implementation. 1230163953Srrs */ 1231163953Srrs 1232163953Srrs/* 1233163953Srrs * Handle incoming Cisco keepalive protocol packets. 1234163953Srrs */ 1235163953Srrsstatic void 1236163953Srrssppp_cisco_input(struct sppp *sp, struct mbuf *m) 1237163953Srrs{ 1238163953Srrs STDDCL; 1239163953Srrs struct cisco_packet *h; 1240163953Srrs u_long me, mymask; 1241163953Srrs 1242163953Srrs if (m->m_pkthdr.len < CISCO_PACKET_LEN) { 1243163953Srrs if (debug) 1244163953Srrs log(LOG_DEBUG, 1245163953Srrs SPP_FMT "cisco invalid packet length: %d bytes\n", 1246163953Srrs SPP_ARGS(ifp), m->m_pkthdr.len); 1247163953Srrs return; 1248163953Srrs } 1249163953Srrs h = mtod (m, struct cisco_packet*); 1250163953Srrs if (debug) 1251163953Srrs log(LOG_DEBUG, 1252163953Srrs SPP_FMT "cisco input: %d bytes " 1253163953Srrs "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 1254163953Srrs SPP_ARGS(ifp), m->m_pkthdr.len, 1255163953Srrs (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel, 1256163953Srrs (u_int)h->time0, (u_int)h->time1); 1257166086Srrs switch (ntohl (h->type)) { 1258163953Srrs default: 1259169420Srrs if (debug) 1260169420Srrs log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n", 1261163953Srrs SPP_ARGS(ifp), (u_long)ntohl (h->type)); 1262163953Srrs break; 1263163953Srrs case CISCO_ADDR_REPLY: 1264163953Srrs /* Reply on address request, ignore */ 1265163953Srrs break; 1266166086Srrs case CISCO_KEEPALIVE_REQ: 1267163953Srrs sp->pp_alivecnt = 0; 1268163953Srrs sp->pp_rseq[IDX_LCP] = ntohl (h->par1); 1269163953Srrs if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) { 1270163953Srrs /* Local and remote sequence numbers are equal. 1271163953Srrs * Probably, the line is in loopback mode. */ 1272169420Srrs if (sp->pp_loopcnt >= MAXALIVECNT) { 1273169420Srrs printf (SPP_FMT "loopback\n", 1274163953Srrs SPP_ARGS(ifp)); 1275163953Srrs sp->pp_loopcnt = 0; 1276163953Srrs if (ifp->if_flags & IFF_UP) { 1277163953Srrs if_down (ifp); 1278163953Srrs sppp_qflush (&sp->pp_cpq); 1279163953Srrs } 1280235418Stuexen } 1281163953Srrs ++sp->pp_loopcnt; 1282163953Srrs 1283163953Srrs /* Generate new local sequence number */ 1284163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 1285237715Stuexen sp->pp_seq[IDX_LCP] = random(); 1286237715Stuexen#else 1287237049Stuexen sp->pp_seq[IDX_LCP] ^= time.tv_sec ^ time.tv_usec; 1288237049Stuexen#endif 1289237049Stuexen break; 1290237049Stuexen } 1291163953Srrs sp->pp_loopcnt = 0; 1292163953Srrs if (! (ifp->if_flags & IFF_UP) && 1293163953Srrs (ifp->if_flags & IFF_RUNNING)) { 1294163953Srrs if_up(ifp); 1295169420Srrs printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 1296169420Srrs } 1297169420Srrs break; 1298163953Srrs case CISCO_ADDR_REQ: 1299169420Srrs sppp_get_ip_addrs(sp, &me, 0, &mymask); 1300169420Srrs if (me != 0L) 1301163953Srrs sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask); 1302163953Srrs break; 1303163953Srrs } 1304163953Srrs} 1305163953Srrs 1306237715Stuexen/* 1307237715Stuexen * Send Cisco keepalive packet. 1308237049Stuexen */ 1309237049Stuexenstatic void 1310168299Srrssppp_cisco_send(struct sppp *sp, int type, long par1, long par2) 1311163953Srrs{ 1312163953Srrs STDDCL; 1313163953Srrs struct ppp_header *h; 1314163953Srrs struct cisco_packet *ch; 1315163953Srrs struct mbuf *m; 1316163953Srrs struct timeval tv; 1317163953Srrs 1318237715Stuexen getmicrouptime(&tv); 1319237715Stuexen 1320237049Stuexen MGETHDR (m, M_DONTWAIT, MT_DATA); 1321237049Stuexen if (! m) 1322168299Srrs return; 1323163953Srrs m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN; 1324163953Srrs m->m_pkthdr.rcvif = 0; 1325163953Srrs 1326163953Srrs h = mtod (m, struct ppp_header*); 1327163953Srrs h->address = CISCO_MULTICAST; 1328237715Stuexen h->control = 0; 1329237715Stuexen h->protocol = htons (CISCO_KEEPALIVE); 1330237049Stuexen 1331237049Stuexen ch = (struct cisco_packet*) (h + 1); 1332168299Srrs ch->type = htonl (type); 1333163953Srrs ch->par1 = htonl (par1); 1334163953Srrs ch->par2 = htonl (par2); 1335163953Srrs ch->rel = -1; 1336163953Srrs 1337163953Srrs ch->time0 = htons ((u_short) (tv.tv_sec >> 16)); 1338237715Stuexen ch->time1 = htons ((u_short) tv.tv_sec); 1339237715Stuexen 1340237049Stuexen if (debug) 1341237049Stuexen log(LOG_DEBUG, 1342168299Srrs SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n", 1343163953Srrs SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1, 1344163953Srrs (u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1); 1345163953Srrs 1346163953Srrs if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 1347163953Srrs ifp->if_oerrors++; 1348237715Stuexen} 1349237715Stuexen 1350237049Stuexen/* 1351237049Stuexen * PPP protocol implementation. 1352168299Srrs */ 1353163953Srrs 1354163953Srrs/* 1355163953Srrs * Send PPP control protocol packet. 1356171943Srrs */ 1357163953Srrsstatic void 1358163953Srrssppp_cp_send(struct sppp *sp, u_short proto, u_char type, 1359163953Srrs u_char ident, u_short len, void *data) 1360163953Srrs{ 1361163953Srrs STDDCL; 1362163953Srrs struct ppp_header *h; 1363163953Srrs struct lcp_header *lh; 1364163953Srrs struct mbuf *m; 1365163953Srrs 1366163953Srrs if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) 1367163953Srrs len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN; 1368163953Srrs MGETHDR (m, M_DONTWAIT, MT_DATA); 1369163953Srrs if (! m) 1370163953Srrs return; 1371172090Srrs m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 1372163953Srrs m->m_pkthdr.rcvif = 0; 1373237715Stuexen 1374237049Stuexen h = mtod (m, struct ppp_header*); 1375237049Stuexen h->address = PPP_ALLSTATIONS; /* broadcast address */ 1376237049Stuexen h->control = PPP_UI; /* Unnumbered Info */ 1377163953Srrs h->protocol = htons (proto); /* Link Control Protocol */ 1378163953Srrs 1379163953Srrs lh = (struct lcp_header*) (h + 1); 1380163953Srrs lh->type = type; 1381169420Srrs lh->ident = ident; 1382171943Srrs lh->len = htons (LCP_HEADER_LEN + len); 1383163953Srrs if (len) 1384163953Srrs bcopy (data, lh+1, len); 1385179783Srrs 1386171943Srrs if (debug) { 1387171943Srrs log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 1388171943Srrs SPP_ARGS(ifp), 1389171943Srrs sppp_proto_name(proto), 1390171943Srrs sppp_cp_type_name (lh->type), lh->ident, 1391171943Srrs ntohs (lh->len)); 1392163953Srrs sppp_print_bytes ((u_char*) (lh+1), len); 1393169378Srrs log(-1, ">\n"); 1394163953Srrs } 1395163953Srrs if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 1396165220Srrs ifp->if_oerrors++; 1397163953Srrs} 1398163953Srrs 1399163953Srrs/* 1400163953Srrs * Handle incoming PPP control protocol packets. 1401163953Srrs */ 1402163953Srrsstatic void 1403163953Srrssppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m) 1404163953Srrs{ 1405163953Srrs STDDCL; 1406163953Srrs struct lcp_header *h; 1407163953Srrs int len = m->m_pkthdr.len; 1408163953Srrs int rv; 1409163953Srrs u_char *p; 1410163953Srrs 1411163953Srrs if (len < 4) { 1412163953Srrs if (debug) 1413163953Srrs log(LOG_DEBUG, 1414163953Srrs SPP_FMT "%s invalid packet length: %d bytes\n", 1415163953Srrs SPP_ARGS(ifp), cp->name, len); 1416163953Srrs return; 1417163953Srrs } 1418163953Srrs h = mtod (m, struct lcp_header*); 1419163953Srrs if (debug) { 1420163953Srrs log(LOG_DEBUG, 1421169420Srrs SPP_FMT "%s input(%s): <%s id=0x%x len=%d", 1422163953Srrs SPP_ARGS(ifp), cp->name, 1423163953Srrs sppp_state_name(sp->state[cp->protoidx]), 1424163953Srrs sppp_cp_type_name (h->type), h->ident, ntohs (h->len)); 1425185694Srrs sppp_print_bytes ((u_char*) (h+1), len-4); 1426185694Srrs log(-1, ">\n"); 1427237715Stuexen } 1428185694Srrs if (len > ntohs (h->len)) 1429185694Srrs len = ntohs (h->len); 1430185694Srrs p = (u_char *)(h + 1); 1431185694Srrs switch (h->type) { 1432237049Stuexen case CONF_REQ: 1433185694Srrs if (len < 4) { 1434163953Srrs if (debug) 1435185694Srrs log(-1, SPP_FMT "%s invalid conf-req length %d\n", 1436163953Srrs SPP_ARGS(ifp), cp->name, 1437163953Srrs len); 1438163953Srrs ++ifp->if_ierrors; 1439163953Srrs break; 1440163953Srrs } 1441163953Srrs /* handle states where RCR doesn't get a SCA/SCN */ 1442163953Srrs switch (sp->state[cp->protoidx]) { 1443163953Srrs case STATE_CLOSING: 1444237715Stuexen case STATE_STOPPING: 1445163953Srrs return; 1446185694Srrs case STATE_CLOSED: 1447228653Stuexen sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 1448237049Stuexen 0, 0); 1449237049Stuexen return; 1450237049Stuexen } 1451163953Srrs rv = (cp->RCR)(sp, h, len); 1452163953Srrs switch (sp->state[cp->protoidx]) { 1453163953Srrs case STATE_OPENED: 1454163953Srrs (cp->tld)(sp); 1455185694Srrs (cp->scr)(sp); 1456185694Srrs /* FALLTHROUGH */ 1457185694Srrs case STATE_ACK_SENT: 1458165220Srrs case STATE_REQ_SENT: 1459163953Srrs /* 1460164205Srrs * sppp_cp_change_state() have the side effect of 1461170140Srrs * restarting the timeouts. We want to avoid that 1462163953Srrs * if the state don't change, otherwise we won't 1463185694Srrs * ever timeout and resend a configuration request 1464163953Srrs * that got lost. 1465163953Srrs */ 1466166675Srrs if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT: 1467166023Srrs STATE_REQ_SENT)) 1468166023Srrs break; 1469166023Srrs sppp_cp_change_state(cp, sp, rv? 1470166023Srrs STATE_ACK_SENT: STATE_REQ_SENT); 1471166023Srrs break; 1472166023Srrs case STATE_STOPPED: 1473163953Srrs sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1474163953Srrs (cp->scr)(sp); 1475163953Srrs sppp_cp_change_state(cp, sp, rv? 1476163953Srrs STATE_ACK_SENT: STATE_REQ_SENT); 1477165647Srrs break; 1478163953Srrs case STATE_ACK_RCVD: 1479163953Srrs if (rv) { 1480163953Srrs sppp_cp_change_state(cp, sp, STATE_OPENED); 1481163953Srrs if (debug) 1482163953Srrs log(LOG_DEBUG, SPP_FMT "%s tlu\n", 1483165647Srrs SPP_ARGS(ifp), 1484163953Srrs cp->name); 1485163953Srrs (cp->tlu)(sp); 1486163953Srrs } else 1487237715Stuexen sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 1488237049Stuexen break; 1489179157Srrs default: 1490166023Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1491166023Srrs SPP_ARGS(ifp), cp->name, 1492163953Srrs sppp_cp_type_name(h->type), 1493163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1494163953Srrs ++ifp->if_ierrors; 1495163953Srrs } 1496163953Srrs break; 1497163953Srrs case CONF_ACK: 1498163953Srrs if (h->ident != sp->confid[cp->protoidx]) { 1499163953Srrs if (debug) 1500163953Srrs log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 1501163953Srrs SPP_ARGS(ifp), cp->name, 1502163953Srrs h->ident, sp->confid[cp->protoidx]); 1503163953Srrs ++ifp->if_ierrors; 1504163953Srrs break; 1505163953Srrs } 1506163953Srrs switch (sp->state[cp->protoidx]) { 1507163953Srrs case STATE_CLOSED: 1508163953Srrs case STATE_STOPPED: 1509163953Srrs sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 1510163953Srrs break; 1511163953Srrs case STATE_CLOSING: 1512163953Srrs case STATE_STOPPING: 1513163953Srrs break; 1514163953Srrs case STATE_REQ_SENT: 1515228907Stuexen sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1516163953Srrs sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 1517163953Srrs break; 1518163953Srrs case STATE_OPENED: 1519163953Srrs (cp->tld)(sp); 1520163953Srrs /* FALLTHROUGH */ 1521163953Srrs case STATE_ACK_RCVD: 1522163953Srrs (cp->scr)(sp); 1523163953Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1524163953Srrs break; 1525163953Srrs case STATE_ACK_SENT: 1526163953Srrs sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1527163953Srrs sppp_cp_change_state(cp, sp, STATE_OPENED); 1528163953Srrs if (debug) 1529163953Srrs log(LOG_DEBUG, SPP_FMT "%s tlu\n", 1530163953Srrs SPP_ARGS(ifp), cp->name); 1531163953Srrs (cp->tlu)(sp); 1532166023Srrs break; 1533172091Srrs default: 1534172091Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1535172091Srrs SPP_ARGS(ifp), cp->name, 1536172091Srrs sppp_cp_type_name(h->type), 1537172091Srrs sppp_state_name(sp->state[cp->protoidx])); 1538172091Srrs ++ifp->if_ierrors; 1539172091Srrs } 1540172091Srrs break; 1541172091Srrs case CONF_NAK: 1542172091Srrs case CONF_REJ: 1543172091Srrs if (h->ident != sp->confid[cp->protoidx]) { 1544172091Srrs if (debug) 1545172091Srrs log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n", 1546172091Srrs SPP_ARGS(ifp), cp->name, 1547172091Srrs h->ident, sp->confid[cp->protoidx]); 1548172091Srrs ++ifp->if_ierrors; 1549172091Srrs break; 1550172091Srrs } 1551166023Srrs if (h->type == CONF_NAK) 1552163953Srrs (cp->RCN_nak)(sp, h, len); 1553163953Srrs else /* CONF_REJ */ 1554163953Srrs (cp->RCN_rej)(sp, h, len); 1555166023Srrs 1556163953Srrs switch (sp->state[cp->protoidx]) { 1557169352Srrs case STATE_CLOSED: 1558166023Srrs case STATE_STOPPED: 1559166023Srrs sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 1560166023Srrs break; 1561163953Srrs case STATE_REQ_SENT: 1562163953Srrs case STATE_ACK_SENT: 1563228653Stuexen sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1564163953Srrs /* 1565166023Srrs * Slow things down a bit if we think we might be 1566166023Srrs * in loopback. Depend on the timeout to send the 1567163953Srrs * next configuration request. 1568163953Srrs */ 1569163953Srrs if (sp->pp_loopcnt) 1570163953Srrs break; 1571171440Srrs (cp->scr)(sp); 1572171440Srrs break; 1573163953Srrs case STATE_OPENED: 1574166675Srrs (cp->tld)(sp); 1575166675Srrs /* FALLTHROUGH */ 1576166675Srrs case STATE_ACK_RCVD: 1577166675Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1578171943Srrs (cp->scr)(sp); 1579171943Srrs break; 1580163953Srrs case STATE_CLOSING: 1581163953Srrs case STATE_STOPPING: 1582163953Srrs break; 1583163953Srrs default: 1584166675Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1585165220Srrs SPP_ARGS(ifp), cp->name, 1586163953Srrs sppp_cp_type_name(h->type), 1587163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1588163953Srrs ++ifp->if_ierrors; 1589163953Srrs } 1590237565Stuexen break; 1591172090Srrs 1592172090Srrs case TERM_REQ: 1593172090Srrs switch (sp->state[cp->protoidx]) { 1594163953Srrs case STATE_ACK_RCVD: 1595163953Srrs case STATE_ACK_SENT: 1596163953Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1597163953Srrs /* FALLTHROUGH */ 1598163953Srrs case STATE_CLOSED: 1599163953Srrs case STATE_STOPPED: 1600163953Srrs case STATE_CLOSING: 1601163953Srrs case STATE_STOPPING: 1602237565Stuexen case STATE_REQ_SENT: 1603172090Srrs sta: 1604172090Srrs /* Send Terminate-Ack packet. */ 1605172090Srrs if (debug) 1606172090Srrs log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n", 1607172090Srrs SPP_ARGS(ifp), cp->name); 1608172090Srrs sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0); 1609172090Srrs break; 1610172090Srrs case STATE_OPENED: 1611172090Srrs (cp->tld)(sp); 1612172090Srrs sp->rst_counter[cp->protoidx] = 0; 1613172090Srrs sppp_cp_change_state(cp, sp, STATE_STOPPING); 1614172090Srrs goto sta; 1615237565Stuexen break; 1616172090Srrs default: 1617172090Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1618163953Srrs SPP_ARGS(ifp), cp->name, 1619163953Srrs sppp_cp_type_name(h->type), 1620163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1621163953Srrs ++ifp->if_ierrors; 1622163953Srrs } 1623163953Srrs break; 1624163953Srrs case TERM_ACK: 1625163953Srrs switch (sp->state[cp->protoidx]) { 1626170642Srrs case STATE_CLOSED: 1627218186Srrs case STATE_STOPPED: 1628218186Srrs case STATE_REQ_SENT: 1629219397Srrs case STATE_ACK_SENT: 1630163953Srrs break; 1631163953Srrs case STATE_CLOSING: 1632163953Srrs sppp_cp_change_state(cp, sp, STATE_CLOSED); 1633163953Srrs (cp->tlf)(sp); 1634163953Srrs break; 1635163953Srrs case STATE_STOPPING: 1636163953Srrs sppp_cp_change_state(cp, sp, STATE_STOPPED); 1637163953Srrs (cp->tlf)(sp); 1638163953Srrs break; 1639163953Srrs case STATE_ACK_RCVD: 1640163953Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1641163953Srrs break; 1642163953Srrs case STATE_OPENED: 1643163953Srrs (cp->tld)(sp); 1644165220Srrs (cp->scr)(sp); 1645163953Srrs sppp_cp_change_state(cp, sp, STATE_ACK_RCVD); 1646163953Srrs break; 1647163953Srrs default: 1648163953Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1649163953Srrs SPP_ARGS(ifp), cp->name, 1650228653Stuexen sppp_cp_type_name(h->type), 1651163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1652237715Stuexen ++ifp->if_ierrors; 1653166023Srrs } 1654166023Srrs break; 1655163953Srrs case CODE_REJ: 1656163953Srrs /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 1657163953Srrs log(LOG_INFO, 1658165220Srrs SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, " 1659163953Srrs "danger will robinson\n", 1660166023Srrs SPP_ARGS(ifp), cp->name, 1661166023Srrs sppp_cp_type_name(h->type), ntohs(*((u_short *)p))); 1662163953Srrs switch (sp->state[cp->protoidx]) { 1663169352Srrs case STATE_CLOSED: 1664163953Srrs case STATE_STOPPED: 1665163953Srrs case STATE_REQ_SENT: 1666163953Srrs case STATE_ACK_SENT: 1667163953Srrs case STATE_CLOSING: 1668163953Srrs case STATE_STOPPING: 1669163953Srrs case STATE_OPENED: 1670163953Srrs break; 1671166023Srrs case STATE_ACK_RCVD: 1672166023Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1673163953Srrs break; 1674163953Srrs default: 1675185694Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1676185694Srrs SPP_ARGS(ifp), cp->name, 1677185694Srrs sppp_cp_type_name(h->type), 1678185694Srrs sppp_state_name(sp->state[cp->protoidx])); 1679185694Srrs ++ifp->if_ierrors; 1680185694Srrs } 1681185694Srrs break; 1682185694Srrs case PROTO_REJ: 1683185694Srrs { 1684163953Srrs int catastrophic; 1685185694Srrs const struct cp *upper; 1686185694Srrs int i; 1687185694Srrs u_int16_t proto; 1688185694Srrs 1689185694Srrs catastrophic = 0; 1690185694Srrs upper = NULL; 1691185694Srrs proto = ntohs(*((u_int16_t *)p)); 1692185694Srrs for (i = 0; i < IDX_COUNT; i++) { 1693185694Srrs if (cps[i]->proto == proto) { 1694185694Srrs upper = cps[i]; 1695185694Srrs break; 1696185694Srrs } 1697185694Srrs } 1698185694Srrs if (upper == NULL) 1699185694Srrs catastrophic++; 1700185694Srrs 1701185694Srrs if (catastrophic || debug) 1702185694Srrs log(catastrophic? LOG_INFO: LOG_DEBUG, 1703185694Srrs SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n", 1704185694Srrs SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+', 1705185694Srrs sppp_cp_type_name(h->type), proto, 1706185694Srrs upper ? upper->name : "unknown", 1707185694Srrs upper ? sppp_state_name(sp->state[upper->protoidx]) : "?"); 1708185694Srrs 1709185694Srrs /* 1710185694Srrs * if we got RXJ+ against conf-req, the peer does not implement 1711185694Srrs * this particular protocol type. terminate the protocol. 1712185694Srrs */ 1713237715Stuexen if (upper && !catastrophic) { 1714237049Stuexen if (sp->state[upper->protoidx] == STATE_REQ_SENT) { 1715237049Stuexen upper->Close(sp); 1716185694Srrs break; 1717185694Srrs } 1718185694Srrs } 1719185694Srrs 1720185694Srrs /* XXX catastrophic rejects (RXJ-) aren't handled yet. */ 1721185694Srrs switch (sp->state[cp->protoidx]) { 1722163953Srrs case STATE_CLOSED: 1723163953Srrs case STATE_STOPPED: 1724163953Srrs case STATE_REQ_SENT: 1725166023Srrs case STATE_ACK_SENT: 1726166023Srrs case STATE_CLOSING: 1727166023Srrs case STATE_STOPPING: 1728166023Srrs case STATE_OPENED: 1729166023Srrs break; 1730166023Srrs case STATE_ACK_RCVD: 1731166023Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1732166023Srrs break; 1733166023Srrs default: 1734166023Srrs printf(SPP_FMT "%s illegal %s in state %s\n", 1735166023Srrs SPP_ARGS(ifp), cp->name, 1736166023Srrs sppp_cp_type_name(h->type), 1737166023Srrs sppp_state_name(sp->state[cp->protoidx])); 1738166023Srrs ++ifp->if_ierrors; 1739166023Srrs } 1740166023Srrs break; 1741166023Srrs } 1742166023Srrs case DISC_REQ: 1743166023Srrs if (cp->proto != PPP_LCP) 1744166023Srrs goto illegal; 1745166023Srrs /* Discard the packet. */ 1746166023Srrs break; 1747166023Srrs case ECHO_REQ: 1748166023Srrs if (cp->proto != PPP_LCP) 1749166023Srrs goto illegal; 1750171440Srrs if (sp->state[cp->protoidx] != STATE_OPENED) { 1751163953Srrs if (debug) 1752163953Srrs log(-1, SPP_FMT "lcp echo req but lcp closed\n", 1753163953Srrs SPP_ARGS(ifp)); 1754163953Srrs ++ifp->if_ierrors; 1755163953Srrs break; 1756163953Srrs } 1757163953Srrs if (len < 8) { 1758163953Srrs if (debug) 1759163953Srrs log(-1, SPP_FMT "invalid lcp echo request " 1760163953Srrs "packet length: %d bytes\n", 1761163953Srrs SPP_ARGS(ifp), len); 1762163953Srrs break; 1763164205Srrs } 1764164205Srrs if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 1765164205Srrs ntohl (*(long*)(h+1)) == sp->lcp.magic) { 1766164205Srrs /* Line loopback mode detected. */ 1767164205Srrs printf(SPP_FMT "loopback\n", SPP_ARGS(ifp)); 1768164205Srrs sp->pp_loopcnt = MAXALIVECNT * 5; 1769164205Srrs if_down (ifp); 1770164205Srrs sppp_qflush (&sp->pp_cpq); 1771164205Srrs 1772164205Srrs /* Shut down the PPP link. */ 1773164205Srrs /* XXX */ 1774164205Srrs lcp.Down(sp); 1775163953Srrs lcp.Up(sp); 1776164205Srrs break; 1777164205Srrs } 1778164205Srrs *(long*)(h+1) = htonl (sp->lcp.magic); 1779171440Srrs if (debug) 1780171440Srrs log(-1, SPP_FMT "got lcp echo req, sending echo rep\n", 1781168124Srrs SPP_ARGS(ifp)); 1782164205Srrs sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1); 1783164205Srrs break; 1784164205Srrs case ECHO_REPLY: 1785164205Srrs if (cp->proto != PPP_LCP) 1786164205Srrs goto illegal; 1787163953Srrs if (h->ident != sp->lcp.echoid) { 1788228653Stuexen ++ifp->if_ierrors; 1789163953Srrs break; 1790166023Srrs } 1791166023Srrs if (len < 8) { 1792163953Srrs if (debug) 1793163953Srrs log(-1, SPP_FMT "lcp invalid echo reply " 1794228653Stuexen "packet length: %d bytes\n", 1795163953Srrs SPP_ARGS(ifp), len); 1796237715Stuexen break; 1797166023Srrs } 1798166023Srrs if (debug) 1799163953Srrs log(-1, SPP_FMT "lcp got echo rep\n", 1800163953Srrs SPP_ARGS(ifp)); 1801163953Srrs if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) || 1802163953Srrs ntohl (*(long*)(h+1)) != sp->lcp.magic) 1803163953Srrs sp->pp_alivecnt = 0; 1804163953Srrs break; 1805163953Srrs default: 1806163953Srrs /* Unknown packet type -- send Code-Reject packet. */ 1807163953Srrs illegal: 1808237565Stuexen if (debug) 1809172090Srrs log(-1, SPP_FMT "%s send code-rej for 0x%x\n", 1810172090Srrs SPP_ARGS(ifp), cp->name, h->type); 1811172090Srrs sppp_cp_send(sp, cp->proto, CODE_REJ, 1812163953Srrs ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h); 1813163953Srrs ++ifp->if_ierrors; 1814237565Stuexen } 1815172090Srrs} 1816172090Srrs 1817172090Srrs 1818172090Srrs/* 1819172090Srrs * The generic part of all Up/Down/Open/Close/TO event handlers. 1820172090Srrs * Basically, the state transition handling in the automaton. 1821172090Srrs */ 1822172090Srrsstatic void 1823172090Srrssppp_up_event(const struct cp *cp, struct sppp *sp) 1824172090Srrs{ 1825172090Srrs STDDCL; 1826172090Srrs 1827237565Stuexen if (debug) 1828172090Srrs log(LOG_DEBUG, SPP_FMT "%s up(%s)\n", 1829172090Srrs SPP_ARGS(ifp), cp->name, 1830163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1831166675Srrs 1832166675Srrs switch (sp->state[cp->protoidx]) { 1833166675Srrs case STATE_INITIAL: 1834166675Srrs sppp_cp_change_state(cp, sp, STATE_CLOSED); 1835166675Srrs break; 1836166675Srrs case STATE_STARTING: 1837166675Srrs sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1838166675Srrs (cp->scr)(sp); 1839166675Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1840163953Srrs break; 1841171943Srrs default: 1842163953Srrs printf(SPP_FMT "%s illegal up in state %s\n", 1843163953Srrs SPP_ARGS(ifp), cp->name, 1844163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1845163953Srrs } 1846163953Srrs} 1847165220Srrs 1848163953Srrsstatic void 1849164205Srrssppp_down_event(const struct cp *cp, struct sppp *sp) 1850164205Srrs{ 1851164205Srrs STDDCL; 1852164205Srrs 1853164205Srrs if (debug) 1854164205Srrs log(LOG_DEBUG, SPP_FMT "%s down(%s)\n", 1855164205Srrs SPP_ARGS(ifp), cp->name, 1856164205Srrs sppp_state_name(sp->state[cp->protoidx])); 1857172090Srrs 1858164205Srrs switch (sp->state[cp->protoidx]) { 1859166023Srrs case STATE_CLOSED: 1860166023Srrs case STATE_CLOSING: 1861166023Srrs sppp_cp_change_state(cp, sp, STATE_INITIAL); 1862163953Srrs break; 1863163953Srrs case STATE_STOPPED: 1864163953Srrs sppp_cp_change_state(cp, sp, STATE_STARTING); 1865163953Srrs (cp->tls)(sp); 1866163953Srrs break; 1867163953Srrs case STATE_STOPPING: 1868163953Srrs case STATE_REQ_SENT: 1869163953Srrs case STATE_ACK_RCVD: 1870163953Srrs case STATE_ACK_SENT: 1871185694Srrs sppp_cp_change_state(cp, sp, STATE_STARTING); 1872185694Srrs break; 1873185694Srrs case STATE_OPENED: 1874185694Srrs (cp->tld)(sp); 1875185694Srrs sppp_cp_change_state(cp, sp, STATE_STARTING); 1876185694Srrs break; 1877237715Stuexen default: 1878237715Stuexen printf(SPP_FMT "%s illegal down in state %s\n", 1879185694Srrs SPP_ARGS(ifp), cp->name, 1880185694Srrs sppp_state_name(sp->state[cp->protoidx])); 1881237049Stuexen } 1882185694Srrs} 1883185694Srrs 1884163953Srrs 1885163953Srrsstatic void 1886163953Srrssppp_open_event(const struct cp *cp, struct sppp *sp) 1887165220Srrs{ 1888166023Srrs STDDCL; 1889166023Srrs 1890171440Srrs if (debug) 1891171440Srrs log(LOG_DEBUG, SPP_FMT "%s open(%s)\n", 1892165647Srrs SPP_ARGS(ifp), cp->name, 1893163953Srrs sppp_state_name(sp->state[cp->protoidx])); 1894163953Srrs 1895165220Srrs switch (sp->state[cp->protoidx]) { 1896166675Srrs case STATE_INITIAL: 1897166675Srrs sppp_cp_change_state(cp, sp, STATE_STARTING); 1898166675Srrs (cp->tls)(sp); 1899166675Srrs break; 1900166675Srrs case STATE_STARTING: 1901166675Srrs break; 1902166675Srrs case STATE_CLOSED: 1903166675Srrs sp->rst_counter[cp->protoidx] = sp->lcp.max_configure; 1904166675Srrs (cp->scr)(sp); 1905166675Srrs sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 1906165647Srrs break; 1907171943Srrs case STATE_STOPPED: 1908165647Srrs /* 1909165647Srrs * Try escaping stopped state. This seems to bite 1910165647Srrs * people occasionally, in particular for IPCP, 1911165647Srrs * presumably following previous IPCP negotiation 1912165647Srrs * aborts. Somehow, we must have missed a Down event 1913171943Srrs * which would have caused a transition into starting 1914165647Srrs * state, so as a bandaid we force the Down event now. 1915165647Srrs * This effectively implements (something like the) 1916165647Srrs * `restart' option mentioned in the state transition 1917165647Srrs * table of RFC 1661. 1918165647Srrs */ 1919179157Srrs sppp_cp_change_state(cp, sp, STATE_STARTING); 1920165647Srrs (cp->tls)(sp); 1921165647Srrs break; 1922165647Srrs case STATE_STOPPING: 1923165647Srrs case STATE_REQ_SENT: 1924165647Srrs case STATE_ACK_RCVD: 1925165647Srrs case STATE_ACK_SENT: 1926170138Srrs case STATE_OPENED: 1927165647Srrs break; 1928165647Srrs case STATE_CLOSING: 1929170138Srrs sppp_cp_change_state(cp, sp, STATE_STOPPING); 1930205627Srrs break; 1931185694Srrs } 1932206137Stuexen} 1933185694Srrs 1934165220Srrs 1935165220Srrsstatic void 1936165220Srrssppp_close_event(const struct cp *cp, struct sppp *sp) 1937165220Srrs{ 1938165220Srrs STDDCL; 1939163953Srrs 1940164205Srrs if (debug) 1941165220Srrs log(LOG_DEBUG, SPP_FMT "%s close(%s)\n", 1942235416Stuexen SPP_ARGS(ifp), cp->name, 1943165220Srrs sppp_state_name(sp->state[cp->protoidx])); 1944165220Srrs 1945165220Srrs switch (sp->state[cp->protoidx]) { 1946165220Srrs case STATE_INITIAL: 1947165220Srrs case STATE_CLOSED: 1948163953Srrs case STATE_CLOSING: 1949163953Srrs break; 1950163953Srrs case STATE_STARTING: 1951163953Srrs sppp_cp_change_state(cp, sp, STATE_INITIAL); 1952163953Srrs (cp->tlf)(sp); 1953163953Srrs break; 1954163953Srrs case STATE_STOPPED: 1955179783Srrs sppp_cp_change_state(cp, sp, STATE_CLOSED); 1956179783Srrs break; 1957163953Srrs case STATE_STOPPING: 1958163953Srrs sppp_cp_change_state(cp, sp, STATE_CLOSING); 1959163953Srrs break; 1960163953Srrs case STATE_OPENED: 1961163953Srrs (cp->tld)(sp); 1962163953Srrs /* FALLTHROUGH */ 1963163953Srrs case STATE_REQ_SENT: 1964164205Srrs case STATE_ACK_RCVD: 1965165220Srrs case STATE_ACK_SENT: 1966165220Srrs sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate; 1967165220Srrs sppp_cp_send(sp, cp->proto, TERM_REQ, 1968228653Stuexen ++sp->pp_seq[cp->protoidx], 0, 0); 1969163953Srrs sppp_cp_change_state(cp, sp, STATE_CLOSING); 1970166023Srrs break; 1971166023Srrs } 1972166023Srrs} 1973163953Srrs 1974163953Srrsstatic void 1975163953Srrssppp_to_event(const struct cp *cp, struct sppp *sp) 1976163953Srrs{ 1977163953Srrs STDDCL; 1978163953Srrs int s; 1979163953Srrs 1980163953Srrs s = splimp(); 1981228653Stuexen if (debug) 1982163953Srrs log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n", 1983237715Stuexen SPP_ARGS(ifp), cp->name, 1984166023Srrs sppp_state_name(sp->state[cp->protoidx]), 1985166023Srrs sp->rst_counter[cp->protoidx]); 1986166023Srrs 1987163953Srrs if (--sp->rst_counter[cp->protoidx] < 0) 1988163953Srrs /* TO- event */ 1989163953Srrs switch (sp->state[cp->protoidx]) { 1990163953Srrs case STATE_CLOSING: 1991165220Srrs sppp_cp_change_state(cp, sp, STATE_CLOSED); 1992163953Srrs (cp->tlf)(sp); 1993166023Srrs break; 1994166023Srrs case STATE_STOPPING: 1995163953Srrs sppp_cp_change_state(cp, sp, STATE_STOPPED); 1996163953Srrs (cp->tlf)(sp); 1997163953Srrs break; 1998166023Srrs case STATE_REQ_SENT: 1999166023Srrs case STATE_ACK_RCVD: 2000163953Srrs case STATE_ACK_SENT: 2001163953Srrs sppp_cp_change_state(cp, sp, STATE_STOPPED); 2002163953Srrs (cp->tlf)(sp); 2003163953Srrs break; 2004166086Srrs } 2005163953Srrs else 2006163953Srrs /* TO+ event */ 2007163953Srrs switch (sp->state[cp->protoidx]) { 2008163953Srrs case STATE_CLOSING: 2009163953Srrs case STATE_STOPPING: 2010163953Srrs sppp_cp_send(sp, cp->proto, TERM_REQ, 2011163953Srrs ++sp->pp_seq[cp->protoidx], 0, 0); 2012237049Stuexen TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 2013163953Srrs sp->ch[cp->protoidx]); 2014237715Stuexen break; 2015163953Srrs case STATE_REQ_SENT: 2016163953Srrs case STATE_ACK_RCVD: 2017163953Srrs (cp->scr)(sp); 2018169352Srrs /* sppp_cp_change_state() will restart the timer */ 2019237049Stuexen sppp_cp_change_state(cp, sp, STATE_REQ_SENT); 2020179157Srrs break; 2021163953Srrs case STATE_ACK_SENT: 2022163953Srrs (cp->scr)(sp); 2023163953Srrs TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 2024163953Srrs sp->ch[cp->protoidx]); 2025163953Srrs break; 2026163953Srrs } 2027163953Srrs 2028163953Srrs splx(s); 2029163953Srrs} 2030163953Srrs 2031166675Srrs/* 2032163953Srrs * Change the state of a control protocol in the state automaton. 2033221249Stuexen * Takes care of starting/stopping the restart timer. 2034221249Stuexen */ 2035221249Stuexenstatic void 2036221249Stuexensppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate) 2037221249Stuexen{ 2038221249Stuexen sp->state[cp->protoidx] = newstate; 2039221249Stuexen 2040221249Stuexen UNTIMEOUT(cp->TO, (void *)sp, sp->ch[cp->protoidx]); 2041237565Stuexen switch (newstate) { 2042172090Srrs case STATE_INITIAL: 2043172090Srrs case STATE_STARTING: 2044172090Srrs case STATE_CLOSED: 2045172090Srrs case STATE_STOPPED: 2046172090Srrs case STATE_OPENED: 2047163953Srrs break; 2048163953Srrs case STATE_CLOSING: 2049163953Srrs case STATE_STOPPING: 2050163953Srrs case STATE_REQ_SENT: 2051163953Srrs case STATE_ACK_RCVD: 2052163953Srrs case STATE_ACK_SENT: 2053163953Srrs TIMEOUT(cp->TO, (void *)sp, sp->lcp.timeout, 2054163953Srrs sp->ch[cp->protoidx]); 2055163953Srrs break; 2056163953Srrs } 2057163953Srrs} 2058169420Srrs 2059169420Srrs/* 2060163953Srrs *--------------------------------------------------------------------------* 2061163953Srrs * * 2062163953Srrs * The LCP implementation. * 2063169420Srrs * * 2064163953Srrs *--------------------------------------------------------------------------* 2065163953Srrs */ 2066228907Stuexenstatic void 2067163953Srrssppp_lcp_init(struct sppp *sp) 2068163953Srrs{ 2069163953Srrs sp->lcp.opts = (1 << LCP_OPT_MAGIC); 2070163953Srrs sp->lcp.magic = 0; 2071163953Srrs sp->state[IDX_LCP] = STATE_INITIAL; 2072163953Srrs sp->fail_counter[IDX_LCP] = 0; 2073163953Srrs sp->pp_seq[IDX_LCP] = 0; 2074163953Srrs sp->pp_rseq[IDX_LCP] = 0; 2075163953Srrs sp->lcp.protos = 0; 2076169420Srrs sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 2077163953Srrs 2078163953Srrs /* Note that these values are relevant for all control protocols */ 2079163953Srrs sp->lcp.timeout = 3 * hz; 2080163953Srrs sp->lcp.max_terminate = 2; 2081163953Srrs sp->lcp.max_configure = 10; 2082163953Srrs sp->lcp.max_failure = 10; 2083163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2084163953Srrs callout_handle_init(&sp->ch[IDX_LCP]); 2085163953Srrs#endif 2086163953Srrs} 2087163953Srrs 2088163953Srrsstatic void 2089163953Srrssppp_lcp_up(struct sppp *sp) 2090163953Srrs{ 2091163953Srrs STDDCL; 2092163953Srrs 2093163953Srrs sp->pp_alivecnt = 0; 2094171531Srrs sp->lcp.opts = (1 << LCP_OPT_MAGIC); 2095171531Srrs sp->lcp.magic = 0; 2096171531Srrs sp->lcp.protos = 0; 2097171531Srrs sp->lcp.mru = sp->lcp.their_mru = PP_MTU; 2098171531Srrs /* 2099171531Srrs * If we are authenticator, negotiate LCP_AUTH 2100171531Srrs */ 2101206137Stuexen if (sp->hisauth.proto != 0) 2102171531Srrs sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO); 2103171531Srrs else 2104171531Srrs sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 2105163953Srrs sp->pp_flags &= ~PP_NEEDAUTH; 2106163953Srrs /* 2107163953Srrs * If this interface is passive or dial-on-demand, and we are 2108163953Srrs * still in Initial state, it means we've got an incoming 2109169420Srrs * call. Activate the interface. 2110169420Srrs */ 2111163953Srrs if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) { 2112170140Srrs if (debug) 2113163953Srrs log(LOG_DEBUG, 2114237715Stuexen SPP_FMT "Up event", SPP_ARGS(ifp)); 2115237049Stuexen ifp->if_flags |= IFF_RUNNING; 2116237049Stuexen if (sp->state[IDX_LCP] == STATE_INITIAL) { 2117163953Srrs if (debug) 2118163953Srrs log(-1, "(incoming call)\n"); 2119163953Srrs sp->pp_flags |= PP_CALLIN; 2120169420Srrs lcp.Open(sp); 2121169420Srrs } else if (debug) 2122169420Srrs log(-1, "\n"); 2123163953Srrs } else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 && 2124163953Srrs (sp->state[IDX_LCP] == STATE_INITIAL)) { 2125163953Srrs ifp->if_flags |= IFF_RUNNING; 2126163953Srrs lcp.Open(sp); 2127163953Srrs } 2128163953Srrs 2129163953Srrs sppp_up_event(&lcp, sp); 2130163953Srrs} 2131163953Srrs 2132163953Srrsstatic void 2133163953Srrssppp_lcp_down(struct sppp *sp) 2134163953Srrs{ 2135163953Srrs STDDCL; 2136163953Srrs 2137163953Srrs sppp_down_event(&lcp, sp); 2138163953Srrs 2139170140Srrs /* 2140163953Srrs * If this is neither a dial-on-demand nor a passive 2141163953Srrs * interface, simulate an ``ifconfig down'' action, so the 2142237715Stuexen * administrator can force a redial by another ``ifconfig 2143237049Stuexen * up''. XXX For leased line operation, should we immediately 2144237049Stuexen * try to reopen the connection here? 2145237565Stuexen */ 2146172090Srrs if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) { 2147172090Srrs log(LOG_INFO, 2148172090Srrs SPP_FMT "Down event, taking interface down.\n", 2149172090Srrs SPP_ARGS(ifp)); 2150171943Srrs if_down(ifp); 2151171440Srrs } else { 2152237565Stuexen if (debug) 2153172090Srrs log(LOG_DEBUG, 2154172090Srrs SPP_FMT "Down event (carrier loss)\n", 2155172090Srrs SPP_ARGS(ifp)); 2156163953Srrs sp->pp_flags &= ~PP_CALLIN; 2157163953Srrs if (sp->state[IDX_LCP] != STATE_INITIAL) 2158163953Srrs lcp.Close(sp); 2159185694Srrs ifp->if_flags &= ~IFF_RUNNING; 2160163953Srrs } 2161163953Srrs} 2162163953Srrs 2163163953Srrsstatic void 2164179157Srrssppp_lcp_open(struct sppp *sp) 2165163953Srrs{ 2166163953Srrs sppp_open_event(&lcp, sp); 2167163953Srrs} 2168163953Srrs 2169163953Srrsstatic void 2170163953Srrssppp_lcp_close(struct sppp *sp) 2171169420Srrs{ 2172228653Stuexen sppp_close_event(&lcp, sp); 2173169420Srrs} 2174169420Srrs 2175163953Srrsstatic void 2176170140Srrssppp_lcp_TO(void *cookie) 2177237565Stuexen{ 2178172090Srrs sppp_to_event(&lcp, (struct sppp *)cookie); 2179172090Srrs} 2180172090Srrs 2181172090Srrs/* 2182171943Srrs * Analyze a configure request. Return true if it was agreeable, and 2183237565Stuexen * caused action sca, false if it has been rejected or nak'ed, and 2184172090Srrs * caused action scn. (The return value is used to make the state 2185172090Srrs * transition decision in the state automaton.) 2186172090Srrs */ 2187163953Srrsstatic int 2188163953Srrssppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 2189163953Srrs{ 2190228653Stuexen STDDCL; 2191237715Stuexen u_char *buf, *r, *p; 2192237715Stuexen int origlen, rlen; 2193170140Srrs u_long nmagic; 2194237565Stuexen u_short authproto; 2195172090Srrs 2196172090Srrs len -= 4; 2197172090Srrs origlen = len; 2198172090Srrs buf = r = malloc (len, M_TEMP, M_NOWAIT); 2199171943Srrs if (! buf) 2200237565Stuexen return (0); 2201172090Srrs 2202172090Srrs if (debug) 2203172090Srrs log(LOG_DEBUG, SPP_FMT "lcp parse opts: ", 2204163953Srrs SPP_ARGS(ifp)); 2205163953Srrs 2206163953Srrs /* pass 1: check for things that need to be rejected */ 2207163953Srrs p = (void*) (h+1); 2208163953Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 2209163953Srrs if (debug) 2210163953Srrs log(-1, " %s ", sppp_lcp_opt_name(*p)); 2211163953Srrs switch (*p) { 2212163953Srrs case LCP_OPT_MAGIC: 2213163953Srrs /* Magic number. */ 2214163953Srrs if (len >= 6 && p[1] == 6) 2215163953Srrs continue; 2216163953Srrs if (debug) 2217166675Srrs log(-1, "[invalid] "); 2218169420Srrs break; 2219163953Srrs case LCP_OPT_ASYNC_MAP: 2220169420Srrs /* Async control character map. */ 2221169420Srrs if (len >= 6 && p[1] == 6) 2222171440Srrs continue; 2223237565Stuexen if (debug) 2224172090Srrs log(-1, "[invalid] "); 2225172090Srrs break; 2226172090Srrs case LCP_OPT_MRU: 2227172090Srrs /* Maximum receive unit. */ 2228171943Srrs if (len >= 4 && p[1] == 4) 2229237565Stuexen continue; 2230172090Srrs if (debug) 2231172090Srrs log(-1, "[invalid] "); 2232172090Srrs break; 2233163953Srrs case LCP_OPT_AUTH_PROTO: 2234163953Srrs if (len < 4) { 2235163953Srrs if (debug) 2236163953Srrs log(-1, "[invalid] "); 2237163953Srrs break; 2238163953Srrs } 2239163953Srrs authproto = (p[2] << 8) + p[3]; 2240169420Srrs if (authproto == PPP_CHAP && p[1] != 5) { 2241171943Srrs if (debug) 2242163953Srrs log(-1, "[invalid chap len] "); 2243163953Srrs break; 2244163953Srrs } 2245163953Srrs if (sp->myauth.proto == 0) { 2246165220Srrs /* we are not configured to do auth */ 2247163953Srrs if (debug) 2248163953Srrs log(-1, "[not configured] "); 2249163953Srrs break; 2250163953Srrs } 2251163953Srrs /* 2252163953Srrs * Remote want us to authenticate, remember this, 2253163953Srrs * so we stay in PHASE_AUTHENTICATE after LCP got 2254163953Srrs * up. 2255163953Srrs */ 2256163953Srrs sp->pp_flags |= PP_NEEDAUTH; 2257163953Srrs continue; 2258163953Srrs default: 2259163953Srrs /* Others not supported. */ 2260163953Srrs if (debug) 2261221249Stuexen log(-1, "[rej] "); 2262221249Stuexen break; 2263221249Stuexen } 2264163953Srrs /* Add the option to rejected list. */ 2265163953Srrs bcopy (p, r, p[1]); 2266163953Srrs r += p[1]; 2267163953Srrs rlen += p[1]; 2268163953Srrs } 2269163953Srrs if (rlen) { 2270221249Stuexen if (debug) 2271221249Stuexen log(-1, " send conf-rej\n"); 2272221249Stuexen sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 2273221249Stuexen return 0; 2274163953Srrs } else if (debug) 2275163953Srrs log(-1, "\n"); 2276163953Srrs 2277163953Srrs /* 2278163953Srrs * pass 2: check for option values that are unacceptable and 2279163953Srrs * thus require to be nak'ed. 2280163953Srrs */ 2281163953Srrs if (debug) 2282221249Stuexen log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ", 2283221249Stuexen SPP_ARGS(ifp)); 2284221249Stuexen 2285170140Srrs p = (void*) (h+1); 2286237565Stuexen len = origlen; 2287172090Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 2288172090Srrs if (debug) 2289172090Srrs log(-1, " %s ", sppp_lcp_opt_name(*p)); 2290172090Srrs switch (*p) { 2291171943Srrs case LCP_OPT_MAGIC: 2292237565Stuexen /* Magic number -- extract. */ 2293172090Srrs nmagic = (u_long)p[2] << 24 | 2294172090Srrs (u_long)p[3] << 16 | p[4] << 8 | p[5]; 2295172090Srrs if (nmagic != sp->lcp.magic) { 2296163953Srrs sp->pp_loopcnt = 0; 2297163953Srrs if (debug) 2298163953Srrs log(-1, "0x%lx ", nmagic); 2299163953Srrs continue; 2300163953Srrs } 2301163953Srrs if (debug && sp->pp_loopcnt < MAXALIVECNT*5) 2302163953Srrs log(-1, "[glitch] "); 2303163953Srrs ++sp->pp_loopcnt; 2304163953Srrs /* 2305163953Srrs * We negate our magic here, and NAK it. If 2306163953Srrs * we see it later in an NAK packet, we 2307163953Srrs * suggest a new one. 2308163953Srrs */ 2309163953Srrs nmagic = ~sp->lcp.magic; 2310163953Srrs /* Gonna NAK it. */ 2311163953Srrs p[2] = nmagic >> 24; 2312163953Srrs p[3] = nmagic >> 16; 2313237565Stuexen p[4] = nmagic >> 8; 2314172090Srrs p[5] = nmagic; 2315172090Srrs break; 2316172090Srrs 2317172090Srrs case LCP_OPT_ASYNC_MAP: 2318172090Srrs /* 2319172090Srrs * Async control character map -- just ignore it. 2320172090Srrs * 2321172090Srrs * Quote from RFC 1662, chapter 6: 2322172090Srrs * To enable this functionality, synchronous PPP 2323172090Srrs * implementations MUST always respond to the 2324172090Srrs * Async-Control-Character-Map Configuration 2325237565Stuexen * Option with the LCP Configure-Ack. However, 2326172090Srrs * acceptance of the Configuration Option does 2327172090Srrs * not imply that the synchronous implementation 2328163953Srrs * will do any ACCM mapping. Instead, all such 2329163953Srrs * octet mapping will be performed by the 2330163953Srrs * asynchronous-to-synchronous converter. 2331163953Srrs */ 2332163953Srrs continue; 2333163953Srrs 2334163953Srrs case LCP_OPT_MRU: 2335163953Srrs /* 2336163953Srrs * Maximum receive unit. Always agreeable, 2337163953Srrs * but ignored by now. 2338169420Srrs */ 2339169420Srrs sp->lcp.their_mru = p[2] * 256 + p[3]; 2340163953Srrs if (debug) 2341163953Srrs log(-1, "%lu ", sp->lcp.their_mru); 2342163953Srrs continue; 2343163953Srrs 2344163953Srrs case LCP_OPT_AUTH_PROTO: 2345165220Srrs authproto = (p[2] << 8) + p[3]; 2346171440Srrs if (sp->myauth.proto != authproto) { 2347170642Srrs /* not agreed, nak */ 2348169420Srrs if (debug) 2349218186Srrs log(-1, "[mine %s != his %s] ", 2350219397Srrs sppp_proto_name(sp->hisauth.proto), 2351170642Srrs sppp_proto_name(authproto)); 2352172190Srrs p[2] = sp->myauth.proto >> 8; 2353163953Srrs p[3] = sp->myauth.proto; 2354172190Srrs break; 2355172190Srrs } 2356172190Srrs if (authproto == PPP_CHAP && p[4] != CHAP_MD5) { 2357172190Srrs if (debug) 2358172190Srrs log(-1, "[chap not MD5] "); 2359172190Srrs p[4] = CHAP_MD5; 2360172190Srrs break; 2361172190Srrs } 2362172190Srrs continue; 2363172190Srrs } 2364172190Srrs /* Add the option to nak'ed list. */ 2365172190Srrs bcopy (p, r, p[1]); 2366163953Srrs r += p[1]; 2367163953Srrs rlen += p[1]; 2368163953Srrs } 2369185694Srrs if (rlen) { 2370185694Srrs /* 2371185694Srrs * Local and remote magics equal -- loopback? 2372185694Srrs */ 2373185694Srrs if (sp->pp_loopcnt >= MAXALIVECNT*5) { 2374185694Srrs if (sp->pp_loopcnt == MAXALIVECNT*5) 2375185694Srrs printf (SPP_FMT "loopback\n", 2376185694Srrs SPP_ARGS(ifp)); 2377185694Srrs if (ifp->if_flags & IFF_UP) { 2378185694Srrs if_down(ifp); 2379185694Srrs sppp_qflush(&sp->pp_cpq); 2380185694Srrs /* XXX ? */ 2381163953Srrs lcp.Down(sp); 2382163953Srrs lcp.Up(sp); 2383163953Srrs } 2384163953Srrs } else if (!sp->pp_loopcnt && 2385163953Srrs ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) { 2386163953Srrs if (debug) 2387163953Srrs log(-1, " max_failure (%d) exceeded, " 2388237715Stuexen "send conf-rej\n", 2389163953Srrs sp->lcp.max_failure); 2390163953Srrs sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf); 2391169352Srrs } else { 2392237049Stuexen if (debug) 2393237049Stuexen log(-1, " send conf-nak\n"); 2394237049Stuexen sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf); 2395163953Srrs } 2396163953Srrs } else { 2397163953Srrs if (debug) 2398163953Srrs log(-1, " send conf-ack\n"); 2399163953Srrs sp->fail_counter[IDX_LCP] = 0; 2400163953Srrs sp->pp_loopcnt = 0; 2401163953Srrs sppp_cp_send (sp, PPP_LCP, CONF_ACK, 2402163953Srrs h->ident, origlen, h+1); 2403163953Srrs } 2404163953Srrs 2405237541Stuexen free (buf, M_TEMP); 2406163953Srrs return (rlen == 0); 2407163953Srrs} 2408163953Srrs 2409163953Srrs/* 2410163953Srrs * Analyze the LCP Configure-Reject option list, and adjust our 2411163953Srrs * negotiation. 2412216887Stuexen */ 2413163953Srrsstatic void 2414221249Stuexensppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 2415221249Stuexen{ 2416221249Stuexen STDDCL; 2417221249Stuexen u_char *buf, *p; 2418221249Stuexen 2419221249Stuexen len -= 4; 2420221249Stuexen buf = malloc (len, M_TEMP, M_NOWAIT); 2421221249Stuexen if (!buf) 2422221249Stuexen return; 2423169420Srrs 2424169420Srrs if (debug) 2425163953Srrs log(LOG_DEBUG, SPP_FMT "lcp rej opts: ", 2426163953Srrs SPP_ARGS(ifp)); 2427163953Srrs 2428163953Srrs p = (void*) (h+1); 2429163953Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 2430163953Srrs if (debug) 2431163953Srrs log(-1, " %s ", sppp_lcp_opt_name(*p)); 2432163953Srrs switch (*p) { 2433163953Srrs case LCP_OPT_MAGIC: 2434163953Srrs /* Magic number -- can't use it, use 0 */ 2435163953Srrs sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC); 2436163953Srrs sp->lcp.magic = 0; 2437163953Srrs break; 2438163953Srrs case LCP_OPT_MRU: 2439163953Srrs /* 2440169352Srrs * Should not be rejected anyway, since we only 2441163953Srrs * negotiate a MRU if explicitly requested by 2442163953Srrs * peer. 2443163953Srrs */ 2444163953Srrs sp->lcp.opts &= ~(1 << LCP_OPT_MRU); 2445237541Stuexen break; 2446163953Srrs case LCP_OPT_AUTH_PROTO: 2447163953Srrs /* 2448237541Stuexen * Peer doesn't want to authenticate himself, 2449163953Srrs * deny unless this is a dialout call, and 2450163953Srrs * AUTHFLAG_NOCALLOUT is set. 2451163953Srrs */ 2452163953Srrs if ((sp->pp_flags & PP_CALLIN) == 0 && 2453163953Srrs (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) { 2454163953Srrs if (debug) 2455163953Srrs log(-1, "[don't insist on auth " 2456163953Srrs "for callout]"); 2457163953Srrs sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO); 2458163953Srrs break; 2459163953Srrs } 2460163953Srrs if (debug) 2461178202Srrs log(-1, "[access denied]\n"); 2462179783Srrs lcp.Close(sp); 2463178202Srrs break; 2464178202Srrs } 2465234461Stuexen } 2466178202Srrs if (debug) 2467178202Srrs log(-1, "\n"); 2468178202Srrs free (buf, M_TEMP); 2469178202Srrs return; 2470178202Srrs} 2471178202Srrs 2472178202Srrs/* 2473163953Srrs * Analyze the LCP Configure-NAK option list, and adjust our 2474163953Srrs * negotiation. 2475163953Srrs */ 2476163953Srrsstatic void 2477163953Srrssppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 2478163953Srrs{ 2479163953Srrs STDDCL; 2480163953Srrs u_char *buf, *p; 2481163953Srrs u_long magic; 2482163953Srrs 2483163953Srrs len -= 4; 2484163953Srrs buf = malloc (len, M_TEMP, M_NOWAIT); 2485163953Srrs if (!buf) 2486163953Srrs return; 2487163953Srrs 2488163953Srrs if (debug) 2489169378Srrs log(LOG_DEBUG, SPP_FMT "lcp nak opts: ", 2490163953Srrs SPP_ARGS(ifp)); 2491170462Srrs 2492163953Srrs p = (void*) (h+1); 2493163953Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 2494169378Srrs if (debug) 2495163953Srrs log(-1, " %s ", sppp_lcp_opt_name(*p)); 2496170462Srrs switch (*p) { 2497163953Srrs case LCP_OPT_MAGIC: 2498163953Srrs /* Magic number -- renegotiate */ 2499163953Srrs if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) && 2500163953Srrs len >= 6 && p[1] == 6) { 2501163953Srrs magic = (u_long)p[2] << 24 | 2502163953Srrs (u_long)p[3] << 16 | p[4] << 8 | p[5]; 2503164085Srrs /* 2504163953Srrs * If the remote magic is our negated one, 2505163953Srrs * this looks like a loopback problem. 2506163953Srrs * Suggest a new magic to make sure. 2507163953Srrs */ 2508163953Srrs if (magic == ~sp->lcp.magic) { 2509163953Srrs if (debug) 2510163953Srrs log(-1, "magic glitch "); 2511163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2512169378Srrs sp->lcp.magic = random(); 2513163953Srrs#else 2514170462Srrs sp->lcp.magic = time.tv_sec + time.tv_usec; 2515163953Srrs#endif 2516163953Srrs } else { 2517163953Srrs sp->lcp.magic = magic; 2518163953Srrs if (debug) 2519163953Srrs log(-1, "%lu ", magic); 2520163953Srrs } 2521163953Srrs } 2522163953Srrs break; 2523163953Srrs case LCP_OPT_MRU: 2524163953Srrs /* 2525163953Srrs * Peer wants to advise us to negotiate an MRU. 2526163953Srrs * Agree on it if it's reasonable, or use 2527163953Srrs * default otherwise. 2528163953Srrs */ 2529163953Srrs if (len >= 4 && p[1] == 4) { 2530163953Srrs u_int mru = p[2] * 256 + p[3]; 2531165647Srrs if (debug) 2532165647Srrs log(-1, "%d ", mru); 2533163953Srrs if (mru < PP_MTU || mru > PP_MAX_MRU) 2534165647Srrs mru = PP_MTU; 2535163953Srrs sp->lcp.mru = mru; 2536163953Srrs sp->lcp.opts |= (1 << LCP_OPT_MRU); 2537163953Srrs } 2538169420Srrs break; 2539169420Srrs case LCP_OPT_AUTH_PROTO: 2540169420Srrs /* 2541169420Srrs * Peer doesn't like our authentication method, 2542163953Srrs * deny. 2543163953Srrs */ 2544163953Srrs if (debug) 2545163953Srrs log(-1, "[access denied]\n"); 2546163953Srrs lcp.Close(sp); 2547169378Srrs break; 2548163953Srrs } 2549169655Srrs } 2550163953Srrs if (debug) 2551180387Srrs log(-1, "\n"); 2552180387Srrs free (buf, M_TEMP); 2553180387Srrs return; 2554180387Srrs} 2555163953Srrs 2556163953Srrsstatic void 2557163953Srrssppp_lcp_tlu(struct sppp *sp) 2558163953Srrs{ 2559163953Srrs STDDCL; 2560163953Srrs int i; 2561163953Srrs u_long mask; 2562165647Srrs 2563163953Srrs /* XXX ? */ 2564163953Srrs if (! (ifp->if_flags & IFF_UP) && 2565163953Srrs (ifp->if_flags & IFF_RUNNING)) { 2566163953Srrs /* Coming out of loopback mode. */ 2567163953Srrs if_up(ifp); 2568165647Srrs printf (SPP_FMT "up\n", SPP_ARGS(ifp)); 2569163953Srrs } 2570163953Srrs 2571163953Srrs for (i = 0; i < IDX_COUNT; i++) 2572163953Srrs if ((cps[i])->flags & CP_QUAL) 2573163953Srrs (cps[i])->Open(sp); 2574163953Srrs 2575163953Srrs if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 || 2576163953Srrs (sp->pp_flags & PP_NEEDAUTH) != 0) 2577163953Srrs sp->pp_phase = PHASE_AUTHENTICATE; 2578163953Srrs else 2579237715Stuexen sp->pp_phase = PHASE_NETWORK; 2580237049Stuexen 2581179157Srrs if (debug) 2582163953Srrs log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 2583163953Srrs sppp_phase_name(sp->pp_phase)); 2584163953Srrs 2585163953Srrs /* 2586163953Srrs * Open all authentication protocols. This is even required 2587163953Srrs * if we already proceeded to network phase, since it might be 2588163953Srrs * that remote wants us to authenticate, so we might have to 2589163953Srrs * send a PAP request. Undesired authentication protocols 2590163953Srrs * don't do anything when they get an Open event. 2591163953Srrs */ 2592163953Srrs for (i = 0; i < IDX_COUNT; i++) 2593163953Srrs if ((cps[i])->flags & CP_AUTH) 2594221249Stuexen (cps[i])->Open(sp); 2595221249Stuexen 2596221249Stuexen if (sp->pp_phase == PHASE_NETWORK) { 2597163953Srrs /* Notify all NCPs. */ 2598163953Srrs for (i = 0; i < IDX_COUNT; i++) 2599163953Srrs if (((cps[i])->flags & CP_NCP) && 2600163953Srrs /* 2601163953Srrs * XXX 2602163953Srrs * Hack to administratively disable IPv6 if 2603163953Srrs * not desired. Perhaps we should have another 2604163953Srrs * flag for this, but right now, we can make 2605221249Stuexen * all struct cp's read/only. 2606221249Stuexen */ 2607221249Stuexen (cps[i] != &ipv6cp || 2608221249Stuexen (sp->confflags & CONF_ENABLE_IPV6))) 2609163953Srrs (cps[i])->Open(sp); 2610163953Srrs } 2611163953Srrs 2612163953Srrs /* Send Up events to all started protos. */ 2613163953Srrs for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 2614163953Srrs if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) 2615221249Stuexen (cps[i])->Up(sp); 2616221249Stuexen 2617221249Stuexen /* notify low-level driver of state change */ 2618169420Srrs if (sp->pp_chg) 2619169420Srrs sp->pp_chg(sp, (int)sp->pp_phase); 2620163953Srrs 2621163953Srrs if (sp->pp_phase == PHASE_NETWORK) 2622163953Srrs /* if no NCP is starting, close down */ 2623237715Stuexen sppp_lcp_check_and_close(sp); 2624163953Srrs} 2625163953Srrs 2626163953Srrsstatic void 2627163953Srrssppp_lcp_tld(struct sppp *sp) 2628163953Srrs{ 2629163953Srrs STDDCL; 2630163953Srrs int i; 2631169420Srrs u_long mask; 2632163953Srrs 2633165220Srrs sp->pp_phase = PHASE_TERMINATE; 2634165220Srrs 2635165220Srrs if (debug) 2636165220Srrs log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 2637165220Srrs sppp_phase_name(sp->pp_phase)); 2638165220Srrs 2639165220Srrs /* 2640165220Srrs * Take upper layers down. We send the Down event first and 2641165220Srrs * the Close second to prevent the upper layers from sending 2642165220Srrs * ``a flurry of terminate-request packets'', as the RFC 2643165220Srrs * describes it. 2644165220Srrs */ 2645165220Srrs for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 2646165220Srrs if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) { 2647165220Srrs (cps[i])->Down(sp); 2648165220Srrs (cps[i])->Close(sp); 2649165220Srrs } 2650165220Srrs} 2651165220Srrs 2652165220Srrsstatic void 2653165220Srrssppp_lcp_tls(struct sppp *sp) 2654169420Srrs{ 2655165220Srrs STDDCL; 2656165220Srrs 2657165220Srrs sp->pp_phase = PHASE_ESTABLISH; 2658163953Srrs 2659163953Srrs if (debug) 2660188067Srrs log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 2661169420Srrs sppp_phase_name(sp->pp_phase)); 2662188067Srrs 2663163953Srrs /* Notify lower layer if desired. */ 2664163953Srrs if (sp->pp_tls) 2665163953Srrs (sp->pp_tls)(sp); 2666237715Stuexen else 2667237715Stuexen (sp->pp_up)(sp); 2668237715Stuexen} 2669237049Stuexen 2670237049Stuexenstatic void 2671237049Stuexensppp_lcp_tlf(struct sppp *sp) 2672163953Srrs{ 2673163953Srrs STDDCL; 2674163953Srrs 2675237715Stuexen sp->pp_phase = PHASE_DEAD; 2676237715Stuexen if (debug) 2677185694Srrs log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 2678237049Stuexen sppp_phase_name(sp->pp_phase)); 2679237049Stuexen 2680237049Stuexen /* Notify lower layer if desired. */ 2681163953Srrs if (sp->pp_tlf) 2682163953Srrs (sp->pp_tlf)(sp); 2683163953Srrs else 2684163953Srrs (sp->pp_down)(sp); 2685163953Srrs} 2686163953Srrs 2687237049Stuexenstatic void 2688237049Stuexensppp_lcp_scr(struct sppp *sp) 2689218400Stuexen{ 2690218392Srrs char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */]; 2691218400Stuexen int i = 0; 2692218335Stuexen u_short authproto; 2693163953Srrs 2694163953Srrs if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) { 2695163953Srrs if (! sp->lcp.magic) 2696163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2697163953Srrs sp->lcp.magic = random(); 2698163953Srrs#else 2699163953Srrs sp->lcp.magic = time.tv_sec + time.tv_usec; 2700163953Srrs#endif 2701163953Srrs opt[i++] = LCP_OPT_MAGIC; 2702163953Srrs opt[i++] = 6; 2703228907Stuexen opt[i++] = sp->lcp.magic >> 24; 2704228907Stuexen opt[i++] = sp->lcp.magic >> 16; 2705228907Stuexen opt[i++] = sp->lcp.magic >> 8; 2706163953Srrs opt[i++] = sp->lcp.magic; 2707163953Srrs } 2708163953Srrs 2709163953Srrs if (sp->lcp.opts & (1 << LCP_OPT_MRU)) { 2710163953Srrs opt[i++] = LCP_OPT_MRU; 2711169420Srrs opt[i++] = 4; 2712163953Srrs opt[i++] = sp->lcp.mru >> 8; 2713216887Stuexen opt[i++] = sp->lcp.mru; 2714163953Srrs } 2715163953Srrs 2716224641Stuexen if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) { 2717163953Srrs authproto = sp->hisauth.proto; 2718163953Srrs opt[i++] = LCP_OPT_AUTH_PROTO; 2719163953Srrs opt[i++] = authproto == PPP_CHAP? 5: 4; 2720163953Srrs opt[i++] = authproto >> 8; 2721163953Srrs opt[i++] = authproto; 2722163953Srrs if (authproto == PPP_CHAP) 2723163953Srrs opt[i++] = CHAP_MD5; 2724163953Srrs } 2725163953Srrs 2726163953Srrs sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP]; 2727163953Srrs sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt); 2728163953Srrs} 2729163953Srrs 2730163953Srrs/* 2731163953Srrs * Check the open NCPs, return true if at least one NCP is open. 2732163953Srrs */ 2733228653Stuexenstatic int 2734216887Stuexensppp_ncp_check(struct sppp *sp) 2735216887Stuexen{ 2736216887Stuexen int i, mask; 2737216887Stuexen 2738163953Srrs for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 2739163953Srrs if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP) 2740163953Srrs return 1; 2741171858Srrs return 0; 2742163953Srrs} 2743218757Sbz 2744166086Srrs/* 2745163953Srrs * Re-check the open NCPs and see if we should terminate the link. 2746218757Sbz * Called by the NCPs during their tlf action handling. 2747163953Srrs */ 2748171858Srrsstatic void 2749171858Srrssppp_lcp_check_and_close(struct sppp *sp) 2750163953Srrs{ 2751163953Srrs 2752163953Srrs if (sp->pp_phase < PHASE_NETWORK) 2753237565Stuexen /* don't bother, we are already going down */ 2754172090Srrs return; 2755172090Srrs 2756172090Srrs if (sppp_ncp_check(sp)) 2757163953Srrs return; 2758169420Srrs 2759163953Srrs lcp.Close(sp); 2760163953Srrs} 2761237715Stuexen 2762237049Stuexen/* 2763237049Stuexen *--------------------------------------------------------------------------* 2764237565Stuexen * * 2765172090Srrs * The IPCP implementation. * 2766172090Srrs * * 2767172090Srrs *--------------------------------------------------------------------------* 2768172090Srrs */ 2769172090Srrs 2770172090Srrsstatic void 2771172090Srrssppp_ipcp_init(struct sppp *sp) 2772171943Srrs{ 2773237565Stuexen sp->ipcp.opts = 0; 2774172090Srrs sp->ipcp.flags = 0; 2775172090Srrs sp->state[IDX_IPCP] = STATE_INITIAL; 2776163953Srrs sp->fail_counter[IDX_IPCP] = 0; 2777163953Srrs sp->pp_seq[IDX_IPCP] = 0; 2778163953Srrs sp->pp_rseq[IDX_IPCP] = 0; 2779166086Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 2780166086Srrs callout_handle_init(&sp->ch[IDX_IPCP]); 2781166086Srrs#endif 2782166086Srrs} 2783166086Srrs 2784166086Srrsstatic void 2785163953Srrssppp_ipcp_up(struct sppp *sp) 2786163953Srrs{ 2787163953Srrs sppp_up_event(&ipcp, sp); 2788166086Srrs} 2789163953Srrs 2790163953Srrsstatic void 2791163953Srrssppp_ipcp_down(struct sppp *sp) 2792172091Srrs{ 2793163953Srrs sppp_down_event(&ipcp, sp); 2794163953Srrs} 2795211944Stuexen 2796218235Stuexenstatic void 2797163953Srrssppp_ipcp_open(struct sppp *sp) 2798163953Srrs{ 2799233660Srrs STDDCL; 2800163953Srrs u_long myaddr, hisaddr; 2801163953Srrs 2802163953Srrs sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN | 2803163953Srrs IPCP_MYADDR_DYN | IPCP_VJ); 2804163953Srrs sp->ipcp.opts = 0; 2805163953Srrs 2806163953Srrs sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); 2807163953Srrs /* 2808163953Srrs * If we don't have his address, this probably means our 2809163953Srrs * interface doesn't want to talk IP at all. (This could 2810163953Srrs * be the case if somebody wants to speak only IPX, for 2811163953Srrs * example.) Don't open IPCP in this case. 2812163953Srrs */ 2813163953Srrs if (hisaddr == 0L) { 2814163953Srrs /* XXX this message should go away */ 2815163953Srrs if (debug) 2816163953Srrs log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n", 2817163953Srrs SPP_ARGS(ifp)); 2818207924Srrs return; 2819207924Srrs } 2820207924Srrs if (myaddr == 0L) { 2821207924Srrs /* 2822207924Srrs * I don't have an assigned address, so i need to 2823207924Srrs * negotiate my address. 2824207924Srrs */ 2825207924Srrs sp->ipcp.flags |= IPCP_MYADDR_DYN; 2826163953Srrs sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 2827170056Srrs } else 2828170056Srrs sp->ipcp.flags |= IPCP_MYADDR_SEEN; 2829170056Srrs if (sp->confflags & CONF_ENABLE_VJ) { 2830170056Srrs sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION); 2831175845Srwatson sp->ipcp.max_state = MAX_STATES - 1; 2832175845Srwatson sp->ipcp.compress_cid = 1; 2833170056Srrs } 2834170056Srrs sppp_open_event(&ipcp, sp); 2835163953Srrs} 2836170056Srrs 2837166086Srrsstatic void 2838166086Srrssppp_ipcp_close(struct sppp *sp) 2839166086Srrs{ 2840166086Srrs sppp_close_event(&ipcp, sp); 2841166086Srrs if (sp->ipcp.flags & IPCP_MYADDR_DYN) 2842166086Srrs /* 2843166086Srrs * My address was dynamic, clear it again. 2844166086Srrs */ 2845166086Srrs sppp_set_ip_addr(sp, 0L); 2846166086Srrs} 2847166086Srrs 2848166086Srrsstatic void 2849166086Srrssppp_ipcp_TO(void *cookie) 2850166086Srrs{ 2851166086Srrs sppp_to_event(&ipcp, (struct sppp *)cookie); 2852163953Srrs} 2853163953Srrs 2854172090Srrs/* 2855216887Stuexen * Analyze a configure request. Return true if it was agreeable, and 2856216887Stuexen * caused action sca, false if it has been rejected or nak'ed, and 2857216887Stuexen * caused action scn. (The return value is used to make the state 2858216887Stuexen * transition decision in the state automaton.) 2859166086Srrs */ 2860166086Srrsstatic int 2861166086Srrssppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) 2862166086Srrs{ 2863237565Stuexen u_char *buf, *r, *p; 2864172090Srrs struct ifnet *ifp = &sp->pp_if; 2865172090Srrs int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 2866172090Srrs u_long hisaddr, desiredaddr; 2867172090Srrs int gotmyaddr = 0; 2868166086Srrs int desiredcomp; 2869237565Stuexen 2870172118Srrs len -= 4; 2871172118Srrs origlen = len; 2872172090Srrs /* 2873172090Srrs * Make sure to allocate a buf that can at least hold a 2874163953Srrs * conf-nak with an `address' option. We might need it below. 2875163953Srrs */ 2876163953Srrs buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 2877216887Stuexen if (! buf) 2878216887Stuexen return (0); 2879216887Stuexen 2880216887Stuexen /* pass 1: see if we can recognize them */ 2881216887Stuexen if (debug) 2882216887Stuexen log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ", 2883216887Stuexen SPP_ARGS(ifp)); 2884216887Stuexen p = (void*) (h+1); 2885163953Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 2886163953Srrs if (debug) 2887163953Srrs log(-1, " %s ", sppp_ipcp_opt_name(*p)); 2888163953Srrs switch (*p) { 2889163953Srrs case IPCP_OPT_COMPRESSION: 2890228653Stuexen if (!(sp->confflags & CONF_ENABLE_VJ)) { 2891163953Srrs /* VJ compression administratively disabled */ 2892163953Srrs if (debug) 2893163953Srrs log(-1, "[locally disabled] "); 2894163953Srrs break; 2895163953Srrs } 2896169420Srrs /* 2897169420Srrs * In theory, we should only conf-rej an 2898163953Srrs * option that is shorter than RFC 1618 2899163953Srrs * requires (i.e. < 4), and should conf-nak 2900163953Srrs * anything else that is not VJ. However, 2901163953Srrs * since our algorithm always uses the 2902163953Srrs * original option to NAK it with new values, 2903163953Srrs * things would become more complicated. In 2904163953Srrs * pratice, the only commonly implemented IP 2905163953Srrs * compression option is VJ anyway, so the 2906163953Srrs * difference is negligible. 2907169420Srrs */ 2908171943Srrs if (len >= 6 && p[1] == 6) { 2909224641Stuexen /* 2910163953Srrs * correctly formed compression option 2911163953Srrs * that could be VJ compression 2912163953Srrs */ 2913163953Srrs continue; 2914163953Srrs } 2915163953Srrs if (debug) 2916163953Srrs log(-1, 2917163953Srrs "optlen %d [invalid/unsupported] ", 2918163953Srrs p[1]); 2919163953Srrs break; 2920218186Srrs case IPCP_OPT_ADDRESS: 2921219397Srrs if (len >= 6 && p[1] == 6) { 2922163953Srrs /* correctly formed address option */ 2923169378Srrs continue; 2924172090Srrs } 2925163953Srrs if (debug) 2926163953Srrs log(-1, "[invalid] "); 2927237565Stuexen break; 2928172090Srrs default: 2929172090Srrs /* Others not supported. */ 2930172090Srrs if (debug) 2931163953Srrs log(-1, "[rej] "); 2932237565Stuexen break; 2933172090Srrs } 2934172090Srrs /* Add the option to rejected list. */ 2935172090Srrs bcopy (p, r, p[1]); 2936172090Srrs r += p[1]; 2937172090Srrs rlen += p[1]; 2938172090Srrs } 2939218641Srrs if (rlen) { 2940218641Srrs if (debug) 2941218641Srrs log(-1, " send conf-rej\n"); 2942172090Srrs sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf); 2943237565Stuexen return 0; 2944172090Srrs } else if (debug) 2945172090Srrs log(-1, "\n"); 2946163953Srrs 2947163953Srrs /* pass 2: parse option values */ 2948163953Srrs sppp_get_ip_addrs(sp, 0, &hisaddr, 0); 2949163953Srrs if (debug) 2950163953Srrs log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ", 2951163953Srrs SPP_ARGS(ifp)); 2952163953Srrs p = (void*) (h+1); 2953218641Srrs len = origlen; 2954218641Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 2955218641Srrs if (debug) 2956218641Srrs log(-1, " %s ", sppp_ipcp_opt_name(*p)); 2957218641Srrs switch (*p) { 2958218641Srrs case IPCP_OPT_COMPRESSION: 2959218641Srrs desiredcomp = p[2] << 8 | p[3]; 2960218641Srrs /* We only support VJ */ 2961218641Srrs if (desiredcomp == IPCP_COMP_VJ) { 2962218641Srrs if (debug) 2963218641Srrs log(-1, "VJ [ack] "); 2964163953Srrs sp->ipcp.flags |= IPCP_VJ; 2965163953Srrs sl_compress_init(sp->pp_comp, p[4]); 2966163953Srrs sp->ipcp.max_state = p[4]; 2967163953Srrs sp->ipcp.compress_cid = p[5]; 2968163953Srrs continue; 2969163953Srrs } 2970171572Srrs if (debug) 2971171572Srrs log(-1, 2972171572Srrs "compproto %#04x [not supported] ", 2973163953Srrs desiredcomp); 2974163953Srrs p[2] = IPCP_COMP_VJ >> 8; 2975163953Srrs p[3] = IPCP_COMP_VJ; 2976163953Srrs p[4] = sp->ipcp.max_state; 2977171572Srrs p[5] = sp->ipcp.compress_cid; 2978163953Srrs break; 2979163953Srrs case IPCP_OPT_ADDRESS: 2980163953Srrs /* This is the address he wants in his end */ 2981171572Srrs desiredaddr = p[2] << 24 | p[3] << 16 | 2982172190Srrs p[4] << 8 | p[5]; 2983172190Srrs if (desiredaddr == hisaddr || 2984171572Srrs (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) { 2985163953Srrs /* 2986163953Srrs * Peer's address is same as our value, 2987218641Srrs * or we have set it to 0.0.0.* to 2988163953Srrs * indicate that we do not really care, 2989163953Srrs * this is agreeable. Gonna conf-ack 2990163953Srrs * it. 2991163953Srrs */ 2992163953Srrs if (debug) 2993163953Srrs log(-1, "%s [ack] ", 2994163953Srrs sppp_dotted_quad(hisaddr)); 2995216822Stuexen /* record that we've seen it already */ 2996163953Srrs sp->ipcp.flags |= IPCP_HISADDR_SEEN; 2997163953Srrs continue; 2998163953Srrs } 2999163953Srrs /* 3000163953Srrs * The address wasn't agreeable. This is either 3001163953Srrs * he sent us 0.0.0.0, asking to assign him an 3002163953Srrs * address, or he send us another address not 3003163953Srrs * matching our value. Either case, we gonna 3004163953Srrs * conf-nak it with our value. 3005218072Srrs * XXX: we should "rej" if hisaddr == 0 3006228907Stuexen */ 3007218072Srrs if (debug) { 3008218072Srrs if (desiredaddr == 0) 3009218232Srrs log(-1, "[addr requested] "); 3010163953Srrs else 3011218072Srrs log(-1, "%s [not agreed] ", 3012218072Srrs sppp_dotted_quad(desiredaddr)); 3013218072Srrs 3014163953Srrs } 3015163953Srrs p[2] = hisaddr >> 24; 3016218072Srrs p[3] = hisaddr >> 16; 3017218072Srrs p[4] = hisaddr >> 8; 3018218072Srrs p[5] = hisaddr; 3019218072Srrs break; 3020218072Srrs } 3021218072Srrs /* Add the option to nak'ed list. */ 3022163953Srrs bcopy (p, r, p[1]); 3023163953Srrs r += p[1]; 3024218072Srrs rlen += p[1]; 3025218072Srrs } 3026163953Srrs 3027218129Srrs /* 3028163953Srrs * If we are about to conf-ack the request, but haven't seen 3029218129Srrs * his address so far, gonna conf-nak it instead, with the 3030163953Srrs * `address' option present and our idea of his address being 3031163953Srrs * filled in there, to request negotiation of both addresses. 3032218072Srrs * 3033163953Srrs * XXX This can result in an endless req - nak loop if peer 3034216822Stuexen * doesn't want to send us his address. Q: What should we do 3035163953Srrs * about it? XXX A: implement the max-failure counter. 3036163953Srrs */ 3037218186Srrs if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { 3038163953Srrs buf[0] = IPCP_OPT_ADDRESS; 3039163953Srrs buf[1] = 6; 3040216825Stuexen buf[2] = hisaddr >> 24; 3041163953Srrs buf[3] = hisaddr >> 16; 3042216825Stuexen buf[4] = hisaddr >> 8; 3043163953Srrs buf[5] = hisaddr; 3044218072Srrs rlen = 6; 3045163953Srrs if (debug) 3046218072Srrs log(-1, "still need hisaddr "); 3047218072Srrs } 3048218072Srrs 3049218072Srrs if (rlen) { 3050218072Srrs if (debug) 3051218072Srrs log(-1, " send conf-nak\n"); 3052218072Srrs sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf); 3053228907Stuexen } else { 3054218072Srrs if (debug) 3055218072Srrs log(-1, " send conf-ack\n"); 3056228907Stuexen sppp_cp_send (sp, PPP_IPCP, CONF_ACK, 3057228907Stuexen h->ident, origlen, h+1); 3058228907Stuexen } 3059228907Stuexen 3060228907Stuexen free (buf, M_TEMP); 3061228907Stuexen return (rlen == 0); 3062228907Stuexen} 3063228907Stuexen 3064228907Stuexen/* 3065228907Stuexen * Analyze the IPCP Configure-Reject option list, and adjust our 3066228907Stuexen * negotiation. 3067228907Stuexen */ 3068228907Stuexenstatic void 3069228907Stuexensppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3070228907Stuexen{ 3071228907Stuexen u_char *buf, *p; 3072228907Stuexen struct ifnet *ifp = &sp->pp_if; 3073218072Srrs int debug = ifp->if_flags & IFF_DEBUG; 3074218129Srrs 3075218129Srrs len -= 4; 3076218072Srrs buf = malloc (len, M_TEMP, M_NOWAIT); 3077171440Srrs if (!buf) 3078171440Srrs return; 3079171440Srrs 3080218129Srrs if (debug) 3081171440Srrs log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ", 3082218072Srrs SPP_ARGS(ifp)); 3083218072Srrs 3084163953Srrs p = (void*) (h+1); 3085218072Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 3086218072Srrs if (debug) 3087218072Srrs log(-1, " %s ", sppp_ipcp_opt_name(*p)); 3088218072Srrs switch (*p) { 3089218072Srrs case IPCP_OPT_COMPRESSION: 3090218072Srrs sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION); 3091218129Srrs break; 3092218129Srrs case IPCP_OPT_ADDRESS: 3093218072Srrs /* 3094218129Srrs * Peer doesn't grok address option. This is 3095218129Srrs * bad. XXX Should we better give up here? 3096218072Srrs * XXX We could try old "addresses" option... 3097218129Srrs */ 3098218072Srrs sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); 3099218072Srrs break; 3100218072Srrs } 3101218129Srrs } 3102218129Srrs if (debug) 3103218072Srrs log(-1, "\n"); 3104218129Srrs free (buf, M_TEMP); 3105218072Srrs return; 3106218129Srrs} 3107218129Srrs 3108218129Srrs/* 3109218129Srrs * Analyze the IPCP Configure-NAK option list, and adjust our 3110218129Srrs * negotiation. 3111218072Srrs */ 3112163953Srrsstatic void 3113163953Srrssppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3114163953Srrs{ 3115163953Srrs u_char *buf, *p; 3116218072Srrs struct ifnet *ifp = &sp->pp_if; 3117218072Srrs int debug = ifp->if_flags & IFF_DEBUG; 3118163953Srrs int desiredcomp; 3119218072Srrs u_long wantaddr; 3120163953Srrs 3121163953Srrs len -= 4; 3122163953Srrs buf = malloc (len, M_TEMP, M_NOWAIT); 3123218072Srrs if (!buf) 3124163953Srrs return; 3125163953Srrs 3126163953Srrs if (debug) 3127163953Srrs log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ", 3128163953Srrs SPP_ARGS(ifp)); 3129163953Srrs 3130163953Srrs p = (void*) (h+1); 3131163953Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 3132218072Srrs if (debug) 3133218072Srrs log(-1, " %s ", sppp_ipcp_opt_name(*p)); 3134163953Srrs switch (*p) { 3135218072Srrs case IPCP_OPT_COMPRESSION: 3136218072Srrs if (len >= 6 && p[1] == 6) { 3137218072Srrs desiredcomp = p[2] << 8 | p[3]; 3138163953Srrs if (debug) 3139163953Srrs log(-1, "[wantcomp %#04x] ", 3140163953Srrs desiredcomp); 3141163953Srrs if (desiredcomp == IPCP_COMP_VJ) { 3142218072Srrs sl_compress_init(sp->pp_comp, p[4]); 3143218072Srrs sp->ipcp.max_state = p[4]; 3144218072Srrs sp->ipcp.compress_cid = p[5]; 3145218072Srrs if (debug) 3146163953Srrs log(-1, "[agree] "); 3147218072Srrs } else 3148163953Srrs sp->ipcp.opts &= 3149163953Srrs ~(1 << IPCP_OPT_COMPRESSION); 3150163953Srrs } 3151163953Srrs break; 3152163953Srrs case IPCP_OPT_ADDRESS: 3153163953Srrs /* 3154163953Srrs * Peer doesn't like our local IP address. See 3155163953Srrs * if we can do something for him. We'll drop 3156163953Srrs * him our address then. 3157221627Stuexen */ 3158218072Srrs if (len >= 6 && p[1] == 6) { 3159218072Srrs wantaddr = p[2] << 24 | p[3] << 16 | 3160218072Srrs p[4] << 8 | p[5]; 3161163953Srrs sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); 3162163953Srrs if (debug) 3163163953Srrs log(-1, "[wantaddr %s] ", 3164163953Srrs sppp_dotted_quad(wantaddr)); 3165163953Srrs /* 3166228653Stuexen * When doing dynamic address assignment, 3167163953Srrs * we accept his offer. Otherwise, we 3168163953Srrs * ignore it and thus continue to negotiate 3169163953Srrs * our already existing value. 3170163953Srrs * XXX: Bogus, if he said no once, he'll 3171237565Stuexen * just say no again, might as well die. 3172172090Srrs */ 3173172090Srrs if (sp->ipcp.flags & IPCP_MYADDR_DYN) { 3174172090Srrs sppp_set_ip_addr(sp, wantaddr); 3175172090Srrs if (debug) 3176169420Srrs log(-1, "[agree] "); 3177169420Srrs sp->ipcp.flags |= IPCP_MYADDR_SEEN; 3178163953Srrs } 3179163953Srrs } 3180163953Srrs break; 3181163953Srrs } 3182163953Srrs } 3183163953Srrs if (debug) 3184163953Srrs log(-1, "\n"); 3185171990Srrs free (buf, M_TEMP); 3186171990Srrs return; 3187163953Srrs} 3188163953Srrs 3189163953Srrsstatic void 3190163953Srrssppp_ipcp_tlu(struct sppp *sp) 3191163953Srrs{ 3192172090Srrs /* we are up - notify isdn daemon */ 3193163953Srrs if (sp->pp_con) 3194163953Srrs sp->pp_con(sp); 3195163953Srrs} 3196217760Stuexen 3197235416Stuexenstatic void 3198163953Srrssppp_ipcp_tld(struct sppp *sp) 3199163953Srrs{ 3200163953Srrs} 3201178202Srrs 3202163953Srrsstatic void 3203163953Srrssppp_ipcp_tls(struct sppp *sp) 3204171990Srrs{ 3205171990Srrs /* indicate to LCP that it must stay alive */ 3206237565Stuexen sp->lcp.protos |= (1 << IDX_IPCP); 3207172090Srrs} 3208172090Srrs 3209172090Srrsstatic void 3210172090Srrssppp_ipcp_tlf(struct sppp *sp) 3211172090Srrs{ 3212172090Srrs /* we no longer need LCP */ 3213172090Srrs sp->lcp.protos &= ~(1 << IDX_IPCP); 3214171943Srrs sppp_lcp_check_and_close(sp); 3215237565Stuexen} 3216172090Srrs 3217172090Srrsstatic void 3218163953Srrssppp_ipcp_scr(struct sppp *sp) 3219163953Srrs{ 3220163953Srrs char opt[6 /* compression */ + 6 /* address */]; 3221163953Srrs u_long ouraddr; 3222163953Srrs int i = 0; 3223163953Srrs 3224163953Srrs if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) { 3225163953Srrs opt[i++] = IPCP_OPT_COMPRESSION; 3226211969Stuexen opt[i++] = 6; 3227163953Srrs opt[i++] = IPCP_COMP_VJ >> 8; 3228163953Srrs opt[i++] = IPCP_COMP_VJ; 3229163953Srrs opt[i++] = sp->ipcp.max_state; 3230163953Srrs opt[i++] = sp->ipcp.compress_cid; 3231163953Srrs } 3232163953Srrs if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) { 3233216822Stuexen sppp_get_ip_addrs(sp, &ouraddr, 0, 0); 3234163953Srrs opt[i++] = IPCP_OPT_ADDRESS; 3235163953Srrs opt[i++] = 6; 3236163953Srrs opt[i++] = ouraddr >> 24; 3237163953Srrs opt[i++] = ouraddr >> 16; 3238216825Stuexen opt[i++] = ouraddr >> 8; 3239163953Srrs opt[i++] = ouraddr; 3240163953Srrs } 3241163953Srrs 3242163953Srrs sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP]; 3243163953Srrs sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt); 3244163953Srrs} 3245163953Srrs 3246163953Srrs/* 3247163953Srrs *--------------------------------------------------------------------------* 3248163953Srrs * * 3249163953Srrs * The IPv6CP implementation. * 3250216822Stuexen * * 3251163953Srrs *--------------------------------------------------------------------------* 3252163953Srrs */ 3253163953Srrs 3254163953Srrs#ifdef INET6 3255163953Srrsstatic void 3256163953Srrssppp_ipv6cp_init(struct sppp *sp) 3257163953Srrs{ 3258163953Srrs sp->ipv6cp.opts = 0; 3259163953Srrs sp->ipv6cp.flags = 0; 3260163953Srrs sp->state[IDX_IPV6CP] = STATE_INITIAL; 3261163953Srrs sp->fail_counter[IDX_IPV6CP] = 0; 3262163953Srrs sp->pp_seq[IDX_IPV6CP] = 0; 3263214877Stuexen sp->pp_rseq[IDX_IPV6CP] = 0; 3264214877Stuexen#if defined(__NetBSD__) 3265214877Stuexen callout_init(&sp->ch[IDX_IPV6CP]); 3266214877Stuexen#endif 3267163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 3268163953Srrs callout_handle_init(&sp->ch[IDX_IPV6CP]); 3269163953Srrs#endif 3270163953Srrs} 3271163953Srrs 3272163953Srrsstatic void 3273163953Srrssppp_ipv6cp_up(struct sppp *sp) 3274163953Srrs{ 3275163953Srrs sppp_up_event(&ipv6cp, sp); 3276163953Srrs} 3277163953Srrs 3278163953Srrsstatic void 3279163953Srrssppp_ipv6cp_down(struct sppp *sp) 3280163953Srrs{ 3281163953Srrs sppp_down_event(&ipv6cp, sp); 3282163953Srrs} 3283163953Srrs 3284163953Srrsstatic void 3285163953Srrssppp_ipv6cp_open(struct sppp *sp) 3286163953Srrs{ 3287163953Srrs STDDCL; 3288163953Srrs struct in6_addr myaddr, hisaddr; 3289163953Srrs 3290163953Srrs#ifdef IPV6CP_MYIFID_DYN 3291163953Srrs sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN); 3292163953Srrs#else 3293163953Srrs sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN; 3294163953Srrs#endif 3295163953Srrs 3296219397Srrs sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0); 3297219397Srrs /* 3298219397Srrs * If we don't have our address, this probably means our 3299163953Srrs * interface doesn't want to talk IPv6 at all. (This could 3300163953Srrs * be the case if somebody wants to speak only IPX, for 3301163953Srrs * example.) Don't open IPv6CP in this case. 3302163953Srrs */ 3303163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) { 3304163953Srrs /* XXX this message should go away */ 3305163953Srrs if (debug) 3306163953Srrs log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n", 3307163953Srrs SPP_ARGS(ifp)); 3308163953Srrs return; 3309163953Srrs } 3310163953Srrs 3311163953Srrs sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 3312163953Srrs sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 3313163953Srrs sppp_open_event(&ipv6cp, sp); 3314163953Srrs} 3315163953Srrs 3316163953Srrsstatic void 3317163953Srrssppp_ipv6cp_close(struct sppp *sp) 3318163953Srrs{ 3319163953Srrs sppp_close_event(&ipv6cp, sp); 3320163953Srrs} 3321163953Srrs 3322171440Srrsstatic void 3323163953Srrssppp_ipv6cp_TO(void *cookie) 3324163953Srrs{ 3325163953Srrs sppp_to_event(&ipv6cp, (struct sppp *)cookie); 3326163953Srrs} 3327179783Srrs 3328170744Srrs/* 3329170744Srrs * Analyze a configure request. Return true if it was agreeable, and 3330170744Srrs * caused action sca, false if it has been rejected or nak'ed, and 3331170744Srrs * caused action scn. (The return value is used to make the state 3332170744Srrs * transition decision in the state automaton.) 3333170744Srrs */ 3334190689Srrsstatic int 3335190689Srrssppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3336190689Srrs{ 3337190689Srrs u_char *buf, *r, *p; 3338216502Stuexen struct ifnet *ifp = &sp->pp_if; 3339163953Srrs int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; 3340163953Srrs struct in6_addr myaddr, desiredaddr, suggestaddr; 3341163953Srrs int ifidcount; 3342163953Srrs int type; 3343163953Srrs int collision, nohisaddr; 3344163953Srrs 3345163953Srrs len -= 4; 3346163953Srrs origlen = len; 3347163953Srrs /* 3348163953Srrs * Make sure to allocate a buf that can at least hold a 3349163953Srrs * conf-nak with an `address' option. We might need it below. 3350163953Srrs */ 3351163953Srrs buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT); 3352163953Srrs if (! buf) 3353163953Srrs return (0); 3354169420Srrs 3355163953Srrs /* pass 1: see if we can recognize them */ 3356163953Srrs if (debug) 3357163953Srrs log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:", 3358163953Srrs SPP_ARGS(ifp)); 3359163953Srrs p = (void*) (h+1); 3360163953Srrs ifidcount = 0; 3361163953Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 3362163953Srrs if (debug) 3363163953Srrs log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 3364163953Srrs switch (*p) { 3365163953Srrs case IPV6CP_OPT_IFID: 3366163953Srrs if (len >= 10 && p[1] == 10 && ifidcount == 0) { 3367163953Srrs /* correctly formed address option */ 3368163953Srrs ifidcount++; 3369163953Srrs continue; 3370163953Srrs } 3371163953Srrs if (debug) 3372163953Srrs log(-1, " [invalid]"); 3373163953Srrs break; 3374163953Srrs#ifdef notyet 3375163953Srrs case IPV6CP_OPT_COMPRESSION: 3376163953Srrs if (len >= 4 && p[1] >= 4) { 3377163953Srrs /* correctly formed compress option */ 3378163953Srrs continue; 3379163953Srrs } 3380163953Srrs if (debug) 3381163953Srrs log(-1, " [invalid]"); 3382163953Srrs break; 3383163953Srrs#endif 3384163953Srrs default: 3385163953Srrs /* Others not supported. */ 3386163953Srrs if (debug) 3387163953Srrs log(-1, " [rej]"); 3388163953Srrs break; 3389163953Srrs } 3390171440Srrs /* Add the option to rejected list. */ 3391172090Srrs bcopy (p, r, p[1]); 3392163953Srrs r += p[1]; 3393163953Srrs rlen += p[1]; 3394163953Srrs } 3395206137Stuexen if (rlen) { 3396163953Srrs if (debug) 3397221627Stuexen log(-1, " send conf-rej\n"); 3398163953Srrs sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf); 3399163953Srrs goto end; 3400163953Srrs } else if (debug) 3401171440Srrs log(-1, "\n"); 3402171440Srrs 3403171440Srrs /* pass 2: parse option values */ 3404171440Srrs sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 3405171440Srrs if (debug) 3406224641Stuexen log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ", 3407171440Srrs SPP_ARGS(ifp)); 3408163953Srrs p = (void*) (h+1); 3409163953Srrs len = origlen; 3410163953Srrs type = CONF_ACK; 3411163953Srrs for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { 3412163953Srrs if (debug) 3413163953Srrs log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 3414163953Srrs switch (*p) { 3415163953Srrs#ifdef notyet 3416163953Srrs case IPV6CP_OPT_COMPRESSION: 3417163953Srrs continue; 3418163953Srrs#endif 3419163953Srrs case IPV6CP_OPT_IFID: 3420163953Srrs bzero(&desiredaddr, sizeof(desiredaddr)); 3421163953Srrs bcopy(&p[2], &desiredaddr.s6_addr[8], 8); 3422163953Srrs collision = (bcmp(&desiredaddr.s6_addr[8], 3423163953Srrs &myaddr.s6_addr[8], 8) == 0); 3424163953Srrs nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr); 3425163953Srrs 3426163953Srrs desiredaddr.s6_addr16[0] = htons(0xfe80); 3427163953Srrs desiredaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 3428163953Srrs 3429163953Srrs if (!collision && !nohisaddr) { 3430163953Srrs /* no collision, hisaddr known - Conf-Ack */ 3431163953Srrs type = CONF_ACK; 3432163953Srrs 3433163953Srrs if (debug) { 3434163953Srrs log(-1, " %s [%s]", 3435163953Srrs ip6_sprintf(&desiredaddr), 3436163953Srrs sppp_cp_type_name(type)); 3437163953Srrs } 3438163953Srrs continue; 3439171990Srrs } 3440163953Srrs 3441163953Srrs bzero(&suggestaddr, sizeof(&suggestaddr)); 3442163953Srrs if (collision && nohisaddr) { 3443163953Srrs /* collision, hisaddr unknown - Conf-Rej */ 3444163953Srrs type = CONF_REJ; 3445163953Srrs bzero(&p[2], 8); 3446163953Srrs } else { 3447163953Srrs /* 3448163953Srrs * - no collision, hisaddr unknown, or 3449163953Srrs * - collision, hisaddr known 3450163953Srrs * Conf-Nak, suggest hisaddr 3451163953Srrs */ 3452163953Srrs type = CONF_NAK; 3453163953Srrs sppp_suggest_ip6_addr(sp, &suggestaddr); 3454163953Srrs bcopy(&suggestaddr.s6_addr[8], &p[2], 8); 3455163953Srrs } 3456163953Srrs if (debug) 3457163953Srrs log(-1, " %s [%s]", ip6_sprintf(&desiredaddr), 3458163953Srrs sppp_cp_type_name(type)); 3459163953Srrs break; 3460163953Srrs } 3461163953Srrs /* Add the option to nak'ed list. */ 3462163953Srrs bcopy (p, r, p[1]); 3463163953Srrs r += p[1]; 3464163953Srrs rlen += p[1]; 3465163953Srrs } 3466163953Srrs 3467163953Srrs if (rlen == 0 && type == CONF_ACK) { 3468163953Srrs if (debug) 3469163953Srrs log(-1, " send %s\n", sppp_cp_type_name(type)); 3470163953Srrs sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1); 3471163953Srrs } else { 3472163953Srrs#ifdef DIAGNOSTIC 3473163953Srrs if (type == CONF_ACK) 3474163953Srrs panic("IPv6CP RCR: CONF_ACK with non-zero rlen"); 3475163953Srrs#endif 3476163953Srrs 3477163953Srrs if (debug) { 3478163953Srrs log(-1, " send %s suggest %s\n", 3479163953Srrs sppp_cp_type_name(type), ip6_sprintf(&suggestaddr)); 3480163953Srrs } 3481163953Srrs sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf); 3482163953Srrs } 3483163953Srrs 3484172090Srrs end: 3485163953Srrs free (buf, M_TEMP); 3486163953Srrs return (rlen == 0); 3487163953Srrs} 3488163953Srrs 3489163953Srrs/* 3490163953Srrs * Analyze the IPv6CP Configure-Reject option list, and adjust our 3491163953Srrs * negotiation. 3492163953Srrs */ 3493163953Srrsstatic void 3494163953Srrssppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3495163953Srrs{ 3496163953Srrs u_char *buf, *p; 3497163953Srrs struct ifnet *ifp = &sp->pp_if; 3498163953Srrs int debug = ifp->if_flags & IFF_DEBUG; 3499163953Srrs 3500163953Srrs len -= 4; 3501163953Srrs buf = malloc (len, M_TEMP, M_NOWAIT); 3502163953Srrs if (!buf) 3503163953Srrs return; 3504163953Srrs 3505163953Srrs if (debug) 3506163953Srrs log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:", 3507163953Srrs SPP_ARGS(ifp)); 3508172090Srrs 3509163953Srrs p = (void*) (h+1); 3510163953Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 3511163953Srrs if (debug) 3512163953Srrs log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 3513163953Srrs switch (*p) { 3514163953Srrs case IPV6CP_OPT_IFID: 3515163953Srrs /* 3516163953Srrs * Peer doesn't grok address option. This is 3517163953Srrs * bad. XXX Should we better give up here? 3518163953Srrs */ 3519163953Srrs sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID); 3520163953Srrs break; 3521163953Srrs#ifdef notyet 3522163953Srrs case IPV6CP_OPT_COMPRESS: 3523169208Srrs sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS); 3524163953Srrs break; 3525163953Srrs#endif 3526163953Srrs } 3527169208Srrs } 3528163953Srrs if (debug) 3529163953Srrs log(-1, "\n"); 3530163953Srrs free (buf, M_TEMP); 3531163953Srrs return; 3532163953Srrs} 3533163953Srrs 3534163953Srrs/* 3535163953Srrs * Analyze the IPv6CP Configure-NAK option list, and adjust our 3536163953Srrs * negotiation. 3537163953Srrs */ 3538163953Srrsstatic void 3539163953Srrssppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3540163953Srrs{ 3541163953Srrs u_char *buf, *p; 3542163953Srrs struct ifnet *ifp = &sp->pp_if; 3543163953Srrs int debug = ifp->if_flags & IFF_DEBUG; 3544163953Srrs struct in6_addr suggestaddr; 3545163953Srrs 3546163953Srrs len -= 4; 3547163953Srrs buf = malloc (len, M_TEMP, M_NOWAIT); 3548163953Srrs if (!buf) 3549163953Srrs return; 3550163953Srrs 3551163953Srrs if (debug) 3552163953Srrs log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:", 3553163953Srrs SPP_ARGS(ifp)); 3554163953Srrs 3555163953Srrs p = (void*) (h+1); 3556163953Srrs for (; len > 1 && p[1]; len -= p[1], p += p[1]) { 3557163953Srrs if (debug) 3558163953Srrs log(-1, " %s", sppp_ipv6cp_opt_name(*p)); 3559163953Srrs switch (*p) { 3560163953Srrs case IPV6CP_OPT_IFID: 3561163953Srrs /* 3562163953Srrs * Peer doesn't like our local ifid. See 3563163953Srrs * if we can do something for him. We'll drop 3564163953Srrs * him our address then. 3565163953Srrs */ 3566166675Srrs if (len < 10 || p[1] != 10) 3567166675Srrs break; 3568171440Srrs bzero(&suggestaddr, sizeof(suggestaddr)); 3569163953Srrs suggestaddr.s6_addr16[0] = htons(0xfe80); 3570163953Srrs suggestaddr.s6_addr16[1] = htons(sp->pp_if.if_index); 3571163953Srrs bcopy(&p[2], &suggestaddr.s6_addr[8], 8); 3572163953Srrs 3573163953Srrs sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID); 3574163953Srrs if (debug) 3575163953Srrs log(-1, " [suggestaddr %s]", 3576163953Srrs ip6_sprintf(&suggestaddr)); 3577221627Stuexen#ifdef IPV6CP_MYIFID_DYN 3578172156Srrs /* 3579163953Srrs * When doing dynamic address assignment, 3580163953Srrs * we accept his offer. 3581163953Srrs */ 3582163953Srrs if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { 3583163953Srrs struct in6_addr lastsuggest; 3584163953Srrs /* 3585163953Srrs * If <suggested myaddr from peer> equals to 3586164139Srrs * <hisaddr we have suggested last time>, 3587163953Srrs * we have a collision. generate new random 3588163953Srrs * ifid. 3589163953Srrs */ 3590163953Srrs sppp_suggest_ip6_addr(&lastsuggest); 3591163953Srrs if (IN6_ARE_ADDR_EQUAL(&suggestaddr, 3592163953Srrs lastsuggest)) { 3593163953Srrs if (debug) 3594163953Srrs log(-1, " [random]"); 3595163953Srrs sppp_gen_ip6_addr(sp, &suggestaddr); 3596163953Srrs } 3597163953Srrs sppp_set_ip6_addr(sp, &suggestaddr, 0); 3598163953Srrs if (debug) 3599163953Srrs log(-1, " [agree]"); 3600163953Srrs sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN; 3601163953Srrs } 3602163953Srrs#else 3603163953Srrs /* 3604163953Srrs * Since we do not do dynamic address assignment, 3605163953Srrs * we ignore it and thus continue to negotiate 3606164139Srrs * our already existing value. This can possibly 3607163953Srrs * go into infinite request-reject loop. 3608163953Srrs * 3609163953Srrs * This is not likely because we normally use 3610235064Stuexen * ifid based on MAC-address. 3611163953Srrs * If you have no ethernet card on the node, too bad. 3612163953Srrs * XXX should we use fail_counter? 3613235066Stuexen */ 3614235066Stuexen#endif 3615163953Srrs break; 3616172090Srrs#ifdef notyet 3617163953Srrs case IPV6CP_OPT_COMPRESS: 3618163953Srrs /* 3619163953Srrs * Peer wants different compression parameters. 3620164139Srrs */ 3621163953Srrs break; 3622163953Srrs#endif 3623235066Stuexen } 3624235066Stuexen } 3625235066Stuexen if (debug) 3626235066Stuexen log(-1, "\n"); 3627233660Srrs free (buf, M_TEMP); 3628233660Srrs return; 3629163953Srrs} 3630233660Srrsstatic void 3631188854Srrssppp_ipv6cp_tlu(struct sppp *sp) 3632233660Srrs{ 3633233660Srrs /* we are up - notify isdn daemon */ 3634233660Srrs if (sp->pp_con) 3635233660Srrs sp->pp_con(sp); 3636233660Srrs} 3637233660Srrs 3638233660Srrsstatic void 3639233660Srrssppp_ipv6cp_tld(struct sppp *sp) 3640189121Srrs{ 3641189121Srrs} 3642235064Stuexen 3643188854Srrsstatic void 3644233660Srrssppp_ipv6cp_tls(struct sppp *sp) 3645233660Srrs{ 3646235066Stuexen /* indicate to LCP that it must stay alive */ 3647235066Stuexen sp->lcp.protos |= (1 << IDX_IPV6CP); 3648235066Stuexen} 3649188854Srrs 3650233660Srrsstatic void 3651235066Stuexensppp_ipv6cp_tlf(struct sppp *sp) 3652188854Srrs{ 3653233660Srrs 3654233660Srrs#if 0 /* need #if 0 to close IPv6CP properly */ 3655233660Srrs /* we no longer need LCP */ 3656235066Stuexen sp->lcp.protos &= ~(1 << IDX_IPV6CP); 3657233660Srrs sppp_lcp_check_and_close(sp); 3658235066Stuexen#endif 3659235066Stuexen} 3660235066Stuexen 3661235066Stuexenstatic void 3662233660Srrssppp_ipv6cp_scr(struct sppp *sp) 3663163953Srrs{ 3664163953Srrs char opt[10 /* ifid */ + 4 /* compression, minimum */]; 3665163953Srrs struct in6_addr ouraddr; 3666163953Srrs int i = 0; 3667163953Srrs 3668163953Srrs if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { 3669163953Srrs sppp_get_ip6_addrs(sp, &ouraddr, 0, 0); 3670163953Srrs opt[i++] = IPV6CP_OPT_IFID; 3671163953Srrs opt[i++] = 10; 3672163953Srrs bcopy(&ouraddr.s6_addr[8], &opt[i], 8); 3673163953Srrs i += 8; 3674163953Srrs } 3675163953Srrs 3676163953Srrs#ifdef notyet 3677235064Stuexen if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) { 3678163953Srrs opt[i++] = IPV6CP_OPT_COMPRESSION; 3679163953Srrs opt[i++] = 4; 3680163953Srrs opt[i++] = 0; /* TBD */ 3681163953Srrs opt[i++] = 0; /* TBD */ 3682163953Srrs /* variable length data may follow */ 3683170992Srrs } 3684163953Srrs#endif 3685163953Srrs 3686163953Srrs sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP]; 3687163953Srrs sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt); 3688179783Srrs} 3689179783Srrs#else /*INET6*/ 3690179783Srrsstatic void sppp_ipv6cp_init(struct sppp *sp) 3691180955Srrs{ 3692163953Srrs} 3693163953Srrs 3694185694Srrsstatic void sppp_ipv6cp_up(struct sppp *sp) 3695205627Srrs{ 3696206137Stuexen} 3697205627Srrs 3698163953Srrsstatic void sppp_ipv6cp_down(struct sppp *sp) 3699163953Srrs{ 3700163953Srrs} 3701163953Srrs 3702163953Srrs 3703233660Srrsstatic void sppp_ipv6cp_open(struct sppp *sp) 3704235066Stuexen{ 3705235066Stuexen} 3706235066Stuexen 3707233660Srrsstatic void sppp_ipv6cp_close(struct sppp *sp) 3708233660Srrs{ 3709235066Stuexen} 3710163953Srrs 3711163953Srrsstatic void sppp_ipv6cp_TO(void *sp) 3712163953Srrs{ 3713163953Srrs} 3714163953Srrs 3715163953Srrsstatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) 3716163953Srrs{ 3717163953Srrs return 0; 3718163953Srrs} 3719163953Srrs 3720163953Srrsstatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) 3721163953Srrs{ 3722163953Srrs} 3723163953Srrs 3724170992Srrsstatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) 3725163953Srrs{ 3726163953Srrs} 3727163953Srrs 3728163953Srrsstatic void sppp_ipv6cp_tlu(struct sppp *sp) 3729163953Srrs{ 3730163953Srrs} 3731163953Srrs 3732163953Srrsstatic void sppp_ipv6cp_tld(struct sppp *sp) 3733163953Srrs{ 3734163953Srrs} 3735163953Srrs 3736163953Srrsstatic void sppp_ipv6cp_tls(struct sppp *sp) 3737163953Srrs{ 3738163953Srrs} 3739235064Stuexen 3740235064Stuexenstatic void sppp_ipv6cp_tlf(struct sppp *sp) 3741235064Stuexen{ 3742235064Stuexen} 3743170992Srrs 3744235064Stuexenstatic void sppp_ipv6cp_scr(struct sppp *sp) 3745170992Srrs{ 3746163953Srrs} 3747163953Srrs#endif /*INET6*/ 3748163953Srrs 3749163953Srrs/* 3750163953Srrs *--------------------------------------------------------------------------* 3751163953Srrs * * 3752235064Stuexen * The CHAP implementation. * 3753163953Srrs * * 3754163953Srrs *--------------------------------------------------------------------------* 3755163953Srrs */ 3756163953Srrs 3757163953Srrs/* 3758163953Srrs * The authentication protocols don't employ a full-fledged state machine as 3759163953Srrs * the control protocols do, since they do have Open and Close events, but 3760163953Srrs * not Up and Down, nor are they explicitly terminated. Also, use of the 3761163953Srrs * authentication protocols may be different in both directions (this makes 3762235064Stuexen * sense, think of a machine that never accepts incoming calls but only 3763163953Srrs * calls out, it doesn't require the called party to authenticate itself). 3764233660Srrs * 3765163953Srrs * Our state machine for the local authentication protocol (we are requesting 3766163953Srrs * the peer to authenticate) looks like: 3767163953Srrs * 3768163953Srrs * RCA- 3769163953Srrs * +--------------------------------------------+ 3770163953Srrs * V scn,tld| 3771235064Stuexen * +--------+ Close +---------+ RCA+ 3772163953Srrs * | |<----------------------------------| |------+ 3773163953Srrs * +--->| Closed | TO* | Opened | sca | 3774163953Srrs * | | |-----+ +-------| |<-----+ 3775163953Srrs * | +--------+ irc | | +---------+ 3776163953Srrs * | ^ | | ^ 3777163953Srrs * | | | | | 3778163953Srrs * | | | | | 3779163953Srrs * | TO-| | | | 3780163953Srrs * | |tld TO+ V | | 3781163953Srrs * | | +------->+ | | 3782163953Srrs * | | | | | | 3783163953Srrs * | +--------+ V | | 3784163953Srrs * | | |<----+<--------------------+ | 3785163953Srrs * | | Req- | scr | 3786163953Srrs * | | Sent | | 3787163953Srrs * | | | | 3788163953Srrs * | +--------+ | 3789163953Srrs * | RCA- | | RCA+ | 3790163953Srrs * +------+ +------------------------------------------+ 3791163953Srrs * scn,tld sca,irc,ict,tlu 3792163953Srrs * 3793235283Stuexen * 3794235064Stuexen * with: 3795235064Stuexen * 3796235283Stuexen * Open: LCP reached authentication phase 3797235064Stuexen * Close: LCP reached terminate phase 3798235283Stuexen * 3799235283Stuexen * RCA+: received reply (pap-req, chap-response), acceptable 3800235283Stuexen * RCN: received reply (pap-req, chap-response), not acceptable 3801235283Stuexen * TO+: timeout with restart counter >= 0 3802235283Stuexen * TO-: timeout with restart counter < 0 3803235283Stuexen * TO*: reschedule timeout for CHAP 3804235283Stuexen * 3805235283Stuexen * scr: send request packet (none for PAP, chap-challenge) 3806235283Stuexen * sca: send ack packet (pap-ack, chap-success) 3807235283Stuexen * scn: send nak packet (pap-nak, chap-failure) 3808235283Stuexen * ict: initialize re-challenge timer (CHAP only) 3809235283Stuexen * 3810235283Stuexen * tlu: this-layer-up, LCP reaches network phase 3811235283Stuexen * tld: this-layer-down, LCP enters terminate phase 3812235283Stuexen * 3813235283Stuexen * Note that in CHAP mode, after sending a new challenge, while the state 3814235283Stuexen * automaton falls back into Req-Sent state, it doesn't signal a tld 3815235283Stuexen * event to LCP, so LCP remains in network phase. Only after not getting 3816235283Stuexen * any response (or after getting an unacceptable response), CHAP closes, 3817235283Stuexen * causing LCP to enter terminate phase. 3818235283Stuexen * 3819235283Stuexen * With PAP, there is no initial request that can be sent. The peer is 3820235283Stuexen * expected to send one based on the successful negotiation of PAP as 3821235283Stuexen * the authentication protocol during the LCP option negotiation. 3822235283Stuexen * 3823235283Stuexen * Incoming authentication protocol requests (remote requests 3824163953Srrs * authentication, we are peer) don't employ a state machine at all, 3825235283Stuexen * they are simply answered. Some peers [Ascend P50 firmware rev 3826235283Stuexen * 4.50] react allergically when sending IPCP requests while they are 3827163953Srrs * still in authentication phase (thereby violating the standard that 3828163953Srrs * demands that these NCP packets are to be discarded), so we keep 3829163953Srrs * track of the peer demanding us to authenticate, and only proceed to 3830235064Stuexen * phase network once we've seen a positive acknowledge for the 3831163953Srrs * authentication. 3832163953Srrs */ 3833235064Stuexen 3834163953Srrs/* 3835235064Stuexen * Handle incoming CHAP packets. 3836163953Srrs */ 3837163953Srrsstatic void 3838163953Srrssppp_chap_input(struct sppp *sp, struct mbuf *m) 3839163953Srrs{ 3840163953Srrs STDDCL; 3841163953Srrs struct lcp_header *h; 3842163953Srrs int len, x; 3843170992Srrs u_char *value, *name, digest[AUTHKEYLEN], dsize; 3844163953Srrs int value_len, name_len; 3845163953Srrs MD5_CTX ctx; 3846163953Srrs 3847163953Srrs len = m->m_pkthdr.len; 3848163953Srrs if (len < 4) { 3849163953Srrs if (debug) 3850163953Srrs log(LOG_DEBUG, 3851163953Srrs SPP_FMT "chap invalid packet length: %d bytes\n", 3852163953Srrs SPP_ARGS(ifp), len); 3853163953Srrs return; 3854163953Srrs } 3855163953Srrs h = mtod (m, struct lcp_header*); 3856163953Srrs if (len > ntohs (h->len)) 3857163953Srrs len = ntohs (h->len); 3858163953Srrs 3859163953Srrs switch (h->type) { 3860163953Srrs /* challenge, failure and success are his authproto */ 3861163953Srrs case CHAP_CHALLENGE: 3862163953Srrs value = 1 + (u_char*)(h+1); 3863163953Srrs value_len = value[-1]; 3864163953Srrs name = value + value_len; 3865163953Srrs name_len = len - value_len - 5; 3866235064Stuexen if (name_len < 0) { 3867235064Stuexen if (debug) { 3868235064Stuexen log(LOG_DEBUG, 3869235064Stuexen SPP_FMT "chap corrupted challenge " 3870216825Stuexen "<%s id=0x%x len=%d", 3871163953Srrs SPP_ARGS(ifp), 3872163953Srrs sppp_auth_type_name(PPP_CHAP, h->type), 3873235064Stuexen h->ident, ntohs(h->len)); 3874163953Srrs sppp_print_bytes((u_char*) (h+1), len-4); 3875163953Srrs log(-1, ">\n"); 3876163953Srrs } 3877163953Srrs break; 3878163953Srrs } 3879163953Srrs 3880163953Srrs if (debug) { 3881163953Srrs log(LOG_DEBUG, 3882163953Srrs SPP_FMT "chap input <%s id=0x%x len=%d name=", 3883163953Srrs SPP_ARGS(ifp), 3884170091Srrs sppp_auth_type_name(PPP_CHAP, h->type), h->ident, 3885163953Srrs ntohs(h->len)); 3886163953Srrs sppp_print_string((char*) name, name_len); 3887235064Stuexen log(-1, " value-size=%d value=", value_len); 3888235064Stuexen sppp_print_bytes(value, value_len); 3889163953Srrs log(-1, ">\n"); 3890163953Srrs } 3891163953Srrs 3892163953Srrs /* Compute reply value. */ 3893163953Srrs MD5Init(&ctx); 3894163953Srrs MD5Update(&ctx, &h->ident, 1); 3895163953Srrs MD5Update(&ctx, sp->myauth.secret, 3896235064Stuexen sppp_strnlen(sp->myauth.secret, AUTHKEYLEN)); 3897163953Srrs MD5Update(&ctx, value, value_len); 3898233660Srrs MD5Final(digest, &ctx); 3899163953Srrs dsize = sizeof digest; 3900163953Srrs 3901163953Srrs sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident, 3902163953Srrs sizeof dsize, (const char *)&dsize, 3903163953Srrs sizeof digest, digest, 3904163953Srrs (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 3905163953Srrs sp->myauth.name, 3906163953Srrs 0); 3907163953Srrs break; 3908163953Srrs 3909163953Srrs case CHAP_SUCCESS: 3910163953Srrs if (debug) { 3911163953Srrs log(LOG_DEBUG, SPP_FMT "chap success", 3912163953Srrs SPP_ARGS(ifp)); 3913235064Stuexen if (len > 4) { 3914163953Srrs log(-1, ": "); 3915163953Srrs sppp_print_string((char*)(h + 1), len - 4); 3916163953Srrs } 3917188854Srrs log(-1, "\n"); 3918188854Srrs } 3919188854Srrs x = splimp(); 3920188854Srrs sp->pp_flags &= ~PP_NEEDAUTH; 3921188854Srrs if (sp->myauth.proto == PPP_CHAP && 3922188854Srrs (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 3923188854Srrs (sp->lcp.protos & (1 << IDX_CHAP)) == 0) { 3924188854Srrs /* 3925233660Srrs * We are authenticator for CHAP but didn't 3926188854Srrs * complete yet. Leave it to tlu to proceed 3927189121Srrs * to network phase. 3928216822Stuexen */ 3929188854Srrs splx(x); 3930188854Srrs break; 3931188854Srrs } 3932188854Srrs splx(x); 3933188854Srrs sppp_phase_network(sp); 3934189121Srrs break; 3935189121Srrs 3936235064Stuexen case CHAP_FAILURE: 3937235064Stuexen if (debug) { 3938235064Stuexen log(LOG_INFO, SPP_FMT "chap failure", 3939235064Stuexen SPP_ARGS(ifp)); 3940233660Srrs if (len > 4) { 3941189121Srrs log(-1, ": "); 3942189121Srrs sppp_print_string((char*)(h + 1), len - 4); 3943235064Stuexen } 3944189121Srrs log(-1, "\n"); 3945189121Srrs } else 3946189121Srrs log(LOG_INFO, SPP_FMT "chap failure\n", 3947189121Srrs SPP_ARGS(ifp)); 3948189121Srrs /* await LCP shutdown by authenticator */ 3949189121Srrs break; 3950189121Srrs 3951189121Srrs /* response is my authproto */ 3952189121Srrs case CHAP_RESPONSE: 3953189121Srrs value = 1 + (u_char*)(h+1); 3954189121Srrs value_len = value[-1]; 3955189121Srrs name = value + value_len; 3956189121Srrs name_len = len - value_len - 5; 3957189121Srrs if (name_len < 0) { 3958189121Srrs if (debug) { 3959189121Srrs log(LOG_DEBUG, 3960189121Srrs SPP_FMT "chap corrupted response " 3961189121Srrs "<%s id=0x%x len=%d", 3962189121Srrs SPP_ARGS(ifp), 3963189121Srrs sppp_auth_type_name(PPP_CHAP, h->type), 3964216822Stuexen h->ident, ntohs(h->len)); 3965189121Srrs sppp_print_bytes((u_char*)(h+1), len-4); 3966189121Srrs log(-1, ">\n"); 3967189121Srrs } 3968189121Srrs break; 3969189121Srrs } 3970189121Srrs if (h->ident != sp->confid[IDX_CHAP]) { 3971189121Srrs if (debug) 3972189121Srrs log(LOG_DEBUG, 3973189121Srrs SPP_FMT "chap dropping response for old ID " 3974189121Srrs "(got %d, expected %d)\n", 3975189121Srrs SPP_ARGS(ifp), 3976189121Srrs h->ident, sp->confid[IDX_CHAP]); 3977189121Srrs break; 3978189121Srrs } 3979235064Stuexen if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) 3980233660Srrs || bcmp(name, sp->hisauth.name, name_len) != 0) { 3981189121Srrs log(LOG_INFO, SPP_FMT "chap response, his name ", 3982233660Srrs SPP_ARGS(ifp)); 3983233660Srrs sppp_print_string(name, name_len); 3984189121Srrs log(-1, " != expected "); 3985189121Srrs sppp_print_string(sp->hisauth.name, 3986189121Srrs sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)); 3987189121Srrs log(-1, "\n"); 3988189121Srrs } 3989189121Srrs if (debug) { 3990189121Srrs log(LOG_DEBUG, SPP_FMT "chap input(%s) " 3991189121Srrs "<%s id=0x%x len=%d name=", 3992189121Srrs SPP_ARGS(ifp), 3993189121Srrs sppp_state_name(sp->state[IDX_CHAP]), 3994189121Srrs sppp_auth_type_name(PPP_CHAP, h->type), 3995189121Srrs h->ident, ntohs (h->len)); 3996188854Srrs sppp_print_string((char*)name, name_len); 3997235064Stuexen log(-1, " value-size=%d value=", value_len); 3998188854Srrs sppp_print_bytes(value, value_len); 3999188854Srrs log(-1, ">\n"); 4000188854Srrs } 4001188854Srrs if (value_len != AUTHKEYLEN) { 4002233660Srrs if (debug) 4003233660Srrs log(LOG_DEBUG, 4004233660Srrs SPP_FMT "chap bad hash value length: " 4005233660Srrs "%d bytes, should be %d\n", 4006233660Srrs SPP_ARGS(ifp), value_len, 4007233660Srrs AUTHKEYLEN); 4008233660Srrs break; 4009233660Srrs } 4010233660Srrs 4011233660Srrs MD5Init(&ctx); 4012233660Srrs MD5Update(&ctx, &h->ident, 1); 4013233660Srrs MD5Update(&ctx, sp->hisauth.secret, 4014233660Srrs sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN)); 4015233660Srrs MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN); 4016233660Srrs MD5Final(digest, &ctx); 4017233660Srrs 4018233660Srrs#define FAILMSG "Failed..." 4019235064Stuexen#define SUCCMSG "Welcome!" 4020235064Stuexen 4021235064Stuexen if (value_len != sizeof digest || 4022235064Stuexen bcmp(digest, value, value_len) != 0) { 4023233660Srrs /* action scn, tld */ 4024235064Stuexen sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident, 4025233660Srrs sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 4026233660Srrs 0); 4027233660Srrs chap.tld(sp); 4028233660Srrs break; 4029233660Srrs } 4030233660Srrs /* action sca, perhaps tlu */ 4031233660Srrs if (sp->state[IDX_CHAP] == STATE_REQ_SENT || 4032235064Stuexen sp->state[IDX_CHAP] == STATE_OPENED) 4033233660Srrs sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident, 4034235064Stuexen sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 4035233660Srrs 0); 4036233660Srrs if (sp->state[IDX_CHAP] == STATE_REQ_SENT) { 4037235064Stuexen sppp_cp_change_state(&chap, sp, STATE_OPENED); 4038233660Srrs chap.tlu(sp); 4039233660Srrs } 4040233660Srrs break; 4041233660Srrs 4042233660Srrs default: 4043233660Srrs /* Unknown CHAP packet type -- ignore. */ 4044233660Srrs if (debug) { 4045233660Srrs log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) " 4046233660Srrs "<0x%x id=0x%xh len=%d", 4047233660Srrs SPP_ARGS(ifp), 4048233660Srrs sppp_state_name(sp->state[IDX_CHAP]), 4049233660Srrs h->type, h->ident, ntohs(h->len)); 4050233660Srrs sppp_print_bytes((u_char*)(h+1), len-4); 4051233660Srrs log(-1, ">\n"); 4052233660Srrs } 4053233660Srrs break; 4054233660Srrs 4055235064Stuexen } 4056233660Srrs} 4057233660Srrs 4058233660Srrsstatic void 4059170992Srrssppp_chap_init(struct sppp *sp) 4060170992Srrs{ 4061170992Srrs /* Chap doesn't have STATE_INITIAL at all. */ 4062170992Srrs sp->state[IDX_CHAP] = STATE_CLOSED; 4063170992Srrs sp->fail_counter[IDX_CHAP] = 0; 4064170992Srrs sp->pp_seq[IDX_CHAP] = 0; 4065163953Srrs sp->pp_rseq[IDX_CHAP] = 0; 4066163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4067170992Srrs callout_handle_init(&sp->ch[IDX_CHAP]); 4068170992Srrs#endif 4069233660Srrs} 4070163953Srrs 4071170992Srrsstatic void 4072163953Srrssppp_chap_open(struct sppp *sp) 4073163953Srrs{ 4074163953Srrs if (sp->myauth.proto == PPP_CHAP && 4075166675Srrs (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 4076166675Srrs /* we are authenticator for CHAP, start it */ 4077163953Srrs chap.scr(sp); 4078163953Srrs sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4079163953Srrs sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 4080163953Srrs } 4081163953Srrs /* nothing to be done if we are peer, await a challenge */ 4082163953Srrs} 4083163953Srrs 4084163953Srrsstatic void 4085163953Srrssppp_chap_close(struct sppp *sp) 4086163953Srrs{ 4087169208Srrs if (sp->state[IDX_CHAP] != STATE_CLOSED) 4088163953Srrs sppp_cp_change_state(&chap, sp, STATE_CLOSED); 4089163953Srrs} 4090163953Srrs 4091166023Srrsstatic void 4092165647Srrssppp_chap_TO(void *cookie) 4093163953Srrs{ 4094163953Srrs struct sppp *sp = (struct sppp *)cookie; 4095163953Srrs STDDCL; 4096163953Srrs int s; 4097163953Srrs 4098163953Srrs s = splimp(); 4099221627Stuexen if (debug) 4100163953Srrs log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n", 4101163953Srrs SPP_ARGS(ifp), 4102165647Srrs sppp_state_name(sp->state[IDX_CHAP]), 4103163953Srrs sp->rst_counter[IDX_CHAP]); 4104163953Srrs 4105163953Srrs if (--sp->rst_counter[IDX_CHAP] < 0) 4106163953Srrs /* TO- event */ 4107224641Stuexen switch (sp->state[IDX_CHAP]) { 4108163953Srrs case STATE_REQ_SENT: 4109163953Srrs chap.tld(sp); 4110163953Srrs sppp_cp_change_state(&chap, sp, STATE_CLOSED); 4111163953Srrs break; 4112163953Srrs } 4113165647Srrs else 4114170992Srrs /* TO+ (or TO*) event */ 4115163953Srrs switch (sp->state[IDX_CHAP]) { 4116170992Srrs case STATE_OPENED: 4117170992Srrs /* TO* event */ 4118170992Srrs sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4119163953Srrs /* FALLTHROUGH */ 4120163953Srrs case STATE_REQ_SENT: 4121163953Srrs chap.scr(sp); 4122163953Srrs /* sppp_cp_change_state() will restart the timer */ 4123163953Srrs sppp_cp_change_state(&chap, sp, STATE_REQ_SENT); 4124170994Srrs break; 4125170992Srrs } 4126163953Srrs 4127163953Srrs splx(s); 4128170994Srrs} 4129170992Srrs 4130170992Srrsstatic void 4131170992Srrssppp_chap_tlu(struct sppp *sp) 4132170992Srrs{ 4133163953Srrs STDDCL; 4134163953Srrs int i, x; 4135163953Srrs 4136163953Srrs i = 0; 4137163953Srrs sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure; 4138163953Srrs 4139163953Srrs /* 4140163953Srrs * Some broken CHAP implementations (Conware CoNet, firmware 4141163953Srrs * 4.0.?) don't want to re-authenticate their CHAP once the 4142163953Srrs * initial challenge-response exchange has taken place. 4143163953Srrs * Provide for an option to avoid rechallenges. 4144163953Srrs */ 4145163953Srrs if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) { 4146235064Stuexen /* 4147163953Srrs * Compute the re-challenge timeout. This will yield 4148163953Srrs * a number between 300 and 810 seconds. 4149170992Srrs */ 4150233660Srrs i = 300 + ((unsigned)(random() & 0xff00) >> 7); 4151188854Srrs TIMEOUT(chap.TO, (void *)sp, i * hz, sp->ch[IDX_CHAP]); 4152188854Srrs } 4153188854Srrs 4154188854Srrs if (debug) { 4155188854Srrs log(LOG_DEBUG, 4156233660Srrs SPP_FMT "chap %s, ", 4157233660Srrs SPP_ARGS(ifp), 4158233660Srrs sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu"); 4159233660Srrs if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) 4160233660Srrs log(-1, "next re-challenge in %d seconds\n", i); 4161233660Srrs else 4162163953Srrs log(-1, "re-challenging supressed\n"); 4163163953Srrs } 4164163953Srrs 4165163953Srrs x = splimp(); 4166163953Srrs /* indicate to LCP that we need to be closed down */ 4167170992Srrs sp->lcp.protos |= (1 << IDX_CHAP); 4168163953Srrs 4169163953Srrs if (sp->pp_flags & PP_NEEDAUTH) { 4170163953Srrs /* 4171163953Srrs * Remote is authenticator, but his auth proto didn't 4172163953Srrs * complete yet. Defer the transition to network 4173163953Srrs * phase. 4174163953Srrs */ 4175163953Srrs splx(x); 4176163953Srrs return; 4177163953Srrs } 4178163953Srrs splx(x); 4179163953Srrs 4180163953Srrs /* 4181163953Srrs * If we are already in phase network, we are done here. This 4182163953Srrs * is the case if this is a dummy tlu event after a re-challenge. 4183163953Srrs */ 4184163953Srrs if (sp->pp_phase != PHASE_NETWORK) 4185163953Srrs sppp_phase_network(sp); 4186163953Srrs} 4187163953Srrs 4188163953Srrsstatic void 4189163953Srrssppp_chap_tld(struct sppp *sp) 4190163953Srrs{ 4191163953Srrs STDDCL; 4192163953Srrs 4193170992Srrs if (debug) 4194163953Srrs log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp)); 4195163953Srrs UNTIMEOUT(chap.TO, (void *)sp, sp->ch[IDX_CHAP]); 4196163953Srrs sp->lcp.protos &= ~(1 << IDX_CHAP); 4197163953Srrs 4198163953Srrs lcp.Close(sp); 4199163953Srrs} 4200163953Srrs 4201163953Srrsstatic void 4202163953Srrssppp_chap_scr(struct sppp *sp) 4203163953Srrs{ 4204163953Srrs u_long *ch, seed; 4205163953Srrs u_char clen; 4206163953Srrs 4207163953Srrs /* Compute random challenge. */ 4208163953Srrs ch = (u_long *)sp->myauth.challenge; 4209163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4210163953Srrs read_random(&seed, sizeof seed); 4211163953Srrs#else 4212163953Srrs { 4213163953Srrs struct timeval tv; 4214163953Srrs microtime(&tv); 4215163953Srrs seed = tv.tv_sec ^ tv.tv_usec; 4216170781Srrs } 4217163953Srrs#endif 4218163953Srrs ch[0] = seed ^ random(); 4219163953Srrs ch[1] = seed ^ random(); 4220163953Srrs ch[2] = seed ^ random(); 4221163953Srrs ch[3] = seed ^ random(); 4222163953Srrs clen = AUTHKEYLEN; 4223163953Srrs 4224163953Srrs sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; 4225163953Srrs 4226163953Srrs sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], 4227163953Srrs sizeof clen, (const char *)&clen, 4228163953Srrs (size_t)AUTHKEYLEN, sp->myauth.challenge, 4229163953Srrs (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN), 4230163953Srrs sp->myauth.name, 4231163953Srrs 0); 4232163953Srrs} 4233163953Srrs 4234163953Srrs/* 4235163953Srrs *--------------------------------------------------------------------------* 4236163953Srrs * * 4237163953Srrs * The PAP implementation. * 4238163953Srrs * * 4239170781Srrs *--------------------------------------------------------------------------* 4240170781Srrs */ 4241170781Srrs/* 4242163953Srrs * For PAP, we need to keep a little state also if we are the peer, not the 4243163953Srrs * authenticator. This is since we don't get a request to authenticate, but 4244163953Srrs * have to repeatedly authenticate ourself until we got a response (or the 4245163953Srrs * retry counter is expired). 4246163953Srrs */ 4247163953Srrs 4248163953Srrs/* 4249163953Srrs * Handle incoming PAP packets. */ 4250163953Srrsstatic void 4251163953Srrssppp_pap_input(struct sppp *sp, struct mbuf *m) 4252163953Srrs{ 4253163953Srrs STDDCL; 4254163953Srrs struct lcp_header *h; 4255163953Srrs int len, x; 4256163953Srrs u_char *name, *passwd, mlen; 4257163953Srrs int name_len, passwd_len; 4258163953Srrs 4259163953Srrs len = m->m_pkthdr.len; 4260163953Srrs if (len < 5) { 4261163953Srrs if (debug) 4262163953Srrs log(LOG_DEBUG, 4263163953Srrs SPP_FMT "pap invalid packet length: %d bytes\n", 4264163953Srrs SPP_ARGS(ifp), len); 4265163953Srrs return; 4266163953Srrs } 4267163953Srrs h = mtod (m, struct lcp_header*); 4268163953Srrs if (len > ntohs (h->len)) 4269163953Srrs len = ntohs (h->len); 4270163953Srrs switch (h->type) { 4271163953Srrs /* PAP request is my authproto */ 4272163953Srrs case PAP_REQ: 4273163953Srrs name = 1 + (u_char*)(h+1); 4274163953Srrs name_len = name[-1]; 4275163953Srrs passwd = name + name_len + 1; 4276163953Srrs if (name_len > len - 6 || 4277163953Srrs (passwd_len = passwd[-1]) > len - 6 - name_len) { 4278163953Srrs if (debug) { 4279163953Srrs log(LOG_DEBUG, SPP_FMT "pap corrupted input " 4280163953Srrs "<%s id=0x%x len=%d", 4281163953Srrs SPP_ARGS(ifp), 4282163953Srrs sppp_auth_type_name(PPP_PAP, h->type), 4283163953Srrs h->ident, ntohs(h->len)); 4284163953Srrs sppp_print_bytes((u_char*)(h+1), len-4); 4285163953Srrs log(-1, ">\n"); 4286163953Srrs } 4287163953Srrs break; 4288163953Srrs } 4289163953Srrs if (debug) { 4290163953Srrs log(LOG_DEBUG, SPP_FMT "pap input(%s) " 4291163953Srrs "<%s id=0x%x len=%d name=", 4292163953Srrs SPP_ARGS(ifp), 4293163953Srrs sppp_state_name(sp->state[IDX_PAP]), 4294163953Srrs sppp_auth_type_name(PPP_PAP, h->type), 4295163953Srrs h->ident, ntohs(h->len)); 4296163953Srrs sppp_print_string((char*)name, name_len); 4297163953Srrs log(-1, " passwd="); 4298163953Srrs sppp_print_string((char*)passwd, passwd_len); 4299163953Srrs log(-1, ">\n"); 4300163953Srrs } 4301163953Srrs if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) || 4302163953Srrs passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) || 4303163953Srrs bcmp(name, sp->hisauth.name, name_len) != 0 || 4304163953Srrs bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) { 4305163953Srrs /* action scn, tld */ 4306163953Srrs mlen = sizeof(FAILMSG) - 1; 4307163953Srrs sppp_auth_send(&pap, sp, PAP_NAK, h->ident, 4308163953Srrs sizeof mlen, (const char *)&mlen, 4309163953Srrs sizeof(FAILMSG) - 1, (u_char *)FAILMSG, 4310163953Srrs 0); 4311163953Srrs pap.tld(sp); 4312163953Srrs break; 4313163953Srrs } 4314163953Srrs /* action sca, perhaps tlu */ 4315163953Srrs if (sp->state[IDX_PAP] == STATE_REQ_SENT || 4316163953Srrs sp->state[IDX_PAP] == STATE_OPENED) { 4317163953Srrs mlen = sizeof(SUCCMSG) - 1; 4318163953Srrs sppp_auth_send(&pap, sp, PAP_ACK, h->ident, 4319163953Srrs sizeof mlen, (const char *)&mlen, 4320163953Srrs sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG, 4321163953Srrs 0); 4322163953Srrs } 4323163953Srrs if (sp->state[IDX_PAP] == STATE_REQ_SENT) { 4324163953Srrs sppp_cp_change_state(&pap, sp, STATE_OPENED); 4325163953Srrs pap.tlu(sp); 4326163953Srrs } 4327163953Srrs break; 4328163953Srrs 4329163953Srrs /* ack and nak are his authproto */ 4330163953Srrs case PAP_ACK: 4331163953Srrs UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 4332163953Srrs if (debug) { 4333163953Srrs log(LOG_DEBUG, SPP_FMT "pap success", 4334163953Srrs SPP_ARGS(ifp)); 4335163953Srrs name_len = *((char *)h); 4336163953Srrs if (len > 5 && name_len) { 4337163953Srrs log(-1, ": "); 4338163953Srrs sppp_print_string((char*)(h+1), name_len); 4339163953Srrs } 4340163953Srrs log(-1, "\n"); 4341163953Srrs } 4342163953Srrs x = splimp(); 4343163953Srrs sp->pp_flags &= ~PP_NEEDAUTH; 4344163953Srrs if (sp->myauth.proto == PPP_PAP && 4345163953Srrs (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) && 4346163953Srrs (sp->lcp.protos & (1 << IDX_PAP)) == 0) { 4347163953Srrs /* 4348163953Srrs * We are authenticator for PAP but didn't 4349163953Srrs * complete yet. Leave it to tlu to proceed 4350163953Srrs * to network phase. 4351163953Srrs */ 4352163953Srrs splx(x); 4353163953Srrs break; 4354163953Srrs } 4355163953Srrs splx(x); 4356163953Srrs sppp_phase_network(sp); 4357163953Srrs break; 4358171440Srrs 4359171440Srrs case PAP_NAK: 4360163953Srrs UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 4361163953Srrs if (debug) { 4362163953Srrs log(LOG_INFO, SPP_FMT "pap failure", 4363163953Srrs SPP_ARGS(ifp)); 4364163953Srrs name_len = *((char *)h); 4365163953Srrs if (len > 5 && name_len) { 4366163953Srrs log(-1, ": "); 4367163953Srrs sppp_print_string((char*)(h+1), name_len); 4368163953Srrs } 4369163953Srrs log(-1, "\n"); 4370163953Srrs } else 4371163953Srrs log(LOG_INFO, SPP_FMT "pap failure\n", 4372170099Srrs SPP_ARGS(ifp)); 4373170099Srrs /* await LCP shutdown by authenticator */ 4374170099Srrs break; 4375170099Srrs 4376170099Srrs default: 4377237715Stuexen /* Unknown PAP packet type -- ignore. */ 4378170099Srrs if (debug) { 4379170099Srrs log(LOG_DEBUG, SPP_FMT "pap corrupted input " 4380237049Stuexen "<0x%x id=0x%x len=%d", 4381179157Srrs SPP_ARGS(ifp), 4382163953Srrs h->type, h->ident, ntohs(h->len)); 4383163953Srrs sppp_print_bytes((u_char*)(h+1), len-4); 4384163953Srrs log(-1, ">\n"); 4385163953Srrs } 4386170140Srrs break; 4387163953Srrs 4388168299Srrs } 4389218186Srrs} 4390163953Srrs 4391163953Srrsstatic void 4392163953Srrssppp_pap_init(struct sppp *sp) 4393163953Srrs{ 4394163953Srrs /* PAP doesn't have STATE_INITIAL at all. */ 4395163953Srrs sp->state[IDX_PAP] = STATE_CLOSED; 4396166675Srrs sp->fail_counter[IDX_PAP] = 0; 4397163953Srrs sp->pp_seq[IDX_PAP] = 0; 4398163953Srrs sp->pp_rseq[IDX_PAP] = 0; 4399163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4400163953Srrs callout_handle_init(&sp->ch[IDX_PAP]); 4401171990Srrs callout_handle_init(&sp->pap_my_to_ch); 4402163953Srrs#endif 4403237565Stuexen} 4404172090Srrs 4405172090Srrsstatic void 4406172090Srrssppp_pap_open(struct sppp *sp) 4407172090Srrs{ 4408169420Srrs if (sp->hisauth.proto == PPP_PAP && 4409169420Srrs (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) { 4410163953Srrs /* we are authenticator for PAP, start our timer */ 4411163953Srrs sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 4412163953Srrs sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 4413170056Srrs } 4414170056Srrs if (sp->myauth.proto == PPP_PAP) { 4415170091Srrs /* we are peer, send a request, and start a timer */ 4416170091Srrs pap.scr(sp); 4417170091Srrs TIMEOUT(sppp_pap_my_TO, (void *)sp, sp->lcp.timeout, 4418163953Srrs sp->pap_my_to_ch); 4419163953Srrs } 4420163953Srrs} 4421163953Srrs 4422163953Srrsstatic void 4423163953Srrssppp_pap_close(struct sppp *sp) 4424163953Srrs{ 4425165220Srrs if (sp->state[IDX_PAP] != STATE_CLOSED) 4426165220Srrs sppp_cp_change_state(&pap, sp, STATE_CLOSED); 4427165220Srrs} 4428163953Srrs 4429170056Srrs/* 4430170056Srrs * That's the timeout routine if we are authenticator. Since the 4431163953Srrs * authenticator is basically passive in PAP, we can't do much here. 4432163953Srrs */ 4433163953Srrsstatic void 4434169378Srrssppp_pap_TO(void *cookie) 4435163953Srrs{ 4436169378Srrs struct sppp *sp = (struct sppp *)cookie; 4437163953Srrs STDDCL; 4438163953Srrs int s; 4439163953Srrs 4440163953Srrs s = splimp(); 4441163953Srrs if (debug) 4442163953Srrs log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n", 4443163953Srrs SPP_ARGS(ifp), 4444163953Srrs sppp_state_name(sp->state[IDX_PAP]), 4445163953Srrs sp->rst_counter[IDX_PAP]); 4446179783Srrs 4447179783Srrs if (--sp->rst_counter[IDX_PAP] < 0) 4448163953Srrs /* TO- event */ 4449163953Srrs switch (sp->state[IDX_PAP]) { 4450163953Srrs case STATE_REQ_SENT: 4451163953Srrs pap.tld(sp); 4452163953Srrs sppp_cp_change_state(&pap, sp, STATE_CLOSED); 4453163953Srrs break; 4454163953Srrs } 4455163953Srrs else 4456163953Srrs /* TO+ event, not very much we could do */ 4457163953Srrs switch (sp->state[IDX_PAP]) { 4458170091Srrs case STATE_REQ_SENT: 4459170091Srrs /* sppp_cp_change_state() will restart the timer */ 4460170091Srrs sppp_cp_change_state(&pap, sp, STATE_REQ_SENT); 4461163953Srrs break; 4462163953Srrs } 4463163953Srrs 4464163953Srrs splx(s); 4465163953Srrs} 4466169420Srrs 4467169420Srrs/* 4468169420Srrs * That's the timeout handler if we are peer. Since the peer is active, 4469170091Srrs * we need to retransmit our PAP request since it is apparently lost. 4470170091Srrs * XXX We should impose a max counter. 4471170091Srrs */ 4472169420Srrsstatic void 4473169420Srrssppp_pap_my_TO(void *cookie) 4474163953Srrs{ 4475163953Srrs struct sppp *sp = (struct sppp *)cookie; 4476163953Srrs STDDCL; 4477163953Srrs 4478163953Srrs if (debug) 4479163953Srrs log(LOG_DEBUG, SPP_FMT "pap peer TO\n", 4480163953Srrs SPP_ARGS(ifp)); 4481163953Srrs 4482171990Srrs pap.scr(sp); 4483171990Srrs} 4484171990Srrs 4485163953Srrsstatic void 4486163953Srrssppp_pap_tlu(struct sppp *sp) 4487163953Srrs{ 4488171990Srrs STDDCL; 4489171990Srrs int x; 4490171990Srrs 4491171990Srrs sp->rst_counter[IDX_PAP] = sp->lcp.max_configure; 4492171990Srrs 4493228653Stuexen if (debug) 4494237715Stuexen log(LOG_DEBUG, SPP_FMT "%s tlu\n", 4495237715Stuexen SPP_ARGS(ifp), pap.name); 4496237715Stuexen 4497171990Srrs x = splimp(); 4498171990Srrs /* indicate to LCP that we need to be closed down */ 4499171990Srrs sp->lcp.protos |= (1 << IDX_PAP); 4500171990Srrs 4501171990Srrs if (sp->pp_flags & PP_NEEDAUTH) { 4502171990Srrs /* 4503163953Srrs * Remote is authenticator, but his auth proto didn't 4504163953Srrs * complete yet. Defer the transition to network 4505163953Srrs * phase. 4506163953Srrs */ 4507163953Srrs splx(x); 4508163953Srrs return; 4509171990Srrs } 4510171990Srrs splx(x); 4511163953Srrs sppp_phase_network(sp); 4512171990Srrs} 4513163953Srrs 4514163953Srrsstatic void 4515163953Srrssppp_pap_tld(struct sppp *sp) 4516163953Srrs{ 4517163953Srrs STDDCL; 4518163953Srrs 4519163953Srrs if (debug) 4520163953Srrs log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp)); 4521163953Srrs UNTIMEOUT(pap.TO, (void *)sp, sp->ch[IDX_PAP]); 4522169420Srrs UNTIMEOUT(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch); 4523163953Srrs sp->lcp.protos &= ~(1 << IDX_PAP); 4524163953Srrs 4525163953Srrs lcp.Close(sp); 4526170091Srrs} 4527170091Srrs 4528170091Srrsstatic void 4529163953Srrssppp_pap_scr(struct sppp *sp) 4530163953Srrs{ 4531163953Srrs u_char idlen, pwdlen; 4532163953Srrs 4533163953Srrs sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP]; 4534163953Srrs pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN); 4535163953Srrs idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN); 4536163953Srrs 4537163953Srrs sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP], 4538237715Stuexen sizeof idlen, (const char *)&idlen, 4539237049Stuexen (size_t)idlen, sp->myauth.name, 4540179157Srrs sizeof pwdlen, (const char *)&pwdlen, 4541163953Srrs (size_t)pwdlen, sp->myauth.secret, 4542169378Srrs 0); 4543163953Srrs} 4544169378Srrs 4545163953Srrs/* 4546163953Srrs * Random miscellaneous functions. 4547163953Srrs */ 4548163953Srrs 4549163953Srrs/* 4550163953Srrs * Send a PAP or CHAP proto packet. 4551163953Srrs * 4552163953Srrs * Varadic function, each of the elements for the ellipsis is of type 4553163953Srrs * ``size_t mlen, const u_char *msg''. Processing will stop iff 4554163953Srrs * mlen == 0. 4555163953Srrs * NOTE: never declare variadic functions with types subject to type 4556163953Srrs * promotion (i.e. u_char). This is asking for big trouble depending 4557163953Srrs * on the architecture you are on... 4558163953Srrs */ 4559169378Srrs 4560163953Srrsstatic void 4561169378Srrssppp_auth_send(const struct cp *cp, struct sppp *sp, 4562163953Srrs unsigned int type, unsigned int id, 4563163953Srrs ...) 4564163953Srrs{ 4565163953Srrs STDDCL; 4566163953Srrs struct ppp_header *h; 4567163953Srrs struct lcp_header *lh; 4568163953Srrs struct mbuf *m; 4569163953Srrs u_char *p; 4570163953Srrs int len; 4571163953Srrs unsigned int mlen; 4572163953Srrs const char *msg; 4573169378Srrs va_list ap; 4574163953Srrs 4575169378Srrs MGETHDR (m, M_DONTWAIT, MT_DATA); 4576237715Stuexen if (! m) 4577237715Stuexen return; 4578237049Stuexen m->m_pkthdr.rcvif = 0; 4579236450Stuexen 4580163953Srrs h = mtod (m, struct ppp_header*); 4581163953Srrs h->address = PPP_ALLSTATIONS; /* broadcast address */ 4582163953Srrs h->control = PPP_UI; /* Unnumbered Info */ 4583163953Srrs h->protocol = htons(cp->proto); 4584163953Srrs 4585163953Srrs lh = (struct lcp_header*)(h + 1); 4586169420Srrs lh->type = type; 4587169420Srrs lh->ident = id; 4588169420Srrs p = (u_char*) (lh+1); 4589163953Srrs 4590169378Srrs va_start(ap, id); 4591163953Srrs len = 0; 4592169378Srrs 4593163953Srrs while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { 4594163953Srrs msg = va_arg(ap, const char *); 4595163953Srrs len += mlen; 4596163953Srrs if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { 4597163953Srrs va_end(ap); 4598163953Srrs m_freem(m); 4599163953Srrs return; 4600163953Srrs } 4601163953Srrs 4602185694Srrs bcopy(msg, p, mlen); 4603163953Srrs p += mlen; 4604163953Srrs } 4605163953Srrs va_end(ap); 4606179783Srrs 4607171943Srrs m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len; 4608171943Srrs lh->len = htons (LCP_HEADER_LEN + len); 4609171943Srrs 4610171943Srrs if (debug) { 4611171943Srrs log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d", 4612171943Srrs SPP_ARGS(ifp), cp->name, 4613163953Srrs sppp_auth_type_name(cp->proto, lh->type), 4614163953Srrs lh->ident, ntohs(lh->len)); 4615163953Srrs sppp_print_bytes((u_char*) (lh+1), len); 4616163953Srrs log(-1, ">\n"); 4617163953Srrs } 4618163953Srrs if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3)) 4619163953Srrs ifp->if_oerrors++; 4620163953Srrs} 4621169420Srrs 4622169420Srrs/* 4623170744Srrs * Flush interface queue. 4624170140Srrs */ 4625170140Srrsstatic void 4626163953Srrssppp_qflush(struct ifqueue *ifq) 4627169378Srrs{ 4628163953Srrs struct mbuf *m, *n; 4629169378Srrs 4630163953Srrs n = ifq->ifq_head; 4631163953Srrs while ((m = n)) { 4632163953Srrs n = m->m_act; 4633163953Srrs m_freem (m); 4634163953Srrs } 4635163953Srrs ifq->ifq_head = 0; 4636163953Srrs ifq->ifq_tail = 0; 4637163953Srrs ifq->ifq_len = 0; 4638169208Srrs} 4639169208Srrs 4640163953Srrs/* 4641163953Srrs * Send keepalive packets, every 10 seconds. 4642163953Srrs */ 4643163953Srrsstatic void 4644163953Srrssppp_keepalive(void *dummy) 4645169378Srrs{ 4646163953Srrs struct sppp *sp; 4647169378Srrs int s; 4648163953Srrs 4649163953Srrs s = splimp(); 4650170642Srrs for (sp=spppq; sp; sp=sp->pp_next) { 4651170786Srrs struct ifnet *ifp = &sp->pp_if; 4652169208Srrs 4653169208Srrs /* Keepalive mode disabled or channel down? */ 4654169208Srrs if (! (sp->pp_flags & PP_KEEPALIVE) || 4655170642Srrs ! (ifp->if_flags & IFF_RUNNING)) 4656170642Srrs continue; 4657170642Srrs 4658170786Srrs /* No keepalive in PPP mode if LCP not opened yet. */ 4659170642Srrs if (sp->pp_mode != IFF_CISCO && 4660170786Srrs sp->pp_phase < PHASE_AUTHENTICATE) 4661170786Srrs continue; 4662169208Srrs 4663169208Srrs if (sp->pp_alivecnt == MAXALIVECNT) { 4664169208Srrs /* No keepalive packets got. Stop the interface. */ 4665169208Srrs printf (SPP_FMT "down\n", SPP_ARGS(ifp)); 4666169208Srrs if_down (ifp); 4667169208Srrs sppp_qflush (&sp->pp_cpq); 4668169378Srrs if (sp->pp_mode != IFF_CISCO) { 4669169208Srrs /* XXX */ 4670169378Srrs /* Shut down the PPP link. */ 4671169208Srrs lcp.Down(sp); 4672169208Srrs /* Initiate negotiation. XXX */ 4673169208Srrs lcp.Up(sp); 4674169208Srrs } 4675170642Srrs } 4676170642Srrs if (sp->pp_alivecnt <= MAXALIVECNT) 4677170642Srrs ++sp->pp_alivecnt; 4678170642Srrs if (sp->pp_mode == IFF_CISCO) 4679170642Srrs sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, 4680170642Srrs ++sp->pp_seq[IDX_LCP], sp->pp_rseq[IDX_LCP]); 4681170642Srrs else if (sp->pp_phase >= PHASE_AUTHENTICATE) { 4682169208Srrs long nmagic = htonl (sp->lcp.magic); 4683170642Srrs sp->lcp.echoid = ++sp->pp_seq[IDX_LCP]; 4684163953Srrs sppp_cp_send (sp, PPP_LCP, ECHO_REQ, 4685163953Srrs sp->lcp.echoid, 4, &nmagic); 4686163953Srrs } 4687163953Srrs } 4688163953Srrs splx(s); 4689163953Srrs TIMEOUT(sppp_keepalive, 0, hz * 10, keepalive_ch); 4690169420Srrs} 4691163953Srrs 4692163953Srrs/* 4693163953Srrs * Get both IP addresses. 4694163953Srrs */ 4695163953Srrsstatic void 4696169420Srrssppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) 4697169420Srrs{ 4698163953Srrs struct ifnet *ifp = &sp->pp_if; 4699163953Srrs struct ifaddr *ifa; 4700163953Srrs struct sockaddr_in *si, *sm; 4701163953Srrs u_long ssrc, ddst; 4702163953Srrs 4703163953Srrs sm = NULL; 4704163953Srrs ssrc = ddst = 0L; 4705179783Srrs /* 4706179783Srrs * Pick the first AF_INET address from the list, 4707179783Srrs * aliases don't make any sense on a p2p link anyway. 4708163953Srrs */ 4709163953Srrs si = 0; 4710163953Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4711163953Srrs TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 4712163953Srrs#elif defined(__NetBSD__) || defined (__OpenBSD__) 4713163953Srrs for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 4714163953Srrs ifa; 4715169420Srrs ifa = TAILQ_NEXT(ifa, ifa_list)) 4716229774Stuexen#else 4717229774Stuexen for (ifa = ifp->if_addrlist; 4718229775Stuexen ifa; 4719237715Stuexen ifa = ifa->ifa_next) 4720237715Stuexen#endif 4721237049Stuexen if (ifa->ifa_addr->sa_family == AF_INET) { 4722237049Stuexen si = (struct sockaddr_in *)ifa->ifa_addr; 4723163953Srrs sm = (struct sockaddr_in *)ifa->ifa_netmask; 4724163953Srrs if (si) 4725163953Srrs break; 4726229774Stuexen } 4727229774Stuexen if (ifa) { 4728229774Stuexen if (si && si->sin_addr.s_addr) { 4729229774Stuexen ssrc = si->sin_addr.s_addr; 4730229774Stuexen if (srcmask) 4731237715Stuexen *srcmask = ntohl(sm->sin_addr.s_addr); 4732237715Stuexen } 4733237049Stuexen 4734237049Stuexen si = (struct sockaddr_in *)ifa->ifa_dstaddr; 4735163953Srrs if (si && si->sin_addr.s_addr) 4736163953Srrs ddst = si->sin_addr.s_addr; 4737163953Srrs } 4738237715Stuexen 4739229774Stuexen if (dst) *dst = ntohl(ddst); 4740237049Stuexen if (src) *src = ntohl(ssrc); 4741237049Stuexen} 4742237049Stuexen 4743163953Srrs/* 4744229774Stuexen * Set my IP address. Must be called at splimp. 4745163953Srrs */ 4746169378Srrsstatic void 4747163953Srrssppp_set_ip_addr(struct sppp *sp, u_long src) 4748163953Srrs{ 4749170642Srrs STDDCL; 4750170642Srrs struct ifaddr *ifa; 4751163953Srrs struct sockaddr_in *si; 4752169420Srrs struct in_ifaddr *ia; 4753163953Srrs 4754163953Srrs /* 4755163953Srrs * Pick the first AF_INET address from the list, 4756163953Srrs * aliases don't make any sense on a p2p link anyway. 4757163953Srrs */ 4758208876Srrs si = 0; 4759208876Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4760163953Srrs TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) 4761169378Srrs#elif defined(__NetBSD__) || defined (__OpenBSD__) 4762163953Srrs for (ifa = TAILQ_FIRST(&ifp->if_addrlist); 4763163953Srrs ifa; 4764237565Stuexen ifa = TAILQ_NEXT(ifa, ifa_list)) 4765172090Srrs#else 4766172090Srrs for (ifa = ifp->if_addrlist; 4767172090Srrs ifa; 4768172090Srrs ifa = ifa->ifa_next) 4769172090Srrs#endif 4770172090Srrs { 4771172090Srrs if (ifa->ifa_addr->sa_family == AF_INET) 4772171943Srrs { 4773237565Stuexen si = (struct sockaddr_in *)ifa->ifa_addr; 4774172090Srrs if (si) 4775172090Srrs break; 4776163953Srrs } 4777163953Srrs } 4778163953Srrs 4779163953Srrs if (ifa && si) 4780229775Stuexen { 4781163953Srrs int error; 4782229775Stuexen#if __NetBSD_Version__ >= 103080000 4783163953Srrs struct sockaddr_in new_sin = *si; 4784169378Srrs 4785163953Srrs new_sin.sin_addr.s_addr = htonl(src); 4786169378Srrs error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); 4787163953Srrs if(debug && error) 4788163953Srrs { 4789169420Srrs log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " 4790237715Stuexen " failed, error=%d\n", SPP_ARGS(ifp), error); 4791237715Stuexen } 4792237049Stuexen#else 4793237049Stuexen /* delete old route */ 4794237049Stuexen error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); 4795237049Stuexen if(debug && error) 4796237049Stuexen { 4797169420Srrs log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", 4798169420Srrs SPP_ARGS(ifp), error); 4799169420Srrs } 4800229774Stuexen 4801229774Stuexen /* set new address */ 4802229774Stuexen si->sin_addr.s_addr = htonl(src); 4803229774Stuexen ia = ifatoia(ifa); 4804163953Srrs LIST_REMOVE(ia, ia_hash); 4805163953Srrs LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); 4806163953Srrs 4807163953Srrs /* add new route */ 4808229774Stuexen error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); 4809172090Srrs if (debug && error) 4810229774Stuexen { 4811169378Srrs log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", 4812163953Srrs SPP_ARGS(ifp), error); 4813169378Srrs } 4814163953Srrs#endif 4815163953Srrs } 4816163953Srrs} 4817163953Srrs 4818163953Srrs#ifdef INET6 4819163953Srrs/* 4820163953Srrs * Get both IPv6 addresses. 4821202526Stuexen */ 4822202526Stuexenstatic void 4823202526Stuexensppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst, 4824163953Srrs struct in6_addr *srcmask) 4825211944Stuexen{ 4826211944Stuexen struct ifnet *ifp = &sp->pp_if; 4827202526Stuexen struct ifaddr *ifa; 4828202526Stuexen struct sockaddr_in6 *si, *sm; 4829202526Stuexen struct in6_addr ssrc, ddst; 4830169208Srrs 4831202526Stuexen sm = NULL; 4832202526Stuexen bzero(&ssrc, sizeof(ssrc)); 4833202526Stuexen bzero(&ddst, sizeof(ddst)); 4834202526Stuexen /* 4835171990Srrs * Pick the first link-local AF_INET6 address from the list, 4836171990Srrs * aliases don't make any sense on a p2p link anyway. 4837171990Srrs */ 4838171990Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4839171990Srrs for (ifa = ifp->if_addrhead.tqh_first, si = 0; 4840171990Srrs ifa; 4841184883Srrs ifa = ifa->ifa_link.tqe_next) 4842171990Srrs#elif defined(__NetBSD__) || defined (__OpenBSD__) 4843163953Srrs for (ifa = ifp->if_addrlist.tqh_first, si = 0; 4844202526Stuexen ifa; 4845163953Srrs ifa = ifa->ifa_list.tqe_next) 4846163953Srrs#else 4847202526Stuexen for (ifa = ifp->if_addrlist, si = 0; 4848163953Srrs ifa; 4849202526Stuexen ifa = ifa->ifa_next) 4850202526Stuexen#endif 4851202526Stuexen if (ifa->ifa_addr->sa_family == AF_INET6) { 4852202526Stuexen si = (struct sockaddr_in6 *)ifa->ifa_addr; 4853202526Stuexen sm = (struct sockaddr_in6 *)ifa->ifa_netmask; 4854202526Stuexen if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) 4855202526Stuexen break; 4856202526Stuexen } 4857170606Srrs if (ifa) { 4858202526Stuexen if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { 4859163953Srrs bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc)); 4860163953Srrs if (srcmask) { 4861163953Srrs bcopy(&sm->sin6_addr, srcmask, 4862216825Stuexen sizeof(*srcmask)); 4863163953Srrs } 4864216188Stuexen } 4865163953Srrs 4866163953Srrs si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 4867163953Srrs if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) 4868163953Srrs bcopy(&si->sin6_addr, &ddst, sizeof(ddst)); 4869163953Srrs } 4870163953Srrs 4871163953Srrs if (dst) 4872163953Srrs bcopy(&ddst, dst, sizeof(*dst)); 4873163953Srrs if (src) 4874163953Srrs bcopy(&ssrc, src, sizeof(*src)); 4875163953Srrs} 4876218186Srrs 4877163953Srrs#ifdef IPV6CP_MYIFID_DYN 4878169420Srrs/* 4879228653Stuexen * Generate random ifid. 4880202526Stuexen */ 4881218186Srrsstatic void 4882163953Srrssppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr) 4883202526Stuexen{ 4884202526Stuexen /* TBD */ 4885202526Stuexen} 4886202526Stuexen 4887202526Stuexen/* 4888185694Srrs * Set my IPv6 address. Must be called at splimp. 4889185694Srrs */ 4890185694Srrsstatic void 4891185694Srrssppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src) 4892185694Srrs{ 4893163953Srrs STDDCL; 4894163953Srrs struct ifaddr *ifa; 4895185694Srrs struct sockaddr_in6 *sin6; 4896185694Srrs 4897185694Srrs /* 4898185694Srrs * Pick the first link-local AF_INET6 address from the list, 4899185694Srrs * aliases don't make any sense on a p2p link anyway. 4900185694Srrs */ 4901185694Srrs 4902185694Srrs sin6 = NULL; 4903185694Srrs#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4904202526Stuexen for (ifa = ifp->if_addrhead.tqh_first; 4905202526Stuexen ifa; 4906202526Stuexen ifa = ifa->ifa_link.tqe_next) 4907185694Srrs#elif defined(__NetBSD__) || defined (__OpenBSD__) 4908211944Stuexen for (ifa = ifp->if_addrlist.tqh_first; 4909211944Stuexen ifa; 4910212225Srrs ifa = ifa->ifa_list.tqe_next) 4911212225Srrs#else 4912212225Srrs for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 4913212225Srrs#endif 4914211944Stuexen { 4915211944Stuexen if (ifa->ifa_addr->sa_family == AF_INET6) 4916185694Srrs { 4917185694Srrs sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 4918202526Stuexen if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 4919202526Stuexen break; 4920202526Stuexen } 4921202526Stuexen } 4922185694Srrs 4923185694Srrs if (ifa && sin6) 4924185694Srrs { 4925185694Srrs int error; 4926185694Srrs struct sockaddr_in6 new_sin6 = *sin6; 4927185694Srrs 4928202526Stuexen bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr)); 4929185694Srrs error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1); 4930185694Srrs if (debug && error) 4931202526Stuexen { 4932185694Srrs log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit " 4933185694Srrs " failed, error=%d\n", SPP_ARGS(ifp), error); 4934185694Srrs } 4935202526Stuexen } 4936185694Srrs} 4937202526Stuexen#endif 4938202526Stuexen 4939202526Stuexen/* 4940202526Stuexen * Suggest a candidate address to be used by peer. 4941202526Stuexen */ 4942202526Stuexenstatic void 4943202526Stuexensppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) 4944202526Stuexen{ 4945185694Srrs struct in6_addr myaddr; 4946202526Stuexen struct timeval tv; 4947185694Srrs 4948185694Srrs sppp_get_ip6_addrs(sp, &myaddr, 0, 0); 4949202526Stuexen 4950216825Stuexen myaddr.s6_addr[8] &= ~0x02; /* u bit to "local" */ 4951185694Srrs microtime(&tv); 4952216188Stuexen if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) { 4953202526Stuexen myaddr.s6_addr[14] ^= 0xff; 4954185694Srrs myaddr.s6_addr[15] ^= 0xff; 4955185694Srrs } else { 4956185694Srrs myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff); 4957202526Stuexen myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff); 4958202526Stuexen } 4959202526Stuexen if (suggest) 4960202526Stuexen bcopy(&myaddr, suggest, sizeof(myaddr)); 4961202526Stuexen} 4962185694Srrs#endif /*INET6*/ 4963218129Srrs 4964218186Srrsstatic int 4965185694Srrssppp_params(struct sppp *sp, u_long cmd, void *data) 4966185694Srrs{ 4967228653Stuexen u_long subcmd; 4968202526Stuexen struct ifreq *ifr = (struct ifreq *)data; 4969218186Srrs struct spppreq *spr; 4970185694Srrs int rv = 0; 4971202526Stuexen 4972202526Stuexen if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) 4973202526Stuexen return (EAGAIN); 4974202526Stuexen /* 4975202526Stuexen * ifr->ifr_data is supposed to point to a struct spppreq. 4976185694Srrs * Check the cmd word first before attempting to fetch all the 4977185694Srrs * data. 4978185694Srrs */ 4979185694Srrs if ((subcmd = fuword(ifr->ifr_data)) == -1) { 4980185694Srrs rv = EFAULT; 4981185694Srrs goto quit; 4982185694Srrs } 4983185694Srrs 4984163953Srrs if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) { 4985169420Srrs rv = EFAULT; 4986169420Srrs goto quit; 4987169420Srrs } 4988169420Srrs 4989169420Srrs switch (subcmd) { 4990169420Srrs case (int)SPPPIOGDEFS: 4991169420Srrs if (cmd != SIOCGIFGENERIC) { 4992179783Srrs rv = EINVAL; 4993171943Srrs break; 4994171943Srrs } 4995171943Srrs /* 4996171943Srrs * We copy over the entire current state, but clean 4997171943Srrs * out some of the stuff we don't wanna pass up. 4998171943Srrs * Remember, SIOCGIFGENERIC is unprotected, and can be 4999169420Srrs * called by any user. No need to ever get PAP or 5000163953Srrs * CHAP secrets back to userland anyway. 5001163953Srrs */ 5002163953Srrs spr->defs.pp_phase = sp->pp_phase; 5003169420Srrs spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0; 5004169420Srrs spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0; 5005169208Srrs spr->defs.lcp = sp->lcp; 5006169352Srrs spr->defs.ipcp = sp->ipcp; 5007169378Srrs spr->defs.ipv6cp = sp->ipv6cp; 5008169295Srrs spr->defs.myauth = sp->myauth; 5009169378Srrs spr->defs.hisauth = sp->hisauth; 5010169208Srrs bzero(spr->defs.myauth.secret, AUTHKEYLEN); 5011169208Srrs bzero(spr->defs.myauth.challenge, AUTHKEYLEN); 5012163953Srrs bzero(spr->defs.hisauth.secret, AUTHKEYLEN); 5013179783Srrs bzero(spr->defs.hisauth.challenge, AUTHKEYLEN); 5014171943Srrs /* 5015171943Srrs * Fixup the LCP timeout value to milliseconds so 5016171943Srrs * spppcontrol doesn't need to bother about the value 5017171943Srrs * of "hz". We do the reverse calculation below when 5018171943Srrs * setting it. 5019171943Srrs */ 5020163953Srrs spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz; 5021163953Srrs rv = copyout(spr, (caddr_t)ifr->ifr_data, 5022169420Srrs sizeof(struct spppreq)); 5023169420Srrs break; 5024169420Srrs 5025163953Srrs case (int)SPPPIOSDEFS: 5026163953Srrs if (cmd != SIOCSIFGENERIC) { 5027170091Srrs rv = EINVAL; 5028170091Srrs break; 5029169420Srrs } 5030169420Srrs /* 5031169420Srrs * We have a very specific idea of which fields we 5032163953Srrs * allow being passed back from userland, so to not 5033163953Srrs * clobber our current state. For one, we only allow 5034163953Srrs * setting anything if LCP is in dead or establish 5035163953Srrs * phase. Once the authentication negotiations 5036170091Srrs * started, the authentication settings must not be 5037170091Srrs * changed again. (The administrator can force an 5038169420Srrs * ifconfig down in order to get LCP back into dead 5039169208Srrs * phase.) 5040169378Srrs * 5041169295Srrs * Also, we only allow for authentication parameters to be 5042169378Srrs * specified. 5043169208Srrs * 5044169420Srrs * XXX Should allow to set or clear pp_flags. 5045169420Srrs * 5046163953Srrs * Finally, if the respective authentication protocol to 5047163953Srrs * be used is set differently than 0, but the secret is 5048163953Srrs * passed as all zeros, we don't trash the existing secret. 5049163953Srrs * This allows an administrator to change the system name 5050163953Srrs * only without clobbering the secret (which he didn't get 5051163953Srrs * back in a previous SPPPIOGDEFS call). However, the 5052163953Srrs * secrets are cleared if the authentication protocol is 5053163953Srrs * reset to 0. */ 5054163953Srrs if (sp->pp_phase != PHASE_DEAD && 5055163953Srrs sp->pp_phase != PHASE_ESTABLISH) { 5056163953Srrs rv = EBUSY; 5057170091Srrs break; 5058169420Srrs } 5059169420Srrs 5060163953Srrs if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP && 5061163953Srrs spr->defs.myauth.proto != PPP_CHAP) || 5062163953Srrs (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP && 5063169420Srrs spr->defs.hisauth.proto != PPP_CHAP)) { 5064163953Srrs rv = EINVAL; 5065169420Srrs break; 5066169420Srrs } 5067163953Srrs 5068163953Srrs if (spr->defs.myauth.proto == 0) 5069163953Srrs /* resetting myauth */ 5070163953Srrs bzero(&sp->myauth, sizeof sp->myauth); 5071163953Srrs else { 5072169420Srrs /* setting/changing myauth */ 5073170091Srrs sp->myauth.proto = spr->defs.myauth.proto; 5074163953Srrs bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN); 5075163953Srrs if (spr->defs.myauth.secret[0] != '\0') 5076163953Srrs bcopy(spr->defs.myauth.secret, sp->myauth.secret, 5077169420Srrs AUTHKEYLEN); 5078163953Srrs } 5079208878Srrs if (spr->defs.hisauth.proto == 0) 5080208853Srrs /* resetting hisauth */ 5081208853Srrs bzero(&sp->hisauth, sizeof sp->hisauth); 5082208853Srrs else { 5083163953Srrs /* setting/changing hisauth */ 5084163953Srrs sp->hisauth.proto = spr->defs.hisauth.proto; 5085163953Srrs sp->hisauth.flags = spr->defs.hisauth.flags; 5086163953Srrs bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN); 5087163953Srrs if (spr->defs.hisauth.secret[0] != '\0') 5088163953Srrs bcopy(spr->defs.hisauth.secret, sp->hisauth.secret, 5089207924Srrs AUTHKEYLEN); 5090207924Srrs } 5091163953Srrs /* set LCP restart timer timeout */ 5092163953Srrs if (spr->defs.lcp.timeout != 0) 5093163953Srrs sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000; 5094172703Srrs /* set VJ enable and IPv6 disable flags */ 5095172703Srrs#ifdef INET 5096172703Srrs if (spr->defs.enable_vj) 5097179783Srrs sp->confflags |= CONF_ENABLE_VJ; 5098229774Stuexen else 5099163953Srrs sp->confflags &= ~CONF_ENABLE_VJ; 5100229774Stuexen#endif 5101237715Stuexen#ifdef INET6 5102237715Stuexen if (spr->defs.enable_ipv6) 5103237049Stuexen sp->confflags |= CONF_ENABLE_IPV6; 5104237049Stuexen else 5105163953Srrs sp->confflags &= ~CONF_ENABLE_IPV6; 5106172703Srrs#endif 5107172703Srrs break; 5108172703Srrs 5109163953Srrs default: 5110165220Srrs rv = EINVAL; 5111163953Srrs } 5112169420Srrs 5113165220Srrs quit: 5114169420Srrs free(spr, M_TEMP); 5115165220Srrs 5116169420Srrs return (rv); 5117165220Srrs} 5118169420Srrs 5119165220Srrsstatic void 5120208878Srrssppp_phase_network(struct sppp *sp) 5121208878Srrs{ 5122208878Srrs STDDCL; 5123208878Srrs int i; 5124208878Srrs u_long mask; 5125169420Srrs 5126169420Srrs sp->pp_phase = PHASE_NETWORK; 5127169420Srrs 5128169420Srrs if (debug) 5129237715Stuexen log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp), 5130237715Stuexen sppp_phase_name(sp->pp_phase)); 5131237715Stuexen 5132169420Srrs /* Notify NCPs now. */ 5133169420Srrs for (i = 0; i < IDX_COUNT; i++) 5134169420Srrs if ((cps[i])->flags & CP_NCP) 5135169420Srrs (cps[i])->Open(sp); 5136169420Srrs 5137169420Srrs /* Send Up events to all NCPs. */ 5138237049Stuexen for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1) 5139237049Stuexen if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP)) 5140179157Srrs (cps[i])->Up(sp); 5141179157Srrs 5142169420Srrs /* if no NCP is starting, all this was in vain, close down */ 5143169420Srrs sppp_lcp_check_and_close(sp); 5144169420Srrs} 5145169420Srrs 5146165220Srrs 5147169420Srrsstatic const char * 5148163953Srrssppp_cp_type_name(u_char type) 5149163953Srrs{ 5150163953Srrs static char buf[12]; 5151163953Srrs switch (type) { 5152169420Srrs case CONF_REQ: return "conf-req"; 5153169420Srrs case CONF_ACK: return "conf-ack"; 5154163953Srrs case CONF_NAK: return "conf-nak"; 5155163953Srrs case CONF_REJ: return "conf-rej"; 5156163953Srrs case TERM_REQ: return "term-req"; 5157163953Srrs case TERM_ACK: return "term-ack"; 5158163953Srrs case CODE_REJ: return "code-rej"; 5159163953Srrs case PROTO_REJ: return "proto-rej"; 5160163953Srrs case ECHO_REQ: return "echo-req"; 5161163953Srrs case ECHO_REPLY: return "echo-reply"; 5162163953Srrs case DISC_REQ: return "discard-req"; 5163163953Srrs } 5164163953Srrs snprintf (buf, sizeof(buf), "cp/0x%x", type); 5165163953Srrs return buf; 5166163953Srrs} 5167163953Srrs 5168163953Srrsstatic const char * 5169163953Srrssppp_auth_type_name(u_short proto, u_char type) 5170216822Stuexen{ 5171163953Srrs static char buf[12]; 5172163953Srrs switch (proto) { 5173163953Srrs case PPP_CHAP: 5174163953Srrs switch (type) { 5175170091Srrs case CHAP_CHALLENGE: return "challenge"; 5176169420Srrs case CHAP_RESPONSE: return "response"; 5177169378Srrs case CHAP_SUCCESS: return "success"; 5178169352Srrs case CHAP_FAILURE: return "failure"; 5179169378Srrs } 5180169352Srrs case PPP_PAP: 5181169352Srrs switch (type) { 5182163953Srrs case PAP_REQ: return "req"; 5183163953Srrs case PAP_ACK: return "ack"; 5184163953Srrs case PAP_NAK: return "nak"; 5185163953Srrs } 5186169420Srrs } 5187237565Stuexen snprintf (buf, sizeof(buf), "auth/0x%x", type); 5188172090Srrs return buf; 5189172090Srrs} 5190172090Srrs 5191172090Srrsstatic const char * 5192172090Srrssppp_lcp_opt_name(u_char opt) 5193172090Srrs{ 5194172090Srrs static char buf[12]; 5195171943Srrs switch (opt) { 5196237565Stuexen case LCP_OPT_MRU: return "mru"; 5197172090Srrs case LCP_OPT_ASYNC_MAP: return "async-map"; 5198172090Srrs case LCP_OPT_AUTH_PROTO: return "auth-proto"; 5199163953Srrs case LCP_OPT_QUAL_PROTO: return "qual-proto"; 5200163953Srrs case LCP_OPT_MAGIC: return "magic"; 5201163953Srrs case LCP_OPT_PROTO_COMP: return "proto-comp"; 5202163953Srrs case LCP_OPT_ADDR_COMP: return "addr-comp"; 5203163953Srrs } 5204169420Srrs snprintf (buf, sizeof(buf), "lcp/0x%x", opt); 5205179783Srrs return buf; 5206171943Srrs} 5207171943Srrs 5208171943Srrsstatic const char * 5209171943Srrssppp_ipcp_opt_name(u_char opt) 5210171943Srrs{ 5211171943Srrs static char buf[12]; 5212169378Srrs switch (opt) { 5213169378Srrs case IPCP_OPT_ADDRESSES: return "addresses"; 5214169378Srrs case IPCP_OPT_COMPRESSION: return "compression"; 5215163953Srrs case IPCP_OPT_ADDRESS: return "address"; 5216163953Srrs } 5217169420Srrs snprintf (buf, sizeof(buf), "ipcp/0x%x", opt); 5218163953Srrs return buf; 5219169420Srrs} 5220169208Srrs 5221169378Srrs#ifdef INET6 5222169295Srrsstatic const char * 5223169378Srrssppp_ipv6cp_opt_name(u_char opt) 5224169208Srrs{ 5225169208Srrs static char buf[12]; 5226169208Srrs switch (opt) { 5227169378Srrs case IPV6CP_OPT_IFID: return "ifid"; 5228179783Srrs case IPV6CP_OPT_COMPRESSION: return "compression"; 5229171943Srrs } 5230171943Srrs sprintf (buf, "0x%x", opt); 5231171943Srrs return buf; 5232171943Srrs} 5233171943Srrs#endif 5234171943Srrs 5235169378Srrsstatic const char * 5236169378Srrssppp_state_name(int state) 5237169378Srrs{ 5238218186Srrs switch (state) { 5239169378Srrs case STATE_INITIAL: return "initial"; 5240163953Srrs case STATE_STARTING: return "starting"; 5241163953Srrs case STATE_CLOSED: return "closed"; 5242169420Srrs case STATE_STOPPED: return "stopped"; 5243163953Srrs case STATE_CLOSING: return "closing"; 5244169420Srrs case STATE_STOPPING: return "stopping"; 5245169208Srrs case STATE_REQ_SENT: return "req-sent"; 5246169378Srrs case STATE_ACK_RCVD: return "ack-rcvd"; 5247169295Srrs case STATE_ACK_SENT: return "ack-sent"; 5248169378Srrs case STATE_OPENED: return "opened"; 5249169208Srrs } 5250169208Srrs return "illegal"; 5251169208Srrs} 5252169378Srrs 5253179783Srrsstatic const char * 5254171943Srrssppp_phase_name(enum ppp_phase phase) 5255171943Srrs{ 5256171943Srrs switch (phase) { 5257171943Srrs case PHASE_DEAD: return "dead"; 5258171943Srrs case PHASE_ESTABLISH: return "establish"; 5259171943Srrs case PHASE_TERMINATE: return "terminate"; 5260169378Srrs case PHASE_AUTHENTICATE: return "authenticate"; 5261218072Srrs case PHASE_NETWORK: return "network"; 5262169378Srrs } 5263163953Srrs return "illegal"; 5264163953Srrs} 5265170091Srrs 5266163953Srrsstatic const char * 5267163953Srrssppp_proto_name(u_short proto) 5268170140Srrs{ 5269163953Srrs static char buf[12]; 5270169378Srrs switch (proto) { 5271163953Srrs case PPP_LCP: return "lcp"; 5272169378Srrs case PPP_IPCP: return "ipcp"; 5273163953Srrs case PPP_PAP: return "pap"; 5274163953Srrs case PPP_CHAP: return "chap"; 5275169420Srrs case PPP_IPV6CP: return "ipv6cp"; 5276169378Srrs } 5277169378Srrs snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto); 5278169378Srrs return buf; 5279163953Srrs} 5280163953Srrs 5281163953Srrsstatic void 5282163953Srrssppp_print_bytes(const u_char *p, u_short len) 5283169420Srrs{ 5284163953Srrs if (len) 5285169378Srrs log(-1, " %*D", len, p, "-"); 5286179783Srrs} 5287171943Srrs 5288171943Srrsstatic void 5289171943Srrssppp_print_string(const char *p, u_short len) 5290171943Srrs{ 5291171943Srrs u_char c; 5292171943Srrs 5293169378Srrs while (len-- > 0) { 5294237715Stuexen c = *p++; 5295171990Srrs /* 5296171990Srrs * Print only ASCII chars directly. RFC 1994 recommends 5297169378Srrs * using only them, but we don't rely on it. */ 5298163953Srrs if (c < ' ' || c > '~') 5299163953Srrs log(-1, "\\x%x", c); 5300169420Srrs else 5301169208Srrs log(-1, "%c", c); 5302169208Srrs } 5303169378Srrs} 5304169295Srrs 5305169378Srrsstatic const char * 5306169208Srrssppp_dotted_quad(u_long addr) 5307169208Srrs{ 5308169208Srrs static char s[16]; 5309169420Srrs sprintf(s, "%d.%d.%d.%d", 5310169378Srrs (int)((addr >> 24) & 0xff), 5311179783Srrs (int)((addr >> 16) & 0xff), 5312171943Srrs (int)((addr >> 8) & 0xff), 5313171943Srrs (int)(addr & 0xff)); 5314171943Srrs return s; 5315171943Srrs} 5316171943Srrs 5317171943Srrsstatic int 5318169378Srrssppp_strnlen(u_char *p, int max) 5319169378Srrs{ 5320172190Srrs int len; 5321172190Srrs 5322172190Srrs for (len = 0; len < max && *p; ++p) 5323169378Srrs ++len; 5324163953Srrs return len; 5325163953Srrs} 5326169420Srrs 5327169208Srrs/* a dummy, used to drop uninteresting events */ 5328169208Srrsstatic void 5329169378Srrssppp_null(struct sppp *unused) 5330169295Srrs{ 5331169378Srrs /* do just nothing */ 5332169208Srrs} 5333169208Srrs