if_spppsubr.c revision 194951
14910Swollman/*
2139365Srik * Synchronous PPP/Cisco/Frame Relay link level subroutines.
34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes.
4139823Simp */
5139823Simp/*-
6139365Srik * Copyright (C) 1994-2000 Cronyx Engineering.
725944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru>
84910Swollman *
925944Sjoerg * Heavily revamped to conform to RFC 1661.
1088534Sjoerg * Copyright (C) 1997, 2001 Joerg Wunsch.
1125944Sjoerg *
124910Swollman * This software is distributed with NO WARRANTIES, not even the implied
134910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
144910Swollman *
154910Swollman * Authors grant any other persons or organisations permission to use
164910Swollman * or modify this software as long as this message is kept with the software,
174910Swollman * all derivative works or modified versions.
184910Swollman *
1930300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997
2016288Sgpalmer *
2150477Speter * $FreeBSD: head/sys/net/if_spppsubr.c 194951 2009-06-25 11:52:33Z rwatson $
224910Swollman */
234910Swollman
2440008Sjoerg#include <sys/param.h>
2540008Sjoerg
2632350Seivind#include "opt_inet.h"
2754263Sshin#include "opt_inet6.h"
2831742Seivind#include "opt_ipx.h"
2931742Seivind
304952Sbde#include <sys/systm.h>
314952Sbde#include <sys/kernel.h>
3270199Sjhay#include <sys/module.h>
3324204Sbde#include <sys/sockio.h>
344910Swollman#include <sys/socket.h>
3525706Sjoerg#include <sys/syslog.h>
3659604Sobrien#include <sys/random.h>
3729024Sbde#include <sys/malloc.h>
384910Swollman#include <sys/mbuf.h>
39181803Sbz#include <sys/vimage.h>
4040008Sjoerg
4130300Sjoerg#include <sys/md5.h>
424910Swollman
434910Swollman#include <net/if.h>
444910Swollman#include <net/netisr.h>
454910Swollman#include <net/if_types.h>
4642104Sphk#include <net/route.h>
4788534Sjoerg#include <netinet/in.h>
4888534Sjoerg#include <netinet/in_systm.h>
4988534Sjoerg#include <netinet/ip.h>
5088534Sjoerg#include <net/slcompress.h>
514910Swollman
5230300Sjoerg#include <machine/stdarg.h>
5330300Sjoerg
544910Swollman#include <netinet/in_var.h>
5588705Sjoerg
5688705Sjoerg#ifdef INET
574910Swollman#include <netinet/ip.h>
584910Swollman#include <netinet/tcp.h>
59185571Sbz#include <netinet/vinet.h>
604910Swollman#endif
614910Swollman
62148385Sume#ifdef INET6
63148385Sume#include <netinet6/scope6_var.h>
64148385Sume#endif
65148385Sume
66182121Simp#include <netinet/if_ether.h>
6788705Sjoerg
6811819Sjulian#ifdef IPX
6911819Sjulian#include <netipx/ipx.h>
7011819Sjulian#include <netipx/ipx_if.h>
7111819Sjulian#endif
7211819Sjulian
734910Swollman#include <net/if_sppp.h>
744910Swollman
75182121Simp#define IOCTL_CMD_T	u_long
764910Swollman#define MAXALIVECNT     3               /* max. alive packets */
774910Swollman
7825944Sjoerg/*
7925944Sjoerg * Interface flags that can be set in an ifconfig command.
8025944Sjoerg *
8125955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked
8225944Sjoerg * as being administrative openable, but won't be opened to begin
8325944Sjoerg * with.  Incoming calls will be answered, or subsequent calls with
8425944Sjoerg * -link1 will cause the administrative open of the LCP layer.
8525955Sjoerg *
8625955Sjoerg * Setting link1 will cause the link to auto-dial only as packets
8725955Sjoerg * arrive to be sent.
8830300Sjoerg *
8930300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state
9030300Sjoerg * transitions at level kern.debug.  Note: all logs consistently look
9130300Sjoerg * like
9230300Sjoerg *
9330300Sjoerg *   <if-name><unit>: <proto-name> <additional info...>
9430300Sjoerg *
9530300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name>
9630300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc.
9725944Sjoerg */
9825944Sjoerg
9925955Sjoerg#define IFF_PASSIVE	IFF_LINK0	/* wait passively for connection */
10025955Sjoerg#define IFF_AUTO	IFF_LINK1	/* auto-dial on output */
10145152Sphk#define IFF_CISCO	IFF_LINK2	/* auto-dial on output */
10225944Sjoerg
10330300Sjoerg#define PPP_ALLSTATIONS 0xff		/* All-Stations broadcast address */
10430300Sjoerg#define PPP_UI		0x03		/* Unnumbered Information */
10530300Sjoerg#define PPP_IP		0x0021		/* Internet Protocol */
10630300Sjoerg#define PPP_ISO		0x0023		/* ISO OSI Protocol */
10730300Sjoerg#define PPP_XNS		0x0025		/* Xerox NS Protocol */
10830300Sjoerg#define PPP_IPX		0x002b		/* Novell IPX Protocol */
10988534Sjoerg#define PPP_VJ_COMP	0x002d		/* VJ compressed TCP/IP */
11088534Sjoerg#define PPP_VJ_UCOMP	0x002f		/* VJ uncompressed TCP/IP */
11178064Sume#define PPP_IPV6	0x0057		/* Internet Protocol Version 6 */
11230300Sjoerg#define PPP_LCP		0xc021		/* Link Control Protocol */
11330300Sjoerg#define PPP_PAP		0xc023		/* Password Authentication Protocol */
11430300Sjoerg#define PPP_CHAP	0xc223		/* Challenge-Handshake Auth Protocol */
11530300Sjoerg#define PPP_IPCP	0x8021		/* Internet Protocol Control Protocol */
11678064Sume#define PPP_IPV6CP	0x8057		/* IPv6 Control Protocol */
1174910Swollman
11825944Sjoerg#define CONF_REQ	1		/* PPP configure request */
11925944Sjoerg#define CONF_ACK	2		/* PPP configure acknowledge */
12025944Sjoerg#define CONF_NAK	3		/* PPP configure negative ack */
12125944Sjoerg#define CONF_REJ	4		/* PPP configure reject */
12225944Sjoerg#define TERM_REQ	5		/* PPP terminate request */
12325944Sjoerg#define TERM_ACK	6		/* PPP terminate acknowledge */
12425944Sjoerg#define CODE_REJ	7		/* PPP code reject */
12525944Sjoerg#define PROTO_REJ	8		/* PPP protocol reject */
12625944Sjoerg#define ECHO_REQ	9		/* PPP echo request */
12725944Sjoerg#define ECHO_REPLY	10		/* PPP echo reply */
12825944Sjoerg#define DISC_REQ	11		/* PPP discard request */
1294910Swollman
13030300Sjoerg#define LCP_OPT_MRU		1	/* maximum receive unit */
13130300Sjoerg#define LCP_OPT_ASYNC_MAP	2	/* async control character map */
13230300Sjoerg#define LCP_OPT_AUTH_PROTO	3	/* authentication protocol */
13330300Sjoerg#define LCP_OPT_QUAL_PROTO	4	/* quality protocol */
13430300Sjoerg#define LCP_OPT_MAGIC		5	/* magic number */
13530300Sjoerg#define LCP_OPT_RESERVED	6	/* reserved */
13630300Sjoerg#define LCP_OPT_PROTO_COMP	7	/* protocol field compression */
13730300Sjoerg#define LCP_OPT_ADDR_COMP	8	/* address/control field compression */
1384910Swollman
13925944Sjoerg#define IPCP_OPT_ADDRESSES	1	/* both IP addresses; deprecated */
14025944Sjoerg#define IPCP_OPT_COMPRESSION	2	/* IP compression protocol (VJ) */
14125944Sjoerg#define IPCP_OPT_ADDRESS	3	/* local IP address */
1424910Swollman
14378064Sume#define IPV6CP_OPT_IFID	1	/* interface identifier */
14478064Sume#define IPV6CP_OPT_COMPRESSION	2	/* IPv6 compression protocol */
14578064Sume
14688534Sjoerg#define IPCP_COMP_VJ		0x2d	/* Code for VJ compression */
14788534Sjoerg
14830300Sjoerg#define PAP_REQ			1	/* PAP name/password request */
14930300Sjoerg#define PAP_ACK			2	/* PAP acknowledge */
15030300Sjoerg#define PAP_NAK			3	/* PAP fail */
1514910Swollman
15230300Sjoerg#define CHAP_CHALLENGE		1	/* CHAP challenge request */
15330300Sjoerg#define CHAP_RESPONSE		2	/* CHAP challenge response */
15430300Sjoerg#define CHAP_SUCCESS		3	/* CHAP response ok */
15530300Sjoerg#define CHAP_FAILURE		4	/* CHAP response failed */
15630300Sjoerg
15730300Sjoerg#define CHAP_MD5		5	/* hash algorithm - MD5 */
15830300Sjoerg
15930300Sjoerg#define CISCO_MULTICAST		0x8f	/* Cisco multicast address */
16030300Sjoerg#define CISCO_UNICAST		0x0f	/* Cisco unicast address */
16130300Sjoerg#define CISCO_KEEPALIVE		0x8035	/* Cisco keepalive protocol */
16230300Sjoerg#define CISCO_ADDR_REQ		0	/* Cisco address request */
16330300Sjoerg#define CISCO_ADDR_REPLY	1	/* Cisco address reply */
16430300Sjoerg#define CISCO_KEEPALIVE_REQ	2	/* Cisco keepalive request */
16530300Sjoerg
16625944Sjoerg/* states are named and numbered according to RFC 1661 */
16725944Sjoerg#define STATE_INITIAL	0
16825944Sjoerg#define STATE_STARTING	1
16925944Sjoerg#define STATE_CLOSED	2
17025944Sjoerg#define STATE_STOPPED	3
17125944Sjoerg#define STATE_CLOSING	4
17225944Sjoerg#define STATE_STOPPING	5
17325944Sjoerg#define STATE_REQ_SENT	6
17425944Sjoerg#define STATE_ACK_RCVD	7
17525944Sjoerg#define STATE_ACK_SENT	8
17625944Sjoerg#define STATE_OPENED	9
17725944Sjoerg
178147256SbrooksMALLOC_DEFINE(M_SPPP, "sppp", "synchronous PPP interface internals");
179147256Sbrooks
1804910Swollmanstruct ppp_header {
18111189Sjkh	u_char address;
18211189Sjkh	u_char control;
18311189Sjkh	u_short protocol;
184103842Salfred} __packed;
1854910Swollman#define PPP_HEADER_LEN          sizeof (struct ppp_header)
1864910Swollman
1874910Swollmanstruct lcp_header {
18811189Sjkh	u_char type;
18911189Sjkh	u_char ident;
19011189Sjkh	u_short len;
191103842Salfred} __packed;
1924910Swollman#define LCP_HEADER_LEN          sizeof (struct lcp_header)
1934910Swollman
1944910Swollmanstruct cisco_packet {
19511189Sjkh	u_long type;
19611189Sjkh	u_long par1;
19711189Sjkh	u_long par2;
19811189Sjkh	u_short rel;
19911189Sjkh	u_short time0;
20011189Sjkh	u_short time1;
201103842Salfred} __packed;
20288704Sjoerg#define CISCO_PACKET_LEN	sizeof (struct cisco_packet)
2034910Swollman
20425944Sjoerg/*
20525944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make
20625944Sjoerg * it easier comparing with the standard.  Please refer to this RFC in
20725944Sjoerg * case you can't make sense out of these abbreviation; it will also
20825944Sjoerg * explain the semantics related to the various events and actions.
20925944Sjoerg */
21025944Sjoergstruct cp {
21125944Sjoerg	u_short	proto;		/* PPP control protocol number */
21225944Sjoerg	u_char protoidx;	/* index into state table in struct sppp */
21325944Sjoerg	u_char flags;
21425944Sjoerg#define CP_LCP		0x01	/* this is the LCP */
21525944Sjoerg#define CP_AUTH		0x02	/* this is an authentication protocol */
21625944Sjoerg#define CP_NCP		0x04	/* this is a NCP */
21725944Sjoerg#define CP_QUAL		0x08	/* this is a quality reporting protocol */
21825944Sjoerg	const char *name;	/* name of this control protocol */
21925944Sjoerg	/* event handlers */
22025944Sjoerg	void	(*Up)(struct sppp *sp);
22125944Sjoerg	void	(*Down)(struct sppp *sp);
22225944Sjoerg	void	(*Open)(struct sppp *sp);
22325944Sjoerg	void	(*Close)(struct sppp *sp);
22425944Sjoerg	void	(*TO)(void *sp);
22525944Sjoerg	int	(*RCR)(struct sppp *sp, struct lcp_header *h, int len);
22625944Sjoerg	void	(*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len);
22725944Sjoerg	void	(*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len);
22825944Sjoerg	/* actions */
22925944Sjoerg	void	(*tlu)(struct sppp *sp);
23025944Sjoerg	void	(*tld)(struct sppp *sp);
23125944Sjoerg	void	(*tls)(struct sppp *sp);
23225944Sjoerg	void	(*tlf)(struct sppp *sp);
23325944Sjoerg	void	(*scr)(struct sppp *sp);
23425944Sjoerg};
23525944Sjoerg
23640008Sjoerg#define	SPP_FMT		"%s: "
23740008Sjoerg#define	SPP_ARGS(ifp)	(ifp)->if_xname
23840008Sjoerg
239188668Srwatson#define SPPP_LOCK(sp)	mtx_lock (&(sp)->mtx)
240188668Srwatson#define SPPP_UNLOCK(sp)	mtx_unlock (&(sp)->mtx)
241188668Srwatson#define SPPP_LOCK_ASSERT(sp)	mtx_assert (&(sp)->mtx, MA_OWNED)
242190818Sed#define SPPP_LOCK_OWNED(sp)	mtx_owned (&(sp)->mtx)
243138745Srik
24488705Sjoerg#ifdef INET
2454910Swollman/*
2464910Swollman * The following disgusting hack gets around the problem that IP TOS
2474910Swollman * can't be set yet.  We want to put "interactive" traffic on a high
2484910Swollman * priority queue.  To decide if traffic is interactive, we check that
2494910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
25030300Sjoerg *
25130300Sjoerg * XXX is this really still necessary?  - joerg -
2524910Swollman */
253126910Srwatsonstatic const u_short interactive_ports[8] = {
2544910Swollman	0,	513,	0,	0,
2554910Swollman	0,	21,	0,	23,
2564910Swollman};
2574910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
25888705Sjoerg#endif
2594910Swollman
26025944Sjoerg/* almost every function needs these */
26125944Sjoerg#define STDDCL							\
262147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);				\
26325944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG
26411189Sjkh
26530300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m,
266191148Skmacy		       struct sockaddr *dst, struct route *ro);
2674910Swollman
26825944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2);
26925944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m);
27025944Sjoerg
27125944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp,
27225944Sjoerg			  struct mbuf *m);
27325944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type,
27425944Sjoerg			 u_char ident, u_short len, void *data);
27542104Sphk/* static void sppp_cp_timeout(void *arg); */
27625944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp,
27725944Sjoerg				 int newstate);
27830300Sjoergstatic void sppp_auth_send(const struct cp *cp,
27942104Sphk			   struct sppp *sp, unsigned int type, unsigned int id,
28030300Sjoerg			   ...);
28125944Sjoerg
28225944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp);
28325944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp);
28425944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp);
28525944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp);
28625944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp);
28725944Sjoerg
28830300Sjoergstatic void sppp_null(struct sppp *sp);
28930300Sjoerg
290138745Srikstatic void sppp_pp_up(struct sppp *sp);
291138745Srikstatic void sppp_pp_down(struct sppp *sp);
292138745Srik
29325944Sjoergstatic void sppp_lcp_init(struct sppp *sp);
29425944Sjoergstatic void sppp_lcp_up(struct sppp *sp);
29525944Sjoergstatic void sppp_lcp_down(struct sppp *sp);
29625944Sjoergstatic void sppp_lcp_open(struct sppp *sp);
29725944Sjoergstatic void sppp_lcp_close(struct sppp *sp);
29825944Sjoergstatic void sppp_lcp_TO(void *sp);
29925944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len);
30025944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
30125944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
30225944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp);
30325944Sjoergstatic void sppp_lcp_tld(struct sppp *sp);
30425944Sjoergstatic void sppp_lcp_tls(struct sppp *sp);
30525944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp);
30625944Sjoergstatic void sppp_lcp_scr(struct sppp *sp);
30730300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp);
30830300Sjoergstatic int sppp_ncp_check(struct sppp *sp);
30925944Sjoerg
31025944Sjoergstatic void sppp_ipcp_init(struct sppp *sp);
31125944Sjoergstatic void sppp_ipcp_up(struct sppp *sp);
31225944Sjoergstatic void sppp_ipcp_down(struct sppp *sp);
31325944Sjoergstatic void sppp_ipcp_open(struct sppp *sp);
31425944Sjoergstatic void sppp_ipcp_close(struct sppp *sp);
31525944Sjoergstatic void sppp_ipcp_TO(void *sp);
31625944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len);
31725944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
31825944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
31925944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp);
32025944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp);
32125944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp);
32225944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp);
32325944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp);
32425944Sjoerg
32578064Sumestatic void sppp_ipv6cp_init(struct sppp *sp);
32678064Sumestatic void sppp_ipv6cp_up(struct sppp *sp);
32778064Sumestatic void sppp_ipv6cp_down(struct sppp *sp);
32878064Sumestatic void sppp_ipv6cp_open(struct sppp *sp);
32978064Sumestatic void sppp_ipv6cp_close(struct sppp *sp);
33078064Sumestatic void sppp_ipv6cp_TO(void *sp);
33178064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len);
33278064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
33378064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
33478064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp);
33578064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp);
33678064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp);
33778064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp);
33878064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp);
33978064Sume
34030300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m);
34130300Sjoergstatic void sppp_pap_init(struct sppp *sp);
34230300Sjoergstatic void sppp_pap_open(struct sppp *sp);
34330300Sjoergstatic void sppp_pap_close(struct sppp *sp);
34430300Sjoergstatic void sppp_pap_TO(void *sp);
34530300Sjoergstatic void sppp_pap_my_TO(void *sp);
34630300Sjoergstatic void sppp_pap_tlu(struct sppp *sp);
34730300Sjoergstatic void sppp_pap_tld(struct sppp *sp);
34830300Sjoergstatic void sppp_pap_scr(struct sppp *sp);
34930300Sjoerg
35030300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m);
35130300Sjoergstatic void sppp_chap_init(struct sppp *sp);
35230300Sjoergstatic void sppp_chap_open(struct sppp *sp);
35330300Sjoergstatic void sppp_chap_close(struct sppp *sp);
35430300Sjoergstatic void sppp_chap_TO(void *sp);
35530300Sjoergstatic void sppp_chap_tlu(struct sppp *sp);
35630300Sjoergstatic void sppp_chap_tld(struct sppp *sp);
35730300Sjoergstatic void sppp_chap_scr(struct sppp *sp);
35830300Sjoerg
35930300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type);
36025944Sjoergstatic const char *sppp_cp_type_name(u_char type);
361184682Sbz#ifdef INET
36230300Sjoergstatic const char *sppp_dotted_quad(u_long addr);
36330300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt);
364184682Sbz#endif
36578064Sume#ifdef INET6
36678064Sumestatic const char *sppp_ipv6cp_opt_name(u_char opt);
36778064Sume#endif
36825944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt);
36925944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase);
37025944Sjoergstatic const char *sppp_proto_name(u_short proto);
37130300Sjoergstatic const char *sppp_state_name(int state);
37238343Sbdestatic int sppp_params(struct sppp *sp, u_long cmd, void *data);
37330300Sjoergstatic int sppp_strnlen(u_char *p, int max);
37425944Sjoergstatic void sppp_keepalive(void *dummy);
37530300Sjoergstatic void sppp_phase_network(struct sppp *sp);
37630300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len);
37730300Sjoergstatic void sppp_print_string(const char *p, u_short len);
37825944Sjoergstatic void sppp_qflush(struct ifqueue *ifq);
379184682Sbz#ifdef INET
38025944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src);
381184682Sbz#endif
38278064Sume#ifdef INET6
38378064Sumestatic void sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src,
38478064Sume			       struct in6_addr *dst, struct in6_addr *srcmask);
38578064Sume#ifdef IPV6CP_MYIFID_DYN
38678064Sumestatic void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src);
38778064Sumestatic void sppp_gen_ip6_addr(struct sppp *sp, const struct in6_addr *src);
38878064Sume#endif
38978064Sumestatic void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *src);
39078064Sume#endif
39125944Sjoerg
392138745Srik/* if_start () wrapper */
393138745Srikstatic void sppp_ifstart (struct ifnet *ifp);
394138745Srik
39525944Sjoerg/* our control protocol descriptors */
39633181Seivindstatic const struct cp lcp = {
39725944Sjoerg	PPP_LCP, IDX_LCP, CP_LCP, "lcp",
39825944Sjoerg	sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close,
39925944Sjoerg	sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak,
40025944Sjoerg	sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf,
40125944Sjoerg	sppp_lcp_scr
40225944Sjoerg};
40325944Sjoerg
40433181Seivindstatic const struct cp ipcp = {
40588709Sjoerg	PPP_IPCP, IDX_IPCP,
40688709Sjoerg#ifdef INET	/* don't run IPCP if there's no IPv4 support */
40788709Sjoerg	CP_NCP,
40888709Sjoerg#else
40988709Sjoerg	0,
41088709Sjoerg#endif
41188709Sjoerg	"ipcp",
41225944Sjoerg	sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close,
41325944Sjoerg	sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak,
41425944Sjoerg	sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf,
41525944Sjoerg	sppp_ipcp_scr
41625944Sjoerg};
41725944Sjoerg
41878064Sumestatic const struct cp ipv6cp = {
41978064Sume	PPP_IPV6CP, IDX_IPV6CP,
42078064Sume#ifdef INET6	/*don't run IPv6CP if there's no IPv6 support*/
42178064Sume	CP_NCP,
42278064Sume#else
42378064Sume	0,
42478064Sume#endif
42578064Sume	"ipv6cp",
42678064Sume	sppp_ipv6cp_up, sppp_ipv6cp_down, sppp_ipv6cp_open, sppp_ipv6cp_close,
42778064Sume	sppp_ipv6cp_TO, sppp_ipv6cp_RCR, sppp_ipv6cp_RCN_rej, sppp_ipv6cp_RCN_nak,
42878064Sume	sppp_ipv6cp_tlu, sppp_ipv6cp_tld, sppp_ipv6cp_tls, sppp_ipv6cp_tlf,
42978064Sume	sppp_ipv6cp_scr
43078064Sume};
43178064Sume
43233181Seivindstatic const struct cp pap = {
43330300Sjoerg	PPP_PAP, IDX_PAP, CP_AUTH, "pap",
43430300Sjoerg	sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,
43530300Sjoerg	sppp_pap_TO, 0, 0, 0,
43630300Sjoerg	sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null,
43730300Sjoerg	sppp_pap_scr
43830300Sjoerg};
43930300Sjoerg
44033181Seivindstatic const struct cp chap = {
44130300Sjoerg	PPP_CHAP, IDX_CHAP, CP_AUTH, "chap",
44230300Sjoerg	sppp_null, sppp_null, sppp_chap_open, sppp_chap_close,
44330300Sjoerg	sppp_chap_TO, 0, 0, 0,
44430300Sjoerg	sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null,
44530300Sjoerg	sppp_chap_scr
44630300Sjoerg};
44730300Sjoerg
44833181Seivindstatic const struct cp *cps[IDX_COUNT] = {
44925944Sjoerg	&lcp,			/* IDX_LCP */
45025944Sjoerg	&ipcp,			/* IDX_IPCP */
45178064Sume	&ipv6cp,		/* IDX_IPV6CP */
45230300Sjoerg	&pap,			/* IDX_PAP */
45330300Sjoerg	&chap,			/* IDX_CHAP */
45425944Sjoerg};
45525944Sjoerg
456147256Sbrooksstatic void*
457147256Sbrookssppp_alloc(u_char type, struct ifnet *ifp)
458147256Sbrooks{
459147256Sbrooks	struct sppp	*sp;
460147256Sbrooks
461147256Sbrooks        sp = malloc(sizeof(struct sppp), M_SPPP, M_WAITOK | M_ZERO);
462147256Sbrooks	sp->pp_ifp = ifp;
463147256Sbrooks
464147256Sbrooks	return (sp);
465147256Sbrooks}
466147256Sbrooks
467147256Sbrooksstatic void
468147256Sbrookssppp_free(void *com, u_char type)
469147256Sbrooks{
470147256Sbrooks
471147256Sbrooks	free(com, M_SPPP);
472147256Sbrooks}
473147256Sbrooks
47470199Sjhaystatic int
47570199Sjhaysppp_modevent(module_t mod, int type, void *unused)
47670199Sjhay{
47770199Sjhay	switch (type) {
47870199Sjhay	case MOD_LOAD:
479147256Sbrooks		/*
480147256Sbrooks		 * XXX: should probably be IFT_SPPP, but it's fairly
481147256Sbrooks		 * harmless to allocate struct sppp's for non-sppp
482147256Sbrooks		 * interfaces.
483147256Sbrooks		 */
484147256Sbrooks
485147256Sbrooks		if_register_com_alloc(IFT_PPP, sppp_alloc, sppp_free);
48670199Sjhay		break;
48770199Sjhay	case MOD_UNLOAD:
488147256Sbrooks		/* if_deregister_com_alloc(IFT_PPP); */
48970199Sjhay		return EACCES;
49070199Sjhay	default:
491132199Sphk		return EOPNOTSUPP;
49270199Sjhay	}
49370199Sjhay	return 0;
49470199Sjhay}
49570199Sjhaystatic moduledata_t spppmod = {
49670199Sjhay	"sppp",
49770199Sjhay	sppp_modevent,
49870199Sjhay	0
49970199Sjhay};
50070199SjhayMODULE_VERSION(sppp, 1);
50170199SjhayDECLARE_MODULE(sppp, spppmod, SI_SUB_DRIVERS, SI_ORDER_ANY);
50225944Sjoerg
50370199Sjhay/*
50425944Sjoerg * Exported functions, comprising our interface to the lower layer.
5054910Swollman */
5064910Swollman
5074910Swollman/*
5084910Swollman * Process the received packet.
5094910Swollman */
51025706Sjoergvoid
51125706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m)
5124910Swollman{
5134910Swollman	struct ppp_header *h;
514111888Sjlemon	int isr = -1;
515147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
516184682Sbz	int debug, do_account = 0;
517184682Sbz#ifdef INET
518184682Sbz	int hlen, vjlen;
51988700Sjoerg	u_char *iphdr;
520184682Sbz#endif
5214910Swollman
522138745Srik	SPPP_LOCK(sp);
523138745Srik	debug = ifp->if_flags & IFF_DEBUG;
524138745Srik
5254910Swollman	if (ifp->if_flags & IFF_UP)
5264910Swollman		/* Count received bytes, add FCS and one flag */
5274910Swollman		ifp->if_ibytes += m->m_pkthdr.len + 3;
5284910Swollman
5294910Swollman	if (m->m_pkthdr.len <= PPP_HEADER_LEN) {
5304910Swollman		/* Too small packet, drop it. */
53125944Sjoerg		if (debug)
53225706Sjoerg			log(LOG_DEBUG,
53340008Sjoerg			    SPP_FMT "input packet is too small, %d bytes\n",
53440008Sjoerg			    SPP_ARGS(ifp), m->m_pkthdr.len);
53525944Sjoerg	  drop:
53688700Sjoerg		m_freem (m);
537138745Srik		SPPP_UNLOCK(sp);
53888700Sjoerg	  drop2:
53925944Sjoerg		++ifp->if_ierrors;
54025944Sjoerg		++ifp->if_iqdrops;
5414910Swollman		return;
5424910Swollman	}
5434910Swollman
544139365Srik	if (sp->pp_mode == PP_FR) {
545139365Srik		sppp_fr_input (sp, m);
546139365Srik		SPPP_UNLOCK(sp);
547139365Srik		return;
548139365Srik	}
549139365Srik
5504910Swollman	/* Get PPP header. */
5514910Swollman	h = mtod (m, struct ppp_header*);
5524910Swollman	m_adj (m, PPP_HEADER_LEN);
5534910Swollman
5544910Swollman	switch (h->address) {
5554910Swollman	case PPP_ALLSTATIONS:
5564910Swollman		if (h->control != PPP_UI)
5574910Swollman			goto invalid;
55845152Sphk		if (sp->pp_mode == IFF_CISCO) {
55925944Sjoerg			if (debug)
56025706Sjoerg				log(LOG_DEBUG,
56140008Sjoerg				    SPP_FMT "PPP packet in Cisco mode "
56225706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
56340008Sjoerg				    SPP_ARGS(ifp),
56425706Sjoerg				    h->address, h->control, ntohs(h->protocol));
56511189Sjkh			goto drop;
56611189Sjkh		}
5674910Swollman		switch (ntohs (h->protocol)) {
5684910Swollman		default:
56925944Sjoerg			if (debug)
57025706Sjoerg				log(LOG_DEBUG,
57144145Sphk				    SPP_FMT "rejecting protocol "
57225706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
57340008Sjoerg				    SPP_ARGS(ifp),
57425706Sjoerg				    h->address, h->control, ntohs(h->protocol));
57544145Sphk			if (sp->state[IDX_LCP] == STATE_OPENED)
57644145Sphk				sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
57778064Sume					++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2,
57844145Sphk					&h->protocol);
5794910Swollman			++ifp->if_noproto;
5804910Swollman			goto drop;
5814910Swollman		case PPP_LCP:
58230300Sjoerg			sppp_cp_input(&lcp, sp, m);
5834910Swollman			m_freem (m);
584138745Srik			SPPP_UNLOCK(sp);
5854910Swollman			return;
58630300Sjoerg		case PPP_PAP:
58730300Sjoerg			if (sp->pp_phase >= PHASE_AUTHENTICATE)
58830300Sjoerg				sppp_pap_input(sp, m);
58930300Sjoerg			m_freem (m);
590138745Srik			SPPP_UNLOCK(sp);
59130300Sjoerg			return;
59230300Sjoerg		case PPP_CHAP:
59330300Sjoerg			if (sp->pp_phase >= PHASE_AUTHENTICATE)
59430300Sjoerg				sppp_chap_input(sp, m);
59530300Sjoerg			m_freem (m);
596138745Srik			SPPP_UNLOCK(sp);
59730300Sjoerg			return;
5984910Swollman#ifdef INET
5994910Swollman		case PPP_IPCP:
60025944Sjoerg			if (sp->pp_phase == PHASE_NETWORK)
60130300Sjoerg				sppp_cp_input(&ipcp, sp, m);
6024910Swollman			m_freem (m);
603138745Srik			SPPP_UNLOCK(sp);
6044910Swollman			return;
6054910Swollman		case PPP_IP:
60625944Sjoerg			if (sp->state[IDX_IPCP] == STATE_OPENED) {
607111888Sjlemon				isr = NETISR_IP;
6084910Swollman			}
60988577Sjoerg			do_account++;
6104910Swollman			break;
61188534Sjoerg		case PPP_VJ_COMP:
61288534Sjoerg			if (sp->state[IDX_IPCP] == STATE_OPENED) {
61388700Sjoerg				if ((vjlen =
61488700Sjoerg				     sl_uncompress_tcp_core(mtod(m, u_char *),
61588700Sjoerg							    m->m_len, m->m_len,
61688700Sjoerg							    TYPE_COMPRESSED_TCP,
61788700Sjoerg							    sp->pp_comp,
61888700Sjoerg							    &iphdr, &hlen)) <= 0) {
61988700Sjoerg					if (debug)
62088700Sjoerg						log(LOG_INFO,
62188700Sjoerg			    SPP_FMT "VJ uncompress failed on compressed packet\n",
62288700Sjoerg						    SPP_ARGS(ifp));
62388534Sjoerg					goto drop;
62488700Sjoerg				}
62588700Sjoerg
62688700Sjoerg				/*
62788700Sjoerg				 * Trim the VJ header off the packet, and prepend
62888700Sjoerg				 * the uncompressed IP header (which will usually
62988700Sjoerg				 * end up in two chained mbufs since there's not
63088700Sjoerg				 * enough leading space in the existing mbuf).
63188700Sjoerg				 */
63288700Sjoerg				m_adj(m, vjlen);
633111119Simp				M_PREPEND(m, hlen, M_DONTWAIT);
634138745Srik				if (m == NULL) {
635138745Srik					SPPP_UNLOCK(sp);
63688700Sjoerg					goto drop2;
637138745Srik				}
63888700Sjoerg				bcopy(iphdr, mtod(m, u_char *), hlen);
639111888Sjlemon				isr = NETISR_IP;
64088534Sjoerg			}
64188599Sjoerg			do_account++;
64288534Sjoerg			break;
64388534Sjoerg		case PPP_VJ_UCOMP:
64488534Sjoerg			if (sp->state[IDX_IPCP] == STATE_OPENED) {
64588700Sjoerg				if (sl_uncompress_tcp_core(mtod(m, u_char *),
64688700Sjoerg							   m->m_len, m->m_len,
64788700Sjoerg							   TYPE_UNCOMPRESSED_TCP,
64888700Sjoerg							   sp->pp_comp,
64988700Sjoerg							   &iphdr, &hlen) != 0) {
65088700Sjoerg					if (debug)
65188700Sjoerg						log(LOG_INFO,
65288700Sjoerg			    SPP_FMT "VJ uncompress failed on uncompressed packet\n",
65388700Sjoerg						    SPP_ARGS(ifp));
65488534Sjoerg					goto drop;
65588700Sjoerg				}
656111888Sjlemon				isr = NETISR_IP;
65788534Sjoerg			}
65888599Sjoerg			do_account++;
65988534Sjoerg			break;
66078064Sume#endif
66188599Sjoerg#ifdef INET6
66288599Sjoerg		case PPP_IPV6CP:
66388599Sjoerg			if (sp->pp_phase == PHASE_NETWORK)
66488599Sjoerg			    sppp_cp_input(&ipv6cp, sp, m);
66588599Sjoerg			m_freem (m);
666138745Srik			SPPP_UNLOCK(sp);
66788599Sjoerg			return;
66888599Sjoerg
66988599Sjoerg		case PPP_IPV6:
670111888Sjlemon			if (sp->state[IDX_IPV6CP] == STATE_OPENED)
671111888Sjlemon				isr = NETISR_IPV6;
67288599Sjoerg			do_account++;
67388599Sjoerg			break;
67488599Sjoerg#endif
67512495Speter#ifdef IPX
67612495Speter		case PPP_IPX:
67712495Speter			/* IPX IPXCP not implemented yet */
678111888Sjlemon			if (sp->pp_phase == PHASE_NETWORK)
679111888Sjlemon				isr = NETISR_IPX;
68088577Sjoerg			do_account++;
68112495Speter			break;
68212495Speter#endif
6834910Swollman		}
6844910Swollman		break;
6854910Swollman	case CISCO_MULTICAST:
6864910Swollman	case CISCO_UNICAST:
6874910Swollman		/* Don't check the control field here (RFC 1547). */
68845152Sphk		if (sp->pp_mode != IFF_CISCO) {
68925944Sjoerg			if (debug)
69025706Sjoerg				log(LOG_DEBUG,
69140008Sjoerg				    SPP_FMT "Cisco packet in PPP mode "
69225706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
69340008Sjoerg				    SPP_ARGS(ifp),
69425706Sjoerg				    h->address, h->control, ntohs(h->protocol));
69511189Sjkh			goto drop;
69611189Sjkh		}
6974910Swollman		switch (ntohs (h->protocol)) {
6984910Swollman		default:
6994910Swollman			++ifp->if_noproto;
7004910Swollman			goto invalid;
7014910Swollman		case CISCO_KEEPALIVE:
702147256Sbrooks			sppp_cisco_input (sp, m);
7034910Swollman			m_freem (m);
704138745Srik			SPPP_UNLOCK(sp);
7054910Swollman			return;
7064910Swollman#ifdef INET
7074910Swollman		case ETHERTYPE_IP:
708111888Sjlemon			isr = NETISR_IP;
70988577Sjoerg			do_account++;
7104910Swollman			break;
7114910Swollman#endif
71254263Sshin#ifdef INET6
71354263Sshin		case ETHERTYPE_IPV6:
714111888Sjlemon			isr = NETISR_IPV6;
71588577Sjoerg			do_account++;
71654263Sshin			break;
71754263Sshin#endif
71812495Speter#ifdef IPX
71912495Speter		case ETHERTYPE_IPX:
720111888Sjlemon			isr = NETISR_IPX;
72188577Sjoerg			do_account++;
72212495Speter			break;
72312495Speter#endif
7244910Swollman		}
7254910Swollman		break;
72625944Sjoerg	default:        /* Invalid PPP packet. */
72725944Sjoerg	  invalid:
72825944Sjoerg		if (debug)
72925944Sjoerg			log(LOG_DEBUG,
73040008Sjoerg			    SPP_FMT "invalid input packet "
73125944Sjoerg			    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
73240008Sjoerg			    SPP_ARGS(ifp),
73325944Sjoerg			    h->address, h->control, ntohs(h->protocol));
73425944Sjoerg		goto drop;
7354910Swollman	}
7364910Swollman
737111888Sjlemon	if (! (ifp->if_flags & IFF_UP) || isr == -1)
7384910Swollman		goto drop;
7394910Swollman
740138745Srik	SPPP_UNLOCK(sp);
7414910Swollman	/* Check queue. */
742134391Sandre	if (netisr_queue(isr, m)) {	/* (0) on success. */
74325944Sjoerg		if (debug)
74440008Sjoerg			log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n",
74540008Sjoerg				SPP_ARGS(ifp));
746131241Srik		goto drop2;
7474910Swollman	}
748138745Srik
74988577Sjoerg	if (do_account)
75088577Sjoerg		/*
75188577Sjoerg		 * Do only account for network packets, not for control
75288577Sjoerg		 * packets.  This is used by some subsystems to detect
75388577Sjoerg		 * idle lines.
75488577Sjoerg		 */
755150349Sandre		sp->pp_last_recv = time_uptime;
7564910Swollman}
7574910Swollman
758138745Srikstatic void
759138745Sriksppp_ifstart_sched(void *dummy)
760138745Srik{
761138745Srik	struct sppp *sp = dummy;
762138745Srik
763147256Sbrooks	sp->if_start(SP2IFP(sp));
764138745Srik}
765138745Srik
766138745Srik/* if_start () wrapper function. We use it to schedule real if_start () for
767138745Srik * execution. We can't call it directly
768138745Srik */
769138745Srikstatic void
770138745Sriksppp_ifstart(struct ifnet *ifp)
771138745Srik{
772147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
773138745Srik
774138745Srik	if (SPPP_LOCK_OWNED(sp)) {
775138745Srik		if (callout_pending(&sp->ifstart_callout))
776138745Srik			return;
777138745Srik		callout_reset(&sp->ifstart_callout, 1, sppp_ifstart_sched,
778138745Srik		    (void *)sp);
779138745Srik	} else {
780138745Srik		sp->if_start(ifp);
781138745Srik	}
782138745Srik}
783138745Srik
7844910Swollman/*
7854910Swollman * Enqueue transmit packet.
7864910Swollman */
78712820Sphkstatic int
78825706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m,
789191148Skmacy	    struct sockaddr *dst, struct route *ro)
7904910Swollman{
791147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
7924910Swollman	struct ppp_header *h;
79378064Sume	struct ifqueue *ifq = NULL;
794130549Smlaier	int s, error, rv = 0;
795184682Sbz#ifdef INET
79688534Sjoerg	int ipproto = PPP_IP;
797184682Sbz#endif
79842066Sphk	int debug = ifp->if_flags & IFF_DEBUG;
7994910Swollman
80025944Sjoerg	s = splimp();
801138745Srik	SPPP_LOCK(sp);
80225944Sjoerg
803148887Srwatson	if (!(ifp->if_flags & IFF_UP) ||
804148887Srwatson	    (!(ifp->if_flags & IFF_AUTO) &&
805148887Srwatson	    !(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
80688723Sjoerg#ifdef INET6
80788723Sjoerg	  drop:
80888723Sjoerg#endif
8094910Swollman		m_freem (m);
810138745Srik		SPPP_UNLOCK(sp);
8114910Swollman		splx (s);
8124910Swollman		return (ENETDOWN);
8134910Swollman	}
8144910Swollman
815148887Srwatson	if ((ifp->if_flags & IFF_AUTO) &&
816148887Srwatson	    !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
81788723Sjoerg#ifdef INET6
81825944Sjoerg		/*
81988723Sjoerg		 * XXX
82088723Sjoerg		 *
82188723Sjoerg		 * Hack to prevent the initialization-time generated
82288723Sjoerg		 * IPv6 multicast packet to erroneously cause a
82388723Sjoerg		 * dialout event in case IPv6 has been
82488723Sjoerg		 * administratively disabled on that interface.
82588723Sjoerg		 */
82688723Sjoerg		if (dst->sa_family == AF_INET6 &&
82788723Sjoerg		    !(sp->confflags & CONF_ENABLE_IPV6))
82888723Sjoerg			goto drop;
82988723Sjoerg#endif
83088723Sjoerg		/*
83125944Sjoerg		 * Interface is not yet running, but auto-dial.  Need
83225944Sjoerg		 * to start LCP for it.
83325944Sjoerg		 */
834148887Srwatson		ifp->if_drv_flags |= IFF_DRV_RUNNING;
83525944Sjoerg		splx(s);
83625944Sjoerg		lcp.Open(sp);
83725944Sjoerg		s = splimp();
83825944Sjoerg	}
83925944Sjoerg
8404910Swollman#ifdef INET
84112436Speter	if (dst->sa_family == AF_INET) {
84240008Sjoerg		/* XXX Check mbuf length here? */
84312436Speter		struct ip *ip = mtod (m, struct ip*);
84412436Speter		struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);
8454910Swollman
84642104Sphk		/*
84742104Sphk		 * When using dynamic local IP address assignment by using
84842104Sphk		 * 0.0.0.0 as a local address, the first TCP session will
84942104Sphk		 * not connect because the local TCP checksum is computed
85042104Sphk		 * using 0.0.0.0 which will later become our real IP address
85142104Sphk		 * so the TCP checksum computed at the remote end will
85242104Sphk		 * become invalid. So we
85342104Sphk		 * - don't let packets with src ip addr 0 thru
85442104Sphk		 * - we flag TCP packets with src ip 0 as an error
85570199Sjhay		 */
85642104Sphk
85742104Sphk		if(ip->ip_src.s_addr == INADDR_ANY)	/* -hm */
85842104Sphk		{
85942104Sphk			m_freem(m);
860138745Srik			SPPP_UNLOCK(sp);
86142104Sphk			splx(s);
86242104Sphk			if(ip->ip_p == IPPROTO_TCP)
86342104Sphk				return(EADDRNOTAVAIL);
86442104Sphk			else
86542104Sphk				return(0);
86642104Sphk		}
86770199Sjhay
86842104Sphk		/*
86942104Sphk		 * Put low delay, telnet, rlogin and ftp control packets
870130549Smlaier		 * in front of the queue or let ALTQ take care.
87142104Sphk		 */
872130549Smlaier		if (ALTQ_IS_ENABLED(&ifp->if_snd))
87341686Sphk			;
874130549Smlaier		else if (_IF_QFULL(&sp->pp_fastq))
875130549Smlaier			;
87641686Sphk		else if (ip->ip_tos & IPTOS_LOWDELAY)
87712436Speter			ifq = &sp->pp_fastq;
87841686Sphk		else if (m->m_len < sizeof *ip + sizeof *tcp)
87941686Sphk			;
88041686Sphk		else if (ip->ip_p != IPPROTO_TCP)
88141686Sphk			;
88241686Sphk		else if (INTERACTIVE (ntohs (tcp->th_sport)))
88341686Sphk			ifq = &sp->pp_fastq;
88441686Sphk		else if (INTERACTIVE (ntohs (tcp->th_dport)))
88541686Sphk			ifq = &sp->pp_fastq;
88688534Sjoerg
88788534Sjoerg		/*
88888534Sjoerg		 * Do IP Header compression
88988534Sjoerg		 */
890139365Srik		if (sp->pp_mode != IFF_CISCO && sp->pp_mode != PP_FR &&
891138745Srik		    (sp->ipcp.flags & IPCP_VJ) && ip->ip_p == IPPROTO_TCP)
89288599Sjoerg			switch (sl_compress_tcp(m, ip, sp->pp_comp,
89388534Sjoerg						sp->ipcp.compress_cid)) {
89488534Sjoerg			case TYPE_COMPRESSED_TCP:
89588534Sjoerg				ipproto = PPP_VJ_COMP;
89688534Sjoerg				break;
89788534Sjoerg			case TYPE_UNCOMPRESSED_TCP:
89888534Sjoerg				ipproto = PPP_VJ_UCOMP;
89988534Sjoerg				break;
90088534Sjoerg			case TYPE_IP:
90188534Sjoerg				ipproto = PPP_IP;
90288534Sjoerg				break;
90388534Sjoerg			default:
90488534Sjoerg				m_freem(m);
905138745Srik				SPPP_UNLOCK(sp);
90688534Sjoerg				splx(s);
90788534Sjoerg				return (EINVAL);
90888534Sjoerg			}
9094910Swollman	}
9104910Swollman#endif
9114910Swollman
91278064Sume#ifdef INET6
91378064Sume	if (dst->sa_family == AF_INET6) {
91478064Sume		/* XXX do something tricky here? */
91578064Sume	}
91678064Sume#endif
91778064Sume
918139365Srik	if (sp->pp_mode == PP_FR) {
919139365Srik		/* Add frame relay header. */
920139365Srik		m = sppp_fr_header (sp, m, dst->sa_family);
921139365Srik		if (! m)
922139365Srik			goto nobufs;
923139365Srik		goto out;
924139365Srik	}
925139365Srik
9264910Swollman	/*
9274910Swollman	 * Prepend general data packet PPP header. For now, IP only.
9284910Swollman	 */
929111119Simp	M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT);
9304910Swollman	if (! m) {
931139365Sriknobufs:		if (debug)
93240008Sjoerg			log(LOG_DEBUG, SPP_FMT "no memory for transmit header\n",
93340008Sjoerg				SPP_ARGS(ifp));
93425944Sjoerg		++ifp->if_oerrors;
935138745Srik		SPPP_UNLOCK(sp);
9364910Swollman		splx (s);
9374910Swollman		return (ENOBUFS);
9384910Swollman	}
93940008Sjoerg	/*
94040008Sjoerg	 * May want to check size of packet
94140008Sjoerg	 * (albeit due to the implementation it's always enough)
94240008Sjoerg	 */
9434910Swollman	h = mtod (m, struct ppp_header*);
94445152Sphk	if (sp->pp_mode == IFF_CISCO) {
94528088Skjc		h->address = CISCO_UNICAST;        /* unicast address */
9464910Swollman		h->control = 0;
9474910Swollman	} else {
9484910Swollman		h->address = PPP_ALLSTATIONS;        /* broadcast address */
9494910Swollman		h->control = PPP_UI;                 /* Unnumbered Info */
9504910Swollman	}
9514910Swollman
9524910Swollman	switch (dst->sa_family) {
9534910Swollman#ifdef INET
9544910Swollman	case AF_INET:   /* Internet Protocol */
95545152Sphk		if (sp->pp_mode == IFF_CISCO)
95611189Sjkh			h->protocol = htons (ETHERTYPE_IP);
95711189Sjkh		else {
95825955Sjoerg			/*
95925955Sjoerg			 * Don't choke with an ENETDOWN early.  It's
96025955Sjoerg			 * possible that we just started dialing out,
96125955Sjoerg			 * so don't drop the packet immediately.  If
96225955Sjoerg			 * we notice that we run out of buffer space
96325955Sjoerg			 * below, we will however remember that we are
96425955Sjoerg			 * not ready to carry IP packets, and return
96525955Sjoerg			 * ENETDOWN, as opposed to ENOBUFS.
96625955Sjoerg			 */
96788534Sjoerg			h->protocol = htons(ipproto);
96825955Sjoerg			if (sp->state[IDX_IPCP] != STATE_OPENED)
96925955Sjoerg				rv = ENETDOWN;
97011189Sjkh		}
9714910Swollman		break;
9724910Swollman#endif
97354263Sshin#ifdef INET6
97454263Sshin	case AF_INET6:   /* Internet Protocol */
97554263Sshin		if (sp->pp_mode == IFF_CISCO)
97654263Sshin			h->protocol = htons (ETHERTYPE_IPV6);
97754263Sshin		else {
97878064Sume			/*
97978064Sume			 * Don't choke with an ENETDOWN early.  It's
98078064Sume			 * possible that we just started dialing out,
98178064Sume			 * so don't drop the packet immediately.  If
98278064Sume			 * we notice that we run out of buffer space
98378064Sume			 * below, we will however remember that we are
98478064Sume			 * not ready to carry IP packets, and return
98578064Sume			 * ENETDOWN, as opposed to ENOBUFS.
98678064Sume			 */
98778064Sume			h->protocol = htons(PPP_IPV6);
98878064Sume			if (sp->state[IDX_IPV6CP] != STATE_OPENED)
98978064Sume				rv = ENETDOWN;
99054263Sshin		}
99154263Sshin		break;
99254263Sshin#endif
99311819Sjulian#ifdef IPX
99412495Speter	case AF_IPX:     /* Novell IPX Protocol */
99545152Sphk		h->protocol = htons (sp->pp_mode == IFF_CISCO ?
99612495Speter			ETHERTYPE_IPX : PPP_IPX);
99711819Sjulian		break;
99811819Sjulian#endif
9994910Swollman	default:
10004910Swollman		m_freem (m);
100125944Sjoerg		++ifp->if_oerrors;
1002138745Srik		SPPP_UNLOCK(sp);
10034910Swollman		splx (s);
10044910Swollman		return (EAFNOSUPPORT);
10054910Swollman	}
10064910Swollman
10074910Swollman	/*
10084910Swollman	 * Queue message on interface, and start output if interface
100988577Sjoerg	 * not yet active.
10104910Swollman	 */
1011139365Srikout:
1012130549Smlaier	if (ifq != NULL)
1013130549Smlaier		error = !(IF_HANDOFF_ADJ(ifq, m, ifp, 3));
1014130549Smlaier	else
1015130549Smlaier		IFQ_HANDOFF_ADJ(ifp, m, 3, error);
1016130549Smlaier	if (error) {
101725944Sjoerg		++ifp->if_oerrors;
1018138745Srik		SPPP_UNLOCK(sp);
1019111038Smaxim		splx (s);
102025955Sjoerg		return (rv? rv: ENOBUFS);
10214910Swollman	}
1022138745Srik	SPPP_UNLOCK(sp);
1023111038Smaxim	splx (s);
102488577Sjoerg	/*
102588577Sjoerg	 * Unlike in sppp_input(), we can always bump the timestamp
102688577Sjoerg	 * here since sppp_output() is only called on behalf of
102788577Sjoerg	 * network-layer traffic; control-layer traffic is handled
102888577Sjoerg	 * by sppp_cp_send().
102988577Sjoerg	 */
1030150349Sandre	sp->pp_last_sent = time_uptime;
10314910Swollman	return (0);
10324910Swollman}
10334910Swollman
103425706Sjoergvoid
103525706Sjoergsppp_attach(struct ifnet *ifp)
10364910Swollman{
1037147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
10384910Swollman
1039138745Srik	/* Initialize mtx lock */
1040138745Srik	mtx_init(&sp->mtx, "sppp", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE);
1041138745Srik
10424910Swollman	/* Initialize keepalive handler. */
1043188668Srwatson 	callout_init(&sp->keepalive_callout, CALLOUT_MPSAFE);
1044138745Srik	callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive,
1045138745Srik 		    (void *)sp);
10464910Swollman
1047147256Sbrooks	ifp->if_mtu = PP_MTU;
1048147256Sbrooks	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
1049147256Sbrooks	ifp->if_output = sppp_output;
105042104Sphk#if 0
105142064Sphk	sp->pp_flags = PP_KEEPALIVE;
105242104Sphk#endif
1053147256Sbrooks 	ifp->if_snd.ifq_maxlen = 32;
105470199Sjhay 	sp->pp_fastq.ifq_maxlen = 32;
105570199Sjhay 	sp->pp_cpq.ifq_maxlen = 20;
10564910Swollman	sp->pp_loopcnt = 0;
10574910Swollman	sp->pp_alivecnt = 0;
105878064Sume	bzero(&sp->pp_seq[0], sizeof(sp->pp_seq));
105978064Sume	bzero(&sp->pp_rseq[0], sizeof(sp->pp_rseq));
106025944Sjoerg	sp->pp_phase = PHASE_DEAD;
1061138745Srik	sp->pp_up = sppp_pp_up;
1062138745Srik	sp->pp_down = sppp_pp_down;
106388716Sjoerg	if(!mtx_initialized(&sp->pp_cpq.ifq_mtx))
106493818Sjhb		mtx_init(&sp->pp_cpq.ifq_mtx, "sppp_cpq", NULL, MTX_DEF);
106588716Sjoerg	if(!mtx_initialized(&sp->pp_fastq.ifq_mtx))
106693818Sjhb		mtx_init(&sp->pp_fastq.ifq_mtx, "sppp_fastq", NULL, MTX_DEF);
1067150349Sandre	sp->pp_last_recv = sp->pp_last_sent = time_uptime;
106888723Sjoerg	sp->confflags = 0;
106988723Sjoerg#ifdef INET
107088723Sjoerg	sp->confflags |= CONF_ENABLE_VJ;
107188723Sjoerg#endif
107288723Sjoerg#ifdef INET6
107388723Sjoerg	sp->confflags |= CONF_ENABLE_IPV6;
107488723Sjoerg#endif
1075188668Srwatson 	callout_init(&sp->ifstart_callout, CALLOUT_MPSAFE);
1076138745Srik	sp->if_start = ifp->if_start;
1077138745Srik	ifp->if_start = sppp_ifstart;
1078118072Sgj	sp->pp_comp = malloc(sizeof(struct slcompress), M_TEMP, M_WAITOK);
107988599Sjoerg	sl_compress_init(sp->pp_comp, -1);
108025944Sjoerg	sppp_lcp_init(sp);
108125944Sjoerg	sppp_ipcp_init(sp);
108278064Sume	sppp_ipv6cp_init(sp);
108330300Sjoerg	sppp_pap_init(sp);
108430300Sjoerg	sppp_chap_init(sp);
10854910Swollman}
10864910Swollman
108730300Sjoergvoid
108825706Sjoergsppp_detach(struct ifnet *ifp)
10894910Swollman{
1090147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
109125944Sjoerg	int i;
10924910Swollman
1093138745Srik	KASSERT(mtx_initialized(&sp->mtx), ("sppp mutex is not initialized"));
10944910Swollman
10954910Swollman	/* Stop keepalive handler. */
1096138745Srik 	if (!callout_drain(&sp->keepalive_callout))
1097138745Srik		callout_stop(&sp->keepalive_callout);
109825944Sjoerg
1099138745Srik	for (i = 0; i < IDX_COUNT; i++) {
1100138745Srik		if (!callout_drain(&sp->ch[i]))
1101138745Srik			callout_stop(&sp->ch[i]);
1102138745Srik	}
1103138745Srik	if (!callout_drain(&sp->pap_my_to_ch))
1104138745Srik		callout_stop(&sp->pap_my_to_ch);
110569152Sjlemon	mtx_destroy(&sp->pp_cpq.ifq_mtx);
110669152Sjlemon	mtx_destroy(&sp->pp_fastq.ifq_mtx);
1107138745Srik	mtx_destroy(&sp->mtx);
11084910Swollman}
11094910Swollman
11104910Swollman/*
11114910Swollman * Flush the interface output queue.
11124910Swollman */
1113138745Srikstatic void
1114138745Sriksppp_flush_unlocked(struct ifnet *ifp)
11154910Swollman{
1116147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
11174910Swollman
1118147256Sbrooks	sppp_qflush ((struct ifqueue *)&SP2IFP(sp)->if_snd);
111925944Sjoerg	sppp_qflush (&sp->pp_fastq);
112026018Sjoerg	sppp_qflush (&sp->pp_cpq);
11214910Swollman}
11224910Swollman
1123138745Srikvoid
1124138745Sriksppp_flush(struct ifnet *ifp)
1125138745Srik{
1126147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
1127138745Srik
1128138745Srik	SPPP_LOCK(sp);
1129138745Srik	sppp_flush_unlocked (ifp);
1130138745Srik	SPPP_UNLOCK(sp);
1131138745Srik}
1132138745Srik
11334910Swollman/*
113411189Sjkh * Check if the output queue is empty.
113511189Sjkh */
113612820Sphkint
113725706Sjoergsppp_isempty(struct ifnet *ifp)
113811189Sjkh{
1139147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
114025944Sjoerg	int empty, s;
114111189Sjkh
114225944Sjoerg	s = splimp();
1143138745Srik	SPPP_LOCK(sp);
114426018Sjoerg	empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
1145147256Sbrooks		!SP2IFP(sp)->if_snd.ifq_head;
1146138745Srik	SPPP_UNLOCK(sp);
114725944Sjoerg	splx(s);
114811189Sjkh	return (empty);
114911189Sjkh}
115011189Sjkh
115111189Sjkh/*
11524910Swollman * Get next packet to send.
11534910Swollman */
115425706Sjoergstruct mbuf *
115525706Sjoergsppp_dequeue(struct ifnet *ifp)
11564910Swollman{
1157147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
11584910Swollman	struct mbuf *m;
115925944Sjoerg	int s;
11604910Swollman
116125944Sjoerg	s = splimp();
1162138745Srik	SPPP_LOCK(sp);
116326018Sjoerg	/*
116430300Sjoerg	 * Process only the control protocol queue until we have at
116530300Sjoerg	 * least one NCP open.
116626018Sjoerg	 *
116726018Sjoerg	 * Do always serve all three queues in Cisco mode.
116826018Sjoerg	 */
116926018Sjoerg	IF_DEQUEUE(&sp->pp_cpq, m);
117026018Sjoerg	if (m == NULL &&
1171139365Srik	    (sppp_ncp_check(sp) || sp->pp_mode == IFF_CISCO ||
1172139365Srik	     sp->pp_mode == PP_FR)) {
117326018Sjoerg		IF_DEQUEUE(&sp->pp_fastq, m);
117426018Sjoerg		if (m == NULL)
1175147256Sbrooks			IF_DEQUEUE (&SP2IFP(sp)->if_snd, m);
117626018Sjoerg	}
1177138745Srik	SPPP_UNLOCK(sp);
117826018Sjoerg	splx(s);
117926018Sjoerg	return m;
11804910Swollman}
11814910Swollman
11824910Swollman/*
118330300Sjoerg * Pick the next packet, do not remove it from the queue.
118430300Sjoerg */
118530300Sjoergstruct mbuf *
118630300Sjoergsppp_pick(struct ifnet *ifp)
118730300Sjoerg{
1188147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
118930300Sjoerg	struct mbuf *m;
119030300Sjoerg	int s;
119130300Sjoerg
1192138745Srik	s = splimp ();
1193138745Srik	SPPP_LOCK(sp);
119430300Sjoerg
119530300Sjoerg	m = sp->pp_cpq.ifq_head;
119630300Sjoerg	if (m == NULL &&
1197138745Srik	    (sp->pp_phase == PHASE_NETWORK ||
1198139365Srik	     sp->pp_mode == IFF_CISCO ||
1199139365Srik	     sp->pp_mode == PP_FR))
120030300Sjoerg		if ((m = sp->pp_fastq.ifq_head) == NULL)
1201147256Sbrooks			m = SP2IFP(sp)->if_snd.ifq_head;
1202138745Srik	SPPP_UNLOCK(sp);
120330300Sjoerg	splx (s);
120430300Sjoerg	return (m);
120530300Sjoerg}
120630300Sjoerg
120730300Sjoerg/*
120825944Sjoerg * Process an ioctl request.  Called on low priority level.
12094910Swollman */
121025944Sjoergint
121142104Sphksppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data)
12124910Swollman{
121325944Sjoerg	struct ifreq *ifr = (struct ifreq*) data;
1214147256Sbrooks	struct sppp *sp = IFP2SP(ifp);
121530300Sjoerg	int s, rv, going_up, going_down, newmode;
12164910Swollman
121725944Sjoerg	s = splimp();
1218138745Srik	SPPP_LOCK(sp);
121930300Sjoerg	rv = 0;
122025944Sjoerg	switch (cmd) {
122125944Sjoerg	case SIOCAIFADDR:
122225944Sjoerg	case SIOCSIFDSTADDR:
122325944Sjoerg		break;
12244910Swollman
122525944Sjoerg	case SIOCSIFADDR:
122688503Sjoerg		/* set the interface "up" when assigning an IP address */
122788503Sjoerg		ifp->if_flags |= IFF_UP;
1228102412Scharnier		/* FALLTHROUGH */
122911189Sjkh
123025944Sjoerg	case SIOCSIFFLAGS:
123125944Sjoerg		going_up = ifp->if_flags & IFF_UP &&
1232148887Srwatson			(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0;
123325944Sjoerg		going_down = (ifp->if_flags & IFF_UP) == 0 &&
1234148887Srwatson			ifp->if_drv_flags & IFF_DRV_RUNNING;
123545152Sphk
123645152Sphk		newmode = ifp->if_flags & IFF_PASSIVE;
123745152Sphk		if (!newmode)
123845152Sphk			newmode = ifp->if_flags & IFF_AUTO;
123945152Sphk		if (!newmode)
124045152Sphk			newmode = ifp->if_flags & IFF_CISCO;
124145152Sphk		ifp->if_flags &= ~(IFF_PASSIVE | IFF_AUTO | IFF_CISCO);
124245152Sphk		ifp->if_flags |= newmode;
124345152Sphk
1244139365Srik		if (!newmode)
1245139365Srik			newmode = sp->pp_flags & PP_FR;
1246139365Srik
124745152Sphk		if (newmode != sp->pp_mode) {
124845152Sphk			going_down = 1;
124945152Sphk			if (!going_up)
1250148887Srwatson				going_up = ifp->if_drv_flags & IFF_DRV_RUNNING;
12514910Swollman		}
12524910Swollman
125345152Sphk		if (going_down) {
1254139365Srik			if (sp->pp_mode != IFF_CISCO &&
1255139365Srik			    sp->pp_mode != PP_FR)
125645152Sphk				lcp.Close(sp);
125745152Sphk			else if (sp->pp_tlf)
125845152Sphk				(sp->pp_tlf)(sp);
1259138745Srik			sppp_flush_unlocked(ifp);
1260148887Srwatson			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
126145152Sphk			sp->pp_mode = newmode;
126226018Sjoerg		}
12634910Swollman
126445152Sphk		if (going_up) {
1265139365Srik			if (sp->pp_mode != IFF_CISCO &&
1266139365Srik			    sp->pp_mode != PP_FR)
126745152Sphk				lcp.Close(sp);
126845152Sphk			sp->pp_mode = newmode;
126945152Sphk			if (sp->pp_mode == 0) {
1270148887Srwatson				ifp->if_drv_flags |= IFF_DRV_RUNNING;
127145152Sphk				lcp.Open(sp);
127245152Sphk			}
1273139365Srik			if ((sp->pp_mode == IFF_CISCO) ||
1274139365Srik			    (sp->pp_mode == PP_FR)) {
127545152Sphk				if (sp->pp_tls)
127645152Sphk					(sp->pp_tls)(sp);
1277148887Srwatson				ifp->if_drv_flags |= IFF_DRV_RUNNING;
127845152Sphk			}
127945152Sphk		}
128045152Sphk
12814910Swollman		break;
128211189Sjkh
128325944Sjoerg#ifdef SIOCSIFMTU
128425944Sjoerg#ifndef ifr_mtu
128525944Sjoerg#define ifr_mtu ifr_metric
128625944Sjoerg#endif
128725944Sjoerg	case SIOCSIFMTU:
128825944Sjoerg		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru)
128925944Sjoerg			return (EINVAL);
129025944Sjoerg		ifp->if_mtu = ifr->ifr_mtu;
12914910Swollman		break;
129225944Sjoerg#endif
129325944Sjoerg#ifdef SLIOCSETMTU
129425944Sjoerg	case SLIOCSETMTU:
129525944Sjoerg		if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru)
129625944Sjoerg			return (EINVAL);
129725944Sjoerg		ifp->if_mtu = *(short*)data;
12984910Swollman		break;
129925944Sjoerg#endif
130025944Sjoerg#ifdef SIOCGIFMTU
130125944Sjoerg	case SIOCGIFMTU:
130225944Sjoerg		ifr->ifr_mtu = ifp->if_mtu;
130311189Sjkh		break;
130425944Sjoerg#endif
130525944Sjoerg#ifdef SLIOCGETMTU
130625944Sjoerg	case SLIOCGETMTU:
130725944Sjoerg		*(short*)data = ifp->if_mtu;
13084910Swollman		break;
130925944Sjoerg#endif
131025944Sjoerg	case SIOCADDMULTI:
131125944Sjoerg	case SIOCDELMULTI:
13124910Swollman		break;
131311189Sjkh
131430300Sjoerg	case SIOCGIFGENERIC:
131530300Sjoerg	case SIOCSIFGENERIC:
131630300Sjoerg		rv = sppp_params(sp, cmd, data);
131730300Sjoerg		break;
131830300Sjoerg
131925944Sjoerg	default:
132030300Sjoerg		rv = ENOTTY;
13214910Swollman	}
1322138745Srik	SPPP_UNLOCK(sp);
132325944Sjoerg	splx(s);
132430300Sjoerg	return rv;
13254910Swollman}
13264910Swollman
132770199Sjhay/*
132825944Sjoerg * Cisco framing implementation.
132925944Sjoerg */
133025944Sjoerg
13314910Swollman/*
13324910Swollman * Handle incoming Cisco keepalive protocol packets.
13334910Swollman */
133430300Sjoergstatic void
133525706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m)
13364910Swollman{
133725944Sjoerg	STDDCL;
13384910Swollman	struct cisco_packet *h;
133930300Sjoerg	u_long me, mymask;
13404910Swollman
134127929Sitojun	if (m->m_pkthdr.len < CISCO_PACKET_LEN) {
134225706Sjoerg		if (debug)
134325706Sjoerg			log(LOG_DEBUG,
134440008Sjoerg			    SPP_FMT "cisco invalid packet length: %d bytes\n",
134540008Sjoerg			    SPP_ARGS(ifp), m->m_pkthdr.len);
13464910Swollman		return;
13474910Swollman	}
13484910Swollman	h = mtod (m, struct cisco_packet*);
134925706Sjoerg	if (debug)
135025706Sjoerg		log(LOG_DEBUG,
135140008Sjoerg		    SPP_FMT "cisco input: %d bytes "
135225706Sjoerg		    "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n",
135340008Sjoerg		    SPP_ARGS(ifp), m->m_pkthdr.len,
135440008Sjoerg		    (u_long)ntohl (h->type), (u_long)h->par1, (u_long)h->par2, (u_int)h->rel,
135540008Sjoerg		    (u_int)h->time0, (u_int)h->time1);
13564910Swollman	switch (ntohl (h->type)) {
13574910Swollman	default:
135825706Sjoerg		if (debug)
135969211Sphk			log(-1, SPP_FMT "cisco unknown packet type: 0x%lx\n",
136040008Sjoerg			       SPP_ARGS(ifp), (u_long)ntohl (h->type));
13614910Swollman		break;
13624910Swollman	case CISCO_ADDR_REPLY:
13634910Swollman		/* Reply on address request, ignore */
13644910Swollman		break;
13654910Swollman	case CISCO_KEEPALIVE_REQ:
13664910Swollman		sp->pp_alivecnt = 0;
136778064Sume		sp->pp_rseq[IDX_LCP] = ntohl (h->par1);
136878064Sume		if (sp->pp_seq[IDX_LCP] == sp->pp_rseq[IDX_LCP]) {
13694910Swollman			/* Local and remote sequence numbers are equal.
13704910Swollman			 * Probably, the line is in loopback mode. */
137111189Sjkh			if (sp->pp_loopcnt >= MAXALIVECNT) {
137240008Sjoerg				printf (SPP_FMT "loopback\n",
137340008Sjoerg					SPP_ARGS(ifp));
137411189Sjkh				sp->pp_loopcnt = 0;
137511189Sjkh				if (ifp->if_flags & IFF_UP) {
137611189Sjkh					if_down (ifp);
137726018Sjoerg					sppp_qflush (&sp->pp_cpq);
137811189Sjkh				}
137911189Sjkh			}
13804910Swollman			++sp->pp_loopcnt;
13814910Swollman
13824910Swollman			/* Generate new local sequence number */
138378064Sume			sp->pp_seq[IDX_LCP] = random();
138411189Sjkh			break;
138511189Sjkh		}
138630300Sjoerg		sp->pp_loopcnt = 0;
138711189Sjkh		if (! (ifp->if_flags & IFF_UP) &&
1388148887Srwatson		    (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
138930300Sjoerg			if_up(ifp);
139040008Sjoerg			printf (SPP_FMT "up\n", SPP_ARGS(ifp));
139111189Sjkh		}
13924910Swollman		break;
13934910Swollman	case CISCO_ADDR_REQ:
139430300Sjoerg		sppp_get_ip_addrs(sp, &me, 0, &mymask);
139530300Sjoerg		if (me != 0L)
139630300Sjoerg			sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask);
13974910Swollman		break;
13984910Swollman	}
13994910Swollman}
14004910Swollman
14014910Swollman/*
140225944Sjoerg * Send Cisco keepalive packet.
14034910Swollman */
140412820Sphkstatic void
140525944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2)
140625944Sjoerg{
140725944Sjoerg	STDDCL;
140825944Sjoerg	struct ppp_header *h;
140925944Sjoerg	struct cisco_packet *ch;
141025944Sjoerg	struct mbuf *m;
141135029Sphk	struct timeval tv;
141225944Sjoerg
141336119Sphk	getmicrouptime(&tv);
141470199Sjhay
1415111119Simp	MGETHDR (m, M_DONTWAIT, MT_DATA);
141625944Sjoerg	if (! m)
141725944Sjoerg		return;
141825944Sjoerg	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN;
141925944Sjoerg	m->m_pkthdr.rcvif = 0;
142025944Sjoerg
142125944Sjoerg	h = mtod (m, struct ppp_header*);
142225944Sjoerg	h->address = CISCO_MULTICAST;
142325944Sjoerg	h->control = 0;
142425944Sjoerg	h->protocol = htons (CISCO_KEEPALIVE);
142525944Sjoerg
142625944Sjoerg	ch = (struct cisco_packet*) (h + 1);
142725944Sjoerg	ch->type = htonl (type);
142825944Sjoerg	ch->par1 = htonl (par1);
142925944Sjoerg	ch->par2 = htonl (par2);
143025944Sjoerg	ch->rel = -1;
143140008Sjoerg
143235029Sphk	ch->time0 = htons ((u_short) (tv.tv_sec >> 16));
143335029Sphk	ch->time1 = htons ((u_short) tv.tv_sec);
143425944Sjoerg
143525944Sjoerg	if (debug)
143625944Sjoerg		log(LOG_DEBUG,
143740008Sjoerg		    SPP_FMT "cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n",
143840008Sjoerg			SPP_ARGS(ifp), (u_long)ntohl (ch->type), (u_long)ch->par1,
143940008Sjoerg			(u_long)ch->par2, (u_int)ch->rel, (u_int)ch->time0, (u_int)ch->time1);
144025944Sjoerg
144169152Sjlemon	if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
144269152Sjlemon		ifp->if_oerrors++;
144325944Sjoerg}
144425944Sjoerg
144570199Sjhay/*
144625944Sjoerg * PPP protocol implementation.
144725944Sjoerg */
144825944Sjoerg
144925944Sjoerg/*
145025944Sjoerg * Send PPP control protocol packet.
145125944Sjoerg */
145225944Sjoergstatic void
145325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type,
145425706Sjoerg	     u_char ident, u_short len, void *data)
14554910Swollman{
145625944Sjoerg	STDDCL;
14574910Swollman	struct ppp_header *h;
14584910Swollman	struct lcp_header *lh;
14594910Swollman	struct mbuf *m;
14604910Swollman
14614910Swollman	if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN)
14624910Swollman		len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN;
1463111119Simp	MGETHDR (m, M_DONTWAIT, MT_DATA);
14644910Swollman	if (! m)
14654910Swollman		return;
14664910Swollman	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;
14674910Swollman	m->m_pkthdr.rcvif = 0;
14684910Swollman
14694910Swollman	h = mtod (m, struct ppp_header*);
14704910Swollman	h->address = PPP_ALLSTATIONS;        /* broadcast address */
14714910Swollman	h->control = PPP_UI;                 /* Unnumbered Info */
14724910Swollman	h->protocol = htons (proto);         /* Link Control Protocol */
14734910Swollman
14744910Swollman	lh = (struct lcp_header*) (h + 1);
14754910Swollman	lh->type = type;
14764910Swollman	lh->ident = ident;
14774910Swollman	lh->len = htons (LCP_HEADER_LEN + len);
14784910Swollman	if (len)
14794910Swollman		bcopy (data, lh+1, len);
14804910Swollman
148125706Sjoerg	if (debug) {
148240008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d",
148340008Sjoerg		    SPP_ARGS(ifp),
148425944Sjoerg		    sppp_proto_name(proto),
148525944Sjoerg		    sppp_cp_type_name (lh->type), lh->ident,
148625944Sjoerg		    ntohs (lh->len));
148744145Sphk		sppp_print_bytes ((u_char*) (lh+1), len);
148869211Sphk		log(-1, ">\n");
14894910Swollman	}
149069152Sjlemon	if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
149169152Sjlemon		ifp->if_oerrors++;
14924910Swollman}
14934910Swollman
14944910Swollman/*
149525944Sjoerg * Handle incoming PPP control protocol packets.
14964910Swollman */
149712820Sphkstatic void
149825944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m)
14994910Swollman{
150025944Sjoerg	STDDCL;
150125944Sjoerg	struct lcp_header *h;
150225944Sjoerg	int len = m->m_pkthdr.len;
150325944Sjoerg	int rv;
150425944Sjoerg	u_char *p;
15054910Swollman
150625944Sjoerg	if (len < 4) {
150725944Sjoerg		if (debug)
150825944Sjoerg			log(LOG_DEBUG,
150940008Sjoerg			    SPP_FMT "%s invalid packet length: %d bytes\n",
151040008Sjoerg			    SPP_ARGS(ifp), cp->name, len);
15114910Swollman		return;
151225944Sjoerg	}
151325944Sjoerg	h = mtod (m, struct lcp_header*);
151425944Sjoerg	if (debug) {
151525944Sjoerg		log(LOG_DEBUG,
151640008Sjoerg		    SPP_FMT "%s input(%s): <%s id=0x%x len=%d",
151740008Sjoerg		    SPP_ARGS(ifp), cp->name,
151825944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]),
151925944Sjoerg		    sppp_cp_type_name (h->type), h->ident, ntohs (h->len));
152044145Sphk		sppp_print_bytes ((u_char*) (h+1), len-4);
152169211Sphk		log(-1, ">\n");
152225944Sjoerg	}
152325944Sjoerg	if (len > ntohs (h->len))
152425944Sjoerg		len = ntohs (h->len);
152530300Sjoerg	p = (u_char *)(h + 1);
152625944Sjoerg	switch (h->type) {
152725944Sjoerg	case CONF_REQ:
152825944Sjoerg		if (len < 4) {
152925944Sjoerg			if (debug)
153069211Sphk				log(-1, SPP_FMT "%s invalid conf-req length %d\n",
153140008Sjoerg				       SPP_ARGS(ifp), cp->name,
153225944Sjoerg				       len);
153325944Sjoerg			++ifp->if_ierrors;
153425944Sjoerg			break;
153525944Sjoerg		}
153630300Sjoerg		/* handle states where RCR doesn't get a SCA/SCN */
153730300Sjoerg		switch (sp->state[cp->protoidx]) {
153830300Sjoerg		case STATE_CLOSING:
153930300Sjoerg		case STATE_STOPPING:
154030300Sjoerg			return;
154130300Sjoerg		case STATE_CLOSED:
154230300Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident,
154330300Sjoerg				     0, 0);
154430300Sjoerg			return;
154530300Sjoerg		}
154625944Sjoerg		rv = (cp->RCR)(sp, h, len);
154725944Sjoerg		switch (sp->state[cp->protoidx]) {
154825944Sjoerg		case STATE_OPENED:
154925944Sjoerg			(cp->tld)(sp);
155025944Sjoerg			(cp->scr)(sp);
1551102412Scharnier			/* FALLTHROUGH */
155225944Sjoerg		case STATE_ACK_SENT:
155325944Sjoerg		case STATE_REQ_SENT:
155470199Sjhay			/*
155570199Sjhay			 * sppp_cp_change_state() have the side effect of
155670199Sjhay			 * restarting the timeouts. We want to avoid that
155770199Sjhay			 * if the state don't change, otherwise we won't
155870199Sjhay			 * ever timeout and resend a configuration request
155970199Sjhay			 * that got lost.
156070199Sjhay			 */
156170199Sjhay			if (sp->state[cp->protoidx] == (rv ? STATE_ACK_SENT:
156270199Sjhay			    STATE_REQ_SENT))
156370199Sjhay				break;
156425944Sjoerg			sppp_cp_change_state(cp, sp, rv?
156525944Sjoerg					     STATE_ACK_SENT: STATE_REQ_SENT);
156625944Sjoerg			break;
156725944Sjoerg		case STATE_STOPPED:
156825944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
156925944Sjoerg			(cp->scr)(sp);
157025944Sjoerg			sppp_cp_change_state(cp, sp, rv?
157125944Sjoerg					     STATE_ACK_SENT: STATE_REQ_SENT);
157225944Sjoerg			break;
157325944Sjoerg		case STATE_ACK_RCVD:
157425944Sjoerg			if (rv) {
157525944Sjoerg				sppp_cp_change_state(cp, sp, STATE_OPENED);
157625944Sjoerg				if (debug)
157740008Sjoerg					log(LOG_DEBUG, SPP_FMT "%s tlu\n",
157840008Sjoerg					    SPP_ARGS(ifp),
157926077Sjoerg					    cp->name);
158025944Sjoerg				(cp->tlu)(sp);
158125944Sjoerg			} else
158225944Sjoerg				sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
158325944Sjoerg			break;
158425944Sjoerg		default:
158540008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
158640008Sjoerg			       SPP_ARGS(ifp), cp->name,
158725944Sjoerg			       sppp_cp_type_name(h->type),
158825944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
158925944Sjoerg			++ifp->if_ierrors;
159025944Sjoerg		}
159125944Sjoerg		break;
159225944Sjoerg	case CONF_ACK:
159325944Sjoerg		if (h->ident != sp->confid[cp->protoidx]) {
159425944Sjoerg			if (debug)
159569211Sphk				log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n",
159640008Sjoerg				       SPP_ARGS(ifp), cp->name,
159725944Sjoerg				       h->ident, sp->confid[cp->protoidx]);
159825944Sjoerg			++ifp->if_ierrors;
159925944Sjoerg			break;
160025944Sjoerg		}
160125944Sjoerg		switch (sp->state[cp->protoidx]) {
160225944Sjoerg		case STATE_CLOSED:
160325944Sjoerg		case STATE_STOPPED:
160425944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
160525944Sjoerg			break;
160625944Sjoerg		case STATE_CLOSING:
160725944Sjoerg		case STATE_STOPPING:
160825944Sjoerg			break;
160925944Sjoerg		case STATE_REQ_SENT:
161025944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
161125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
161225944Sjoerg			break;
161325944Sjoerg		case STATE_OPENED:
161425944Sjoerg			(cp->tld)(sp);
1615102412Scharnier			/* FALLTHROUGH */
161625944Sjoerg		case STATE_ACK_RCVD:
161725944Sjoerg			(cp->scr)(sp);
161825944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
161925944Sjoerg			break;
162025944Sjoerg		case STATE_ACK_SENT:
162125944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
162225944Sjoerg			sppp_cp_change_state(cp, sp, STATE_OPENED);
162325944Sjoerg			if (debug)
162440008Sjoerg				log(LOG_DEBUG, SPP_FMT "%s tlu\n",
162540008Sjoerg				       SPP_ARGS(ifp), cp->name);
162625944Sjoerg			(cp->tlu)(sp);
162725944Sjoerg			break;
162825944Sjoerg		default:
162940008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
163040008Sjoerg			       SPP_ARGS(ifp), cp->name,
163125944Sjoerg			       sppp_cp_type_name(h->type),
163225944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
163325944Sjoerg			++ifp->if_ierrors;
163425944Sjoerg		}
163525944Sjoerg		break;
163625944Sjoerg	case CONF_NAK:
163725944Sjoerg	case CONF_REJ:
163825944Sjoerg		if (h->ident != sp->confid[cp->protoidx]) {
163925944Sjoerg			if (debug)
164069211Sphk				log(-1, SPP_FMT "%s id mismatch 0x%x != 0x%x\n",
164140008Sjoerg				       SPP_ARGS(ifp), cp->name,
164225944Sjoerg				       h->ident, sp->confid[cp->protoidx]);
164325944Sjoerg			++ifp->if_ierrors;
164425944Sjoerg			break;
164525944Sjoerg		}
164625944Sjoerg		if (h->type == CONF_NAK)
164725944Sjoerg			(cp->RCN_nak)(sp, h, len);
164825944Sjoerg		else /* CONF_REJ */
164925944Sjoerg			(cp->RCN_rej)(sp, h, len);
16504910Swollman
165125944Sjoerg		switch (sp->state[cp->protoidx]) {
165225944Sjoerg		case STATE_CLOSED:
165325944Sjoerg		case STATE_STOPPED:
165425944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
165525944Sjoerg			break;
165625944Sjoerg		case STATE_REQ_SENT:
165725944Sjoerg		case STATE_ACK_SENT:
165825944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
165970199Sjhay			/*
166070199Sjhay			 * Slow things down a bit if we think we might be
166170199Sjhay			 * in loopback. Depend on the timeout to send the
166270199Sjhay			 * next configuration request.
166370199Sjhay			 */
166470199Sjhay			if (sp->pp_loopcnt)
166570199Sjhay				break;
166625944Sjoerg			(cp->scr)(sp);
166725944Sjoerg			break;
166825944Sjoerg		case STATE_OPENED:
166925944Sjoerg			(cp->tld)(sp);
1670102412Scharnier			/* FALLTHROUGH */
167125944Sjoerg		case STATE_ACK_RCVD:
167252633Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
167325944Sjoerg			(cp->scr)(sp);
167425944Sjoerg			break;
167525944Sjoerg		case STATE_CLOSING:
167625944Sjoerg		case STATE_STOPPING:
167725944Sjoerg			break;
167825944Sjoerg		default:
167940008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
168040008Sjoerg			       SPP_ARGS(ifp), cp->name,
168125944Sjoerg			       sppp_cp_type_name(h->type),
168225944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
168325944Sjoerg			++ifp->if_ierrors;
168425944Sjoerg		}
168525944Sjoerg		break;
16864910Swollman
168725944Sjoerg	case TERM_REQ:
168825944Sjoerg		switch (sp->state[cp->protoidx]) {
168925944Sjoerg		case STATE_ACK_RCVD:
169025944Sjoerg		case STATE_ACK_SENT:
169125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
1692102412Scharnier			/* FALLTHROUGH */
169325944Sjoerg		case STATE_CLOSED:
169425944Sjoerg		case STATE_STOPPED:
169525944Sjoerg		case STATE_CLOSING:
169625944Sjoerg		case STATE_STOPPING:
169725944Sjoerg		case STATE_REQ_SENT:
169825944Sjoerg		  sta:
169925944Sjoerg			/* Send Terminate-Ack packet. */
170025944Sjoerg			if (debug)
170140008Sjoerg				log(LOG_DEBUG, SPP_FMT "%s send terminate-ack\n",
170240008Sjoerg				    SPP_ARGS(ifp), cp->name);
170325944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
170425944Sjoerg			break;
170525944Sjoerg		case STATE_OPENED:
170625944Sjoerg			(cp->tld)(sp);
170725944Sjoerg			sp->rst_counter[cp->protoidx] = 0;
170825944Sjoerg			sppp_cp_change_state(cp, sp, STATE_STOPPING);
170925944Sjoerg			goto sta;
171025944Sjoerg			break;
171125944Sjoerg		default:
171240008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
171340008Sjoerg			       SPP_ARGS(ifp), cp->name,
171425944Sjoerg			       sppp_cp_type_name(h->type),
171525944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
171625944Sjoerg			++ifp->if_ierrors;
171725944Sjoerg		}
171825944Sjoerg		break;
171925944Sjoerg	case TERM_ACK:
172025944Sjoerg		switch (sp->state[cp->protoidx]) {
172125944Sjoerg		case STATE_CLOSED:
172225944Sjoerg		case STATE_STOPPED:
172325944Sjoerg		case STATE_REQ_SENT:
172425944Sjoerg		case STATE_ACK_SENT:
172525944Sjoerg			break;
172625944Sjoerg		case STATE_CLOSING:
172741881Sphk			sppp_cp_change_state(cp, sp, STATE_CLOSED);
172825944Sjoerg			(cp->tlf)(sp);
172925944Sjoerg			break;
173025944Sjoerg		case STATE_STOPPING:
173141881Sphk			sppp_cp_change_state(cp, sp, STATE_STOPPED);
173225944Sjoerg			(cp->tlf)(sp);
173325944Sjoerg			break;
173425944Sjoerg		case STATE_ACK_RCVD:
173525944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
173625944Sjoerg			break;
173725944Sjoerg		case STATE_OPENED:
173825944Sjoerg			(cp->tld)(sp);
173925944Sjoerg			(cp->scr)(sp);
174025944Sjoerg			sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
174125944Sjoerg			break;
174225944Sjoerg		default:
174340008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
174440008Sjoerg			       SPP_ARGS(ifp), cp->name,
174525944Sjoerg			       sppp_cp_type_name(h->type),
174625944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
174725944Sjoerg			++ifp->if_ierrors;
174825944Sjoerg		}
174925944Sjoerg		break;
175025944Sjoerg	case CODE_REJ:
175125944Sjoerg		/* XXX catastrophic rejects (RXJ-) aren't handled yet. */
175230300Sjoerg		log(LOG_INFO,
175340008Sjoerg		    SPP_FMT "%s: ignoring RXJ (%s) for proto 0x%x, "
175430300Sjoerg		    "danger will robinson\n",
175540008Sjoerg		    SPP_ARGS(ifp), cp->name,
175630300Sjoerg		    sppp_cp_type_name(h->type), ntohs(*((u_short *)p)));
175725944Sjoerg		switch (sp->state[cp->protoidx]) {
175825944Sjoerg		case STATE_CLOSED:
175925944Sjoerg		case STATE_STOPPED:
176025944Sjoerg		case STATE_REQ_SENT:
176125944Sjoerg		case STATE_ACK_SENT:
176225944Sjoerg		case STATE_CLOSING:
176325944Sjoerg		case STATE_STOPPING:
176425944Sjoerg		case STATE_OPENED:
176525944Sjoerg			break;
176625944Sjoerg		case STATE_ACK_RCVD:
176725944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
176825944Sjoerg			break;
176925944Sjoerg		default:
177040008Sjoerg			printf(SPP_FMT "%s illegal %s in state %s\n",
177140008Sjoerg			       SPP_ARGS(ifp), cp->name,
177225944Sjoerg			       sppp_cp_type_name(h->type),
177325944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
177425944Sjoerg			++ifp->if_ierrors;
177525944Sjoerg		}
177625944Sjoerg		break;
177780715Sume	case PROTO_REJ:
177880715Sume	    {
177980715Sume		int catastrophic;
178080715Sume		const struct cp *upper;
178180715Sume		int i;
178280715Sume		u_int16_t proto;
178380715Sume
178480715Sume		catastrophic = 0;
178580715Sume		upper = NULL;
178680715Sume		proto = ntohs(*((u_int16_t *)p));
178780715Sume		for (i = 0; i < IDX_COUNT; i++) {
178880715Sume			if (cps[i]->proto == proto) {
178980715Sume				upper = cps[i];
179080715Sume				break;
179180715Sume			}
179280715Sume		}
179380715Sume		if (upper == NULL)
179480715Sume			catastrophic++;
179580715Sume
179688508Sjoerg		if (catastrophic || debug)
179788508Sjoerg			log(catastrophic? LOG_INFO: LOG_DEBUG,
179888508Sjoerg			    SPP_FMT "%s: RXJ%c (%s) for proto 0x%x (%s/%s)\n",
179988508Sjoerg			    SPP_ARGS(ifp), cp->name, catastrophic ? '-' : '+',
180088508Sjoerg			    sppp_cp_type_name(h->type), proto,
180188508Sjoerg			    upper ? upper->name : "unknown",
180288508Sjoerg			    upper ? sppp_state_name(sp->state[upper->protoidx]) : "?");
180380715Sume
180480715Sume		/*
180580715Sume		 * if we got RXJ+ against conf-req, the peer does not implement
180680715Sume		 * this particular protocol type.  terminate the protocol.
180780715Sume		 */
180880715Sume		if (upper && !catastrophic) {
180980715Sume			if (sp->state[upper->protoidx] == STATE_REQ_SENT) {
181080715Sume				upper->Close(sp);
181180715Sume				break;
181280715Sume			}
181380715Sume		}
181480715Sume
181580715Sume		/* XXX catastrophic rejects (RXJ-) aren't handled yet. */
181680715Sume		switch (sp->state[cp->protoidx]) {
181780715Sume		case STATE_CLOSED:
181880715Sume		case STATE_STOPPED:
181980715Sume		case STATE_REQ_SENT:
182080715Sume		case STATE_ACK_SENT:
182180715Sume		case STATE_CLOSING:
182280715Sume		case STATE_STOPPING:
182380715Sume		case STATE_OPENED:
182480715Sume			break;
182580715Sume		case STATE_ACK_RCVD:
182680715Sume			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
182780715Sume			break;
182880715Sume		default:
182980715Sume			printf(SPP_FMT "%s illegal %s in state %s\n",
183080715Sume			       SPP_ARGS(ifp), cp->name,
183180715Sume			       sppp_cp_type_name(h->type),
183280715Sume			       sppp_state_name(sp->state[cp->protoidx]));
183380715Sume			++ifp->if_ierrors;
183480715Sume		}
183580715Sume		break;
183680715Sume	    }
183725944Sjoerg	case DISC_REQ:
183825944Sjoerg		if (cp->proto != PPP_LCP)
183925944Sjoerg			goto illegal;
184025944Sjoerg		/* Discard the packet. */
184125944Sjoerg		break;
184225944Sjoerg	case ECHO_REQ:
184325944Sjoerg		if (cp->proto != PPP_LCP)
184425944Sjoerg			goto illegal;
184525944Sjoerg		if (sp->state[cp->protoidx] != STATE_OPENED) {
184625944Sjoerg			if (debug)
184769211Sphk				log(-1, SPP_FMT "lcp echo req but lcp closed\n",
184840008Sjoerg				       SPP_ARGS(ifp));
184925944Sjoerg			++ifp->if_ierrors;
185025944Sjoerg			break;
185125944Sjoerg		}
185225944Sjoerg		if (len < 8) {
185325944Sjoerg			if (debug)
185469211Sphk				log(-1, SPP_FMT "invalid lcp echo request "
185525944Sjoerg				       "packet length: %d bytes\n",
185640008Sjoerg				       SPP_ARGS(ifp), len);
185725944Sjoerg			break;
185825944Sjoerg		}
185944145Sphk		if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
186044145Sphk		    ntohl (*(long*)(h+1)) == sp->lcp.magic) {
186125944Sjoerg			/* Line loopback mode detected. */
186240008Sjoerg			printf(SPP_FMT "loopback\n", SPP_ARGS(ifp));
186370199Sjhay			sp->pp_loopcnt = MAXALIVECNT * 5;
186425944Sjoerg			if_down (ifp);
186526018Sjoerg			sppp_qflush (&sp->pp_cpq);
18664910Swollman
186725944Sjoerg			/* Shut down the PPP link. */
186825944Sjoerg			/* XXX */
186925944Sjoerg			lcp.Down(sp);
187025944Sjoerg			lcp.Up(sp);
187125944Sjoerg			break;
187225944Sjoerg		}
187325944Sjoerg		*(long*)(h+1) = htonl (sp->lcp.magic);
187425944Sjoerg		if (debug)
187569211Sphk			log(-1, SPP_FMT "got lcp echo req, sending echo rep\n",
187640008Sjoerg			       SPP_ARGS(ifp));
187725944Sjoerg		sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1);
187825944Sjoerg		break;
187925944Sjoerg	case ECHO_REPLY:
188025944Sjoerg		if (cp->proto != PPP_LCP)
188125944Sjoerg			goto illegal;
188225944Sjoerg		if (h->ident != sp->lcp.echoid) {
188325944Sjoerg			++ifp->if_ierrors;
188425944Sjoerg			break;
188525944Sjoerg		}
188625944Sjoerg		if (len < 8) {
188725944Sjoerg			if (debug)
188869211Sphk				log(-1, SPP_FMT "lcp invalid echo reply "
188925944Sjoerg				       "packet length: %d bytes\n",
189040008Sjoerg				       SPP_ARGS(ifp), len);
189125944Sjoerg			break;
189225944Sjoerg		}
189325944Sjoerg		if (debug)
189469211Sphk			log(-1, SPP_FMT "lcp got echo rep\n",
189540008Sjoerg			       SPP_ARGS(ifp));
189644145Sphk		if (!(sp->lcp.opts & (1 << LCP_OPT_MAGIC)) ||
189744145Sphk		    ntohl (*(long*)(h+1)) != sp->lcp.magic)
189825944Sjoerg			sp->pp_alivecnt = 0;
189925944Sjoerg		break;
190025944Sjoerg	default:
190125944Sjoerg		/* Unknown packet type -- send Code-Reject packet. */
190225944Sjoerg	  illegal:
190325944Sjoerg		if (debug)
190469211Sphk			log(-1, SPP_FMT "%s send code-rej for 0x%x\n",
190540008Sjoerg			       SPP_ARGS(ifp), cp->name, h->type);
190678064Sume		sppp_cp_send(sp, cp->proto, CODE_REJ,
190778064Sume			     ++sp->pp_seq[cp->protoidx], m->m_pkthdr.len, h);
190825944Sjoerg		++ifp->if_ierrors;
190925944Sjoerg	}
19104910Swollman}
19114910Swollman
191225944Sjoerg
19134910Swollman/*
191425944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers.
191525944Sjoerg * Basically, the state transition handling in the automaton.
19164910Swollman */
191725944Sjoergstatic void
191825944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp)
19194910Swollman{
192025944Sjoerg	STDDCL;
19214910Swollman
192225944Sjoerg	if (debug)
192340008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s up(%s)\n",
192440008Sjoerg		    SPP_ARGS(ifp), cp->name,
192525944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
192625944Sjoerg
192725944Sjoerg	switch (sp->state[cp->protoidx]) {
192825944Sjoerg	case STATE_INITIAL:
192925944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSED);
193025944Sjoerg		break;
193125944Sjoerg	case STATE_STARTING:
193225944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
193325944Sjoerg		(cp->scr)(sp);
193425944Sjoerg		sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
193525944Sjoerg		break;
19364910Swollman	default:
193740008Sjoerg		printf(SPP_FMT "%s illegal up in state %s\n",
193840008Sjoerg		       SPP_ARGS(ifp), cp->name,
193925944Sjoerg		       sppp_state_name(sp->state[cp->protoidx]));
194025944Sjoerg	}
194125944Sjoerg}
19424910Swollman
194325944Sjoergstatic void
194425944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp)
194525944Sjoerg{
194625944Sjoerg	STDDCL;
194725944Sjoerg
194825944Sjoerg	if (debug)
194940008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s down(%s)\n",
195040008Sjoerg		    SPP_ARGS(ifp), cp->name,
195125944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
195225944Sjoerg
195325944Sjoerg	switch (sp->state[cp->protoidx]) {
195425944Sjoerg	case STATE_CLOSED:
195525944Sjoerg	case STATE_CLOSING:
195625944Sjoerg		sppp_cp_change_state(cp, sp, STATE_INITIAL);
19574910Swollman		break;
195825944Sjoerg	case STATE_STOPPED:
195941881Sphk		sppp_cp_change_state(cp, sp, STATE_STARTING);
196025944Sjoerg		(cp->tls)(sp);
196141881Sphk		break;
196225944Sjoerg	case STATE_STOPPING:
196325944Sjoerg	case STATE_REQ_SENT:
196425944Sjoerg	case STATE_ACK_RCVD:
196525944Sjoerg	case STATE_ACK_SENT:
196625944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
196725944Sjoerg		break;
196825944Sjoerg	case STATE_OPENED:
196925944Sjoerg		(cp->tld)(sp);
197025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
197125944Sjoerg		break;
197225944Sjoerg	default:
197340008Sjoerg		printf(SPP_FMT "%s illegal down in state %s\n",
197440008Sjoerg		       SPP_ARGS(ifp), cp->name,
197525944Sjoerg		       sppp_state_name(sp->state[cp->protoidx]));
197625944Sjoerg	}
197725944Sjoerg}
19784910Swollman
197911189Sjkh
198025944Sjoergstatic void
198125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp)
198225944Sjoerg{
198325944Sjoerg	STDDCL;
198425944Sjoerg
198525944Sjoerg	if (debug)
198640008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s open(%s)\n",
198740008Sjoerg		    SPP_ARGS(ifp), cp->name,
198825944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
198925944Sjoerg
199025944Sjoerg	switch (sp->state[cp->protoidx]) {
199125944Sjoerg	case STATE_INITIAL:
199241881Sphk		sppp_cp_change_state(cp, sp, STATE_STARTING);
199325944Sjoerg		(cp->tls)(sp);
19944910Swollman		break;
199525944Sjoerg	case STATE_STARTING:
199625944Sjoerg		break;
199725944Sjoerg	case STATE_CLOSED:
199825944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
199925944Sjoerg		(cp->scr)(sp);
200025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
200125944Sjoerg		break;
200225944Sjoerg	case STATE_STOPPED:
200374703Sjoerg		/*
200474703Sjoerg		 * Try escaping stopped state.  This seems to bite
200574703Sjoerg		 * people occasionally, in particular for IPCP,
200674703Sjoerg		 * presumably following previous IPCP negotiation
200774703Sjoerg		 * aborts.  Somehow, we must have missed a Down event
200874703Sjoerg		 * which would have caused a transition into starting
200974703Sjoerg		 * state, so as a bandaid we force the Down event now.
201074703Sjoerg		 * This effectively implements (something like the)
201174703Sjoerg		 * `restart' option mentioned in the state transition
201274703Sjoerg		 * table of RFC 1661.
201374703Sjoerg		 */
201474703Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
201574703Sjoerg		(cp->tls)(sp);
201674703Sjoerg		break;
201725944Sjoerg	case STATE_STOPPING:
201825944Sjoerg	case STATE_REQ_SENT:
201925944Sjoerg	case STATE_ACK_RCVD:
202025944Sjoerg	case STATE_ACK_SENT:
202125944Sjoerg	case STATE_OPENED:
202225944Sjoerg		break;
202325944Sjoerg	case STATE_CLOSING:
202425944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STOPPING);
202525944Sjoerg		break;
202625944Sjoerg	}
202725944Sjoerg}
20284910Swollman
202925944Sjoerg
203025944Sjoergstatic void
203125944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp)
203225944Sjoerg{
203325944Sjoerg	STDDCL;
203425944Sjoerg
203525944Sjoerg	if (debug)
203640008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s close(%s)\n",
203740008Sjoerg		    SPP_ARGS(ifp), cp->name,
203825944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
203925944Sjoerg
204025944Sjoerg	switch (sp->state[cp->protoidx]) {
204125944Sjoerg	case STATE_INITIAL:
204225944Sjoerg	case STATE_CLOSED:
204325944Sjoerg	case STATE_CLOSING:
20444910Swollman		break;
204525944Sjoerg	case STATE_STARTING:
204641881Sphk		sppp_cp_change_state(cp, sp, STATE_INITIAL);
204725944Sjoerg		(cp->tlf)(sp);
20484910Swollman		break;
204925944Sjoerg	case STATE_STOPPED:
205025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSED);
20514910Swollman		break;
205225944Sjoerg	case STATE_STOPPING:
205325944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSING);
20544910Swollman		break;
205525944Sjoerg	case STATE_OPENED:
205625944Sjoerg		(cp->tld)(sp);
2057102412Scharnier		/* FALLTHROUGH */
205825944Sjoerg	case STATE_REQ_SENT:
205925944Sjoerg	case STATE_ACK_RCVD:
206025944Sjoerg	case STATE_ACK_SENT:
206125944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate;
206278064Sume		sppp_cp_send(sp, cp->proto, TERM_REQ,
206378064Sume			     ++sp->pp_seq[cp->protoidx], 0, 0);
206425944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSING);
20654910Swollman		break;
20664910Swollman	}
20674910Swollman}
20684910Swollman
206925944Sjoergstatic void
207025944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp)
207125944Sjoerg{
207225944Sjoerg	STDDCL;
207325944Sjoerg	int s;
207425944Sjoerg
207525944Sjoerg	s = splimp();
2076138745Srik	SPPP_LOCK(sp);
207725944Sjoerg	if (debug)
207840008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s TO(%s) rst_counter = %d\n",
207940008Sjoerg		    SPP_ARGS(ifp), cp->name,
208025944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]),
208125944Sjoerg		    sp->rst_counter[cp->protoidx]);
208225944Sjoerg
208325944Sjoerg	if (--sp->rst_counter[cp->protoidx] < 0)
208425944Sjoerg		/* TO- event */
208525944Sjoerg		switch (sp->state[cp->protoidx]) {
208625944Sjoerg		case STATE_CLOSING:
208741881Sphk			sppp_cp_change_state(cp, sp, STATE_CLOSED);
208825944Sjoerg			(cp->tlf)(sp);
208925944Sjoerg			break;
209025944Sjoerg		case STATE_STOPPING:
209141881Sphk			sppp_cp_change_state(cp, sp, STATE_STOPPED);
209225944Sjoerg			(cp->tlf)(sp);
209325944Sjoerg			break;
209425944Sjoerg		case STATE_REQ_SENT:
209525944Sjoerg		case STATE_ACK_RCVD:
209625944Sjoerg		case STATE_ACK_SENT:
209741881Sphk			sppp_cp_change_state(cp, sp, STATE_STOPPED);
209825944Sjoerg			(cp->tlf)(sp);
209925944Sjoerg			break;
210025944Sjoerg		}
210125944Sjoerg	else
210225944Sjoerg		/* TO+ event */
210325944Sjoerg		switch (sp->state[cp->protoidx]) {
210425944Sjoerg		case STATE_CLOSING:
210525944Sjoerg		case STATE_STOPPING:
210678064Sume			sppp_cp_send(sp, cp->proto, TERM_REQ,
210778064Sume				     ++sp->pp_seq[cp->protoidx], 0, 0);
2108138745Srik			callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
2109138745Srik				      cp->TO, (void *)sp);
211025944Sjoerg			break;
211125944Sjoerg		case STATE_REQ_SENT:
211225944Sjoerg		case STATE_ACK_RCVD:
211325944Sjoerg			(cp->scr)(sp);
211425944Sjoerg			/* sppp_cp_change_state() will restart the timer */
211525944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
211625944Sjoerg			break;
211725944Sjoerg		case STATE_ACK_SENT:
211825944Sjoerg			(cp->scr)(sp);
2119138745Srik			callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
2120138745Srik				      cp->TO, (void *)sp);
212125944Sjoerg			break;
212225944Sjoerg		}
212325944Sjoerg
2124138745Srik	SPPP_UNLOCK(sp);
212525944Sjoerg	splx(s);
212625944Sjoerg}
212725944Sjoerg
212811189Sjkh/*
212925944Sjoerg * Change the state of a control protocol in the state automaton.
213025944Sjoerg * Takes care of starting/stopping the restart timer.
213111189Sjkh */
2132105228Sphkstatic void
213325944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate)
213425944Sjoerg{
213525944Sjoerg	sp->state[cp->protoidx] = newstate;
213625944Sjoerg
2137138745Srik	callout_stop (&sp->ch[cp->protoidx]);
2138138745Srik
213925944Sjoerg	switch (newstate) {
214025944Sjoerg	case STATE_INITIAL:
214125944Sjoerg	case STATE_STARTING:
214225944Sjoerg	case STATE_CLOSED:
214325944Sjoerg	case STATE_STOPPED:
214425944Sjoerg	case STATE_OPENED:
214525944Sjoerg		break;
214625944Sjoerg	case STATE_CLOSING:
214725944Sjoerg	case STATE_STOPPING:
214825944Sjoerg	case STATE_REQ_SENT:
214925944Sjoerg	case STATE_ACK_RCVD:
215025944Sjoerg	case STATE_ACK_SENT:
2151138745Srik		callout_reset(&sp->ch[cp->protoidx], sp->lcp.timeout,
2152138745Srik			      cp->TO, (void *)sp);
215325944Sjoerg		break;
215425944Sjoerg	}
215525944Sjoerg}
215670199Sjhay
215770199Sjhay/*
215825944Sjoerg *--------------------------------------------------------------------------*
215925944Sjoerg *                                                                          *
216025944Sjoerg *                         The LCP implementation.                          *
216125944Sjoerg *                                                                          *
216225944Sjoerg *--------------------------------------------------------------------------*
216325944Sjoerg */
216425944Sjoergstatic void
2165138745Sriksppp_pp_up(struct sppp *sp)
2166138745Srik{
2167138745Srik	SPPP_LOCK(sp);
2168138745Srik	lcp.Up(sp);
2169138745Srik	SPPP_UNLOCK(sp);
2170138745Srik}
2171138745Srik
2172138745Srikstatic void
2173138745Sriksppp_pp_down(struct sppp *sp)
2174138745Srik{
2175138745Srik	SPPP_LOCK(sp);
2176138745Srik	lcp.Down(sp);
2177138745Srik	SPPP_UNLOCK(sp);
2178138745Srik}
2179138745Srik
2180138745Srikstatic void
218125944Sjoergsppp_lcp_init(struct sppp *sp)
218225944Sjoerg{
218325944Sjoerg	sp->lcp.opts = (1 << LCP_OPT_MAGIC);
218425944Sjoerg	sp->lcp.magic = 0;
218525944Sjoerg	sp->state[IDX_LCP] = STATE_INITIAL;
218625944Sjoerg	sp->fail_counter[IDX_LCP] = 0;
218778064Sume	sp->pp_seq[IDX_LCP] = 0;
218878064Sume	sp->pp_rseq[IDX_LCP] = 0;
218925944Sjoerg	sp->lcp.protos = 0;
219025944Sjoerg	sp->lcp.mru = sp->lcp.their_mru = PP_MTU;
219130300Sjoerg
219244145Sphk	/* Note that these values are  relevant for all control protocols */
219344145Sphk	sp->lcp.timeout = 3 * hz;
219425944Sjoerg	sp->lcp.max_terminate = 2;
219525944Sjoerg	sp->lcp.max_configure = 10;
219625944Sjoerg	sp->lcp.max_failure = 10;
2197188668Srwatson 	callout_init(&sp->ch[IDX_LCP], CALLOUT_MPSAFE);
219825944Sjoerg}
219925944Sjoerg
220025944Sjoergstatic void
220125944Sjoergsppp_lcp_up(struct sppp *sp)
220225944Sjoerg{
220325944Sjoerg	STDDCL;
220425944Sjoerg
220570199Sjhay	sp->pp_alivecnt = 0;
220670199Sjhay	sp->lcp.opts = (1 << LCP_OPT_MAGIC);
220770199Sjhay	sp->lcp.magic = 0;
220870199Sjhay	sp->lcp.protos = 0;
220970199Sjhay	sp->lcp.mru = sp->lcp.their_mru = PP_MTU;
221025944Sjoerg	/*
221175321Sjoerg	 * If we are authenticator, negotiate LCP_AUTH
221275321Sjoerg	 */
221375321Sjoerg	if (sp->hisauth.proto != 0)
221475321Sjoerg		sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO);
221575321Sjoerg	else
221675321Sjoerg		sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
221775321Sjoerg	sp->pp_flags &= ~PP_NEEDAUTH;
221875321Sjoerg	/*
221930300Sjoerg	 * If this interface is passive or dial-on-demand, and we are
222030300Sjoerg	 * still in Initial state, it means we've got an incoming
222130300Sjoerg	 * call.  Activate the interface.
222225944Sjoerg	 */
222325944Sjoerg	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) {
222425944Sjoerg		if (debug)
222525944Sjoerg			log(LOG_DEBUG,
222640008Sjoerg			    SPP_FMT "Up event", SPP_ARGS(ifp));
2227148887Srwatson		ifp->if_drv_flags |= IFF_DRV_RUNNING;
222830300Sjoerg		if (sp->state[IDX_LCP] == STATE_INITIAL) {
222930300Sjoerg			if (debug)
223069211Sphk				log(-1, "(incoming call)\n");
223130300Sjoerg			sp->pp_flags |= PP_CALLIN;
223230300Sjoerg			lcp.Open(sp);
223330300Sjoerg		} else if (debug)
223469211Sphk			log(-1, "\n");
223588710Sjoerg	} else if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0 &&
223688710Sjoerg		   (sp->state[IDX_LCP] == STATE_INITIAL)) {
2237148887Srwatson		ifp->if_drv_flags |= IFF_DRV_RUNNING;
223888710Sjoerg		lcp.Open(sp);
223925944Sjoerg	}
224025944Sjoerg
224125944Sjoerg	sppp_up_event(&lcp, sp);
224225944Sjoerg}
224325944Sjoerg
224425944Sjoergstatic void
224525944Sjoergsppp_lcp_down(struct sppp *sp)
224625944Sjoerg{
224725944Sjoerg	STDDCL;
224825944Sjoerg
224925944Sjoerg	sppp_down_event(&lcp, sp);
225025944Sjoerg
225125944Sjoerg	/*
225225944Sjoerg	 * If this is neither a dial-on-demand nor a passive
225325944Sjoerg	 * interface, simulate an ``ifconfig down'' action, so the
225425944Sjoerg	 * administrator can force a redial by another ``ifconfig
225525944Sjoerg	 * up''.  XXX For leased line operation, should we immediately
225625944Sjoerg	 * try to reopen the connection here?
225725944Sjoerg	 */
225825944Sjoerg	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) {
225925944Sjoerg		log(LOG_INFO,
226042066Sphk		    SPP_FMT "Down event, taking interface down.\n",
226140008Sjoerg		    SPP_ARGS(ifp));
226225944Sjoerg		if_down(ifp);
226325944Sjoerg	} else {
226425944Sjoerg		if (debug)
226525944Sjoerg			log(LOG_DEBUG,
226640008Sjoerg			    SPP_FMT "Down event (carrier loss)\n",
226740008Sjoerg			    SPP_ARGS(ifp));
226870199Sjhay		sp->pp_flags &= ~PP_CALLIN;
226970199Sjhay		if (sp->state[IDX_LCP] != STATE_INITIAL)
227070199Sjhay			lcp.Close(sp);
2271148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
227225944Sjoerg	}
227325944Sjoerg}
227425944Sjoerg
227525944Sjoergstatic void
227625944Sjoergsppp_lcp_open(struct sppp *sp)
227725944Sjoerg{
227825944Sjoerg	sppp_open_event(&lcp, sp);
227925944Sjoerg}
228025944Sjoerg
228125944Sjoergstatic void
228225944Sjoergsppp_lcp_close(struct sppp *sp)
228325944Sjoerg{
228425944Sjoerg	sppp_close_event(&lcp, sp);
228525944Sjoerg}
228625944Sjoerg
228725944Sjoergstatic void
228825944Sjoergsppp_lcp_TO(void *cookie)
228925944Sjoerg{
229025944Sjoerg	sppp_to_event(&lcp, (struct sppp *)cookie);
229125944Sjoerg}
229225944Sjoerg
229325944Sjoerg/*
229425944Sjoerg * Analyze a configure request.  Return true if it was agreeable, and
229525944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and
229625944Sjoerg * caused action scn.  (The return value is used to make the state
229725944Sjoerg * transition decision in the state automaton.)
229825944Sjoerg */
229912820Sphkstatic int
230025944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
23014910Swollman{
230225944Sjoerg	STDDCL;
230311189Sjkh	u_char *buf, *r, *p;
230425944Sjoerg	int origlen, rlen;
230525944Sjoerg	u_long nmagic;
230630300Sjoerg	u_short authproto;
23074910Swollman
230811189Sjkh	len -= 4;
230925944Sjoerg	origlen = len;
231011189Sjkh	buf = r = malloc (len, M_TEMP, M_NOWAIT);
231111189Sjkh	if (! buf)
231211189Sjkh		return (0);
23134910Swollman
231425706Sjoerg	if (debug)
231540008Sjoerg		log(LOG_DEBUG, SPP_FMT "lcp parse opts: ",
231640008Sjoerg		    SPP_ARGS(ifp));
231725706Sjoerg
231825944Sjoerg	/* pass 1: check for things that need to be rejected */
231911189Sjkh	p = (void*) (h+1);
2320161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
2321161556Scperciva	    len-=p[1], p+=p[1]) {
232225944Sjoerg		if (debug)
232369211Sphk			log(-1, " %s ", sppp_lcp_opt_name(*p));
232411189Sjkh		switch (*p) {
232511189Sjkh		case LCP_OPT_MAGIC:
232625944Sjoerg			/* Magic number. */
232770199Sjhay			if (len >= 6 && p[1] == 6)
232870199Sjhay				continue;
232970199Sjhay			if (debug)
233070199Sjhay				log(-1, "[invalid] ");
233170199Sjhay			break;
233225944Sjoerg		case LCP_OPT_ASYNC_MAP:
233325944Sjoerg			/* Async control character map. */
233470199Sjhay			if (len >= 6 && p[1] == 6)
233525944Sjoerg				continue;
233625944Sjoerg			if (debug)
233769211Sphk				log(-1, "[invalid] ");
233825944Sjoerg			break;
233925944Sjoerg		case LCP_OPT_MRU:
234025944Sjoerg			/* Maximum receive unit. */
234125944Sjoerg			if (len >= 4 && p[1] == 4)
234225944Sjoerg				continue;
234325944Sjoerg			if (debug)
234469211Sphk				log(-1, "[invalid] ");
234525944Sjoerg			break;
234630300Sjoerg		case LCP_OPT_AUTH_PROTO:
234730300Sjoerg			if (len < 4) {
234830300Sjoerg				if (debug)
234969211Sphk					log(-1, "[invalid] ");
235030300Sjoerg				break;
235130300Sjoerg			}
235230300Sjoerg			authproto = (p[2] << 8) + p[3];
235330300Sjoerg			if (authproto == PPP_CHAP && p[1] != 5) {
235430300Sjoerg				if (debug)
235569211Sphk					log(-1, "[invalid chap len] ");
235630300Sjoerg				break;
235730300Sjoerg			}
235830300Sjoerg			if (sp->myauth.proto == 0) {
235930300Sjoerg				/* we are not configured to do auth */
236030300Sjoerg				if (debug)
236169211Sphk					log(-1, "[not configured] ");
236230300Sjoerg				break;
236330300Sjoerg			}
236430300Sjoerg			/*
236530300Sjoerg			 * Remote want us to authenticate, remember this,
236630300Sjoerg			 * so we stay in PHASE_AUTHENTICATE after LCP got
236730300Sjoerg			 * up.
236830300Sjoerg			 */
236930300Sjoerg			sp->pp_flags |= PP_NEEDAUTH;
237030300Sjoerg			continue;
237125944Sjoerg		default:
237225944Sjoerg			/* Others not supported. */
237325944Sjoerg			if (debug)
237469211Sphk				log(-1, "[rej] ");
237525944Sjoerg			break;
237625944Sjoerg		}
237725944Sjoerg		/* Add the option to rejected list. */
237825944Sjoerg		bcopy (p, r, p[1]);
237925944Sjoerg		r += p[1];
238025944Sjoerg		rlen += p[1];
238125944Sjoerg	}
238225944Sjoerg	if (rlen) {
238325944Sjoerg		if (debug)
238469211Sphk			log(-1, " send conf-rej\n");
238525944Sjoerg		sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
238625944Sjoerg		return 0;
238725944Sjoerg	} else if (debug)
238869211Sphk		log(-1, "\n");
238925944Sjoerg
239025944Sjoerg	/*
239125944Sjoerg	 * pass 2: check for option values that are unacceptable and
239225944Sjoerg	 * thus require to be nak'ed.
239325944Sjoerg	 */
239425944Sjoerg	if (debug)
239540008Sjoerg		log(LOG_DEBUG, SPP_FMT "lcp parse opt values: ",
239640008Sjoerg		    SPP_ARGS(ifp));
239725944Sjoerg
239825944Sjoerg	p = (void*) (h+1);
239925944Sjoerg	len = origlen;
2400161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
2401161556Scperciva	    len-=p[1], p+=p[1]) {
240225944Sjoerg		if (debug)
240369211Sphk			log(-1, " %s ", sppp_lcp_opt_name(*p));
240425944Sjoerg		switch (*p) {
240525944Sjoerg		case LCP_OPT_MAGIC:
240611189Sjkh			/* Magic number -- extract. */
240725944Sjoerg			nmagic = (u_long)p[2] << 24 |
240825944Sjoerg				(u_long)p[3] << 16 | p[4] << 8 | p[5];
240925944Sjoerg			if (nmagic != sp->lcp.magic) {
241070199Sjhay				sp->pp_loopcnt = 0;
241125706Sjoerg				if (debug)
241269211Sphk					log(-1, "0x%lx ", nmagic);
241311189Sjkh				continue;
241411189Sjkh			}
241570199Sjhay			if (debug && sp->pp_loopcnt < MAXALIVECNT*5)
241669211Sphk				log(-1, "[glitch] ");
241725944Sjoerg			++sp->pp_loopcnt;
241825944Sjoerg			/*
241925944Sjoerg			 * We negate our magic here, and NAK it.  If
242025944Sjoerg			 * we see it later in an NAK packet, we
242125944Sjoerg			 * suggest a new one.
242225944Sjoerg			 */
242325944Sjoerg			nmagic = ~sp->lcp.magic;
242425944Sjoerg			/* Gonna NAK it. */
242525944Sjoerg			p[2] = nmagic >> 24;
242625944Sjoerg			p[3] = nmagic >> 16;
242725944Sjoerg			p[4] = nmagic >> 8;
242825944Sjoerg			p[5] = nmagic;
242911189Sjkh			break;
243025944Sjoerg
243111189Sjkh		case LCP_OPT_ASYNC_MAP:
243288506Sjoerg			/*
243388506Sjoerg			 * Async control character map -- just ignore it.
243488506Sjoerg			 *
243588506Sjoerg			 * Quote from RFC 1662, chapter 6:
243688506Sjoerg			 * To enable this functionality, synchronous PPP
243788506Sjoerg			 * implementations MUST always respond to the
243888506Sjoerg			 * Async-Control-Character-Map Configuration
243988506Sjoerg			 * Option with the LCP Configure-Ack.  However,
244088506Sjoerg			 * acceptance of the Configuration Option does
244188506Sjoerg			 * not imply that the synchronous implementation
244288506Sjoerg			 * will do any ACCM mapping.  Instead, all such
244388506Sjoerg			 * octet mapping will be performed by the
244488506Sjoerg			 * asynchronous-to-synchronous converter.
244588506Sjoerg			 */
244688506Sjoerg			continue;
244725944Sjoerg
244811189Sjkh		case LCP_OPT_MRU:
244925944Sjoerg			/*
245025944Sjoerg			 * Maximum receive unit.  Always agreeable,
245125944Sjoerg			 * but ignored by now.
245225944Sjoerg			 */
245325944Sjoerg			sp->lcp.their_mru = p[2] * 256 + p[3];
245425706Sjoerg			if (debug)
245569211Sphk				log(-1, "%lu ", sp->lcp.their_mru);
245611189Sjkh			continue;
245730300Sjoerg
245830300Sjoerg		case LCP_OPT_AUTH_PROTO:
245930300Sjoerg			authproto = (p[2] << 8) + p[3];
246030300Sjoerg			if (sp->myauth.proto != authproto) {
246130300Sjoerg				/* not agreed, nak */
246230300Sjoerg				if (debug)
246369211Sphk					log(-1, "[mine %s != his %s] ",
246430300Sjoerg					       sppp_proto_name(sp->hisauth.proto),
246530300Sjoerg					       sppp_proto_name(authproto));
246630300Sjoerg				p[2] = sp->myauth.proto >> 8;
246730300Sjoerg				p[3] = sp->myauth.proto;
246830300Sjoerg				break;
246930300Sjoerg			}
247030300Sjoerg			if (authproto == PPP_CHAP && p[4] != CHAP_MD5) {
247130300Sjoerg				if (debug)
247269211Sphk					log(-1, "[chap not MD5] ");
247339981Sjoerg				p[4] = CHAP_MD5;
247430300Sjoerg				break;
247530300Sjoerg			}
247630300Sjoerg			continue;
247711189Sjkh		}
247825944Sjoerg		/* Add the option to nak'ed list. */
247925706Sjoerg		bcopy (p, r, p[1]);
248025706Sjoerg		r += p[1];
248111189Sjkh		rlen += p[1];
248212436Speter	}
248325706Sjoerg	if (rlen) {
248470199Sjhay		/*
248570199Sjhay		 * Local and remote magics equal -- loopback?
248670199Sjhay		 */
248770199Sjhay		if (sp->pp_loopcnt >= MAXALIVECNT*5) {
248870199Sjhay			if (sp->pp_loopcnt == MAXALIVECNT*5)
248970199Sjhay				printf (SPP_FMT "loopback\n",
249070199Sjhay					SPP_ARGS(ifp));
249170199Sjhay			if (ifp->if_flags & IFF_UP) {
249270199Sjhay				if_down(ifp);
249370199Sjhay				sppp_qflush(&sp->pp_cpq);
249470199Sjhay				/* XXX ? */
249570199Sjhay				lcp.Down(sp);
249670199Sjhay				lcp.Up(sp);
249770199Sjhay			}
2498131093Srik		} else if (!sp->pp_loopcnt &&
2499131093Srik			   ++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) {
250028036Sjoerg			if (debug)
250169211Sphk				log(-1, " max_failure (%d) exceeded, "
250228036Sjoerg				       "send conf-rej\n",
250328036Sjoerg				       sp->lcp.max_failure);
250428036Sjoerg			sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
250528036Sjoerg		} else {
250628036Sjoerg			if (debug)
250769211Sphk				log(-1, " send conf-nak\n");
250828036Sjoerg			sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf);
250928036Sjoerg		}
251025944Sjoerg	} else {
251125944Sjoerg		if (debug)
251269211Sphk			log(-1, " send conf-ack\n");
251328036Sjoerg		sp->fail_counter[IDX_LCP] = 0;
251425944Sjoerg		sp->pp_loopcnt = 0;
251525944Sjoerg		sppp_cp_send (sp, PPP_LCP, CONF_ACK,
251625944Sjoerg			      h->ident, origlen, h+1);
251725944Sjoerg	}
251825944Sjoerg
251911189Sjkh	free (buf, M_TEMP);
252011189Sjkh	return (rlen == 0);
25214910Swollman}
25224910Swollman
252325944Sjoerg/*
252425944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our
252525944Sjoerg * negotiation.
252625944Sjoerg */
252712820Sphkstatic void
252825944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
25294910Swollman{
253025944Sjoerg	STDDCL;
253125944Sjoerg	u_char *buf, *p;
25324910Swollman
253325944Sjoerg	len -= 4;
253425944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
253525944Sjoerg	if (!buf)
25364910Swollman		return;
253725944Sjoerg
253825944Sjoerg	if (debug)
253940008Sjoerg		log(LOG_DEBUG, SPP_FMT "lcp rej opts: ",
254040008Sjoerg		    SPP_ARGS(ifp));
254125944Sjoerg
254225944Sjoerg	p = (void*) (h+1);
2543161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
2544161556Scperciva	    len -= p[1], p += p[1]) {
254525944Sjoerg		if (debug)
254669211Sphk			log(-1, " %s ", sppp_lcp_opt_name(*p));
254725944Sjoerg		switch (*p) {
254825944Sjoerg		case LCP_OPT_MAGIC:
254925944Sjoerg			/* Magic number -- can't use it, use 0 */
255025944Sjoerg			sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC);
255125944Sjoerg			sp->lcp.magic = 0;
255225944Sjoerg			break;
255325944Sjoerg		case LCP_OPT_MRU:
255425944Sjoerg			/*
255525944Sjoerg			 * Should not be rejected anyway, since we only
255625944Sjoerg			 * negotiate a MRU if explicitly requested by
255725944Sjoerg			 * peer.
255825944Sjoerg			 */
255925944Sjoerg			sp->lcp.opts &= ~(1 << LCP_OPT_MRU);
256025944Sjoerg			break;
256130300Sjoerg		case LCP_OPT_AUTH_PROTO:
256230300Sjoerg			/*
256330300Sjoerg			 * Peer doesn't want to authenticate himself,
256430300Sjoerg			 * deny unless this is a dialout call, and
256530300Sjoerg			 * AUTHFLAG_NOCALLOUT is set.
256630300Sjoerg			 */
256730300Sjoerg			if ((sp->pp_flags & PP_CALLIN) == 0 &&
256830300Sjoerg			    (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) {
256930300Sjoerg				if (debug)
257069211Sphk					log(-1, "[don't insist on auth "
257130300Sjoerg					       "for callout]");
257230300Sjoerg				sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
257330300Sjoerg				break;
257430300Sjoerg			}
257530300Sjoerg			if (debug)
257669211Sphk				log(-1, "[access denied]\n");
257730300Sjoerg			lcp.Close(sp);
257830300Sjoerg			break;
257925944Sjoerg		}
25804910Swollman	}
258125944Sjoerg	if (debug)
258269211Sphk		log(-1, "\n");
258325944Sjoerg	free (buf, M_TEMP);
258425944Sjoerg	return;
258525944Sjoerg}
258625944Sjoerg
258725944Sjoerg/*
258825944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our
258925944Sjoerg * negotiation.
259025944Sjoerg */
259125944Sjoergstatic void
259225944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
259325944Sjoerg{
259425944Sjoerg	STDDCL;
259525944Sjoerg	u_char *buf, *p;
259625944Sjoerg	u_long magic;
259725944Sjoerg
259825944Sjoerg	len -= 4;
259925944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
260025944Sjoerg	if (!buf)
260125944Sjoerg		return;
260225944Sjoerg
260325944Sjoerg	if (debug)
260440008Sjoerg		log(LOG_DEBUG, SPP_FMT "lcp nak opts: ",
260540008Sjoerg		    SPP_ARGS(ifp));
260625944Sjoerg
260725944Sjoerg	p = (void*) (h+1);
2608161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
2609161556Scperciva	    len -= p[1], p += p[1]) {
261025706Sjoerg		if (debug)
261169211Sphk			log(-1, " %s ", sppp_lcp_opt_name(*p));
261225944Sjoerg		switch (*p) {
261325944Sjoerg		case LCP_OPT_MAGIC:
261425944Sjoerg			/* Magic number -- renegotiate */
261525944Sjoerg			if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
261625944Sjoerg			    len >= 6 && p[1] == 6) {
261725944Sjoerg				magic = (u_long)p[2] << 24 |
261825944Sjoerg					(u_long)p[3] << 16 | p[4] << 8 | p[5];
261925944Sjoerg				/*
262025944Sjoerg				 * If the remote magic is our negated one,
262125944Sjoerg				 * this looks like a loopback problem.
262225944Sjoerg				 * Suggest a new magic to make sure.
262325944Sjoerg				 */
262425944Sjoerg				if (magic == ~sp->lcp.magic) {
262525944Sjoerg					if (debug)
262669211Sphk						log(-1, "magic glitch ");
262735064Sphk					sp->lcp.magic = random();
262825944Sjoerg				} else {
262925944Sjoerg					sp->lcp.magic = magic;
263025944Sjoerg					if (debug)
263169211Sphk						log(-1, "%lu ", magic);
263225944Sjoerg				}
263325944Sjoerg			}
263425944Sjoerg			break;
263525944Sjoerg		case LCP_OPT_MRU:
263625944Sjoerg			/*
263725944Sjoerg			 * Peer wants to advise us to negotiate an MRU.
263825944Sjoerg			 * Agree on it if it's reasonable, or use
263925944Sjoerg			 * default otherwise.
264025944Sjoerg			 */
264125944Sjoerg			if (len >= 4 && p[1] == 4) {
264225944Sjoerg				u_int mru = p[2] * 256 + p[3];
264325944Sjoerg				if (debug)
264469211Sphk					log(-1, "%d ", mru);
264525944Sjoerg				if (mru < PP_MTU || mru > PP_MAX_MRU)
264625944Sjoerg					mru = PP_MTU;
264725944Sjoerg				sp->lcp.mru = mru;
264825944Sjoerg				sp->lcp.opts |= (1 << LCP_OPT_MRU);
264925944Sjoerg			}
265025944Sjoerg			break;
265130300Sjoerg		case LCP_OPT_AUTH_PROTO:
265230300Sjoerg			/*
265330300Sjoerg			 * Peer doesn't like our authentication method,
265430300Sjoerg			 * deny.
265530300Sjoerg			 */
265630300Sjoerg			if (debug)
265769211Sphk				log(-1, "[access denied]\n");
265830300Sjoerg			lcp.Close(sp);
265930300Sjoerg			break;
26604910Swollman		}
266125944Sjoerg	}
266225944Sjoerg	if (debug)
266369211Sphk		log(-1, "\n");
266425944Sjoerg	free (buf, M_TEMP);
266525944Sjoerg	return;
266625944Sjoerg}
266711189Sjkh
266825944Sjoergstatic void
266925944Sjoergsppp_lcp_tlu(struct sppp *sp)
267025944Sjoerg{
267142066Sphk	STDDCL;
267225944Sjoerg	int i;
267325944Sjoerg	u_long mask;
267425944Sjoerg
267525944Sjoerg	/* XXX ? */
267625944Sjoerg	if (! (ifp->if_flags & IFF_UP) &&
2677148887Srwatson	    (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
267825944Sjoerg		/* Coming out of loopback mode. */
267925944Sjoerg		if_up(ifp);
268040008Sjoerg		printf (SPP_FMT "up\n", SPP_ARGS(ifp));
268125944Sjoerg	}
268225944Sjoerg
268325944Sjoerg	for (i = 0; i < IDX_COUNT; i++)
268425944Sjoerg		if ((cps[i])->flags & CP_QUAL)
268525944Sjoerg			(cps[i])->Open(sp);
268625944Sjoerg
268730300Sjoerg	if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 ||
268830300Sjoerg	    (sp->pp_flags & PP_NEEDAUTH) != 0)
268925944Sjoerg		sp->pp_phase = PHASE_AUTHENTICATE;
269025944Sjoerg	else
269125944Sjoerg		sp->pp_phase = PHASE_NETWORK;
269225944Sjoerg
269342066Sphk	if (debug)
269442066Sphk		log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
269542066Sphk		    sppp_phase_name(sp->pp_phase));
269625944Sjoerg
269730300Sjoerg	/*
269830300Sjoerg	 * Open all authentication protocols.  This is even required
269930300Sjoerg	 * if we already proceeded to network phase, since it might be
270030300Sjoerg	 * that remote wants us to authenticate, so we might have to
270130300Sjoerg	 * send a PAP request.  Undesired authentication protocols
270230300Sjoerg	 * don't do anything when they get an Open event.
270330300Sjoerg	 */
270430300Sjoerg	for (i = 0; i < IDX_COUNT; i++)
270530300Sjoerg		if ((cps[i])->flags & CP_AUTH)
270630300Sjoerg			(cps[i])->Open(sp);
270730300Sjoerg
270830300Sjoerg	if (sp->pp_phase == PHASE_NETWORK) {
270925944Sjoerg		/* Notify all NCPs. */
271025944Sjoerg		for (i = 0; i < IDX_COUNT; i++)
271188723Sjoerg			if (((cps[i])->flags & CP_NCP) &&
271288723Sjoerg			    /*
271388723Sjoerg			     * XXX
271488723Sjoerg			     * Hack to administratively disable IPv6 if
271588723Sjoerg			     * not desired.  Perhaps we should have another
271688723Sjoerg			     * flag for this, but right now, we can make
271788723Sjoerg			     * all struct cp's read/only.
271888723Sjoerg			     */
271988723Sjoerg			    (cps[i] != &ipv6cp ||
272088723Sjoerg			     (sp->confflags & CONF_ENABLE_IPV6)))
272125944Sjoerg				(cps[i])->Open(sp);
272225944Sjoerg	}
272325944Sjoerg
272425944Sjoerg	/* Send Up events to all started protos. */
272525944Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
272688706Sjoerg		if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0)
272725944Sjoerg			(cps[i])->Up(sp);
272825944Sjoerg
272942104Sphk	/* notify low-level driver of state change */
273042104Sphk	if (sp->pp_chg)
273142104Sphk		sp->pp_chg(sp, (int)sp->pp_phase);
273242104Sphk
273325944Sjoerg	if (sp->pp_phase == PHASE_NETWORK)
273425944Sjoerg		/* if no NCP is starting, close down */
273530300Sjoerg		sppp_lcp_check_and_close(sp);
273625944Sjoerg}
273725944Sjoerg
273825944Sjoergstatic void
273925944Sjoergsppp_lcp_tld(struct sppp *sp)
274025944Sjoerg{
274142066Sphk	STDDCL;
274225944Sjoerg	int i;
274325944Sjoerg	u_long mask;
274425944Sjoerg
274525944Sjoerg	sp->pp_phase = PHASE_TERMINATE;
274625944Sjoerg
274742066Sphk	if (debug)
274842066Sphk		log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
274942066Sphk		    sppp_phase_name(sp->pp_phase));
275025944Sjoerg
275125944Sjoerg	/*
275225944Sjoerg	 * Take upper layers down.  We send the Down event first and
275325944Sjoerg	 * the Close second to prevent the upper layers from sending
275425944Sjoerg	 * ``a flurry of terminate-request packets'', as the RFC
275525944Sjoerg	 * describes it.
275625944Sjoerg	 */
275725944Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
275888706Sjoerg		if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_LCP) == 0) {
275925944Sjoerg			(cps[i])->Down(sp);
276025944Sjoerg			(cps[i])->Close(sp);
276125944Sjoerg		}
276225944Sjoerg}
276325944Sjoerg
276425944Sjoergstatic void
276525944Sjoergsppp_lcp_tls(struct sppp *sp)
276625944Sjoerg{
276742066Sphk	STDDCL;
276825944Sjoerg
276925944Sjoerg	sp->pp_phase = PHASE_ESTABLISH;
277025944Sjoerg
277142066Sphk	if (debug)
277242066Sphk		log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
277342066Sphk		    sppp_phase_name(sp->pp_phase));
277425944Sjoerg
277525944Sjoerg	/* Notify lower layer if desired. */
277625944Sjoerg	if (sp->pp_tls)
277725944Sjoerg		(sp->pp_tls)(sp);
277841881Sphk	else
277941881Sphk		(sp->pp_up)(sp);
278025944Sjoerg}
278125944Sjoerg
278225944Sjoergstatic void
278325944Sjoergsppp_lcp_tlf(struct sppp *sp)
278425944Sjoerg{
278542066Sphk	STDDCL;
278625944Sjoerg
278725944Sjoerg	sp->pp_phase = PHASE_DEAD;
278842066Sphk	if (debug)
278942066Sphk		log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
279042066Sphk		    sppp_phase_name(sp->pp_phase));
279125944Sjoerg
279225944Sjoerg	/* Notify lower layer if desired. */
279325944Sjoerg	if (sp->pp_tlf)
279425944Sjoerg		(sp->pp_tlf)(sp);
279541881Sphk	else
279641881Sphk		(sp->pp_down)(sp);
279725944Sjoerg}
279825944Sjoerg
279925944Sjoergstatic void
280025944Sjoergsppp_lcp_scr(struct sppp *sp)
280125944Sjoerg{
280230300Sjoerg	char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */];
280325944Sjoerg	int i = 0;
280430300Sjoerg	u_short authproto;
280525944Sjoerg
280625944Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) {
280725944Sjoerg		if (! sp->lcp.magic)
280835064Sphk			sp->lcp.magic = random();
280925944Sjoerg		opt[i++] = LCP_OPT_MAGIC;
281025944Sjoerg		opt[i++] = 6;
281125944Sjoerg		opt[i++] = sp->lcp.magic >> 24;
281225944Sjoerg		opt[i++] = sp->lcp.magic >> 16;
281325944Sjoerg		opt[i++] = sp->lcp.magic >> 8;
281425944Sjoerg		opt[i++] = sp->lcp.magic;
281525944Sjoerg	}
281625944Sjoerg
281725944Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_MRU)) {
281825944Sjoerg		opt[i++] = LCP_OPT_MRU;
281925944Sjoerg		opt[i++] = 4;
282025944Sjoerg		opt[i++] = sp->lcp.mru >> 8;
282125944Sjoerg		opt[i++] = sp->lcp.mru;
282225944Sjoerg	}
282325944Sjoerg
282430300Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) {
282530300Sjoerg		authproto = sp->hisauth.proto;
282630300Sjoerg		opt[i++] = LCP_OPT_AUTH_PROTO;
282730300Sjoerg		opt[i++] = authproto == PPP_CHAP? 5: 4;
282830300Sjoerg		opt[i++] = authproto >> 8;
282930300Sjoerg		opt[i++] = authproto;
283030300Sjoerg		if (authproto == PPP_CHAP)
283130300Sjoerg			opt[i++] = CHAP_MD5;
283230300Sjoerg	}
283330300Sjoerg
283478064Sume	sp->confid[IDX_LCP] = ++sp->pp_seq[IDX_LCP];
283525944Sjoerg	sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt);
283625944Sjoerg}
283725944Sjoerg
283825944Sjoerg/*
283930300Sjoerg * Check the open NCPs, return true if at least one NCP is open.
284030300Sjoerg */
284130300Sjoergstatic int
284230300Sjoergsppp_ncp_check(struct sppp *sp)
284330300Sjoerg{
284430300Sjoerg	int i, mask;
284530300Sjoerg
284630300Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
284788706Sjoerg		if ((sp->lcp.protos & mask) && (cps[i])->flags & CP_NCP)
284830300Sjoerg			return 1;
284930300Sjoerg	return 0;
285030300Sjoerg}
285130300Sjoerg
285230300Sjoerg/*
285325944Sjoerg * Re-check the open NCPs and see if we should terminate the link.
285425944Sjoerg * Called by the NCPs during their tlf action handling.
285525944Sjoerg */
285625944Sjoergstatic void
285730300Sjoergsppp_lcp_check_and_close(struct sppp *sp)
285825944Sjoerg{
285925944Sjoerg
286030300Sjoerg	if (sp->pp_phase < PHASE_NETWORK)
286130300Sjoerg		/* don't bother, we are already going down */
286230300Sjoerg		return;
286330300Sjoerg
286430300Sjoerg	if (sppp_ncp_check(sp))
286530300Sjoerg		return;
286630300Sjoerg
286725944Sjoerg	lcp.Close(sp);
286825944Sjoerg}
286970199Sjhay
287070199Sjhay/*
287125944Sjoerg *--------------------------------------------------------------------------*
287225944Sjoerg *                                                                          *
287325944Sjoerg *                        The IPCP implementation.                          *
287425944Sjoerg *                                                                          *
287525944Sjoerg *--------------------------------------------------------------------------*
287625944Sjoerg */
287725944Sjoerg
2878184682Sbz#ifdef INET
287925944Sjoergstatic void
288025944Sjoergsppp_ipcp_init(struct sppp *sp)
288125944Sjoerg{
288225944Sjoerg	sp->ipcp.opts = 0;
288325944Sjoerg	sp->ipcp.flags = 0;
288425944Sjoerg	sp->state[IDX_IPCP] = STATE_INITIAL;
288525944Sjoerg	sp->fail_counter[IDX_IPCP] = 0;
288678064Sume	sp->pp_seq[IDX_IPCP] = 0;
288778064Sume	sp->pp_rseq[IDX_IPCP] = 0;
2888188668Srwatson 	callout_init(&sp->ch[IDX_IPCP], CALLOUT_MPSAFE);
288925944Sjoerg}
289025944Sjoerg
289125944Sjoergstatic void
289225944Sjoergsppp_ipcp_up(struct sppp *sp)
289325944Sjoerg{
289425944Sjoerg	sppp_up_event(&ipcp, sp);
289525944Sjoerg}
289625944Sjoerg
289725944Sjoergstatic void
289825944Sjoergsppp_ipcp_down(struct sppp *sp)
289925944Sjoerg{
290025944Sjoerg	sppp_down_event(&ipcp, sp);
290125944Sjoerg}
290225944Sjoerg
290325944Sjoergstatic void
290425944Sjoergsppp_ipcp_open(struct sppp *sp)
290525944Sjoerg{
290625944Sjoerg	STDDCL;
290725944Sjoerg	u_long myaddr, hisaddr;
290825944Sjoerg
290988534Sjoerg	sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN |
291088534Sjoerg			    IPCP_MYADDR_DYN | IPCP_VJ);
291188700Sjoerg	sp->ipcp.opts = 0;
291242104Sphk
291330300Sjoerg	sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
291425944Sjoerg	/*
291525944Sjoerg	 * If we don't have his address, this probably means our
291625944Sjoerg	 * interface doesn't want to talk IP at all.  (This could
291725944Sjoerg	 * be the case if somebody wants to speak only IPX, for
291825944Sjoerg	 * example.)  Don't open IPCP in this case.
291925944Sjoerg	 */
292025944Sjoerg	if (hisaddr == 0L) {
292125944Sjoerg		/* XXX this message should go away */
292225944Sjoerg		if (debug)
292340008Sjoerg			log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n",
292440008Sjoerg			    SPP_ARGS(ifp));
292525944Sjoerg		return;
292625944Sjoerg	}
292725944Sjoerg	if (myaddr == 0L) {
292825944Sjoerg		/*
292925944Sjoerg		 * I don't have an assigned address, so i need to
293025944Sjoerg		 * negotiate my address.
293125944Sjoerg		 */
293225944Sjoerg		sp->ipcp.flags |= IPCP_MYADDR_DYN;
293325944Sjoerg		sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
293442104Sphk	} else
293542104Sphk		sp->ipcp.flags |= IPCP_MYADDR_SEEN;
293688723Sjoerg	if (sp->confflags & CONF_ENABLE_VJ) {
293788534Sjoerg		sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION);
293888534Sjoerg		sp->ipcp.max_state = MAX_STATES - 1;
293988534Sjoerg		sp->ipcp.compress_cid = 1;
294088534Sjoerg	}
294125944Sjoerg	sppp_open_event(&ipcp, sp);
294225944Sjoerg}
294325944Sjoerg
294425944Sjoergstatic void
294525944Sjoergsppp_ipcp_close(struct sppp *sp)
294625944Sjoerg{
294725944Sjoerg	sppp_close_event(&ipcp, sp);
294825944Sjoerg	if (sp->ipcp.flags & IPCP_MYADDR_DYN)
294925944Sjoerg		/*
295025944Sjoerg		 * My address was dynamic, clear it again.
295125944Sjoerg		 */
295225944Sjoerg		sppp_set_ip_addr(sp, 0L);
295325944Sjoerg}
295425944Sjoerg
295525944Sjoergstatic void
295625944Sjoergsppp_ipcp_TO(void *cookie)
295725944Sjoerg{
295825944Sjoerg	sppp_to_event(&ipcp, (struct sppp *)cookie);
295925944Sjoerg}
296025944Sjoerg
296125944Sjoerg/*
296225944Sjoerg * Analyze a configure request.  Return true if it was agreeable, and
296325944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and
296425944Sjoerg * caused action scn.  (The return value is used to make the state
296525944Sjoerg * transition decision in the state automaton.)
296625944Sjoerg */
296725944Sjoergstatic int
296825944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
296925944Sjoerg{
297025944Sjoerg	u_char *buf, *r, *p;
2971147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
297225944Sjoerg	int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
297325944Sjoerg	u_long hisaddr, desiredaddr;
297442104Sphk	int gotmyaddr = 0;
297588534Sjoerg	int desiredcomp;
297625944Sjoerg
297725944Sjoerg	len -= 4;
297825944Sjoerg	origlen = len;
297925944Sjoerg	/*
298025944Sjoerg	 * Make sure to allocate a buf that can at least hold a
298125944Sjoerg	 * conf-nak with an `address' option.  We might need it below.
298225944Sjoerg	 */
298325944Sjoerg	buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT);
298425944Sjoerg	if (! buf)
298525944Sjoerg		return (0);
298625944Sjoerg
298725944Sjoerg	/* pass 1: see if we can recognize them */
298825944Sjoerg	if (debug)
298940008Sjoerg		log(LOG_DEBUG, SPP_FMT "ipcp parse opts: ",
299040008Sjoerg		    SPP_ARGS(ifp));
299125944Sjoerg	p = (void*) (h+1);
2992161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
2993161556Scperciva	    len-=p[1], p+=p[1]) {
299425944Sjoerg		if (debug)
299569211Sphk			log(-1, " %s ", sppp_ipcp_opt_name(*p));
299625944Sjoerg		switch (*p) {
299788534Sjoerg		case IPCP_OPT_COMPRESSION:
299888723Sjoerg			if (!(sp->confflags & CONF_ENABLE_VJ)) {
299988534Sjoerg				/* VJ compression administratively disabled */
300088534Sjoerg				if (debug)
300188534Sjoerg					log(-1, "[locally disabled] ");
300288534Sjoerg				break;
300388534Sjoerg			}
300488534Sjoerg			/*
300588534Sjoerg			 * In theory, we should only conf-rej an
300688534Sjoerg			 * option that is shorter than RFC 1618
300788534Sjoerg			 * requires (i.e. < 4), and should conf-nak
300888534Sjoerg			 * anything else that is not VJ.  However,
300988534Sjoerg			 * since our algorithm always uses the
301088534Sjoerg			 * original option to NAK it with new values,
301188534Sjoerg			 * things would become more complicated.  In
301288534Sjoerg			 * pratice, the only commonly implemented IP
301388534Sjoerg			 * compression option is VJ anyway, so the
301488534Sjoerg			 * difference is negligible.
301588534Sjoerg			 */
301688534Sjoerg			if (len >= 6 && p[1] == 6) {
301788534Sjoerg				/*
301888534Sjoerg				 * correctly formed compression option
301988534Sjoerg				 * that could be VJ compression
302088534Sjoerg				 */
302188534Sjoerg				continue;
302288534Sjoerg			}
302388534Sjoerg			if (debug)
302488534Sjoerg				log(-1,
302588534Sjoerg				    "optlen %d [invalid/unsupported] ",
302688534Sjoerg				    p[1]);
302788534Sjoerg			break;
302825944Sjoerg		case IPCP_OPT_ADDRESS:
302925944Sjoerg			if (len >= 6 && p[1] == 6) {
303025944Sjoerg				/* correctly formed address option */
303125944Sjoerg				continue;
303225944Sjoerg			}
303325706Sjoerg			if (debug)
303469211Sphk				log(-1, "[invalid] ");
303511189Sjkh			break;
303625944Sjoerg		default:
303725944Sjoerg			/* Others not supported. */
303825944Sjoerg			if (debug)
303969211Sphk				log(-1, "[rej] ");
30404910Swollman			break;
30414910Swollman		}
304225944Sjoerg		/* Add the option to rejected list. */
304325944Sjoerg		bcopy (p, r, p[1]);
304425944Sjoerg		r += p[1];
304525944Sjoerg		rlen += p[1];
304625944Sjoerg	}
304725944Sjoerg	if (rlen) {
304825944Sjoerg		if (debug)
304969211Sphk			log(-1, " send conf-rej\n");
305025944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf);
305125944Sjoerg		return 0;
305225944Sjoerg	} else if (debug)
305369211Sphk		log(-1, "\n");
305425944Sjoerg
305525944Sjoerg	/* pass 2: parse option values */
305630300Sjoerg	sppp_get_ip_addrs(sp, 0, &hisaddr, 0);
305725944Sjoerg	if (debug)
305840008Sjoerg		log(LOG_DEBUG, SPP_FMT "ipcp parse opt values: ",
305940008Sjoerg		       SPP_ARGS(ifp));
306025944Sjoerg	p = (void*) (h+1);
306125944Sjoerg	len = origlen;
3062161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
3063161556Scperciva	    len-=p[1], p+=p[1]) {
306425944Sjoerg		if (debug)
306569211Sphk			log(-1, " %s ", sppp_ipcp_opt_name(*p));
306625944Sjoerg		switch (*p) {
306788534Sjoerg		case IPCP_OPT_COMPRESSION:
306888534Sjoerg			desiredcomp = p[2] << 8 | p[3];
306988534Sjoerg			/* We only support VJ */
307088534Sjoerg			if (desiredcomp == IPCP_COMP_VJ) {
307188534Sjoerg				if (debug)
307288534Sjoerg					log(-1, "VJ [ack] ");
307388534Sjoerg				sp->ipcp.flags |= IPCP_VJ;
307488599Sjoerg				sl_compress_init(sp->pp_comp, p[4]);
307588534Sjoerg				sp->ipcp.max_state = p[4];
307688534Sjoerg				sp->ipcp.compress_cid = p[5];
307788534Sjoerg				continue;
307888534Sjoerg			}
307988534Sjoerg			if (debug)
308088534Sjoerg				log(-1,
308188534Sjoerg				    "compproto %#04x [not supported] ",
308288534Sjoerg				    desiredcomp);
308388534Sjoerg			p[2] = IPCP_COMP_VJ >> 8;
308488534Sjoerg			p[3] = IPCP_COMP_VJ;
308588534Sjoerg			p[4] = sp->ipcp.max_state;
308688534Sjoerg			p[5] = sp->ipcp.compress_cid;
308788534Sjoerg			break;
308825944Sjoerg		case IPCP_OPT_ADDRESS:
308942104Sphk			/* This is the address he wants in his end */
309025944Sjoerg			desiredaddr = p[2] << 24 | p[3] << 16 |
309125944Sjoerg				p[4] << 8 | p[5];
309233928Sphk			if (desiredaddr == hisaddr ||
309388702Sjoerg			    (hisaddr >= 1 && hisaddr <= 254 && desiredaddr != 0)) {
309425944Sjoerg				/*
309525944Sjoerg				 * Peer's address is same as our value,
309688702Sjoerg				 * or we have set it to 0.0.0.* to
309733928Sphk				 * indicate that we do not really care,
309825944Sjoerg				 * this is agreeable.  Gonna conf-ack
309925944Sjoerg				 * it.
310025944Sjoerg				 */
310125944Sjoerg				if (debug)
310269211Sphk					log(-1, "%s [ack] ",
310342104Sphk						sppp_dotted_quad(hisaddr));
310425944Sjoerg				/* record that we've seen it already */
310525944Sjoerg				sp->ipcp.flags |= IPCP_HISADDR_SEEN;
310625944Sjoerg				continue;
310725944Sjoerg			}
310825944Sjoerg			/*
310925944Sjoerg			 * The address wasn't agreeable.  This is either
311025944Sjoerg			 * he sent us 0.0.0.0, asking to assign him an
311125944Sjoerg			 * address, or he send us another address not
311225944Sjoerg			 * matching our value.  Either case, we gonna
311325944Sjoerg			 * conf-nak it with our value.
311442104Sphk			 * XXX: we should "rej" if hisaddr == 0
311525944Sjoerg			 */
311625944Sjoerg			if (debug) {
311725944Sjoerg				if (desiredaddr == 0)
311869211Sphk					log(-1, "[addr requested] ");
311925944Sjoerg				else
312069211Sphk					log(-1, "%s [not agreed] ",
312142104Sphk						sppp_dotted_quad(desiredaddr));
312225944Sjoerg
312325944Sjoerg			}
312444235Sphk			p[2] = hisaddr >> 24;
312544235Sphk			p[3] = hisaddr >> 16;
312644235Sphk			p[4] = hisaddr >> 8;
312744235Sphk			p[5] = hisaddr;
312811189Sjkh			break;
312925706Sjoerg		}
313025944Sjoerg		/* Add the option to nak'ed list. */
313125944Sjoerg		bcopy (p, r, p[1]);
313225944Sjoerg		r += p[1];
313325944Sjoerg		rlen += p[1];
313425944Sjoerg	}
313525944Sjoerg
313625944Sjoerg	/*
313725944Sjoerg	 * If we are about to conf-ack the request, but haven't seen
313825944Sjoerg	 * his address so far, gonna conf-nak it instead, with the
313925944Sjoerg	 * `address' option present and our idea of his address being
314025944Sjoerg	 * filled in there, to request negotiation of both addresses.
314125944Sjoerg	 *
314225944Sjoerg	 * XXX This can result in an endless req - nak loop if peer
314325944Sjoerg	 * doesn't want to send us his address.  Q: What should we do
314425944Sjoerg	 * about it?  XXX  A: implement the max-failure counter.
314525944Sjoerg	 */
314642104Sphk	if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) {
314725944Sjoerg		buf[0] = IPCP_OPT_ADDRESS;
314825944Sjoerg		buf[1] = 6;
314925944Sjoerg		buf[2] = hisaddr >> 24;
315025944Sjoerg		buf[3] = hisaddr >> 16;
315125944Sjoerg		buf[4] = hisaddr >> 8;
315225944Sjoerg		buf[5] = hisaddr;
315325944Sjoerg		rlen = 6;
315425706Sjoerg		if (debug)
315569211Sphk			log(-1, "still need hisaddr ");
315625944Sjoerg	}
315725944Sjoerg
315825944Sjoerg	if (rlen) {
315925706Sjoerg		if (debug)
316069211Sphk			log(-1, " send conf-nak\n");
316125944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf);
316225944Sjoerg	} else {
316325706Sjoerg		if (debug)
316469211Sphk			log(-1, " send conf-ack\n");
316525944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_ACK,
316625944Sjoerg			      h->ident, origlen, h+1);
316725944Sjoerg	}
316825944Sjoerg
316925944Sjoerg	free (buf, M_TEMP);
317025944Sjoerg	return (rlen == 0);
317125944Sjoerg}
317225944Sjoerg
317325944Sjoerg/*
317425944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our
317525944Sjoerg * negotiation.
317625944Sjoerg */
317725944Sjoergstatic void
317825944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
317925944Sjoerg{
318025944Sjoerg	u_char *buf, *p;
3181147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
318225944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG;
318325944Sjoerg
318425944Sjoerg	len -= 4;
318525944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
318625944Sjoerg	if (!buf)
318725944Sjoerg		return;
318825944Sjoerg
318925944Sjoerg	if (debug)
319040008Sjoerg		log(LOG_DEBUG, SPP_FMT "ipcp rej opts: ",
319140008Sjoerg		    SPP_ARGS(ifp));
319225944Sjoerg
319325944Sjoerg	p = (void*) (h+1);
3194161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
3195161556Scperciva	    len -= p[1], p += p[1]) {
319625706Sjoerg		if (debug)
319769211Sphk			log(-1, " %s ", sppp_ipcp_opt_name(*p));
319825944Sjoerg		switch (*p) {
319988534Sjoerg		case IPCP_OPT_COMPRESSION:
320088534Sjoerg			sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION);
320188534Sjoerg			break;
320225944Sjoerg		case IPCP_OPT_ADDRESS:
320325944Sjoerg			/*
320425944Sjoerg			 * Peer doesn't grok address option.  This is
320525944Sjoerg			 * bad.  XXX  Should we better give up here?
320642104Sphk			 * XXX We could try old "addresses" option...
320725944Sjoerg			 */
320825944Sjoerg			sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS);
320925944Sjoerg			break;
321025944Sjoerg		}
32114910Swollman	}
321225944Sjoerg	if (debug)
321369211Sphk		log(-1, "\n");
321425944Sjoerg	free (buf, M_TEMP);
321525944Sjoerg	return;
32164910Swollman}
32174910Swollman
321825944Sjoerg/*
321925944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our
322025944Sjoerg * negotiation.
322125944Sjoerg */
322212820Sphkstatic void
322325944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
32244910Swollman{
322525944Sjoerg	u_char *buf, *p;
3226147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
322725944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG;
322888534Sjoerg	int desiredcomp;
322925944Sjoerg	u_long wantaddr;
32304910Swollman
323125944Sjoerg	len -= 4;
323225944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
323325944Sjoerg	if (!buf)
323425944Sjoerg		return;
323525944Sjoerg
323625944Sjoerg	if (debug)
323740008Sjoerg		log(LOG_DEBUG, SPP_FMT "ipcp nak opts: ",
323840008Sjoerg		    SPP_ARGS(ifp));
323925944Sjoerg
324025944Sjoerg	p = (void*) (h+1);
3241161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
3242161556Scperciva	    len -= p[1], p += p[1]) {
324325944Sjoerg		if (debug)
324469211Sphk			log(-1, " %s ", sppp_ipcp_opt_name(*p));
324525944Sjoerg		switch (*p) {
324688534Sjoerg		case IPCP_OPT_COMPRESSION:
324788534Sjoerg			if (len >= 6 && p[1] == 6) {
324888534Sjoerg				desiredcomp = p[2] << 8 | p[3];
324988534Sjoerg				if (debug)
325088534Sjoerg					log(-1, "[wantcomp %#04x] ",
325188534Sjoerg						desiredcomp);
325288534Sjoerg				if (desiredcomp == IPCP_COMP_VJ) {
325388599Sjoerg					sl_compress_init(sp->pp_comp, p[4]);
325488534Sjoerg					sp->ipcp.max_state = p[4];
325588534Sjoerg					sp->ipcp.compress_cid = p[5];
325688534Sjoerg					if (debug)
325788534Sjoerg						log(-1, "[agree] ");
325888534Sjoerg				} else
325988534Sjoerg					sp->ipcp.opts &=
326088534Sjoerg						~(1 << IPCP_OPT_COMPRESSION);
326188534Sjoerg			}
326288534Sjoerg			break;
326325944Sjoerg		case IPCP_OPT_ADDRESS:
326425944Sjoerg			/*
326525944Sjoerg			 * Peer doesn't like our local IP address.  See
326625944Sjoerg			 * if we can do something for him.  We'll drop
326725944Sjoerg			 * him our address then.
326825944Sjoerg			 */
326925944Sjoerg			if (len >= 6 && p[1] == 6) {
327025944Sjoerg				wantaddr = p[2] << 24 | p[3] << 16 |
327125944Sjoerg					p[4] << 8 | p[5];
327225944Sjoerg				sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
327325944Sjoerg				if (debug)
327469211Sphk					log(-1, "[wantaddr %s] ",
327530300Sjoerg					       sppp_dotted_quad(wantaddr));
327625944Sjoerg				/*
327725944Sjoerg				 * When doing dynamic address assignment,
327825944Sjoerg				 * we accept his offer.  Otherwise, we
327925944Sjoerg				 * ignore it and thus continue to negotiate
328025944Sjoerg				 * our already existing value.
328142104Sphk			 	 * XXX: Bogus, if he said no once, he'll
328242104Sphk				 * just say no again, might as well die.
328325944Sjoerg				 */
328425944Sjoerg				if (sp->ipcp.flags & IPCP_MYADDR_DYN) {
328525944Sjoerg					sppp_set_ip_addr(sp, wantaddr);
328625944Sjoerg					if (debug)
328769211Sphk						log(-1, "[agree] ");
328842104Sphk					sp->ipcp.flags |= IPCP_MYADDR_SEEN;
328925944Sjoerg				}
329025944Sjoerg			}
329125944Sjoerg			break;
329225944Sjoerg		}
329325944Sjoerg	}
329425944Sjoerg	if (debug)
329569211Sphk		log(-1, "\n");
329625944Sjoerg	free (buf, M_TEMP);
329725944Sjoerg	return;
32984910Swollman}
32994910Swollman
330012820Sphkstatic void
330125944Sjoergsppp_ipcp_tlu(struct sppp *sp)
33024910Swollman{
330342104Sphk	/* we are up - notify isdn daemon */
330442104Sphk	if (sp->pp_con)
330542104Sphk		sp->pp_con(sp);
33064910Swollman}
33074910Swollman
330825944Sjoergstatic void
330925944Sjoergsppp_ipcp_tld(struct sppp *sp)
331025944Sjoerg{
331125944Sjoerg}
331225944Sjoerg
331325944Sjoergstatic void
331425944Sjoergsppp_ipcp_tls(struct sppp *sp)
331525944Sjoerg{
331625944Sjoerg	/* indicate to LCP that it must stay alive */
331725944Sjoerg	sp->lcp.protos |= (1 << IDX_IPCP);
331825944Sjoerg}
331925944Sjoerg
332025944Sjoergstatic void
332125944Sjoergsppp_ipcp_tlf(struct sppp *sp)
332225944Sjoerg{
332325944Sjoerg	/* we no longer need LCP */
332425944Sjoerg	sp->lcp.protos &= ~(1 << IDX_IPCP);
332530300Sjoerg	sppp_lcp_check_and_close(sp);
332625944Sjoerg}
332725944Sjoerg
332825944Sjoergstatic void
332925944Sjoergsppp_ipcp_scr(struct sppp *sp)
333025944Sjoerg{
333125944Sjoerg	char opt[6 /* compression */ + 6 /* address */];
333225944Sjoerg	u_long ouraddr;
333325944Sjoerg	int i = 0;
333425944Sjoerg
333588534Sjoerg	if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) {
333688534Sjoerg		opt[i++] = IPCP_OPT_COMPRESSION;
333788534Sjoerg		opt[i++] = 6;
333888534Sjoerg		opt[i++] = IPCP_COMP_VJ >> 8;
333988534Sjoerg		opt[i++] = IPCP_COMP_VJ;
334088534Sjoerg		opt[i++] = sp->ipcp.max_state;
334188534Sjoerg		opt[i++] = sp->ipcp.compress_cid;
334288534Sjoerg	}
334325944Sjoerg	if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) {
334430300Sjoerg		sppp_get_ip_addrs(sp, &ouraddr, 0, 0);
334525944Sjoerg		opt[i++] = IPCP_OPT_ADDRESS;
334625944Sjoerg		opt[i++] = 6;
334725944Sjoerg		opt[i++] = ouraddr >> 24;
334825944Sjoerg		opt[i++] = ouraddr >> 16;
334925944Sjoerg		opt[i++] = ouraddr >> 8;
335025944Sjoerg		opt[i++] = ouraddr;
335125944Sjoerg	}
335225944Sjoerg
335378064Sume	sp->confid[IDX_IPCP] = ++sp->pp_seq[IDX_IPCP];
335425944Sjoerg	sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt);
335525944Sjoerg}
3356184682Sbz#else /* !INET */
3357184682Sbzstatic void
3358184682Sbzsppp_ipcp_init(struct sppp *sp)
3359184682Sbz{
3360184682Sbz}
336125944Sjoerg
3362184682Sbzstatic void
3363184682Sbzsppp_ipcp_up(struct sppp *sp)
3364184682Sbz{
3365184682Sbz}
3366184682Sbz
3367184682Sbzstatic void
3368184682Sbzsppp_ipcp_down(struct sppp *sp)
3369184682Sbz{
3370184682Sbz}
3371184682Sbz
3372184682Sbzstatic void
3373184682Sbzsppp_ipcp_open(struct sppp *sp)
3374184682Sbz{
3375184682Sbz}
3376184682Sbz
3377184682Sbzstatic void
3378184682Sbzsppp_ipcp_close(struct sppp *sp)
3379184682Sbz{
3380184682Sbz}
3381184682Sbz
3382184682Sbzstatic void
3383184682Sbzsppp_ipcp_TO(void *cookie)
3384184682Sbz{
3385184682Sbz}
3386184682Sbz
3387184682Sbzstatic int
3388184682Sbzsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
3389184682Sbz{
3390184682Sbz	return (0);
3391184682Sbz}
3392184682Sbz
3393184682Sbzstatic void
3394184682Sbzsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
3395184682Sbz{
3396184682Sbz}
3397184682Sbz
3398184682Sbzstatic void
3399184682Sbzsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
3400184682Sbz{
3401184682Sbz}
3402184682Sbz
3403184682Sbzstatic void
3404184682Sbzsppp_ipcp_tlu(struct sppp *sp)
3405184682Sbz{
3406184682Sbz}
3407184682Sbz
3408184682Sbzstatic void
3409184682Sbzsppp_ipcp_tld(struct sppp *sp)
3410184682Sbz{
3411184682Sbz}
3412184682Sbz
3413184682Sbzstatic void
3414184682Sbzsppp_ipcp_tls(struct sppp *sp)
3415184682Sbz{
3416184682Sbz}
3417184682Sbz
3418184682Sbzstatic void
3419184682Sbzsppp_ipcp_tlf(struct sppp *sp)
3420184682Sbz{
3421184682Sbz}
3422184682Sbz
3423184682Sbzstatic void
3424184682Sbzsppp_ipcp_scr(struct sppp *sp)
3425184682Sbz{
3426184682Sbz}
3427184682Sbz#endif
3428184682Sbz
342970199Sjhay/*
343030300Sjoerg *--------------------------------------------------------------------------*
343130300Sjoerg *                                                                          *
343278064Sume *                      The IPv6CP implementation.                          *
343378064Sume *                                                                          *
343478064Sume *--------------------------------------------------------------------------*
343578064Sume */
343678064Sume
343778064Sume#ifdef INET6
343878064Sumestatic void
343978064Sumesppp_ipv6cp_init(struct sppp *sp)
344078064Sume{
344178064Sume	sp->ipv6cp.opts = 0;
344278064Sume	sp->ipv6cp.flags = 0;
344378064Sume	sp->state[IDX_IPV6CP] = STATE_INITIAL;
344478064Sume	sp->fail_counter[IDX_IPV6CP] = 0;
344578064Sume	sp->pp_seq[IDX_IPV6CP] = 0;
344678064Sume	sp->pp_rseq[IDX_IPV6CP] = 0;
3447188668Srwatson 	callout_init(&sp->ch[IDX_IPV6CP], CALLOUT_MPSAFE);
344878064Sume}
344978064Sume
345078064Sumestatic void
345178064Sumesppp_ipv6cp_up(struct sppp *sp)
345278064Sume{
345378064Sume	sppp_up_event(&ipv6cp, sp);
345478064Sume}
345578064Sume
345678064Sumestatic void
345778064Sumesppp_ipv6cp_down(struct sppp *sp)
345878064Sume{
345978064Sume	sppp_down_event(&ipv6cp, sp);
346078064Sume}
346178064Sume
346278064Sumestatic void
346378064Sumesppp_ipv6cp_open(struct sppp *sp)
346478064Sume{
346578064Sume	STDDCL;
346678064Sume	struct in6_addr myaddr, hisaddr;
346778064Sume
346878064Sume#ifdef IPV6CP_MYIFID_DYN
346978064Sume	sp->ipv6cp.flags &= ~(IPV6CP_MYIFID_SEEN|IPV6CP_MYIFID_DYN);
347078064Sume#else
347178064Sume	sp->ipv6cp.flags &= ~IPV6CP_MYIFID_SEEN;
347278064Sume#endif
347378064Sume
347478064Sume	sppp_get_ip6_addrs(sp, &myaddr, &hisaddr, 0);
347578064Sume	/*
347678064Sume	 * If we don't have our address, this probably means our
347778064Sume	 * interface doesn't want to talk IPv6 at all.  (This could
347878064Sume	 * be the case if somebody wants to speak only IPX, for
347978064Sume	 * example.)  Don't open IPv6CP in this case.
348078064Sume	 */
348178064Sume	if (IN6_IS_ADDR_UNSPECIFIED(&myaddr)) {
348278064Sume		/* XXX this message should go away */
348378064Sume		if (debug)
348478064Sume			log(LOG_DEBUG, SPP_FMT "ipv6cp_open(): no IPv6 interface\n",
348578064Sume			    SPP_ARGS(ifp));
348678064Sume		return;
348778064Sume	}
348878064Sume
348978064Sume	sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN;
349078064Sume	sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID);
349178064Sume	sppp_open_event(&ipv6cp, sp);
349278064Sume}
349378064Sume
349478064Sumestatic void
349578064Sumesppp_ipv6cp_close(struct sppp *sp)
349678064Sume{
349778064Sume	sppp_close_event(&ipv6cp, sp);
349878064Sume}
349978064Sume
350078064Sumestatic void
350178064Sumesppp_ipv6cp_TO(void *cookie)
350278064Sume{
350378064Sume	sppp_to_event(&ipv6cp, (struct sppp *)cookie);
350478064Sume}
350578064Sume
350678064Sume/*
350778064Sume * Analyze a configure request.  Return true if it was agreeable, and
350878064Sume * caused action sca, false if it has been rejected or nak'ed, and
350978064Sume * caused action scn.  (The return value is used to make the state
351078064Sume * transition decision in the state automaton.)
351178064Sume */
351278064Sumestatic int
351378064Sumesppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len)
351478064Sume{
351578064Sume	u_char *buf, *r, *p;
3516147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
351778064Sume	int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
351878064Sume	struct in6_addr myaddr, desiredaddr, suggestaddr;
351978064Sume	int ifidcount;
352078064Sume	int type;
352178064Sume	int collision, nohisaddr;
3522165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
352378064Sume
352478064Sume	len -= 4;
352578064Sume	origlen = len;
352678064Sume	/*
352778064Sume	 * Make sure to allocate a buf that can at least hold a
352878064Sume	 * conf-nak with an `address' option.  We might need it below.
352978064Sume	 */
353078064Sume	buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT);
353178064Sume	if (! buf)
353278064Sume		return (0);
353378064Sume
353478064Sume	/* pass 1: see if we can recognize them */
353578064Sume	if (debug)
353678064Sume		log(LOG_DEBUG, SPP_FMT "ipv6cp parse opts:",
353778064Sume		    SPP_ARGS(ifp));
353878064Sume	p = (void*) (h+1);
353978064Sume	ifidcount = 0;
3540161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
3541161556Scperciva	    len-=p[1], p+=p[1]) {
354278064Sume		if (debug)
354378176Sume			log(-1, " %s", sppp_ipv6cp_opt_name(*p));
354478064Sume		switch (*p) {
354578064Sume		case IPV6CP_OPT_IFID:
354678064Sume			if (len >= 10 && p[1] == 10 && ifidcount == 0) {
354778064Sume				/* correctly formed address option */
354878064Sume				ifidcount++;
354978064Sume				continue;
355078064Sume			}
355178064Sume			if (debug)
355278176Sume				log(-1, " [invalid]");
355378064Sume			break;
355478064Sume#ifdef notyet
355578064Sume		case IPV6CP_OPT_COMPRESSION:
355678064Sume			if (len >= 4 && p[1] >= 4) {
355778064Sume				/* correctly formed compress option */
355878064Sume				continue;
355978064Sume			}
356078064Sume			if (debug)
356178176Sume				log(-1, " [invalid]");
356278064Sume			break;
356378064Sume#endif
356478064Sume		default:
356578064Sume			/* Others not supported. */
356678064Sume			if (debug)
356778176Sume				log(-1, " [rej]");
356878064Sume			break;
356978064Sume		}
357078064Sume		/* Add the option to rejected list. */
357178064Sume		bcopy (p, r, p[1]);
357278064Sume		r += p[1];
357378064Sume		rlen += p[1];
357478064Sume	}
357578064Sume	if (rlen) {
357678064Sume		if (debug)
357778176Sume			log(-1, " send conf-rej\n");
357878064Sume		sppp_cp_send (sp, PPP_IPV6CP, CONF_REJ, h->ident, rlen, buf);
357978064Sume		goto end;
358078064Sume	} else if (debug)
358178176Sume		log(-1, "\n");
358278064Sume
358378064Sume	/* pass 2: parse option values */
358478064Sume	sppp_get_ip6_addrs(sp, &myaddr, 0, 0);
358578064Sume	if (debug)
358678064Sume		log(LOG_DEBUG, SPP_FMT "ipv6cp parse opt values: ",
358778064Sume		    SPP_ARGS(ifp));
358878064Sume	p = (void*) (h+1);
358978064Sume	len = origlen;
359078064Sume	type = CONF_ACK;
3591161556Scperciva	for (rlen=0; len >= 2 && p[1] >= 2 && len >= p[1];
3592161556Scperciva	    len-=p[1], p+=p[1]) {
359378064Sume		if (debug)
359478176Sume			log(-1, " %s", sppp_ipv6cp_opt_name(*p));
359578064Sume		switch (*p) {
359678064Sume#ifdef notyet
359778064Sume		case IPV6CP_OPT_COMPRESSION:
359878064Sume			continue;
359978064Sume#endif
360078064Sume		case IPV6CP_OPT_IFID:
360178064Sume			bzero(&desiredaddr, sizeof(desiredaddr));
360278064Sume			bcopy(&p[2], &desiredaddr.s6_addr[8], 8);
360378064Sume			collision = (bcmp(&desiredaddr.s6_addr[8],
360478064Sume					  &myaddr.s6_addr[8], 8) == 0);
360578064Sume			nohisaddr = IN6_IS_ADDR_UNSPECIFIED(&desiredaddr);
360678064Sume
360778064Sume			desiredaddr.s6_addr16[0] = htons(0xfe80);
3608148385Sume			(void)in6_setscope(&desiredaddr, SP2IFP(sp), NULL);
360978064Sume
361078064Sume			if (!collision && !nohisaddr) {
361178064Sume				/* no collision, hisaddr known - Conf-Ack */
361278064Sume				type = CONF_ACK;
361378064Sume
361478064Sume				if (debug) {
361578176Sume					log(-1, " %s [%s]",
3616165118Sbz					    ip6_sprintf(ip6buf, &desiredaddr),
3617165118Sbz					    sppp_cp_type_name(type));
361878064Sume				}
361978064Sume				continue;
362078064Sume			}
362178064Sume
362278064Sume			bzero(&suggestaddr, sizeof(&suggestaddr));
362378064Sume			if (collision && nohisaddr) {
362478064Sume				/* collision, hisaddr unknown - Conf-Rej */
362578064Sume				type = CONF_REJ;
362678064Sume				bzero(&p[2], 8);
362778064Sume			} else {
362878064Sume				/*
362978064Sume				 * - no collision, hisaddr unknown, or
363078064Sume				 * - collision, hisaddr known
363178064Sume				 * Conf-Nak, suggest hisaddr
363278064Sume				 */
363378064Sume				type = CONF_NAK;
363478064Sume				sppp_suggest_ip6_addr(sp, &suggestaddr);
363578064Sume				bcopy(&suggestaddr.s6_addr[8], &p[2], 8);
363678064Sume			}
363778064Sume			if (debug)
3638165118Sbz				log(-1, " %s [%s]",
3639165118Sbz				    ip6_sprintf(ip6buf, &desiredaddr),
3640165118Sbz				    sppp_cp_type_name(type));
364178064Sume			break;
364278064Sume		}
364378064Sume		/* Add the option to nak'ed list. */
364478064Sume		bcopy (p, r, p[1]);
364578064Sume		r += p[1];
364678064Sume		rlen += p[1];
364778064Sume	}
364878064Sume
364978064Sume	if (rlen == 0 && type == CONF_ACK) {
365078064Sume		if (debug)
365178176Sume			log(-1, " send %s\n", sppp_cp_type_name(type));
365278064Sume		sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, origlen, h+1);
365378064Sume	} else {
365478064Sume#ifdef DIAGNOSTIC
365578064Sume		if (type == CONF_ACK)
365678064Sume			panic("IPv6CP RCR: CONF_ACK with non-zero rlen");
365778064Sume#endif
365878064Sume
365978064Sume		if (debug) {
366078176Sume			log(-1, " send %s suggest %s\n",
3661165118Sbz			    sppp_cp_type_name(type),
3662165118Sbz			    ip6_sprintf(ip6buf, &suggestaddr));
366378064Sume		}
366478064Sume		sppp_cp_send (sp, PPP_IPV6CP, type, h->ident, rlen, buf);
366578064Sume	}
366678064Sume
366778064Sume end:
366878064Sume	free (buf, M_TEMP);
366978064Sume	return (rlen == 0);
367078064Sume}
367178064Sume
367278064Sume/*
367378064Sume * Analyze the IPv6CP Configure-Reject option list, and adjust our
367478064Sume * negotiation.
367578064Sume */
367678064Sumestatic void
367778064Sumesppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
367878064Sume{
367978064Sume	u_char *buf, *p;
3680147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
368178064Sume	int debug = ifp->if_flags & IFF_DEBUG;
368278064Sume
368378064Sume	len -= 4;
368478064Sume	buf = malloc (len, M_TEMP, M_NOWAIT);
368578064Sume	if (!buf)
368678064Sume		return;
368778064Sume
368878064Sume	if (debug)
368978064Sume		log(LOG_DEBUG, SPP_FMT "ipv6cp rej opts:",
369078064Sume		    SPP_ARGS(ifp));
369178064Sume
369278064Sume	p = (void*) (h+1);
3693161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
3694161556Scperciva	    len -= p[1], p += p[1]) {
369578064Sume		if (debug)
369678176Sume			log(-1, " %s", sppp_ipv6cp_opt_name(*p));
369778064Sume		switch (*p) {
369878064Sume		case IPV6CP_OPT_IFID:
369978064Sume			/*
370078064Sume			 * Peer doesn't grok address option.  This is
370178064Sume			 * bad.  XXX  Should we better give up here?
370278064Sume			 */
370378064Sume			sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_IFID);
370478064Sume			break;
370578064Sume#ifdef notyet
370678064Sume		case IPV6CP_OPT_COMPRESS:
370778064Sume			sp->ipv6cp.opts &= ~(1 << IPV6CP_OPT_COMPRESS);
370878064Sume			break;
370978064Sume#endif
371078064Sume		}
371178064Sume	}
371278064Sume	if (debug)
371378176Sume		log(-1, "\n");
371478064Sume	free (buf, M_TEMP);
371578064Sume	return;
371678064Sume}
371778064Sume
371878064Sume/*
371978064Sume * Analyze the IPv6CP Configure-NAK option list, and adjust our
372078064Sume * negotiation.
372178064Sume */
372278064Sumestatic void
372378064Sumesppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
372478064Sume{
372578064Sume	u_char *buf, *p;
3726147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
372778064Sume	int debug = ifp->if_flags & IFF_DEBUG;
372878064Sume	struct in6_addr suggestaddr;
3729165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
373078064Sume
373178064Sume	len -= 4;
373278064Sume	buf = malloc (len, M_TEMP, M_NOWAIT);
373378064Sume	if (!buf)
373478064Sume		return;
373578064Sume
373678064Sume	if (debug)
373778064Sume		log(LOG_DEBUG, SPP_FMT "ipv6cp nak opts:",
373878064Sume		    SPP_ARGS(ifp));
373978064Sume
374078064Sume	p = (void*) (h+1);
3741161556Scperciva	for (; len >= 2 && p[1] >= 2 && len >= p[1];
3742161556Scperciva	    len -= p[1], p += p[1]) {
374378064Sume		if (debug)
374478176Sume			log(-1, " %s", sppp_ipv6cp_opt_name(*p));
374578064Sume		switch (*p) {
374678064Sume		case IPV6CP_OPT_IFID:
374778064Sume			/*
374878064Sume			 * Peer doesn't like our local ifid.  See
374978064Sume			 * if we can do something for him.  We'll drop
375078064Sume			 * him our address then.
375178064Sume			 */
375278064Sume			if (len < 10 || p[1] != 10)
375378064Sume				break;
375478064Sume			bzero(&suggestaddr, sizeof(suggestaddr));
375578064Sume			suggestaddr.s6_addr16[0] = htons(0xfe80);
3756148385Sume			(void)in6_setscope(&suggestaddr, SP2IFP(sp), NULL);
375778064Sume			bcopy(&p[2], &suggestaddr.s6_addr[8], 8);
375878064Sume
375978064Sume			sp->ipv6cp.opts |= (1 << IPV6CP_OPT_IFID);
376078064Sume			if (debug)
376178176Sume				log(-1, " [suggestaddr %s]",
3762165118Sbz				       ip6_sprintf(ip6buf, &suggestaddr));
376378064Sume#ifdef IPV6CP_MYIFID_DYN
376478064Sume			/*
376578064Sume			 * When doing dynamic address assignment,
376678064Sume			 * we accept his offer.
376778064Sume			 */
376878064Sume			if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) {
376978064Sume				struct in6_addr lastsuggest;
377078064Sume				/*
377178064Sume				 * If <suggested myaddr from peer> equals to
377278064Sume				 * <hisaddr we have suggested last time>,
377378064Sume				 * we have a collision.  generate new random
377478064Sume				 * ifid.
377578064Sume				 */
377678064Sume				sppp_suggest_ip6_addr(&lastsuggest);
377778064Sume				if (IN6_ARE_ADDR_EQUAL(&suggestaddr,
377878064Sume						       lastsuggest)) {
377978064Sume					if (debug)
378078176Sume						log(-1, " [random]");
378178064Sume					sppp_gen_ip6_addr(sp, &suggestaddr);
378278064Sume				}
378378064Sume				sppp_set_ip6_addr(sp, &suggestaddr, 0);
378478064Sume				if (debug)
378578176Sume					log(-1, " [agree]");
378678064Sume				sp->ipv6cp.flags |= IPV6CP_MYIFID_SEEN;
378778064Sume			}
378878064Sume#else
378978064Sume			/*
379078064Sume			 * Since we do not do dynamic address assignment,
379178064Sume			 * we ignore it and thus continue to negotiate
379278064Sume			 * our already existing value.  This can possibly
379378064Sume			 * go into infinite request-reject loop.
379478064Sume			 *
379578064Sume			 * This is not likely because we normally use
379678064Sume			 * ifid based on MAC-address.
379778064Sume			 * If you have no ethernet card on the node, too bad.
379878064Sume			 * XXX should we use fail_counter?
379978064Sume			 */
380078064Sume#endif
380178064Sume			break;
380278064Sume#ifdef notyet
380378064Sume		case IPV6CP_OPT_COMPRESS:
380478064Sume			/*
380578064Sume			 * Peer wants different compression parameters.
380678064Sume			 */
380778064Sume			break;
380878064Sume#endif
380978064Sume		}
381078064Sume	}
381178064Sume	if (debug)
381278176Sume		log(-1, "\n");
381378064Sume	free (buf, M_TEMP);
381478064Sume	return;
381578064Sume}
381678064Sumestatic void
381778064Sumesppp_ipv6cp_tlu(struct sppp *sp)
381878064Sume{
381978064Sume	/* we are up - notify isdn daemon */
382078064Sume	if (sp->pp_con)
382178064Sume		sp->pp_con(sp);
382278064Sume}
382378064Sume
382478064Sumestatic void
382578064Sumesppp_ipv6cp_tld(struct sppp *sp)
382678064Sume{
382778064Sume}
382878064Sume
382978064Sumestatic void
383078064Sumesppp_ipv6cp_tls(struct sppp *sp)
383178064Sume{
383278064Sume	/* indicate to LCP that it must stay alive */
383378064Sume	sp->lcp.protos |= (1 << IDX_IPV6CP);
383478064Sume}
383578064Sume
383678064Sumestatic void
383778064Sumesppp_ipv6cp_tlf(struct sppp *sp)
383878064Sume{
383978064Sume
384078064Sume#if 0	/* need #if 0 to close IPv6CP properly */
384178064Sume	/* we no longer need LCP */
384278064Sume	sp->lcp.protos &= ~(1 << IDX_IPV6CP);
384378064Sume	sppp_lcp_check_and_close(sp);
384478064Sume#endif
384578064Sume}
384678064Sume
384778064Sumestatic void
384878064Sumesppp_ipv6cp_scr(struct sppp *sp)
384978064Sume{
385078064Sume	char opt[10 /* ifid */ + 4 /* compression, minimum */];
385178064Sume	struct in6_addr ouraddr;
385278064Sume	int i = 0;
385378064Sume
385478064Sume	if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) {
385578064Sume		sppp_get_ip6_addrs(sp, &ouraddr, 0, 0);
385678064Sume		opt[i++] = IPV6CP_OPT_IFID;
385778064Sume		opt[i++] = 10;
385878064Sume		bcopy(&ouraddr.s6_addr[8], &opt[i], 8);
385978064Sume		i += 8;
386078064Sume	}
386178064Sume
386278064Sume#ifdef notyet
386378064Sume	if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_COMPRESSION)) {
386478064Sume		opt[i++] = IPV6CP_OPT_COMPRESSION;
386578064Sume		opt[i++] = 4;
386678064Sume		opt[i++] = 0;   /* TBD */
386778064Sume		opt[i++] = 0;   /* TBD */
386878064Sume		/* variable length data may follow */
386978064Sume	}
387078064Sume#endif
387178064Sume
387278064Sume	sp->confid[IDX_IPV6CP] = ++sp->pp_seq[IDX_IPV6CP];
387378064Sume	sppp_cp_send(sp, PPP_IPV6CP, CONF_REQ, sp->confid[IDX_IPV6CP], i, &opt);
387478064Sume}
387578064Sume#else /*INET6*/
387678064Sumestatic void sppp_ipv6cp_init(struct sppp *sp)
387778064Sume{
387878064Sume}
387978064Sume
388078064Sumestatic void sppp_ipv6cp_up(struct sppp *sp)
388178064Sume{
388278064Sume}
388378064Sume
388478064Sumestatic void sppp_ipv6cp_down(struct sppp *sp)
388578064Sume{
388678064Sume}
388778064Sume
388878064Sume
388978064Sumestatic void sppp_ipv6cp_open(struct sppp *sp)
389078064Sume{
389178064Sume}
389278064Sume
389378064Sumestatic void sppp_ipv6cp_close(struct sppp *sp)
389478064Sume{
389578064Sume}
389678064Sume
389778064Sumestatic void sppp_ipv6cp_TO(void *sp)
389878064Sume{
389978064Sume}
390078064Sume
390178064Sumestatic int sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len)
390278064Sume{
390378064Sume	return 0;
390478064Sume}
390578064Sume
390678064Sumestatic void sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
390778064Sume{
390878064Sume}
390978064Sume
391078064Sumestatic void sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
391178064Sume{
391278064Sume}
391378064Sume
391478064Sumestatic void sppp_ipv6cp_tlu(struct sppp *sp)
391578064Sume{
391678064Sume}
391778064Sume
391878064Sumestatic void sppp_ipv6cp_tld(struct sppp *sp)
391978064Sume{
392078064Sume}
392178064Sume
392278064Sumestatic void sppp_ipv6cp_tls(struct sppp *sp)
392378064Sume{
392478064Sume}
392578064Sume
392678064Sumestatic void sppp_ipv6cp_tlf(struct sppp *sp)
392778064Sume{
392878064Sume}
392978064Sume
393078064Sumestatic void sppp_ipv6cp_scr(struct sppp *sp)
393178064Sume{
393278064Sume}
393378064Sume#endif /*INET6*/
393478064Sume
393578064Sume/*
393678064Sume *--------------------------------------------------------------------------*
393778064Sume *                                                                          *
393830300Sjoerg *                        The CHAP implementation.                          *
393930300Sjoerg *                                                                          *
394030300Sjoerg *--------------------------------------------------------------------------*
394130300Sjoerg */
394230300Sjoerg
394330300Sjoerg/*
394430300Sjoerg * The authentication protocols don't employ a full-fledged state machine as
394530300Sjoerg * the control protocols do, since they do have Open and Close events, but
394630300Sjoerg * not Up and Down, nor are they explicitly terminated.  Also, use of the
394730300Sjoerg * authentication protocols may be different in both directions (this makes
394830300Sjoerg * sense, think of a machine that never accepts incoming calls but only
394930300Sjoerg * calls out, it doesn't require the called party to authenticate itself).
395030300Sjoerg *
395130300Sjoerg * Our state machine for the local authentication protocol (we are requesting
395230300Sjoerg * the peer to authenticate) looks like:
395330300Sjoerg *
395430300Sjoerg *						    RCA-
395530300Sjoerg *	      +--------------------------------------------+
395630300Sjoerg *	      V					    scn,tld|
395730300Sjoerg *	  +--------+			       Close   +---------+ RCA+
395830300Sjoerg *	  |	   |<----------------------------------|	 |------+
395930300Sjoerg *   +--->| Closed |				TO*    | Opened	 | sca	|
396030300Sjoerg *   |	  |	   |-----+		       +-------|	 |<-----+
396130300Sjoerg *   |	  +--------+ irc |		       |       +---------+
396230300Sjoerg *   |	    ^		 |		       |	   ^
396330300Sjoerg *   |	    |		 |		       |	   |
396430300Sjoerg *   |	    |		 |		       |	   |
396530300Sjoerg *   |	 TO-|		 |		       |	   |
396630300Sjoerg *   |	    |tld  TO+	 V		       |	   |
396730300Sjoerg *   |	    |	+------->+		       |	   |
396830300Sjoerg *   |	    |	|	 |		       |	   |
396930300Sjoerg *   |	  +--------+	 V		       |	   |
397030300Sjoerg *   |	  |	   |<----+<--------------------+	   |
397130300Sjoerg *   |	  | Req-   | scr				   |
397230300Sjoerg *   |	  | Sent   |					   |
397330300Sjoerg *   |	  |	   |					   |
397430300Sjoerg *   |	  +--------+					   |
397530300Sjoerg *   | RCA- |	| RCA+					   |
397630300Sjoerg *   +------+	+------------------------------------------+
397730300Sjoerg *   scn,tld	  sca,irc,ict,tlu
397830300Sjoerg *
397930300Sjoerg *
398030300Sjoerg *   with:
398130300Sjoerg *
398230300Sjoerg *	Open:	LCP reached authentication phase
398330300Sjoerg *	Close:	LCP reached terminate phase
398430300Sjoerg *
398530300Sjoerg *	RCA+:	received reply (pap-req, chap-response), acceptable
398630300Sjoerg *	RCN:	received reply (pap-req, chap-response), not acceptable
398730300Sjoerg *	TO+:	timeout with restart counter >= 0
398830300Sjoerg *	TO-:	timeout with restart counter < 0
398930300Sjoerg *	TO*:	reschedule timeout for CHAP
399030300Sjoerg *
399130300Sjoerg *	scr:	send request packet (none for PAP, chap-challenge)
399230300Sjoerg *	sca:	send ack packet (pap-ack, chap-success)
399330300Sjoerg *	scn:	send nak packet (pap-nak, chap-failure)
399430300Sjoerg *	ict:	initialize re-challenge timer (CHAP only)
399530300Sjoerg *
399630300Sjoerg *	tlu:	this-layer-up, LCP reaches network phase
399730300Sjoerg *	tld:	this-layer-down, LCP enters terminate phase
399830300Sjoerg *
399930300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state
400030300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld
400130300Sjoerg * event to LCP, so LCP remains in network phase.  Only after not getting
400230300Sjoerg * any response (or after getting an unacceptable response), CHAP closes,
400330300Sjoerg * causing LCP to enter terminate phase.
400430300Sjoerg *
400530300Sjoerg * With PAP, there is no initial request that can be sent.  The peer is
400630300Sjoerg * expected to send one based on the successful negotiation of PAP as
400730300Sjoerg * the authentication protocol during the LCP option negotiation.
400830300Sjoerg *
400930300Sjoerg * Incoming authentication protocol requests (remote requests
401030300Sjoerg * authentication, we are peer) don't employ a state machine at all,
401130300Sjoerg * they are simply answered.  Some peers [Ascend P50 firmware rev
401230300Sjoerg * 4.50] react allergically when sending IPCP requests while they are
401330300Sjoerg * still in authentication phase (thereby violating the standard that
401430300Sjoerg * demands that these NCP packets are to be discarded), so we keep
401530300Sjoerg * track of the peer demanding us to authenticate, and only proceed to
401630300Sjoerg * phase network once we've seen a positive acknowledge for the
401730300Sjoerg * authentication.
401830300Sjoerg */
401930300Sjoerg
402030300Sjoerg/*
402130300Sjoerg * Handle incoming CHAP packets.
402230300Sjoerg */
4023105228Sphkstatic void
402430300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m)
402530300Sjoerg{
402630300Sjoerg	STDDCL;
402730300Sjoerg	struct lcp_header *h;
402830300Sjoerg	int len, x;
402930300Sjoerg	u_char *value, *name, digest[AUTHKEYLEN], dsize;
403030300Sjoerg	int value_len, name_len;
403130300Sjoerg	MD5_CTX ctx;
403230300Sjoerg
403330300Sjoerg	len = m->m_pkthdr.len;
403430300Sjoerg	if (len < 4) {
403530300Sjoerg		if (debug)
403630300Sjoerg			log(LOG_DEBUG,
403740008Sjoerg			    SPP_FMT "chap invalid packet length: %d bytes\n",
403840008Sjoerg			    SPP_ARGS(ifp), len);
403930300Sjoerg		return;
404030300Sjoerg	}
404130300Sjoerg	h = mtod (m, struct lcp_header*);
404230300Sjoerg	if (len > ntohs (h->len))
404330300Sjoerg		len = ntohs (h->len);
404430300Sjoerg
404530300Sjoerg	switch (h->type) {
404630300Sjoerg	/* challenge, failure and success are his authproto */
404730300Sjoerg	case CHAP_CHALLENGE:
404830300Sjoerg		value = 1 + (u_char*)(h+1);
404930300Sjoerg		value_len = value[-1];
405030300Sjoerg		name = value + value_len;
405130300Sjoerg		name_len = len - value_len - 5;
405230300Sjoerg		if (name_len < 0) {
405330300Sjoerg			if (debug) {
405430300Sjoerg				log(LOG_DEBUG,
405540008Sjoerg				    SPP_FMT "chap corrupted challenge "
405630300Sjoerg				    "<%s id=0x%x len=%d",
405740008Sjoerg				    SPP_ARGS(ifp),
405830300Sjoerg				    sppp_auth_type_name(PPP_CHAP, h->type),
405930300Sjoerg				    h->ident, ntohs(h->len));
406044145Sphk				sppp_print_bytes((u_char*) (h+1), len-4);
406169211Sphk				log(-1, ">\n");
406230300Sjoerg			}
406330300Sjoerg			break;
406430300Sjoerg		}
406570199Sjhay
406630300Sjoerg		if (debug) {
406730300Sjoerg			log(LOG_DEBUG,
406840008Sjoerg			    SPP_FMT "chap input <%s id=0x%x len=%d name=",
406940008Sjoerg			    SPP_ARGS(ifp),
407030300Sjoerg			    sppp_auth_type_name(PPP_CHAP, h->type), h->ident,
407130300Sjoerg			    ntohs(h->len));
407230300Sjoerg			sppp_print_string((char*) name, name_len);
407369211Sphk			log(-1, " value-size=%d value=", value_len);
407430300Sjoerg			sppp_print_bytes(value, value_len);
407569211Sphk			log(-1, ">\n");
407630300Sjoerg		}
407730300Sjoerg
407830300Sjoerg		/* Compute reply value. */
407930300Sjoerg		MD5Init(&ctx);
408030300Sjoerg		MD5Update(&ctx, &h->ident, 1);
408130300Sjoerg		MD5Update(&ctx, sp->myauth.secret,
408230300Sjoerg			  sppp_strnlen(sp->myauth.secret, AUTHKEYLEN));
408330300Sjoerg		MD5Update(&ctx, value, value_len);
408430300Sjoerg		MD5Final(digest, &ctx);
408530300Sjoerg		dsize = sizeof digest;
408630300Sjoerg
408730300Sjoerg		sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident,
408830300Sjoerg			       sizeof dsize, (const char *)&dsize,
408930300Sjoerg			       sizeof digest, digest,
409040008Sjoerg			       (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
409130300Sjoerg			       sp->myauth.name,
409230300Sjoerg			       0);
409330300Sjoerg		break;
409430300Sjoerg
409530300Sjoerg	case CHAP_SUCCESS:
409630300Sjoerg		if (debug) {
409740008Sjoerg			log(LOG_DEBUG, SPP_FMT "chap success",
409840008Sjoerg			    SPP_ARGS(ifp));
409930300Sjoerg			if (len > 4) {
410069211Sphk				log(-1, ": ");
410130300Sjoerg				sppp_print_string((char*)(h + 1), len - 4);
410230300Sjoerg			}
410369211Sphk			log(-1, "\n");
410430300Sjoerg		}
410530300Sjoerg		x = splimp();
4106138745Srik		SPPP_LOCK(sp);
410730300Sjoerg		sp->pp_flags &= ~PP_NEEDAUTH;
410830300Sjoerg		if (sp->myauth.proto == PPP_CHAP &&
410932169Sgj		    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) &&
411030300Sjoerg		    (sp->lcp.protos & (1 << IDX_CHAP)) == 0) {
411130300Sjoerg			/*
411230300Sjoerg			 * We are authenticator for CHAP but didn't
411330300Sjoerg			 * complete yet.  Leave it to tlu to proceed
411430300Sjoerg			 * to network phase.
411530300Sjoerg			 */
4116138745Srik			SPPP_UNLOCK(sp);
411730300Sjoerg			splx(x);
411830300Sjoerg			break;
411930300Sjoerg		}
4120138745Srik		SPPP_UNLOCK(sp);
412130300Sjoerg		splx(x);
412230300Sjoerg		sppp_phase_network(sp);
412330300Sjoerg		break;
412430300Sjoerg
412530300Sjoerg	case CHAP_FAILURE:
412630300Sjoerg		if (debug) {
412740008Sjoerg			log(LOG_INFO, SPP_FMT "chap failure",
412840008Sjoerg			    SPP_ARGS(ifp));
412930300Sjoerg			if (len > 4) {
413069211Sphk				log(-1, ": ");
413130300Sjoerg				sppp_print_string((char*)(h + 1), len - 4);
413230300Sjoerg			}
413369211Sphk			log(-1, "\n");
413430300Sjoerg		} else
413540008Sjoerg			log(LOG_INFO, SPP_FMT "chap failure\n",
413640008Sjoerg			    SPP_ARGS(ifp));
413730300Sjoerg		/* await LCP shutdown by authenticator */
413830300Sjoerg		break;
413930300Sjoerg
414030300Sjoerg	/* response is my authproto */
414130300Sjoerg	case CHAP_RESPONSE:
414230300Sjoerg		value = 1 + (u_char*)(h+1);
414330300Sjoerg		value_len = value[-1];
414430300Sjoerg		name = value + value_len;
414530300Sjoerg		name_len = len - value_len - 5;
414630300Sjoerg		if (name_len < 0) {
414730300Sjoerg			if (debug) {
414830300Sjoerg				log(LOG_DEBUG,
414940008Sjoerg				    SPP_FMT "chap corrupted response "
415030300Sjoerg				    "<%s id=0x%x len=%d",
415140008Sjoerg				    SPP_ARGS(ifp),
415230300Sjoerg				    sppp_auth_type_name(PPP_CHAP, h->type),
415330300Sjoerg				    h->ident, ntohs(h->len));
415444145Sphk				sppp_print_bytes((u_char*)(h+1), len-4);
415569211Sphk				log(-1, ">\n");
415630300Sjoerg			}
415730300Sjoerg			break;
415830300Sjoerg		}
415930300Sjoerg		if (h->ident != sp->confid[IDX_CHAP]) {
416030300Sjoerg			if (debug)
416130300Sjoerg				log(LOG_DEBUG,
416240008Sjoerg				    SPP_FMT "chap dropping response for old ID "
416330300Sjoerg				    "(got %d, expected %d)\n",
416440008Sjoerg				    SPP_ARGS(ifp),
416530300Sjoerg				    h->ident, sp->confid[IDX_CHAP]);
416630300Sjoerg			break;
416730300Sjoerg		}
416830300Sjoerg		if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)
416930300Sjoerg		    || bcmp(name, sp->hisauth.name, name_len) != 0) {
417040008Sjoerg			log(LOG_INFO, SPP_FMT "chap response, his name ",
417140008Sjoerg			    SPP_ARGS(ifp));
417230300Sjoerg			sppp_print_string(name, name_len);
417369211Sphk			log(-1, " != expected ");
417430300Sjoerg			sppp_print_string(sp->hisauth.name,
417530300Sjoerg					  sppp_strnlen(sp->hisauth.name, AUTHNAMELEN));
417669211Sphk			log(-1, "\n");
417770199Sjhay		}
417830300Sjoerg		if (debug) {
417940008Sjoerg			log(LOG_DEBUG, SPP_FMT "chap input(%s) "
418030300Sjoerg			    "<%s id=0x%x len=%d name=",
418140008Sjoerg			    SPP_ARGS(ifp),
418230300Sjoerg			    sppp_state_name(sp->state[IDX_CHAP]),
418330300Sjoerg			    sppp_auth_type_name(PPP_CHAP, h->type),
418430300Sjoerg			    h->ident, ntohs (h->len));
418530300Sjoerg			sppp_print_string((char*)name, name_len);
418669211Sphk			log(-1, " value-size=%d value=", value_len);
418730300Sjoerg			sppp_print_bytes(value, value_len);
418869211Sphk			log(-1, ">\n");
418930300Sjoerg		}
419030300Sjoerg		if (value_len != AUTHKEYLEN) {
419130300Sjoerg			if (debug)
419230300Sjoerg				log(LOG_DEBUG,
419340008Sjoerg				    SPP_FMT "chap bad hash value length: "
419430300Sjoerg				    "%d bytes, should be %d\n",
419540008Sjoerg				    SPP_ARGS(ifp), value_len,
419630300Sjoerg				    AUTHKEYLEN);
419730300Sjoerg			break;
419830300Sjoerg		}
419930300Sjoerg
420030300Sjoerg		MD5Init(&ctx);
420130300Sjoerg		MD5Update(&ctx, &h->ident, 1);
420230300Sjoerg		MD5Update(&ctx, sp->hisauth.secret,
420330300Sjoerg			  sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN));
420430300Sjoerg		MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN);
420530300Sjoerg		MD5Final(digest, &ctx);
420630300Sjoerg
420730300Sjoerg#define FAILMSG "Failed..."
420830300Sjoerg#define SUCCMSG "Welcome!"
420930300Sjoerg
421030300Sjoerg		if (value_len != sizeof digest ||
421130300Sjoerg		    bcmp(digest, value, value_len) != 0) {
421230300Sjoerg			/* action scn, tld */
421330300Sjoerg			sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident,
421430300Sjoerg				       sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
421530300Sjoerg				       0);
421630300Sjoerg			chap.tld(sp);
421730300Sjoerg			break;
421830300Sjoerg		}
421930300Sjoerg		/* action sca, perhaps tlu */
422030300Sjoerg		if (sp->state[IDX_CHAP] == STATE_REQ_SENT ||
422130300Sjoerg		    sp->state[IDX_CHAP] == STATE_OPENED)
422230300Sjoerg			sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident,
422330300Sjoerg				       sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
422430300Sjoerg				       0);
422530300Sjoerg		if (sp->state[IDX_CHAP] == STATE_REQ_SENT) {
422630300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_OPENED);
422730300Sjoerg			chap.tlu(sp);
422830300Sjoerg		}
422930300Sjoerg		break;
423030300Sjoerg
423130300Sjoerg	default:
423230300Sjoerg		/* Unknown CHAP packet type -- ignore. */
423330300Sjoerg		if (debug) {
423440008Sjoerg			log(LOG_DEBUG, SPP_FMT "chap unknown input(%s) "
423530300Sjoerg			    "<0x%x id=0x%xh len=%d",
423640008Sjoerg			    SPP_ARGS(ifp),
423730300Sjoerg			    sppp_state_name(sp->state[IDX_CHAP]),
423830300Sjoerg			    h->type, h->ident, ntohs(h->len));
423944145Sphk			sppp_print_bytes((u_char*)(h+1), len-4);
424069211Sphk			log(-1, ">\n");
424130300Sjoerg		}
424230300Sjoerg		break;
424330300Sjoerg
424430300Sjoerg	}
424530300Sjoerg}
424630300Sjoerg
424730300Sjoergstatic void
424830300Sjoergsppp_chap_init(struct sppp *sp)
424930300Sjoerg{
425030300Sjoerg	/* Chap doesn't have STATE_INITIAL at all. */
425130300Sjoerg	sp->state[IDX_CHAP] = STATE_CLOSED;
425230300Sjoerg	sp->fail_counter[IDX_CHAP] = 0;
425378064Sume	sp->pp_seq[IDX_CHAP] = 0;
425478064Sume	sp->pp_rseq[IDX_CHAP] = 0;
4255188668Srwatson 	callout_init(&sp->ch[IDX_CHAP], CALLOUT_MPSAFE);
425630300Sjoerg}
425730300Sjoerg
425830300Sjoergstatic void
425930300Sjoergsppp_chap_open(struct sppp *sp)
426030300Sjoerg{
426130300Sjoerg	if (sp->myauth.proto == PPP_CHAP &&
426230300Sjoerg	    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
426330300Sjoerg		/* we are authenticator for CHAP, start it */
426430300Sjoerg		chap.scr(sp);
426530300Sjoerg		sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
426630300Sjoerg		sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
426730300Sjoerg	}
426830300Sjoerg	/* nothing to be done if we are peer, await a challenge */
426930300Sjoerg}
427030300Sjoerg
427130300Sjoergstatic void
427230300Sjoergsppp_chap_close(struct sppp *sp)
427330300Sjoerg{
427430300Sjoerg	if (sp->state[IDX_CHAP] != STATE_CLOSED)
427530300Sjoerg		sppp_cp_change_state(&chap, sp, STATE_CLOSED);
427630300Sjoerg}
427730300Sjoerg
427830300Sjoergstatic void
427930300Sjoergsppp_chap_TO(void *cookie)
428030300Sjoerg{
428130300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
428230300Sjoerg	STDDCL;
428330300Sjoerg	int s;
428430300Sjoerg
428530300Sjoerg	s = splimp();
4286138745Srik	SPPP_LOCK(sp);
428730300Sjoerg	if (debug)
428840008Sjoerg		log(LOG_DEBUG, SPP_FMT "chap TO(%s) rst_counter = %d\n",
428940008Sjoerg		    SPP_ARGS(ifp),
429030300Sjoerg		    sppp_state_name(sp->state[IDX_CHAP]),
429130300Sjoerg		    sp->rst_counter[IDX_CHAP]);
429230300Sjoerg
429330300Sjoerg	if (--sp->rst_counter[IDX_CHAP] < 0)
429430300Sjoerg		/* TO- event */
429530300Sjoerg		switch (sp->state[IDX_CHAP]) {
429630300Sjoerg		case STATE_REQ_SENT:
429730300Sjoerg			chap.tld(sp);
429830300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_CLOSED);
429930300Sjoerg			break;
430030300Sjoerg		}
430130300Sjoerg	else
430230300Sjoerg		/* TO+ (or TO*) event */
430330300Sjoerg		switch (sp->state[IDX_CHAP]) {
430430300Sjoerg		case STATE_OPENED:
430530300Sjoerg			/* TO* event */
430630300Sjoerg			sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
4307102412Scharnier			/* FALLTHROUGH */
430830300Sjoerg		case STATE_REQ_SENT:
430930300Sjoerg			chap.scr(sp);
431030300Sjoerg			/* sppp_cp_change_state() will restart the timer */
431130300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
431230300Sjoerg			break;
431330300Sjoerg		}
431430300Sjoerg
4315138745Srik	SPPP_UNLOCK(sp);
431630300Sjoerg	splx(s);
431730300Sjoerg}
431830300Sjoerg
431930300Sjoergstatic void
432030300Sjoergsppp_chap_tlu(struct sppp *sp)
432130300Sjoerg{
432230300Sjoerg	STDDCL;
432330300Sjoerg	int i, x;
432430300Sjoerg
432540010Sjoerg	i = 0;
432630300Sjoerg	sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
432730300Sjoerg
432830300Sjoerg	/*
432930300Sjoerg	 * Some broken CHAP implementations (Conware CoNet, firmware
433030300Sjoerg	 * 4.0.?) don't want to re-authenticate their CHAP once the
433130300Sjoerg	 * initial challenge-response exchange has taken place.
433230300Sjoerg	 * Provide for an option to avoid rechallenges.
433330300Sjoerg	 */
433430300Sjoerg	if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) {
433530300Sjoerg		/*
433630300Sjoerg		 * Compute the re-challenge timeout.  This will yield
433730300Sjoerg		 * a number between 300 and 810 seconds.
433830300Sjoerg		 */
433930300Sjoerg		i = 300 + ((unsigned)(random() & 0xff00) >> 7);
4340138745Srik		callout_reset(&sp->ch[IDX_CHAP], i * hz, chap.TO, (void *)sp);
434130300Sjoerg	}
434230300Sjoerg
434330300Sjoerg	if (debug) {
434430300Sjoerg		log(LOG_DEBUG,
434540008Sjoerg		    SPP_FMT "chap %s, ",
434640008Sjoerg		    SPP_ARGS(ifp),
434730300Sjoerg		    sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu");
434830300Sjoerg		if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0)
434969211Sphk			log(-1, "next re-challenge in %d seconds\n", i);
435030300Sjoerg		else
435169211Sphk			log(-1, "re-challenging supressed\n");
435230300Sjoerg	}
435330300Sjoerg
435430300Sjoerg	x = splimp();
4355138745Srik	SPPP_LOCK(sp);
435630300Sjoerg	/* indicate to LCP that we need to be closed down */
435730300Sjoerg	sp->lcp.protos |= (1 << IDX_CHAP);
435830300Sjoerg
435930300Sjoerg	if (sp->pp_flags & PP_NEEDAUTH) {
436030300Sjoerg		/*
436130300Sjoerg		 * Remote is authenticator, but his auth proto didn't
436230300Sjoerg		 * complete yet.  Defer the transition to network
436330300Sjoerg		 * phase.
436430300Sjoerg		 */
4365138745Srik		SPPP_UNLOCK(sp);
436630300Sjoerg		splx(x);
436730300Sjoerg		return;
436830300Sjoerg	}
4369138745Srik	SPPP_UNLOCK(sp);
437030300Sjoerg	splx(x);
437130300Sjoerg
437230300Sjoerg	/*
437330300Sjoerg	 * If we are already in phase network, we are done here.  This
437430300Sjoerg	 * is the case if this is a dummy tlu event after a re-challenge.
437530300Sjoerg	 */
437630300Sjoerg	if (sp->pp_phase != PHASE_NETWORK)
437730300Sjoerg		sppp_phase_network(sp);
437830300Sjoerg}
437930300Sjoerg
438030300Sjoergstatic void
438130300Sjoergsppp_chap_tld(struct sppp *sp)
438230300Sjoerg{
438330300Sjoerg	STDDCL;
438430300Sjoerg
438530300Sjoerg	if (debug)
438640008Sjoerg		log(LOG_DEBUG, SPP_FMT "chap tld\n", SPP_ARGS(ifp));
4387138745Srik	callout_stop(&sp->ch[IDX_CHAP]);
438830300Sjoerg	sp->lcp.protos &= ~(1 << IDX_CHAP);
438930300Sjoerg
439030300Sjoerg	lcp.Close(sp);
439130300Sjoerg}
439230300Sjoerg
439330300Sjoergstatic void
439430300Sjoergsppp_chap_scr(struct sppp *sp)
439530300Sjoerg{
439630300Sjoerg	u_long *ch, seed;
439730300Sjoerg	u_char clen;
439830300Sjoerg
439930300Sjoerg	/* Compute random challenge. */
440030300Sjoerg	ch = (u_long *)sp->myauth.challenge;
440135064Sphk	read_random(&seed, sizeof seed);
440230300Sjoerg	ch[0] = seed ^ random();
440330300Sjoerg	ch[1] = seed ^ random();
440430300Sjoerg	ch[2] = seed ^ random();
440530300Sjoerg	ch[3] = seed ^ random();
440630300Sjoerg	clen = AUTHKEYLEN;
440730300Sjoerg
440878064Sume	sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP];
440930300Sjoerg
441030300Sjoerg	sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP],
441130300Sjoerg		       sizeof clen, (const char *)&clen,
441240008Sjoerg		       (size_t)AUTHKEYLEN, sp->myauth.challenge,
441340008Sjoerg		       (size_t)sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
441430300Sjoerg		       sp->myauth.name,
441530300Sjoerg		       0);
441630300Sjoerg}
441770199Sjhay
441870199Sjhay/*
441930300Sjoerg *--------------------------------------------------------------------------*
442030300Sjoerg *                                                                          *
442130300Sjoerg *                        The PAP implementation.                           *
442230300Sjoerg *                                                                          *
442330300Sjoerg *--------------------------------------------------------------------------*
442430300Sjoerg */
442530300Sjoerg/*
442630300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the
442730300Sjoerg * authenticator.  This is since we don't get a request to authenticate, but
442830300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the
442930300Sjoerg * retry counter is expired).
443030300Sjoerg */
443130300Sjoerg
443230300Sjoerg/*
443330300Sjoerg * Handle incoming PAP packets.  */
443430300Sjoergstatic void
443530300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m)
443630300Sjoerg{
443730300Sjoerg	STDDCL;
443830300Sjoerg	struct lcp_header *h;
443930300Sjoerg	int len, x;
444030300Sjoerg	u_char *name, *passwd, mlen;
444130300Sjoerg	int name_len, passwd_len;
444230300Sjoerg
444330300Sjoerg	len = m->m_pkthdr.len;
444430300Sjoerg	if (len < 5) {
444530300Sjoerg		if (debug)
444630300Sjoerg			log(LOG_DEBUG,
444740008Sjoerg			    SPP_FMT "pap invalid packet length: %d bytes\n",
444840008Sjoerg			    SPP_ARGS(ifp), len);
444930300Sjoerg		return;
445030300Sjoerg	}
445130300Sjoerg	h = mtod (m, struct lcp_header*);
445230300Sjoerg	if (len > ntohs (h->len))
445330300Sjoerg		len = ntohs (h->len);
445430300Sjoerg	switch (h->type) {
445530300Sjoerg	/* PAP request is my authproto */
445630300Sjoerg	case PAP_REQ:
445730300Sjoerg		name = 1 + (u_char*)(h+1);
445830300Sjoerg		name_len = name[-1];
445930300Sjoerg		passwd = name + name_len + 1;
446030300Sjoerg		if (name_len > len - 6 ||
446130300Sjoerg		    (passwd_len = passwd[-1]) > len - 6 - name_len) {
446230300Sjoerg			if (debug) {
446340008Sjoerg				log(LOG_DEBUG, SPP_FMT "pap corrupted input "
446430300Sjoerg				    "<%s id=0x%x len=%d",
446540008Sjoerg				    SPP_ARGS(ifp),
446630300Sjoerg				    sppp_auth_type_name(PPP_PAP, h->type),
446730300Sjoerg				    h->ident, ntohs(h->len));
446844145Sphk				sppp_print_bytes((u_char*)(h+1), len-4);
446969211Sphk				log(-1, ">\n");
447030300Sjoerg			}
447130300Sjoerg			break;
447230300Sjoerg		}
447330300Sjoerg		if (debug) {
447440008Sjoerg			log(LOG_DEBUG, SPP_FMT "pap input(%s) "
447530300Sjoerg			    "<%s id=0x%x len=%d name=",
447640008Sjoerg			    SPP_ARGS(ifp),
447730300Sjoerg			    sppp_state_name(sp->state[IDX_PAP]),
447830300Sjoerg			    sppp_auth_type_name(PPP_PAP, h->type),
447930300Sjoerg			    h->ident, ntohs(h->len));
448030300Sjoerg			sppp_print_string((char*)name, name_len);
448169211Sphk			log(-1, " passwd=");
448230300Sjoerg			sppp_print_string((char*)passwd, passwd_len);
448369211Sphk			log(-1, ">\n");
448430300Sjoerg		}
448574774Sjoerg		if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN) ||
448674774Sjoerg		    passwd_len != sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN) ||
448730300Sjoerg		    bcmp(name, sp->hisauth.name, name_len) != 0 ||
448830300Sjoerg		    bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) {
448930300Sjoerg			/* action scn, tld */
449030300Sjoerg			mlen = sizeof(FAILMSG) - 1;
449130300Sjoerg			sppp_auth_send(&pap, sp, PAP_NAK, h->ident,
449230300Sjoerg				       sizeof mlen, (const char *)&mlen,
449330300Sjoerg				       sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
449430300Sjoerg				       0);
449530300Sjoerg			pap.tld(sp);
449630300Sjoerg			break;
449730300Sjoerg		}
449830300Sjoerg		/* action sca, perhaps tlu */
449930300Sjoerg		if (sp->state[IDX_PAP] == STATE_REQ_SENT ||
450030300Sjoerg		    sp->state[IDX_PAP] == STATE_OPENED) {
450130300Sjoerg			mlen = sizeof(SUCCMSG) - 1;
450230300Sjoerg			sppp_auth_send(&pap, sp, PAP_ACK, h->ident,
450330300Sjoerg				       sizeof mlen, (const char *)&mlen,
450430300Sjoerg				       sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
450530300Sjoerg				       0);
450630300Sjoerg		}
450730300Sjoerg		if (sp->state[IDX_PAP] == STATE_REQ_SENT) {
450830300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_OPENED);
450930300Sjoerg			pap.tlu(sp);
451030300Sjoerg		}
451130300Sjoerg		break;
451230300Sjoerg
451330300Sjoerg	/* ack and nak are his authproto */
451430300Sjoerg	case PAP_ACK:
4515138745Srik		callout_stop(&sp->pap_my_to_ch);
451630300Sjoerg		if (debug) {
451740008Sjoerg			log(LOG_DEBUG, SPP_FMT "pap success",
451840008Sjoerg			    SPP_ARGS(ifp));
451930300Sjoerg			name_len = *((char *)h);
452030300Sjoerg			if (len > 5 && name_len) {
452169211Sphk				log(-1, ": ");
452230300Sjoerg				sppp_print_string((char*)(h+1), name_len);
452330300Sjoerg			}
452469211Sphk			log(-1, "\n");
452530300Sjoerg		}
452630300Sjoerg		x = splimp();
4527138745Srik		SPPP_LOCK(sp);
452830300Sjoerg		sp->pp_flags &= ~PP_NEEDAUTH;
452930300Sjoerg		if (sp->myauth.proto == PPP_PAP &&
453032169Sgj		    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) &&
453130300Sjoerg		    (sp->lcp.protos & (1 << IDX_PAP)) == 0) {
453230300Sjoerg			/*
453330300Sjoerg			 * We are authenticator for PAP but didn't
453430300Sjoerg			 * complete yet.  Leave it to tlu to proceed
453530300Sjoerg			 * to network phase.
453630300Sjoerg			 */
4537138745Srik			SPPP_UNLOCK(sp);
453830300Sjoerg			splx(x);
453930300Sjoerg			break;
454030300Sjoerg		}
4541138745Srik		SPPP_UNLOCK(sp);
454230300Sjoerg		splx(x);
454330300Sjoerg		sppp_phase_network(sp);
454430300Sjoerg		break;
454530300Sjoerg
454630300Sjoerg	case PAP_NAK:
4547138745Srik		callout_stop (&sp->pap_my_to_ch);
454830300Sjoerg		if (debug) {
454940008Sjoerg			log(LOG_INFO, SPP_FMT "pap failure",
455040008Sjoerg			    SPP_ARGS(ifp));
455130300Sjoerg			name_len = *((char *)h);
455230300Sjoerg			if (len > 5 && name_len) {
455369211Sphk				log(-1, ": ");
455430300Sjoerg				sppp_print_string((char*)(h+1), name_len);
455530300Sjoerg			}
455669211Sphk			log(-1, "\n");
455730300Sjoerg		} else
455840008Sjoerg			log(LOG_INFO, SPP_FMT "pap failure\n",
455940008Sjoerg			    SPP_ARGS(ifp));
456030300Sjoerg		/* await LCP shutdown by authenticator */
456130300Sjoerg		break;
456230300Sjoerg
456330300Sjoerg	default:
456430300Sjoerg		/* Unknown PAP packet type -- ignore. */
456530300Sjoerg		if (debug) {
456640008Sjoerg			log(LOG_DEBUG, SPP_FMT "pap corrupted input "
456730300Sjoerg			    "<0x%x id=0x%x len=%d",
456840008Sjoerg			    SPP_ARGS(ifp),
456930300Sjoerg			    h->type, h->ident, ntohs(h->len));
457044145Sphk			sppp_print_bytes((u_char*)(h+1), len-4);
457169211Sphk			log(-1, ">\n");
457230300Sjoerg		}
457330300Sjoerg		break;
457430300Sjoerg
457530300Sjoerg	}
457630300Sjoerg}
457730300Sjoerg
457830300Sjoergstatic void
457930300Sjoergsppp_pap_init(struct sppp *sp)
458030300Sjoerg{
458130300Sjoerg	/* PAP doesn't have STATE_INITIAL at all. */
458230300Sjoerg	sp->state[IDX_PAP] = STATE_CLOSED;
458330300Sjoerg	sp->fail_counter[IDX_PAP] = 0;
458478064Sume	sp->pp_seq[IDX_PAP] = 0;
458578064Sume	sp->pp_rseq[IDX_PAP] = 0;
4586188668Srwatson 	callout_init(&sp->ch[IDX_PAP], CALLOUT_MPSAFE);
4587188668Srwatson 	callout_init(&sp->pap_my_to_ch, CALLOUT_MPSAFE);
458830300Sjoerg}
458930300Sjoerg
459030300Sjoergstatic void
459130300Sjoergsppp_pap_open(struct sppp *sp)
459230300Sjoerg{
459330300Sjoerg	if (sp->hisauth.proto == PPP_PAP &&
459430300Sjoerg	    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
459530300Sjoerg		/* we are authenticator for PAP, start our timer */
459630300Sjoerg		sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
459730300Sjoerg		sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
459830300Sjoerg	}
459930300Sjoerg	if (sp->myauth.proto == PPP_PAP) {
460030300Sjoerg		/* we are peer, send a request, and start a timer */
460130300Sjoerg		pap.scr(sp);
4602138745Srik		callout_reset(&sp->pap_my_to_ch, sp->lcp.timeout,
4603138745Srik			      sppp_pap_my_TO, (void *)sp);
460430300Sjoerg	}
460530300Sjoerg}
460630300Sjoerg
460730300Sjoergstatic void
460830300Sjoergsppp_pap_close(struct sppp *sp)
460930300Sjoerg{
461030300Sjoerg	if (sp->state[IDX_PAP] != STATE_CLOSED)
461130300Sjoerg		sppp_cp_change_state(&pap, sp, STATE_CLOSED);
461230300Sjoerg}
461330300Sjoerg
461430300Sjoerg/*
461530300Sjoerg * That's the timeout routine if we are authenticator.  Since the
461630300Sjoerg * authenticator is basically passive in PAP, we can't do much here.
461730300Sjoerg */
461830300Sjoergstatic void
461930300Sjoergsppp_pap_TO(void *cookie)
462030300Sjoerg{
462130300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
462230300Sjoerg	STDDCL;
462330300Sjoerg	int s;
462430300Sjoerg
462530300Sjoerg	s = splimp();
4626138745Srik	SPPP_LOCK(sp);
462730300Sjoerg	if (debug)
462840008Sjoerg		log(LOG_DEBUG, SPP_FMT "pap TO(%s) rst_counter = %d\n",
462940008Sjoerg		    SPP_ARGS(ifp),
463030300Sjoerg		    sppp_state_name(sp->state[IDX_PAP]),
463130300Sjoerg		    sp->rst_counter[IDX_PAP]);
463230300Sjoerg
463330300Sjoerg	if (--sp->rst_counter[IDX_PAP] < 0)
463430300Sjoerg		/* TO- event */
463530300Sjoerg		switch (sp->state[IDX_PAP]) {
463630300Sjoerg		case STATE_REQ_SENT:
463730300Sjoerg			pap.tld(sp);
463830300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_CLOSED);
463930300Sjoerg			break;
464030300Sjoerg		}
464130300Sjoerg	else
464230300Sjoerg		/* TO+ event, not very much we could do */
464330300Sjoerg		switch (sp->state[IDX_PAP]) {
464430300Sjoerg		case STATE_REQ_SENT:
464530300Sjoerg			/* sppp_cp_change_state() will restart the timer */
464630300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
464730300Sjoerg			break;
464830300Sjoerg		}
464930300Sjoerg
4650138745Srik	SPPP_UNLOCK(sp);
465130300Sjoerg	splx(s);
465230300Sjoerg}
465330300Sjoerg
465430300Sjoerg/*
465530300Sjoerg * That's the timeout handler if we are peer.  Since the peer is active,
465630300Sjoerg * we need to retransmit our PAP request since it is apparently lost.
465730300Sjoerg * XXX We should impose a max counter.
465830300Sjoerg */
465930300Sjoergstatic void
466030300Sjoergsppp_pap_my_TO(void *cookie)
466130300Sjoerg{
466230300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
466330300Sjoerg	STDDCL;
466430300Sjoerg
466530300Sjoerg	if (debug)
466640008Sjoerg		log(LOG_DEBUG, SPP_FMT "pap peer TO\n",
466740008Sjoerg		    SPP_ARGS(ifp));
466830300Sjoerg
4669138745Srik	SPPP_LOCK(sp);
467030300Sjoerg	pap.scr(sp);
4671138745Srik	SPPP_UNLOCK(sp);
467230300Sjoerg}
467330300Sjoerg
467430300Sjoergstatic void
467530300Sjoergsppp_pap_tlu(struct sppp *sp)
467630300Sjoerg{
467730300Sjoerg	STDDCL;
467830300Sjoerg	int x;
467930300Sjoerg
468030300Sjoerg	sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
468130300Sjoerg
468230300Sjoerg	if (debug)
468340008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s tlu\n",
468440008Sjoerg		    SPP_ARGS(ifp), pap.name);
468530300Sjoerg
468630300Sjoerg	x = splimp();
4687138745Srik	SPPP_LOCK(sp);
468830300Sjoerg	/* indicate to LCP that we need to be closed down */
468930300Sjoerg	sp->lcp.protos |= (1 << IDX_PAP);
469030300Sjoerg
469130300Sjoerg	if (sp->pp_flags & PP_NEEDAUTH) {
469230300Sjoerg		/*
469330300Sjoerg		 * Remote is authenticator, but his auth proto didn't
469430300Sjoerg		 * complete yet.  Defer the transition to network
469530300Sjoerg		 * phase.
469630300Sjoerg		 */
4697138745Srik		SPPP_UNLOCK(sp);
469830300Sjoerg		splx(x);
469930300Sjoerg		return;
470030300Sjoerg	}
4701138745Srik	SPPP_UNLOCK(sp);
470230300Sjoerg	splx(x);
470330300Sjoerg	sppp_phase_network(sp);
470430300Sjoerg}
470530300Sjoerg
470630300Sjoergstatic void
470730300Sjoergsppp_pap_tld(struct sppp *sp)
470830300Sjoerg{
470930300Sjoerg	STDDCL;
471030300Sjoerg
471130300Sjoerg	if (debug)
471240008Sjoerg		log(LOG_DEBUG, SPP_FMT "pap tld\n", SPP_ARGS(ifp));
4713138745Srik	callout_stop (&sp->ch[IDX_PAP]);
4714138745Srik	callout_stop (&sp->pap_my_to_ch);
471530300Sjoerg	sp->lcp.protos &= ~(1 << IDX_PAP);
471630300Sjoerg
471730300Sjoerg	lcp.Close(sp);
471830300Sjoerg}
471930300Sjoerg
472030300Sjoergstatic void
472130300Sjoergsppp_pap_scr(struct sppp *sp)
472230300Sjoerg{
472330300Sjoerg	u_char idlen, pwdlen;
472430300Sjoerg
472578064Sume	sp->confid[IDX_PAP] = ++sp->pp_seq[IDX_PAP];
472630300Sjoerg	pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN);
472730300Sjoerg	idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN);
472830300Sjoerg
472930300Sjoerg	sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP],
473030300Sjoerg		       sizeof idlen, (const char *)&idlen,
473140008Sjoerg		       (size_t)idlen, sp->myauth.name,
473230300Sjoerg		       sizeof pwdlen, (const char *)&pwdlen,
473340008Sjoerg		       (size_t)pwdlen, sp->myauth.secret,
473430300Sjoerg		       0);
473530300Sjoerg}
473670199Sjhay
473770199Sjhay/*
473825944Sjoerg * Random miscellaneous functions.
473925944Sjoerg */
474025944Sjoerg
47414910Swollman/*
474230300Sjoerg * Send a PAP or CHAP proto packet.
474330300Sjoerg *
474430300Sjoerg * Varadic function, each of the elements for the ellipsis is of type
474540008Sjoerg * ``size_t mlen, const u_char *msg''.  Processing will stop iff
474630300Sjoerg * mlen == 0.
474742104Sphk * NOTE: never declare variadic functions with types subject to type
474842104Sphk * promotion (i.e. u_char). This is asking for big trouble depending
474942104Sphk * on the architecture you are on...
475030300Sjoerg */
475130300Sjoerg
475230300Sjoergstatic void
475342104Sphksppp_auth_send(const struct cp *cp, struct sppp *sp,
475442104Sphk               unsigned int type, unsigned int id,
475530300Sjoerg	       ...)
475630300Sjoerg{
475730300Sjoerg	STDDCL;
475830300Sjoerg	struct ppp_header *h;
475930300Sjoerg	struct lcp_header *lh;
476030300Sjoerg	struct mbuf *m;
476130300Sjoerg	u_char *p;
476230300Sjoerg	int len;
476342104Sphk	unsigned int mlen;
476430300Sjoerg	const char *msg;
476530300Sjoerg	va_list ap;
476630300Sjoerg
4767111119Simp	MGETHDR (m, M_DONTWAIT, MT_DATA);
476830300Sjoerg	if (! m)
476930300Sjoerg		return;
477030300Sjoerg	m->m_pkthdr.rcvif = 0;
477130300Sjoerg
477230300Sjoerg	h = mtod (m, struct ppp_header*);
477330300Sjoerg	h->address = PPP_ALLSTATIONS;		/* broadcast address */
477430300Sjoerg	h->control = PPP_UI;			/* Unnumbered Info */
477530300Sjoerg	h->protocol = htons(cp->proto);
477630300Sjoerg
477730300Sjoerg	lh = (struct lcp_header*)(h + 1);
477830300Sjoerg	lh->type = type;
477930300Sjoerg	lh->ident = id;
478030300Sjoerg	p = (u_char*) (lh+1);
478130300Sjoerg
478230300Sjoerg	va_start(ap, id);
478330300Sjoerg	len = 0;
478430300Sjoerg
478542104Sphk	while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) {
478630300Sjoerg		msg = va_arg(ap, const char *);
478730300Sjoerg		len += mlen;
478830300Sjoerg		if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) {
478930300Sjoerg			va_end(ap);
479030300Sjoerg			m_freem(m);
479130300Sjoerg			return;
479230300Sjoerg		}
479330300Sjoerg
479430300Sjoerg		bcopy(msg, p, mlen);
479530300Sjoerg		p += mlen;
479630300Sjoerg	}
479730300Sjoerg	va_end(ap);
479830300Sjoerg
479930300Sjoerg	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;
480030300Sjoerg	lh->len = htons (LCP_HEADER_LEN + len);
480130300Sjoerg
480230300Sjoerg	if (debug) {
480340008Sjoerg		log(LOG_DEBUG, SPP_FMT "%s output <%s id=0x%x len=%d",
480440008Sjoerg		    SPP_ARGS(ifp), cp->name,
480530300Sjoerg		    sppp_auth_type_name(cp->proto, lh->type),
480630300Sjoerg		    lh->ident, ntohs(lh->len));
480744145Sphk		sppp_print_bytes((u_char*) (lh+1), len);
480869211Sphk		log(-1, ">\n");
480930300Sjoerg	}
481069152Sjlemon	if (! IF_HANDOFF_ADJ(&sp->pp_cpq, m, ifp, 3))
481169152Sjlemon		ifp->if_oerrors++;
481230300Sjoerg}
481330300Sjoerg
481430300Sjoerg/*
481525944Sjoerg * Flush interface queue.
48164910Swollman */
481712820Sphkstatic void
481825944Sjoergsppp_qflush(struct ifqueue *ifq)
48194910Swollman{
482025944Sjoerg	struct mbuf *m, *n;
48214910Swollman
482225944Sjoerg	n = ifq->ifq_head;
482325944Sjoerg	while ((m = n)) {
482425944Sjoerg		n = m->m_act;
482525944Sjoerg		m_freem (m);
482611189Sjkh	}
482725944Sjoerg	ifq->ifq_head = 0;
482825944Sjoerg	ifq->ifq_tail = 0;
482925944Sjoerg	ifq->ifq_len = 0;
483025944Sjoerg}
483125944Sjoerg
483225944Sjoerg/*
483325944Sjoerg * Send keepalive packets, every 10 seconds.
483425944Sjoerg */
483525944Sjoergstatic void
483625944Sjoergsppp_keepalive(void *dummy)
483725944Sjoerg{
4838138745Srik	struct sppp *sp = (struct sppp*)dummy;
4839147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
484025944Sjoerg	int s;
484125944Sjoerg
484225944Sjoerg	s = splimp();
4843138745Srik	SPPP_LOCK(sp);
4844138745Srik	/* Keepalive mode disabled or channel down? */
4845138745Srik	if (! (sp->pp_flags & PP_KEEPALIVE) ||
4846148887Srwatson	    ! (ifp->if_drv_flags & IFF_DRV_RUNNING))
4847138745Srik		goto out;
484825944Sjoerg
4849139365Srik	if (sp->pp_mode == PP_FR) {
4850139365Srik		sppp_fr_keepalive (sp);
4851139365Srik		goto out;
4852139365Srik	}
4853139365Srik
4854138745Srik	/* No keepalive in PPP mode if LCP not opened yet. */
4855138745Srik	if (sp->pp_mode != IFF_CISCO &&
4856138745Srik	    sp->pp_phase < PHASE_AUTHENTICATE)
4857138745Srik		goto out;
485825944Sjoerg
4859138745Srik	if (sp->pp_alivecnt == MAXALIVECNT) {
4860138745Srik		/* No keepalive packets got.  Stop the interface. */
4861138745Srik		printf (SPP_FMT "down\n", SPP_ARGS(ifp));
4862138745Srik		if_down (ifp);
4863138745Srik		sppp_qflush (&sp->pp_cpq);
4864138745Srik		if (sp->pp_mode != IFF_CISCO) {
4865138745Srik			/* XXX */
4866138745Srik			/* Shut down the PPP link. */
4867138745Srik			lcp.Down(sp);
4868138745Srik			/* Initiate negotiation. XXX */
4869138745Srik			lcp.Up(sp);
48704910Swollman		}
48714910Swollman	}
4872138745Srik	if (sp->pp_alivecnt <= MAXALIVECNT)
4873138745Srik		++sp->pp_alivecnt;
4874138745Srik	if (sp->pp_mode == IFF_CISCO)
4875138745Srik		sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ,
4876138745Srik			 ++sp->pp_seq[IDX_LCP],	sp->pp_rseq[IDX_LCP]);
4877138745Srik	else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
4878138745Srik		long nmagic = htonl (sp->lcp.magic);
4879138745Srik		sp->lcp.echoid = ++sp->pp_seq[IDX_LCP];
4880138745Srik		sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
4881138745Srik			sp->lcp.echoid, 4, &nmagic);
4882138745Srik	}
4883138745Srikout:
4884138745Srik	SPPP_UNLOCK(sp);
488525944Sjoerg	splx(s);
4886138745Srik 	callout_reset(&sp->keepalive_callout, hz * 10, sppp_keepalive,
4887138745Srik		      (void *)sp);
48884910Swollman}
48894910Swollman
489025944Sjoerg/*
489125944Sjoerg * Get both IP addresses.
489225944Sjoerg */
4893139365Srikvoid
489430300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask)
489525944Sjoerg{
4896147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
489725944Sjoerg	struct ifaddr *ifa;
489830300Sjoerg	struct sockaddr_in *si, *sm;
489925944Sjoerg	u_long ssrc, ddst;
490025944Sjoerg
490140010Sjoerg	sm = NULL;
490225944Sjoerg	ssrc = ddst = 0L;
490325944Sjoerg	/*
490425944Sjoerg	 * Pick the first AF_INET address from the list,
490525944Sjoerg	 * aliases don't make any sense on a p2p link anyway.
490625944Sjoerg	 */
490742065Sphk	si = 0;
4908194813Srwatson	IF_ADDR_LOCK(ifp);
490942065Sphk	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
491025944Sjoerg		if (ifa->ifa_addr->sa_family == AF_INET) {
491125944Sjoerg			si = (struct sockaddr_in *)ifa->ifa_addr;
491230300Sjoerg			sm = (struct sockaddr_in *)ifa->ifa_netmask;
491325944Sjoerg			if (si)
491425944Sjoerg				break;
491525944Sjoerg		}
491625944Sjoerg	if (ifa) {
491730300Sjoerg		if (si && si->sin_addr.s_addr) {
491825944Sjoerg			ssrc = si->sin_addr.s_addr;
491930300Sjoerg			if (srcmask)
492030300Sjoerg				*srcmask = ntohl(sm->sin_addr.s_addr);
492130300Sjoerg		}
492225944Sjoerg
492325944Sjoerg		si = (struct sockaddr_in *)ifa->ifa_dstaddr;
492425944Sjoerg		if (si && si->sin_addr.s_addr)
492525944Sjoerg			ddst = si->sin_addr.s_addr;
492625944Sjoerg	}
4927194813Srwatson	IF_ADDR_UNLOCK(ifp);
492825944Sjoerg
492925944Sjoerg	if (dst) *dst = ntohl(ddst);
493025944Sjoerg	if (src) *src = ntohl(ssrc);
493125944Sjoerg}
493225944Sjoerg
4933184682Sbz#ifdef INET
493425944Sjoerg/*
493525944Sjoerg * Set my IP address.  Must be called at splimp.
493625944Sjoerg */
493725944Sjoergstatic void
493825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src)
493925944Sjoerg{
4940183550Szec	INIT_VNET_INET(curvnet);
494142104Sphk	STDDCL;
494225944Sjoerg	struct ifaddr *ifa;
494325944Sjoerg	struct sockaddr_in *si;
494484318Sjlemon	struct in_ifaddr *ia;
494525944Sjoerg
494625944Sjoerg	/*
494725944Sjoerg	 * Pick the first AF_INET address from the list,
494825944Sjoerg	 * aliases don't make any sense on a p2p link anyway.
494925944Sjoerg	 */
495042065Sphk	si = 0;
4951194813Srwatson	IF_ADDR_LOCK(ifp);
4952194813Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
4953194813Srwatson		if (ifa->ifa_addr->sa_family == AF_INET) {
495425944Sjoerg			si = (struct sockaddr_in *)ifa->ifa_addr;
4955194813Srwatson			if (si != NULL) {
4956194813Srwatson				ifa_ref(ifa);
495725944Sjoerg				break;
4958194813Srwatson			}
495925944Sjoerg		}
496040008Sjoerg	}
4961194813Srwatson	IF_ADDR_UNLOCK(ifp);
496240008Sjoerg
4963194813Srwatson	if (ifa != NULL) {
496442104Sphk		int error;
4965194813Srwatson
496642104Sphk		/* delete old route */
496742104Sphk		error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST);
4968194813Srwatson		if (debug && error) {
496942104Sphk			log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n",
497042104Sphk		    		SPP_ARGS(ifp), error);
497142104Sphk		}
497242104Sphk
497342104Sphk		/* set new address */
497425944Sjoerg		si->sin_addr.s_addr = htonl(src);
497584318Sjlemon		ia = ifatoia(ifa);
4976194951Srwatson		IN_IFADDR_WLOCK();
497784318Sjlemon		LIST_REMOVE(ia, ia_hash);
497884318Sjlemon		LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash);
4979194951Srwatson		IN_IFADDR_WUNLOCK();
498025944Sjoerg
498142104Sphk		/* add new route */
498270199Sjhay		error = rtinit(ifa, (int)RTM_ADD, RTF_HOST);
4983194813Srwatson		if (debug && error) {
498442104Sphk			log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d",
498542104Sphk		    		SPP_ARGS(ifp), error);
498642104Sphk		}
4987194813Srwatson		ifa_free(ifa);
498842104Sphk	}
498988599Sjoerg}
4990184682Sbz#endif
499178064Sume
499278064Sume#ifdef INET6
499378064Sume/*
499478064Sume * Get both IPv6 addresses.
499578064Sume */
499678064Sumestatic void
499778064Sumesppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst,
499878064Sume		   struct in6_addr *srcmask)
499978064Sume{
5000147256Sbrooks	struct ifnet *ifp = SP2IFP(sp);
500178064Sume	struct ifaddr *ifa;
500278064Sume	struct sockaddr_in6 *si, *sm;
500378064Sume	struct in6_addr ssrc, ddst;
500478064Sume
500578064Sume	sm = NULL;
500678064Sume	bzero(&ssrc, sizeof(ssrc));
500778064Sume	bzero(&ddst, sizeof(ddst));
500878064Sume	/*
500978064Sume	 * Pick the first link-local AF_INET6 address from the list,
501078064Sume	 * aliases don't make any sense on a p2p link anyway.
501178064Sume	 */
5012194813Srwatson	si = NULL;
5013194813Srwatson	IF_ADDR_LOCK(ifp);
5014160377Sbrooks	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
501578064Sume		if (ifa->ifa_addr->sa_family == AF_INET6) {
501678064Sume			si = (struct sockaddr_in6 *)ifa->ifa_addr;
501778064Sume			sm = (struct sockaddr_in6 *)ifa->ifa_netmask;
501878064Sume			if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr))
501978064Sume				break;
502078064Sume		}
502178064Sume	if (ifa) {
502278064Sume		if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) {
502378064Sume			bcopy(&si->sin6_addr, &ssrc, sizeof(ssrc));
502478064Sume			if (srcmask) {
502578064Sume				bcopy(&sm->sin6_addr, srcmask,
502678064Sume				      sizeof(*srcmask));
502778064Sume			}
502878064Sume		}
502978064Sume
503078064Sume		si = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
503178064Sume		if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr))
503278064Sume			bcopy(&si->sin6_addr, &ddst, sizeof(ddst));
503378064Sume	}
503478064Sume
503578064Sume	if (dst)
503678064Sume		bcopy(&ddst, dst, sizeof(*dst));
503778064Sume	if (src)
503878064Sume		bcopy(&ssrc, src, sizeof(*src));
5039194813Srwatson	IF_ADDR_UNLOCK(ifp);
504070199Sjhay}
504142104Sphk
504278064Sume#ifdef IPV6CP_MYIFID_DYN
504378064Sume/*
504478064Sume * Generate random ifid.
504578064Sume */
504678064Sumestatic void
504778064Sumesppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr)
504878064Sume{
504978064Sume	/* TBD */
505078064Sume}
505178064Sume
505278064Sume/*
505378064Sume * Set my IPv6 address.  Must be called at splimp.
505478064Sume */
505578064Sumestatic void
505678064Sumesppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src)
505778064Sume{
505878064Sume	STDDCL;
505978064Sume	struct ifaddr *ifa;
506078064Sume	struct sockaddr_in6 *sin6;
506178064Sume
506278064Sume	/*
506378064Sume	 * Pick the first link-local AF_INET6 address from the list,
506478064Sume	 * aliases don't make any sense on a p2p link anyway.
506578064Sume	 */
506678064Sume
506778064Sume	sin6 = NULL;
5068194813Srwatson	IF_ADDR_LOCK(ifp);
5069194813Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
5070194813Srwatson		if (ifa->ifa_addr->sa_family == AF_INET6) {
507178064Sume			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
5072194813Srwatson			if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
5073194813Srwatson				ifa_ref(ifa);
507478064Sume				break;
5075194813Srwatson			}
507678064Sume		}
507778064Sume	}
5078194813Srwatson	IF_ADDR_UNLOCK(ifp);
507978064Sume
5080194813Srwatson	if (ifa != NULL) {
508178064Sume		int error;
508278064Sume		struct sockaddr_in6 new_sin6 = *sin6;
508378064Sume
508478064Sume		bcopy(src, &new_sin6.sin6_addr, sizeof(new_sin6.sin6_addr));
508578064Sume		error = in6_ifinit(ifp, ifatoia6(ifa), &new_sin6, 1);
5086194813Srwatson		if (debug && error) {
508778064Sume			log(LOG_DEBUG, SPP_FMT "sppp_set_ip6_addr: in6_ifinit "
508878064Sume			    " failed, error=%d\n", SPP_ARGS(ifp), error);
508978064Sume		}
5090194813Srwatson		ifa_free(ifa);
509178064Sume	}
509278064Sume}
509378064Sume#endif
509478064Sume
509578064Sume/*
509678064Sume * Suggest a candidate address to be used by peer.
509778064Sume */
509878064Sumestatic void
509978064Sumesppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest)
510078064Sume{
510178064Sume	struct in6_addr myaddr;
510278064Sume	struct timeval tv;
510378064Sume
510478064Sume	sppp_get_ip6_addrs(sp, &myaddr, 0, 0);
510578064Sume
510678064Sume	myaddr.s6_addr[8] &= ~0x02;	/* u bit to "local" */
510778064Sume	microtime(&tv);
510878064Sume	if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) {
510978064Sume		myaddr.s6_addr[14] ^= 0xff;
511078064Sume		myaddr.s6_addr[15] ^= 0xff;
511178064Sume	} else {
511278064Sume		myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff);
511378064Sume		myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff);
511478064Sume	}
511578064Sume	if (suggest)
511678064Sume		bcopy(&myaddr, suggest, sizeof(myaddr));
511778064Sume}
511878064Sume#endif /*INET6*/
511978064Sume
512030300Sjoergstatic int
512138343Sbdesppp_params(struct sppp *sp, u_long cmd, void *data)
512230300Sjoerg{
512338343Sbde	u_long subcmd;
512430300Sjoerg	struct ifreq *ifr = (struct ifreq *)data;
512588600Sjoerg	struct spppreq *spr;
512688600Sjoerg	int rv = 0;
512730300Sjoerg
512888600Sjoerg	if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0)
512988600Sjoerg		return (EAGAIN);
513030300Sjoerg	/*
513130300Sjoerg	 * ifr->ifr_data is supposed to point to a struct spppreq.
513230300Sjoerg	 * Check the cmd word first before attempting to fetch all the
513330300Sjoerg	 * data.
513430300Sjoerg	 */
513588600Sjoerg	if ((subcmd = fuword(ifr->ifr_data)) == -1) {
513688600Sjoerg		rv = EFAULT;
513788600Sjoerg		goto quit;
513888600Sjoerg	}
513930300Sjoerg
514088600Sjoerg	if (copyin((caddr_t)ifr->ifr_data, spr, sizeof(struct spppreq)) != 0) {
514188600Sjoerg		rv = EFAULT;
514288600Sjoerg		goto quit;
514388600Sjoerg	}
514430300Sjoerg
514530300Sjoerg	switch (subcmd) {
5146170490Smjacob	case (u_long)SPPPIOGDEFS:
514788600Sjoerg		if (cmd != SIOCGIFGENERIC) {
514888600Sjoerg			rv = EINVAL;
514988600Sjoerg			break;
515088600Sjoerg		}
515130300Sjoerg		/*
515230300Sjoerg		 * We copy over the entire current state, but clean
515330300Sjoerg		 * out some of the stuff we don't wanna pass up.
515430300Sjoerg		 * Remember, SIOCGIFGENERIC is unprotected, and can be
515530300Sjoerg		 * called by any user.  No need to ever get PAP or
515630300Sjoerg		 * CHAP secrets back to userland anyway.
515730300Sjoerg		 */
515888600Sjoerg		spr->defs.pp_phase = sp->pp_phase;
515988723Sjoerg		spr->defs.enable_vj = (sp->confflags & CONF_ENABLE_VJ) != 0;
516088723Sjoerg		spr->defs.enable_ipv6 = (sp->confflags & CONF_ENABLE_IPV6) != 0;
516188600Sjoerg		spr->defs.lcp = sp->lcp;
516288600Sjoerg		spr->defs.ipcp = sp->ipcp;
516388600Sjoerg		spr->defs.ipv6cp = sp->ipv6cp;
516488600Sjoerg		spr->defs.myauth = sp->myauth;
516588600Sjoerg		spr->defs.hisauth = sp->hisauth;
516688600Sjoerg		bzero(spr->defs.myauth.secret, AUTHKEYLEN);
516788600Sjoerg		bzero(spr->defs.myauth.challenge, AUTHKEYLEN);
516888600Sjoerg		bzero(spr->defs.hisauth.secret, AUTHKEYLEN);
516988600Sjoerg		bzero(spr->defs.hisauth.challenge, AUTHKEYLEN);
517088550Sjoerg		/*
517188550Sjoerg		 * Fixup the LCP timeout value to milliseconds so
517288550Sjoerg		 * spppcontrol doesn't need to bother about the value
517388550Sjoerg		 * of "hz".  We do the reverse calculation below when
517488550Sjoerg		 * setting it.
517588550Sjoerg		 */
517688600Sjoerg		spr->defs.lcp.timeout = sp->lcp.timeout * 1000 / hz;
517788600Sjoerg		rv = copyout(spr, (caddr_t)ifr->ifr_data,
517888600Sjoerg			     sizeof(struct spppreq));
517988600Sjoerg		break;
518030300Sjoerg
5181170490Smjacob	case (u_long)SPPPIOSDEFS:
518288600Sjoerg		if (cmd != SIOCSIFGENERIC) {
518388600Sjoerg			rv = EINVAL;
518488600Sjoerg			break;
518588600Sjoerg		}
518630300Sjoerg		/*
518788550Sjoerg		 * We have a very specific idea of which fields we
518888550Sjoerg		 * allow being passed back from userland, so to not
518988550Sjoerg		 * clobber our current state.  For one, we only allow
519088550Sjoerg		 * setting anything if LCP is in dead or establish
519188550Sjoerg		 * phase.  Once the authentication negotiations
519288550Sjoerg		 * started, the authentication settings must not be
519388550Sjoerg		 * changed again.  (The administrator can force an
519430300Sjoerg		 * ifconfig down in order to get LCP back into dead
519530300Sjoerg		 * phase.)
519630300Sjoerg		 *
519730300Sjoerg		 * Also, we only allow for authentication parameters to be
519830300Sjoerg		 * specified.
519930300Sjoerg		 *
520030300Sjoerg		 * XXX Should allow to set or clear pp_flags.
520130300Sjoerg		 *
520230300Sjoerg		 * Finally, if the respective authentication protocol to
520330300Sjoerg		 * be used is set differently than 0, but the secret is
520430300Sjoerg		 * passed as all zeros, we don't trash the existing secret.
520530300Sjoerg		 * This allows an administrator to change the system name
520630300Sjoerg		 * only without clobbering the secret (which he didn't get
520730300Sjoerg		 * back in a previous SPPPIOGDEFS call).  However, the
520830300Sjoerg		 * secrets are cleared if the authentication protocol is
520988550Sjoerg		 * reset to 0.  */
521088550Sjoerg		if (sp->pp_phase != PHASE_DEAD &&
521188600Sjoerg		    sp->pp_phase != PHASE_ESTABLISH) {
521288600Sjoerg			rv = EBUSY;
521388600Sjoerg			break;
521488600Sjoerg		}
521530300Sjoerg
521688600Sjoerg		if ((spr->defs.myauth.proto != 0 && spr->defs.myauth.proto != PPP_PAP &&
521788600Sjoerg		     spr->defs.myauth.proto != PPP_CHAP) ||
521888600Sjoerg		    (spr->defs.hisauth.proto != 0 && spr->defs.hisauth.proto != PPP_PAP &&
521988600Sjoerg		     spr->defs.hisauth.proto != PPP_CHAP)) {
522088600Sjoerg			rv = EINVAL;
522188600Sjoerg			break;
522288600Sjoerg		}
522330300Sjoerg
522488600Sjoerg		if (spr->defs.myauth.proto == 0)
522530300Sjoerg			/* resetting myauth */
522630300Sjoerg			bzero(&sp->myauth, sizeof sp->myauth);
522730300Sjoerg		else {
522830300Sjoerg			/* setting/changing myauth */
522988600Sjoerg			sp->myauth.proto = spr->defs.myauth.proto;
523088600Sjoerg			bcopy(spr->defs.myauth.name, sp->myauth.name, AUTHNAMELEN);
523188600Sjoerg			if (spr->defs.myauth.secret[0] != '\0')
523288600Sjoerg				bcopy(spr->defs.myauth.secret, sp->myauth.secret,
523330300Sjoerg				      AUTHKEYLEN);
523430300Sjoerg		}
523588600Sjoerg		if (spr->defs.hisauth.proto == 0)
523630300Sjoerg			/* resetting hisauth */
523730300Sjoerg			bzero(&sp->hisauth, sizeof sp->hisauth);
523830300Sjoerg		else {
523930300Sjoerg			/* setting/changing hisauth */
524088600Sjoerg			sp->hisauth.proto = spr->defs.hisauth.proto;
524188600Sjoerg			sp->hisauth.flags = spr->defs.hisauth.flags;
524288600Sjoerg			bcopy(spr->defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN);
524388600Sjoerg			if (spr->defs.hisauth.secret[0] != '\0')
524488600Sjoerg				bcopy(spr->defs.hisauth.secret, sp->hisauth.secret,
524530300Sjoerg				      AUTHKEYLEN);
524630300Sjoerg		}
524788550Sjoerg		/* set LCP restart timer timeout */
524888600Sjoerg		if (spr->defs.lcp.timeout != 0)
524988600Sjoerg			sp->lcp.timeout = spr->defs.lcp.timeout * hz / 1000;
525088723Sjoerg		/* set VJ enable and IPv6 disable flags */
525188723Sjoerg#ifdef INET
525288723Sjoerg		if (spr->defs.enable_vj)
525388723Sjoerg			sp->confflags |= CONF_ENABLE_VJ;
525488723Sjoerg		else
525588723Sjoerg			sp->confflags &= ~CONF_ENABLE_VJ;
525688723Sjoerg#endif
525788723Sjoerg#ifdef INET6
525888723Sjoerg		if (spr->defs.enable_ipv6)
525988723Sjoerg			sp->confflags |= CONF_ENABLE_IPV6;
526088723Sjoerg		else
526188723Sjoerg			sp->confflags &= ~CONF_ENABLE_IPV6;
526296349Sjoerg#endif
526330300Sjoerg		break;
526430300Sjoerg
526530300Sjoerg	default:
526688600Sjoerg		rv = EINVAL;
526730300Sjoerg	}
526830300Sjoerg
526988600Sjoerg quit:
527088600Sjoerg	free(spr, M_TEMP);
527188600Sjoerg
527288600Sjoerg	return (rv);
527330300Sjoerg}
527430300Sjoerg
527530300Sjoergstatic void
527630300Sjoergsppp_phase_network(struct sppp *sp)
527730300Sjoerg{
527842066Sphk	STDDCL;
527930300Sjoerg	int i;
528030300Sjoerg	u_long mask;
528130300Sjoerg
528230300Sjoerg	sp->pp_phase = PHASE_NETWORK;
528330300Sjoerg
528442066Sphk	if (debug)
528542066Sphk		log(LOG_DEBUG, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
528642066Sphk		    sppp_phase_name(sp->pp_phase));
528730300Sjoerg
528830300Sjoerg	/* Notify NCPs now. */
528930300Sjoerg	for (i = 0; i < IDX_COUNT; i++)
529030300Sjoerg		if ((cps[i])->flags & CP_NCP)
529130300Sjoerg			(cps[i])->Open(sp);
529230300Sjoerg
529330300Sjoerg	/* Send Up events to all NCPs. */
529430300Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
529588706Sjoerg		if ((sp->lcp.protos & mask) && ((cps[i])->flags & CP_NCP))
529630300Sjoerg			(cps[i])->Up(sp);
529730300Sjoerg
529830300Sjoerg	/* if no NCP is starting, all this was in vain, close down */
529930300Sjoerg	sppp_lcp_check_and_close(sp);
530030300Sjoerg}
530130300Sjoerg
530270199Sjhay
530325706Sjoergstatic const char *
530425944Sjoergsppp_cp_type_name(u_char type)
53054910Swollman{
530630300Sjoerg	static char buf[12];
53074910Swollman	switch (type) {
530830300Sjoerg	case CONF_REQ:   return "conf-req";
530930300Sjoerg	case CONF_ACK:   return "conf-ack";
531030300Sjoerg	case CONF_NAK:   return "conf-nak";
531130300Sjoerg	case CONF_REJ:   return "conf-rej";
531230300Sjoerg	case TERM_REQ:   return "term-req";
531330300Sjoerg	case TERM_ACK:   return "term-ack";
531430300Sjoerg	case CODE_REJ:   return "code-rej";
531530300Sjoerg	case PROTO_REJ:  return "proto-rej";
531630300Sjoerg	case ECHO_REQ:   return "echo-req";
531730300Sjoerg	case ECHO_REPLY: return "echo-reply";
531830300Sjoerg	case DISC_REQ:   return "discard-req";
53194910Swollman	}
532044145Sphk	snprintf (buf, sizeof(buf), "cp/0x%x", type);
532130300Sjoerg	return buf;
53224910Swollman}
53234910Swollman
532425706Sjoergstatic const char *
532530300Sjoergsppp_auth_type_name(u_short proto, u_char type)
532630300Sjoerg{
532730300Sjoerg	static char buf[12];
532830300Sjoerg	switch (proto) {
532930300Sjoerg	case PPP_CHAP:
533030300Sjoerg		switch (type) {
533130300Sjoerg		case CHAP_CHALLENGE:	return "challenge";
533230300Sjoerg		case CHAP_RESPONSE:	return "response";
533330300Sjoerg		case CHAP_SUCCESS:	return "success";
533430300Sjoerg		case CHAP_FAILURE:	return "failure";
533530300Sjoerg		}
533630300Sjoerg	case PPP_PAP:
533730300Sjoerg		switch (type) {
533830300Sjoerg		case PAP_REQ:		return "req";
533930300Sjoerg		case PAP_ACK:		return "ack";
534030300Sjoerg		case PAP_NAK:		return "nak";
534130300Sjoerg		}
534230300Sjoerg	}
534344145Sphk	snprintf (buf, sizeof(buf), "auth/0x%x", type);
534430300Sjoerg	return buf;
534530300Sjoerg}
534630300Sjoerg
534730300Sjoergstatic const char *
534825944Sjoergsppp_lcp_opt_name(u_char opt)
53494910Swollman{
535030300Sjoerg	static char buf[12];
535125944Sjoerg	switch (opt) {
535230300Sjoerg	case LCP_OPT_MRU:		return "mru";
535330300Sjoerg	case LCP_OPT_ASYNC_MAP:		return "async-map";
535430300Sjoerg	case LCP_OPT_AUTH_PROTO:	return "auth-proto";
535530300Sjoerg	case LCP_OPT_QUAL_PROTO:	return "qual-proto";
535630300Sjoerg	case LCP_OPT_MAGIC:		return "magic";
535730300Sjoerg	case LCP_OPT_PROTO_COMP:	return "proto-comp";
535830300Sjoerg	case LCP_OPT_ADDR_COMP:		return "addr-comp";
53594910Swollman	}
536044145Sphk	snprintf (buf, sizeof(buf), "lcp/0x%x", opt);
536130300Sjoerg	return buf;
53624910Swollman}
53634910Swollman
5364184682Sbz#ifdef INET
536525944Sjoergstatic const char *
536625944Sjoergsppp_ipcp_opt_name(u_char opt)
536725944Sjoerg{
536830300Sjoerg	static char buf[12];
536925944Sjoerg	switch (opt) {
537030300Sjoerg	case IPCP_OPT_ADDRESSES:	return "addresses";
537130300Sjoerg	case IPCP_OPT_COMPRESSION:	return "compression";
537230300Sjoerg	case IPCP_OPT_ADDRESS:		return "address";
537325944Sjoerg	}
537444145Sphk	snprintf (buf, sizeof(buf), "ipcp/0x%x", opt);
537530300Sjoerg	return buf;
537625944Sjoerg}
5377184682Sbz#endif
537825944Sjoerg
537978064Sume#ifdef INET6
538025944Sjoergstatic const char *
538178064Sumesppp_ipv6cp_opt_name(u_char opt)
538278064Sume{
538378064Sume	static char buf[12];
538478064Sume	switch (opt) {
538578064Sume	case IPV6CP_OPT_IFID:		return "ifid";
538678064Sume	case IPV6CP_OPT_COMPRESSION:	return "compression";
538778064Sume	}
538878064Sume	sprintf (buf, "0x%x", opt);
538978064Sume	return buf;
539078064Sume}
539178064Sume#endif
539278064Sume
539378064Sumestatic const char *
539425944Sjoergsppp_state_name(int state)
539525944Sjoerg{
539625944Sjoerg	switch (state) {
539725944Sjoerg	case STATE_INITIAL:	return "initial";
539825944Sjoerg	case STATE_STARTING:	return "starting";
539925944Sjoerg	case STATE_CLOSED:	return "closed";
540025944Sjoerg	case STATE_STOPPED:	return "stopped";
540125944Sjoerg	case STATE_CLOSING:	return "closing";
540225944Sjoerg	case STATE_STOPPING:	return "stopping";
540325944Sjoerg	case STATE_REQ_SENT:	return "req-sent";
540425944Sjoerg	case STATE_ACK_RCVD:	return "ack-rcvd";
540525944Sjoerg	case STATE_ACK_SENT:	return "ack-sent";
540625944Sjoerg	case STATE_OPENED:	return "opened";
540725944Sjoerg	}
540825944Sjoerg	return "illegal";
540925944Sjoerg}
541025944Sjoerg
541125944Sjoergstatic const char *
541225944Sjoergsppp_phase_name(enum ppp_phase phase)
541325944Sjoerg{
541425944Sjoerg	switch (phase) {
541525944Sjoerg	case PHASE_DEAD:	return "dead";
541625944Sjoerg	case PHASE_ESTABLISH:	return "establish";
541725944Sjoerg	case PHASE_TERMINATE:	return "terminate";
541825944Sjoerg	case PHASE_AUTHENTICATE: return "authenticate";
541925944Sjoerg	case PHASE_NETWORK:	return "network";
542025944Sjoerg	}
542125944Sjoerg	return "illegal";
542225944Sjoerg}
542325944Sjoerg
542425944Sjoergstatic const char *
542525944Sjoergsppp_proto_name(u_short proto)
542625944Sjoerg{
542725944Sjoerg	static char buf[12];
542825944Sjoerg	switch (proto) {
542925944Sjoerg	case PPP_LCP:	return "lcp";
543025944Sjoerg	case PPP_IPCP:	return "ipcp";
543130300Sjoerg	case PPP_PAP:	return "pap";
543230300Sjoerg	case PPP_CHAP:	return "chap";
543378064Sume	case PPP_IPV6CP: return "ipv6cp";
543425944Sjoerg	}
543544145Sphk	snprintf(buf, sizeof(buf), "proto/0x%x", (unsigned)proto);
543625944Sjoerg	return buf;
543725944Sjoerg}
543825944Sjoerg
543912820Sphkstatic void
544030300Sjoergsppp_print_bytes(const u_char *p, u_short len)
54414910Swollman{
544244145Sphk	if (len)
544369211Sphk		log(-1, " %*D", len, p, "-");
54444910Swollman}
544525944Sjoerg
544630300Sjoergstatic void
544730300Sjoergsppp_print_string(const char *p, u_short len)
544830300Sjoerg{
544930300Sjoerg	u_char c;
545030300Sjoerg
545130300Sjoerg	while (len-- > 0) {
545230300Sjoerg		c = *p++;
545330300Sjoerg		/*
545430300Sjoerg		 * Print only ASCII chars directly.  RFC 1994 recommends
545530300Sjoerg		 * using only them, but we don't rely on it.  */
545630300Sjoerg		if (c < ' ' || c > '~')
545769211Sphk			log(-1, "\\x%x", c);
545830300Sjoerg		else
545969211Sphk			log(-1, "%c", c);
546030300Sjoerg	}
546130300Sjoerg}
546230300Sjoerg
5463184682Sbz#ifdef INET
546430300Sjoergstatic const char *
546530300Sjoergsppp_dotted_quad(u_long addr)
546630300Sjoerg{
546730300Sjoerg	static char s[16];
546830300Sjoerg	sprintf(s, "%d.%d.%d.%d",
546940008Sjoerg		(int)((addr >> 24) & 0xff),
547040008Sjoerg		(int)((addr >> 16) & 0xff),
547140008Sjoerg		(int)((addr >> 8) & 0xff),
547238372Sbde		(int)(addr & 0xff));
547330300Sjoerg	return s;
547430300Sjoerg}
5475184682Sbz#endif
547630300Sjoerg
547730300Sjoergstatic int
547830300Sjoergsppp_strnlen(u_char *p, int max)
547930300Sjoerg{
548030300Sjoerg	int len;
548130300Sjoerg
548230300Sjoerg	for (len = 0; len < max && *p; ++p)
548330300Sjoerg		++len;
548430300Sjoerg	return len;
548530300Sjoerg}
548630300Sjoerg
548730300Sjoerg/* a dummy, used to drop uninteresting events */
548830300Sjoergstatic void
548930300Sjoergsppp_null(struct sppp *unused)
549030300Sjoerg{
549130300Sjoerg	/* do just nothing */
549230300Sjoerg}
5493