if_spppsubr.c revision 31742
14910Swollman/*
24910Swollman * Synchronous PPP/Cisco link level subroutines.
34910Swollman * Keepalive protocol implemented in both Cisco and PPP modes.
44910Swollman *
530300Sjoerg * Copyright (C) 1994-1996 Cronyx Engineering Ltd.
625944Sjoerg * Author: Serge Vakulenko, <vak@cronyx.ru>
74910Swollman *
825944Sjoerg * Heavily revamped to conform to RFC 1661.
925944Sjoerg * Copyright (C) 1997, Joerg Wunsch.
1025944Sjoerg *
114910Swollman * This software is distributed with NO WARRANTIES, not even the implied
124910Swollman * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
134910Swollman *
144910Swollman * Authors grant any other persons or organisations permission to use
154910Swollman * or modify this software as long as this message is kept with the software,
164910Swollman * all derivative works or modified versions.
174910Swollman *
1830300Sjoerg * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997
1916288Sgpalmer *
2031742Seivind * $Id: if_spppsubr.c,v 1.28 1997/10/11 11:25:28 joerg Exp $
214910Swollman */
224910Swollman
2331742Seivind#include "opt_ipx.h"
2431742Seivind
254910Swollman#include <sys/param.h>
264952Sbde#include <sys/systm.h>
274952Sbde#include <sys/kernel.h>
2824204Sbde#include <sys/sockio.h>
294910Swollman#include <sys/socket.h>
3025706Sjoerg#include <sys/syslog.h>
3129024Sbde#include <sys/malloc.h>
324910Swollman#include <sys/mbuf.h>
3330300Sjoerg#include <sys/md5.h>
344910Swollman
354910Swollman#include <net/if.h>
364910Swollman#include <net/netisr.h>
374910Swollman#include <net/if_types.h>
384910Swollman
3930300Sjoerg#include <machine/stdarg.h>
4030300Sjoerg
414910Swollman#ifdef INET
424910Swollman#include <netinet/in.h>
434910Swollman#include <netinet/in_systm.h>
444910Swollman#include <netinet/in_var.h>
454910Swollman#include <netinet/ip.h>
464910Swollman#include <netinet/tcp.h>
474910Swollman#include <netinet/if_ether.h>
484910Swollman#endif
494910Swollman
5011819Sjulian#ifdef IPX
5111819Sjulian#include <netipx/ipx.h>
5211819Sjulian#include <netipx/ipx_if.h>
5311819Sjulian#endif
5411819Sjulian
554910Swollman#ifdef NS
564910Swollman#include <netns/ns.h>
574910Swollman#include <netns/ns_if.h>
584910Swollman#endif
594910Swollman
604910Swollman#ifdef ISO
614910Swollman#include <netiso/argo_debug.h>
624910Swollman#include <netiso/iso.h>
634910Swollman#include <netiso/iso_var.h>
644910Swollman#include <netiso/iso_snpac.h>
654910Swollman#endif
664910Swollman
674910Swollman#include <net/if_sppp.h>
684910Swollman
694910Swollman#define MAXALIVECNT     3               /* max. alive packets */
704910Swollman
7125944Sjoerg/*
7225944Sjoerg * Interface flags that can be set in an ifconfig command.
7325944Sjoerg *
7425955Sjoerg * Setting link0 will make the link passive, i.e. it will be marked
7525944Sjoerg * as being administrative openable, but won't be opened to begin
7625944Sjoerg * with.  Incoming calls will be answered, or subsequent calls with
7725944Sjoerg * -link1 will cause the administrative open of the LCP layer.
7825955Sjoerg *
7925955Sjoerg * Setting link1 will cause the link to auto-dial only as packets
8025955Sjoerg * arrive to be sent.
8130300Sjoerg *
8230300Sjoerg * Setting IFF_DEBUG will syslog the option negotiation and state
8330300Sjoerg * transitions at level kern.debug.  Note: all logs consistently look
8430300Sjoerg * like
8530300Sjoerg *
8630300Sjoerg *   <if-name><unit>: <proto-name> <additional info...>
8730300Sjoerg *
8830300Sjoerg * with <if-name><unit> being something like "bppp0", and <proto-name>
8930300Sjoerg * being one of "lcp", "ipcp", "cisco", "chap", "pap", etc.
9025944Sjoerg */
9125944Sjoerg
9225955Sjoerg#define IFF_PASSIVE	IFF_LINK0	/* wait passively for connection */
9325955Sjoerg#define IFF_AUTO	IFF_LINK1	/* auto-dial on output */
9425944Sjoerg
9530300Sjoerg#define PPP_ALLSTATIONS 0xff		/* All-Stations broadcast address */
9630300Sjoerg#define PPP_UI		0x03		/* Unnumbered Information */
9730300Sjoerg#define PPP_IP		0x0021		/* Internet Protocol */
9830300Sjoerg#define PPP_ISO		0x0023		/* ISO OSI Protocol */
9930300Sjoerg#define PPP_XNS		0x0025		/* Xerox NS Protocol */
10030300Sjoerg#define PPP_IPX		0x002b		/* Novell IPX Protocol */
10130300Sjoerg#define PPP_LCP		0xc021		/* Link Control Protocol */
10230300Sjoerg#define PPP_PAP		0xc023		/* Password Authentication Protocol */
10330300Sjoerg#define PPP_CHAP	0xc223		/* Challenge-Handshake Auth Protocol */
10430300Sjoerg#define PPP_IPCP	0x8021		/* Internet Protocol Control Protocol */
1054910Swollman
10625944Sjoerg#define CONF_REQ	1		/* PPP configure request */
10725944Sjoerg#define CONF_ACK	2		/* PPP configure acknowledge */
10825944Sjoerg#define CONF_NAK	3		/* PPP configure negative ack */
10925944Sjoerg#define CONF_REJ	4		/* PPP configure reject */
11025944Sjoerg#define TERM_REQ	5		/* PPP terminate request */
11125944Sjoerg#define TERM_ACK	6		/* PPP terminate acknowledge */
11225944Sjoerg#define CODE_REJ	7		/* PPP code reject */
11325944Sjoerg#define PROTO_REJ	8		/* PPP protocol reject */
11425944Sjoerg#define ECHO_REQ	9		/* PPP echo request */
11525944Sjoerg#define ECHO_REPLY	10		/* PPP echo reply */
11625944Sjoerg#define DISC_REQ	11		/* PPP discard request */
1174910Swollman
11830300Sjoerg#define LCP_OPT_MRU		1	/* maximum receive unit */
11930300Sjoerg#define LCP_OPT_ASYNC_MAP	2	/* async control character map */
12030300Sjoerg#define LCP_OPT_AUTH_PROTO	3	/* authentication protocol */
12130300Sjoerg#define LCP_OPT_QUAL_PROTO	4	/* quality protocol */
12230300Sjoerg#define LCP_OPT_MAGIC		5	/* magic number */
12330300Sjoerg#define LCP_OPT_RESERVED	6	/* reserved */
12430300Sjoerg#define LCP_OPT_PROTO_COMP	7	/* protocol field compression */
12530300Sjoerg#define LCP_OPT_ADDR_COMP	8	/* address/control field compression */
1264910Swollman
12725944Sjoerg#define IPCP_OPT_ADDRESSES	1	/* both IP addresses; deprecated */
12825944Sjoerg#define IPCP_OPT_COMPRESSION	2	/* IP compression protocol (VJ) */
12925944Sjoerg#define IPCP_OPT_ADDRESS	3	/* local IP address */
1304910Swollman
13130300Sjoerg#define PAP_REQ			1	/* PAP name/password request */
13230300Sjoerg#define PAP_ACK			2	/* PAP acknowledge */
13330300Sjoerg#define PAP_NAK			3	/* PAP fail */
1344910Swollman
13530300Sjoerg#define CHAP_CHALLENGE		1	/* CHAP challenge request */
13630300Sjoerg#define CHAP_RESPONSE		2	/* CHAP challenge response */
13730300Sjoerg#define CHAP_SUCCESS		3	/* CHAP response ok */
13830300Sjoerg#define CHAP_FAILURE		4	/* CHAP response failed */
13930300Sjoerg
14030300Sjoerg#define CHAP_MD5		5	/* hash algorithm - MD5 */
14130300Sjoerg
14230300Sjoerg#define CISCO_MULTICAST		0x8f	/* Cisco multicast address */
14330300Sjoerg#define CISCO_UNICAST		0x0f	/* Cisco unicast address */
14430300Sjoerg#define CISCO_KEEPALIVE		0x8035	/* Cisco keepalive protocol */
14530300Sjoerg#define CISCO_ADDR_REQ		0	/* Cisco address request */
14630300Sjoerg#define CISCO_ADDR_REPLY	1	/* Cisco address reply */
14730300Sjoerg#define CISCO_KEEPALIVE_REQ	2	/* Cisco keepalive request */
14830300Sjoerg
14925944Sjoerg/* states are named and numbered according to RFC 1661 */
15025944Sjoerg#define STATE_INITIAL	0
15125944Sjoerg#define STATE_STARTING	1
15225944Sjoerg#define STATE_CLOSED	2
15325944Sjoerg#define STATE_STOPPED	3
15425944Sjoerg#define STATE_CLOSING	4
15525944Sjoerg#define STATE_STOPPING	5
15625944Sjoerg#define STATE_REQ_SENT	6
15725944Sjoerg#define STATE_ACK_RCVD	7
15825944Sjoerg#define STATE_ACK_SENT	8
15925944Sjoerg#define STATE_OPENED	9
16025944Sjoerg
1614910Swollmanstruct ppp_header {
16211189Sjkh	u_char address;
16311189Sjkh	u_char control;
16411189Sjkh	u_short protocol;
1654910Swollman};
1664910Swollman#define PPP_HEADER_LEN          sizeof (struct ppp_header)
1674910Swollman
1684910Swollmanstruct lcp_header {
16911189Sjkh	u_char type;
17011189Sjkh	u_char ident;
17111189Sjkh	u_short len;
1724910Swollman};
1734910Swollman#define LCP_HEADER_LEN          sizeof (struct lcp_header)
1744910Swollman
1754910Swollmanstruct cisco_packet {
17611189Sjkh	u_long type;
17711189Sjkh	u_long par1;
17811189Sjkh	u_long par2;
17911189Sjkh	u_short rel;
18011189Sjkh	u_short time0;
18111189Sjkh	u_short time1;
1824910Swollman};
1834910Swollman#define CISCO_PACKET_LEN 18
1844910Swollman
18525944Sjoerg/*
18625944Sjoerg * We follow the spelling and capitalization of RFC 1661 here, to make
18725944Sjoerg * it easier comparing with the standard.  Please refer to this RFC in
18825944Sjoerg * case you can't make sense out of these abbreviation; it will also
18925944Sjoerg * explain the semantics related to the various events and actions.
19025944Sjoerg */
19125944Sjoergstruct cp {
19225944Sjoerg	u_short	proto;		/* PPP control protocol number */
19325944Sjoerg	u_char protoidx;	/* index into state table in struct sppp */
19425944Sjoerg	u_char flags;
19525944Sjoerg#define CP_LCP		0x01	/* this is the LCP */
19625944Sjoerg#define CP_AUTH		0x02	/* this is an authentication protocol */
19725944Sjoerg#define CP_NCP		0x04	/* this is a NCP */
19825944Sjoerg#define CP_QUAL		0x08	/* this is a quality reporting protocol */
19925944Sjoerg	const char *name;	/* name of this control protocol */
20025944Sjoerg	/* event handlers */
20125944Sjoerg	void	(*Up)(struct sppp *sp);
20225944Sjoerg	void	(*Down)(struct sppp *sp);
20325944Sjoerg	void	(*Open)(struct sppp *sp);
20425944Sjoerg	void	(*Close)(struct sppp *sp);
20525944Sjoerg	void	(*TO)(void *sp);
20625944Sjoerg	int	(*RCR)(struct sppp *sp, struct lcp_header *h, int len);
20725944Sjoerg	void	(*RCN_rej)(struct sppp *sp, struct lcp_header *h, int len);
20825944Sjoerg	void	(*RCN_nak)(struct sppp *sp, struct lcp_header *h, int len);
20925944Sjoerg	/* actions */
21025944Sjoerg	void	(*tlu)(struct sppp *sp);
21125944Sjoerg	void	(*tld)(struct sppp *sp);
21225944Sjoerg	void	(*tls)(struct sppp *sp);
21325944Sjoerg	void	(*tlf)(struct sppp *sp);
21425944Sjoerg	void	(*scr)(struct sppp *sp);
21525944Sjoerg};
21625944Sjoerg
21712820Sphkstatic struct sppp *spppq;
21830300Sjoergstatic struct callout_handle keepalive_ch;
2194910Swollman
2204910Swollman/*
2214910Swollman * The following disgusting hack gets around the problem that IP TOS
2224910Swollman * can't be set yet.  We want to put "interactive" traffic on a high
2234910Swollman * priority queue.  To decide if traffic is interactive, we check that
2244910Swollman * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
22530300Sjoerg *
22630300Sjoerg * XXX is this really still necessary?  - joerg -
2274910Swollman */
22811189Sjkhstatic u_short interactive_ports[8] = {
2294910Swollman	0,	513,	0,	0,
2304910Swollman	0,	21,	0,	23,
2314910Swollman};
2324910Swollman#define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
2334910Swollman
23425944Sjoerg/* almost every function needs these */
23525944Sjoerg#define STDDCL							\
23625944Sjoerg	struct ifnet *ifp = &sp->pp_if;				\
23725944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG
23811189Sjkh
23930300Sjoergstatic int sppp_output(struct ifnet *ifp, struct mbuf *m,
24025944Sjoerg		       struct sockaddr *dst, struct rtentry *rt);
2414910Swollman
24225944Sjoergstatic void sppp_cisco_send(struct sppp *sp, int type, long par1, long par2);
24325944Sjoergstatic void sppp_cisco_input(struct sppp *sp, struct mbuf *m);
24425944Sjoerg
24525944Sjoergstatic void sppp_cp_input(const struct cp *cp, struct sppp *sp,
24625944Sjoerg			  struct mbuf *m);
24725944Sjoergstatic void sppp_cp_send(struct sppp *sp, u_short proto, u_char type,
24825944Sjoerg			 u_char ident, u_short len, void *data);
24925944Sjoergstatic void sppp_cp_timeout(void *arg);
25025944Sjoergstatic void sppp_cp_change_state(const struct cp *cp, struct sppp *sp,
25125944Sjoerg				 int newstate);
25230300Sjoergstatic void sppp_auth_send(const struct cp *cp,
25330300Sjoerg			   struct sppp *sp, u_char type, u_char id,
25430300Sjoerg			   ...);
25525944Sjoerg
25625944Sjoergstatic void sppp_up_event(const struct cp *cp, struct sppp *sp);
25725944Sjoergstatic void sppp_down_event(const struct cp *cp, struct sppp *sp);
25825944Sjoergstatic void sppp_open_event(const struct cp *cp, struct sppp *sp);
25925944Sjoergstatic void sppp_close_event(const struct cp *cp, struct sppp *sp);
26025944Sjoergstatic void sppp_to_event(const struct cp *cp, struct sppp *sp);
26125944Sjoerg
26230300Sjoergstatic void sppp_null(struct sppp *sp);
26330300Sjoerg
26425944Sjoergstatic void sppp_lcp_init(struct sppp *sp);
26525944Sjoergstatic void sppp_lcp_up(struct sppp *sp);
26625944Sjoergstatic void sppp_lcp_down(struct sppp *sp);
26725944Sjoergstatic void sppp_lcp_open(struct sppp *sp);
26825944Sjoergstatic void sppp_lcp_close(struct sppp *sp);
26925944Sjoergstatic void sppp_lcp_TO(void *sp);
27025944Sjoergstatic int sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len);
27125944Sjoergstatic void sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
27225944Sjoergstatic void sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
27325944Sjoergstatic void sppp_lcp_tlu(struct sppp *sp);
27425944Sjoergstatic void sppp_lcp_tld(struct sppp *sp);
27525944Sjoergstatic void sppp_lcp_tls(struct sppp *sp);
27625944Sjoergstatic void sppp_lcp_tlf(struct sppp *sp);
27725944Sjoergstatic void sppp_lcp_scr(struct sppp *sp);
27830300Sjoergstatic void sppp_lcp_check_and_close(struct sppp *sp);
27930300Sjoergstatic int sppp_ncp_check(struct sppp *sp);
28025944Sjoerg
28125944Sjoergstatic void sppp_ipcp_init(struct sppp *sp);
28225944Sjoergstatic void sppp_ipcp_up(struct sppp *sp);
28325944Sjoergstatic void sppp_ipcp_down(struct sppp *sp);
28425944Sjoergstatic void sppp_ipcp_open(struct sppp *sp);
28525944Sjoergstatic void sppp_ipcp_close(struct sppp *sp);
28625944Sjoergstatic void sppp_ipcp_TO(void *sp);
28725944Sjoergstatic int sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len);
28825944Sjoergstatic void sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len);
28925944Sjoergstatic void sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len);
29025944Sjoergstatic void sppp_ipcp_tlu(struct sppp *sp);
29125944Sjoergstatic void sppp_ipcp_tld(struct sppp *sp);
29225944Sjoergstatic void sppp_ipcp_tls(struct sppp *sp);
29325944Sjoergstatic void sppp_ipcp_tlf(struct sppp *sp);
29425944Sjoergstatic void sppp_ipcp_scr(struct sppp *sp);
29525944Sjoerg
29630300Sjoergstatic void sppp_pap_input(struct sppp *sp, struct mbuf *m);
29730300Sjoergstatic void sppp_pap_init(struct sppp *sp);
29830300Sjoergstatic void sppp_pap_open(struct sppp *sp);
29930300Sjoergstatic void sppp_pap_close(struct sppp *sp);
30030300Sjoergstatic void sppp_pap_TO(void *sp);
30130300Sjoergstatic void sppp_pap_my_TO(void *sp);
30230300Sjoergstatic void sppp_pap_tlu(struct sppp *sp);
30330300Sjoergstatic void sppp_pap_tld(struct sppp *sp);
30430300Sjoergstatic void sppp_pap_scr(struct sppp *sp);
30530300Sjoerg
30630300Sjoergstatic void sppp_chap_input(struct sppp *sp, struct mbuf *m);
30730300Sjoergstatic void sppp_chap_init(struct sppp *sp);
30830300Sjoergstatic void sppp_chap_open(struct sppp *sp);
30930300Sjoergstatic void sppp_chap_close(struct sppp *sp);
31030300Sjoergstatic void sppp_chap_TO(void *sp);
31130300Sjoergstatic void sppp_chap_tlu(struct sppp *sp);
31230300Sjoergstatic void sppp_chap_tld(struct sppp *sp);
31330300Sjoergstatic void sppp_chap_scr(struct sppp *sp);
31430300Sjoerg
31530300Sjoergstatic const char *sppp_auth_type_name(u_short proto, u_char type);
31625944Sjoergstatic const char *sppp_cp_type_name(u_char type);
31730300Sjoergstatic const char *sppp_dotted_quad(u_long addr);
31830300Sjoergstatic const char *sppp_ipcp_opt_name(u_char opt);
31925944Sjoergstatic const char *sppp_lcp_opt_name(u_char opt);
32025944Sjoergstatic const char *sppp_phase_name(enum ppp_phase phase);
32125944Sjoergstatic const char *sppp_proto_name(u_short proto);
32230300Sjoergstatic const char *sppp_state_name(int state);
32330300Sjoergstatic int sppp_params(struct sppp *sp, int cmd, void *data);
32430300Sjoergstatic int sppp_strnlen(u_char *p, int max);
32530300Sjoergstatic void sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst,
32630300Sjoerg			      u_long *srcmask);
32725944Sjoergstatic void sppp_keepalive(void *dummy);
32830300Sjoergstatic void sppp_phase_network(struct sppp *sp);
32930300Sjoergstatic void sppp_print_bytes(const u_char *p, u_short len);
33030300Sjoergstatic void sppp_print_string(const char *p, u_short len);
33125944Sjoergstatic void sppp_qflush(struct ifqueue *ifq);
33225944Sjoergstatic void sppp_set_ip_addr(struct sppp *sp, u_long src);
33325944Sjoerg
33425944Sjoerg/* our control protocol descriptors */
33525944Sjoergconst struct cp lcp = {
33625944Sjoerg	PPP_LCP, IDX_LCP, CP_LCP, "lcp",
33725944Sjoerg	sppp_lcp_up, sppp_lcp_down, sppp_lcp_open, sppp_lcp_close,
33825944Sjoerg	sppp_lcp_TO, sppp_lcp_RCR, sppp_lcp_RCN_rej, sppp_lcp_RCN_nak,
33925944Sjoerg	sppp_lcp_tlu, sppp_lcp_tld, sppp_lcp_tls, sppp_lcp_tlf,
34025944Sjoerg	sppp_lcp_scr
34125944Sjoerg};
34225944Sjoerg
34325944Sjoergconst struct cp ipcp = {
34425944Sjoerg	PPP_IPCP, IDX_IPCP, CP_NCP, "ipcp",
34525944Sjoerg	sppp_ipcp_up, sppp_ipcp_down, sppp_ipcp_open, sppp_ipcp_close,
34625944Sjoerg	sppp_ipcp_TO, sppp_ipcp_RCR, sppp_ipcp_RCN_rej, sppp_ipcp_RCN_nak,
34725944Sjoerg	sppp_ipcp_tlu, sppp_ipcp_tld, sppp_ipcp_tls, sppp_ipcp_tlf,
34825944Sjoerg	sppp_ipcp_scr
34925944Sjoerg};
35025944Sjoerg
35130300Sjoergconst struct cp pap = {
35230300Sjoerg	PPP_PAP, IDX_PAP, CP_AUTH, "pap",
35330300Sjoerg	sppp_null, sppp_null, sppp_pap_open, sppp_pap_close,
35430300Sjoerg	sppp_pap_TO, 0, 0, 0,
35530300Sjoerg	sppp_pap_tlu, sppp_pap_tld, sppp_null, sppp_null,
35630300Sjoerg	sppp_pap_scr
35730300Sjoerg};
35830300Sjoerg
35930300Sjoergconst struct cp chap = {
36030300Sjoerg	PPP_CHAP, IDX_CHAP, CP_AUTH, "chap",
36130300Sjoerg	sppp_null, sppp_null, sppp_chap_open, sppp_chap_close,
36230300Sjoerg	sppp_chap_TO, 0, 0, 0,
36330300Sjoerg	sppp_chap_tlu, sppp_chap_tld, sppp_null, sppp_null,
36430300Sjoerg	sppp_chap_scr
36530300Sjoerg};
36630300Sjoerg
36725944Sjoergconst struct cp *cps[IDX_COUNT] = {
36825944Sjoerg	&lcp,			/* IDX_LCP */
36925944Sjoerg	&ipcp,			/* IDX_IPCP */
37030300Sjoerg	&pap,			/* IDX_PAP */
37130300Sjoerg	&chap,			/* IDX_CHAP */
37225944Sjoerg};
37325944Sjoerg
37425944Sjoerg
37525944Sjoerg/*
37625944Sjoerg * Exported functions, comprising our interface to the lower layer.
3774910Swollman */
3784910Swollman
3794910Swollman/*
3804910Swollman * Process the received packet.
3814910Swollman */
38225706Sjoergvoid
38325706Sjoergsppp_input(struct ifnet *ifp, struct mbuf *m)
3844910Swollman{
3854910Swollman	struct ppp_header *h;
3864910Swollman	struct ifqueue *inq = 0;
38711189Sjkh	int s;
38825944Sjoerg	struct sppp *sp = (struct sppp *)ifp;
38925944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG;
3904910Swollman
3914910Swollman	if (ifp->if_flags & IFF_UP)
3924910Swollman		/* Count received bytes, add FCS and one flag */
3934910Swollman		ifp->if_ibytes += m->m_pkthdr.len + 3;
3944910Swollman
3954910Swollman	if (m->m_pkthdr.len <= PPP_HEADER_LEN) {
3964910Swollman		/* Too small packet, drop it. */
39725944Sjoerg		if (debug)
39825706Sjoerg			log(LOG_DEBUG,
39925706Sjoerg			    "%s%d: input packet is too small, %d bytes\n",
40025706Sjoerg			    ifp->if_name, ifp->if_unit, m->m_pkthdr.len);
40125944Sjoerg	  drop:
40225944Sjoerg		++ifp->if_ierrors;
40325944Sjoerg		++ifp->if_iqdrops;
4044910Swollman		m_freem (m);
4054910Swollman		return;
4064910Swollman	}
4074910Swollman
4084910Swollman	/* Get PPP header. */
4094910Swollman	h = mtod (m, struct ppp_header*);
4104910Swollman	m_adj (m, PPP_HEADER_LEN);
4114910Swollman
4124910Swollman	switch (h->address) {
4134910Swollman	case PPP_ALLSTATIONS:
4144910Swollman		if (h->control != PPP_UI)
4154910Swollman			goto invalid;
41611189Sjkh		if (sp->pp_flags & PP_CISCO) {
41725944Sjoerg			if (debug)
41825706Sjoerg				log(LOG_DEBUG,
41925706Sjoerg				    "%s%d: PPP packet in Cisco mode "
42025706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
42125706Sjoerg				    ifp->if_name, ifp->if_unit,
42225706Sjoerg				    h->address, h->control, ntohs(h->protocol));
42311189Sjkh			goto drop;
42411189Sjkh		}
4254910Swollman		switch (ntohs (h->protocol)) {
4264910Swollman		default:
42725944Sjoerg			if (sp->state[IDX_LCP] == STATE_OPENED)
42825944Sjoerg				sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
42911189Sjkh					++sp->pp_seq, m->m_pkthdr.len + 2,
4304910Swollman					&h->protocol);
43125944Sjoerg			if (debug)
43225706Sjoerg				log(LOG_DEBUG,
43325706Sjoerg				    "%s%d: invalid input protocol "
43425706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
43525706Sjoerg				    ifp->if_name, ifp->if_unit,
43625706Sjoerg				    h->address, h->control, ntohs(h->protocol));
4374910Swollman			++ifp->if_noproto;
4384910Swollman			goto drop;
4394910Swollman		case PPP_LCP:
44030300Sjoerg			sppp_cp_input(&lcp, sp, m);
4414910Swollman			m_freem (m);
4424910Swollman			return;
44330300Sjoerg		case PPP_PAP:
44430300Sjoerg			if (sp->pp_phase >= PHASE_AUTHENTICATE)
44530300Sjoerg				sppp_pap_input(sp, m);
44630300Sjoerg			m_freem (m);
44730300Sjoerg			return;
44830300Sjoerg		case PPP_CHAP:
44930300Sjoerg			if (sp->pp_phase >= PHASE_AUTHENTICATE)
45030300Sjoerg				sppp_chap_input(sp, m);
45130300Sjoerg			m_freem (m);
45230300Sjoerg			return;
4534910Swollman#ifdef INET
4544910Swollman		case PPP_IPCP:
45525944Sjoerg			if (sp->pp_phase == PHASE_NETWORK)
45630300Sjoerg				sppp_cp_input(&ipcp, sp, m);
4574910Swollman			m_freem (m);
4584910Swollman			return;
4594910Swollman		case PPP_IP:
46025944Sjoerg			if (sp->state[IDX_IPCP] == STATE_OPENED) {
4614910Swollman				schednetisr (NETISR_IP);
4624910Swollman				inq = &ipintrq;
4634910Swollman			}
4644910Swollman			break;
4654910Swollman#endif
46612495Speter#ifdef IPX
46712495Speter		case PPP_IPX:
46812495Speter			/* IPX IPXCP not implemented yet */
46925944Sjoerg			if (sp->pp_phase == PHASE_NETWORK) {
47012495Speter				schednetisr (NETISR_IPX);
47112495Speter				inq = &ipxintrq;
47212495Speter			}
47312495Speter			break;
47412495Speter#endif
4754910Swollman#ifdef NS
4764910Swollman		case PPP_XNS:
4774910Swollman			/* XNS IDPCP not implemented yet */
47825944Sjoerg			if (sp->pp_phase == PHASE_NETWORK) {
4794910Swollman				schednetisr (NETISR_NS);
4804910Swollman				inq = &nsintrq;
4814910Swollman			}
4824910Swollman			break;
4834910Swollman#endif
4844910Swollman#ifdef ISO
4854910Swollman		case PPP_ISO:
4864910Swollman			/* OSI NLCP not implemented yet */
48725944Sjoerg			if (sp->pp_phase == PHASE_NETWORK) {
4884910Swollman				schednetisr (NETISR_ISO);
4894910Swollman				inq = &clnlintrq;
4904910Swollman			}
4914910Swollman			break;
4924910Swollman#endif
4934910Swollman		}
4944910Swollman		break;
4954910Swollman	case CISCO_MULTICAST:
4964910Swollman	case CISCO_UNICAST:
4974910Swollman		/* Don't check the control field here (RFC 1547). */
49811189Sjkh		if (! (sp->pp_flags & PP_CISCO)) {
49925944Sjoerg			if (debug)
50025706Sjoerg				log(LOG_DEBUG,
50125706Sjoerg				    "%s%d: Cisco packet in PPP mode "
50225706Sjoerg				    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
50325706Sjoerg				    ifp->if_name, ifp->if_unit,
50425706Sjoerg				    h->address, h->control, ntohs(h->protocol));
50511189Sjkh			goto drop;
50611189Sjkh		}
5074910Swollman		switch (ntohs (h->protocol)) {
5084910Swollman		default:
5094910Swollman			++ifp->if_noproto;
5104910Swollman			goto invalid;
5114910Swollman		case CISCO_KEEPALIVE:
5124910Swollman			sppp_cisco_input ((struct sppp*) ifp, m);
5134910Swollman			m_freem (m);
5144910Swollman			return;
5154910Swollman#ifdef INET
5164910Swollman		case ETHERTYPE_IP:
5174910Swollman			schednetisr (NETISR_IP);
5184910Swollman			inq = &ipintrq;
5194910Swollman			break;
5204910Swollman#endif
52112495Speter#ifdef IPX
52212495Speter		case ETHERTYPE_IPX:
52312495Speter			schednetisr (NETISR_IPX);
52412495Speter			inq = &ipxintrq;
52512495Speter			break;
52612495Speter#endif
5274910Swollman#ifdef NS
5284910Swollman		case ETHERTYPE_NS:
5294910Swollman			schednetisr (NETISR_NS);
5304910Swollman			inq = &nsintrq;
5314910Swollman			break;
5324910Swollman#endif
5334910Swollman		}
5344910Swollman		break;
53525944Sjoerg	default:        /* Invalid PPP packet. */
53625944Sjoerg	  invalid:
53725944Sjoerg		if (debug)
53825944Sjoerg			log(LOG_DEBUG,
53925944Sjoerg			    "%s%d: invalid input packet "
54025944Sjoerg			    "<addr=0x%x ctrl=0x%x proto=0x%x>\n",
54125944Sjoerg			    ifp->if_name, ifp->if_unit,
54225944Sjoerg			    h->address, h->control, ntohs(h->protocol));
54325944Sjoerg		goto drop;
5444910Swollman	}
5454910Swollman
5464910Swollman	if (! (ifp->if_flags & IFF_UP) || ! inq)
5474910Swollman		goto drop;
5484910Swollman
5494910Swollman	/* Check queue. */
55025944Sjoerg	s = splimp();
5514910Swollman	if (IF_QFULL (inq)) {
5524910Swollman		/* Queue overflow. */
55325944Sjoerg		IF_DROP(inq);
55425944Sjoerg		splx(s);
55525944Sjoerg		if (debug)
55625706Sjoerg			log(LOG_DEBUG, "%s%d: protocol queue overflow\n",
5574910Swollman				ifp->if_name, ifp->if_unit);
5584910Swollman		goto drop;
5594910Swollman	}
56025944Sjoerg	IF_ENQUEUE(inq, m);
56125944Sjoerg	splx(s);
5624910Swollman}
5634910Swollman
5644910Swollman/*
5654910Swollman * Enqueue transmit packet.
5664910Swollman */
56712820Sphkstatic int
56825706Sjoergsppp_output(struct ifnet *ifp, struct mbuf *m,
56925706Sjoerg	    struct sockaddr *dst, struct rtentry *rt)
5704910Swollman{
5714910Swollman	struct sppp *sp = (struct sppp*) ifp;
5724910Swollman	struct ppp_header *h;
5734910Swollman	struct ifqueue *ifq;
57425955Sjoerg	int s, rv = 0;
5754910Swollman
57625944Sjoerg	s = splimp();
57725944Sjoerg
57825944Sjoerg	if ((ifp->if_flags & IFF_UP) == 0 ||
57925944Sjoerg	    (ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == 0) {
5804910Swollman		m_freem (m);
5814910Swollman		splx (s);
5824910Swollman		return (ENETDOWN);
5834910Swollman	}
5844910Swollman
58525944Sjoerg	if ((ifp->if_flags & (IFF_RUNNING | IFF_AUTO)) == IFF_AUTO) {
58625944Sjoerg		/*
58725944Sjoerg		 * Interface is not yet running, but auto-dial.  Need
58825944Sjoerg		 * to start LCP for it.
58925944Sjoerg		 */
59025944Sjoerg		ifp->if_flags |= IFF_RUNNING;
59125944Sjoerg		splx(s);
59225944Sjoerg		lcp.Open(sp);
59325944Sjoerg		s = splimp();
59425944Sjoerg	}
59525944Sjoerg
5964910Swollman	ifq = &ifp->if_snd;
5974910Swollman#ifdef INET
5984910Swollman	/*
5994910Swollman	 * Put low delay, telnet, rlogin and ftp control packets
6004910Swollman	 * in front of the queue.
6014910Swollman	 */
60212436Speter	if (dst->sa_family == AF_INET) {
60312436Speter		struct ip *ip = mtod (m, struct ip*);
60412436Speter		struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);
6054910Swollman
60612436Speter		if (! IF_QFULL (&sp->pp_fastq) &&
60712436Speter		    ((ip->ip_tos & IPTOS_LOWDELAY) ||
60812436Speter	    	    ip->ip_p == IPPROTO_TCP &&
60912436Speter	    	    m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) &&
61012436Speter	    	    (INTERACTIVE (ntohs (tcp->th_sport)) ||
61112436Speter	    	    INTERACTIVE (ntohs (tcp->th_dport)))))
61212436Speter			ifq = &sp->pp_fastq;
6134910Swollman	}
6144910Swollman#endif
6154910Swollman
6164910Swollman	/*
6174910Swollman	 * Prepend general data packet PPP header. For now, IP only.
6184910Swollman	 */
6194910Swollman	M_PREPEND (m, PPP_HEADER_LEN, M_DONTWAIT);
6204910Swollman	if (! m) {
6214910Swollman		if (ifp->if_flags & IFF_DEBUG)
62225706Sjoerg			log(LOG_DEBUG, "%s%d: no memory for transmit header\n",
6234910Swollman				ifp->if_name, ifp->if_unit);
62425944Sjoerg		++ifp->if_oerrors;
6254910Swollman		splx (s);
6264910Swollman		return (ENOBUFS);
6274910Swollman	}
6284910Swollman	h = mtod (m, struct ppp_header*);
6294910Swollman	if (sp->pp_flags & PP_CISCO) {
63028088Skjc		h->address = CISCO_UNICAST;        /* unicast address */
6314910Swollman		h->control = 0;
6324910Swollman	} else {
6334910Swollman		h->address = PPP_ALLSTATIONS;        /* broadcast address */
6344910Swollman		h->control = PPP_UI;                 /* Unnumbered Info */
6354910Swollman	}
6364910Swollman
6374910Swollman	switch (dst->sa_family) {
6384910Swollman#ifdef INET
6394910Swollman	case AF_INET:   /* Internet Protocol */
64011189Sjkh		if (sp->pp_flags & PP_CISCO)
64111189Sjkh			h->protocol = htons (ETHERTYPE_IP);
64211189Sjkh		else {
64325955Sjoerg			/*
64425955Sjoerg			 * Don't choke with an ENETDOWN early.  It's
64525955Sjoerg			 * possible that we just started dialing out,
64625955Sjoerg			 * so don't drop the packet immediately.  If
64725955Sjoerg			 * we notice that we run out of buffer space
64825955Sjoerg			 * below, we will however remember that we are
64925955Sjoerg			 * not ready to carry IP packets, and return
65025955Sjoerg			 * ENETDOWN, as opposed to ENOBUFS.
65125955Sjoerg			 */
65225955Sjoerg			h->protocol = htons(PPP_IP);
65325955Sjoerg			if (sp->state[IDX_IPCP] != STATE_OPENED)
65425955Sjoerg				rv = ENETDOWN;
65511189Sjkh		}
6564910Swollman		break;
6574910Swollman#endif
6584910Swollman#ifdef NS
6594910Swollman	case AF_NS:     /* Xerox NS Protocol */
6604910Swollman		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?
6614910Swollman			ETHERTYPE_NS : PPP_XNS);
6624910Swollman		break;
6634910Swollman#endif
66411819Sjulian#ifdef IPX
66512495Speter	case AF_IPX:     /* Novell IPX Protocol */
66611819Sjulian		h->protocol = htons ((sp->pp_flags & PP_CISCO) ?
66712495Speter			ETHERTYPE_IPX : PPP_IPX);
66811819Sjulian		break;
66911819Sjulian#endif
6704910Swollman#ifdef ISO
6714910Swollman	case AF_ISO:    /* ISO OSI Protocol */
6724910Swollman		if (sp->pp_flags & PP_CISCO)
6734910Swollman			goto nosupport;
6744910Swollman		h->protocol = htons (PPP_ISO);
6754910Swollman		break;
67612820Sphknosupport:
6774910Swollman#endif
6784910Swollman	default:
6794910Swollman		m_freem (m);
68025944Sjoerg		++ifp->if_oerrors;
6814910Swollman		splx (s);
6824910Swollman		return (EAFNOSUPPORT);
6834910Swollman	}
6844910Swollman
6854910Swollman	/*
6864910Swollman	 * Queue message on interface, and start output if interface
6874910Swollman	 * not yet active.
6884910Swollman	 */
6894910Swollman	if (IF_QFULL (ifq)) {
6904910Swollman		IF_DROP (&ifp->if_snd);
6914910Swollman		m_freem (m);
69225944Sjoerg		++ifp->if_oerrors;
6934910Swollman		splx (s);
69425955Sjoerg		return (rv? rv: ENOBUFS);
6954910Swollman	}
6964910Swollman	IF_ENQUEUE (ifq, m);
6974910Swollman	if (! (ifp->if_flags & IFF_OACTIVE))
6984910Swollman		(*ifp->if_start) (ifp);
6994910Swollman
7004910Swollman	/*
7014910Swollman	 * Count output packets and bytes.
7024910Swollman	 * The packet length includes header, FCS and 1 flag,
7034910Swollman	 * according to RFC 1333.
7044910Swollman	 */
7054910Swollman	ifp->if_obytes += m->m_pkthdr.len + 3;
7064910Swollman	splx (s);
7074910Swollman	return (0);
7084910Swollman}
7094910Swollman
71025706Sjoergvoid
71125706Sjoergsppp_attach(struct ifnet *ifp)
7124910Swollman{
7134910Swollman	struct sppp *sp = (struct sppp*) ifp;
7144910Swollman
7154910Swollman	/* Initialize keepalive handler. */
7164910Swollman	if (! spppq)
71730300Sjoerg		keepalive_ch = timeout(sppp_keepalive, 0, hz * 10);
7184910Swollman
7194910Swollman	/* Insert new entry into the keepalive list. */
7204910Swollman	sp->pp_next = spppq;
7214910Swollman	spppq = sp;
7224910Swollman
7234910Swollman	sp->pp_if.if_type = IFT_PPP;
7244910Swollman	sp->pp_if.if_output = sppp_output;
7254910Swollman	sp->pp_fastq.ifq_maxlen = 32;
72626018Sjoerg	sp->pp_cpq.ifq_maxlen = 20;
7274910Swollman	sp->pp_loopcnt = 0;
7284910Swollman	sp->pp_alivecnt = 0;
72911189Sjkh	sp->pp_seq = 0;
7304910Swollman	sp->pp_rseq = 0;
73125944Sjoerg	sp->pp_phase = PHASE_DEAD;
73225944Sjoerg	sp->pp_up = lcp.Up;
73325944Sjoerg	sp->pp_down = lcp.Down;
73425944Sjoerg
73525944Sjoerg	sppp_lcp_init(sp);
73625944Sjoerg	sppp_ipcp_init(sp);
73730300Sjoerg	sppp_pap_init(sp);
73830300Sjoerg	sppp_chap_init(sp);
7394910Swollman}
7404910Swollman
74130300Sjoergvoid
74225706Sjoergsppp_detach(struct ifnet *ifp)
7434910Swollman{
7444910Swollman	struct sppp **q, *p, *sp = (struct sppp*) ifp;
74525944Sjoerg	int i;
7464910Swollman
7474910Swollman	/* Remove the entry from the keepalive list. */
7484910Swollman	for (q = &spppq; (p = *q); q = &p->pp_next)
7494910Swollman		if (p == sp) {
7504910Swollman			*q = p->pp_next;
7514910Swollman			break;
7524910Swollman		}
7534910Swollman
7544910Swollman	/* Stop keepalive handler. */
7554910Swollman	if (! spppq)
75630300Sjoerg		untimeout(sppp_keepalive, 0, keepalive_ch);
75725944Sjoerg
75825944Sjoerg	for (i = 0; i < IDX_COUNT; i++)
75929681Sgibbs		untimeout((cps[i])->TO, (void *)sp, sp->ch[i]);
76030300Sjoerg	untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
7614910Swollman}
7624910Swollman
7634910Swollman/*
7644910Swollman * Flush the interface output queue.
7654910Swollman */
76625706Sjoergvoid
76725706Sjoergsppp_flush(struct ifnet *ifp)
7684910Swollman{
7694910Swollman	struct sppp *sp = (struct sppp*) ifp;
7704910Swollman
77125944Sjoerg	sppp_qflush (&sp->pp_if.if_snd);
77225944Sjoerg	sppp_qflush (&sp->pp_fastq);
77326018Sjoerg	sppp_qflush (&sp->pp_cpq);
7744910Swollman}
7754910Swollman
7764910Swollman/*
77711189Sjkh * Check if the output queue is empty.
77811189Sjkh */
77912820Sphkint
78025706Sjoergsppp_isempty(struct ifnet *ifp)
78111189Sjkh{
78211189Sjkh	struct sppp *sp = (struct sppp*) ifp;
78325944Sjoerg	int empty, s;
78411189Sjkh
78525944Sjoerg	s = splimp();
78626018Sjoerg	empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
78726018Sjoerg		!sp->pp_if.if_snd.ifq_head;
78825944Sjoerg	splx(s);
78911189Sjkh	return (empty);
79011189Sjkh}
79111189Sjkh
79211189Sjkh/*
7934910Swollman * Get next packet to send.
7944910Swollman */
79525706Sjoergstruct mbuf *
79625706Sjoergsppp_dequeue(struct ifnet *ifp)
7974910Swollman{
7984910Swollman	struct sppp *sp = (struct sppp*) ifp;
7994910Swollman	struct mbuf *m;
80025944Sjoerg	int s;
8014910Swollman
80225944Sjoerg	s = splimp();
80326018Sjoerg	/*
80430300Sjoerg	 * Process only the control protocol queue until we have at
80530300Sjoerg	 * least one NCP open.
80626018Sjoerg	 *
80726018Sjoerg	 * Do always serve all three queues in Cisco mode.
80826018Sjoerg	 */
80926018Sjoerg	IF_DEQUEUE(&sp->pp_cpq, m);
81026018Sjoerg	if (m == NULL &&
81130300Sjoerg	    (sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {
81226018Sjoerg		IF_DEQUEUE(&sp->pp_fastq, m);
81326018Sjoerg		if (m == NULL)
81426018Sjoerg			IF_DEQUEUE (&sp->pp_if.if_snd, m);
81526018Sjoerg	}
81626018Sjoerg	splx(s);
81726018Sjoerg	return m;
8184910Swollman}
8194910Swollman
8204910Swollman/*
82130300Sjoerg * Pick the next packet, do not remove it from the queue.
82230300Sjoerg */
82330300Sjoergstruct mbuf *
82430300Sjoergsppp_pick(struct ifnet *ifp)
82530300Sjoerg{
82630300Sjoerg	struct sppp *sp = (struct sppp*)ifp;
82730300Sjoerg	struct mbuf *m;
82830300Sjoerg	int s;
82930300Sjoerg
83030300Sjoerg	s= splimp ();
83130300Sjoerg
83230300Sjoerg	m = sp->pp_cpq.ifq_head;
83330300Sjoerg	if (m == NULL &&
83430300Sjoerg	    (sp->pp_phase == PHASE_NETWORK ||
83530300Sjoerg	     (sp->pp_flags & PP_CISCO) != 0))
83630300Sjoerg		if ((m = sp->pp_fastq.ifq_head) == NULL)
83730300Sjoerg			m = sp->pp_if.if_snd.ifq_head;
83830300Sjoerg	splx (s);
83930300Sjoerg	return (m);
84030300Sjoerg}
84130300Sjoerg
84230300Sjoerg/*
84325944Sjoerg * Process an ioctl request.  Called on low priority level.
8444910Swollman */
84525944Sjoergint
84625944Sjoergsppp_ioctl(struct ifnet *ifp, int cmd, void *data)
8474910Swollman{
84825944Sjoerg	struct ifreq *ifr = (struct ifreq*) data;
84925944Sjoerg	struct sppp *sp = (struct sppp*) ifp;
85030300Sjoerg	int s, rv, going_up, going_down, newmode;
8514910Swollman
85225944Sjoerg	s = splimp();
85330300Sjoerg	rv = 0;
85425944Sjoerg	switch (cmd) {
85525944Sjoerg	case SIOCAIFADDR:
85625944Sjoerg	case SIOCSIFDSTADDR:
85725944Sjoerg		break;
8584910Swollman
85925944Sjoerg	case SIOCSIFADDR:
86025944Sjoerg		if_up(ifp);
86125944Sjoerg		/* fall through... */
86211189Sjkh
86325944Sjoerg	case SIOCSIFFLAGS:
86425944Sjoerg		going_up = ifp->if_flags & IFF_UP &&
86525944Sjoerg			(ifp->if_flags & IFF_RUNNING) == 0;
86625944Sjoerg		going_down = (ifp->if_flags & IFF_UP) == 0 &&
86725944Sjoerg			ifp->if_flags & IFF_RUNNING;
86825944Sjoerg		newmode = ifp->if_flags & (IFF_AUTO | IFF_PASSIVE);
86925944Sjoerg		if (newmode == (IFF_AUTO | IFF_PASSIVE)) {
87025944Sjoerg			/* sanity */
87125944Sjoerg			newmode = IFF_PASSIVE;
87225944Sjoerg			ifp->if_flags &= ~IFF_AUTO;
8734910Swollman		}
8744910Swollman
87525944Sjoerg		if (going_up || going_down)
87625944Sjoerg			lcp.Close(sp);
87725944Sjoerg		if (going_up && newmode == 0) {
87825944Sjoerg			/* neither auto-dial nor passive */
87925944Sjoerg			ifp->if_flags |= IFF_RUNNING;
88025944Sjoerg			if (!(sp->pp_flags & PP_CISCO))
88125944Sjoerg				lcp.Open(sp);
88226018Sjoerg		} else if (going_down) {
88326018Sjoerg			sppp_flush(ifp);
88425944Sjoerg			ifp->if_flags &= ~IFF_RUNNING;
88526018Sjoerg		}
8864910Swollman
8874910Swollman		break;
88811189Sjkh
88925944Sjoerg#ifdef SIOCSIFMTU
89025944Sjoerg#ifndef ifr_mtu
89125944Sjoerg#define ifr_mtu ifr_metric
89225944Sjoerg#endif
89325944Sjoerg	case SIOCSIFMTU:
89425944Sjoerg		if (ifr->ifr_mtu < 128 || ifr->ifr_mtu > sp->lcp.their_mru)
89525944Sjoerg			return (EINVAL);
89625944Sjoerg		ifp->if_mtu = ifr->ifr_mtu;
8974910Swollman		break;
89825944Sjoerg#endif
89925944Sjoerg#ifdef SLIOCSETMTU
90025944Sjoerg	case SLIOCSETMTU:
90125944Sjoerg		if (*(short*)data < 128 || *(short*)data > sp->lcp.their_mru)
90225944Sjoerg			return (EINVAL);
90325944Sjoerg		ifp->if_mtu = *(short*)data;
9044910Swollman		break;
90525944Sjoerg#endif
90625944Sjoerg#ifdef SIOCGIFMTU
90725944Sjoerg	case SIOCGIFMTU:
90825944Sjoerg		ifr->ifr_mtu = ifp->if_mtu;
90911189Sjkh		break;
91025944Sjoerg#endif
91125944Sjoerg#ifdef SLIOCGETMTU
91225944Sjoerg	case SLIOCGETMTU:
91325944Sjoerg		*(short*)data = ifp->if_mtu;
9144910Swollman		break;
91525944Sjoerg#endif
91625944Sjoerg	case SIOCADDMULTI:
91725944Sjoerg	case SIOCDELMULTI:
9184910Swollman		break;
91911189Sjkh
92030300Sjoerg	case SIOCGIFGENERIC:
92130300Sjoerg	case SIOCSIFGENERIC:
92230300Sjoerg		rv = sppp_params(sp, cmd, data);
92330300Sjoerg		break;
92430300Sjoerg
92525944Sjoerg	default:
92630300Sjoerg		rv = ENOTTY;
9274910Swollman	}
92825944Sjoerg	splx(s);
92930300Sjoerg	return rv;
9304910Swollman}
9314910Swollman
93225944Sjoerg
93325944Sjoerg/*
93425944Sjoerg * Cisco framing implementation.
93525944Sjoerg */
93625944Sjoerg
9374910Swollman/*
9384910Swollman * Handle incoming Cisco keepalive protocol packets.
9394910Swollman */
94030300Sjoergstatic void
94125706Sjoergsppp_cisco_input(struct sppp *sp, struct mbuf *m)
9424910Swollman{
94325944Sjoerg	STDDCL;
9444910Swollman	struct cisco_packet *h;
94530300Sjoerg	u_long me, mymask;
9464910Swollman
94727929Sitojun	if (m->m_pkthdr.len < CISCO_PACKET_LEN) {
94825706Sjoerg		if (debug)
94925706Sjoerg			log(LOG_DEBUG,
95030300Sjoerg			    "%s%d: cisco invalid packet length: %d bytes\n",
95125706Sjoerg			    ifp->if_name, ifp->if_unit, m->m_pkthdr.len);
9524910Swollman		return;
9534910Swollman	}
9544910Swollman	h = mtod (m, struct cisco_packet*);
95525706Sjoerg	if (debug)
95625706Sjoerg		log(LOG_DEBUG,
95725706Sjoerg		    "%s%d: cisco input: %d bytes "
95825706Sjoerg		    "<0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n",
95925706Sjoerg		    ifp->if_name, ifp->if_unit, m->m_pkthdr.len,
96025706Sjoerg		    ntohl (h->type), h->par1, h->par2, h->rel,
96125706Sjoerg		    h->time0, h->time1);
9624910Swollman	switch (ntohl (h->type)) {
9634910Swollman	default:
96425706Sjoerg		if (debug)
96530300Sjoerg			addlog("%s%d: cisco unknown packet type: 0x%lx\n",
96625706Sjoerg			       ifp->if_name, ifp->if_unit, ntohl (h->type));
9674910Swollman		break;
9684910Swollman	case CISCO_ADDR_REPLY:
9694910Swollman		/* Reply on address request, ignore */
9704910Swollman		break;
9714910Swollman	case CISCO_KEEPALIVE_REQ:
9724910Swollman		sp->pp_alivecnt = 0;
9734910Swollman		sp->pp_rseq = ntohl (h->par1);
9744910Swollman		if (sp->pp_seq == sp->pp_rseq) {
9754910Swollman			/* Local and remote sequence numbers are equal.
9764910Swollman			 * Probably, the line is in loopback mode. */
97711189Sjkh			if (sp->pp_loopcnt >= MAXALIVECNT) {
97811189Sjkh				printf ("%s%d: loopback\n",
97911189Sjkh					ifp->if_name, ifp->if_unit);
98011189Sjkh				sp->pp_loopcnt = 0;
98111189Sjkh				if (ifp->if_flags & IFF_UP) {
98211189Sjkh					if_down (ifp);
98326018Sjoerg					sppp_qflush (&sp->pp_cpq);
98411189Sjkh				}
98511189Sjkh			}
9864910Swollman			++sp->pp_loopcnt;
9874910Swollman
9884910Swollman			/* Generate new local sequence number */
9894910Swollman			sp->pp_seq ^= time.tv_sec ^ time.tv_usec;
99011189Sjkh			break;
99111189Sjkh		}
99230300Sjoerg		sp->pp_loopcnt = 0;
99311189Sjkh		if (! (ifp->if_flags & IFF_UP) &&
99411189Sjkh		    (ifp->if_flags & IFF_RUNNING)) {
99530300Sjoerg			if_up(ifp);
99611189Sjkh			printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
99711189Sjkh		}
9984910Swollman		break;
9994910Swollman	case CISCO_ADDR_REQ:
100030300Sjoerg		sppp_get_ip_addrs(sp, &me, 0, &mymask);
100130300Sjoerg		if (me != 0L)
100230300Sjoerg			sppp_cisco_send(sp, CISCO_ADDR_REPLY, me, mymask);
10034910Swollman		break;
10044910Swollman	}
10054910Swollman}
10064910Swollman
10074910Swollman/*
100825944Sjoerg * Send Cisco keepalive packet.
10094910Swollman */
101012820Sphkstatic void
101125944Sjoergsppp_cisco_send(struct sppp *sp, int type, long par1, long par2)
101225944Sjoerg{
101325944Sjoerg	STDDCL;
101425944Sjoerg	struct ppp_header *h;
101525944Sjoerg	struct cisco_packet *ch;
101625944Sjoerg	struct mbuf *m;
101725944Sjoerg	u_long t = (time.tv_sec - boottime.tv_sec) * 1000;
101825944Sjoerg
101925944Sjoerg	MGETHDR (m, M_DONTWAIT, MT_DATA);
102025944Sjoerg	if (! m)
102125944Sjoerg		return;
102225944Sjoerg	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + CISCO_PACKET_LEN;
102325944Sjoerg	m->m_pkthdr.rcvif = 0;
102425944Sjoerg
102525944Sjoerg	h = mtod (m, struct ppp_header*);
102625944Sjoerg	h->address = CISCO_MULTICAST;
102725944Sjoerg	h->control = 0;
102825944Sjoerg	h->protocol = htons (CISCO_KEEPALIVE);
102925944Sjoerg
103025944Sjoerg	ch = (struct cisco_packet*) (h + 1);
103125944Sjoerg	ch->type = htonl (type);
103225944Sjoerg	ch->par1 = htonl (par1);
103325944Sjoerg	ch->par2 = htonl (par2);
103425944Sjoerg	ch->rel = -1;
103525944Sjoerg	ch->time0 = htons ((u_short) (t >> 16));
103625944Sjoerg	ch->time1 = htons ((u_short) t);
103725944Sjoerg
103825944Sjoerg	if (debug)
103925944Sjoerg		log(LOG_DEBUG,
104025944Sjoerg		    "%s%d: cisco output: <0x%lx 0x%lx 0x%lx 0x%x 0x%x-0x%x>\n",
104125944Sjoerg			ifp->if_name, ifp->if_unit, ntohl (ch->type), ch->par1,
104225944Sjoerg			ch->par2, ch->rel, ch->time0, ch->time1);
104325944Sjoerg
104426018Sjoerg	if (IF_QFULL (&sp->pp_cpq)) {
104526018Sjoerg		IF_DROP (&sp->pp_fastq);
104625944Sjoerg		IF_DROP (&ifp->if_snd);
104725944Sjoerg		m_freem (m);
104825944Sjoerg	} else
104926018Sjoerg		IF_ENQUEUE (&sp->pp_cpq, m);
105025944Sjoerg	if (! (ifp->if_flags & IFF_OACTIVE))
105125944Sjoerg		(*ifp->if_start) (ifp);
105225944Sjoerg	ifp->if_obytes += m->m_pkthdr.len + 3;
105325944Sjoerg}
105425944Sjoerg
105525944Sjoerg/*
105625944Sjoerg * PPP protocol implementation.
105725944Sjoerg */
105825944Sjoerg
105925944Sjoerg/*
106025944Sjoerg * Send PPP control protocol packet.
106125944Sjoerg */
106225944Sjoergstatic void
106325706Sjoergsppp_cp_send(struct sppp *sp, u_short proto, u_char type,
106425706Sjoerg	     u_char ident, u_short len, void *data)
10654910Swollman{
106625944Sjoerg	STDDCL;
10674910Swollman	struct ppp_header *h;
10684910Swollman	struct lcp_header *lh;
10694910Swollman	struct mbuf *m;
10704910Swollman
10714910Swollman	if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN)
10724910Swollman		len = MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN;
10734910Swollman	MGETHDR (m, M_DONTWAIT, MT_DATA);
10744910Swollman	if (! m)
10754910Swollman		return;
10764910Swollman	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;
10774910Swollman	m->m_pkthdr.rcvif = 0;
10784910Swollman
10794910Swollman	h = mtod (m, struct ppp_header*);
10804910Swollman	h->address = PPP_ALLSTATIONS;        /* broadcast address */
10814910Swollman	h->control = PPP_UI;                 /* Unnumbered Info */
10824910Swollman	h->protocol = htons (proto);         /* Link Control Protocol */
10834910Swollman
10844910Swollman	lh = (struct lcp_header*) (h + 1);
10854910Swollman	lh->type = type;
10864910Swollman	lh->ident = ident;
10874910Swollman	lh->len = htons (LCP_HEADER_LEN + len);
10884910Swollman	if (len)
10894910Swollman		bcopy (data, lh+1, len);
10904910Swollman
109125706Sjoerg	if (debug) {
109225944Sjoerg		log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d",
109325944Sjoerg		    ifp->if_name, ifp->if_unit,
109425944Sjoerg		    sppp_proto_name(proto),
109525944Sjoerg		    sppp_cp_type_name (lh->type), lh->ident,
109625944Sjoerg		    ntohs (lh->len));
10974910Swollman		if (len)
109811189Sjkh			sppp_print_bytes ((u_char*) (lh+1), len);
109925706Sjoerg		addlog(">\n");
11004910Swollman	}
110126018Sjoerg	if (IF_QFULL (&sp->pp_cpq)) {
110226018Sjoerg		IF_DROP (&sp->pp_fastq);
11034910Swollman		IF_DROP (&ifp->if_snd);
11044910Swollman		m_freem (m);
110525944Sjoerg		++ifp->if_oerrors;
11064910Swollman	} else
110726018Sjoerg		IF_ENQUEUE (&sp->pp_cpq, m);
11084910Swollman	if (! (ifp->if_flags & IFF_OACTIVE))
11094910Swollman		(*ifp->if_start) (ifp);
11104910Swollman	ifp->if_obytes += m->m_pkthdr.len + 3;
11114910Swollman}
11124910Swollman
11134910Swollman/*
111425944Sjoerg * Handle incoming PPP control protocol packets.
11154910Swollman */
111612820Sphkstatic void
111725944Sjoergsppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m)
11184910Swollman{
111925944Sjoerg	STDDCL;
112025944Sjoerg	struct lcp_header *h;
112125944Sjoerg	int len = m->m_pkthdr.len;
112225944Sjoerg	int rv;
112325944Sjoerg	u_char *p;
11244910Swollman
112525944Sjoerg	if (len < 4) {
112625944Sjoerg		if (debug)
112725944Sjoerg			log(LOG_DEBUG,
112825944Sjoerg			    "%s%d: %s invalid packet length: %d bytes\n",
112925944Sjoerg			    ifp->if_name, ifp->if_unit, cp->name, len);
11304910Swollman		return;
113125944Sjoerg	}
113225944Sjoerg	h = mtod (m, struct lcp_header*);
113325944Sjoerg	if (debug) {
113425944Sjoerg		log(LOG_DEBUG,
113525944Sjoerg		    "%s%d: %s input(%s): <%s id=0x%x len=%d",
113625944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
113725944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]),
113825944Sjoerg		    sppp_cp_type_name (h->type), h->ident, ntohs (h->len));
113925944Sjoerg		if (len > 4)
114025944Sjoerg			sppp_print_bytes ((u_char*) (h+1), len-4);
114125944Sjoerg		addlog(">\n");
114225944Sjoerg	}
114325944Sjoerg	if (len > ntohs (h->len))
114425944Sjoerg		len = ntohs (h->len);
114530300Sjoerg	p = (u_char *)(h + 1);
114625944Sjoerg	switch (h->type) {
114725944Sjoerg	case CONF_REQ:
114825944Sjoerg		if (len < 4) {
114925944Sjoerg			if (debug)
115025944Sjoerg				addlog("%s%d: %s invalid conf-req length %d\n",
115125944Sjoerg				       ifp->if_name, ifp->if_unit, cp->name,
115225944Sjoerg				       len);
115325944Sjoerg			++ifp->if_ierrors;
115425944Sjoerg			break;
115525944Sjoerg		}
115630300Sjoerg		/* handle states where RCR doesn't get a SCA/SCN */
115730300Sjoerg		switch (sp->state[cp->protoidx]) {
115830300Sjoerg		case STATE_CLOSING:
115930300Sjoerg		case STATE_STOPPING:
116030300Sjoerg			return;
116130300Sjoerg		case STATE_CLOSED:
116230300Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident,
116330300Sjoerg				     0, 0);
116430300Sjoerg			return;
116530300Sjoerg		}
116625944Sjoerg		rv = (cp->RCR)(sp, h, len);
116725944Sjoerg		switch (sp->state[cp->protoidx]) {
116825944Sjoerg		case STATE_OPENED:
116925944Sjoerg			(cp->tld)(sp);
117025944Sjoerg			(cp->scr)(sp);
117125944Sjoerg			/* fall through... */
117225944Sjoerg		case STATE_ACK_SENT:
117325944Sjoerg		case STATE_REQ_SENT:
117425944Sjoerg			sppp_cp_change_state(cp, sp, rv?
117525944Sjoerg					     STATE_ACK_SENT: STATE_REQ_SENT);
117625944Sjoerg			break;
117725944Sjoerg		case STATE_STOPPED:
117825944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
117925944Sjoerg			(cp->scr)(sp);
118025944Sjoerg			sppp_cp_change_state(cp, sp, rv?
118125944Sjoerg					     STATE_ACK_SENT: STATE_REQ_SENT);
118225944Sjoerg			break;
118325944Sjoerg		case STATE_ACK_RCVD:
118425944Sjoerg			if (rv) {
118525944Sjoerg				sppp_cp_change_state(cp, sp, STATE_OPENED);
118625944Sjoerg				if (debug)
118726077Sjoerg					log(LOG_DEBUG, "%s%d: %s tlu\n",
118826077Sjoerg					    ifp->if_name, ifp->if_unit,
118926077Sjoerg					    cp->name);
119025944Sjoerg				(cp->tlu)(sp);
119125944Sjoerg			} else
119225944Sjoerg				sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
119325944Sjoerg			break;
119425944Sjoerg		default:
119525944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
119625944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
119725944Sjoerg			       sppp_cp_type_name(h->type),
119825944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
119925944Sjoerg			++ifp->if_ierrors;
120025944Sjoerg		}
120125944Sjoerg		break;
120225944Sjoerg	case CONF_ACK:
120325944Sjoerg		if (h->ident != sp->confid[cp->protoidx]) {
120425944Sjoerg			if (debug)
120525944Sjoerg				addlog("%s%d: %s id mismatch 0x%x != 0x%x\n",
120625944Sjoerg				       ifp->if_name, ifp->if_unit, cp->name,
120725944Sjoerg				       h->ident, sp->confid[cp->protoidx]);
120825944Sjoerg			++ifp->if_ierrors;
120925944Sjoerg			break;
121025944Sjoerg		}
121125944Sjoerg		switch (sp->state[cp->protoidx]) {
121225944Sjoerg		case STATE_CLOSED:
121325944Sjoerg		case STATE_STOPPED:
121425944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
121525944Sjoerg			break;
121625944Sjoerg		case STATE_CLOSING:
121725944Sjoerg		case STATE_STOPPING:
121825944Sjoerg			break;
121925944Sjoerg		case STATE_REQ_SENT:
122025944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
122125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
122225944Sjoerg			break;
122325944Sjoerg		case STATE_OPENED:
122425944Sjoerg			(cp->tld)(sp);
122525944Sjoerg			/* fall through */
122625944Sjoerg		case STATE_ACK_RCVD:
122725944Sjoerg			(cp->scr)(sp);
122825944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
122925944Sjoerg			break;
123025944Sjoerg		case STATE_ACK_SENT:
123125944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
123225944Sjoerg			sppp_cp_change_state(cp, sp, STATE_OPENED);
123325944Sjoerg			if (debug)
123430300Sjoerg				log(LOG_DEBUG, "%s%d: %s tlu\n",
123525944Sjoerg				       ifp->if_name, ifp->if_unit, cp->name);
123625944Sjoerg			(cp->tlu)(sp);
123725944Sjoerg			break;
123825944Sjoerg		default:
123925944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
124025944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
124125944Sjoerg			       sppp_cp_type_name(h->type),
124225944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
124325944Sjoerg			++ifp->if_ierrors;
124425944Sjoerg		}
124525944Sjoerg		break;
124625944Sjoerg	case CONF_NAK:
124725944Sjoerg	case CONF_REJ:
124825944Sjoerg		if (h->ident != sp->confid[cp->protoidx]) {
124925944Sjoerg			if (debug)
125025944Sjoerg				addlog("%s%d: %s id mismatch 0x%x != 0x%x\n",
125125944Sjoerg				       ifp->if_name, ifp->if_unit, cp->name,
125225944Sjoerg				       h->ident, sp->confid[cp->protoidx]);
125325944Sjoerg			++ifp->if_ierrors;
125425944Sjoerg			break;
125525944Sjoerg		}
125625944Sjoerg		if (h->type == CONF_NAK)
125725944Sjoerg			(cp->RCN_nak)(sp, h, len);
125825944Sjoerg		else /* CONF_REJ */
125925944Sjoerg			(cp->RCN_rej)(sp, h, len);
12604910Swollman
126125944Sjoerg		switch (sp->state[cp->protoidx]) {
126225944Sjoerg		case STATE_CLOSED:
126325944Sjoerg		case STATE_STOPPED:
126425944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
126525944Sjoerg			break;
126625944Sjoerg		case STATE_REQ_SENT:
126725944Sjoerg		case STATE_ACK_SENT:
126825944Sjoerg			sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
126925944Sjoerg			(cp->scr)(sp);
127025944Sjoerg			break;
127125944Sjoerg		case STATE_OPENED:
127225944Sjoerg			(cp->tld)(sp);
127325944Sjoerg			/* fall through */
127425944Sjoerg		case STATE_ACK_RCVD:
127525944Sjoerg			sppp_cp_change_state(cp, sp, STATE_ACK_SENT);
127625944Sjoerg			(cp->scr)(sp);
127725944Sjoerg			break;
127825944Sjoerg		case STATE_CLOSING:
127925944Sjoerg		case STATE_STOPPING:
128025944Sjoerg			break;
128125944Sjoerg		default:
128225944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
128325944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
128425944Sjoerg			       sppp_cp_type_name(h->type),
128525944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
128625944Sjoerg			++ifp->if_ierrors;
128725944Sjoerg		}
128825944Sjoerg		break;
12894910Swollman
129025944Sjoerg	case TERM_REQ:
129125944Sjoerg		switch (sp->state[cp->protoidx]) {
129225944Sjoerg		case STATE_ACK_RCVD:
129325944Sjoerg		case STATE_ACK_SENT:
129425944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
129525944Sjoerg			/* fall through */
129625944Sjoerg		case STATE_CLOSED:
129725944Sjoerg		case STATE_STOPPED:
129825944Sjoerg		case STATE_CLOSING:
129925944Sjoerg		case STATE_STOPPING:
130025944Sjoerg		case STATE_REQ_SENT:
130125944Sjoerg		  sta:
130225944Sjoerg			/* Send Terminate-Ack packet. */
130325944Sjoerg			if (debug)
130425944Sjoerg				log(LOG_DEBUG, "%s%d: %s send terminate-ack\n",
130525944Sjoerg				    ifp->if_name, ifp->if_unit, cp->name);
130625944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_ACK, h->ident, 0, 0);
130725944Sjoerg			break;
130825944Sjoerg		case STATE_OPENED:
130925944Sjoerg			(cp->tld)(sp);
131025944Sjoerg			sp->rst_counter[cp->protoidx] = 0;
131125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_STOPPING);
131225944Sjoerg			goto sta;
131325944Sjoerg			break;
131425944Sjoerg		default:
131525944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
131625944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
131725944Sjoerg			       sppp_cp_type_name(h->type),
131825944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
131925944Sjoerg			++ifp->if_ierrors;
132025944Sjoerg		}
132125944Sjoerg		break;
132225944Sjoerg	case TERM_ACK:
132325944Sjoerg		switch (sp->state[cp->protoidx]) {
132425944Sjoerg		case STATE_CLOSED:
132525944Sjoerg		case STATE_STOPPED:
132625944Sjoerg		case STATE_REQ_SENT:
132725944Sjoerg		case STATE_ACK_SENT:
132825944Sjoerg			break;
132925944Sjoerg		case STATE_CLOSING:
133025944Sjoerg			(cp->tlf)(sp);
133125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_CLOSED);
133225944Sjoerg			break;
133325944Sjoerg		case STATE_STOPPING:
133425944Sjoerg			(cp->tlf)(sp);
133525944Sjoerg			sppp_cp_change_state(cp, sp, STATE_STOPPED);
133625944Sjoerg			break;
133725944Sjoerg		case STATE_ACK_RCVD:
133825944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
133925944Sjoerg			break;
134025944Sjoerg		case STATE_OPENED:
134125944Sjoerg			(cp->tld)(sp);
134225944Sjoerg			(cp->scr)(sp);
134325944Sjoerg			sppp_cp_change_state(cp, sp, STATE_ACK_RCVD);
134425944Sjoerg			break;
134525944Sjoerg		default:
134625944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
134725944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
134825944Sjoerg			       sppp_cp_type_name(h->type),
134925944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
135025944Sjoerg			++ifp->if_ierrors;
135125944Sjoerg		}
135225944Sjoerg		break;
135325944Sjoerg	case CODE_REJ:
135425944Sjoerg	case PROTO_REJ:
135525944Sjoerg		/* XXX catastrophic rejects (RXJ-) aren't handled yet. */
135630300Sjoerg		log(LOG_INFO,
135730300Sjoerg		    "%s%d: %s: ignoring RXJ (%s) for proto 0x%x, "
135830300Sjoerg		    "danger will robinson\n",
135930300Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
136030300Sjoerg		    sppp_cp_type_name(h->type), ntohs(*((u_short *)p)));
136125944Sjoerg		switch (sp->state[cp->protoidx]) {
136225944Sjoerg		case STATE_CLOSED:
136325944Sjoerg		case STATE_STOPPED:
136425944Sjoerg		case STATE_REQ_SENT:
136525944Sjoerg		case STATE_ACK_SENT:
136625944Sjoerg		case STATE_CLOSING:
136725944Sjoerg		case STATE_STOPPING:
136825944Sjoerg		case STATE_OPENED:
136925944Sjoerg			break;
137025944Sjoerg		case STATE_ACK_RCVD:
137125944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
137225944Sjoerg			break;
137325944Sjoerg		default:
137425944Sjoerg			printf("%s%d: %s illegal %s in state %s\n",
137525944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name,
137625944Sjoerg			       sppp_cp_type_name(h->type),
137725944Sjoerg			       sppp_state_name(sp->state[cp->protoidx]));
137825944Sjoerg			++ifp->if_ierrors;
137925944Sjoerg		}
138025944Sjoerg		break;
138125944Sjoerg	case DISC_REQ:
138225944Sjoerg		if (cp->proto != PPP_LCP)
138325944Sjoerg			goto illegal;
138425944Sjoerg		/* Discard the packet. */
138525944Sjoerg		break;
138625944Sjoerg	case ECHO_REQ:
138725944Sjoerg		if (cp->proto != PPP_LCP)
138825944Sjoerg			goto illegal;
138925944Sjoerg		if (sp->state[cp->protoidx] != STATE_OPENED) {
139025944Sjoerg			if (debug)
139125944Sjoerg				addlog("%s%d: lcp echo req but lcp closed\n",
139225944Sjoerg				       ifp->if_name, ifp->if_unit);
139325944Sjoerg			++ifp->if_ierrors;
139425944Sjoerg			break;
139525944Sjoerg		}
139625944Sjoerg		if (len < 8) {
139725944Sjoerg			if (debug)
139825944Sjoerg				addlog("%s%d: invalid lcp echo request "
139925944Sjoerg				       "packet length: %d bytes\n",
140025944Sjoerg				       ifp->if_name, ifp->if_unit, len);
140125944Sjoerg			break;
140225944Sjoerg		}
140325944Sjoerg		if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {
140425944Sjoerg			/* Line loopback mode detected. */
140525944Sjoerg			printf("%s%d: loopback\n", ifp->if_name, ifp->if_unit);
140625944Sjoerg			if_down (ifp);
140726018Sjoerg			sppp_qflush (&sp->pp_cpq);
14084910Swollman
140925944Sjoerg			/* Shut down the PPP link. */
141025944Sjoerg			/* XXX */
141125944Sjoerg			lcp.Down(sp);
141225944Sjoerg			lcp.Up(sp);
141325944Sjoerg			break;
141425944Sjoerg		}
141525944Sjoerg		*(long*)(h+1) = htonl (sp->lcp.magic);
141625944Sjoerg		if (debug)
141725944Sjoerg			addlog("%s%d: got lcp echo req, sending echo rep\n",
141825944Sjoerg			       ifp->if_name, ifp->if_unit);
141925944Sjoerg		sppp_cp_send (sp, PPP_LCP, ECHO_REPLY, h->ident, len-4, h+1);
142025944Sjoerg		break;
142125944Sjoerg	case ECHO_REPLY:
142225944Sjoerg		if (cp->proto != PPP_LCP)
142325944Sjoerg			goto illegal;
142425944Sjoerg		if (h->ident != sp->lcp.echoid) {
142525944Sjoerg			++ifp->if_ierrors;
142625944Sjoerg			break;
142725944Sjoerg		}
142825944Sjoerg		if (len < 8) {
142925944Sjoerg			if (debug)
143025944Sjoerg				addlog("%s%d: lcp invalid echo reply "
143125944Sjoerg				       "packet length: %d bytes\n",
143225944Sjoerg				       ifp->if_name, ifp->if_unit, len);
143325944Sjoerg			break;
143425944Sjoerg		}
143525944Sjoerg		if (debug)
143625944Sjoerg			addlog("%s%d: lcp got echo rep\n",
143725944Sjoerg			       ifp->if_name, ifp->if_unit);
143825944Sjoerg		if (ntohl (*(long*)(h+1)) != sp->lcp.magic)
143925944Sjoerg			sp->pp_alivecnt = 0;
144025944Sjoerg		break;
144125944Sjoerg	default:
144225944Sjoerg		/* Unknown packet type -- send Code-Reject packet. */
144325944Sjoerg	  illegal:
144425944Sjoerg		if (debug)
144525944Sjoerg			addlog("%s%d: %c send code-rej for 0x%x\n",
144625944Sjoerg			       ifp->if_name, ifp->if_unit, cp->name, h->type);
144725944Sjoerg		sppp_cp_send(sp, cp->proto, CODE_REJ, ++sp->pp_seq,
144825944Sjoerg			     m->m_pkthdr.len, h);
144925944Sjoerg		++ifp->if_ierrors;
145025944Sjoerg	}
14514910Swollman}
14524910Swollman
145325944Sjoerg
14544910Swollman/*
145525944Sjoerg * The generic part of all Up/Down/Open/Close/TO event handlers.
145625944Sjoerg * Basically, the state transition handling in the automaton.
14574910Swollman */
145825944Sjoergstatic void
145925944Sjoergsppp_up_event(const struct cp *cp, struct sppp *sp)
14604910Swollman{
146125944Sjoerg	STDDCL;
14624910Swollman
146325944Sjoerg	if (debug)
146425944Sjoerg		log(LOG_DEBUG, "%s%d: %s up(%s)\n",
146525944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
146625944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
146725944Sjoerg
146825944Sjoerg	switch (sp->state[cp->protoidx]) {
146925944Sjoerg	case STATE_INITIAL:
147025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSED);
147125944Sjoerg		break;
147225944Sjoerg	case STATE_STARTING:
147325944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
147425944Sjoerg		(cp->scr)(sp);
147525944Sjoerg		sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
147625944Sjoerg		break;
14774910Swollman	default:
147825944Sjoerg		printf("%s%d: %s illegal up in state %s\n",
147925944Sjoerg		       ifp->if_name, ifp->if_unit, cp->name,
148025944Sjoerg		       sppp_state_name(sp->state[cp->protoidx]));
148125944Sjoerg	}
148225944Sjoerg}
14834910Swollman
148425944Sjoergstatic void
148525944Sjoergsppp_down_event(const struct cp *cp, struct sppp *sp)
148625944Sjoerg{
148725944Sjoerg	STDDCL;
148825944Sjoerg
148925944Sjoerg	if (debug)
149025944Sjoerg		log(LOG_DEBUG, "%s%d: %s down(%s)\n",
149125944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
149225944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
149325944Sjoerg
149425944Sjoerg	switch (sp->state[cp->protoidx]) {
149525944Sjoerg	case STATE_CLOSED:
149625944Sjoerg	case STATE_CLOSING:
149725944Sjoerg		sppp_cp_change_state(cp, sp, STATE_INITIAL);
14984910Swollman		break;
149925944Sjoerg	case STATE_STOPPED:
150025944Sjoerg		(cp->tls)(sp);
150125944Sjoerg		/* fall through */
150225944Sjoerg	case STATE_STOPPING:
150325944Sjoerg	case STATE_REQ_SENT:
150425944Sjoerg	case STATE_ACK_RCVD:
150525944Sjoerg	case STATE_ACK_SENT:
150625944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
150725944Sjoerg		break;
150825944Sjoerg	case STATE_OPENED:
150925944Sjoerg		(cp->tld)(sp);
151025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
151125944Sjoerg		break;
151225944Sjoerg	default:
151325944Sjoerg		printf("%s%d: %s illegal down in state %s\n",
151425944Sjoerg		       ifp->if_name, ifp->if_unit, cp->name,
151525944Sjoerg		       sppp_state_name(sp->state[cp->protoidx]));
151625944Sjoerg	}
151725944Sjoerg}
15184910Swollman
151911189Sjkh
152025944Sjoergstatic void
152125944Sjoergsppp_open_event(const struct cp *cp, struct sppp *sp)
152225944Sjoerg{
152325944Sjoerg	STDDCL;
152425944Sjoerg
152525944Sjoerg	if (debug)
152625944Sjoerg		log(LOG_DEBUG, "%s%d: %s open(%s)\n",
152725944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
152825944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
152925944Sjoerg
153025944Sjoerg	switch (sp->state[cp->protoidx]) {
153125944Sjoerg	case STATE_INITIAL:
153225944Sjoerg		(cp->tls)(sp);
153325944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STARTING);
15344910Swollman		break;
153525944Sjoerg	case STATE_STARTING:
153625944Sjoerg		break;
153725944Sjoerg	case STATE_CLOSED:
153825944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_configure;
153925944Sjoerg		(cp->scr)(sp);
154025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
154125944Sjoerg		break;
154225944Sjoerg	case STATE_STOPPED:
154325944Sjoerg	case STATE_STOPPING:
154425944Sjoerg	case STATE_REQ_SENT:
154525944Sjoerg	case STATE_ACK_RCVD:
154625944Sjoerg	case STATE_ACK_SENT:
154725944Sjoerg	case STATE_OPENED:
154825944Sjoerg		break;
154925944Sjoerg	case STATE_CLOSING:
155025944Sjoerg		sppp_cp_change_state(cp, sp, STATE_STOPPING);
155125944Sjoerg		break;
155225944Sjoerg	}
155325944Sjoerg}
15544910Swollman
155525944Sjoerg
155625944Sjoergstatic void
155725944Sjoergsppp_close_event(const struct cp *cp, struct sppp *sp)
155825944Sjoerg{
155925944Sjoerg	STDDCL;
156025944Sjoerg
156125944Sjoerg	if (debug)
156225944Sjoerg		log(LOG_DEBUG, "%s%d: %s close(%s)\n",
156325944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
156425944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]));
156525944Sjoerg
156625944Sjoerg	switch (sp->state[cp->protoidx]) {
156725944Sjoerg	case STATE_INITIAL:
156825944Sjoerg	case STATE_CLOSED:
156925944Sjoerg	case STATE_CLOSING:
15704910Swollman		break;
157125944Sjoerg	case STATE_STARTING:
157225944Sjoerg		(cp->tlf)(sp);
157325944Sjoerg		sppp_cp_change_state(cp, sp, STATE_INITIAL);
15744910Swollman		break;
157525944Sjoerg	case STATE_STOPPED:
157625944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSED);
15774910Swollman		break;
157825944Sjoerg	case STATE_STOPPING:
157925944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSING);
15804910Swollman		break;
158125944Sjoerg	case STATE_OPENED:
158225944Sjoerg		(cp->tld)(sp);
158325944Sjoerg		/* fall through */
158425944Sjoerg	case STATE_REQ_SENT:
158525944Sjoerg	case STATE_ACK_RCVD:
158625944Sjoerg	case STATE_ACK_SENT:
158725944Sjoerg		sp->rst_counter[cp->protoidx] = sp->lcp.max_terminate;
158825944Sjoerg		sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq, 0, 0);
158925944Sjoerg		sppp_cp_change_state(cp, sp, STATE_CLOSING);
15904910Swollman		break;
15914910Swollman	}
15924910Swollman}
15934910Swollman
159425944Sjoergstatic void
159525944Sjoergsppp_to_event(const struct cp *cp, struct sppp *sp)
159625944Sjoerg{
159725944Sjoerg	STDDCL;
159825944Sjoerg	int s;
159925944Sjoerg
160025944Sjoerg	s = splimp();
160125944Sjoerg	if (debug)
160225944Sjoerg		log(LOG_DEBUG, "%s%d: %s TO(%s) rst_counter = %d\n",
160325944Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
160425944Sjoerg		    sppp_state_name(sp->state[cp->protoidx]),
160525944Sjoerg		    sp->rst_counter[cp->protoidx]);
160625944Sjoerg
160725944Sjoerg	if (--sp->rst_counter[cp->protoidx] < 0)
160825944Sjoerg		/* TO- event */
160925944Sjoerg		switch (sp->state[cp->protoidx]) {
161025944Sjoerg		case STATE_CLOSING:
161125944Sjoerg			(cp->tlf)(sp);
161225944Sjoerg			sppp_cp_change_state(cp, sp, STATE_CLOSED);
161325944Sjoerg			break;
161425944Sjoerg		case STATE_STOPPING:
161525944Sjoerg			(cp->tlf)(sp);
161625944Sjoerg			sppp_cp_change_state(cp, sp, STATE_STOPPED);
161725944Sjoerg			break;
161825944Sjoerg		case STATE_REQ_SENT:
161925944Sjoerg		case STATE_ACK_RCVD:
162025944Sjoerg		case STATE_ACK_SENT:
162125944Sjoerg			(cp->tlf)(sp);
162225944Sjoerg			sppp_cp_change_state(cp, sp, STATE_STOPPED);
162325944Sjoerg			break;
162425944Sjoerg		}
162525944Sjoerg	else
162625944Sjoerg		/* TO+ event */
162725944Sjoerg		switch (sp->state[cp->protoidx]) {
162825944Sjoerg		case STATE_CLOSING:
162925944Sjoerg		case STATE_STOPPING:
163025944Sjoerg			sppp_cp_send(sp, cp->proto, TERM_REQ, ++sp->pp_seq,
163125944Sjoerg				     0, 0);
163229681Sgibbs			sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp,
163329681Sgibbs						       sp->lcp.timeout);
163425944Sjoerg			break;
163525944Sjoerg		case STATE_REQ_SENT:
163625944Sjoerg		case STATE_ACK_RCVD:
163725944Sjoerg			(cp->scr)(sp);
163825944Sjoerg			/* sppp_cp_change_state() will restart the timer */
163925944Sjoerg			sppp_cp_change_state(cp, sp, STATE_REQ_SENT);
164025944Sjoerg			break;
164125944Sjoerg		case STATE_ACK_SENT:
164225944Sjoerg			(cp->scr)(sp);
164329681Sgibbs			sp->ch[cp->protoidx] = timeout(cp->TO, (void *)sp,
164429681Sgibbs						       sp->lcp.timeout);
164525944Sjoerg			break;
164625944Sjoerg		}
164725944Sjoerg
164825944Sjoerg	splx(s);
164925944Sjoerg}
165025944Sjoerg
165111189Sjkh/*
165225944Sjoerg * Change the state of a control protocol in the state automaton.
165325944Sjoerg * Takes care of starting/stopping the restart timer.
165411189Sjkh */
165525944Sjoergvoid
165625944Sjoergsppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate)
165725944Sjoerg{
165825944Sjoerg	sp->state[cp->protoidx] = newstate;
165925944Sjoerg
166029681Sgibbs	untimeout(cp->TO, (void *)sp, sp->ch[cp->protoidx]);
166125944Sjoerg	switch (newstate) {
166225944Sjoerg	case STATE_INITIAL:
166325944Sjoerg	case STATE_STARTING:
166425944Sjoerg	case STATE_CLOSED:
166525944Sjoerg	case STATE_STOPPED:
166625944Sjoerg	case STATE_OPENED:
166725944Sjoerg		break;
166825944Sjoerg	case STATE_CLOSING:
166925944Sjoerg	case STATE_STOPPING:
167025944Sjoerg	case STATE_REQ_SENT:
167125944Sjoerg	case STATE_ACK_RCVD:
167225944Sjoerg	case STATE_ACK_SENT:
167329681Sgibbs		sp->ch[cp->protoidx]  = timeout(cp->TO, (void *)sp,
167429681Sgibbs						sp->lcp.timeout);
167525944Sjoerg		break;
167625944Sjoerg	}
167725944Sjoerg}
167825944Sjoerg/*
167925944Sjoerg *--------------------------------------------------------------------------*
168025944Sjoerg *                                                                          *
168125944Sjoerg *                         The LCP implementation.                          *
168225944Sjoerg *                                                                          *
168325944Sjoerg *--------------------------------------------------------------------------*
168425944Sjoerg */
168525944Sjoergstatic void
168625944Sjoergsppp_lcp_init(struct sppp *sp)
168725944Sjoerg{
168825944Sjoerg	sp->lcp.opts = (1 << LCP_OPT_MAGIC);
168925944Sjoerg	sp->lcp.magic = 0;
169025944Sjoerg	sp->state[IDX_LCP] = STATE_INITIAL;
169125944Sjoerg	sp->fail_counter[IDX_LCP] = 0;
169225944Sjoerg	sp->lcp.protos = 0;
169325944Sjoerg	sp->lcp.mru = sp->lcp.their_mru = PP_MTU;
169430300Sjoerg
169525944Sjoerg	/*
169625944Sjoerg	 * Initialize counters and timeout values.  Note that we don't
169725944Sjoerg	 * use the 3 seconds suggested in RFC 1661 since we are likely
169825944Sjoerg	 * running on a fast link.  XXX We should probably implement
169925944Sjoerg	 * the exponential backoff option.  Note that these values are
170025944Sjoerg	 * relevant for all control protocols, not just LCP only.
170125944Sjoerg	 */
170225944Sjoerg	sp->lcp.timeout = 1 * hz;
170325944Sjoerg	sp->lcp.max_terminate = 2;
170425944Sjoerg	sp->lcp.max_configure = 10;
170525944Sjoerg	sp->lcp.max_failure = 10;
170630300Sjoerg	callout_handle_init(&sp->ch[IDX_LCP]);
170725944Sjoerg}
170825944Sjoerg
170925944Sjoergstatic void
171025944Sjoergsppp_lcp_up(struct sppp *sp)
171125944Sjoerg{
171225944Sjoerg	STDDCL;
171325944Sjoerg
171425944Sjoerg	/*
171530300Sjoerg	 * If this interface is passive or dial-on-demand, and we are
171630300Sjoerg	 * still in Initial state, it means we've got an incoming
171730300Sjoerg	 * call.  Activate the interface.
171825944Sjoerg	 */
171925944Sjoerg	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) != 0) {
172025944Sjoerg		if (debug)
172125944Sjoerg			log(LOG_DEBUG,
172230300Sjoerg			    "%s%d: Up event", ifp->if_name, ifp->if_unit);
172325944Sjoerg		ifp->if_flags |= IFF_RUNNING;
172430300Sjoerg		if (sp->state[IDX_LCP] == STATE_INITIAL) {
172530300Sjoerg			if (debug)
172630300Sjoerg				addlog("(incoming call)\n");
172730300Sjoerg			sp->pp_flags |= PP_CALLIN;
172830300Sjoerg			lcp.Open(sp);
172930300Sjoerg		} else if (debug)
173030300Sjoerg			addlog("\n");
173125944Sjoerg	}
173225944Sjoerg
173325944Sjoerg	sppp_up_event(&lcp, sp);
173425944Sjoerg}
173525944Sjoerg
173625944Sjoergstatic void
173725944Sjoergsppp_lcp_down(struct sppp *sp)
173825944Sjoerg{
173925944Sjoerg	STDDCL;
174025944Sjoerg
174125944Sjoerg	sppp_down_event(&lcp, sp);
174225944Sjoerg
174325944Sjoerg	/*
174425944Sjoerg	 * If this is neither a dial-on-demand nor a passive
174525944Sjoerg	 * interface, simulate an ``ifconfig down'' action, so the
174625944Sjoerg	 * administrator can force a redial by another ``ifconfig
174725944Sjoerg	 * up''.  XXX For leased line operation, should we immediately
174825944Sjoerg	 * try to reopen the connection here?
174925944Sjoerg	 */
175025944Sjoerg	if ((ifp->if_flags & (IFF_AUTO | IFF_PASSIVE)) == 0) {
175125944Sjoerg		log(LOG_INFO,
175225944Sjoerg		    "%s%d: Down event (carrier loss), taking interface down.\n",
175325944Sjoerg		    ifp->if_name, ifp->if_unit);
175425944Sjoerg		if_down(ifp);
175525944Sjoerg	} else {
175625944Sjoerg		if (debug)
175725944Sjoerg			log(LOG_DEBUG,
175825944Sjoerg			    "%s%d: Down event (carrier loss)\n",
175925944Sjoerg			    ifp->if_name, ifp->if_unit);
176025944Sjoerg	}
176130300Sjoerg	sp->pp_flags &= ~PP_CALLIN;
176230300Sjoerg	if (sp->state[IDX_LCP] != STATE_INITIAL)
176330300Sjoerg		lcp.Close(sp);
176425944Sjoerg	ifp->if_flags &= ~IFF_RUNNING;
176525944Sjoerg}
176625944Sjoerg
176725944Sjoergstatic void
176825944Sjoergsppp_lcp_open(struct sppp *sp)
176925944Sjoerg{
177030300Sjoerg	/*
177130300Sjoerg	 * If we are authenticator, negotiate LCP_AUTH
177230300Sjoerg	 */
177330300Sjoerg	if (sp->hisauth.proto != 0)
177430300Sjoerg		sp->lcp.opts |= (1 << LCP_OPT_AUTH_PROTO);
177530300Sjoerg	else
177630300Sjoerg		sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
177730300Sjoerg	sp->pp_flags &= ~PP_NEEDAUTH;
177825944Sjoerg	sppp_open_event(&lcp, sp);
177925944Sjoerg}
178025944Sjoerg
178125944Sjoergstatic void
178225944Sjoergsppp_lcp_close(struct sppp *sp)
178325944Sjoerg{
178425944Sjoerg	sppp_close_event(&lcp, sp);
178525944Sjoerg}
178625944Sjoerg
178725944Sjoergstatic void
178825944Sjoergsppp_lcp_TO(void *cookie)
178925944Sjoerg{
179025944Sjoerg	sppp_to_event(&lcp, (struct sppp *)cookie);
179125944Sjoerg}
179225944Sjoerg
179325944Sjoerg/*
179425944Sjoerg * Analyze a configure request.  Return true if it was agreeable, and
179525944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and
179625944Sjoerg * caused action scn.  (The return value is used to make the state
179725944Sjoerg * transition decision in the state automaton.)
179825944Sjoerg */
179912820Sphkstatic int
180025944Sjoergsppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
18014910Swollman{
180225944Sjoerg	STDDCL;
180311189Sjkh	u_char *buf, *r, *p;
180425944Sjoerg	int origlen, rlen;
180525944Sjoerg	u_long nmagic;
180630300Sjoerg	u_short authproto;
18074910Swollman
180811189Sjkh	len -= 4;
180925944Sjoerg	origlen = len;
181011189Sjkh	buf = r = malloc (len, M_TEMP, M_NOWAIT);
181111189Sjkh	if (! buf)
181211189Sjkh		return (0);
18134910Swollman
181425706Sjoerg	if (debug)
181525944Sjoerg		log(LOG_DEBUG, "%s%d: lcp parse opts: ",
181625944Sjoerg		    ifp->if_name, ifp->if_unit);
181725706Sjoerg
181825944Sjoerg	/* pass 1: check for things that need to be rejected */
181911189Sjkh	p = (void*) (h+1);
182011189Sjkh	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
182125944Sjoerg		if (debug)
182225944Sjoerg			addlog(" %s ", sppp_lcp_opt_name(*p));
182311189Sjkh		switch (*p) {
182411189Sjkh		case LCP_OPT_MAGIC:
182525944Sjoerg			/* Magic number. */
182625944Sjoerg			/* fall through, both are same length */
182725944Sjoerg		case LCP_OPT_ASYNC_MAP:
182825944Sjoerg			/* Async control character map. */
182925944Sjoerg			if (len >= 6 || p[1] == 6)
183025944Sjoerg				continue;
183125944Sjoerg			if (debug)
183225944Sjoerg				addlog("[invalid] ");
183325944Sjoerg			break;
183425944Sjoerg		case LCP_OPT_MRU:
183525944Sjoerg			/* Maximum receive unit. */
183625944Sjoerg			if (len >= 4 && p[1] == 4)
183725944Sjoerg				continue;
183825944Sjoerg			if (debug)
183925944Sjoerg				addlog("[invalid] ");
184025944Sjoerg			break;
184130300Sjoerg		case LCP_OPT_AUTH_PROTO:
184230300Sjoerg			if (len < 4) {
184330300Sjoerg				if (debug)
184430300Sjoerg					addlog("[invalid] ");
184530300Sjoerg				break;
184630300Sjoerg			}
184730300Sjoerg			authproto = (p[2] << 8) + p[3];
184830300Sjoerg			if (authproto == PPP_CHAP && p[1] != 5) {
184930300Sjoerg				if (debug)
185030300Sjoerg					addlog("[invalid chap len] ");
185130300Sjoerg				break;
185230300Sjoerg			}
185330300Sjoerg			if (sp->myauth.proto == 0) {
185430300Sjoerg				/* we are not configured to do auth */
185530300Sjoerg				if (debug)
185630300Sjoerg					addlog("[not configured] ");
185730300Sjoerg				break;
185830300Sjoerg			}
185930300Sjoerg			/*
186030300Sjoerg			 * Remote want us to authenticate, remember this,
186130300Sjoerg			 * so we stay in PHASE_AUTHENTICATE after LCP got
186230300Sjoerg			 * up.
186330300Sjoerg			 */
186430300Sjoerg			sp->pp_flags |= PP_NEEDAUTH;
186530300Sjoerg			continue;
186625944Sjoerg		default:
186725944Sjoerg			/* Others not supported. */
186825944Sjoerg			if (debug)
186925944Sjoerg				addlog("[rej] ");
187025944Sjoerg			break;
187125944Sjoerg		}
187225944Sjoerg		/* Add the option to rejected list. */
187325944Sjoerg		bcopy (p, r, p[1]);
187425944Sjoerg		r += p[1];
187525944Sjoerg		rlen += p[1];
187625944Sjoerg	}
187725944Sjoerg	if (rlen) {
187825944Sjoerg		if (debug)
187925944Sjoerg			addlog(" send conf-rej\n");
188025944Sjoerg		sppp_cp_send (sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
188125944Sjoerg		return 0;
188225944Sjoerg	} else if (debug)
188325944Sjoerg		addlog("\n");
188425944Sjoerg
188525944Sjoerg	/*
188625944Sjoerg	 * pass 2: check for option values that are unacceptable and
188725944Sjoerg	 * thus require to be nak'ed.
188825944Sjoerg	 */
188925944Sjoerg	if (debug)
189026077Sjoerg		log(LOG_DEBUG, "%s%d: lcp parse opt values: ",
189126077Sjoerg		    ifp->if_name, ifp->if_unit);
189225944Sjoerg
189325944Sjoerg	p = (void*) (h+1);
189425944Sjoerg	len = origlen;
189525944Sjoerg	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
189625944Sjoerg		if (debug)
189725944Sjoerg			addlog(" %s ", sppp_lcp_opt_name(*p));
189825944Sjoerg		switch (*p) {
189925944Sjoerg		case LCP_OPT_MAGIC:
190011189Sjkh			/* Magic number -- extract. */
190125944Sjoerg			nmagic = (u_long)p[2] << 24 |
190225944Sjoerg				(u_long)p[3] << 16 | p[4] << 8 | p[5];
190325944Sjoerg			if (nmagic != sp->lcp.magic) {
190425706Sjoerg				if (debug)
190525944Sjoerg					addlog("0x%x ", nmagic);
190611189Sjkh				continue;
190711189Sjkh			}
190825944Sjoerg			/*
190925944Sjoerg			 * Local and remote magics equal -- loopback?
191025944Sjoerg			 */
191125944Sjoerg			if (sp->pp_loopcnt >= MAXALIVECNT*5) {
191230300Sjoerg				printf ("%s%d: loopback\n",
191325944Sjoerg					ifp->if_name, ifp->if_unit);
191425944Sjoerg				sp->pp_loopcnt = 0;
191525944Sjoerg				if (ifp->if_flags & IFF_UP) {
191625944Sjoerg					if_down(ifp);
191726018Sjoerg					sppp_qflush(&sp->pp_cpq);
191825944Sjoerg					/* XXX ? */
191925944Sjoerg					lcp.Down(sp);
192025944Sjoerg					lcp.Up(sp);
192125944Sjoerg				}
192225944Sjoerg			} else if (debug)
192325944Sjoerg				addlog("[glitch] ");
192425944Sjoerg			++sp->pp_loopcnt;
192525944Sjoerg			/*
192625944Sjoerg			 * We negate our magic here, and NAK it.  If
192725944Sjoerg			 * we see it later in an NAK packet, we
192825944Sjoerg			 * suggest a new one.
192925944Sjoerg			 */
193025944Sjoerg			nmagic = ~sp->lcp.magic;
193125944Sjoerg			/* Gonna NAK it. */
193225944Sjoerg			p[2] = nmagic >> 24;
193325944Sjoerg			p[3] = nmagic >> 16;
193425944Sjoerg			p[4] = nmagic >> 8;
193525944Sjoerg			p[5] = nmagic;
193611189Sjkh			break;
193725944Sjoerg
193811189Sjkh		case LCP_OPT_ASYNC_MAP:
193911189Sjkh			/* Async control character map -- check to be zero. */
194025944Sjoerg			if (! p[2] && ! p[3] && ! p[4] && ! p[5]) {
194125706Sjoerg				if (debug)
194225944Sjoerg					addlog("[empty] ");
194311189Sjkh				continue;
194425706Sjoerg			}
194525706Sjoerg			if (debug)
194625944Sjoerg				addlog("[non-empty] ");
194725944Sjoerg			/* suggest a zero one */
194825944Sjoerg			p[2] = p[3] = p[4] = p[5] = 0;
194911189Sjkh			break;
195025944Sjoerg
195111189Sjkh		case LCP_OPT_MRU:
195225944Sjoerg			/*
195325944Sjoerg			 * Maximum receive unit.  Always agreeable,
195425944Sjoerg			 * but ignored by now.
195525944Sjoerg			 */
195625944Sjoerg			sp->lcp.their_mru = p[2] * 256 + p[3];
195725706Sjoerg			if (debug)
195825944Sjoerg				addlog("%d ", sp->lcp.their_mru);
195911189Sjkh			continue;
196030300Sjoerg
196130300Sjoerg		case LCP_OPT_AUTH_PROTO:
196230300Sjoerg			authproto = (p[2] << 8) + p[3];
196330300Sjoerg			if (sp->myauth.proto != authproto) {
196430300Sjoerg				/* not agreed, nak */
196530300Sjoerg				if (debug)
196630300Sjoerg					addlog("[mine %s != his %s] ",
196730300Sjoerg					       sppp_proto_name(sp->hisauth.proto),
196830300Sjoerg					       sppp_proto_name(authproto));
196930300Sjoerg				p[2] = sp->myauth.proto >> 8;
197030300Sjoerg				p[3] = sp->myauth.proto;
197130300Sjoerg				break;
197230300Sjoerg			}
197330300Sjoerg			if (authproto == PPP_CHAP && p[4] != CHAP_MD5) {
197430300Sjoerg				if (debug)
197530300Sjoerg					addlog("[chap not MD5] ");
197630300Sjoerg				p[4] == CHAP_MD5;
197730300Sjoerg				break;
197830300Sjoerg			}
197930300Sjoerg			continue;
198011189Sjkh		}
198125944Sjoerg		/* Add the option to nak'ed list. */
198225706Sjoerg		bcopy (p, r, p[1]);
198325706Sjoerg		r += p[1];
198411189Sjkh		rlen += p[1];
198512436Speter	}
198625706Sjoerg	if (rlen) {
198728036Sjoerg		if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) {
198828036Sjoerg			if (debug)
198928036Sjoerg				addlog(" max_failure (%d) exceeded, "
199028036Sjoerg				       "send conf-rej\n",
199128036Sjoerg				       sp->lcp.max_failure);
199228036Sjoerg			sppp_cp_send(sp, PPP_LCP, CONF_REJ, h->ident, rlen, buf);
199328036Sjoerg		} else {
199428036Sjoerg			if (debug)
199528036Sjoerg				addlog(" send conf-nak\n");
199628036Sjoerg			sppp_cp_send (sp, PPP_LCP, CONF_NAK, h->ident, rlen, buf);
199728036Sjoerg		}
199825944Sjoerg		return 0;
199925944Sjoerg	} else {
200025944Sjoerg		if (debug)
200125944Sjoerg			addlog(" send conf-ack\n");
200228036Sjoerg		sp->fail_counter[IDX_LCP] = 0;
200325944Sjoerg		sp->pp_loopcnt = 0;
200425944Sjoerg		sppp_cp_send (sp, PPP_LCP, CONF_ACK,
200525944Sjoerg			      h->ident, origlen, h+1);
200625944Sjoerg	}
200725944Sjoerg
200811189Sjkh	free (buf, M_TEMP);
200911189Sjkh	return (rlen == 0);
20104910Swollman}
20114910Swollman
201225944Sjoerg/*
201325944Sjoerg * Analyze the LCP Configure-Reject option list, and adjust our
201425944Sjoerg * negotiation.
201525944Sjoerg */
201612820Sphkstatic void
201725944Sjoergsppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
20184910Swollman{
201925944Sjoerg	STDDCL;
202025944Sjoerg	u_char *buf, *p;
20214910Swollman
202225944Sjoerg	len -= 4;
202325944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
202425944Sjoerg	if (!buf)
20254910Swollman		return;
202625944Sjoerg
202725944Sjoerg	if (debug)
202825944Sjoerg		log(LOG_DEBUG, "%s%d: lcp rej opts: ",
202925944Sjoerg		    ifp->if_name, ifp->if_unit);
203025944Sjoerg
203125944Sjoerg	p = (void*) (h+1);
203225944Sjoerg	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
203325944Sjoerg		if (debug)
203425944Sjoerg			addlog(" %s ", sppp_lcp_opt_name(*p));
203525944Sjoerg		switch (*p) {
203625944Sjoerg		case LCP_OPT_MAGIC:
203725944Sjoerg			/* Magic number -- can't use it, use 0 */
203825944Sjoerg			sp->lcp.opts &= ~(1 << LCP_OPT_MAGIC);
203925944Sjoerg			sp->lcp.magic = 0;
204025944Sjoerg			break;
204125944Sjoerg		case LCP_OPT_MRU:
204225944Sjoerg			/*
204325944Sjoerg			 * Should not be rejected anyway, since we only
204425944Sjoerg			 * negotiate a MRU if explicitly requested by
204525944Sjoerg			 * peer.
204625944Sjoerg			 */
204725944Sjoerg			sp->lcp.opts &= ~(1 << LCP_OPT_MRU);
204825944Sjoerg			break;
204930300Sjoerg		case LCP_OPT_AUTH_PROTO:
205030300Sjoerg			/*
205130300Sjoerg			 * Peer doesn't want to authenticate himself,
205230300Sjoerg			 * deny unless this is a dialout call, and
205330300Sjoerg			 * AUTHFLAG_NOCALLOUT is set.
205430300Sjoerg			 */
205530300Sjoerg			if ((sp->pp_flags & PP_CALLIN) == 0 &&
205630300Sjoerg			    (sp->hisauth.flags & AUTHFLAG_NOCALLOUT) != 0) {
205730300Sjoerg				if (debug)
205830300Sjoerg					addlog("[don't insist on auth "
205930300Sjoerg					       "for callout]");
206030300Sjoerg				sp->lcp.opts &= ~(1 << LCP_OPT_AUTH_PROTO);
206130300Sjoerg				break;
206230300Sjoerg			}
206330300Sjoerg			if (debug)
206430300Sjoerg				addlog("[access denied]\n");
206530300Sjoerg			lcp.Close(sp);
206630300Sjoerg			break;
206725944Sjoerg		}
20684910Swollman	}
206925944Sjoerg	if (debug)
207025944Sjoerg		addlog("\n");
207125944Sjoerg	free (buf, M_TEMP);
207225944Sjoerg	return;
207325944Sjoerg}
207425944Sjoerg
207525944Sjoerg/*
207625944Sjoerg * Analyze the LCP Configure-NAK option list, and adjust our
207725944Sjoerg * negotiation.
207825944Sjoerg */
207925944Sjoergstatic void
208025944Sjoergsppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
208125944Sjoerg{
208225944Sjoerg	STDDCL;
208325944Sjoerg	u_char *buf, *p;
208425944Sjoerg	u_long magic;
208525944Sjoerg
208625944Sjoerg	len -= 4;
208725944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
208825944Sjoerg	if (!buf)
208925944Sjoerg		return;
209025944Sjoerg
209125944Sjoerg	if (debug)
209225944Sjoerg		log(LOG_DEBUG, "%s%d: lcp nak opts: ",
209325944Sjoerg		    ifp->if_name, ifp->if_unit);
209425944Sjoerg
209525944Sjoerg	p = (void*) (h+1);
209625944Sjoerg	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
209725706Sjoerg		if (debug)
209825944Sjoerg			addlog(" %s ", sppp_lcp_opt_name(*p));
209925944Sjoerg		switch (*p) {
210025944Sjoerg		case LCP_OPT_MAGIC:
210125944Sjoerg			/* Magic number -- renegotiate */
210225944Sjoerg			if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
210325944Sjoerg			    len >= 6 && p[1] == 6) {
210425944Sjoerg				magic = (u_long)p[2] << 24 |
210525944Sjoerg					(u_long)p[3] << 16 | p[4] << 8 | p[5];
210625944Sjoerg				/*
210725944Sjoerg				 * If the remote magic is our negated one,
210825944Sjoerg				 * this looks like a loopback problem.
210925944Sjoerg				 * Suggest a new magic to make sure.
211025944Sjoerg				 */
211125944Sjoerg				if (magic == ~sp->lcp.magic) {
211225944Sjoerg					if (debug)
211325944Sjoerg						addlog("magic glitch ");
211425944Sjoerg					sp->lcp.magic += time.tv_sec + time.tv_usec;
211525944Sjoerg				} else {
211625944Sjoerg					sp->lcp.magic = magic;
211725944Sjoerg					if (debug)
211825944Sjoerg						addlog("%d ");
211925944Sjoerg				}
212025944Sjoerg			}
212125944Sjoerg			break;
212225944Sjoerg		case LCP_OPT_MRU:
212325944Sjoerg			/*
212425944Sjoerg			 * Peer wants to advise us to negotiate an MRU.
212525944Sjoerg			 * Agree on it if it's reasonable, or use
212625944Sjoerg			 * default otherwise.
212725944Sjoerg			 */
212825944Sjoerg			if (len >= 4 && p[1] == 4) {
212925944Sjoerg				u_int mru = p[2] * 256 + p[3];
213025944Sjoerg				if (debug)
213125944Sjoerg					addlog("%d ", mru);
213225944Sjoerg				if (mru < PP_MTU || mru > PP_MAX_MRU)
213325944Sjoerg					mru = PP_MTU;
213425944Sjoerg				sp->lcp.mru = mru;
213525944Sjoerg				sp->lcp.opts |= (1 << LCP_OPT_MRU);
213625944Sjoerg			}
213725944Sjoerg			break;
213830300Sjoerg		case LCP_OPT_AUTH_PROTO:
213930300Sjoerg			/*
214030300Sjoerg			 * Peer doesn't like our authentication method,
214130300Sjoerg			 * deny.
214230300Sjoerg			 */
214330300Sjoerg			if (debug)
214430300Sjoerg				addlog("[access denied]\n");
214530300Sjoerg			lcp.Close(sp);
214630300Sjoerg			break;
21474910Swollman		}
214825944Sjoerg	}
214925944Sjoerg	if (debug)
215025944Sjoerg		addlog("\n");
215125944Sjoerg	free (buf, M_TEMP);
215225944Sjoerg	return;
215325944Sjoerg}
215411189Sjkh
215525944Sjoergstatic void
215625944Sjoergsppp_lcp_tlu(struct sppp *sp)
215725944Sjoerg{
215825944Sjoerg	STDDCL;
215925944Sjoerg	int i;
216025944Sjoerg	u_long mask;
216125944Sjoerg
216225944Sjoerg	/* XXX ? */
216325944Sjoerg	if (! (ifp->if_flags & IFF_UP) &&
216425944Sjoerg	    (ifp->if_flags & IFF_RUNNING)) {
216525944Sjoerg		/* Coming out of loopback mode. */
216625944Sjoerg		if_up(ifp);
216725944Sjoerg		printf ("%s%d: up\n", ifp->if_name, ifp->if_unit);
216825944Sjoerg	}
216925944Sjoerg
217025944Sjoerg	for (i = 0; i < IDX_COUNT; i++)
217125944Sjoerg		if ((cps[i])->flags & CP_QUAL)
217225944Sjoerg			(cps[i])->Open(sp);
217325944Sjoerg
217430300Sjoerg	if ((sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0 ||
217530300Sjoerg	    (sp->pp_flags & PP_NEEDAUTH) != 0)
217625944Sjoerg		sp->pp_phase = PHASE_AUTHENTICATE;
217725944Sjoerg	else
217825944Sjoerg		sp->pp_phase = PHASE_NETWORK;
217925944Sjoerg
218025944Sjoerg	log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
218125944Sjoerg	    sppp_phase_name(sp->pp_phase));
218225944Sjoerg
218330300Sjoerg	/*
218430300Sjoerg	 * Open all authentication protocols.  This is even required
218530300Sjoerg	 * if we already proceeded to network phase, since it might be
218630300Sjoerg	 * that remote wants us to authenticate, so we might have to
218730300Sjoerg	 * send a PAP request.  Undesired authentication protocols
218830300Sjoerg	 * don't do anything when they get an Open event.
218930300Sjoerg	 */
219030300Sjoerg	for (i = 0; i < IDX_COUNT; i++)
219130300Sjoerg		if ((cps[i])->flags & CP_AUTH)
219230300Sjoerg			(cps[i])->Open(sp);
219330300Sjoerg
219430300Sjoerg	if (sp->pp_phase == PHASE_NETWORK) {
219525944Sjoerg		/* Notify all NCPs. */
219625944Sjoerg		for (i = 0; i < IDX_COUNT; i++)
219725944Sjoerg			if ((cps[i])->flags & CP_NCP)
219825944Sjoerg				(cps[i])->Open(sp);
219925944Sjoerg	}
220025944Sjoerg
220125944Sjoerg	/* Send Up events to all started protos. */
220225944Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
220325944Sjoerg		if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0)
220425944Sjoerg			(cps[i])->Up(sp);
220525944Sjoerg
220625944Sjoerg	if (sp->pp_phase == PHASE_NETWORK)
220725944Sjoerg		/* if no NCP is starting, close down */
220830300Sjoerg		sppp_lcp_check_and_close(sp);
220925944Sjoerg}
221025944Sjoerg
221125944Sjoergstatic void
221225944Sjoergsppp_lcp_tld(struct sppp *sp)
221325944Sjoerg{
221425944Sjoerg	STDDCL;
221525944Sjoerg	int i;
221625944Sjoerg	u_long mask;
221725944Sjoerg
221825944Sjoerg	sp->pp_phase = PHASE_TERMINATE;
221925944Sjoerg
222025944Sjoerg	log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
222125944Sjoerg	    sppp_phase_name(sp->pp_phase));
222225944Sjoerg
222325944Sjoerg	/*
222425944Sjoerg	 * Take upper layers down.  We send the Down event first and
222525944Sjoerg	 * the Close second to prevent the upper layers from sending
222625944Sjoerg	 * ``a flurry of terminate-request packets'', as the RFC
222725944Sjoerg	 * describes it.
222825944Sjoerg	 */
222925944Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
223025944Sjoerg		if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) {
223125944Sjoerg			(cps[i])->Down(sp);
223225944Sjoerg			(cps[i])->Close(sp);
223325944Sjoerg		}
223425944Sjoerg}
223525944Sjoerg
223625944Sjoergstatic void
223725944Sjoergsppp_lcp_tls(struct sppp *sp)
223825944Sjoerg{
223925944Sjoerg	STDDCL;
224025944Sjoerg
224125944Sjoerg	sp->pp_phase = PHASE_ESTABLISH;
224225944Sjoerg
224325944Sjoerg	log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
224425944Sjoerg	    sppp_phase_name(sp->pp_phase));
224525944Sjoerg
224625944Sjoerg	/* Notify lower layer if desired. */
224725944Sjoerg	if (sp->pp_tls)
224825944Sjoerg		(sp->pp_tls)(sp);
224925944Sjoerg}
225025944Sjoerg
225125944Sjoergstatic void
225225944Sjoergsppp_lcp_tlf(struct sppp *sp)
225325944Sjoerg{
225425944Sjoerg	STDDCL;
225525944Sjoerg
225625944Sjoerg	sp->pp_phase = PHASE_DEAD;
225725944Sjoerg	log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
225825944Sjoerg	    sppp_phase_name(sp->pp_phase));
225925944Sjoerg
226025944Sjoerg	/* Notify lower layer if desired. */
226125944Sjoerg	if (sp->pp_tlf)
226225944Sjoerg		(sp->pp_tlf)(sp);
226325944Sjoerg}
226425944Sjoerg
226525944Sjoergstatic void
226625944Sjoergsppp_lcp_scr(struct sppp *sp)
226725944Sjoerg{
226830300Sjoerg	char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */];
226925944Sjoerg	int i = 0;
227030300Sjoerg	u_short authproto;
227125944Sjoerg
227225944Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) {
227325944Sjoerg		if (! sp->lcp.magic)
227425944Sjoerg			sp->lcp.magic = time.tv_sec + time.tv_usec;
227525944Sjoerg		opt[i++] = LCP_OPT_MAGIC;
227625944Sjoerg		opt[i++] = 6;
227725944Sjoerg		opt[i++] = sp->lcp.magic >> 24;
227825944Sjoerg		opt[i++] = sp->lcp.magic >> 16;
227925944Sjoerg		opt[i++] = sp->lcp.magic >> 8;
228025944Sjoerg		opt[i++] = sp->lcp.magic;
228125944Sjoerg	}
228225944Sjoerg
228325944Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_MRU)) {
228425944Sjoerg		opt[i++] = LCP_OPT_MRU;
228525944Sjoerg		opt[i++] = 4;
228625944Sjoerg		opt[i++] = sp->lcp.mru >> 8;
228725944Sjoerg		opt[i++] = sp->lcp.mru;
228825944Sjoerg	}
228925944Sjoerg
229030300Sjoerg	if (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) {
229130300Sjoerg		authproto = sp->hisauth.proto;
229230300Sjoerg		opt[i++] = LCP_OPT_AUTH_PROTO;
229330300Sjoerg		opt[i++] = authproto == PPP_CHAP? 5: 4;
229430300Sjoerg		opt[i++] = authproto >> 8;
229530300Sjoerg		opt[i++] = authproto;
229630300Sjoerg		if (authproto == PPP_CHAP)
229730300Sjoerg			opt[i++] = CHAP_MD5;
229830300Sjoerg	}
229930300Sjoerg
230025944Sjoerg	sp->confid[IDX_LCP] = ++sp->pp_seq;
230125944Sjoerg	sppp_cp_send (sp, PPP_LCP, CONF_REQ, sp->confid[IDX_LCP], i, &opt);
230225944Sjoerg}
230325944Sjoerg
230425944Sjoerg/*
230530300Sjoerg * Check the open NCPs, return true if at least one NCP is open.
230630300Sjoerg */
230730300Sjoergstatic int
230830300Sjoergsppp_ncp_check(struct sppp *sp)
230930300Sjoerg{
231030300Sjoerg	int i, mask;
231130300Sjoerg
231230300Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
231330300Sjoerg		if (sp->lcp.protos & mask && (cps[i])->flags & CP_NCP)
231430300Sjoerg			return 1;
231530300Sjoerg	return 0;
231630300Sjoerg}
231730300Sjoerg
231830300Sjoerg/*
231925944Sjoerg * Re-check the open NCPs and see if we should terminate the link.
232025944Sjoerg * Called by the NCPs during their tlf action handling.
232125944Sjoerg */
232225944Sjoergstatic void
232330300Sjoergsppp_lcp_check_and_close(struct sppp *sp)
232425944Sjoerg{
232525944Sjoerg
232630300Sjoerg	if (sp->pp_phase < PHASE_NETWORK)
232730300Sjoerg		/* don't bother, we are already going down */
232830300Sjoerg		return;
232930300Sjoerg
233030300Sjoerg	if (sppp_ncp_check(sp))
233130300Sjoerg		return;
233230300Sjoerg
233325944Sjoerg	lcp.Close(sp);
233425944Sjoerg}
233525944Sjoerg/*
233625944Sjoerg *--------------------------------------------------------------------------*
233725944Sjoerg *                                                                          *
233825944Sjoerg *                        The IPCP implementation.                          *
233925944Sjoerg *                                                                          *
234025944Sjoerg *--------------------------------------------------------------------------*
234125944Sjoerg */
234225944Sjoerg
234325944Sjoergstatic void
234425944Sjoergsppp_ipcp_init(struct sppp *sp)
234525944Sjoerg{
234625944Sjoerg	sp->ipcp.opts = 0;
234725944Sjoerg	sp->ipcp.flags = 0;
234825944Sjoerg	sp->state[IDX_IPCP] = STATE_INITIAL;
234925944Sjoerg	sp->fail_counter[IDX_IPCP] = 0;
235029681Sgibbs	callout_handle_init(&sp->ch[IDX_IPCP]);
235125944Sjoerg}
235225944Sjoerg
235325944Sjoergstatic void
235425944Sjoergsppp_ipcp_up(struct sppp *sp)
235525944Sjoerg{
235625944Sjoerg	sppp_up_event(&ipcp, sp);
235725944Sjoerg}
235825944Sjoerg
235925944Sjoergstatic void
236025944Sjoergsppp_ipcp_down(struct sppp *sp)
236125944Sjoerg{
236225944Sjoerg	sppp_down_event(&ipcp, sp);
236325944Sjoerg}
236425944Sjoerg
236525944Sjoergstatic void
236625944Sjoergsppp_ipcp_open(struct sppp *sp)
236725944Sjoerg{
236825944Sjoerg	STDDCL;
236925944Sjoerg	u_long myaddr, hisaddr;
237025944Sjoerg
237130300Sjoerg	sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
237225944Sjoerg	/*
237325944Sjoerg	 * If we don't have his address, this probably means our
237425944Sjoerg	 * interface doesn't want to talk IP at all.  (This could
237525944Sjoerg	 * be the case if somebody wants to speak only IPX, for
237625944Sjoerg	 * example.)  Don't open IPCP in this case.
237725944Sjoerg	 */
237825944Sjoerg	if (hisaddr == 0L) {
237925944Sjoerg		/* XXX this message should go away */
238025944Sjoerg		if (debug)
238125944Sjoerg			log(LOG_DEBUG, "%s%d: ipcp_open(): no IP interface\n",
238225944Sjoerg			    ifp->if_name, ifp->if_unit);
238325944Sjoerg		return;
238425944Sjoerg	}
238525944Sjoerg
238625944Sjoerg	if (myaddr == 0L) {
238725944Sjoerg		/*
238825944Sjoerg		 * I don't have an assigned address, so i need to
238925944Sjoerg		 * negotiate my address.
239025944Sjoerg		 */
239125944Sjoerg		sp->ipcp.flags |= IPCP_MYADDR_DYN;
239225944Sjoerg		sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
239325944Sjoerg	}
239425944Sjoerg	sppp_open_event(&ipcp, sp);
239525944Sjoerg}
239625944Sjoerg
239725944Sjoergstatic void
239825944Sjoergsppp_ipcp_close(struct sppp *sp)
239925944Sjoerg{
240025944Sjoerg	sppp_close_event(&ipcp, sp);
240125944Sjoerg	if (sp->ipcp.flags & IPCP_MYADDR_DYN)
240225944Sjoerg		/*
240325944Sjoerg		 * My address was dynamic, clear it again.
240425944Sjoerg		 */
240525944Sjoerg		sppp_set_ip_addr(sp, 0L);
240625944Sjoerg}
240725944Sjoerg
240825944Sjoergstatic void
240925944Sjoergsppp_ipcp_TO(void *cookie)
241025944Sjoerg{
241125944Sjoerg	sppp_to_event(&ipcp, (struct sppp *)cookie);
241225944Sjoerg}
241325944Sjoerg
241425944Sjoerg/*
241525944Sjoerg * Analyze a configure request.  Return true if it was agreeable, and
241625944Sjoerg * caused action sca, false if it has been rejected or nak'ed, and
241725944Sjoerg * caused action scn.  (The return value is used to make the state
241825944Sjoerg * transition decision in the state automaton.)
241925944Sjoerg */
242025944Sjoergstatic int
242125944Sjoergsppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
242225944Sjoerg{
242325944Sjoerg	u_char *buf, *r, *p;
242425944Sjoerg	struct ifnet *ifp = &sp->pp_if;
242525944Sjoerg	int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
242625944Sjoerg	u_long hisaddr, desiredaddr;
242725944Sjoerg
242825944Sjoerg	len -= 4;
242925944Sjoerg	origlen = len;
243025944Sjoerg	/*
243125944Sjoerg	 * Make sure to allocate a buf that can at least hold a
243225944Sjoerg	 * conf-nak with an `address' option.  We might need it below.
243325944Sjoerg	 */
243425944Sjoerg	buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT);
243525944Sjoerg	if (! buf)
243625944Sjoerg		return (0);
243725944Sjoerg
243825944Sjoerg	/* pass 1: see if we can recognize them */
243925944Sjoerg	if (debug)
244025944Sjoerg		log(LOG_DEBUG, "%s%d: ipcp parse opts: ",
244125944Sjoerg		    ifp->if_name, ifp->if_unit);
244225944Sjoerg	p = (void*) (h+1);
244325944Sjoerg	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
244425944Sjoerg		if (debug)
244525944Sjoerg			addlog(" %s ", sppp_ipcp_opt_name(*p));
244625944Sjoerg		switch (*p) {
244725944Sjoerg#ifdef notyet
244825944Sjoerg		case IPCP_OPT_COMPRESSION:
244925944Sjoerg			if (len >= 6 && p[1] >= 6) {
245025944Sjoerg				/* correctly formed compress option */
245125944Sjoerg				continue;
245211189Sjkh			}
245325706Sjoerg			if (debug)
245425944Sjoerg				addlog("[invalid] ");
245525944Sjoerg			break;
245625944Sjoerg#endif
245725944Sjoerg		case IPCP_OPT_ADDRESS:
245825944Sjoerg			if (len >= 6 && p[1] == 6) {
245925944Sjoerg				/* correctly formed address option */
246025944Sjoerg				continue;
246125944Sjoerg			}
246225706Sjoerg			if (debug)
246325944Sjoerg				addlog("[invalid] ");
246411189Sjkh			break;
246525944Sjoerg		default:
246625944Sjoerg			/* Others not supported. */
246725944Sjoerg			if (debug)
246825944Sjoerg				addlog("[rej] ");
24694910Swollman			break;
24704910Swollman		}
247125944Sjoerg		/* Add the option to rejected list. */
247225944Sjoerg		bcopy (p, r, p[1]);
247325944Sjoerg		r += p[1];
247425944Sjoerg		rlen += p[1];
247525944Sjoerg	}
247625944Sjoerg	if (rlen) {
247725944Sjoerg		if (debug)
247825944Sjoerg			addlog(" send conf-rej\n");
247925944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_REJ, h->ident, rlen, buf);
248025944Sjoerg		return 0;
248125944Sjoerg	} else if (debug)
248225944Sjoerg		addlog("\n");
248325944Sjoerg
248425944Sjoerg	/* pass 2: parse option values */
248530300Sjoerg	sppp_get_ip_addrs(sp, 0, &hisaddr, 0);
248625944Sjoerg	if (debug)
248730300Sjoerg		log(LOG_DEBUG, "%s%d: ipcp parse opt values: ",
248830300Sjoerg		       ifp->if_name, ifp->if_unit);
248925944Sjoerg	p = (void*) (h+1);
249025944Sjoerg	len = origlen;
249125944Sjoerg	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
249225944Sjoerg		if (debug)
249325944Sjoerg			addlog(" %s ", sppp_ipcp_opt_name(*p));
249425944Sjoerg		switch (*p) {
249525944Sjoerg#ifdef notyet
249625944Sjoerg		case IPCP_OPT_COMPRESSION:
249725944Sjoerg			continue;
249825944Sjoerg#endif
249925944Sjoerg		case IPCP_OPT_ADDRESS:
250025944Sjoerg			desiredaddr = p[2] << 24 | p[3] << 16 |
250125944Sjoerg				p[4] << 8 | p[5];
250225944Sjoerg			if (desiredaddr == hisaddr) {
250325944Sjoerg				/*
250425944Sjoerg				 * Peer's address is same as our value,
250525944Sjoerg				 * this is agreeable.  Gonna conf-ack
250625944Sjoerg				 * it.
250725944Sjoerg				 */
250825944Sjoerg				if (debug)
250930300Sjoerg					addlog("%s [ack] ",
251030300Sjoerg					       sppp_dotted_quad(hisaddr));
251125944Sjoerg				/* record that we've seen it already */
251225944Sjoerg				sp->ipcp.flags |= IPCP_HISADDR_SEEN;
251325944Sjoerg				continue;
251425944Sjoerg			}
251525944Sjoerg			/*
251625944Sjoerg			 * The address wasn't agreeable.  This is either
251725944Sjoerg			 * he sent us 0.0.0.0, asking to assign him an
251825944Sjoerg			 * address, or he send us another address not
251925944Sjoerg			 * matching our value.  Either case, we gonna
252025944Sjoerg			 * conf-nak it with our value.
252125944Sjoerg			 */
252225944Sjoerg			if (debug) {
252325944Sjoerg				if (desiredaddr == 0)
252425944Sjoerg					addlog("[addr requested] ");
252525944Sjoerg				else
252630300Sjoerg					addlog("%s [not agreed] ",
252730300Sjoerg					       sppp_dotted_quad(desiredaddr));
252825944Sjoerg
252925944Sjoerg				p[2] = hisaddr >> 24;
253025944Sjoerg				p[3] = hisaddr >> 16;
253125944Sjoerg				p[4] = hisaddr >> 8;
253225944Sjoerg				p[5] = hisaddr;
253325944Sjoerg			}
253411189Sjkh			break;
253525706Sjoerg		}
253625944Sjoerg		/* Add the option to nak'ed list. */
253725944Sjoerg		bcopy (p, r, p[1]);
253825944Sjoerg		r += p[1];
253925944Sjoerg		rlen += p[1];
254025944Sjoerg	}
254125944Sjoerg
254225944Sjoerg	/*
254325944Sjoerg	 * If we are about to conf-ack the request, but haven't seen
254425944Sjoerg	 * his address so far, gonna conf-nak it instead, with the
254525944Sjoerg	 * `address' option present and our idea of his address being
254625944Sjoerg	 * filled in there, to request negotiation of both addresses.
254725944Sjoerg	 *
254825944Sjoerg	 * XXX This can result in an endless req - nak loop if peer
254925944Sjoerg	 * doesn't want to send us his address.  Q: What should we do
255025944Sjoerg	 * about it?  XXX  A: implement the max-failure counter.
255125944Sjoerg	 */
255225944Sjoerg	if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) {
255325944Sjoerg		buf[0] = IPCP_OPT_ADDRESS;
255425944Sjoerg		buf[1] = 6;
255525944Sjoerg		buf[2] = hisaddr >> 24;
255625944Sjoerg		buf[3] = hisaddr >> 16;
255725944Sjoerg		buf[4] = hisaddr >> 8;
255825944Sjoerg		buf[5] = hisaddr;
255925944Sjoerg		rlen = 6;
256025706Sjoerg		if (debug)
256125944Sjoerg			addlog("still need hisaddr ");
256225944Sjoerg	}
256325944Sjoerg
256425944Sjoerg	if (rlen) {
256525706Sjoerg		if (debug)
256625944Sjoerg			addlog(" send conf-nak\n");
256725944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_NAK, h->ident, rlen, buf);
256825944Sjoerg	} else {
256925706Sjoerg		if (debug)
257025944Sjoerg			addlog(" send conf-ack\n");
257125944Sjoerg		sppp_cp_send (sp, PPP_IPCP, CONF_ACK,
257225944Sjoerg			      h->ident, origlen, h+1);
257325944Sjoerg	}
257425944Sjoerg
257525944Sjoerg	free (buf, M_TEMP);
257625944Sjoerg	return (rlen == 0);
257725944Sjoerg}
257825944Sjoerg
257925944Sjoerg/*
258025944Sjoerg * Analyze the IPCP Configure-Reject option list, and adjust our
258125944Sjoerg * negotiation.
258225944Sjoerg */
258325944Sjoergstatic void
258425944Sjoergsppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
258525944Sjoerg{
258625944Sjoerg	u_char *buf, *p;
258725944Sjoerg	struct ifnet *ifp = &sp->pp_if;
258825944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG;
258925944Sjoerg
259025944Sjoerg	len -= 4;
259125944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
259225944Sjoerg	if (!buf)
259325944Sjoerg		return;
259425944Sjoerg
259525944Sjoerg	if (debug)
259625944Sjoerg		log(LOG_DEBUG, "%s%d: ipcp rej opts: ",
259725944Sjoerg		    ifp->if_name, ifp->if_unit);
259825944Sjoerg
259925944Sjoerg	p = (void*) (h+1);
260025944Sjoerg	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
260125706Sjoerg		if (debug)
260225944Sjoerg			addlog(" %s ", sppp_ipcp_opt_name(*p));
260325944Sjoerg		switch (*p) {
260425944Sjoerg		case IPCP_OPT_ADDRESS:
260525944Sjoerg			/*
260625944Sjoerg			 * Peer doesn't grok address option.  This is
260725944Sjoerg			 * bad.  XXX  Should we better give up here?
260825944Sjoerg			 */
260925944Sjoerg			sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS);
261025944Sjoerg			break;
261125944Sjoerg#ifdef notyet
261225944Sjoerg		case IPCP_OPT_COMPRESS:
261325944Sjoerg			sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS);
261425944Sjoerg			break;
261525944Sjoerg#endif
261625944Sjoerg		}
26174910Swollman	}
261825944Sjoerg	if (debug)
261925944Sjoerg		addlog("\n");
262025944Sjoerg	free (buf, M_TEMP);
262125944Sjoerg	return;
26224910Swollman}
26234910Swollman
262425944Sjoerg/*
262525944Sjoerg * Analyze the IPCP Configure-NAK option list, and adjust our
262625944Sjoerg * negotiation.
262725944Sjoerg */
262812820Sphkstatic void
262925944Sjoergsppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
26304910Swollman{
263125944Sjoerg	u_char *buf, *p;
263225944Sjoerg	struct ifnet *ifp = &sp->pp_if;
263325944Sjoerg	int debug = ifp->if_flags & IFF_DEBUG;
263425944Sjoerg	u_long wantaddr;
26354910Swollman
263625944Sjoerg	len -= 4;
263725944Sjoerg	buf = malloc (len, M_TEMP, M_NOWAIT);
263825944Sjoerg	if (!buf)
263925944Sjoerg		return;
264025944Sjoerg
264125944Sjoerg	if (debug)
264225944Sjoerg		log(LOG_DEBUG, "%s%d: ipcp nak opts: ",
264325944Sjoerg		    ifp->if_name, ifp->if_unit);
264425944Sjoerg
264525944Sjoerg	p = (void*) (h+1);
264625944Sjoerg	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
264725944Sjoerg		if (debug)
264825944Sjoerg			addlog(" %s ", sppp_ipcp_opt_name(*p));
264925944Sjoerg		switch (*p) {
265025944Sjoerg		case IPCP_OPT_ADDRESS:
265125944Sjoerg			/*
265225944Sjoerg			 * Peer doesn't like our local IP address.  See
265325944Sjoerg			 * if we can do something for him.  We'll drop
265425944Sjoerg			 * him our address then.
265525944Sjoerg			 */
265625944Sjoerg			if (len >= 6 && p[1] == 6) {
265725944Sjoerg				wantaddr = p[2] << 24 | p[3] << 16 |
265825944Sjoerg					p[4] << 8 | p[5];
265925944Sjoerg				sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
266025944Sjoerg				if (debug)
266130300Sjoerg					addlog("[wantaddr %s] ",
266230300Sjoerg					       sppp_dotted_quad(wantaddr));
266325944Sjoerg				/*
266425944Sjoerg				 * When doing dynamic address assignment,
266525944Sjoerg				 * we accept his offer.  Otherwise, we
266625944Sjoerg				 * ignore it and thus continue to negotiate
266725944Sjoerg				 * our already existing value.
266825944Sjoerg				 */
266925944Sjoerg				if (sp->ipcp.flags & IPCP_MYADDR_DYN) {
267025944Sjoerg					sppp_set_ip_addr(sp, wantaddr);
267125944Sjoerg					if (debug)
267225944Sjoerg						addlog("[agree] ");
267325944Sjoerg				}
267425944Sjoerg			}
267525944Sjoerg			break;
267625944Sjoerg#ifdef notyet
267725944Sjoerg		case IPCP_OPT_COMPRESS:
267825944Sjoerg			/*
267925944Sjoerg			 * Peer wants different compression parameters.
268025944Sjoerg			 */
268125944Sjoerg			break;
268225944Sjoerg#endif
268325944Sjoerg		}
268425944Sjoerg	}
268525944Sjoerg	if (debug)
268625944Sjoerg		addlog("\n");
268725944Sjoerg	free (buf, M_TEMP);
268825944Sjoerg	return;
26894910Swollman}
26904910Swollman
269112820Sphkstatic void
269225944Sjoergsppp_ipcp_tlu(struct sppp *sp)
26934910Swollman{
26944910Swollman}
26954910Swollman
269625944Sjoergstatic void
269725944Sjoergsppp_ipcp_tld(struct sppp *sp)
269825944Sjoerg{
269925944Sjoerg}
270025944Sjoerg
270125944Sjoergstatic void
270225944Sjoergsppp_ipcp_tls(struct sppp *sp)
270325944Sjoerg{
270425944Sjoerg	/* indicate to LCP that it must stay alive */
270525944Sjoerg	sp->lcp.protos |= (1 << IDX_IPCP);
270625944Sjoerg}
270725944Sjoerg
270825944Sjoergstatic void
270925944Sjoergsppp_ipcp_tlf(struct sppp *sp)
271025944Sjoerg{
271125944Sjoerg	/* we no longer need LCP */
271225944Sjoerg	sp->lcp.protos &= ~(1 << IDX_IPCP);
271330300Sjoerg	sppp_lcp_check_and_close(sp);
271425944Sjoerg}
271525944Sjoerg
271625944Sjoergstatic void
271725944Sjoergsppp_ipcp_scr(struct sppp *sp)
271825944Sjoerg{
271925944Sjoerg	char opt[6 /* compression */ + 6 /* address */];
272025944Sjoerg	u_long ouraddr;
272125944Sjoerg	int i = 0;
272225944Sjoerg
272325944Sjoerg#ifdef notyet
272425944Sjoerg	if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) {
272525944Sjoerg		opt[i++] = IPCP_OPT_COMPRESSION;
272625944Sjoerg		opt[i++] = 6;
272725944Sjoerg		opt[i++] = 0;	/* VJ header compression */
272825944Sjoerg		opt[i++] = 0x2d; /* VJ header compression */
272925944Sjoerg		opt[i++] = max_slot_id;
273025944Sjoerg		opt[i++] = comp_slot_id;
273125944Sjoerg	}
273225944Sjoerg#endif
273325944Sjoerg
273425944Sjoerg	if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) {
273530300Sjoerg		sppp_get_ip_addrs(sp, &ouraddr, 0, 0);
273625944Sjoerg		opt[i++] = IPCP_OPT_ADDRESS;
273725944Sjoerg		opt[i++] = 6;
273825944Sjoerg		opt[i++] = ouraddr >> 24;
273925944Sjoerg		opt[i++] = ouraddr >> 16;
274025944Sjoerg		opt[i++] = ouraddr >> 8;
274125944Sjoerg		opt[i++] = ouraddr;
274225944Sjoerg	}
274325944Sjoerg
274425944Sjoerg	sp->confid[IDX_IPCP] = ++sp->pp_seq;
274525944Sjoerg	sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, &opt);
274625944Sjoerg}
274725944Sjoerg
274825944Sjoerg
274925944Sjoerg/*
275030300Sjoerg *--------------------------------------------------------------------------*
275130300Sjoerg *                                                                          *
275230300Sjoerg *                        The CHAP implementation.                          *
275330300Sjoerg *                                                                          *
275430300Sjoerg *--------------------------------------------------------------------------*
275530300Sjoerg */
275630300Sjoerg
275730300Sjoerg/*
275830300Sjoerg * The authentication protocols don't employ a full-fledged state machine as
275930300Sjoerg * the control protocols do, since they do have Open and Close events, but
276030300Sjoerg * not Up and Down, nor are they explicitly terminated.  Also, use of the
276130300Sjoerg * authentication protocols may be different in both directions (this makes
276230300Sjoerg * sense, think of a machine that never accepts incoming calls but only
276330300Sjoerg * calls out, it doesn't require the called party to authenticate itself).
276430300Sjoerg *
276530300Sjoerg * Our state machine for the local authentication protocol (we are requesting
276630300Sjoerg * the peer to authenticate) looks like:
276730300Sjoerg *
276830300Sjoerg *						    RCA-
276930300Sjoerg *	      +--------------------------------------------+
277030300Sjoerg *	      V					    scn,tld|
277130300Sjoerg *	  +--------+			       Close   +---------+ RCA+
277230300Sjoerg *	  |	   |<----------------------------------|	 |------+
277330300Sjoerg *   +--->| Closed |				TO*    | Opened	 | sca	|
277430300Sjoerg *   |	  |	   |-----+		       +-------|	 |<-----+
277530300Sjoerg *   |	  +--------+ irc |		       |       +---------+
277630300Sjoerg *   |	    ^		 |		       |	   ^
277730300Sjoerg *   |	    |		 |		       |	   |
277830300Sjoerg *   |	    |		 |		       |	   |
277930300Sjoerg *   |	 TO-|		 |		       |	   |
278030300Sjoerg *   |	    |tld  TO+	 V		       |	   |
278130300Sjoerg *   |	    |	+------->+		       |	   |
278230300Sjoerg *   |	    |	|	 |		       |	   |
278330300Sjoerg *   |	  +--------+	 V		       |	   |
278430300Sjoerg *   |	  |	   |<----+<--------------------+	   |
278530300Sjoerg *   |	  | Req-   | scr				   |
278630300Sjoerg *   |	  | Sent   |					   |
278730300Sjoerg *   |	  |	   |					   |
278830300Sjoerg *   |	  +--------+					   |
278930300Sjoerg *   | RCA- |	| RCA+					   |
279030300Sjoerg *   +------+	+------------------------------------------+
279130300Sjoerg *   scn,tld	  sca,irc,ict,tlu
279230300Sjoerg *
279330300Sjoerg *
279430300Sjoerg *   with:
279530300Sjoerg *
279630300Sjoerg *	Open:	LCP reached authentication phase
279730300Sjoerg *	Close:	LCP reached terminate phase
279830300Sjoerg *
279930300Sjoerg *	RCA+:	received reply (pap-req, chap-response), acceptable
280030300Sjoerg *	RCN:	received reply (pap-req, chap-response), not acceptable
280130300Sjoerg *	TO+:	timeout with restart counter >= 0
280230300Sjoerg *	TO-:	timeout with restart counter < 0
280330300Sjoerg *	TO*:	reschedule timeout for CHAP
280430300Sjoerg *
280530300Sjoerg *	scr:	send request packet (none for PAP, chap-challenge)
280630300Sjoerg *	sca:	send ack packet (pap-ack, chap-success)
280730300Sjoerg *	scn:	send nak packet (pap-nak, chap-failure)
280830300Sjoerg *	ict:	initialize re-challenge timer (CHAP only)
280930300Sjoerg *
281030300Sjoerg *	tlu:	this-layer-up, LCP reaches network phase
281130300Sjoerg *	tld:	this-layer-down, LCP enters terminate phase
281230300Sjoerg *
281330300Sjoerg * Note that in CHAP mode, after sending a new challenge, while the state
281430300Sjoerg * automaton falls back into Req-Sent state, it doesn't signal a tld
281530300Sjoerg * event to LCP, so LCP remains in network phase.  Only after not getting
281630300Sjoerg * any response (or after getting an unacceptable response), CHAP closes,
281730300Sjoerg * causing LCP to enter terminate phase.
281830300Sjoerg *
281930300Sjoerg * With PAP, there is no initial request that can be sent.  The peer is
282030300Sjoerg * expected to send one based on the successful negotiation of PAP as
282130300Sjoerg * the authentication protocol during the LCP option negotiation.
282230300Sjoerg *
282330300Sjoerg * Incoming authentication protocol requests (remote requests
282430300Sjoerg * authentication, we are peer) don't employ a state machine at all,
282530300Sjoerg * they are simply answered.  Some peers [Ascend P50 firmware rev
282630300Sjoerg * 4.50] react allergically when sending IPCP requests while they are
282730300Sjoerg * still in authentication phase (thereby violating the standard that
282830300Sjoerg * demands that these NCP packets are to be discarded), so we keep
282930300Sjoerg * track of the peer demanding us to authenticate, and only proceed to
283030300Sjoerg * phase network once we've seen a positive acknowledge for the
283130300Sjoerg * authentication.
283230300Sjoerg */
283330300Sjoerg
283430300Sjoerg/*
283530300Sjoerg * Handle incoming CHAP packets.
283630300Sjoerg */
283730300Sjoergvoid
283830300Sjoergsppp_chap_input(struct sppp *sp, struct mbuf *m)
283930300Sjoerg{
284030300Sjoerg	STDDCL;
284130300Sjoerg	struct lcp_header *h;
284230300Sjoerg	int len, x;
284330300Sjoerg	u_char *value, *name, digest[AUTHKEYLEN], dsize;
284430300Sjoerg	int value_len, name_len;
284530300Sjoerg	MD5_CTX ctx;
284630300Sjoerg
284730300Sjoerg	len = m->m_pkthdr.len;
284830300Sjoerg	if (len < 4) {
284930300Sjoerg		if (debug)
285030300Sjoerg			log(LOG_DEBUG,
285130300Sjoerg			    "%s%d: chap invalid packet length: %d bytes\n",
285230300Sjoerg			    ifp->if_name, ifp->if_unit, len);
285330300Sjoerg		return;
285430300Sjoerg	}
285530300Sjoerg	h = mtod (m, struct lcp_header*);
285630300Sjoerg	if (len > ntohs (h->len))
285730300Sjoerg		len = ntohs (h->len);
285830300Sjoerg
285930300Sjoerg	switch (h->type) {
286030300Sjoerg	/* challenge, failure and success are his authproto */
286130300Sjoerg	case CHAP_CHALLENGE:
286230300Sjoerg		value = 1 + (u_char*)(h+1);
286330300Sjoerg		value_len = value[-1];
286430300Sjoerg		name = value + value_len;
286530300Sjoerg		name_len = len - value_len - 5;
286630300Sjoerg		if (name_len < 0) {
286730300Sjoerg			if (debug) {
286830300Sjoerg				log(LOG_DEBUG,
286930300Sjoerg				    "%s%d: chap corrupted challenge "
287030300Sjoerg				    "<%s id=0x%x len=%d",
287130300Sjoerg				    ifp->if_name, ifp->if_unit,
287230300Sjoerg				    sppp_auth_type_name(PPP_CHAP, h->type),
287330300Sjoerg				    h->ident, ntohs(h->len));
287430300Sjoerg				if (len > 4)
287530300Sjoerg					sppp_print_bytes((u_char*) (h+1), len-4);
287630300Sjoerg				addlog(">\n");
287730300Sjoerg			}
287830300Sjoerg			break;
287930300Sjoerg		}
288030300Sjoerg		if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)
288130300Sjoerg		    || bcmp(name, sp->hisauth.name, name_len) != 0) {
288230300Sjoerg			log(LOG_INFO, "%s%d: chap challenge, his name ");
288330300Sjoerg			sppp_print_string(name, name_len);
288430300Sjoerg			addlog(" != expected ");
288530300Sjoerg			sppp_print_string(sp->hisauth.name,
288630300Sjoerg					  sppp_strnlen(sp->hisauth.name, AUTHNAMELEN));
288730300Sjoerg			addlog("\n");
288830300Sjoerg		}
288930300Sjoerg
289030300Sjoerg		if (debug) {
289130300Sjoerg			log(LOG_DEBUG,
289230300Sjoerg			    "%s%d: chap input <%s id=0x%x len=%d name=",
289330300Sjoerg			    ifp->if_name, ifp->if_unit,
289430300Sjoerg			    sppp_auth_type_name(PPP_CHAP, h->type), h->ident,
289530300Sjoerg			    ntohs(h->len));
289630300Sjoerg			sppp_print_string((char*) name, name_len);
289730300Sjoerg			addlog(" value-size=%d value=", value_len);
289830300Sjoerg			sppp_print_bytes(value, value_len);
289930300Sjoerg			addlog(">\n");
290030300Sjoerg		}
290130300Sjoerg
290230300Sjoerg		/* Compute reply value. */
290330300Sjoerg		MD5Init(&ctx);
290430300Sjoerg		MD5Update(&ctx, &h->ident, 1);
290530300Sjoerg		MD5Update(&ctx, sp->myauth.secret,
290630300Sjoerg			  sppp_strnlen(sp->myauth.secret, AUTHKEYLEN));
290730300Sjoerg		MD5Update(&ctx, value, value_len);
290830300Sjoerg		MD5Final(digest, &ctx);
290930300Sjoerg		dsize = sizeof digest;
291030300Sjoerg
291130300Sjoerg		sppp_auth_send(&chap, sp, CHAP_RESPONSE, h->ident,
291230300Sjoerg			       sizeof dsize, (const char *)&dsize,
291330300Sjoerg			       sizeof digest, digest,
291430300Sjoerg			       sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
291530300Sjoerg			       sp->myauth.name,
291630300Sjoerg			       0);
291730300Sjoerg		break;
291830300Sjoerg
291930300Sjoerg	case CHAP_SUCCESS:
292030300Sjoerg		if (debug) {
292130300Sjoerg			log(LOG_DEBUG, "%s%d: chap success",
292230300Sjoerg			    ifp->if_name, ifp->if_unit);
292330300Sjoerg			if (len > 4) {
292430300Sjoerg				addlog(": ");
292530300Sjoerg				sppp_print_string((char*)(h + 1), len - 4);
292630300Sjoerg			}
292730300Sjoerg			addlog("\n");
292830300Sjoerg		}
292930300Sjoerg		x = splimp();
293030300Sjoerg		sp->pp_flags &= ~PP_NEEDAUTH;
293130300Sjoerg		if (sp->myauth.proto == PPP_CHAP &&
293230300Sjoerg		    (sp->lcp.protos & (1 << IDX_CHAP)) == 0) {
293330300Sjoerg			/*
293430300Sjoerg			 * We are authenticator for CHAP but didn't
293530300Sjoerg			 * complete yet.  Leave it to tlu to proceed
293630300Sjoerg			 * to network phase.
293730300Sjoerg			 */
293830300Sjoerg			splx(x);
293930300Sjoerg			break;
294030300Sjoerg		}
294130300Sjoerg		splx(x);
294230300Sjoerg		sppp_phase_network(sp);
294330300Sjoerg		break;
294430300Sjoerg
294530300Sjoerg	case CHAP_FAILURE:
294630300Sjoerg		if (debug) {
294730300Sjoerg			log(LOG_INFO, "%s%d: chap failure",
294830300Sjoerg			    ifp->if_name, ifp->if_unit);
294930300Sjoerg			if (len > 4) {
295030300Sjoerg				addlog(": ");
295130300Sjoerg				sppp_print_string((char*)(h + 1), len - 4);
295230300Sjoerg			}
295330300Sjoerg			addlog("\n");
295430300Sjoerg		} else
295530300Sjoerg			log(LOG_INFO, "%s%d: chap failure\n",
295630300Sjoerg			    ifp->if_name, ifp->if_unit);
295730300Sjoerg		/* await LCP shutdown by authenticator */
295830300Sjoerg		break;
295930300Sjoerg
296030300Sjoerg	/* response is my authproto */
296130300Sjoerg	case CHAP_RESPONSE:
296230300Sjoerg		value = 1 + (u_char*)(h+1);
296330300Sjoerg		value_len = value[-1];
296430300Sjoerg		name = value + value_len;
296530300Sjoerg		name_len = len - value_len - 5;
296630300Sjoerg		if (name_len < 0) {
296730300Sjoerg			if (debug) {
296830300Sjoerg				log(LOG_DEBUG,
296930300Sjoerg				    "%s%d: chap corrupted response "
297030300Sjoerg				    "<%s id=0x%x len=%d",
297130300Sjoerg				    ifp->if_name, ifp->if_unit,
297230300Sjoerg				    sppp_auth_type_name(PPP_CHAP, h->type),
297330300Sjoerg				    h->ident, ntohs(h->len));
297430300Sjoerg				if (len > 4)
297530300Sjoerg					sppp_print_bytes((u_char*)(h+1), len-4);
297630300Sjoerg				addlog(">\n");
297730300Sjoerg			}
297830300Sjoerg			break;
297930300Sjoerg		}
298030300Sjoerg		if (h->ident != sp->confid[IDX_CHAP]) {
298130300Sjoerg			if (debug)
298230300Sjoerg				log(LOG_DEBUG,
298330300Sjoerg				    "%s%d: chap dropping response for old ID "
298430300Sjoerg				    "(got %d, expected %d)\n",
298530300Sjoerg				    h->ident, sp->confid[IDX_CHAP]);
298630300Sjoerg			break;
298730300Sjoerg		}
298830300Sjoerg		if (name_len != sppp_strnlen(sp->hisauth.name, AUTHNAMELEN)
298930300Sjoerg		    || bcmp(name, sp->hisauth.name, name_len) != 0) {
299030300Sjoerg			log(LOG_INFO, "%s%d: chap response, his name ",
299130300Sjoerg			    ifp->if_name, ifp->if_unit);
299230300Sjoerg			sppp_print_string(name, name_len);
299330300Sjoerg			addlog(" != expected ");
299430300Sjoerg			sppp_print_string(sp->hisauth.name,
299530300Sjoerg					  sppp_strnlen(sp->hisauth.name, AUTHNAMELEN));
299630300Sjoerg			addlog("\n");
299730300Sjoerg		}
299830300Sjoerg		if (debug) {
299930300Sjoerg			log(LOG_DEBUG, "%s%d: chap input(%s) "
300030300Sjoerg			    "<%s id=0x%x len=%d name=",
300130300Sjoerg			    ifp->if_name, ifp->if_unit,
300230300Sjoerg			    sppp_state_name(sp->state[IDX_CHAP]),
300330300Sjoerg			    sppp_auth_type_name(PPP_CHAP, h->type),
300430300Sjoerg			    h->ident, ntohs (h->len));
300530300Sjoerg			sppp_print_string((char*)name, name_len);
300630300Sjoerg			addlog(" value-size=%d value=", value_len);
300730300Sjoerg			sppp_print_bytes(value, value_len);
300830300Sjoerg			addlog(">\n");
300930300Sjoerg		}
301030300Sjoerg		if (value_len != AUTHKEYLEN) {
301130300Sjoerg			if (debug)
301230300Sjoerg				log(LOG_DEBUG,
301330300Sjoerg				    "%s%d: chap bad hash value length: "
301430300Sjoerg				    "%d bytes, should be %d\n",
301530300Sjoerg				    ifp->if_name, ifp->if_unit, value_len,
301630300Sjoerg				    AUTHKEYLEN);
301730300Sjoerg			break;
301830300Sjoerg		}
301930300Sjoerg
302030300Sjoerg		MD5Init(&ctx);
302130300Sjoerg		MD5Update(&ctx, &h->ident, 1);
302230300Sjoerg		MD5Update(&ctx, sp->hisauth.secret,
302330300Sjoerg			  sppp_strnlen(sp->hisauth.secret, AUTHKEYLEN));
302430300Sjoerg		MD5Update(&ctx, sp->myauth.challenge, AUTHKEYLEN);
302530300Sjoerg		MD5Final(digest, &ctx);
302630300Sjoerg
302730300Sjoerg#define FAILMSG "Failed..."
302830300Sjoerg#define SUCCMSG "Welcome!"
302930300Sjoerg
303030300Sjoerg		if (value_len != sizeof digest ||
303130300Sjoerg		    bcmp(digest, value, value_len) != 0) {
303230300Sjoerg			/* action scn, tld */
303330300Sjoerg			sppp_auth_send(&chap, sp, CHAP_FAILURE, h->ident,
303430300Sjoerg				       sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
303530300Sjoerg				       0);
303630300Sjoerg			chap.tld(sp);
303730300Sjoerg			break;
303830300Sjoerg		}
303930300Sjoerg		/* action sca, perhaps tlu */
304030300Sjoerg		if (sp->state[IDX_CHAP] == STATE_REQ_SENT ||
304130300Sjoerg		    sp->state[IDX_CHAP] == STATE_OPENED)
304230300Sjoerg			sppp_auth_send(&chap, sp, CHAP_SUCCESS, h->ident,
304330300Sjoerg				       sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
304430300Sjoerg				       0);
304530300Sjoerg		if (sp->state[IDX_CHAP] == STATE_REQ_SENT) {
304630300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_OPENED);
304730300Sjoerg			chap.tlu(sp);
304830300Sjoerg		}
304930300Sjoerg		break;
305030300Sjoerg
305130300Sjoerg	default:
305230300Sjoerg		/* Unknown CHAP packet type -- ignore. */
305330300Sjoerg		if (debug) {
305430300Sjoerg			log(LOG_DEBUG, "%s%d: chap unknown input(%s) "
305530300Sjoerg			    "<0x%x id=0x%xh len=%d",
305630300Sjoerg			    ifp->if_name, ifp->if_unit,
305730300Sjoerg			    sppp_state_name(sp->state[IDX_CHAP]),
305830300Sjoerg			    h->type, h->ident, ntohs(h->len));
305930300Sjoerg			if (len > 4)
306030300Sjoerg				sppp_print_bytes((u_char*)(h+1), len-4);
306130300Sjoerg			addlog(">\n");
306230300Sjoerg		}
306330300Sjoerg		break;
306430300Sjoerg
306530300Sjoerg	}
306630300Sjoerg}
306730300Sjoerg
306830300Sjoergstatic void
306930300Sjoergsppp_chap_init(struct sppp *sp)
307030300Sjoerg{
307130300Sjoerg	/* Chap doesn't have STATE_INITIAL at all. */
307230300Sjoerg	sp->state[IDX_CHAP] = STATE_CLOSED;
307330300Sjoerg	sp->fail_counter[IDX_CHAP] = 0;
307430300Sjoerg	callout_handle_init(&sp->ch[IDX_CHAP]);
307530300Sjoerg}
307630300Sjoerg
307730300Sjoergstatic void
307830300Sjoergsppp_chap_open(struct sppp *sp)
307930300Sjoerg{
308030300Sjoerg	if (sp->myauth.proto == PPP_CHAP &&
308130300Sjoerg	    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
308230300Sjoerg		/* we are authenticator for CHAP, start it */
308330300Sjoerg		chap.scr(sp);
308430300Sjoerg		sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
308530300Sjoerg		sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
308630300Sjoerg	}
308730300Sjoerg	/* nothing to be done if we are peer, await a challenge */
308830300Sjoerg}
308930300Sjoerg
309030300Sjoergstatic void
309130300Sjoergsppp_chap_close(struct sppp *sp)
309230300Sjoerg{
309330300Sjoerg	if (sp->state[IDX_CHAP] != STATE_CLOSED)
309430300Sjoerg		sppp_cp_change_state(&chap, sp, STATE_CLOSED);
309530300Sjoerg}
309630300Sjoerg
309730300Sjoergstatic void
309830300Sjoergsppp_chap_TO(void *cookie)
309930300Sjoerg{
310030300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
310130300Sjoerg	STDDCL;
310230300Sjoerg	int s;
310330300Sjoerg
310430300Sjoerg	s = splimp();
310530300Sjoerg	if (debug)
310630300Sjoerg		log(LOG_DEBUG, "%s%d: chap TO(%s) rst_counter = %d\n",
310730300Sjoerg		    ifp->if_name, ifp->if_unit,
310830300Sjoerg		    sppp_state_name(sp->state[IDX_CHAP]),
310930300Sjoerg		    sp->rst_counter[IDX_CHAP]);
311030300Sjoerg
311130300Sjoerg	if (--sp->rst_counter[IDX_CHAP] < 0)
311230300Sjoerg		/* TO- event */
311330300Sjoerg		switch (sp->state[IDX_CHAP]) {
311430300Sjoerg		case STATE_REQ_SENT:
311530300Sjoerg			chap.tld(sp);
311630300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_CLOSED);
311730300Sjoerg			break;
311830300Sjoerg		}
311930300Sjoerg	else
312030300Sjoerg		/* TO+ (or TO*) event */
312130300Sjoerg		switch (sp->state[IDX_CHAP]) {
312230300Sjoerg		case STATE_OPENED:
312330300Sjoerg			/* TO* event */
312430300Sjoerg			sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
312530300Sjoerg			/* fall through */
312630300Sjoerg		case STATE_REQ_SENT:
312730300Sjoerg			chap.scr(sp);
312830300Sjoerg			/* sppp_cp_change_state() will restart the timer */
312930300Sjoerg			sppp_cp_change_state(&chap, sp, STATE_REQ_SENT);
313030300Sjoerg			break;
313130300Sjoerg		}
313230300Sjoerg
313330300Sjoerg	splx(s);
313430300Sjoerg}
313530300Sjoerg
313630300Sjoergstatic void
313730300Sjoergsppp_chap_tlu(struct sppp *sp)
313830300Sjoerg{
313930300Sjoerg	STDDCL;
314030300Sjoerg	int i, x;
314130300Sjoerg
314230300Sjoerg	sp->rst_counter[IDX_CHAP] = sp->lcp.max_configure;
314330300Sjoerg
314430300Sjoerg	/*
314530300Sjoerg	 * Some broken CHAP implementations (Conware CoNet, firmware
314630300Sjoerg	 * 4.0.?) don't want to re-authenticate their CHAP once the
314730300Sjoerg	 * initial challenge-response exchange has taken place.
314830300Sjoerg	 * Provide for an option to avoid rechallenges.
314930300Sjoerg	 */
315030300Sjoerg	if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) {
315130300Sjoerg		/*
315230300Sjoerg		 * Compute the re-challenge timeout.  This will yield
315330300Sjoerg		 * a number between 300 and 810 seconds.
315430300Sjoerg		 */
315530300Sjoerg		i = 300 + ((unsigned)(random() & 0xff00) >> 7);
315630300Sjoerg
315730300Sjoerg		sp->ch[IDX_CHAP] = timeout(chap.TO, (void *)sp, i * hz);
315830300Sjoerg	}
315930300Sjoerg
316030300Sjoerg	if (debug) {
316130300Sjoerg		log(LOG_DEBUG,
316230300Sjoerg		    "%s%d: chap %s, ",
316330300Sjoerg		    ifp->if_name, ifp->if_unit,
316430300Sjoerg		    sp->pp_phase == PHASE_NETWORK? "reconfirmed": "tlu");
316530300Sjoerg		if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0)
316630300Sjoerg			addlog("next re-challenge in %d seconds\n", i);
316730300Sjoerg		else
316830300Sjoerg			addlog("re-challenging supressed\n");
316930300Sjoerg	}
317030300Sjoerg
317130300Sjoerg	x = splimp();
317230300Sjoerg	/* indicate to LCP that we need to be closed down */
317330300Sjoerg	sp->lcp.protos |= (1 << IDX_CHAP);
317430300Sjoerg
317530300Sjoerg	if (sp->pp_flags & PP_NEEDAUTH) {
317630300Sjoerg		/*
317730300Sjoerg		 * Remote is authenticator, but his auth proto didn't
317830300Sjoerg		 * complete yet.  Defer the transition to network
317930300Sjoerg		 * phase.
318030300Sjoerg		 */
318130300Sjoerg		splx(x);
318230300Sjoerg		return;
318330300Sjoerg	}
318430300Sjoerg	splx(x);
318530300Sjoerg
318630300Sjoerg	/*
318730300Sjoerg	 * If we are already in phase network, we are done here.  This
318830300Sjoerg	 * is the case if this is a dummy tlu event after a re-challenge.
318930300Sjoerg	 */
319030300Sjoerg	if (sp->pp_phase != PHASE_NETWORK)
319130300Sjoerg		sppp_phase_network(sp);
319230300Sjoerg}
319330300Sjoerg
319430300Sjoergstatic void
319530300Sjoergsppp_chap_tld(struct sppp *sp)
319630300Sjoerg{
319730300Sjoerg	STDDCL;
319830300Sjoerg
319930300Sjoerg	if (debug)
320030300Sjoerg		log(LOG_DEBUG, "%s%d: chap tld\n", ifp->if_name, ifp->if_unit);
320130300Sjoerg	untimeout(chap.TO, (void *)sp, sp->ch[IDX_CHAP]);
320230300Sjoerg	sp->lcp.protos &= ~(1 << IDX_CHAP);
320330300Sjoerg
320430300Sjoerg	lcp.Close(sp);
320530300Sjoerg}
320630300Sjoerg
320730300Sjoergstatic void
320830300Sjoergsppp_chap_scr(struct sppp *sp)
320930300Sjoerg{
321030300Sjoerg	struct timeval tv;
321130300Sjoerg	u_long *ch, seed;
321230300Sjoerg	u_char clen;
321330300Sjoerg
321430300Sjoerg	/* Compute random challenge. */
321530300Sjoerg	ch = (u_long *)sp->myauth.challenge;
321630300Sjoerg	microtime(&tv);
321730300Sjoerg	seed = tv.tv_sec ^ tv.tv_usec;
321830300Sjoerg	ch[0] = seed ^ random();
321930300Sjoerg	ch[1] = seed ^ random();
322030300Sjoerg	ch[2] = seed ^ random();
322130300Sjoerg	ch[3] = seed ^ random();
322230300Sjoerg	clen = AUTHKEYLEN;
322330300Sjoerg
322430300Sjoerg	sp->confid[IDX_CHAP] = ++sp->pp_seq;
322530300Sjoerg
322630300Sjoerg	sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP],
322730300Sjoerg		       sizeof clen, (const char *)&clen,
322830300Sjoerg		       AUTHKEYLEN, sp->myauth.challenge,
322930300Sjoerg		       sppp_strnlen(sp->myauth.name, AUTHNAMELEN),
323030300Sjoerg		       sp->myauth.name,
323130300Sjoerg		       0);
323230300Sjoerg}
323330300Sjoerg/*
323430300Sjoerg *--------------------------------------------------------------------------*
323530300Sjoerg *                                                                          *
323630300Sjoerg *                        The PAP implementation.                           *
323730300Sjoerg *                                                                          *
323830300Sjoerg *--------------------------------------------------------------------------*
323930300Sjoerg */
324030300Sjoerg/*
324130300Sjoerg * For PAP, we need to keep a little state also if we are the peer, not the
324230300Sjoerg * authenticator.  This is since we don't get a request to authenticate, but
324330300Sjoerg * have to repeatedly authenticate ourself until we got a response (or the
324430300Sjoerg * retry counter is expired).
324530300Sjoerg */
324630300Sjoerg
324730300Sjoerg/*
324830300Sjoerg * Handle incoming PAP packets.  */
324930300Sjoergstatic void
325030300Sjoergsppp_pap_input(struct sppp *sp, struct mbuf *m)
325130300Sjoerg{
325230300Sjoerg	STDDCL;
325330300Sjoerg	struct lcp_header *h;
325430300Sjoerg	int len, x;
325530300Sjoerg	u_char *name, *passwd, mlen;
325630300Sjoerg	int name_len, passwd_len;
325730300Sjoerg
325830300Sjoerg	len = m->m_pkthdr.len;
325930300Sjoerg	if (len < 5) {
326030300Sjoerg		if (debug)
326130300Sjoerg			log(LOG_DEBUG,
326230300Sjoerg			    "%s%d: pap invalid packet length: %d bytes\n",
326330300Sjoerg			    ifp->if_name, ifp->if_unit, len);
326430300Sjoerg		return;
326530300Sjoerg	}
326630300Sjoerg	h = mtod (m, struct lcp_header*);
326730300Sjoerg	if (len > ntohs (h->len))
326830300Sjoerg		len = ntohs (h->len);
326930300Sjoerg	switch (h->type) {
327030300Sjoerg	/* PAP request is my authproto */
327130300Sjoerg	case PAP_REQ:
327230300Sjoerg		name = 1 + (u_char*)(h+1);
327330300Sjoerg		name_len = name[-1];
327430300Sjoerg		passwd = name + name_len + 1;
327530300Sjoerg		if (name_len > len - 6 ||
327630300Sjoerg		    (passwd_len = passwd[-1]) > len - 6 - name_len) {
327730300Sjoerg			if (debug) {
327830300Sjoerg				log(LOG_DEBUG, "%s%d: pap corrupted input "
327930300Sjoerg				    "<%s id=0x%x len=%d",
328030300Sjoerg				    ifp->if_name, ifp->if_unit,
328130300Sjoerg				    sppp_auth_type_name(PPP_PAP, h->type),
328230300Sjoerg				    h->ident, ntohs(h->len));
328330300Sjoerg				if (len > 4)
328430300Sjoerg					sppp_print_bytes((u_char*)(h+1), len-4);
328530300Sjoerg				addlog(">\n");
328630300Sjoerg			}
328730300Sjoerg			break;
328830300Sjoerg		}
328930300Sjoerg		if (debug) {
329030300Sjoerg			log(LOG_DEBUG, "%s%d: pap input(%s) "
329130300Sjoerg			    "<%s id=0x%x len=%d name=",
329230300Sjoerg			    ifp->if_name, ifp->if_unit,
329330300Sjoerg			    sppp_state_name(sp->state[IDX_PAP]),
329430300Sjoerg			    sppp_auth_type_name(PPP_PAP, h->type),
329530300Sjoerg			    h->ident, ntohs(h->len));
329630300Sjoerg			sppp_print_string((char*)name, name_len);
329730300Sjoerg			addlog(" passwd=");
329830300Sjoerg			sppp_print_string((char*)passwd, passwd_len);
329930300Sjoerg			addlog(">\n");
330030300Sjoerg		}
330130300Sjoerg		if (name_len > AUTHNAMELEN ||
330230300Sjoerg		    passwd_len > AUTHKEYLEN ||
330330300Sjoerg		    bcmp(name, sp->hisauth.name, name_len) != 0 ||
330430300Sjoerg		    bcmp(passwd, sp->hisauth.secret, passwd_len) != 0) {
330530300Sjoerg			/* action scn, tld */
330630300Sjoerg			mlen = sizeof(FAILMSG) - 1;
330730300Sjoerg			sppp_auth_send(&pap, sp, PAP_NAK, h->ident,
330830300Sjoerg				       sizeof mlen, (const char *)&mlen,
330930300Sjoerg				       sizeof(FAILMSG) - 1, (u_char *)FAILMSG,
331030300Sjoerg				       0);
331130300Sjoerg			pap.tld(sp);
331230300Sjoerg			break;
331330300Sjoerg		}
331430300Sjoerg		/* action sca, perhaps tlu */
331530300Sjoerg		if (sp->state[IDX_PAP] == STATE_REQ_SENT ||
331630300Sjoerg		    sp->state[IDX_PAP] == STATE_OPENED) {
331730300Sjoerg			mlen = sizeof(SUCCMSG) - 1;
331830300Sjoerg			sppp_auth_send(&pap, sp, PAP_ACK, h->ident,
331930300Sjoerg				       sizeof mlen, (const char *)&mlen,
332030300Sjoerg				       sizeof(SUCCMSG) - 1, (u_char *)SUCCMSG,
332130300Sjoerg				       0);
332230300Sjoerg		}
332330300Sjoerg		if (sp->state[IDX_PAP] == STATE_REQ_SENT) {
332430300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_OPENED);
332530300Sjoerg			pap.tlu(sp);
332630300Sjoerg		}
332730300Sjoerg		break;
332830300Sjoerg
332930300Sjoerg	/* ack and nak are his authproto */
333030300Sjoerg	case PAP_ACK:
333130300Sjoerg		untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
333230300Sjoerg		if (debug) {
333330300Sjoerg			log(LOG_DEBUG, "%s%d: pap success",
333430300Sjoerg			    ifp->if_name, ifp->if_unit);
333530300Sjoerg			name_len = *((char *)h);
333630300Sjoerg			if (len > 5 && name_len) {
333730300Sjoerg				addlog(": ");
333830300Sjoerg				sppp_print_string((char*)(h+1), name_len);
333930300Sjoerg			}
334030300Sjoerg			addlog("\n");
334130300Sjoerg		}
334230300Sjoerg		x = splimp();
334330300Sjoerg		sp->pp_flags &= ~PP_NEEDAUTH;
334430300Sjoerg		if (sp->myauth.proto == PPP_PAP &&
334530300Sjoerg		    (sp->lcp.protos & (1 << IDX_PAP)) == 0) {
334630300Sjoerg			/*
334730300Sjoerg			 * We are authenticator for PAP but didn't
334830300Sjoerg			 * complete yet.  Leave it to tlu to proceed
334930300Sjoerg			 * to network phase.
335030300Sjoerg			 */
335130300Sjoerg			splx(x);
335230300Sjoerg			break;
335330300Sjoerg		}
335430300Sjoerg		splx(x);
335530300Sjoerg		sppp_phase_network(sp);
335630300Sjoerg		break;
335730300Sjoerg
335830300Sjoerg	case PAP_NAK:
335930300Sjoerg		untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
336030300Sjoerg		if (debug) {
336130300Sjoerg			log(LOG_INFO, "%s%d: pap failure",
336230300Sjoerg			    ifp->if_name, ifp->if_unit);
336330300Sjoerg			name_len = *((char *)h);
336430300Sjoerg			if (len > 5 && name_len) {
336530300Sjoerg				addlog(": ");
336630300Sjoerg				sppp_print_string((char*)(h+1), name_len);
336730300Sjoerg			}
336830300Sjoerg			addlog("\n");
336930300Sjoerg		} else
337030300Sjoerg			log(LOG_INFO, "%s%d: pap failure\n",
337130300Sjoerg			    ifp->if_name, ifp->if_unit);
337230300Sjoerg		/* await LCP shutdown by authenticator */
337330300Sjoerg		break;
337430300Sjoerg
337530300Sjoerg	default:
337630300Sjoerg		/* Unknown PAP packet type -- ignore. */
337730300Sjoerg		if (debug) {
337830300Sjoerg			log(LOG_DEBUG, "%s%d: pap corrupted input "
337930300Sjoerg			    "<0x%x id=0x%x len=%d",
338030300Sjoerg			    ifp->if_name, ifp->if_unit,
338130300Sjoerg			    h->type, h->ident, ntohs(h->len));
338230300Sjoerg			if (len > 4)
338330300Sjoerg				sppp_print_bytes((u_char*)(h+1), len-4);
338430300Sjoerg			addlog(">\n");
338530300Sjoerg		}
338630300Sjoerg		break;
338730300Sjoerg
338830300Sjoerg	}
338930300Sjoerg}
339030300Sjoerg
339130300Sjoergstatic void
339230300Sjoergsppp_pap_init(struct sppp *sp)
339330300Sjoerg{
339430300Sjoerg	/* PAP doesn't have STATE_INITIAL at all. */
339530300Sjoerg	sp->state[IDX_PAP] = STATE_CLOSED;
339630300Sjoerg	sp->fail_counter[IDX_PAP] = 0;
339730300Sjoerg	callout_handle_init(&sp->ch[IDX_PAP]);
339830300Sjoerg	callout_handle_init(&sp->pap_my_to_ch);
339930300Sjoerg}
340030300Sjoerg
340130300Sjoergstatic void
340230300Sjoergsppp_pap_open(struct sppp *sp)
340330300Sjoerg{
340430300Sjoerg	if (sp->hisauth.proto == PPP_PAP &&
340530300Sjoerg	    (sp->lcp.opts & (1 << LCP_OPT_AUTH_PROTO)) != 0) {
340630300Sjoerg		/* we are authenticator for PAP, start our timer */
340730300Sjoerg		sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
340830300Sjoerg		sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
340930300Sjoerg	}
341030300Sjoerg	if (sp->myauth.proto == PPP_PAP) {
341130300Sjoerg		/* we are peer, send a request, and start a timer */
341230300Sjoerg		pap.scr(sp);
341330300Sjoerg		sp->pap_my_to_ch = timeout(sppp_pap_my_TO, (void *)sp,
341430300Sjoerg					   sp->lcp.timeout);
341530300Sjoerg	}
341630300Sjoerg}
341730300Sjoerg
341830300Sjoergstatic void
341930300Sjoergsppp_pap_close(struct sppp *sp)
342030300Sjoerg{
342130300Sjoerg	if (sp->state[IDX_PAP] != STATE_CLOSED)
342230300Sjoerg		sppp_cp_change_state(&pap, sp, STATE_CLOSED);
342330300Sjoerg}
342430300Sjoerg
342530300Sjoerg/*
342630300Sjoerg * That's the timeout routine if we are authenticator.  Since the
342730300Sjoerg * authenticator is basically passive in PAP, we can't do much here.
342830300Sjoerg */
342930300Sjoergstatic void
343030300Sjoergsppp_pap_TO(void *cookie)
343130300Sjoerg{
343230300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
343330300Sjoerg	STDDCL;
343430300Sjoerg	int s;
343530300Sjoerg
343630300Sjoerg	s = splimp();
343730300Sjoerg	if (debug)
343830300Sjoerg		log(LOG_DEBUG, "%s%d: pap TO(%s) rst_counter = %d\n",
343930300Sjoerg		    ifp->if_name, ifp->if_unit,
344030300Sjoerg		    sppp_state_name(sp->state[IDX_PAP]),
344130300Sjoerg		    sp->rst_counter[IDX_PAP]);
344230300Sjoerg
344330300Sjoerg	if (--sp->rst_counter[IDX_PAP] < 0)
344430300Sjoerg		/* TO- event */
344530300Sjoerg		switch (sp->state[IDX_PAP]) {
344630300Sjoerg		case STATE_REQ_SENT:
344730300Sjoerg			pap.tld(sp);
344830300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_CLOSED);
344930300Sjoerg			break;
345030300Sjoerg		}
345130300Sjoerg	else
345230300Sjoerg		/* TO+ event, not very much we could do */
345330300Sjoerg		switch (sp->state[IDX_PAP]) {
345430300Sjoerg		case STATE_REQ_SENT:
345530300Sjoerg			/* sppp_cp_change_state() will restart the timer */
345630300Sjoerg			sppp_cp_change_state(&pap, sp, STATE_REQ_SENT);
345730300Sjoerg			break;
345830300Sjoerg		}
345930300Sjoerg
346030300Sjoerg	splx(s);
346130300Sjoerg}
346230300Sjoerg
346330300Sjoerg/*
346430300Sjoerg * That's the timeout handler if we are peer.  Since the peer is active,
346530300Sjoerg * we need to retransmit our PAP request since it is apparently lost.
346630300Sjoerg * XXX We should impose a max counter.
346730300Sjoerg */
346830300Sjoergstatic void
346930300Sjoergsppp_pap_my_TO(void *cookie)
347030300Sjoerg{
347130300Sjoerg	struct sppp *sp = (struct sppp *)cookie;
347230300Sjoerg	STDDCL;
347330300Sjoerg
347430300Sjoerg	if (debug)
347530300Sjoerg		log(LOG_DEBUG, "%s%d: pap peer TO\n",
347630300Sjoerg		    ifp->if_name, ifp->if_unit);
347730300Sjoerg
347830300Sjoerg	pap.scr(sp);
347930300Sjoerg}
348030300Sjoerg
348130300Sjoergstatic void
348230300Sjoergsppp_pap_tlu(struct sppp *sp)
348330300Sjoerg{
348430300Sjoerg	STDDCL;
348530300Sjoerg	int x;
348630300Sjoerg
348730300Sjoerg	sp->rst_counter[IDX_PAP] = sp->lcp.max_configure;
348830300Sjoerg
348930300Sjoerg	if (debug)
349030300Sjoerg		log(LOG_DEBUG, "%s%d: %s tlu\n",
349130300Sjoerg		    ifp->if_name, ifp->if_unit, pap.name);
349230300Sjoerg
349330300Sjoerg	x = splimp();
349430300Sjoerg	/* indicate to LCP that we need to be closed down */
349530300Sjoerg	sp->lcp.protos |= (1 << IDX_PAP);
349630300Sjoerg
349730300Sjoerg	if (sp->pp_flags & PP_NEEDAUTH) {
349830300Sjoerg		/*
349930300Sjoerg		 * Remote is authenticator, but his auth proto didn't
350030300Sjoerg		 * complete yet.  Defer the transition to network
350130300Sjoerg		 * phase.
350230300Sjoerg		 */
350330300Sjoerg		splx(x);
350430300Sjoerg		return;
350530300Sjoerg	}
350630300Sjoerg	splx(x);
350730300Sjoerg	sppp_phase_network(sp);
350830300Sjoerg}
350930300Sjoerg
351030300Sjoergstatic void
351130300Sjoergsppp_pap_tld(struct sppp *sp)
351230300Sjoerg{
351330300Sjoerg	STDDCL;
351430300Sjoerg
351530300Sjoerg	if (debug)
351630300Sjoerg		log(LOG_DEBUG, "%s%d: pap tld\n", ifp->if_name, ifp->if_unit);
351730300Sjoerg	untimeout(pap.TO, (void *)sp, sp->ch[IDX_PAP]);
351830300Sjoerg	untimeout(sppp_pap_my_TO, (void *)sp, sp->pap_my_to_ch);
351930300Sjoerg	sp->lcp.protos &= ~(1 << IDX_PAP);
352030300Sjoerg
352130300Sjoerg	lcp.Close(sp);
352230300Sjoerg}
352330300Sjoerg
352430300Sjoergstatic void
352530300Sjoergsppp_pap_scr(struct sppp *sp)
352630300Sjoerg{
352730300Sjoerg	STDDCL;
352830300Sjoerg	u_char idlen, pwdlen;
352930300Sjoerg
353030300Sjoerg	sp->confid[IDX_PAP] = ++sp->pp_seq;
353130300Sjoerg	pwdlen = sppp_strnlen(sp->myauth.secret, AUTHKEYLEN);
353230300Sjoerg	idlen = sppp_strnlen(sp->myauth.name, AUTHNAMELEN);
353330300Sjoerg
353430300Sjoerg	sppp_auth_send(&pap, sp, PAP_REQ, sp->confid[IDX_PAP],
353530300Sjoerg		       sizeof idlen, (const char *)&idlen,
353630300Sjoerg		       (unsigned)idlen, sp->myauth.name,
353730300Sjoerg		       sizeof pwdlen, (const char *)&pwdlen,
353830300Sjoerg		       (unsigned)pwdlen, sp->myauth.secret,
353930300Sjoerg		       0);
354030300Sjoerg}
354130300Sjoerg/*
354225944Sjoerg * Random miscellaneous functions.
354325944Sjoerg */
354425944Sjoerg
35454910Swollman/*
354630300Sjoerg * Send a PAP or CHAP proto packet.
354730300Sjoerg *
354830300Sjoerg * Varadic function, each of the elements for the ellipsis is of type
354930300Sjoerg * ``unsigned mlen, const u_char *msg''.  Processing will stop iff
355030300Sjoerg * mlen == 0.
355130300Sjoerg */
355230300Sjoerg
355330300Sjoergstatic void
355430300Sjoergsppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id,
355530300Sjoerg	       ...)
355630300Sjoerg{
355730300Sjoerg	STDDCL;
355830300Sjoerg	struct ppp_header *h;
355930300Sjoerg	struct lcp_header *lh;
356030300Sjoerg	struct mbuf *m;
356130300Sjoerg	u_char *p;
356230300Sjoerg	int len;
356330300Sjoerg	unsigned mlen;
356430300Sjoerg	const char *msg;
356530300Sjoerg	va_list ap;
356630300Sjoerg
356730300Sjoerg	MGETHDR (m, M_DONTWAIT, MT_DATA);
356830300Sjoerg	if (! m)
356930300Sjoerg		return;
357030300Sjoerg	m->m_pkthdr.rcvif = 0;
357130300Sjoerg
357230300Sjoerg	h = mtod (m, struct ppp_header*);
357330300Sjoerg	h->address = PPP_ALLSTATIONS;		/* broadcast address */
357430300Sjoerg	h->control = PPP_UI;			/* Unnumbered Info */
357530300Sjoerg	h->protocol = htons(cp->proto);
357630300Sjoerg
357730300Sjoerg	lh = (struct lcp_header*)(h + 1);
357830300Sjoerg	lh->type = type;
357930300Sjoerg	lh->ident = id;
358030300Sjoerg	p = (u_char*) (lh+1);
358130300Sjoerg
358230300Sjoerg	va_start(ap, id);
358330300Sjoerg	len = 0;
358430300Sjoerg
358530300Sjoerg	while ((mlen = va_arg(ap, unsigned)) != 0) {
358630300Sjoerg		msg = va_arg(ap, const char *);
358730300Sjoerg		len += mlen;
358830300Sjoerg		if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) {
358930300Sjoerg			va_end(ap);
359030300Sjoerg			m_freem(m);
359130300Sjoerg			return;
359230300Sjoerg		}
359330300Sjoerg
359430300Sjoerg		bcopy(msg, p, mlen);
359530300Sjoerg		p += mlen;
359630300Sjoerg	}
359730300Sjoerg	va_end(ap);
359830300Sjoerg
359930300Sjoerg	m->m_pkthdr.len = m->m_len = PPP_HEADER_LEN + LCP_HEADER_LEN + len;
360030300Sjoerg	lh->len = htons (LCP_HEADER_LEN + len);
360130300Sjoerg
360230300Sjoerg	if (debug) {
360330300Sjoerg		log(LOG_DEBUG, "%s%d: %s output <%s id=0x%x len=%d",
360430300Sjoerg		    ifp->if_name, ifp->if_unit, cp->name,
360530300Sjoerg		    sppp_auth_type_name(cp->proto, lh->type),
360630300Sjoerg		    lh->ident, ntohs(lh->len));
360730300Sjoerg		if (len)
360830300Sjoerg			sppp_print_bytes((u_char*) (lh+1), len);
360930300Sjoerg		addlog(">\n");
361030300Sjoerg	}
361130300Sjoerg	if (IF_QFULL (&sp->pp_cpq)) {
361230300Sjoerg		IF_DROP (&sp->pp_fastq);
361330300Sjoerg		IF_DROP (&ifp->if_snd);
361430300Sjoerg		m_freem (m);
361530300Sjoerg		++ifp->if_oerrors;
361630300Sjoerg	} else
361730300Sjoerg		IF_ENQUEUE (&sp->pp_cpq, m);
361830300Sjoerg	if (! (ifp->if_flags & IFF_OACTIVE))
361930300Sjoerg		(*ifp->if_start) (ifp);
362030300Sjoerg	ifp->if_obytes += m->m_pkthdr.len + 3;
362130300Sjoerg}
362230300Sjoerg
362330300Sjoerg/*
362425944Sjoerg * Flush interface queue.
36254910Swollman */
362612820Sphkstatic void
362725944Sjoergsppp_qflush(struct ifqueue *ifq)
36284910Swollman{
362925944Sjoerg	struct mbuf *m, *n;
36304910Swollman
363125944Sjoerg	n = ifq->ifq_head;
363225944Sjoerg	while ((m = n)) {
363325944Sjoerg		n = m->m_act;
363425944Sjoerg		m_freem (m);
363511189Sjkh	}
363625944Sjoerg	ifq->ifq_head = 0;
363725944Sjoerg	ifq->ifq_tail = 0;
363825944Sjoerg	ifq->ifq_len = 0;
363925944Sjoerg}
364025944Sjoerg
364125944Sjoerg/*
364225944Sjoerg * Send keepalive packets, every 10 seconds.
364325944Sjoerg */
364425944Sjoergstatic void
364525944Sjoergsppp_keepalive(void *dummy)
364625944Sjoerg{
364725944Sjoerg	struct sppp *sp;
364825944Sjoerg	int s;
364925944Sjoerg
365025944Sjoerg	s = splimp();
365125944Sjoerg	for (sp=spppq; sp; sp=sp->pp_next) {
365225944Sjoerg		struct ifnet *ifp = &sp->pp_if;
365325944Sjoerg
365425944Sjoerg		/* Keepalive mode disabled or channel down? */
365525944Sjoerg		if (! (sp->pp_flags & PP_KEEPALIVE) ||
365625944Sjoerg		    ! (ifp->if_flags & IFF_RUNNING))
365725944Sjoerg			continue;
365825944Sjoerg
365925944Sjoerg		/* No keepalive in PPP mode if LCP not opened yet. */
366025944Sjoerg		if (! (sp->pp_flags & PP_CISCO) &&
366125944Sjoerg		    sp->pp_phase < PHASE_AUTHENTICATE)
366225944Sjoerg			continue;
366325944Sjoerg
366425944Sjoerg		if (sp->pp_alivecnt == MAXALIVECNT) {
366525944Sjoerg			/* No keepalive packets got.  Stop the interface. */
366625944Sjoerg			printf ("%s%d: down\n", ifp->if_name, ifp->if_unit);
366725944Sjoerg			if_down (ifp);
366826018Sjoerg			sppp_qflush (&sp->pp_cpq);
366925944Sjoerg			if (! (sp->pp_flags & PP_CISCO)) {
367025944Sjoerg				/* XXX */
367125944Sjoerg				/* Shut down the PPP link. */
367225944Sjoerg				lcp.Down(sp);
367325944Sjoerg				/* Initiate negotiation. XXX */
367425944Sjoerg				lcp.Up(sp);
367525944Sjoerg			}
36764910Swollman		}
367725944Sjoerg		if (sp->pp_alivecnt <= MAXALIVECNT)
367825944Sjoerg			++sp->pp_alivecnt;
367925944Sjoerg		if (sp->pp_flags & PP_CISCO)
368025944Sjoerg			sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,
368125944Sjoerg				sp->pp_rseq);
368225944Sjoerg		else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
368325944Sjoerg			long nmagic = htonl (sp->lcp.magic);
368425944Sjoerg			sp->lcp.echoid = ++sp->pp_seq;
368525944Sjoerg			sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
368625944Sjoerg				sp->lcp.echoid, 4, &nmagic);
368725944Sjoerg		}
36884910Swollman	}
368925944Sjoerg	splx(s);
369029681Sgibbs	keepalive_ch = timeout(sppp_keepalive, 0, hz * 10);
36914910Swollman}
36924910Swollman
369325944Sjoerg/*
369425944Sjoerg * Get both IP addresses.
369525944Sjoerg */
369625944Sjoergstatic void
369730300Sjoergsppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask)
369825944Sjoerg{
369925944Sjoerg	struct ifnet *ifp = &sp->pp_if;
370025944Sjoerg	struct ifaddr *ifa;
370130300Sjoerg	struct sockaddr_in *si, *sm;
370225944Sjoerg	u_long ssrc, ddst;
370325944Sjoerg
370425944Sjoerg	ssrc = ddst = 0L;
370525944Sjoerg	/*
370625944Sjoerg	 * Pick the first AF_INET address from the list,
370725944Sjoerg	 * aliases don't make any sense on a p2p link anyway.
370825944Sjoerg	 */
370925944Sjoerg	for (ifa = ifp->if_addrhead.tqh_first, si = 0;
371030300Sjoerg	     ifa;
371125944Sjoerg	     ifa = ifa->ifa_link.tqe_next)
371225944Sjoerg		if (ifa->ifa_addr->sa_family == AF_INET) {
371325944Sjoerg			si = (struct sockaddr_in *)ifa->ifa_addr;
371430300Sjoerg			sm = (struct sockaddr_in *)ifa->ifa_netmask;
371525944Sjoerg			if (si)
371625944Sjoerg				break;
371725944Sjoerg		}
371825944Sjoerg	if (ifa) {
371930300Sjoerg		if (si && si->sin_addr.s_addr) {
372025944Sjoerg			ssrc = si->sin_addr.s_addr;
372130300Sjoerg			if (srcmask)
372230300Sjoerg				*srcmask = ntohl(sm->sin_addr.s_addr);
372330300Sjoerg		}
372425944Sjoerg
372525944Sjoerg		si = (struct sockaddr_in *)ifa->ifa_dstaddr;
372625944Sjoerg		if (si && si->sin_addr.s_addr)
372725944Sjoerg			ddst = si->sin_addr.s_addr;
372825944Sjoerg	}
372925944Sjoerg
373025944Sjoerg	if (dst) *dst = ntohl(ddst);
373125944Sjoerg	if (src) *src = ntohl(ssrc);
373225944Sjoerg}
373325944Sjoerg
373425944Sjoerg/*
373525944Sjoerg * Set my IP address.  Must be called at splimp.
373625944Sjoerg */
373725944Sjoergstatic void
373825944Sjoergsppp_set_ip_addr(struct sppp *sp, u_long src)
373925944Sjoerg{
374025944Sjoerg	struct ifnet *ifp = &sp->pp_if;
374125944Sjoerg	struct ifaddr *ifa;
374225944Sjoerg	struct sockaddr_in *si;
374325944Sjoerg	u_long ssrc, ddst;
374425944Sjoerg
374525944Sjoerg	/*
374625944Sjoerg	 * Pick the first AF_INET address from the list,
374725944Sjoerg	 * aliases don't make any sense on a p2p link anyway.
374825944Sjoerg	 */
374925944Sjoerg	for (ifa = ifp->if_addrhead.tqh_first, si = 0;
375030300Sjoerg	     ifa;
375125944Sjoerg	     ifa = ifa->ifa_link.tqe_next)
375225944Sjoerg		if (ifa->ifa_addr->sa_family == AF_INET) {
375325944Sjoerg			si = (struct sockaddr_in *)ifa->ifa_addr;
375425944Sjoerg			if (si)
375525944Sjoerg				break;
375625944Sjoerg		}
375725944Sjoerg	if (ifa && si)
375825944Sjoerg		si->sin_addr.s_addr = htonl(src);
375925944Sjoerg}
376025944Sjoerg
376130300Sjoergstatic int
376230300Sjoergsppp_params(struct sppp *sp, int cmd, void *data)
376330300Sjoerg{
376430300Sjoerg	int subcmd;
376530300Sjoerg	struct ifreq *ifr = (struct ifreq *)data;
376630300Sjoerg	struct spppreq spr;
376730300Sjoerg
376830300Sjoerg	/*
376930300Sjoerg	 * ifr->ifr_data is supposed to point to a struct spppreq.
377030300Sjoerg	 * Check the cmd word first before attempting to fetch all the
377130300Sjoerg	 * data.
377230300Sjoerg	 */
377330300Sjoerg	if ((subcmd = fuword(ifr->ifr_data)) == -1)
377430300Sjoerg		return EFAULT;
377530300Sjoerg
377630300Sjoerg	if (copyin((caddr_t)ifr->ifr_data, &spr, sizeof spr) != 0)
377730300Sjoerg		return EFAULT;
377830300Sjoerg
377930300Sjoerg	switch (subcmd) {
378030300Sjoerg	case SPPPIOGDEFS:
378130300Sjoerg		if (cmd != SIOCGIFGENERIC)
378230300Sjoerg			return EINVAL;
378330300Sjoerg		/*
378430300Sjoerg		 * We copy over the entire current state, but clean
378530300Sjoerg		 * out some of the stuff we don't wanna pass up.
378630300Sjoerg		 * Remember, SIOCGIFGENERIC is unprotected, and can be
378730300Sjoerg		 * called by any user.  No need to ever get PAP or
378830300Sjoerg		 * CHAP secrets back to userland anyway.
378930300Sjoerg		 */
379030300Sjoerg		bcopy(sp, &spr.defs, sizeof(struct sppp));
379130300Sjoerg		bzero(spr.defs.myauth.secret, AUTHKEYLEN);
379230300Sjoerg		bzero(spr.defs.myauth.challenge, AUTHKEYLEN);
379330300Sjoerg		bzero(spr.defs.hisauth.secret, AUTHKEYLEN);
379430300Sjoerg		bzero(spr.defs.hisauth.challenge, AUTHKEYLEN);
379530300Sjoerg		return copyout(&spr, (caddr_t)ifr->ifr_data, sizeof spr);
379630300Sjoerg
379730300Sjoerg	case SPPPIOSDEFS:
379830300Sjoerg		if (cmd != SIOCSIFGENERIC)
379930300Sjoerg			return EINVAL;
380030300Sjoerg		/*
380130300Sjoerg		 * We have a very specific idea of which fields we allow
380230300Sjoerg		 * being passed back from userland, so to not clobber our
380330300Sjoerg		 * current state.  For one, we only allow setting
380430300Sjoerg		 * anything if LCP is in dead phase.  Once the LCP
380530300Sjoerg		 * negotiations started, the authentication settings must
380630300Sjoerg		 * not be changed again.  (The administrator can force an
380730300Sjoerg		 * ifconfig down in order to get LCP back into dead
380830300Sjoerg		 * phase.)
380930300Sjoerg		 *
381030300Sjoerg		 * Also, we only allow for authentication parameters to be
381130300Sjoerg		 * specified.
381230300Sjoerg		 *
381330300Sjoerg		 * XXX Should allow to set or clear pp_flags.
381430300Sjoerg		 *
381530300Sjoerg		 * Finally, if the respective authentication protocol to
381630300Sjoerg		 * be used is set differently than 0, but the secret is
381730300Sjoerg		 * passed as all zeros, we don't trash the existing secret.
381830300Sjoerg		 * This allows an administrator to change the system name
381930300Sjoerg		 * only without clobbering the secret (which he didn't get
382030300Sjoerg		 * back in a previous SPPPIOGDEFS call).  However, the
382130300Sjoerg		 * secrets are cleared if the authentication protocol is
382230300Sjoerg		 * reset to 0.
382330300Sjoerg		 */
382430300Sjoerg		if (sp->pp_phase != PHASE_DEAD)
382530300Sjoerg			return EBUSY;
382630300Sjoerg
382730300Sjoerg		if ((spr.defs.myauth.proto != 0 && spr.defs.myauth.proto != PPP_PAP &&
382830300Sjoerg		     spr.defs.myauth.proto != PPP_CHAP) ||
382930300Sjoerg		    (spr.defs.hisauth.proto != 0 && spr.defs.hisauth.proto != PPP_PAP &&
383030300Sjoerg		     spr.defs.hisauth.proto != PPP_CHAP))
383130300Sjoerg			return EINVAL;
383230300Sjoerg
383330300Sjoerg		if (spr.defs.myauth.proto == 0)
383430300Sjoerg			/* resetting myauth */
383530300Sjoerg			bzero(&sp->myauth, sizeof sp->myauth);
383630300Sjoerg		else {
383730300Sjoerg			/* setting/changing myauth */
383830300Sjoerg			sp->myauth.proto = spr.defs.myauth.proto;
383930300Sjoerg			bcopy(spr.defs.myauth.name, sp->myauth.name, AUTHNAMELEN);
384030300Sjoerg			if (spr.defs.myauth.secret[0] != '\0')
384130300Sjoerg				bcopy(spr.defs.myauth.secret, sp->myauth.secret,
384230300Sjoerg				      AUTHKEYLEN);
384330300Sjoerg		}
384430300Sjoerg		if (spr.defs.hisauth.proto == 0)
384530300Sjoerg			/* resetting hisauth */
384630300Sjoerg			bzero(&sp->hisauth, sizeof sp->hisauth);
384730300Sjoerg		else {
384830300Sjoerg			/* setting/changing hisauth */
384930300Sjoerg			sp->hisauth.proto = spr.defs.hisauth.proto;
385030300Sjoerg			sp->hisauth.flags = spr.defs.hisauth.flags;
385130300Sjoerg			bcopy(spr.defs.hisauth.name, sp->hisauth.name, AUTHNAMELEN);
385230300Sjoerg			if (spr.defs.hisauth.secret[0] != '\0')
385330300Sjoerg				bcopy(spr.defs.hisauth.secret, sp->hisauth.secret,
385430300Sjoerg				      AUTHKEYLEN);
385530300Sjoerg		}
385630300Sjoerg		break;
385730300Sjoerg
385830300Sjoerg	default:
385930300Sjoerg		return EINVAL;
386030300Sjoerg	}
386130300Sjoerg
386230300Sjoerg	return 0;
386330300Sjoerg}
386430300Sjoerg
386530300Sjoergstatic void
386630300Sjoergsppp_phase_network(struct sppp *sp)
386730300Sjoerg{
386830300Sjoerg	struct ifnet *ifp = &sp->pp_if;
386930300Sjoerg	int i;
387030300Sjoerg	u_long mask;
387130300Sjoerg
387230300Sjoerg	sp->pp_phase = PHASE_NETWORK;
387330300Sjoerg
387430300Sjoerg	log(LOG_INFO, "%s%d: phase %s\n", ifp->if_name, ifp->if_unit,
387530300Sjoerg	    sppp_phase_name(sp->pp_phase));
387630300Sjoerg
387730300Sjoerg	/* Notify NCPs now. */
387830300Sjoerg	for (i = 0; i < IDX_COUNT; i++)
387930300Sjoerg		if ((cps[i])->flags & CP_NCP)
388030300Sjoerg			(cps[i])->Open(sp);
388130300Sjoerg
388230300Sjoerg	/* Send Up events to all NCPs. */
388330300Sjoerg	for (i = 0, mask = 1; i < IDX_COUNT; i++, mask <<= 1)
388430300Sjoerg		if (sp->lcp.protos & mask && ((cps[i])->flags & CP_NCP))
388530300Sjoerg			(cps[i])->Up(sp);
388630300Sjoerg
388730300Sjoerg	/* if no NCP is starting, all this was in vain, close down */
388830300Sjoerg	sppp_lcp_check_and_close(sp);
388930300Sjoerg}
389030300Sjoerg
389130300Sjoerg
389225706Sjoergstatic const char *
389325944Sjoergsppp_cp_type_name(u_char type)
38944910Swollman{
389530300Sjoerg	static char buf[12];
38964910Swollman	switch (type) {
389730300Sjoerg	case CONF_REQ:   return "conf-req";
389830300Sjoerg	case CONF_ACK:   return "conf-ack";
389930300Sjoerg	case CONF_NAK:   return "conf-nak";
390030300Sjoerg	case CONF_REJ:   return "conf-rej";
390130300Sjoerg	case TERM_REQ:   return "term-req";
390230300Sjoerg	case TERM_ACK:   return "term-ack";
390330300Sjoerg	case CODE_REJ:   return "code-rej";
390430300Sjoerg	case PROTO_REJ:  return "proto-rej";
390530300Sjoerg	case ECHO_REQ:   return "echo-req";
390630300Sjoerg	case ECHO_REPLY: return "echo-reply";
390730300Sjoerg	case DISC_REQ:   return "discard-req";
39084910Swollman	}
390925706Sjoerg	sprintf (buf, "0x%x", type);
391030300Sjoerg	return buf;
39114910Swollman}
39124910Swollman
391325706Sjoergstatic const char *
391430300Sjoergsppp_auth_type_name(u_short proto, u_char type)
391530300Sjoerg{
391630300Sjoerg	static char buf[12];
391730300Sjoerg	switch (proto) {
391830300Sjoerg	case PPP_CHAP:
391930300Sjoerg		switch (type) {
392030300Sjoerg		case CHAP_CHALLENGE:	return "challenge";
392130300Sjoerg		case CHAP_RESPONSE:	return "response";
392230300Sjoerg		case CHAP_SUCCESS:	return "success";
392330300Sjoerg		case CHAP_FAILURE:	return "failure";
392430300Sjoerg		}
392530300Sjoerg	case PPP_PAP:
392630300Sjoerg		switch (type) {
392730300Sjoerg		case PAP_REQ:		return "req";
392830300Sjoerg		case PAP_ACK:		return "ack";
392930300Sjoerg		case PAP_NAK:		return "nak";
393030300Sjoerg		}
393130300Sjoerg	}
393230300Sjoerg	sprintf (buf, "0x%x", type);
393330300Sjoerg	return buf;
393430300Sjoerg}
393530300Sjoerg
393630300Sjoergstatic const char *
393725944Sjoergsppp_lcp_opt_name(u_char opt)
39384910Swollman{
393930300Sjoerg	static char buf[12];
394025944Sjoerg	switch (opt) {
394130300Sjoerg	case LCP_OPT_MRU:		return "mru";
394230300Sjoerg	case LCP_OPT_ASYNC_MAP:		return "async-map";
394330300Sjoerg	case LCP_OPT_AUTH_PROTO:	return "auth-proto";
394430300Sjoerg	case LCP_OPT_QUAL_PROTO:	return "qual-proto";
394530300Sjoerg	case LCP_OPT_MAGIC:		return "magic";
394630300Sjoerg	case LCP_OPT_PROTO_COMP:	return "proto-comp";
394730300Sjoerg	case LCP_OPT_ADDR_COMP:		return "addr-comp";
39484910Swollman	}
394925944Sjoerg	sprintf (buf, "0x%x", opt);
395030300Sjoerg	return buf;
39514910Swollman}
39524910Swollman
395325944Sjoergstatic const char *
395425944Sjoergsppp_ipcp_opt_name(u_char opt)
395525944Sjoerg{
395630300Sjoerg	static char buf[12];
395725944Sjoerg	switch (opt) {
395830300Sjoerg	case IPCP_OPT_ADDRESSES:	return "addresses";
395930300Sjoerg	case IPCP_OPT_COMPRESSION:	return "compression";
396030300Sjoerg	case IPCP_OPT_ADDRESS:		return "address";
396125944Sjoerg	}
396225944Sjoerg	sprintf (buf, "0x%x", opt);
396330300Sjoerg	return buf;
396425944Sjoerg}
396525944Sjoerg
396625944Sjoergstatic const char *
396725944Sjoergsppp_state_name(int state)
396825944Sjoerg{
396925944Sjoerg	switch (state) {
397025944Sjoerg	case STATE_INITIAL:	return "initial";
397125944Sjoerg	case STATE_STARTING:	return "starting";
397225944Sjoerg	case STATE_CLOSED:	return "closed";
397325944Sjoerg	case STATE_STOPPED:	return "stopped";
397425944Sjoerg	case STATE_CLOSING:	return "closing";
397525944Sjoerg	case STATE_STOPPING:	return "stopping";
397625944Sjoerg	case STATE_REQ_SENT:	return "req-sent";
397725944Sjoerg	case STATE_ACK_RCVD:	return "ack-rcvd";
397825944Sjoerg	case STATE_ACK_SENT:	return "ack-sent";
397925944Sjoerg	case STATE_OPENED:	return "opened";
398025944Sjoerg	}
398125944Sjoerg	return "illegal";
398225944Sjoerg}
398325944Sjoerg
398425944Sjoergstatic const char *
398525944Sjoergsppp_phase_name(enum ppp_phase phase)
398625944Sjoerg{
398725944Sjoerg	switch (phase) {
398825944Sjoerg	case PHASE_DEAD:	return "dead";
398925944Sjoerg	case PHASE_ESTABLISH:	return "establish";
399025944Sjoerg	case PHASE_TERMINATE:	return "terminate";
399125944Sjoerg	case PHASE_AUTHENTICATE: return "authenticate";
399225944Sjoerg	case PHASE_NETWORK:	return "network";
399325944Sjoerg	}
399425944Sjoerg	return "illegal";
399525944Sjoerg}
399625944Sjoerg
399725944Sjoergstatic const char *
399825944Sjoergsppp_proto_name(u_short proto)
399925944Sjoerg{
400025944Sjoerg	static char buf[12];
400125944Sjoerg	switch (proto) {
400225944Sjoerg	case PPP_LCP:	return "lcp";
400325944Sjoerg	case PPP_IPCP:	return "ipcp";
400430300Sjoerg	case PPP_PAP:	return "pap";
400530300Sjoerg	case PPP_CHAP:	return "chap";
400625944Sjoerg	}
400725944Sjoerg	sprintf(buf, "0x%x", (unsigned)proto);
400825944Sjoerg	return buf;
400925944Sjoerg}
401025944Sjoerg
401112820Sphkstatic void
401230300Sjoergsppp_print_bytes(const u_char *p, u_short len)
40134910Swollman{
401425706Sjoerg	addlog(" %x", *p++);
40154910Swollman	while (--len > 0)
401625706Sjoerg		addlog("-%x", *p++);
40174910Swollman}
401825944Sjoerg
401930300Sjoergstatic void
402030300Sjoergsppp_print_string(const char *p, u_short len)
402130300Sjoerg{
402230300Sjoerg	u_char c;
402330300Sjoerg
402430300Sjoerg	while (len-- > 0) {
402530300Sjoerg		c = *p++;
402630300Sjoerg		/*
402730300Sjoerg		 * Print only ASCII chars directly.  RFC 1994 recommends
402830300Sjoerg		 * using only them, but we don't rely on it.  */
402930300Sjoerg		if (c < ' ' || c > '~')
403030300Sjoerg			addlog("\\x%x", c);
403130300Sjoerg		else
403230300Sjoerg			addlog("%c", c);
403330300Sjoerg	}
403430300Sjoerg}
403530300Sjoerg
403630300Sjoergstatic const char *
403730300Sjoergsppp_dotted_quad(u_long addr)
403830300Sjoerg{
403930300Sjoerg	static char s[16];
404030300Sjoerg	sprintf(s, "%d.%d.%d.%d",
404130300Sjoerg		(addr >> 24) & 0xff,
404230300Sjoerg		(addr >> 16) & 0xff,
404330300Sjoerg		(addr >> 8) & 0xff,
404430300Sjoerg		addr & 0xff);
404530300Sjoerg	return s;
404630300Sjoerg}
404730300Sjoerg
404830300Sjoergstatic int
404930300Sjoergsppp_strnlen(u_char *p, int max)
405030300Sjoerg{
405130300Sjoerg	int len;
405230300Sjoerg
405330300Sjoerg	for (len = 0; len < max && *p; ++p)
405430300Sjoerg		++len;
405530300Sjoerg	return len;
405630300Sjoerg}
405730300Sjoerg
405830300Sjoerg/* a dummy, used to drop uninteresting events */
405930300Sjoergstatic void
406030300Sjoergsppp_null(struct sppp *unused)
406130300Sjoerg{
406230300Sjoerg	/* do just nothing */
406330300Sjoerg}
406425944Sjoerg/*
406525944Sjoerg * This file is large.  Tell emacs to highlight it nevertheless.
406625944Sjoerg *
406725944Sjoerg * Local Variables:
406830300Sjoerg * hilit-auto-highlight-maxout: 120000
406925944Sjoerg * End:
407025944Sjoerg */
4071