[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/ppp-2.4.1/Makefile b/ap/app/ppp-2.4.1/Makefile
new file mode 100755
index 0000000..409e565
--- /dev/null
+++ b/ap/app/ppp-2.4.1/Makefile
@@ -0,0 +1,65 @@
+# PPP top-level Makefile for Linux.
+
+#include ../net_team.mk
+include $(COMMON_BASE_MK)
+BINDIR = $(DESTDIR)/usr/sbin
+MANDIR = $(DESTDIR)/usr/man
+ETCDIR = $(DESTDIR)/etc/ppp
+
+# uid 0 = root
+INSTALL= install
+
+all:
+	cd pppoecd; make $(MFLAGS) all
+	#cd chat; $(MAKE) $(MFLAGS) all
+	#cd pppd/plugins; $(MAKE) $(MFLAGS) all
+	#cd pppd; $(MAKE) $(MFLAGS) all
+	#cd pppstats; $(MAKE) $(MFLAGS) all
+	#cd pppdump; $(MAKE) $(MFLAGS) all
+
+install: $(BINDIR) $(MANDIR)/man8 install-progs install-etcppp
+
+install-progs:
+	#cd chat; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install
+	#cd pppd/plugins; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install
+	#cd pppd; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install
+	#cd pppstats; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install
+	#cd pppdump; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install
+
+install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
+	$(ETCDIR)/chap-secrets
+
+$(ETCDIR)/options:
+	$(INSTALL) -c -m 644 etc.ppp/options $@
+$(ETCDIR)/pap-secrets:
+	$(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
+$(ETCDIR)/chap-secrets:
+	$(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
+
+$(BINDIR):
+	$(INSTALL) -d -m 755 $@
+$(MANDIR)/man8:
+	$(INSTALL) -d -m 755 $@
+$(ETCDIR):
+	$(INSTALL) -d -m 755 $@
+
+clean:
+	rm -f `find . -name '*.[oas]' -print`
+	rm -f `find . -name 'core' -print`
+	rm -f `find . -name '*~' -print`
+	-rm pppoecd/pppoecd pppoecd/pppoecd.elf
+	-rm pppoecd/poeupdown pppoecd/poeupdown.elf
+
+dist-clean:	clean
+	rm -f Makefile `find . -name Makefile -print`
+ifneq ($(LINUX_TYPE),uClinux)
+romfs:
+	cd pppoecd; \
+	make $(MFLAGS) romfs
+else
+romfs:
+	cd pppoecd; \
+	make $(MFLAGS) romfs
+endif
+#kernel:
+#	cd linux; ./kinstall.sh
diff --git a/ap/app/ppp-2.4.1/include/linux/if_ppp.h b/ap/app/ppp-2.4.1/include/linux/if_ppp.h
new file mode 100644
index 0000000..2a7982f
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/linux/if_ppp.h
@@ -0,0 +1,155 @@
+/*	$Id: if_ppp.h,v 1.1 2008-08-04 06:11:50 winfred Exp $	*/
+
+/*
+ * if_ppp.h - Point-to-Point Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ *  ==FILEVERSION 20000724==
+ *
+ *  NOTE TO MAINTAINERS:
+ *     If you modify this file at all, please set the above date.
+ *     if_ppp.h is shipped with a PPP distribution as well as with the kernel;
+ *     if everyone increases the FILEVERSION number above, then scripts
+ *     can do the right thing when deciding whether to install a new if_ppp.h
+ *     file.  Don't change the format of that line otherwise, so the
+ *     installation script can recognize it.
+ */
+
+#ifndef _IF_PPP_H_
+#define _IF_PPP_H_
+
+/*
+ * Packet sizes
+ */
+
+#define	PPP_MTU		1500	/* Default MTU (size of Info field) */
+#define PPP_MAXMRU	65000	/* Largest MRU we allow */
+#define PROTO_IPX	0x002b	/* protocol numbers */
+#define PROTO_DNA_RT    0x0027  /* DNA Routing */
+
+
+/*
+ * Bit definitions for flags.
+ */
+
+#define SC_COMP_PROT	0x00000001	/* protocol compression (output) */
+#define SC_COMP_AC	0x00000002	/* header compression (output) */
+#define	SC_COMP_TCP	0x00000004	/* TCP (VJ) compression (output) */
+#define SC_NO_TCP_CCID	0x00000008	/* disable VJ connection-id comp. */
+#define SC_REJ_COMP_AC	0x00000010	/* reject adrs/ctrl comp. on input */
+#define SC_REJ_COMP_TCP	0x00000020	/* reject TCP (VJ) comp. on input */
+#define SC_CCP_OPEN	0x00000040	/* Look at CCP packets */
+#define SC_CCP_UP	0x00000080	/* May send/recv compressed packets */
+#define SC_ENABLE_IP	0x00000100	/* IP packets may be exchanged */
+#define SC_LOOP_TRAFFIC	0x00000200	/* send traffic to pppd */
+#define SC_MULTILINK	0x00000400	/* do multilink encapsulation */
+#define SC_MP_SHORTSEQ	0x00000800	/* use short MP sequence numbers */
+#define SC_COMP_RUN	0x00001000	/* compressor has been inited */
+#define SC_DECOMP_RUN	0x00002000	/* decompressor has been inited */
+#define SC_MP_XSHORTSEQ	0x00004000	/* transmit short MP seq numbers */
+#define SC_DEBUG	0x00010000	/* enable debug messages */
+#define SC_LOG_INPKT	0x00020000	/* log contents of good pkts recvd */
+#define SC_LOG_OUTPKT	0x00040000	/* log contents of pkts sent */
+#define SC_LOG_RAWIN	0x00080000	/* log all chars received */
+#define SC_LOG_FLUSH	0x00100000	/* log all chars flushed */
+#define	SC_SYNC		0x00200000	/* synchronous serial mode */
+#define	SC_MASK		0x0f200fff	/* bits that user can change */
+
+/* state bits */
+#define SC_XMIT_BUSY	0x10000000	/* (used by isdn_ppp?) */
+#define SC_RCV_ODDP	0x08000000	/* have rcvd char with odd parity */
+#define SC_RCV_EVNP	0x04000000	/* have rcvd char with even parity */
+#define SC_RCV_B7_1	0x02000000	/* have rcvd char with bit 7 = 1 */
+#define SC_RCV_B7_0	0x01000000	/* have rcvd char with bit 7 = 0 */
+#define SC_DC_FERROR	0x00800000	/* fatal decomp error detected */
+#define SC_DC_ERROR	0x00400000	/* non-fatal decomp error detected */
+
+/*
+ * Ioctl definitions.
+ */
+
+struct npioctl {
+	int		protocol;	/* PPP protocol, e.g. PPP_IP */
+	enum NPmode	mode;
+};
+
+/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
+struct ppp_option_data {
+	__u8	*ptr;
+	__u32	length;
+	int	transmit;
+};
+
+struct ifpppstatsreq {
+	struct ifreq	 b;
+	struct ppp_stats stats;			/* statistic information */
+};
+
+struct ifpppcstatsreq {
+	struct ifreq	      b;
+	struct ppp_comp_stats stats;
+};
+
+#define ifr__name       b.ifr_ifrn.ifrn_name
+#define stats_ptr       b.ifr_ifru.ifru_data
+
+/*
+ * Ioctl definitions.
+ */
+
+#define	PPPIOCGFLAGS	_IOR('t', 90, int)	/* get configuration flags */
+#define	PPPIOCSFLAGS	_IOW('t', 89, int)	/* set configuration flags */
+#define	PPPIOCGASYNCMAP	_IOR('t', 88, int)	/* get async map */
+#define	PPPIOCSASYNCMAP	_IOW('t', 87, int)	/* set async map */
+#define	PPPIOCGUNIT	_IOR('t', 86, int)	/* get ppp unit number */
+#define	PPPIOCGRASYNCMAP _IOR('t', 85, int)	/* get receive async map */
+#define	PPPIOCSRASYNCMAP _IOW('t', 84, int)	/* set receive async map */
+#define	PPPIOCGMRU	_IOR('t', 83, int)	/* get max receive unit */
+#define	PPPIOCSMRU	_IOW('t', 82, int)	/* set max receive unit */
+#define	PPPIOCSMAXCID	_IOW('t', 81, int)	/* set VJ max slot ID */
+#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
+#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
+#define PPPIOCXFERUNIT	_IO('t', 78)		/* transfer PPP unit */
+#define PPPIOCSCOMPRESS	_IOW('t', 77, struct ppp_option_data)
+#define PPPIOCGNPMODE	_IOWR('t', 76, struct npioctl) /* get NP mode */
+#define PPPIOCSNPMODE	_IOW('t', 75, struct npioctl)  /* set NP mode */
+#define PPPIOCSPASS	_IOW('t', 71, struct sock_fprog) /* set pass filter */
+#define PPPIOCSACTIVE	_IOW('t', 70, struct sock_fprog) /* set active filt */
+#define PPPIOCGDEBUG	_IOR('t', 65, int)	/* Read debug level */
+#define PPPIOCSDEBUG	_IOW('t', 64, int)	/* Set debug level */
+#define PPPIOCGIDLE	_IOR('t', 63, struct ppp_idle) /* get idle time */
+#define PPPIOCNEWUNIT	_IOWR('t', 62, int)	/* create new ppp unit */
+#define PPPIOCATTACH	_IOW('t', 61, int)	/* attach to ppp unit */
+#define PPPIOCDETACH	_IOW('t', 60, int)	/* detach from ppp unit/chan */
+#define PPPIOCSMRRU	_IOW('t', 59, int)	/* set multilink MRU */
+#define PPPIOCCONNECT	_IOW('t', 58, int)	/* connect channel to unit */
+#define PPPIOCDISCONN	_IO('t', 57)		/* disconnect channel */
+#define PPPIOCATTCHAN	_IOW('t', 56, int)	/* attach to ppp channel */
+#define PPPIOCGCHAN	_IOR('t', 55, int)	/* get ppp channel number */
+
+#define SIOCGPPPSTATS   (SIOCDEVPRIVATE + 0)
+#define SIOCGPPPVER     (SIOCDEVPRIVATE + 1)	/* NEVER change this!! */
+#define SIOCGPPPCSTATS  (SIOCDEVPRIVATE + 2)
+
+#if !defined(ifr_mtu)
+#define ifr_mtu	ifr_ifru.ifru_metric
+#endif
+
+#endif /* _IF_PPP_H_ */
diff --git a/ap/app/ppp-2.4.1/include/linux/if_pppvar.h b/ap/app/ppp-2.4.1/include/linux/if_pppvar.h
new file mode 100644
index 0000000..b2485cd
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/linux/if_pppvar.h
@@ -0,0 +1,138 @@
+/*	From: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp */
+/*
+ * if_pppvar.h - private structures and declarations for PPP.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ==FILEVERSION 990911==
+ *
+ *  NOTE TO MAINTAINERS:
+ *   If you modify this file at all, please set the above date.
+ *   if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
+ *   if everyone increases the FILEVERSION number above, then scripts
+ *   can do the right thing when deciding whether to install a new if_pppvar.h
+ *   file.  Don't change the format of that line otherwise, so the
+ *   installation script can recognize it.
+ */
+
+/*
+ * Supported network protocols.  These values are used for
+ * indexing sc_npmode.
+ */
+
+#define NP_IP	0		/* Internet Protocol */
+#define NP_IPX	1		/* IPX protocol */
+#define NP_AT	2		/* Appletalk protocol */
+#define NP_IPV6	3		/* Internet Protocol */
+#define NUM_NP	4		/* Number of NPs. */
+
+#define OBUFSIZE	256	/* # chars of output buffering */
+
+/*
+ * Structure describing each ppp unit.
+ */
+
+struct ppp {
+	int		magic;		/* magic value for structure	*/
+	struct ppp	*next;		/* unit with next index		*/
+	unsigned long	inuse;		/* are we allocated?		*/
+	int		line;		/* network interface unit #	*/
+	__u32		flags;		/* miscellaneous control flags	*/
+	int		mtu;		/* maximum xmit frame size	*/
+	int		mru;		/* maximum receive frame size	*/
+	struct slcompress *slcomp;	/* for TCP header compression	*/
+	struct sk_buff_head xmt_q;	/* frames to send from pppd	*/
+	struct sk_buff_head rcv_q;	/* frames for pppd to read	*/
+	unsigned long	xmit_busy;	/* bit 0 set when xmitter busy  */
+
+	/* Information specific to using ppp on async serial lines. */
+	struct tty_struct *tty;		/* ptr to TTY structure	*/
+	struct tty_struct *backup_tty;	/* TTY to use if tty gets closed */
+	__u8		escape;		/* 0x20 if prev char was PPP_ESC */
+	__u8		toss;		/* toss this frame		*/
+	volatile __u8	tty_pushing;	/* internal state flag		*/
+	volatile __u8	woke_up;	/* internal state flag		*/
+	__u32		xmit_async_map[8]; /* 1 bit means that given control 
+					   character is quoted on output*/
+	__u32		recv_async_map; /* 1 bit means that given control 
+					   character is ignored on input*/
+	__u32		bytes_sent;	/* Bytes sent on frame	*/
+	__u32		bytes_rcvd;	/* Bytes recvd on frame	*/
+
+	/* Async transmission information */
+	struct sk_buff	*tpkt;		/* frame currently being sent	*/
+	int		tpkt_pos;	/* how much of it we've done	*/
+	__u16		tfcs;		/* FCS so far for it		*/
+	unsigned char	*optr;		/* where we're up to in sending */
+	unsigned char	*olim;		/* points past last valid char	*/
+
+	/* Async reception information */
+	struct sk_buff	*rpkt;		/* frame currently being rcvd	*/
+	__u16		rfcs;		/* FCS so far of rpkt		*/
+
+	/* Queues for select() functionality */
+	struct wait_queue *read_wait;	/* queue for reading processes	*/
+
+	/* info for detecting idle channels */
+	unsigned long	last_xmit;	/* time of last transmission	*/
+	unsigned long	last_recv;	/* time last packet received    */
+
+	/* Statistic information */
+	struct pppstat	stats;		/* statistic information	*/
+
+	/* PPP compression protocol information */
+	struct	compressor *sc_xcomp;	/* transmit compressor */
+	void	*sc_xc_state;		/* transmit compressor state */
+	struct	compressor *sc_rcomp;	/* receive decompressor */
+	void	*sc_rc_state;		/* receive decompressor state */
+
+	enum	NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
+	int	 sc_xfer;		/* PID of reserved PPP table */
+	char	name[8];		/* space for unit name */
+	struct device	dev;		/* net device structure */
+	struct enet_statistics estats;	/* more detailed stats */
+
+	/* tty output buffer */
+	unsigned char	obuf[OBUFSIZE];	/* buffer for characters to send */
+};
+
+#define PPP_MAGIC	0x5002
+#define PPP_VERSION	"2.3.11"
diff --git a/ap/app/ppp-2.4.1/include/linux/ppp-comp.h b/ap/app/ppp-2.4.1/include/linux/ppp-comp.h
new file mode 100644
index 0000000..da9dde8
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/linux/ppp-comp.h
@@ -0,0 +1,218 @@
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-comp.h,v 1.1 2008-08-04 06:11:50 winfred Exp $
+ */
+
+/*
+ *  ==FILEVERSION 990623==
+ *
+ *  NOTE TO MAINTAINERS:
+ *     If you modify this file at all, please set the above date.
+ *     ppp-comp.h is shipped with a PPP distribution as well as with the kernel;
+ *     if everyone increases the FILEVERSION number above, then scripts
+ *     can do the right thing when deciding whether to install a new ppp-comp.h
+ *     file.  Don't change the format of that line otherwise, so the
+ *     installation script can recognize it.
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS	1	/* by default, include BSD-Compress */
+#endif
+#ifndef DO_DEFLATE
+#define DO_DEFLATE	1	/* by default, include Deflate */
+#endif
+#define DO_PREDICTOR_1	0
+#define DO_PREDICTOR_2	0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+
+struct compressor {
+	int	compress_proto;	/* CCP compression protocol number */
+
+	/* Allocate space for a compressor (transmit side) */
+	void	*(*comp_alloc) (unsigned char *options, int opt_len);
+
+	/* Free space used by a compressor */
+	void	(*comp_free) (void *state);
+
+	/* Initialize a compressor */
+	int	(*comp_init) (void *state, unsigned char *options,
+			      int opt_len, int unit, int opthdr, int debug);
+
+	/* Reset a compressor */
+	void	(*comp_reset) (void *state);
+
+	/* Compress a packet */
+	int     (*compress) (void *state, unsigned char *rptr,
+			      unsigned char *obuf, int isize, int osize);
+
+	/* Return compression statistics */
+	void	(*comp_stat) (void *state, struct compstat *stats);
+
+	/* Allocate space for a decompressor (receive side) */
+	void	*(*decomp_alloc) (unsigned char *options, int opt_len);
+
+	/* Free space used by a decompressor */
+	void	(*decomp_free) (void *state);
+
+	/* Initialize a decompressor */
+	int	(*decomp_init) (void *state, unsigned char *options,
+				int opt_len, int unit, int opthdr, int mru,
+				int debug);
+
+	/* Reset a decompressor */
+	void	(*decomp_reset) (void *state);
+
+	/* Decompress a packet. */
+	int	(*decompress) (void *state, unsigned char *ibuf, int isize,
+				unsigned char *obuf, int osize);
+
+	/* Update state for an incompressible packet received */
+	void	(*incomp) (void *state, unsigned char *ibuf, int icnt);
+
+	/* Return decompression statistics */
+	void	(*decomp_stat) (void *state, struct compstat *stats);
+};
+
+/*
+ * The return value from decompress routine is the length of the
+ * decompressed packet if successful, otherwise DECOMP_ERROR
+ * or DECOMP_FATALERROR if an error occurred.
+ * 
+ * We need to make this distinction so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression.  This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+
+#define DECOMP_OK		0	/* no error occured */
+#define DECOMP_ERROR		-1	/* error detected before decomp. */
+#define DECOMP_FATALERROR	-2	/* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+
+#define CCP_CONFREQ	1
+#define CCP_CONFACK	2
+#define CCP_TERMREQ	5
+#define CCP_TERMACK	6
+#define CCP_RESETREQ	14
+#define CCP_RESETACK	15
+
+/*
+ * Max # bytes for a CCP option
+ */
+
+#define CCP_MAX_OPTION_LENGTH	64
+
+/*
+ * Parts of a CCP packet.
+ */
+
+#define CCP_CODE(dp)		((dp)[0])
+#define CCP_ID(dp)		((dp)[1])
+#define CCP_LENGTH(dp)		(((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN		4
+
+#define CCP_OPT_CODE(dp)	((dp)[0])
+#define CCP_OPT_LENGTH(dp)	((dp)[1])
+#define CCP_OPT_MINLEN		2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+
+#define CI_BSD_COMPRESS		21	/* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS	3	/* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x)		((x) & 0x1F)	/* number of bits requested */
+#define BSD_VERSION(x)		((x) >> 5)	/* version of option format */
+#define BSD_CURRENT_VERSION	1		/* current version number */
+#define BSD_MAKE_OPT(v, n)	(((v) << 5) | (n))
+
+#define BSD_MIN_BITS		9	/* smallest code size supported */
+#define BSD_MAX_BITS		15	/* largest code size supported */
+
+/*
+ * Definitions for Deflate.
+ */
+
+#define CI_DEFLATE		26	/* config option for Deflate */
+#define CI_DEFLATE_DRAFT	24	/* value used in original draft RFC */
+#define CILEN_DEFLATE		4	/* length of its config option */
+
+#define DEFLATE_MIN_SIZE	8
+#define DEFLATE_MAX_SIZE	15
+#define DEFLATE_METHOD_VAL	8
+#define DEFLATE_SIZE(x)		(((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x)	((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w)	((((w) - DEFLATE_MIN_SIZE) << 4) \
+				 + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE	0
+
+/*
+ * Definitions for MPPE.
+ */
+
+#define CI_MPPE			18	/* config. option for MPPE */
+#define CILEN_MPPE		6	/* length of config. option */
+
+/*
+ * Definitions for Stac LZS.
+ */
+
+#define CI_LZS			17	/* config option for Stac LZS */
+#define CILEN_LZS		5	/* length of config option */
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+
+#define CI_PREDICTOR_1		1	/* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1	2	/* length of its config option */
+#define CI_PREDICTOR_2		2	/* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2	2	/* length of its config option */
+
+#ifdef __KERNEL__
+extern int ppp_register_compressor(struct compressor *);
+extern void ppp_unregister_compressor(struct compressor *);
+#endif /* __KERNEL__ */
+
+#endif /* _NET_PPP_COMP_H */
diff --git a/ap/app/ppp-2.4.1/include/linux/ppp_defs.h b/ap/app/ppp-2.4.1/include/linux/ppp_defs.h
new file mode 100644
index 0000000..19831c7
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/linux/ppp_defs.h
@@ -0,0 +1,185 @@
+/*	$Id: ppp_defs.h,v 1.1 2008-08-04 06:11:50 winfred Exp $	*/
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+/*
+ *  ==FILEVERSION 20000114==
+ *
+ *  NOTE TO MAINTAINERS:
+ *     If you modify this file at all, please set the above date.
+ *     ppp_defs.h is shipped with a PPP distribution as well as with the kernel;
+ *     if everyone increases the FILEVERSION number above, then scripts
+ *     can do the right thing when deciding whether to install a new ppp_defs.h
+ *     file.  Don't change the format of that line otherwise, so the
+ *     installation script can recognize it.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN	4	/* octets for standard ppp header */
+#define PPP_FCSLEN	2	/* octets for FCS */
+#define PPP_MRU		1500	/* default MRU = max length of info field */
+
+#define PPP_ADDRESS(p)	(((__u8 *)(p))[0])
+#define PPP_CONTROL(p)	(((__u8 *)(p))[1])
+#define PPP_PROTOCOL(p)	((((__u8 *)(p))[2] << 8) + ((__u8 *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define	PPP_ALLSTATIONS	0xff	/* All-Stations broadcast address */
+#define	PPP_UI		0x03	/* Unnumbered Information */
+#define	PPP_FLAG	0x7e	/* Flag Sequence */
+#define	PPP_ESCAPE	0x7d	/* Asynchronous Control Escape */
+#define	PPP_TRANS	0x20	/* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP		0x21	/* Internet Protocol */
+#define PPP_AT		0x29	/* AppleTalk Protocol */
+#define PPP_IPX		0x2b	/* IPX protocol */
+#define	PPP_VJC_COMP	0x2d	/* VJ compressed TCP */
+#define	PPP_VJC_UNCOMP	0x2f	/* VJ uncompressed TCP */
+#define PPP_MP		0x3d	/* Multilink protocol */
+#define PPP_IPV6	0x57	/* Internet Protocol Version 6 */
+#define PPP_COMPFRAG	0xfb	/* fragment compressed below bundle */
+#define PPP_COMP	0xfd	/* compressed packet */
+#define PPP_IPCP	0x8021	/* IP Control Protocol */
+#define PPP_ATCP	0x8029	/* AppleTalk Control Protocol */
+#define PPP_IPXCP	0x802b	/* IPX Control Protocol */
+#define PPP_IPV6CP	0x8057	/* IPv6 Control Protocol */
+#define PPP_CCPFRAG	0x80fb	/* CCP at link level (below MP bundle) */
+#define PPP_CCP		0x80fd	/* Compression Control Protocol */
+#define PPP_LCP		0xc021	/* Link Control Protocol */
+#define PPP_PAP		0xc023	/* Password Authentication Protocol */
+#define PPP_LQR		0xc025	/* Link Quality Report protocol */
+#define PPP_CHAP	0xc223	/* Cryptographic Handshake Auth. Protocol */
+#define PPP_CBCP	0xc029	/* Callback Control Protocol */
+
+/*
+ * Values for FCS calculations.
+ */
+
+#define PPP_INITFCS	0xffff	/* Initial FCS value */
+#define PPP_GOODFCS	0xf0b8	/* Good final FCS value */
+#define PPP_FCS(fcs, c)	(((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+
+typedef __u32		ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+    NPMODE_PASS,		/* pass the packet through */
+    NPMODE_DROP,		/* silently drop the packet */
+    NPMODE_ERROR,		/* return an error */
+    NPMODE_QUEUE		/* save it up for later. */
+};
+
+/*
+ * Statistics for LQRP and pppstats
+ */
+struct pppstat	{
+    __u32	ppp_discards;	/* # frames discarded */
+
+    __u32	ppp_ibytes;	/* bytes received */
+    __u32	ppp_ioctects;	/* bytes received not in error */
+    __u32	ppp_ipackets;	/* packets received */
+    __u32	ppp_ierrors;	/* receive errors */
+    __u32	ppp_ilqrs;	/* # LQR frames received */
+
+    __u32	ppp_obytes;	/* raw bytes sent */
+    __u32	ppp_ooctects;	/* frame bytes sent */
+    __u32	ppp_opackets;	/* packets sent */
+    __u32	ppp_oerrors;	/* transmit errors */ 
+    __u32	ppp_olqrs;	/* # LQR frames sent */
+};
+
+struct vjstat {
+    __u32	vjs_packets;	/* outbound packets */
+    __u32	vjs_compressed;	/* outbound compressed packets */
+    __u32	vjs_searches;	/* searches for connection state */
+    __u32	vjs_misses;	/* times couldn't find conn. state */
+    __u32	vjs_uncompressedin; /* inbound uncompressed packets */
+    __u32	vjs_compressedin;   /* inbound compressed packets */
+    __u32	vjs_errorin;	/* inbound unknown type packets */
+    __u32	vjs_tossed;	/* inbound packets tossed because of error */
+};
+
+struct compstat {
+    __u32	unc_bytes;	/* total uncompressed bytes */
+    __u32	unc_packets;	/* total uncompressed packets */
+    __u32	comp_bytes;	/* compressed bytes */
+    __u32	comp_packets;	/* compressed packets */
+    __u32	inc_bytes;	/* incompressible bytes */
+    __u32	inc_packets;	/* incompressible packets */
+
+    /* the compression ratio is defined as in_count / bytes_out */
+    __u32       in_count;	/* Bytes received */
+    __u32       bytes_out;	/* Bytes transmitted */
+
+    double	ratio;		/* not computed in kernel. */
+};
+
+struct ppp_stats {
+    struct pppstat	p;	/* basic PPP statistics */
+    struct vjstat	vj;	/* VJ header compression statistics */
+};
+
+struct ppp_comp_stats {
+    struct compstat	c;	/* packet compression statistics */
+    struct compstat	d;	/* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+    time_t xmit_idle;		/* time since last NP packet sent */
+    time_t recv_idle;		/* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x)	x
+#else
+#define __P(x)	()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
diff --git a/ap/app/ppp-2.4.1/include/net/if_ppp.h b/ap/app/ppp-2.4.1/include/net/if_ppp.h
new file mode 100644
index 0000000..8cf212a
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/if_ppp.h
@@ -0,0 +1,133 @@
+/*	$Id: if_ppp.h,v 1.1 2008-08-04 06:11:50 winfred Exp $	*/
+
+/*
+ * if_ppp.h - Point-to-Point Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _IF_PPP_H_
+#define _IF_PPP_H_
+
+/*
+ * Bit definitions for flags.
+ */
+#define SC_COMP_PROT	0x00000001	/* protocol compression (output) */
+#define SC_COMP_AC	0x00000002	/* header compression (output) */
+#define	SC_COMP_TCP	0x00000004	/* TCP (VJ) compression (output) */
+#define SC_NO_TCP_CCID	0x00000008	/* disable VJ connection-id comp. */
+#define SC_REJ_COMP_AC	0x00000010	/* reject adrs/ctrl comp. on input */
+#define SC_REJ_COMP_TCP	0x00000020	/* reject TCP (VJ) comp. on input */
+#define SC_CCP_OPEN	0x00000040	/* Look at CCP packets */
+#define SC_CCP_UP	0x00000080	/* May send/recv compressed packets */
+#define SC_DEBUG	0x00010000	/* enable debug messages */
+#define SC_LOG_INPKT	0x00020000	/* log contents of good pkts recvd */
+#define SC_LOG_OUTPKT	0x00040000	/* log contents of pkts sent */
+#define SC_LOG_RAWIN	0x00080000	/* log all chars received */
+#define SC_LOG_FLUSH	0x00100000	/* log all chars flushed */
+#define SC_RCV_B7_0	0x01000000	/* have rcvd char with bit 7 = 0 */
+#define SC_RCV_B7_1	0x02000000	/* have rcvd char with bit 7 = 1 */
+#define SC_RCV_EVNP	0x04000000	/* have rcvd char with even parity */
+#define SC_RCV_ODDP	0x08000000	/* have rcvd char with odd parity */
+#define SC_SYNC		0x00200000	/* use synchronous HDLC framing */
+#define	SC_MASK		0x0fff00ff	/* bits that user can change */
+
+/*
+ * State bits in sc_flags, not changeable by user.
+ */
+#define SC_TIMEOUT	0x00000400	/* timeout is currently pending */
+#define SC_VJ_RESET	0x00000800	/* need to reset VJ decomp */
+#define SC_COMP_RUN	0x00001000	/* compressor has been inited */
+#define SC_DECOMP_RUN	0x00002000	/* decompressor has been inited */
+#define SC_DC_ERROR	0x00004000	/* non-fatal decomp error detected */
+#define SC_DC_FERROR	0x00008000	/* fatal decomp error detected */
+#define SC_TBUSY	0x10000000	/* xmitter doesn't need a packet yet */
+#define SC_PKTLOST	0x20000000	/* have lost or dropped a packet */
+#define	SC_FLUSH	0x40000000	/* flush input until next PPP_FLAG */
+#define	SC_ESCAPED	0x80000000	/* saw a PPP_ESCAPE */
+
+/*
+ * Ioctl definitions.
+ */
+
+struct npioctl {
+    int		protocol;	/* PPP procotol, e.g. PPP_IP */
+    enum NPmode	mode;
+};
+
+/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
+struct ppp_option_data {
+	u_char	*ptr;
+	u_int	length;
+	int	transmit;
+};
+
+struct ifpppstatsreq {
+    char ifr_name[IFNAMSIZ];
+    struct ppp_stats stats;
+};
+
+struct ifpppcstatsreq {
+    char ifr_name[IFNAMSIZ];
+    struct ppp_comp_stats stats;
+};
+
+/*
+ * Ioctl definitions.
+ */
+
+#define	PPPIOCGFLAGS	_IOR('t', 90, int)	/* get configuration flags */
+#define	PPPIOCSFLAGS	_IOW('t', 89, int)	/* set configuration flags */
+#define	PPPIOCGASYNCMAP	_IOR('t', 88, int)	/* get async map */
+#define	PPPIOCSASYNCMAP	_IOW('t', 87, int)	/* set async map */
+#define	PPPIOCGUNIT	_IOR('t', 86, int)	/* get ppp unit number */
+#define	PPPIOCGRASYNCMAP _IOR('t', 85, int)	/* get receive async map */
+#define	PPPIOCSRASYNCMAP _IOW('t', 84, int)	/* set receive async map */
+#define	PPPIOCGMRU	_IOR('t', 83, int)	/* get max receive unit */
+#define	PPPIOCSMRU	_IOW('t', 82, int)	/* set max receive unit */
+#define	PPPIOCSMAXCID	_IOW('t', 81, int)	/* set VJ max slot ID */
+#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
+#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
+#define PPPIOCXFERUNIT	_IO('t', 78)		/* transfer PPP unit */
+#define PPPIOCSCOMPRESS	_IOW('t', 77, struct ppp_option_data)
+#define PPPIOCGNPMODE	_IOWR('t', 76, struct npioctl) /* get NP mode */
+#define PPPIOCSNPMODE	_IOW('t', 75, struct npioctl)  /* set NP mode */
+#define PPPIOCGIDLE	_IOR('t', 74, struct ppp_idle) /* get idle time */
+#ifdef PPP_FILTER
+#define PPPIOCSPASS	_IOW('t', 71, struct bpf_program) /* set pass filter */
+#define PPPIOCSACTIVE	_IOW('t', 70, struct bpf_program) /* set active filt */
+#endif /* PPP_FILTER */
+
+/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */
+#define PPPIOCGMTU	_IOR('t', 73, int)	/* get interface MTU */
+#define PPPIOCSMTU	_IOW('t', 72, int)	/* set interface MTU */
+
+/*
+ * These two are interface ioctls so that pppstats can do them on
+ * a socket without having to open the serial device.
+ */
+#define SIOCGPPPSTATS	_IOWR('i', 123, struct ifpppstatsreq)
+#define SIOCGPPPCSTATS	_IOWR('i', 122, struct ifpppcstatsreq)
+
+#if !defined(ifr_mtu)
+#define ifr_mtu	ifr_ifru.ifru_metric
+#endif
+
+#if (defined(_KERNEL) || defined(KERNEL)) && !defined(NeXT)
+void pppattach __P((void));
+void pppintr __P((void));
+#endif
+#endif /* _IF_PPP_H_ */
diff --git a/ap/app/ppp-2.4.1/include/net/ppp-comp.h b/ap/app/ppp-2.4.1/include/net/ppp-comp.h
new file mode 100644
index 0000000..4bc3c98
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/ppp-comp.h
@@ -0,0 +1,179 @@
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-comp.h,v 1.1 2008-08-04 06:11:50 winfred Exp $
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS	1	/* by default, include BSD-Compress */
+#endif
+#ifndef DO_DEFLATE
+#define DO_DEFLATE	1	/* by default, include Deflate */
+#endif
+#define DO_PREDICTOR_1	0
+#define DO_PREDICTOR_2	0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+#ifdef PACKETPTR
+struct compressor {
+	int	compress_proto;	/* CCP compression protocol number */
+
+	/* Allocate space for a compressor (transmit side) */
+	void	*(*comp_alloc) __P((u_char *options, int opt_len));
+	/* Free space used by a compressor */
+	void	(*comp_free) __P((void *state));
+	/* Initialize a compressor */
+	int	(*comp_init) __P((void *state, u_char *options, int opt_len,
+				  int unit, int hdrlen, int debug));
+	/* Reset a compressor */
+	void	(*comp_reset) __P((void *state));
+	/* Compress a packet */
+	int	(*compress) __P((void *state, PACKETPTR *mret,
+				 PACKETPTR mp, int orig_len, int max_len));
+	/* Return compression statistics */
+	void	(*comp_stat) __P((void *state, struct compstat *stats));
+
+	/* Allocate space for a decompressor (receive side) */
+	void	*(*decomp_alloc) __P((u_char *options, int opt_len));
+	/* Free space used by a decompressor */
+	void	(*decomp_free) __P((void *state));
+	/* Initialize a decompressor */
+	int	(*decomp_init) __P((void *state, u_char *options, int opt_len,
+				    int unit, int hdrlen, int mru, int debug));
+	/* Reset a decompressor */
+	void	(*decomp_reset) __P((void *state));
+	/* Decompress a packet. */
+	int	(*decompress) __P((void *state, PACKETPTR mp,
+				   PACKETPTR *dmpp));
+	/* Update state for an incompressible packet received */
+	void	(*incomp) __P((void *state, PACKETPTR mp));
+	/* Return decompression statistics */
+	void	(*decomp_stat) __P((void *state, struct compstat *stats));
+};
+#endif /* PACKETPTR */
+
+/*
+ * Return values for decompress routine.
+ * We need to make these distinctions so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression.  This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+#define DECOMP_OK		0	/* everything went OK */
+#define DECOMP_ERROR		1	/* error detected before decomp. */
+#define DECOMP_FATALERROR	2	/* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+#define CCP_CONFREQ	1
+#define CCP_CONFACK	2
+#define CCP_TERMREQ	5
+#define CCP_TERMACK	6
+#define CCP_RESETREQ	14
+#define CCP_RESETACK	15
+
+/*
+ * Max # bytes for a CCP option
+ */
+#define CCP_MAX_OPTION_LENGTH	64
+
+/*
+ * Parts of a CCP packet.
+ */
+#define CCP_CODE(dp)		((dp)[0])
+#define CCP_ID(dp)		((dp)[1])
+#define CCP_LENGTH(dp)		(((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN		4
+
+#define CCP_OPT_CODE(dp)	((dp)[0])
+#define CCP_OPT_LENGTH(dp)	((dp)[1])
+#define CCP_OPT_MINLEN		2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+#define CI_BSD_COMPRESS		21	/* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS	3	/* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x)		((x) & 0x1F)	/* number of bits requested */
+#define BSD_VERSION(x)		((x) >> 5)	/* version of option format */
+#define BSD_CURRENT_VERSION	1		/* current version number */
+#define BSD_MAKE_OPT(v, n)	(((v) << 5) | (n))
+
+#define BSD_MIN_BITS		9	/* smallest code size supported */
+#define BSD_MAX_BITS		15	/* largest code size supported */
+
+/*
+ * Definitions for Deflate.
+ */
+#define CI_DEFLATE		26	/* config option for Deflate */
+#define CI_DEFLATE_DRAFT	24	/* value used in original draft RFC */
+#define CILEN_DEFLATE		4	/* length of its config option */
+
+#define DEFLATE_MIN_SIZE	8
+#define DEFLATE_MAX_SIZE	15
+#define DEFLATE_METHOD_VAL	8
+#define DEFLATE_SIZE(x)		(((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x)	((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w)	((((w) - DEFLATE_MIN_SIZE) << 4) \
+				 + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE	0
+
+/*
+ * Definitions for MPPE.
+ */
+
+#define CI_MPPE			18	/* config. option for MPPE */
+#define CILEN_MPPE		6	/* length of config. option */
+
+/*
+ * Definitions for Stac LZS.
+ */
+
+#define CI_LZS			17	/* config option for Stac LZS */
+#define CILEN_LZS		5	/* length of config option */
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+#define CI_PREDICTOR_1		1	/* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1	2	/* length of its config option */
+#define CI_PREDICTOR_2		2	/* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2	2	/* length of its config option */
+
+#endif /* _NET_PPP_COMP_H */
diff --git a/ap/app/ppp-2.4.1/include/net/ppp_defs.h b/ap/app/ppp-2.4.1/include/net/ppp_defs.h
new file mode 100644
index 0000000..03d76e3
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/ppp_defs.h
@@ -0,0 +1,176 @@
+/*	$Id: ppp_defs.h,v 1.1 2008-08-04 06:11:50 winfred Exp $	*/
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN	4	/* octets for standard ppp header */
+#define PPP_FCSLEN	2	/* octets for FCS */
+
+#define	PPP_MTU		1500	/* Default MTU (size of Info field) */
+#define PPP_MAXMTU	65535 - (PPP_HDRLEN + PPP_FCSLEN)
+#define PPP_MINMTU	64
+#define PPP_MRU		1500	/* default MRU = max length of info field */
+#define PPP_MAXMRU	65000	/* Largest MRU we allow */
+#define PPP_MINMRU	128
+
+#define PPP_ADDRESS(p)	(((u_char *)(p))[0])
+#define PPP_CONTROL(p)	(((u_char *)(p))[1])
+#define PPP_PROTOCOL(p)	((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define	PPP_ALLSTATIONS	0xff	/* All-Stations broadcast address */
+#define	PPP_UI		0x03	/* Unnumbered Information */
+#define	PPP_FLAG	0x7e	/* Flag Sequence */
+#define	PPP_ESCAPE	0x7d	/* Asynchronous Control Escape */
+#define	PPP_TRANS	0x20	/* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP		0x21	/* Internet Protocol */
+#define PPP_AT		0x29	/* AppleTalk Protocol */
+#define PPP_IPX		0x2b	/* IPX protocol */
+#define	PPP_VJC_COMP	0x2d	/* VJ compressed TCP */
+#define	PPP_VJC_UNCOMP	0x2f	/* VJ uncompressed TCP */
+#define PPP_IPV6	0x57	/* Internet Protocol Version 6 */
+#define PPP_COMP	0xfd	/* compressed packet */
+#define PPP_IPCP	0x8021	/* IP Control Protocol */
+#define PPP_ATCP	0x8029	/* AppleTalk Control Protocol */
+#define PPP_IPXCP	0x802b	/* IPX Control Protocol */
+#define PPP_IPV6CP	0x8057	/* IPv6 Control Protocol */
+#define PPP_CCP		0x80fd	/* Compression Control Protocol */
+#define PPP_LCP		0xc021	/* Link Control Protocol */
+#define PPP_PAP		0xc023	/* Password Authentication Protocol */
+#define PPP_LQR		0xc025	/* Link Quality Report protocol */
+#define PPP_CHAP	0xc223	/* Cryptographic Handshake Auth. Protocol */
+#define PPP_CBCP	0xc029	/* Callback Control Protocol */
+
+/*
+ * Values for FCS calculations.
+ */
+#define PPP_INITFCS	0xffff	/* Initial FCS value */
+#define PPP_GOODFCS	0xf0b8	/* Good final FCS value */
+#define PPP_FCS(fcs, c)	(((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+
+/*
+ * A 32-bit unsigned integral type.
+ */
+
+#if !defined(__BIT_TYPES_DEFINED__) && !defined(_BITYPES) \
+ && !defined(__FreeBSD__) && (NS_TARGET < 40)
+#ifdef	UINT32_T
+typedef UINT32_T	u_int32_t;
+#else
+typedef unsigned int	u_int32_t;
+typedef unsigned short  u_int16_t;
+#endif
+#endif
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+typedef u_int32_t	ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+    NPMODE_PASS,		/* pass the packet through */
+    NPMODE_DROP,		/* silently drop the packet */
+    NPMODE_ERROR,		/* return an error */
+    NPMODE_QUEUE		/* save it up for later. */
+};
+
+/*
+ * Statistics.
+ */
+struct pppstat	{
+    unsigned int ppp_ibytes;	/* bytes received */
+    unsigned int ppp_ipackets;	/* packets received */
+    unsigned int ppp_ierrors;	/* receive errors */
+    unsigned int ppp_obytes;	/* bytes sent */
+    unsigned int ppp_opackets;	/* packets sent */
+    unsigned int ppp_oerrors;	/* transmit errors */
+};
+
+struct vjstat {
+    unsigned int vjs_packets;	/* outbound packets */
+    unsigned int vjs_compressed; /* outbound compressed packets */
+    unsigned int vjs_searches;	/* searches for connection state */
+    unsigned int vjs_misses;	/* times couldn't find conn. state */
+    unsigned int vjs_uncompressedin; /* inbound uncompressed packets */
+    unsigned int vjs_compressedin; /* inbound compressed packets */
+    unsigned int vjs_errorin;	/* inbound unknown type packets */
+    unsigned int vjs_tossed;	/* inbound packets tossed because of error */
+};
+
+struct ppp_stats {
+    struct pppstat p;		/* basic PPP statistics */
+    struct vjstat vj;		/* VJ header compression statistics */
+};
+
+struct compstat {
+    unsigned int unc_bytes;	/* total uncompressed bytes */
+    unsigned int unc_packets;	/* total uncompressed packets */
+    unsigned int comp_bytes;	/* compressed bytes */
+    unsigned int comp_packets;	/* compressed packets */
+    unsigned int inc_bytes;	/* incompressible bytes */
+    unsigned int inc_packets;	/* incompressible packets */
+    unsigned int ratio;		/* recent compression ratio << 8 */
+};
+
+struct ppp_comp_stats {
+    struct compstat c;		/* packet compression statistics */
+    struct compstat d;		/* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+    time_t xmit_idle;		/* time since last NP packet sent */
+    time_t recv_idle;		/* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x)	x
+#else
+#define __P(x)	()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
diff --git a/ap/app/ppp-2.4.1/include/net/pppio.h b/ap/app/ppp-2.4.1/include/net/pppio.h
new file mode 100644
index 0000000..4739df6
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/pppio.h
@@ -0,0 +1,99 @@
+/*
+ * pppio.h - ioctl and other misc. definitions for STREAMS modules.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: pppio.h,v 1.1 2008-08-04 06:11:50 winfred Exp $
+ */
+
+#define _PPPIO(n)	(('p' << 8) + (n))
+
+#define PPPIO_NEWPPA	_PPPIO(130)	/* allocate a new PPP unit */
+#define PPPIO_GETSTAT	_PPPIO(131)	/* get PPP statistics */
+#define PPPIO_GETCSTAT	_PPPIO(132)	/* get PPP compression stats */
+#define PPPIO_MTU	_PPPIO(133)	/* set max transmission unit */
+#define PPPIO_MRU	_PPPIO(134)	/* set max receive unit */
+#define PPPIO_CFLAGS	_PPPIO(135)	/* set/clear/get compression flags */
+#define PPPIO_XCOMP	_PPPIO(136)	/* alloc transmit compressor */
+#define PPPIO_RCOMP	_PPPIO(137)	/* alloc receive decompressor */
+#define PPPIO_XACCM	_PPPIO(138)	/* set transmit asyncmap */
+#define PPPIO_RACCM	_PPPIO(139)	/* set receive asyncmap */
+#define PPPIO_VJINIT	_PPPIO(140)	/* initialize VJ comp/decomp */
+#define PPPIO_ATTACH	_PPPIO(141)	/* attach to a ppa (without putmsg) */
+#define PPPIO_LASTMOD	_PPPIO(142)	/* mark last ppp module */
+#define PPPIO_GCLEAN	_PPPIO(143)	/* get 8-bit-clean flags */
+#define PPPIO_DEBUG	_PPPIO(144)	/* request debug information */
+#define PPPIO_BIND	_PPPIO(145)	/* bind to SAP */
+#define PPPIO_NPMODE	_PPPIO(146)	/* set mode for handling data pkts */
+#define PPPIO_GIDLE	_PPPIO(147)	/* get time since last data pkt */
+#define PPPIO_PASSFILT	_PPPIO(148)	/* set filter for packets to pass */
+#define PPPIO_ACTIVEFILT _PPPIO(149)	/* set filter for "link active" pkts */
+
+/*
+ * Values for PPPIO_CFLAGS
+ */
+#define COMP_AC		0x1		/* compress address/control */
+#define DECOMP_AC	0x2		/* decompress address/control */
+#define COMP_PROT	0x4		/* compress PPP protocol */
+#define DECOMP_PROT	0x8		/* decompress PPP protocol */
+
+#define COMP_VJC	0x10		/* compress TCP/IP headers */
+#define COMP_VJCCID	0x20		/* compress connection ID as well */
+#define DECOMP_VJC	0x40		/* decompress TCP/IP headers */
+#define DECOMP_VJCCID	0x80		/* accept compressed connection ID */
+
+#define CCP_ISOPEN	0x100		/* look at CCP packets */
+#define CCP_ISUP	0x200		/* do packet comp/decomp */
+#define CCP_ERROR	0x400		/* (status) error in packet decomp */
+#define CCP_FATALERROR	0x800		/* (status) fatal error ditto */
+#define CCP_COMP_RUN	0x1000		/* (status) seen CCP ack sent */
+#define CCP_DECOMP_RUN	0x2000		/* (status) seen CCP ack rcvd */
+
+/*
+ * Values for 8-bit-clean flags.
+ */
+#define RCV_B7_0	1		/* have rcvd char with bit 7 = 0 */
+#define RCV_B7_1	2		/* have rcvd char with bit 7 = 1 */
+#define RCV_EVNP	4		/* have rcvd char with even parity */
+#define RCV_ODDP	8		/* have rcvd char with odd parity */
+
+/*
+ * Values for the first byte of M_CTL messages passed between
+ * PPP modules.
+ */
+#define PPPCTL_OERROR	0xe0		/* output error [up] */
+#define PPPCTL_IERROR	0xe1		/* input error (e.g. FCS) [up] */
+#define PPPCTL_MTU	0xe2		/* set MTU [down] */
+#define PPPCTL_MRU	0xe3		/* set MRU [down] */
+#define PPPCTL_UNIT	0xe4		/* note PPP unit number [down] */
+
+/*
+ * Values for the integer argument to PPPIO_DEBUG.
+ */
+#define PPPDBG_DUMP	0x10000		/* print out debug info now */
+#define PPPDBG_LOG	0x100		/* log various things */
+#define PPPDBG_DRIVER	0		/* identifies ppp driver as target */
+#define PPPDBG_IF	1		/* identifies ppp network i/f target */
+#define PPPDBG_COMP	2		/* identifies ppp compression target */
+#define PPPDBG_AHDLC	3		/* identifies ppp async hdlc target */
diff --git a/ap/app/ppp-2.4.1/include/net/slcompress.h b/ap/app/ppp-2.4.1/include/net/slcompress.h
new file mode 100644
index 0000000..6a0ba89
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/slcompress.h
@@ -0,0 +1,148 @@
+/*
+ * Definitions for tcp compression routines.
+ *
+ * $Id: slcompress.h,v 1.1 2008-08-04 06:11:50 winfred Exp $
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ *	- Initial distribution.
+ */
+
+#ifndef _SLCOMPRESS_H_
+#define _SLCOMPRESS_H_
+
+#define MAX_STATES 16		/* must be > 2 and < 256 */
+#define MAX_HDR MLEN		
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits).  The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet.  The next two octets are the TCP checksum
+ * from the original datagram.  The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ * 
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowlegement, sequence number and IP ID.  (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.)  Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0.  (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type.  There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows.  Top
+ * three bits are actual packet type.  For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+/* packet types */
+#define TYPE_IP 0x40
+#define TYPE_UNCOMPRESSED_TCP 0x70
+#define TYPE_COMPRESSED_TCP 0x80
+#define TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C	0x40	/* flag bits for what changed in a packet */
+#define NEW_I	0x20
+#define NEW_S	0x08
+#define NEW_A	0x04
+#define NEW_W	0x02
+#define NEW_U	0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U)		/* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U)	/* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+
+/*
+ * "state" data for each active tcp conversation on the wire.  This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+	struct cstate *cs_next;	/* next most recently used cstate (xmit only) */
+	u_short cs_hlen;	/* size of hdr (receive only) */
+	u_char cs_id;		/* connection # associated with this state */
+	u_char cs_filler;
+	union {
+		char csu_hdr[MAX_HDR];
+		struct ip csu_ip;	/* ip/tcp hdr from most recent packet */
+	} slcs_u;
+};
+#define cs_ip slcs_u.csu_ip
+#define cs_hdr slcs_u.csu_hdr
+
+/*
+ * all the state data for one serial line (we need one of these
+ * per line).
+ */
+struct slcompress {
+	struct cstate *last_cs;	/* most recently used tstate */
+	u_char last_recv;	/* last rcvd conn. id */
+	u_char last_xmit;	/* last sent conn. id */
+	u_short flags;
+#ifndef SL_NO_STATS
+	int sls_packets;	/* outbound packets */
+	int sls_compressed;	/* outbound compressed packets */
+	int sls_searches;	/* searches for connection state */
+	int sls_misses;		/* times couldn't find conn. state */
+	int sls_uncompressedin;	/* inbound uncompressed packets */
+	int sls_compressedin;	/* inbound compressed packets */
+	int sls_errorin;	/* inbound unknown type packets */
+	int sls_tossed;		/* inbound packets tossed because of error */
+#endif
+	struct cstate tstate[MAX_STATES];	/* xmit connection states */
+	struct cstate rstate[MAX_STATES];	/* receive connection states */
+};
+/* flag values */
+#define SLF_TOSS 1		/* tossing rcvd frames because of input err */
+
+void	sl_compress_init __P((struct slcompress *));
+void	sl_compress_setup __P((struct slcompress *, int));
+u_int	sl_compress_tcp __P((struct mbuf *,
+	    struct ip *, struct slcompress *, int));
+int	sl_uncompress_tcp __P((u_char **, int, u_int, struct slcompress *));
+int	sl_uncompress_tcp_core __P((u_char *, int, int, u_int,
+	    struct slcompress *, u_char **, u_int *));
+
+#endif /* _SLCOMPRESS_H_ */
diff --git a/ap/app/ppp-2.4.1/include/net/vjcompress.h b/ap/app/ppp-2.4.1/include/net/vjcompress.h
new file mode 100644
index 0000000..f5250f6
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/net/vjcompress.h
@@ -0,0 +1,144 @@
+/*
+ * Definitions for tcp compression routines.
+ *
+ * $Id: vjcompress.h,v 1.1 2008-08-04 06:11:50 winfred Exp $
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ *	- Initial distribution.
+ */
+
+#ifndef _VJCOMPRESS_H_
+#define _VJCOMPRESS_H_
+
+#define MAX_STATES 16		/* must be > 2 and < 256 */
+#define MAX_HDR	   128
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits).  The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet.  The next two octets are the TCP checksum
+ * from the original datagram.  The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ * 
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowlegement, sequence number and IP ID.  (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.)  Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0.  (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type.  There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows.  Top
+ * three bits are actual packet type.  For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+/* packet types */
+#define TYPE_IP 0x40
+#define TYPE_UNCOMPRESSED_TCP 0x70
+#define TYPE_COMPRESSED_TCP 0x80
+#define TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C	0x40	/* flag bits for what changed in a packet */
+#define NEW_I	0x20
+#define NEW_S	0x08
+#define NEW_A	0x04
+#define NEW_W	0x02
+#define NEW_U	0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U)		/* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U)	/* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+
+/*
+ * "state" data for each active tcp conversation on the wire.  This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+    struct cstate *cs_next;	/* next most recently used state (xmit only) */
+    u_short cs_hlen;		/* size of hdr (receive only) */
+    u_char cs_id;		/* connection # associated with this state */
+    u_char cs_filler;
+    union {
+	char csu_hdr[MAX_HDR];
+	struct ip csu_ip;	/* ip/tcp hdr from most recent packet */
+    } vjcs_u;
+};
+#define cs_ip vjcs_u.csu_ip
+#define cs_hdr vjcs_u.csu_hdr
+
+/*
+ * all the state data for one serial line (we need one of these per line).
+ */
+struct vjcompress {
+    struct cstate *last_cs;	/* most recently used tstate */
+    u_char last_recv;		/* last rcvd conn. id */
+    u_char last_xmit;		/* last sent conn. id */
+    u_short flags;
+#ifndef VJ_NO_STATS
+    struct vjstat stats;
+#endif
+    struct cstate tstate[MAX_STATES];	/* xmit connection states */
+    struct cstate rstate[MAX_STATES];	/* receive connection states */
+};
+
+/* flag values */
+#define VJF_TOSS 1		/* tossing rcvd frames because of input err */
+
+extern void  vj_compress_init __P((struct vjcompress *comp, int max_state));
+extern u_int vj_compress_tcp __P((struct ip *ip, u_int mlen,
+				struct vjcompress *comp, int compress_cid_flag,
+				u_char **vjhdrp));
+extern void  vj_uncompress_err __P((struct vjcompress *comp));
+extern int   vj_uncompress_uncomp __P((u_char *buf, int buflen,
+				struct vjcompress *comp));
+extern int   vj_uncompress_tcp __P((u_char *buf, int buflen, int total_len,
+				struct vjcompress *comp, u_char **hdrp,
+				u_int *hlenp));
+
+#endif /* _VJCOMPRESS_H_ */
diff --git a/ap/app/ppp-2.4.1/include/openssl/opensslconf.h b/ap/app/ppp-2.4.1/include/openssl/opensslconf.h
new file mode 100644
index 0000000..2c6ddae
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/openssl/opensslconf.h
@@ -0,0 +1,167 @@
+/* opensslconf.h */
+/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+
+/* OpenSSL was configured with the following options: */
+#ifdef OPENSSL_ALGORITHM_DEFINES
+   /* no ciphers excluded */
+#endif
+#ifdef OPENSSL_THREAD_DEFINES
+#endif
+#ifdef OPENSSL_OTHER_DEFINES
+#endif
+
+/* crypto/opensslconf.h.in */
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */
+#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
+#define OPENSSLDIR "/usr/local/ssl"
+#endif
+#endif
+
+#define OPENSSL_UNISTD <unistd.h>
+
+#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)
+#define IDEA_INT unsigned int
+#endif
+
+#if defined(HEADER_MD2_H) && !defined(MD2_INT)
+#define MD2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC2_H) && !defined(RC2_INT)
+/* I need to put in a mod for the alpha - eay */
+#define RC2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC4_H)
+#if !defined(RC4_INT)
+/* using int types make the structure larger but make the code faster
+ * on most boxes I have tested - up to %20 faster. */
+/*
+ * I don't know what does "most" mean, but declaring "int" is a must on:
+ * - Intel P6 because partial register stalls are very expensive;
+ * - elder Alpha because it lacks byte load/store instructions;
+ */
+#define RC4_INT unsigned int
+#endif
+#if !defined(RC4_CHUNK)
+/*
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+#undef RC4_CHUNK
+#endif
+#endif
+
+#if defined(HEADER_DES_H) && !defined(DES_LONG)
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+#define DES_LONG unsigned long
+#endif
+#endif
+
+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
+#define CONFIG_HEADER_BN_H
+#undef BN_LLONG
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+/* The prime number generation stuff may not work when
+ * EIGHT_BIT but I don't care since I've only used this mode
+ * for debuging the bignum libraries */
+#undef SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#define THIRTY_TWO_BIT
+#undef SIXTEEN_BIT
+#undef EIGHT_BIT
+#endif
+
+#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+#define CONFIG_HEADER_RC4_LOCL_H
+/* if this is defined data[i] is used instead of *data, this is a %20
+ * speedup on x86 */
+#undef RC4_INDEX
+#endif
+
+#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+#define CONFIG_HEADER_BF_LOCL_H
+#undef BF_PTR
+#endif /* HEADER_BF_LOCL_H */
+
+#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+#define CONFIG_HEADER_DES_LOCL_H
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#undef DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units.  It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#undef DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#undef DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman <pgut001@cs.auckland.ac.nz>
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+   even newer MIPS CPU's, but at the moment one size fits all for
+   optimization options.  Older Sparc's work better with only UNROLL, but
+   there's no way to tell at compile time what it is you're running on */
+ 
+#if defined( sun )		/* Newer Sparc's */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#elif defined( __ultrix )	/* Older MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined( __osf1__ )	/* Alpha */
+#  define DES_PTR
+#  define DES_RISC2
+#elif defined ( _AIX )		/* RS6000 */
+  /* Unknown */
+#elif defined( __hpux )		/* HP-PA */
+  /* Unknown */
+#elif defined( __aux )		/* 68K */
+  /* Unknown */
+#elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
+#  define DES_UNROLL
+#elif defined( __sgi )		/* Newer MIPS */
+#  define DES_PTR
+#  define DES_RISC2
+#  define DES_UNROLL
+#elif defined( i386 )		/* x86 boxes, should be gcc */
+#  define DES_PTR
+#  define DES_RISC1
+#  define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+#endif /* HEADER_DES_LOCL_H */
diff --git a/ap/app/ppp-2.4.1/include/openssl/opensslv.h b/ap/app/ppp-2.4.1/include/openssl/opensslv.h
new file mode 100644
index 0000000..71b53ef
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/openssl/opensslv.h
@@ -0,0 +1,85 @@
+#ifndef HEADER_OPENSSLV_H
+#define HEADER_OPENSSLV_H
+
+/* Numeric release version identifier:
+ * MMNNFFPPS: major minor fix patch status
+ * The status nibble has one of the values 0 for development, 1 to e for betas
+ * 1 to 14, and f for release.  The patch level is exactly that.
+ * For example:
+ * 0.9.3-dev	  0x00903000
+ * 0.9.3-beta1	  0x00903001
+ * 0.9.3-beta2-dev 0x00903002
+ * 0.9.3-beta2    0x00903002 (same as ...beta2-dev)
+ * 0.9.3	  0x0090300f
+ * 0.9.3a	  0x0090301f
+ * 0.9.4 	  0x0090400f
+ * 1.2.3z	  0x102031af
+ *
+ * For continuity reasons (because 0.9.5 is already out, and is coded
+ * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
+ * part is slightly different, by setting the highest bit.  This means
+ * that 0.9.5a looks like this: 0x0090581f.  At 0.9.6, we can start
+ * with 0x0090600S...
+ *
+ * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
+ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
+ *  major minor fix final patch/beta)
+ */
+#define OPENSSL_VERSION_NUMBER	0x0090600fL
+#define OPENSSL_VERSION_TEXT	"OpenSSL 0.9.6 24 Sep 2000"
+#define OPENSSL_VERSION_PTEXT	" part of " OPENSSL_VERSION_TEXT
+
+
+/* The macros below are to be used for shared library (.so, .dll, ...)
+ * versioning.  That kind of versioning works a bit differently between
+ * operating systems.  The most usual scheme is to set a major and a minor
+ * number, and have the runtime loader check that the major number is equal
+ * to what it was at application link time, while the minor number has to
+ * be greater or equal to what it was at application link time.  With this
+ * scheme, the version number is usually part of the file name, like this:
+ *
+ *	libcrypto.so.0.9
+ *
+ * Some unixen also make a softlink with the major verson number only:
+ *
+ *	libcrypto.so.0
+ *
+ * On True64 it works a little bit differently.  There, the shared library
+ * version is stored in the file, and is actually a series of versions,
+ * separated by colons.  The rightmost version present in the library when
+ * linking an application is stored in the application to be matched at
+ * run time.  When the application is run, a check is done to see if the
+ * library version stored in the application matches any of the versions
+ * in the version string of the library itself.
+ * This version string can be constructed in any way, depending on what
+ * kind of matching is desired.  However, to implement the same scheme as
+ * the one used in the other unixen, all compatible versions, from lowest
+ * to highest, should be part of the string.  Consecutive builds would
+ * give the following versions strings:
+ *
+ *	3.0
+ *	3.0:3.1
+ *	3.0:3.1:3.2
+ *	4.0
+ *	4.0:4.1
+ *
+ * Notice how version 4 is completely incompatible with version, and
+ * therefore give the breach you can see.
+ *
+ * There may be other schemes as well that I haven't yet discovered.
+ *
+ * So, here's the way it works here: first of all, the library version
+ * number doesn't need at all to match the overall OpenSSL version.
+ * However, it's nice and more understandable if it actually does.
+ * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
+ * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
+ * For the sake of True64 and any other OS that behaves in similar ways,
+ * we need to keep a history of version numbers, which is done in the
+ * macro SHLIB_VERSION_HISTORY.  The numbers are separated by colons and
+ * should only keep the versions that are binary compatible with the current.
+ */
+#define SHLIB_VERSION_HISTORY ""
+#define SHLIB_VERSION_NUMBER "0.9.6"
+
+
+#endif /* HEADER_OPENSSLV_H */
diff --git a/ap/app/ppp-2.4.1/include/openssl/sha.h b/ap/app/ppp-2.4.1/include/openssl/sha.h
new file mode 100644
index 0000000..77f6d96
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/openssl/sha.h
@@ -0,0 +1,119 @@
+/* crypto/sha/sha.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(NO_SHA) || (defined(NO_SHA0) && defined(NO_SHA1))
+#error SHA is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#else
+#define SHA_LONG unsigned int
+#endif
+
+#define SHA_LBLOCK	16
+#define SHA_CBLOCK	(SHA_LBLOCK*4)	/* SHA treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values. */
+#define SHA_LAST_BLOCK  (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+typedef struct SHAstate_st
+	{
+	SHA_LONG h0,h1,h2,h3,h4;
+	SHA_LONG Nl,Nh;
+	SHA_LONG data[SHA_LBLOCK];
+	int num;
+	} SHA_CTX;
+
+#ifndef NO_SHA0
+void SHA_Init(SHA_CTX *c);
+void SHA_Update(SHA_CTX *c, const void *data, unsigned long len);
+void SHA_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md);
+void SHA_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifndef NO_SHA1
+void SHA1_Init(SHA_CTX *c);
+void SHA1_Update(SHA_CTX *c, const void *data, unsigned long len);
+void SHA1_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md);
+void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/ap/app/ppp-2.4.1/include/pcap-int.h b/ap/app/ppp-2.4.1/include/pcap-int.h
new file mode 100644
index 0000000..ca77a0a
--- /dev/null
+++ b/ap/app/ppp-2.4.1/include/pcap-int.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /home/cvsroot/RT288x_SDK/source/user/ppp-2.4.1/include/pcap-int.h,v 1.1 2008-08-04 06:11:50 winfred Exp $ (LBL)
+ */
+
+#ifndef pcap_int_h
+#define pcap_int_h
+
+#include <pcap.h>
+
+/*
+ * Savefile
+ */
+struct pcap_sf {
+	FILE *rfile;
+	int swapped;
+	int version_major;
+	int version_minor;
+	u_char *base;
+};
+
+struct pcap_md {
+	struct pcap_stat stat;
+	int use_bpf;
+	u_long	TotPkts;	/* can't oflow for 79 hrs on ether */
+	u_long	TotAccepted;	/* count accepted by filter */
+	u_long	TotDrops;	/* count of dropped packets */
+	long	TotMissed;	/* missed by i/f during this run */
+	long	OrigMissed;	/* missed by i/f before this run */
+#ifdef linux
+	int pad;
+	int skip;
+	char *device;
+#endif
+};
+
+struct pcap {
+	int fd;
+	int snapshot;
+	int linktype;
+	int tzoff;		/* timezone offset */
+	int offset;		/* offset for proper alignment */
+
+	struct pcap_sf sf;
+	struct pcap_md md;
+
+	/*
+	 * Read buffer.
+	 */
+	int bufsize;
+	u_char *buffer;
+	u_char *bp;
+	int cc;
+
+	/*
+	 * Place holder for pcap_next().
+	 */
+	u_char *pkt;
+
+	
+	/*
+	 * Placeholder for filter code if bpf not in kernel.
+	 */
+	struct bpf_program fcode;
+
+	char errbuf[PCAP_ERRBUF_SIZE];
+};
+
+int	yylex(void);
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+int	pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
+int	pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
+
+/* Ultrix pads to make everything line up on a nice boundary */
+#if defined(ultrix) || defined(__alpha)
+#define       PCAP_FDDIPAD 3
+#endif
+
+extern	int pcap_fddipad;
+#endif
diff --git a/ap/app/ppp-2.4.1/pppd/ccp.c b/ap/app/ppp-2.4.1/pppd/ccp.c
new file mode 100644
index 0000000..af26573
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/ccp.c
@@ -0,0 +1,1497 @@
+/*
+ * ccp.c - PPP Compression Control Protocol.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#define RCSID	"$Id: ccp.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <pppd.h>
+#include "fsm.h"
+#include "ccp.h"
+#ifdef MPPE
+#include "mppe.h"
+#endif
+#include <net/ppp-comp.h>
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Unfortunately there is a bug in zlib which means that using a
+ * size of 8 (window size = 256) for Deflate compression will cause
+ * buffer overruns and kernel crashes in the deflate module.
+ * Until this is fixed we only accept sizes in the range 9 .. 15.
+ * Thanks to James Carlson for pointing this out.
+ */
+#define DEFLATE_MIN_WORKS	9
+
+/*
+ * Command-line options.
+ */
+static int setbsdcomp __P((char **));
+static int setdeflate __P((char **));
+static char bsd_value[8];
+static char deflate_value[8];
+
+static option_t ccp_option_list[] = {
+    { "noccp", o_bool, &ccp_protent.enabled_flag,
+      "Disable CCP negotiation" },
+    { "-ccp", o_bool, &ccp_protent.enabled_flag,
+      "Disable CCP negotiation", OPT_ALIAS },
+
+    { "bsdcomp", o_special, (void *)setbsdcomp,
+      "Request BSD-Compress packet compression",
+      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value },
+    { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+      "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].bsd_compress },
+    { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+      "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].bsd_compress },
+
+    { "deflate", o_special, (void *)setdeflate,
+      "request Deflate compression",
+      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value },
+    { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
+      "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].deflate },
+    { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
+      "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].deflate },
+
+    { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
+      "don't use draft deflate #", OPT_A2COPY,
+      &ccp_allowoptions[0].deflate_draft },
+
+    { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO },
+    { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].predictor_1 },
+    { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
+      &ccp_allowoptions[0].predictor_1 },
+#ifdef MPPE
+    { "mppe-40", o_special_noarg, setmppe_40,
+      "Allow 40 bit MPPE encryption" }, 
+    { "+mppe-40", o_special_noarg, setmppe_40,
+      "Allow 40 bit MPPE encryption" }, 
+    { "nomppe-40", o_special_noarg, setnomppe_40,
+      "Disallow 40 bit MPPE encryption" }, 
+    { "-mppe-40", o_special_noarg, setnomppe_40,
+      "Disallow 40 bit MPPE encryption" }, 
+    { "mppe-128", o_special_noarg, setmppe_128,
+      "Allow 128 bit MPPE encryption" }, 
+    { "+mppe-128", o_special_noarg, setmppe_128,
+      "Allow 128 bit MPPE encryption" }, 
+    { "nomppe-128", o_special_noarg, setnomppe_128,
+      "Disallow 128 bit MPPE encryption" }, 
+    { "-mppe-128", o_special_noarg, setnomppe_128,
+      "Disallow 128 bit MPPE encryption" }, 
+    { "mppe-stateless", o_special_noarg, setmppe_stateless,
+      "Allow stateless MPPE encryption" }, 
+    { "+mppe-stateless", o_special_noarg, setmppe_stateless,
+      "Allow stateless MPPE encryption" }, 
+    { "nomppe-stateless", o_special_noarg, setnomppe_stateless,
+      "Disallow stateless MPPE encryption" }, 
+    { "-mppe-stateless", o_special_noarg, setnomppe_stateless,
+      "Disallow stateless MPPE encryption" }, 
+#endif
+
+    { NULL }
+};
+
+/*
+ * Protocol entry points from main code.
+ */
+static void ccp_init __P((int unit));
+static void ccp_open __P((int unit));
+static void ccp_close __P((int unit, char *));
+static void ccp_lowerup __P((int unit));
+static void ccp_lowerdown __P((int));
+static void ccp_input __P((int unit, u_char *pkt, int len));
+static void ccp_protrej __P((int unit));
+static int  ccp_printpkt __P((u_char *pkt, int len,
+			      void (*printer) __P((void *, char *, ...)),
+			      void *arg));
+static void ccp_datainput __P((int unit, u_char *pkt, int len));
+
+struct protent ccp_protent = {
+    PPP_CCP,
+    ccp_init,
+    ccp_input,
+    ccp_protrej,
+    ccp_lowerup,
+    ccp_lowerdown,
+    ccp_open,
+    ccp_close,
+    ccp_printpkt,
+    ccp_datainput,
+    1,
+    "CCP",
+    "Compressed",
+    ccp_option_list,
+    NULL,
+    NULL,
+    NULL
+};
+
+fsm ccp_fsm[NUM_PPP];
+ccp_options ccp_wantoptions[NUM_PPP];	/* what to request the peer to use */
+ccp_options ccp_gotoptions[NUM_PPP];	/* what the peer agreed to do */
+ccp_options ccp_allowoptions[NUM_PPP];	/* what we'll agree to do */
+ccp_options ccp_hisoptions[NUM_PPP];	/* what we agreed to do */
+
+/*
+ * Callbacks for fsm code.
+ */
+static void ccp_resetci __P((fsm *));
+static int  ccp_cilen __P((fsm *));
+static void ccp_addci __P((fsm *, u_char *, int *));
+static int  ccp_ackci __P((fsm *, u_char *, int));
+static int  ccp_nakci __P((fsm *, u_char *, int));
+static int  ccp_rejci __P((fsm *, u_char *, int));
+static int  ccp_reqci __P((fsm *, u_char *, int *, int));
+static void ccp_up __P((fsm *));
+static void ccp_down __P((fsm *));
+static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
+static void ccp_rack_timeout __P((void *));
+static char *method_name __P((ccp_options *, ccp_options *));
+
+static fsm_callbacks ccp_callbacks = {
+    ccp_resetci,
+    ccp_cilen,
+    ccp_addci,
+    ccp_ackci,
+    ccp_nakci,
+    ccp_rejci,
+    ccp_reqci,
+    ccp_up,
+    ccp_down,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    ccp_extcode,
+    "CCP"
+};
+
+/*
+ * Do we want / did we get any compression?
+ */
+#define ANY_COMPRESS(opt)	((opt).deflate || (opt).bsd_compress \
+				 || (opt).predictor_1 || (opt).predictor_2 \
+				 || (opt).mppe )
+
+/*
+ * Local state (mainly for handling reset-reqs and reset-acks).
+ */
+static int ccp_localstate[NUM_PPP];
+#define RACK_PENDING	1	/* waiting for reset-ack */
+#define RREQ_REPEAT	2	/* send another reset-req if no reset-ack */
+
+#define RACKTIMEOUT	1	/* second */
+
+static int all_rejected[NUM_PPP];	/* we rejected all peer's options */
+
+/*
+ * Option parsing.
+ */
+static int
+setbsdcomp(argv)
+    char **argv;
+{
+    int rbits, abits;
+    char *str, *endp;
+
+    str = *argv;
+    abits = rbits = strtol(str, &endp, 0);
+    if (endp != str && *endp == ',') {
+	str = endp + 1;
+	abits = strtol(str, &endp, 0);
+    }
+    if (*endp != 0 || endp == str) {
+	option_error("invalid parameter '%s' for bsdcomp option", *argv);
+	return 0;
+    }
+    if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
+	|| (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
+	option_error("bsdcomp option values must be 0 or %d .. %d",
+		     BSD_MIN_BITS, BSD_MAX_BITS);
+	return 0;
+    }
+    if (rbits > 0) {
+	ccp_wantoptions[0].bsd_compress = 1;
+	ccp_wantoptions[0].bsd_bits = rbits;
+    } else
+	ccp_wantoptions[0].bsd_compress = 0;
+    if (abits > 0) {
+	ccp_allowoptions[0].bsd_compress = 1;
+	ccp_allowoptions[0].bsd_bits = abits;
+    } else
+	ccp_allowoptions[0].bsd_compress = 0;
+    slprintf(bsd_value, sizeof(bsd_value),
+	     rbits == abits? "%d": "%d,%d", rbits, abits);
+
+    return 1;
+}
+
+static int
+setdeflate(argv)
+    char **argv;
+{
+    int rbits, abits;
+    char *str, *endp;
+
+    str = *argv;
+    abits = rbits = strtol(str, &endp, 0);
+    if (endp != str && *endp == ',') {
+	str = endp + 1;
+	abits = strtol(str, &endp, 0);
+    }
+    if (*endp != 0 || endp == str) {
+	option_error("invalid parameter '%s' for deflate option", *argv);
+	return 0;
+    }
+    if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
+	|| (abits != 0 && (abits < DEFLATE_MIN_SIZE
+			  || abits > DEFLATE_MAX_SIZE))) {
+	option_error("deflate option values must be 0 or %d .. %d",
+		     DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
+	return 0;
+    }
+    if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) {
+	if (rbits == DEFLATE_MIN_SIZE)
+	    rbits = DEFLATE_MIN_WORKS;
+	if (abits == DEFLATE_MIN_SIZE)
+	    abits = DEFLATE_MIN_WORKS;
+	warn("deflate option value of %d changed to %d to avoid zlib bug",
+	     DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS);
+    }
+    if (rbits > 0) {
+	ccp_wantoptions[0].deflate = 1;
+	ccp_wantoptions[0].deflate_size = rbits;
+    } else
+	ccp_wantoptions[0].deflate = 0;
+    if (abits > 0) {
+	ccp_allowoptions[0].deflate = 1;
+	ccp_allowoptions[0].deflate_size = abits;
+    } else
+	ccp_allowoptions[0].deflate = 0;
+    slprintf(deflate_value, sizeof(deflate_value),
+	     rbits == abits? "%d": "%d,%d", rbits, abits);
+
+    return 1;
+}
+
+/*
+ * ccp_init - initialize CCP.
+ */
+static void
+ccp_init(unit)
+    int unit;
+{
+    fsm *f = &ccp_fsm[unit];
+
+    f->unit = unit;
+    f->protocol = PPP_CCP;
+    f->callbacks = &ccp_callbacks;
+    fsm_init(f);
+
+    memset(&ccp_wantoptions[unit],  0, sizeof(ccp_options));
+    memset(&ccp_gotoptions[unit],   0, sizeof(ccp_options));
+    memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
+    memset(&ccp_hisoptions[unit],   0, sizeof(ccp_options));
+
+    ccp_wantoptions[0].deflate = 1;
+    ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+    ccp_wantoptions[0].deflate_correct = 1;
+    ccp_wantoptions[0].deflate_draft = 1;
+    ccp_allowoptions[0].deflate = 1;
+    ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+    ccp_allowoptions[0].deflate_correct = 1;
+    ccp_allowoptions[0].deflate_draft = 1;
+
+    ccp_wantoptions[0].bsd_compress = 1;
+    ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
+    ccp_allowoptions[0].bsd_compress = 1;
+    ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
+
+    ccp_allowoptions[0].predictor_1 = 1;
+#ifdef MPPE
+    ccp_wantoptions[0].mppe = 0;
+    ccp_wantoptions[0].mppe_stateless = 0;
+    ccp_wantoptions[0].mppe_40 = 0;
+    ccp_wantoptions[0].mppe_128 = 0;
+    ccp_allowoptions[0].mppe_stateless = 1;
+    ccp_allowoptions[0].mppe = 1;
+    ccp_allowoptions[0].mppe_40 = 1;
+    ccp_allowoptions[0].mppe_128 = 1;
+#endif /* MPPE*/
+}
+
+/*
+ * ccp_open - CCP is allowed to come up.
+ */
+static void
+ccp_open(unit)
+    int unit;
+{
+    fsm *f = &ccp_fsm[unit];
+
+    if (f->state != OPENED)
+	ccp_flags_set(unit, 1, 0);
+
+    /*
+     * Find out which compressors the kernel supports before
+     * deciding whether to open in silent mode.
+     */
+    ccp_resetci(f);
+    if (!ANY_COMPRESS(ccp_gotoptions[unit]))
+	f->flags |= OPT_SILENT;
+
+    fsm_open(f);
+}
+
+/*
+ * ccp_close - Terminate CCP.
+ */
+static void
+ccp_close(unit, reason)
+    int unit;
+    char *reason;
+{
+    ccp_flags_set(unit, 0, 0);
+    fsm_close(&ccp_fsm[unit], reason);
+}
+
+/*
+ * ccp_lowerup - we may now transmit CCP packets.
+ */
+static void
+ccp_lowerup(unit)
+    int unit;
+{
+    fsm_lowerup(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_lowerdown - we may not transmit CCP packets.
+ */
+static void
+ccp_lowerdown(unit)
+    int unit;
+{
+    fsm_lowerdown(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_input - process a received CCP packet.
+ */
+static void
+ccp_input(unit, p, len)
+    int unit;
+    u_char *p;
+    int len;
+{
+    fsm *f = &ccp_fsm[unit];
+    int oldstate;
+
+    /*
+     * Check for a terminate-request so we can print a message.
+     */
+    oldstate = f->state;
+    fsm_input(f, p, len);
+    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
+	notice("Compression disabled by peer.");
+
+    /*
+     * If we get a terminate-ack and we're not asking for compression,
+     * close CCP.
+     */
+    if (oldstate == REQSENT && p[0] == TERMACK
+	&& !ANY_COMPRESS(ccp_gotoptions[unit]))
+	ccp_close(unit, "No compression negotiated");
+}
+
+/*
+ * Handle a CCP-specific code.
+ */
+static int
+ccp_extcode(f, code, id, p, len)
+    fsm *f;
+    int code, id;
+    u_char *p;
+    int len;
+{
+    switch (code) {
+    case CCP_RESETREQ:
+	if (f->state != OPENED)
+	    break;
+	/* send a reset-ack, which the transmitter will see and
+	   reset its compression state. */
+	fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
+	break;
+
+    case CCP_RESETACK:
+	if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
+	    ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
+	    UNTIMEOUT(ccp_rack_timeout, f);
+	}
+	break;
+
+    default:
+	return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * ccp_protrej - peer doesn't talk CCP.
+ */
+static void
+ccp_protrej(unit)
+    int unit;
+{
+    ccp_flags_set(unit, 0, 0);
+    fsm_lowerdown(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_resetci - initialize at start of negotiation.
+ */
+static void
+ccp_resetci(f)
+    fsm *f;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    u_char opt_buf[256];
+
+    *go = ccp_wantoptions[f->unit];
+    all_rejected[f->unit] = 0;
+
+    /*
+     * Check whether the kernel knows about the various
+     * compression methods we might request.
+     */
+    if (go->bsd_compress) {
+	opt_buf[0] = CI_BSD_COMPRESS;
+	opt_buf[1] = CILEN_BSD_COMPRESS;
+	opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
+	if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
+	    go->bsd_compress = 0;
+    }
+#ifdef MPPE
+    if (go->mppe) {
+        opt_buf[0] = CI_MPPE;
+        opt_buf[1] = CILEN_MPPE;
+        opt_buf[2] = 0;
+	/* keysize is 8 here */
+        BCOPY(mppe_master_send_key_40, opt_buf+3, 8);
+        BCOPY(mppe_master_recv_key_40, opt_buf+11, 8);
+        if (ccp_test(f->unit, opt_buf, (2*8)+3, 0) <= 0)
+            go->mppe = 0;
+    }
+#endif /*MPPE*/
+    if (go->deflate) {
+	if (go->deflate_correct) {
+	    opt_buf[0] = CI_DEFLATE;
+	    opt_buf[1] = CILEN_DEFLATE;
+	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
+	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+		go->deflate_correct = 0;
+	}
+	if (go->deflate_draft) {
+	    opt_buf[0] = CI_DEFLATE_DRAFT;
+	    opt_buf[1] = CILEN_DEFLATE;
+	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
+	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+		go->deflate_draft = 0;
+	}
+	if (!go->deflate_correct && !go->deflate_draft)
+	    go->deflate = 0;
+    }
+    if (go->predictor_1) {
+	opt_buf[0] = CI_PREDICTOR_1;
+	opt_buf[1] = CILEN_PREDICTOR_1;
+	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
+	    go->predictor_1 = 0;
+    }
+    if (go->predictor_2) {
+	opt_buf[0] = CI_PREDICTOR_2;
+	opt_buf[1] = CILEN_PREDICTOR_2;
+	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
+	    go->predictor_2 = 0;
+    }
+}
+
+/*
+ * ccp_cilen - Return total length of our configuration info.
+ */
+static int
+ccp_cilen(f)
+    fsm *f;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+
+    return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
+	+ (go->deflate? CILEN_DEFLATE: 0)
+	+ (go->predictor_1? CILEN_PREDICTOR_1: 0)
+	+ (go->predictor_2? CILEN_PREDICTOR_2: 0)
+	+ (go->mppe? CILEN_MPPE: 0);
+}
+
+/*
+ * ccp_addci - put our requests in a packet.
+ */
+static void
+ccp_addci(f, p, lenp)
+    fsm *f;
+    u_char *p;
+    int *lenp;
+{
+    int res;
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    u_char *p0 = p;
+
+    /*
+     * Add the compression types that we can receive, in decreasing
+     * preference order.  Get the kernel to allocate the first one
+     * in case it gets Acked.
+     */
+    if (go->deflate) {
+	p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
+	p[1] = CILEN_DEFLATE;
+	p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
+	p[3] = DEFLATE_CHK_SEQUENCE;
+	for (;;) {
+	    res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
+	    if (res > 0) {
+		p += CILEN_DEFLATE;
+		break;
+	    }
+	    if (res < 0 || go->deflate_size <= DEFLATE_MIN_WORKS) {
+		go->deflate = 0;
+		break;
+	    }
+	    --go->deflate_size;
+	    p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
+	}
+	if (p != p0 && go->deflate_correct && go->deflate_draft) {
+	    p[0] = CI_DEFLATE_DRAFT;
+	    p[1] = CILEN_DEFLATE;
+	    p[2] = p[2 - CILEN_DEFLATE];
+	    p[3] = DEFLATE_CHK_SEQUENCE;
+	    p += CILEN_DEFLATE;
+	}
+    }
+#ifdef MPPE
+    if (go->mppe) {
+        u_char opt_buf[64];
+        u_int keysize = 0;
+
+        if(!mppe_allowed)
+            go->mppe_stateless = go->mppe_40 = go->mppe_128 = 0;
+        p[0]=CI_MPPE;
+        p[1]=CILEN_MPPE;
+        p[2]=(go->mppe_stateless ? MPPE_STATELESS : 0);
+        p[3]=0;
+        p[4]=0;
+        p[5]=(go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0);
+        if(p[5] & MPPE_40BIT) {
+            keysize = 8;
+            BCOPY(mppe_master_send_key_40, opt_buf+3, keysize);
+            BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize);
+        } else if(p[5] & MPPE_128BIT) {
+            keysize = 16;
+            BCOPY(mppe_master_send_key_128, opt_buf+3, keysize);
+            BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize);
+        }
+        if(p[5] != 0) {
+            opt_buf[0]=CI_MPPE;
+            opt_buf[1]=CILEN_MPPE;
+            opt_buf[2] = (go->mppe_stateless) ? 1 : 0;
+            res = ccp_test(f->unit, opt_buf, (2*keysize)+3, 0);
+        } else {
+            res = -1;
+        }
+        if (res > 0) {
+                p += CILEN_MPPE;
+        }
+    }
+#endif /* MPPE*/
+    if (go->bsd_compress) {
+	p[0] = CI_BSD_COMPRESS;
+	p[1] = CILEN_BSD_COMPRESS;
+	p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
+	if (p != p0) {
+	    p += CILEN_BSD_COMPRESS;	/* not the first option */
+	} else {
+	    for (;;) {
+		res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
+		if (res > 0) {
+		    p += CILEN_BSD_COMPRESS;
+		    break;
+		}
+		if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
+		    go->bsd_compress = 0;
+		    break;
+		}
+		--go->bsd_bits;
+		p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
+	    }
+	}
+    }
+    if (go->predictor_1) {
+	p[0] = CI_PREDICTOR_1;
+	p[1] = CILEN_PREDICTOR_1;
+	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
+	    go->predictor_1 = 0;
+	} else {
+	    p += CILEN_PREDICTOR_1;
+	}
+    }
+    if (go->predictor_2) {
+	p[0] = CI_PREDICTOR_2;
+	p[1] = CILEN_PREDICTOR_2;
+	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
+	    go->predictor_2 = 0;
+	} else {
+	    p += CILEN_PREDICTOR_2;
+	}
+    }
+
+    go->method = (p > p0)? p0[0]: -1;
+
+    *lenp = p - p0;
+}
+
+/*
+ * ccp_ackci - process a received configure-ack, and return
+ * 1 iff the packet was OK.
+ */
+static int
+ccp_ackci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    u_char *p0 = p;
+
+    if (go->deflate) {
+	if (len < CILEN_DEFLATE
+	    || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+	    || p[1] != CILEN_DEFLATE
+	    || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+	    || p[3] != DEFLATE_CHK_SEQUENCE)
+	    return 0;
+	p += CILEN_DEFLATE;
+	len -= CILEN_DEFLATE;
+	if (len == 0)
+	    return 1;
+	if (go->deflate_correct && go->deflate_draft) {
+	    if (len < CILEN_DEFLATE
+		|| p[0] != CI_DEFLATE_DRAFT
+		|| p[1] != CILEN_DEFLATE
+		|| p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+		|| p[3] != DEFLATE_CHK_SEQUENCE)
+		return 0;
+	    p += CILEN_DEFLATE;
+	    len -= CILEN_DEFLATE;
+	}
+    }
+#ifdef MPPE
+    if (go->mppe) {
+        if ( len < CILEN_MPPE
+		|| p[1] != CILEN_MPPE || p[0] != CI_MPPE
+		|| p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0)
+		|| p[3] != 0
+		|| p[4] != 0
+		|| p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0)))
+           return 0;
+        p += CILEN_MPPE;
+        len -= CILEN_MPPE;
+        /* Cope with first/fast ack */
+        if (len == 0)
+            return 1;
+    }
+#endif /* MPPE */
+    if (go->bsd_compress) {
+	if (len < CILEN_BSD_COMPRESS
+	    || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
+	    || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
+	    return 0;
+	p += CILEN_BSD_COMPRESS;
+	len -= CILEN_BSD_COMPRESS;
+	if (p == p0 && len == 0)
+	    return 1;
+    }
+    if (go->predictor_1) {
+	if (len < CILEN_PREDICTOR_1
+	    || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
+	    return 0;
+	p += CILEN_PREDICTOR_1;
+	len -= CILEN_PREDICTOR_1;
+	if (p == p0 && len == 0)
+	    return 1;
+    }
+    if (go->predictor_2) {
+	if (len < CILEN_PREDICTOR_2
+	    || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
+	    return 0;
+	p += CILEN_PREDICTOR_2;
+	len -= CILEN_PREDICTOR_2;
+	if (p == p0 && len == 0)
+	    return 1;
+    }
+
+    if (len != 0)
+	return 0;
+    return 1;
+}
+
+/*
+ * ccp_nakci - process received configure-nak.
+ * Returns 1 iff the nak was OK.
+ */
+static int
+ccp_nakci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    ccp_options no;		/* options we've seen already */
+    ccp_options try;		/* options to ask for next time */
+
+    memset(&no, 0, sizeof(no));
+    try = *go;
+
+    if (go->deflate && len >= CILEN_DEFLATE
+	&& p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+	&& p[1] == CILEN_DEFLATE) {
+	no.deflate = 1;
+	/*
+	 * Peer wants us to use a different code size or something.
+	 * Stop asking for Deflate if we don't understand his suggestion.
+	 */
+	if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
+	    || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS
+	    || p[3] != DEFLATE_CHK_SEQUENCE)
+	    try.deflate = 0;
+	else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
+	    try.deflate_size = DEFLATE_SIZE(p[2]);
+	p += CILEN_DEFLATE;
+	len -= CILEN_DEFLATE;
+	if (go->deflate_correct && go->deflate_draft
+	    && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+	    && p[1] == CILEN_DEFLATE) {
+	    p += CILEN_DEFLATE;
+	    len -= CILEN_DEFLATE;
+	}
+    }
+
+#ifdef MPPE
+    if (len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+	no.mppe = 1;
+	if((p[5] & MPPE_128BIT) == 0)
+	    try.mppe_128 = 0;
+	if((p[5] & MPPE_40BIT) == 0)
+            try.mppe_40 = 0;
+	if((p[2] & MPPE_STATELESS) == 0)
+            try.mppe_stateless = 0;
+	if(!try.mppe_128 && !try.mppe_40) {
+            no.mppe = 0;
+            try.mppe = 0;
+	}
+	p += CILEN_MPPE;
+	len -= CILEN_MPPE;
+    }
+#endif /* MPPE */
+
+    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
+	&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
+	no.bsd_compress = 1;
+	/*
+	 * Peer wants us to use a different number of bits
+	 * or a different version.
+	 */
+	if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
+	    try.bsd_compress = 0;
+	else if (BSD_NBITS(p[2]) < go->bsd_bits)
+	    try.bsd_bits = BSD_NBITS(p[2]);
+	p += CILEN_BSD_COMPRESS;
+	len -= CILEN_BSD_COMPRESS;
+    }
+
+    /*
+     * Predictor-1 and 2 have no options, so they can't be Naked.
+     *
+     * There may be remaining options but we ignore them.
+     */
+
+    if (f->state != OPENED)
+	*go = try;
+    return 1;
+}
+
+/*
+ * ccp_rejci - reject some of our suggested compression methods.
+ */
+static int
+ccp_rejci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    ccp_options try;		/* options to request next time */
+
+    try = *go;
+
+    /*
+     * Cope with empty configure-rejects by ceasing to send
+     * configure-requests.
+     */
+    if (len == 0 && all_rejected[f->unit])
+	return -1;
+
+    if (go->deflate && len >= CILEN_DEFLATE
+	&& p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+	&& p[1] == CILEN_DEFLATE) {
+	if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+	    || p[3] != DEFLATE_CHK_SEQUENCE)
+	    return 0;		/* Rej is bad */
+	if (go->deflate_correct)
+	    try.deflate_correct = 0;
+	else
+	    try.deflate_draft = 0;
+	p += CILEN_DEFLATE;
+	len -= CILEN_DEFLATE;
+	if (go->deflate_correct && go->deflate_draft
+	    && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+	    && p[1] == CILEN_DEFLATE) {
+	    if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+		|| p[3] != DEFLATE_CHK_SEQUENCE)
+		return 0;		/* Rej is bad */
+	    try.deflate_draft = 0;
+	    p += CILEN_DEFLATE;
+	    len -= CILEN_DEFLATE;
+	}
+	if (!try.deflate_correct && !try.deflate_draft)
+	    try.deflate = 0;
+    }
+#ifdef MPPE
+    if (go->mppe && len >= CILEN_MPPE
+	&& p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+	try.mppe = 0;
+	p += CILEN_MPPE;
+	len -= CILEN_MPPE;
+    }
+#endif /*MPPE*/
+    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
+	&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
+	if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
+	    return 0;
+	try.bsd_compress = 0;
+	p += CILEN_BSD_COMPRESS;
+	len -= CILEN_BSD_COMPRESS;
+    }
+    if (go->predictor_1 && len >= CILEN_PREDICTOR_1
+	&& p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
+	try.predictor_1 = 0;
+	p += CILEN_PREDICTOR_1;
+	len -= CILEN_PREDICTOR_1;
+    }
+    if (go->predictor_2 && len >= CILEN_PREDICTOR_2
+	&& p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
+	try.predictor_2 = 0;
+	p += CILEN_PREDICTOR_2;
+	len -= CILEN_PREDICTOR_2;
+    }
+
+    if (len != 0)
+	return 0;
+
+    if (f->state != OPENED)
+	*go = try;
+
+    return 1;
+}
+
+/*
+ * ccp_reqci - processed a received configure-request.
+ * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
+ * appropriately.
+ */
+static int
+ccp_reqci(f, p, lenp, dont_nak)
+    fsm *f;
+    u_char *p;
+    int *lenp;
+    int dont_nak;
+{
+    int ret, newret, res;
+    u_char *p0, *retp;
+    int len, clen, type, nb;
+    ccp_options *ho = &ccp_hisoptions[f->unit];
+    ccp_options *ao = &ccp_allowoptions[f->unit];
+
+    ret = CONFACK;
+    retp = p0 = p;
+    len = *lenp;
+
+    memset(ho, 0, sizeof(ccp_options));
+    ho->method = (len > 0)? p[0]: -1;
+
+    while (len > 0) {
+	newret = CONFACK;
+	if (len < 2 || p[1] < 2 || p[1] > len) {
+	    /* length is bad */
+	    clen = len;
+	    newret = CONFREJ;
+
+	} else {
+	    type = p[0];
+	    clen = p[1];
+
+	    switch (type) {
+	    case CI_DEFLATE:
+	    case CI_DEFLATE_DRAFT:
+		if (!ao->deflate || clen != CILEN_DEFLATE
+		    || (!ao->deflate_correct && type == CI_DEFLATE)
+		    || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
+		    newret = CONFREJ;
+		    break;
+		}
+
+		ho->deflate = 1;
+		ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
+		if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
+		    || p[3] != DEFLATE_CHK_SEQUENCE
+		    || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) {
+		    newret = CONFNAK;
+		    if (!dont_nak) {
+			p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
+			p[3] = DEFLATE_CHK_SEQUENCE;
+			/* fall through to test this #bits below */
+		    } else
+			break;
+		}
+
+		/*
+		 * Check whether we can do Deflate with the window
+		 * size they want.  If the window is too big, reduce
+		 * it until the kernel can cope and nak with that.
+		 * We only check this for the first option.
+		 */
+		if (p == p0) {
+		    for (;;) {
+			res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
+			if (res > 0)
+			    break;		/* it's OK now */
+			if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) {
+			    newret = CONFREJ;
+			    p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
+			    break;
+			}
+			newret = CONFNAK;
+			--nb;
+			p[2] = DEFLATE_MAKE_OPT(nb);
+		    }
+		}
+		break;
+
+#ifdef MPPE
+	    case CI_MPPE:
+		if (!ao->mppe || clen != CILEN_MPPE) {
+		    newret = CONFREJ;
+		    break;
+		}
+		if(!mppe_allowed)
+		{
+		    newret = CONFREJ;
+		    break;
+		}
+		ho->mppe = 1;
+		if((p[5]&(MPPE_40BIT|MPPE_128BIT)) == (MPPE_40BIT|MPPE_128BIT))
+		{
+		    /* if both are available, select the stronger */
+		    p[5] &= ~MPPE_40BIT;
+		    newret = CONFNAK;
+		}
+		if((p[2] & ~MPPE_STATELESS) != 0
+		   || p[3] != 0
+		   || p[4] != 0
+		   || (p[5] & ~(MPPE_40BIT | MPPE_128BIT)) != 0)
+		{
+    		    ccp_options *wo = &ccp_wantoptions[f->unit];
+		    /* not sure what they want, tell 'em what we got */
+		    p[2] &= MPPE_STATELESS;
+		    p[3] &= 0;
+		    p[4] &= 0;
+		    p[5] &= MPPE_40BIT | MPPE_128BIT;
+		    if(wo->mppe_40)
+		        p[5] |= MPPE_40BIT;
+		    if(wo->mppe_128)
+		        p[5] |= MPPE_128BIT;
+		    newret = CONFNAK;
+		}
+		
+		if((newret == CONFACK) || (newret == CONFNAK))
+		{
+    		    /* 
+		     * The kernel ppp driver needs the session key 
+                     * which is not sent via CCP :( 
+		     */
+		    unsigned int keysize;
+		    unsigned char opt_buf[64];
+		    opt_buf[0] = CI_MPPE;
+		    opt_buf[1] = CILEN_MPPE;
+		    if(p[2] & MPPE_STATELESS) {
+			ho->mppe_stateless=1;
+	 		opt_buf[2] = MPPE_STATELESS;
+		    }
+		    /* push in our send/receive keys */
+		    if(p[5] & MPPE_40BIT) {
+			ho->mppe_40 = 1;
+			keysize = 8;
+		        BCOPY(mppe_master_send_key_40, opt_buf+3, keysize);
+		        BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize);
+		    } else if(p[5] & MPPE_128BIT) {
+			ho->mppe_128 = 1;
+			keysize = 16;
+		        BCOPY(mppe_master_send_key_128, opt_buf+3, keysize);
+		        BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize);
+		    } else {
+		        ho->mppe = 0;
+		        newret = CONFREJ;
+		        break;
+		    }
+		    /* call ioctl and pass this nasty stuff to the kernel */
+		    if (ccp_test(f->unit, opt_buf, (2*keysize)+3, 1) <= 0){
+			ho->mppe = 0;
+			newret = CONFREJ;
+			break;
+		    }
+		}
+		break;
+#endif /* MPPE */
+
+	    case CI_BSD_COMPRESS:
+		if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
+		    newret = CONFREJ;
+		    break;
+		}
+
+		ho->bsd_compress = 1;
+		ho->bsd_bits = nb = BSD_NBITS(p[2]);
+		if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
+		    || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
+		    newret = CONFNAK;
+		    if (!dont_nak) {
+			p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
+			/* fall through to test this #bits below */
+		    } else
+			break;
+		}
+
+		/*
+		 * Check whether we can do BSD-Compress with the code
+		 * size they want.  If the code size is too big, reduce
+		 * it until the kernel can cope and nak with that.
+		 * We only check this for the first option.
+		 */
+		if (p == p0) {
+		    for (;;) {
+			res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
+			if (res > 0)
+			    break;
+			if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
+			    newret = CONFREJ;
+			    p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
+						ho->bsd_bits);
+			    break;
+			}
+			newret = CONFNAK;
+			--nb;
+			p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
+		    }
+		}
+		break;
+
+	    case CI_PREDICTOR_1:
+		if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
+		    newret = CONFREJ;
+		    break;
+		}
+
+		ho->predictor_1 = 1;
+		if (p == p0
+		    && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
+		    newret = CONFREJ;
+		}
+		break;
+
+	    case CI_PREDICTOR_2:
+		if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
+		    newret = CONFREJ;
+		    break;
+		}
+
+		ho->predictor_2 = 1;
+		if (p == p0
+		    && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
+		    newret = CONFREJ;
+		}
+		break;
+
+	    default:
+		newret = CONFREJ;
+	    }
+	}
+
+	if (newret == CONFNAK && dont_nak)
+	    newret = CONFREJ;
+	if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
+	    /* we're returning this option */
+	    if (newret == CONFREJ && ret == CONFNAK)
+		retp = p0;
+	    ret = newret;
+	    if (p != retp)
+		BCOPY(p, retp, clen);
+	    retp += clen;
+	}
+
+	p += clen;
+	len -= clen;
+    }
+
+    if (ret != CONFACK) {
+	if (ret == CONFREJ && *lenp == retp - p0)
+	    all_rejected[f->unit] = 1;
+	else
+	    *lenp = retp - p0;
+    }
+    return ret;
+}
+
+/*
+ * Make a string name for a compression method (or 2).
+ */
+static char *
+method_name(opt, opt2)
+    ccp_options *opt, *opt2;
+{
+    static char result[64];
+
+    if (!ANY_COMPRESS(*opt))
+	return "(none)";
+    switch (opt->method) {
+    case CI_DEFLATE:
+    case CI_DEFLATE_DRAFT:
+	if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
+	    slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
+		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+		     opt->deflate_size, opt2->deflate_size);
+	else
+	    slprintf(result, sizeof(result), "Deflate%s (%d)",
+		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+		     opt->deflate_size);
+	break;
+#ifdef MPPE
+    case CI_MPPE:
+	if (opt->mppe_40) {
+	    if (opt->mppe_stateless) {
+		return "MPPE 40 bit, stateless";
+	    } else {
+		return "MPPE 40 bit, non-stateless";
+	    }
+	} else if (opt->mppe_128) {
+	    if (opt->mppe_stateless) {
+		return "MPPE 128 bit, stateless";
+	    } else {
+		return "MPPE 128 bit, non-stateless";
+	    }
+	} else {
+	    if (opt->mppe_stateless) {
+		return "MPPE unknown strength, stateless";
+	    } else {
+		return "MPPE unknown strength, stateless";
+	    }
+	}
+#endif
+    case CI_LZS:
+	return "Stac LZS";
+    case CI_BSD_COMPRESS:
+	if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
+	    slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
+		     opt->bsd_bits, opt2->bsd_bits);
+	else
+	    slprintf(result, sizeof(result), "BSD-Compress (%d)",
+		     opt->bsd_bits);
+	break;
+    case CI_PREDICTOR_1:
+	return "Predictor 1";
+    case CI_PREDICTOR_2:
+	return "Predictor 2";
+    default:
+	slprintf(result, sizeof(result), "Method %d", opt->method);
+    }
+    return result;
+}
+
+/*
+ * CCP has come up - inform the kernel driver and log a message.
+ */
+static void
+ccp_up(f)
+    fsm *f;
+{
+    ccp_options *go = &ccp_gotoptions[f->unit];
+    ccp_options *ho = &ccp_hisoptions[f->unit];
+    char method1[64];
+
+    ccp_flags_set(f->unit, 1, 1);
+    if (ANY_COMPRESS(*go)) {
+	if (ANY_COMPRESS(*ho)) {
+	    if (go->method == ho->method) {
+		notice("%s compression enabled", method_name(go, ho));
+	    } else {
+		strlcpy(method1, method_name(go, NULL), sizeof(method1));
+		notice("%s / %s compression enabled",
+		       method1, method_name(ho, NULL));
+	    }
+	} else
+	    notice("%s receive compression enabled", method_name(go, NULL));
+    } else if (ANY_COMPRESS(*ho))
+	notice("%s transmit compression enabled", method_name(ho, NULL));
+}
+
+/*
+ * CCP has gone down - inform the kernel driver.
+ */
+static void
+ccp_down(f)
+    fsm *f;
+{
+    if (ccp_localstate[f->unit] & RACK_PENDING)
+	UNTIMEOUT(ccp_rack_timeout, f);
+    ccp_localstate[f->unit] = 0;
+    ccp_flags_set(f->unit, 1, 0);
+}
+
+/*
+ * Print the contents of a CCP packet.
+ */
+static char *ccp_codenames[] = {
+    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+    "TermReq", "TermAck", "CodeRej",
+    NULL, NULL, NULL, NULL, NULL, NULL,
+    "ResetReq", "ResetAck",
+};
+
+static int
+ccp_printpkt(p, plen, printer, arg)
+    u_char *p;
+    int plen;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    u_char *p0, *optend;
+    int code, id, len;
+    int optlen;
+
+    p0 = p;
+    if (plen < HEADERLEN)
+	return 0;
+    code = p[0];
+    id = p[1];
+    len = (p[2] << 8) + p[3];
+    if (len < HEADERLEN || len > plen)
+	return 0;
+
+    if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
+	&& ccp_codenames[code-1] != NULL)
+	printer(arg, " %s", ccp_codenames[code-1]);
+    else
+	printer(arg, " code=0x%x", code);
+    printer(arg, " id=0x%x", id);
+    len -= HEADERLEN;
+    p += HEADERLEN;
+
+    switch (code) {
+    case CONFREQ:
+    case CONFACK:
+    case CONFNAK:
+    case CONFREJ:
+	/* print list of possible compression methods */
+	while (len >= 2) {
+	    code = p[0];
+	    optlen = p[1];
+	    if (optlen < 2 || optlen > len)
+		break;
+	    printer(arg, " <");
+	    len -= optlen;
+	    optend = p + optlen;
+	    switch (code) {
+	    case CI_DEFLATE:
+	    case CI_DEFLATE_DRAFT:
+		if (optlen >= CILEN_DEFLATE) {
+		    printer(arg, "deflate%s %d",
+			    (code == CI_DEFLATE_DRAFT? "(old#)": ""),
+			    DEFLATE_SIZE(p[2]));
+		    if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
+			printer(arg, " method %d", DEFLATE_METHOD(p[2]));
+		    if (p[3] != DEFLATE_CHK_SEQUENCE)
+			printer(arg, " check %d", p[3]);
+		    p += CILEN_DEFLATE;
+		}
+		break;
+	    case CI_BSD_COMPRESS:
+		if (optlen >= CILEN_BSD_COMPRESS) {
+		    printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
+			    BSD_NBITS(p[2]));
+		    p += CILEN_BSD_COMPRESS;
+		}
+		break;
+	    case CI_PREDICTOR_1:
+		if (optlen >= CILEN_PREDICTOR_1) {
+		    printer(arg, "predictor 1");
+		    p += CILEN_PREDICTOR_1;
+		}
+		break;
+	    case CI_MPPE:
+		if (optlen >= CILEN_MPPE) {
+		    printer(arg, "mppe %x %x %x %x",p[2],p[3],p[4],p[5]);
+		    p += CILEN_MPPE;
+		}
+		break;
+	    case CI_LZS:
+		if (optlen >= CILEN_LZS) {
+		    printer(arg, "lzs %x %x %x", p[2], p[3], p[4]);
+		    p += CILEN_LZS;
+		}
+		break;
+	    case CI_PREDICTOR_2:
+		if (optlen >= CILEN_PREDICTOR_2) {
+		    printer(arg, "predictor 2");
+		    p += CILEN_PREDICTOR_2;
+		}
+		break;
+	    }
+	    while (p < optend)
+		printer(arg, " %.2x", *p++);
+	    printer(arg, ">");
+	}
+	break;
+
+    case TERMACK:
+    case TERMREQ:
+	if (len > 0 && *p >= ' ' && *p < 0x7f) {
+	    print_string((char *)p, len, printer, arg);
+	    p += len;
+	    len = 0;
+	}
+	break;
+    }
+
+    /* dump out the rest of the packet in hex */
+    while (--len >= 0)
+	printer(arg, " %.2x", *p++);
+
+    return p - p0;
+}
+
+/*
+ * We have received a packet that the decompressor failed to
+ * decompress.  Here we would expect to issue a reset-request, but
+ * Motorola has a patent on resetting the compressor as a result of
+ * detecting an error in the decompressed data after decompression.
+ * (See US patent 5,130,993; international patent publication number
+ * WO 91/10289; Australian patent 73296/91.)
+ *
+ * So we ask the kernel whether the error was detected after
+ * decompression; if it was, we take CCP down, thus disabling
+ * compression :-(, otherwise we issue the reset-request.
+ */
+static void
+ccp_datainput(unit, pkt, len)
+    int unit;
+    u_char *pkt;
+    int len;
+{
+    fsm *f;
+
+    f = &ccp_fsm[unit];
+    if (f->state == OPENED) {
+	if (ccp_fatal_error(unit)) {
+	    /*
+	     * Disable compression by taking CCP down.
+	     */
+	    error("Lost compression sync: disabling compression");
+	    ccp_close(unit, "Lost compression sync");
+	} else {
+	    /* MPPE/MPPC does not requires CCP_RESETREQ */
+	    if (ccp_gotoptions[f->unit].method == CI_MPPE)
+		return;
+	    /*
+	     * Send a reset-request to reset the peer's compressor.
+	     * We don't do that if we are still waiting for an
+	     * acknowledgement to a previous reset-request.
+	     */
+	    if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
+		fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
+		TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
+		ccp_localstate[f->unit] |= RACK_PENDING;
+	    } else
+		ccp_localstate[f->unit] |= RREQ_REPEAT;
+	}
+    }
+}
+
+/*
+ * Timeout waiting for reset-ack.
+ */
+static void
+ccp_rack_timeout(arg)
+    void *arg;
+{
+    fsm *f = arg;
+
+    if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
+	fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
+	TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
+	ccp_localstate[f->unit] &= ~RREQ_REPEAT;
+    } else
+	ccp_localstate[f->unit] &= ~RACK_PENDING;
+}
+
diff --git a/ap/app/ppp-2.4.1/pppd/ccp.h b/ap/app/ppp-2.4.1/pppd/ccp.h
new file mode 100644
index 0000000..a66e466
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/ccp.h
@@ -0,0 +1,57 @@
+/*
+ * ccp.h - Definitions for PPP Compression Control Protocol.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ccp.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+typedef struct ccp_options {
+    bool bsd_compress;		/* do BSD Compress? */
+    bool deflate;		/* do Deflate? */
+    bool predictor_1;		/* do Predictor-1? */
+    bool predictor_2;		/* do Predictor-2? */
+    bool deflate_correct;	/* use correct code for deflate? */
+    bool deflate_draft;		/* use draft RFC code for deflate? */
+    bool mppe;			/* do M$ encryption? */
+    bool mppe_40;		/* allow 40 bit encryption */
+    bool mppe_128;		/* allow 128 bit encryption */
+    bool mppe_stateless;	/* allow stateless encryption */
+    u_short bsd_bits;		/* # bits/code for BSD Compress */
+    u_short deflate_size;	/* lg(window size) for Deflate */
+    short method;		/* code for chosen compression method */
+} ccp_options;
+
+extern fsm ccp_fsm[];
+extern ccp_options ccp_wantoptions[];
+extern ccp_options ccp_gotoptions[];
+extern ccp_options ccp_allowoptions[];
+extern ccp_options ccp_hisoptions[];
+
+extern struct protent ccp_protent;
+
+#ifdef MPPE
+size_t mppe_generate_session_key(char *optbuf);
+#endif
+
diff --git a/ap/app/ppp-2.4.1/pppd/chap.c b/ap/app/ppp-2.4.1/pppd/chap.c
new file mode 100644
index 0000000..6c6c5fc
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/chap.c
@@ -0,0 +1,958 @@
+/*
+ * chap.c - Challenge Handshake Authentication Protocol.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University.  The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1991 Gregory M. Christy.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Gregory M. Christy.  The name of the author may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: chap.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <pppd.h>
+#include "chap.h"
+#include "md5.h"
+#include "fsm.h"
+#include "lcp.h"
+#ifdef CHAPMS
+#include "chap_ms.h"
+#endif
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Command-line options.
+ */
+static option_t chap_option_list[] = {
+    { "chap-restart", o_int, &chap[0].timeouttime,
+      "Set timeout for CHAP", OPT_PRIO },
+    { "chap-max-challenge", o_int, &chap[0].max_transmits,
+      "Set max #xmits for challenge", OPT_PRIO },
+    { "chap-interval", o_int, &chap[0].chal_interval,
+      "Set interval for rechallenge", OPT_PRIO },
+#ifdef MSLANMAN
+    { "ms-lanman", o_bool, &ms_lanman,
+      "Use LanMan passwd when using MS-CHAP", 1 },
+#endif
+    { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+static void ChapInit __P((int));
+static void ChapLowerUp __P((int));
+static void ChapLowerDown __P((int));
+static void ChapInput __P((int, u_char *, int));
+static void ChapProtocolReject __P((int));
+static int  ChapPrintPkt __P((u_char *, int,
+			      void (*) __P((void *, char *, ...)), void *));
+
+struct protent chap_protent = {
+    PPP_CHAP,
+    ChapInit,
+    ChapInput,
+    ChapProtocolReject,
+    ChapLowerUp,
+    ChapLowerDown,
+    NULL,
+    NULL,
+    ChapPrintPkt,
+    NULL,
+    1,
+    "CHAP",
+    NULL,
+    chap_option_list,
+    NULL,
+    NULL,
+    NULL
+};
+
+chap_state chap[NUM_PPP];		/* CHAP state; one for each unit */
+
+static void ChapChallengeTimeout __P((void *));
+static void ChapResponseTimeout __P((void *));
+static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
+static void ChapRechallenge __P((void *));
+static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
+static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
+static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
+static void ChapSendStatus __P((chap_state *, int));
+static void ChapSendChallenge __P((chap_state *));
+static void ChapSendResponse __P((chap_state *));
+void ChapGenChallenge __P((chap_state *));
+
+extern double drand48 __P((void));
+extern void srand48 __P((long));
+
+/*
+ * ChapInit - Initialize a CHAP unit.
+ */
+static void
+ChapInit(unit)
+    int unit;
+{
+    chap_state *cstate = &chap[unit];
+
+    BZERO(cstate, sizeof(*cstate));
+    cstate->unit = unit;
+    cstate->clientstate = CHAPCS_INITIAL;
+    cstate->serverstate = CHAPSS_INITIAL;
+    cstate->timeouttime = CHAP_DEFTIMEOUT;
+    cstate->max_transmits = CHAP_DEFTRANSMITS;
+    /* random number generator is initialized in magic_init */
+}
+
+
+/*
+ * ChapAuthWithPeer - Authenticate us with our peer (start client).
+ *
+ */
+void
+ChapAuthWithPeer(unit, our_name, digest)
+    int unit;
+    char *our_name;
+    int digest;
+{
+    chap_state *cstate = &chap[unit];
+
+    cstate->resp_name = our_name;
+    cstate->resp_type = digest;
+
+    if (cstate->clientstate == CHAPCS_INITIAL ||
+	cstate->clientstate == CHAPCS_PENDING) {
+	/* lower layer isn't up - wait until later */
+	cstate->clientstate = CHAPCS_PENDING;
+	return;
+    }
+
+    /*
+     * We get here as a result of LCP coming up.
+     * So even if CHAP was open before, we will 
+     * have to re-authenticate ourselves.
+     */
+    cstate->clientstate = CHAPCS_LISTEN;
+}
+
+
+/*
+ * ChapAuthPeer - Authenticate our peer (start server).
+ */
+void
+ChapAuthPeer(unit, our_name, digest)
+    int unit;
+    char *our_name;
+    int digest;
+{
+    chap_state *cstate = &chap[unit];
+  
+    cstate->chal_name = our_name;
+    cstate->chal_type = digest;
+
+    if (cstate->serverstate == CHAPSS_INITIAL ||
+	cstate->serverstate == CHAPSS_PENDING) {
+	/* lower layer isn't up - wait until later */
+	cstate->serverstate = CHAPSS_PENDING;
+	return;
+    }
+
+    ChapGenChallenge(cstate);
+    ChapSendChallenge(cstate);		/* crank it up dude! */
+    cstate->serverstate = CHAPSS_INITIAL_CHAL;
+}
+
+
+/*
+ * ChapChallengeTimeout - Timeout expired on sending challenge.
+ */
+static void
+ChapChallengeTimeout(arg)
+    void *arg;
+{
+    chap_state *cstate = (chap_state *) arg;
+  
+    /* if we aren't sending challenges, don't worry.  then again we */
+    /* probably shouldn't be here either */
+    if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
+	cstate->serverstate != CHAPSS_RECHALLENGE)
+	return;
+
+    if (cstate->chal_transmits >= cstate->max_transmits) {
+	/* give up on peer */
+	error("Peer failed to respond to CHAP challenge");
+	cstate->serverstate = CHAPSS_BADAUTH;
+	auth_peer_fail(cstate->unit, PPP_CHAP);
+	return;
+    }
+
+    ChapSendChallenge(cstate);		/* Re-send challenge */
+}
+
+
+/*
+ * ChapResponseTimeout - Timeout expired on sending response.
+ */
+static void
+ChapResponseTimeout(arg)
+    void *arg;
+{
+    chap_state *cstate = (chap_state *) arg;
+
+    /* if we aren't sending a response, don't worry. */
+    if (cstate->clientstate != CHAPCS_RESPONSE)
+	return;
+
+    ChapSendResponse(cstate);		/* re-send response */
+}
+
+
+/*
+ * ChapRechallenge - Time to challenge the peer again.
+ */
+static void
+ChapRechallenge(arg)
+    void *arg;
+{
+    chap_state *cstate = (chap_state *) arg;
+
+    /* if we aren't sending a response, don't worry. */
+    if (cstate->serverstate != CHAPSS_OPEN)
+	return;
+
+    ChapGenChallenge(cstate);
+    ChapSendChallenge(cstate);
+    cstate->serverstate = CHAPSS_RECHALLENGE;
+}
+
+
+/*
+ * ChapLowerUp - The lower layer is up.
+ *
+ * Start up if we have pending requests.
+ */
+static void
+ChapLowerUp(unit)
+    int unit;
+{
+    chap_state *cstate = &chap[unit];
+  
+    if (cstate->clientstate == CHAPCS_INITIAL)
+	cstate->clientstate = CHAPCS_CLOSED;
+    else if (cstate->clientstate == CHAPCS_PENDING)
+	cstate->clientstate = CHAPCS_LISTEN;
+
+    if (cstate->serverstate == CHAPSS_INITIAL)
+	cstate->serverstate = CHAPSS_CLOSED;
+    else if (cstate->serverstate == CHAPSS_PENDING) {
+	ChapGenChallenge(cstate);
+	ChapSendChallenge(cstate);
+	cstate->serverstate = CHAPSS_INITIAL_CHAL;
+    }
+}
+
+
+/*
+ * ChapLowerDown - The lower layer is down.
+ *
+ * Cancel all timeouts.
+ */
+static void
+ChapLowerDown(unit)
+    int unit;
+{
+    chap_state *cstate = &chap[unit];
+  
+    /* Timeout(s) pending?  Cancel if so. */
+    if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
+	cstate->serverstate == CHAPSS_RECHALLENGE)
+	UNTIMEOUT(ChapChallengeTimeout, cstate);
+    else if (cstate->serverstate == CHAPSS_OPEN
+	     && cstate->chal_interval != 0)
+	UNTIMEOUT(ChapRechallenge, cstate);
+    if (cstate->clientstate == CHAPCS_RESPONSE)
+	UNTIMEOUT(ChapResponseTimeout, cstate);
+
+    cstate->clientstate = CHAPCS_INITIAL;
+    cstate->serverstate = CHAPSS_INITIAL;
+}
+
+
+/*
+ * ChapProtocolReject - Peer doesn't grok CHAP.
+ */
+static void
+ChapProtocolReject(unit)
+    int unit;
+{
+    chap_state *cstate = &chap[unit];
+
+    if (cstate->serverstate != CHAPSS_INITIAL &&
+	cstate->serverstate != CHAPSS_CLOSED)
+	auth_peer_fail(unit, PPP_CHAP);
+    if (cstate->clientstate != CHAPCS_INITIAL &&
+	cstate->clientstate != CHAPCS_CLOSED)
+	auth_withpeer_fail(unit, PPP_CHAP);
+    ChapLowerDown(unit);		/* shutdown chap */
+}
+
+
+/*
+ * ChapInput - Input CHAP packet.
+ */
+static void
+ChapInput(unit, inpacket, packet_len)
+    int unit;
+    u_char *inpacket;
+    int packet_len;
+{
+    chap_state *cstate = &chap[unit];
+    u_char *inp;
+    u_char code, id;
+    int len;
+  
+    /*
+     * Parse header (code, id and length).
+     * If packet too short, drop it.
+     */
+    inp = inpacket;
+    if (packet_len < CHAP_HEADERLEN) {
+	CHAPDEBUG(("ChapInput: rcvd short header."));
+	return;
+    }
+    GETCHAR(code, inp);
+    GETCHAR(id, inp);
+    GETSHORT(len, inp);
+    if (len < CHAP_HEADERLEN) {
+	CHAPDEBUG(("ChapInput: rcvd illegal length."));
+	return;
+    }
+    if (len > packet_len) {
+	CHAPDEBUG(("ChapInput: rcvd short packet."));
+	return;
+    }
+    len -= CHAP_HEADERLEN;
+  
+    /*
+     * Action depends on code (as in fact it usually does :-).
+     */
+    switch (code) {
+    case CHAP_CHALLENGE:
+	ChapReceiveChallenge(cstate, inp, id, len);
+	break;
+    
+    case CHAP_RESPONSE:
+	ChapReceiveResponse(cstate, inp, id, len);
+	break;
+    
+    case CHAP_FAILURE:
+	ChapReceiveFailure(cstate, inp, id, len);
+	break;
+
+    case CHAP_SUCCESS:
+	ChapReceiveSuccess(cstate, inp, id, len);
+	break;
+
+    default:				/* Need code reject? */
+	warn("Unknown CHAP code (%d) received.", code);
+	break;
+    }
+}
+
+
+/*
+ * ChapReceiveChallenge - Receive Challenge and send Response.
+ */
+static void
+ChapReceiveChallenge(cstate, inp, id, len)
+    chap_state *cstate;
+    u_char *inp;
+    int id;
+    int len;
+{
+    int rchallenge_len;
+    u_char *rchallenge;
+    int secret_len;
+    char secret[MAXSECRETLEN];
+    char rhostname[256];
+    MD5_CTX mdContext;
+    u_char hash[MD5_SIGNATURE_SIZE];
+ 
+    if (cstate->clientstate == CHAPCS_CLOSED ||
+	cstate->clientstate == CHAPCS_PENDING) {
+	CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate));
+	return;
+    }
+
+    if (len < 2) {
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
+	return;
+    }
+
+    GETCHAR(rchallenge_len, inp);
+    len -= sizeof (u_char) + rchallenge_len;	/* now name field length */
+    if (len < 0) {
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
+	return;
+    }
+    rchallenge = inp;
+    INCPTR(rchallenge_len, inp);
+
+    if (len >= sizeof(rhostname))
+	len = sizeof(rhostname) - 1;
+    BCOPY(inp, rhostname, len);
+    rhostname[len] = '\000';
+
+    /* Microsoft doesn't send their name back in the PPP packet */
+    if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) {
+	strlcpy(rhostname, remote_name, sizeof(rhostname));
+	CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name",
+		   rhostname));
+    }
+
+    /* get secret for authenticating ourselves with the specified host */
+    if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
+		    secret, &secret_len, 0)) {
+	secret_len = 0;		/* assume null secret if can't find one */
+	warn("No CHAP secret found for authenticating us to %q", rhostname);
+    }
+
+    /* cancel response send timeout if necessary */
+    if (cstate->clientstate == CHAPCS_RESPONSE)
+	UNTIMEOUT(ChapResponseTimeout, cstate);
+
+    cstate->resp_id = id;
+    cstate->resp_transmits = 0;
+
+    /*  generate MD based on negotiated type */
+    switch (cstate->resp_type) { 
+
+    case CHAP_DIGEST_MD5:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type CHAP-DIGEST-MD5"));
+	MD5Init(&mdContext);
+	MD5Update(&mdContext, &cstate->resp_id, 1);
+	MD5Update(&mdContext, secret, secret_len);
+	MD5Update(&mdContext, rchallenge, rchallenge_len);
+	MD5Final(hash, &mdContext);
+	BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
+	cstate->resp_length = MD5_SIGNATURE_SIZE;
+	break;
+
+#ifdef CHAPMS
+    case CHAP_MICROSOFT:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V1."));
+	if(rchallenge_len != 8)
+	{
+	    CHAPDEBUG(("Invalid challenge length for MS-CHAP-V1"));
+	    return;
+	}
+	ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
+	break;
+
+    case CHAP_MICROSOFT_V2:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V2."));
+	if(rchallenge_len != 16)
+	{
+	    CHAPDEBUG(("Invalid challenge length for MS-CHAP-V2"));
+	    return;
+	}
+	ChapMS_v2(cstate, rchallenge, rchallenge_len, secret, secret_len);
+	break;
+#endif
+
+    default:
+	CHAPDEBUG(("unknown digest type %d", cstate->resp_type));
+	return;
+    }
+
+    BZERO(secret, sizeof(secret));
+    ChapSendResponse(cstate);
+}
+
+
+/*
+ * ChapReceiveResponse - Receive and process response.
+ */
+static void
+ChapReceiveResponse(cstate, inp, id, len)
+    chap_state *cstate;
+    u_char *inp;
+    int id;
+    int len;
+{
+    u_char *remmd, remmd_len;
+    int secret_len, old_state;
+    int code;
+    char rhostname[256];
+    MD5_CTX mdContext;
+    char secret[MAXSECRETLEN];
+    u_char hash[MD5_SIGNATURE_SIZE];
+
+    if (cstate->serverstate == CHAPSS_CLOSED ||
+	cstate->serverstate == CHAPSS_PENDING) {
+	CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
+	return;
+    }
+
+    if (id != cstate->chal_id)
+	return;			/* doesn't match ID of last challenge */
+
+    /*
+     * If we have received a duplicate or bogus Response,
+     * we have to send the same answer (Success/Failure)
+     * as we did for the first Response we saw.
+     */
+    if (cstate->serverstate == CHAPSS_OPEN) {
+	ChapSendStatus(cstate, CHAP_SUCCESS);
+	return;
+    }
+    if (cstate->serverstate == CHAPSS_BADAUTH) {
+	ChapSendStatus(cstate, CHAP_FAILURE);
+	return;
+    }
+
+    if (len < 2) {
+	CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
+	return;
+    }
+    GETCHAR(remmd_len, inp);		/* get length of MD */
+    remmd = inp;			/* get pointer to MD */
+    INCPTR(remmd_len, inp);
+
+    len -= sizeof (u_char) + remmd_len;
+    if (len < 0) {
+	CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
+	return;
+    }
+
+    UNTIMEOUT(ChapChallengeTimeout, cstate);
+
+    if (len >= sizeof(rhostname))
+	len = sizeof(rhostname) - 1;
+    BCOPY(inp, rhostname, len);
+    rhostname[len] = '\000';
+
+    /*
+     * Get secret for authenticating them with us,
+     * do the hash ourselves, and compare the result.
+     */
+    code = CHAP_FAILURE;
+    if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname),
+		    cstate->chal_name, secret, &secret_len, 1)) {
+	warn("No CHAP secret found for authenticating %q", rhostname);
+    } else {
+
+	/*  generate MD based on negotiated type */
+	switch (cstate->chal_type) { 
+
+	case CHAP_DIGEST_MD5:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type CHAP-DIGEST-MD5"));
+	    if (remmd_len != MD5_SIGNATURE_SIZE)
+		break;			/* it's not even the right length */
+	    MD5Init(&mdContext);
+	    MD5Update(&mdContext, &cstate->chal_id, 1);
+	    MD5Update(&mdContext, secret, secret_len);
+	    MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
+	    MD5Final(hash, &mdContext); 
+
+	    /* compare local and remote MDs and send the appropriate status */
+	    if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
+		code = CHAP_SUCCESS;	/* they are the same! */
+	    break;
+
+#ifdef CHAPMS
+	case CHAP_MICROSOFT:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V1"));
+	    if(remmd_len != MS_CHAP_RESPONSE_LEN)
+		break;
+	    if(ChapMS_Resp(cstate, secret, secret_len, remmd) == 0)
+		code = CHAP_SUCCESS;
+	    break;
+
+	case CHAP_MICROSOFT_V2:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V2"));
+	    if(remmd_len != MS_CHAP_RESPONSE_LEN)
+		break;
+	    if(ChapMS_v2_Resp(cstate,secret,secret_len,remmd,rhostname) == 0)
+	    {
+		code = CHAP_SUCCESS_R;
+		ChapMS_v2_Auth(cstate, secret, secret_len, remmd, rhostname);
+	    }
+	    break;
+#endif
+
+	default:
+	    CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
+	}
+    }
+
+    BZERO(secret, sizeof(secret));
+    ChapSendStatus(cstate, code);
+
+    if ((code == CHAP_SUCCESS) || (code == CHAP_SUCCESS_R)) {
+	old_state = cstate->serverstate;
+	cstate->serverstate = CHAPSS_OPEN;
+	if (old_state == CHAPSS_INITIAL_CHAL) {
+	    auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
+	}
+	if (cstate->chal_interval != 0)
+	    TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
+	switch (cstate->chal_type) { 
+	  case CHAP_DIGEST_MD5:
+	    notice("CHAP peer authentication succeeded for %q", rhostname);
+	    break;
+#ifdef CHAPMS
+	  case CHAP_MICROSOFT:
+	    notice("MSCHAP peer authentication succeeded for %q", rhostname);
+	    break;
+	  case CHAP_MICROSOFT_V2:
+	    notice("MSCHAP-v2 peer authentication succeeded for %q", rhostname);
+	    break;
+#endif
+	  default:
+	    notice("CHAP (unknown) peer authentication succeeded for %q", 
+		   rhostname);
+	    break;
+	}
+    } else {
+	switch (cstate->chal_type) { 
+	  case CHAP_DIGEST_MD5:
+	    error("CHAP peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+#ifdef CHAPMS
+	  case CHAP_MICROSOFT:
+	    error("MSCHAP peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+	  case CHAP_MICROSOFT_V2:
+	    error("MSCHAP-v2 peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+#endif
+	  default:
+	    error("CHAP (unknown) peer authentication failed for remote host %q", rhostname);
+	    break;
+	}
+	cstate->serverstate = CHAPSS_BADAUTH;
+	auth_peer_fail(cstate->unit, PPP_CHAP);
+    }
+}
+
+/*
+ * ChapReceiveSuccess - Receive Success
+ */
+static void
+ChapReceiveSuccess(cstate, inp, id, len)
+    chap_state *cstate;
+    u_char *inp;
+    u_char id;
+    int len;
+{
+
+    if (cstate->clientstate == CHAPCS_OPEN)
+	/* presumably an answer to a duplicate response */
+	return;
+
+    if (cstate->clientstate != CHAPCS_RESPONSE) {
+	/* don't know what this is */
+	CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate));
+	return;
+    }
+
+    UNTIMEOUT(ChapResponseTimeout, cstate);
+
+    /*
+     * Print message.
+     */
+    if (len > 0)
+	PRINTMSG(inp, len);
+
+    cstate->clientstate = CHAPCS_OPEN;
+
+    auth_withpeer_success(cstate->unit, PPP_CHAP);
+}
+
+
+/*
+ * ChapReceiveFailure - Receive failure.
+ */
+static void
+ChapReceiveFailure(cstate, inp, id, len)
+    chap_state *cstate;
+    u_char *inp;
+    u_char id;
+    int len;
+{
+    if (cstate->clientstate != CHAPCS_RESPONSE) {
+	/* don't know what this is */
+	CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate));
+	return;
+    }
+
+    UNTIMEOUT(ChapResponseTimeout, cstate);
+
+    /*
+     * Print message.
+     */
+    if (len > 0)
+	PRINTMSG(inp, len);
+
+    error("CHAP authentication failed");
+
+    //log_to_file("CHAP_AUTH_FAIL");
+    system("ppp_event -t CHAP_AUTH_FAIL &");
+
+    auth_withpeer_fail(cstate->unit, PPP_CHAP);
+}
+
+
+/*
+ * ChapSendChallenge - Send an Authenticate challenge.
+ */
+static void
+ChapSendChallenge(cstate)
+    chap_state *cstate;
+{
+    u_char *outp;
+    int chal_len, name_len;
+    int outlen;
+
+    chal_len = cstate->chal_len;
+    name_len = strlen(cstate->chal_name);
+    outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
+    outp = outpacket_buf;
+
+    MAKEHEADER(outp, PPP_CHAP);		/* paste in a CHAP header */
+
+    PUTCHAR(CHAP_CHALLENGE, outp);
+    PUTCHAR(cstate->chal_id, outp);
+    PUTSHORT(outlen, outp);
+
+    PUTCHAR(chal_len, outp);		/* put length of challenge */
+    BCOPY(cstate->challenge, outp, chal_len);
+    INCPTR(chal_len, outp);
+
+    BCOPY(cstate->chal_name, outp, name_len);	/* append hostname */
+
+    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+  
+    TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
+    ++cstate->chal_transmits;
+}
+
+
+/*
+ * ChapSendStatus - Send a status response (ack or nak).
+ */
+static void
+ChapSendStatus(cstate, code)
+    chap_state *cstate;
+    int code;
+{
+    u_char *outp;
+    int outlen, msglen;
+    char msg[256];
+
+    if (code == CHAP_SUCCESS)
+	slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
+    else if(code == CHAP_SUCCESS_R)
+	strcpy(msg, cstate->response);
+    else
+	slprintf(msg, sizeof(msg), "I don't like you.  Go 'way.");
+    msglen = strlen(msg);
+
+    outlen = CHAP_HEADERLEN + msglen;
+    outp = outpacket_buf;
+
+    MAKEHEADER(outp, PPP_CHAP);	/* paste in a header */
+  
+    PUTCHAR(code == CHAP_SUCCESS_R ? CHAP_SUCCESS : code, outp);
+    PUTCHAR(cstate->chal_id, outp);
+    PUTSHORT(outlen, outp);
+    BCOPY(msg, outp, msglen);
+    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
+
+/*
+ * ChapGenChallenge is used to generate a pseudo-random challenge string of
+ * a pseudo-random length between min_len and max_len.  The challenge
+ * string and its length are stored in *cstate, and various other fields of
+ * *cstate are initialized.
+ */
+
+void
+ChapGenChallenge(cstate)
+    chap_state *cstate;
+{
+    int chal_len;
+    u_char *ptr = cstate->challenge;
+    int i;
+
+#ifdef CHAPMS
+    if(cstate->chal_type == CHAP_MICROSOFT)
+	chal_len = 8;
+    else if(cstate->chal_type == CHAP_MICROSOFT_V2)
+	chal_len = 16;
+    else
+#endif
+
+    /* pick a random challenge length between MIN_CHALLENGE_LENGTH and 
+       MAX_CHALLENGE_LENGTH */  
+    chal_len =  (unsigned) ((drand48() *
+			     (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
+			    MIN_CHALLENGE_LENGTH);
+    cstate->chal_len = chal_len;
+    cstate->chal_id = ++cstate->id;
+    cstate->chal_transmits = 0;
+
+    /* generate a random string */
+    for (i = 0; i < chal_len; i++)
+	*ptr++ = (char) (drand48() * 0xff);
+}
+
+/*
+ * ChapSendResponse - send a response packet with values as specified
+ * in *cstate.
+ */
+/* ARGSUSED */
+static void
+ChapSendResponse(cstate)
+    chap_state *cstate;
+{
+    u_char *outp;
+    int outlen, md_len, name_len;
+
+    md_len = cstate->resp_length;
+    name_len = strlen(cstate->resp_name);
+    outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
+    outp = outpacket_buf;
+
+    MAKEHEADER(outp, PPP_CHAP);
+
+    PUTCHAR(CHAP_RESPONSE, outp);	/* we are a response */
+    PUTCHAR(cstate->resp_id, outp);	/* copy id from challenge packet */
+    PUTSHORT(outlen, outp);		/* packet length */
+
+    PUTCHAR(md_len, outp);		/* length of MD */
+    BCOPY(cstate->response, outp, md_len);	/* copy MD to buffer */
+    INCPTR(md_len, outp);
+
+    BCOPY(cstate->resp_name, outp, name_len); /* append our name */
+
+    /* send the packet */
+    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+
+    cstate->clientstate = CHAPCS_RESPONSE;
+    TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
+    ++cstate->resp_transmits;
+}
+
+/*
+ * ChapPrintPkt - print the contents of a CHAP packet.
+ */
+static char *ChapCodenames[] = {
+    "Challenge", "Response", "Success", "Failure"
+};
+
+static int
+ChapPrintPkt(p, plen, printer, arg)
+    u_char *p;
+    int plen;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int code, id, len;
+    int clen, nlen;
+    u_char x;
+
+    if (plen < CHAP_HEADERLEN)
+	return 0;
+    GETCHAR(code, p);
+    GETCHAR(id, p);
+    GETSHORT(len, p);
+    if (len < CHAP_HEADERLEN || len > plen)
+	return 0;
+
+    if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
+	printer(arg, " %s", ChapCodenames[code-1]);
+    else
+	printer(arg, " code=0x%x", code);
+    printer(arg, " id=0x%x", id);
+    len -= CHAP_HEADERLEN;
+    switch (code) {
+    case CHAP_CHALLENGE:
+    case CHAP_RESPONSE:
+	if (len < 1)
+	    break;
+	clen = p[0];
+	if (len < clen + 1)
+	    break;
+	++p;
+	nlen = len - clen - 1;
+	printer(arg, " <");
+	for (; clen > 0; --clen) {
+	    GETCHAR(x, p);
+	    printer(arg, "%.2x", x);
+	}
+	printer(arg, ">, name = ");
+	print_string((char *)p, nlen, printer, arg);
+	break;
+    case CHAP_FAILURE:
+    case CHAP_SUCCESS:
+	printer(arg, " ");
+	print_string((char *)p, len, printer, arg);
+	break;
+    default:
+	for (clen = len; clen > 0; --clen) {
+	    GETCHAR(x, p);
+	    printer(arg, " %.2x", x);
+	}
+    }
+
+    return len + CHAP_HEADERLEN;
+}
+
+int
+reqchap(argv)
+        char **argv;
+{
+    lcp_wantoptions[0].neg_chap = 1;
+    lcp_wantoptions[0].use_digest = 1;
+    auth_required = 1;
+    return 1;
+}
diff --git a/ap/app/ppp-2.4.1/pppd/chap.h b/ap/app/ppp-2.4.1/pppd/chap.h
new file mode 100644
index 0000000..3fa0d8c
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/chap.h
@@ -0,0 +1,129 @@
+/*
+ * chap.h - Challenge Handshake Authentication Protocol definitions.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University.  The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1991 Gregory M. Christy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: chap.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+#ifndef __CHAP_INCLUDE__
+
+/* Code + ID + length */
+#define CHAP_HEADERLEN		4
+
+/*
+ * CHAP codes.
+ */
+
+#define CHAP_DIGEST_MD5		5	/* use MD5 algorithm */
+#define MD5_SIGNATURE_SIZE	16	/* 16 bytes in a MD5 message digest */
+#define CHAP_MICROSOFT		0x80	/* use Microsoft-compatible alg. */
+#define MS_CHAP_RESPONSE_LEN	49	/* Response length for MS-CHAP */
+#define CHAP_MICROSOFT_V2	0x81	/* use MS-CHAP v2 */
+
+#define CHAP_CHALLENGE		1
+#define CHAP_RESPONSE		2
+#define CHAP_SUCCESS		3
+#define CHAP_FAILURE    	4
+#define CHAP_SUCCESS_R		13	/* Send response, not text message */
+
+/*
+ *  Challenge lengths (for challenges we send) and other limits.
+ */
+#define MIN_CHALLENGE_LENGTH	16
+#define MAX_CHALLENGE_LENGTH	24
+#define MAX_RESPONSE_LENGTH	64	/* sufficient for MD5 or MS-CHAP */
+
+/*
+ * Each interface is described by a chap structure.
+ */
+
+typedef struct chap_state {
+    int unit;			/* Interface unit number */
+    int clientstate;		/* Client state */
+    int serverstate;		/* Server state */
+    u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
+    u_char chal_len;		/* challenge length */
+    u_char chal_id;		/* ID of last challenge */
+    u_char chal_type;		/* hash algorithm for challenges */
+    u_char id;			/* Current id */
+    char *chal_name;		/* Our name to use with challenge */
+    int chal_interval;		/* Time until we challenge peer again */
+    int timeouttime;		/* Timeout time in seconds */
+    int max_transmits;		/* Maximum # of challenge transmissions */
+    int chal_transmits;		/* Number of transmissions of challenge */
+    int resp_transmits;		/* Number of transmissions of response */
+    u_char response[MAX_RESPONSE_LENGTH];	/* Response to send */
+    u_char resp_length;		/* length of response */
+    u_char resp_id;		/* ID for response messages */
+    u_char resp_type;		/* hash algorithm for responses */
+    char *resp_name;		/* Our name to send with response */
+} chap_state;
+
+
+/*
+ * Client (peer) states.
+ */
+#define CHAPCS_INITIAL		0	/* Lower layer down, not opened */
+#define CHAPCS_CLOSED		1	/* Lower layer up, not opened */
+#define CHAPCS_PENDING		2	/* Auth us to peer when lower up */
+#define CHAPCS_LISTEN		3	/* Listening for a challenge */
+#define CHAPCS_RESPONSE		4	/* Sent response, waiting for status */
+#define CHAPCS_OPEN		5	/* We've received Success */
+
+/*
+ * Server (authenticator) states.
+ */
+#define CHAPSS_INITIAL		0	/* Lower layer down, not opened */
+#define CHAPSS_CLOSED		1	/* Lower layer up, not opened */
+#define CHAPSS_PENDING		2	/* Auth peer when lower up */
+#define CHAPSS_INITIAL_CHAL	3	/* We've sent the first challenge */
+#define CHAPSS_OPEN		4	/* We've sent a Success msg */
+#define CHAPSS_RECHALLENGE	5	/* We've sent another challenge */
+#define CHAPSS_BADAUTH		6	/* We've sent a Failure msg */
+
+/*
+ * Timeouts.
+ */
+#define CHAP_DEFTIMEOUT		3	/* Timeout time in seconds */
+#define CHAP_DEFTRANSMITS	10	/* max # times to send challenge */
+
+extern chap_state chap[];
+
+void ChapAuthWithPeer __P((int, char *, int));
+void ChapAuthPeer __P((int, char *, int));
+void ChapGenChallenge __P((chap_state *));
+
+int reqchap(char **);
+
+extern struct protent chap_protent;
+
+#define __CHAP_INCLUDE__
+#endif /* __CHAP_INCLUDE__ */
diff --git a/ap/app/ppp-2.4.1/pppd/chap_ms.c b/ap/app/ppp-2.4.1/pppd/chap_ms.c
new file mode 100644
index 0000000..aea9dac
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/chap_ms.c
@@ -0,0 +1,366 @@
+/*
+ * chap_ms.c - Microsoft MS-CHAP compatible implementation.
+ *
+ * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
+ * http://www.strataware.com/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Eric Rosenquist.  The name of the author may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
+ *
+ *   Implemented LANManager type password response to MS-CHAP challenges.
+ *   Now pppd provides both NT style and LANMan style blocks, and the
+ *   prefered is set by option "ms-lanman". Default is to use NT.
+ *   The hash text (StdText) was taken from Win95 RASAPI32.DLL.
+ *
+ *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
+ */
+
+#define RCSID	"$Id: chap_ms.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+#ifdef CHAPMS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#include "pppd.h"
+#include "chap.h"
+#include "chap_ms.h"
+#include <openssl/sha.h>
+#include "fsm.h"
+#include "lcp.h"
+#ifdef MPPE
+#include "mppe.h"
+#endif
+#include "extra_crypto.h"
+
+static const char rcsid[] = RCSID;
+
+typedef struct {
+    u_char LANManResp[24];
+    u_char NTResp[24];
+    u_char UseNT;		/* If 1, ignore the LANMan response field */
+} MS_ChapResponse;
+/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
+   in case this struct gets padded. */
+
+typedef struct {
+    u_char PeerChallenge[16];
+    u_char Reserved[8];
+    u_char NTResp[24];
+    u_char Flags;
+} MS_ChapResponse_v2;
+
+static void	ChallengeResponse __P((u_char *, u_char *, u_char *));
+static void	ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *));
+#ifdef MSLANMAN
+static void	ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
+#endif
+
+#ifdef MSLANMAN
+bool	ms_lanman = 0;    	/* Use LanMan password instead of NT */
+			  	/* Has meaning only with MS-CHAP challenges */
+#endif
+
+static void
+ChallengeResponse(challenge, pwHash, response)
+    u_char *challenge;	/* IN   8 octets */
+    u_char *pwHash;	/* IN  16 octets */
+    u_char *response;	/* OUT 24 octets */
+{
+    char    ZPasswordHash[21];
+
+    BZERO(ZPasswordHash, sizeof(ZPasswordHash));
+    BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
+
+
+    DesEncrypt(challenge, ZPasswordHash +  0, response + 0);
+    DesEncrypt(challenge, ZPasswordHash +  7, response + 8);
+    DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
+
+}
+
+
+static void
+ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
+    char *rchallenge;
+    int rchallenge_len;
+    char *secret;
+    int secret_len;
+    MS_ChapResponse    *response;
+{
+    u_char		hash[MD4_SIGNATURE_SIZE];
+
+    NtPasswordHash(secret, secret_len, hash);
+    ChallengeResponse(rchallenge, hash, response->NTResp);
+}
+
+#ifdef MSLANMAN
+static void
+ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
+    char *rchallenge;
+    int rchallenge_len;
+    char *secret;
+    int secret_len;
+    MS_ChapResponse	*response;
+{
+    u_char		PasswordHash[MD4_SIGNATURE_SIZE];
+
+    LmPasswordHash(secret, secret_len, PasswordHash);
+    ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
+}
+#endif
+
+void
+ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
+    chap_state *cstate;
+    char *rchallenge;
+    int rchallenge_len;
+    char *secret;
+    int secret_len;
+{
+    MS_ChapResponse	response;
+
+    BZERO(&response, sizeof(response));
+
+    /* Calculate both always */
+    ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+#ifdef MSLANMAN
+    ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+    /* prefered method is set by option  */
+    response.UseNT = !ms_lanman;
+#else
+    response.UseNT = 1;
+#endif
+
+#ifdef MPPE
+    mppe_gen_master_key(secret, secret_len, rchallenge);
+#endif
+    BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
+    cstate->resp_length = MS_CHAP_RESPONSE_LEN;
+}
+
+int
+ChapMS_Resp(cstate, secret, secret_len, remmd)
+    chap_state *cstate;
+    char *secret;
+    int secret_len;
+    u_char *remmd;
+{
+    MS_ChapResponse local;
+    MS_ChapResponse *response = (MS_ChapResponse *)remmd;
+    int i;
+
+    BZERO(&local, sizeof(response));
+
+    if(response->UseNT)
+    {
+      ChapMS_NT(cstate->challenge,cstate->chal_len, secret, secret_len, &local);
+      i = memcmp(local.NTResp, response->NTResp, sizeof(local.NTResp));
+
+#ifdef MPPE
+      if(i == 0)
+        mppe_gen_master_key(secret, secret_len, cstate->challenge);
+#endif
+      return(i);
+    }
+
+#ifdef MSLANMAN
+    ChapMS_LANMan(cstate->challenge, cstate->chal_len, secret, secret_len, 
+		&local);
+    if(memcmp(local.LANManResp, response->LANManResp, 
+	sizeof(local.LANManResp)) == 0) {
+#ifdef MPPE
+      mppe_gen_master_key(secret, secret_len, cstate->challenge);
+#endif
+      return(0);
+    }
+#endif /* MSLANMAN */
+    return(1);
+}
+
+void
+ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge)
+    char *PeerChallenge;
+    char *AuthenticatorChallenge;
+    char *UserName;
+    char *Challenge;
+{
+    SHA_CTX Context;
+    u_char Digest[SHA_DIGEST_LENGTH];
+    char *username;
+    
+    if((username = strrchr(UserName, '\\')) != (char *)NULL)
+      ++username;
+    else
+      username = UserName;
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, PeerChallenge, 16);
+    SHA1_Update(&Context, AuthenticatorChallenge, 16);
+    SHA1_Update(&Context, username, strlen(username));
+    SHA1_Final(Digest, &Context);
+    BCOPY(Digest, Challenge, 8);
+}
+
+void
+ChapMS_v2(cstate, AuthenticatorChallenge, AuthenticatorChallengeLen, Password, PasswordLen)
+    chap_state *cstate;
+    char *AuthenticatorChallenge;
+    int AuthenticatorChallengeLen;
+    char *Password;
+    int PasswordLen;
+{
+    u_char Challenge[8];
+    u_char PasswordHash[MD4_SIGNATURE_SIZE];
+    MS_ChapResponse_v2 response;
+  
+    BZERO(&response, sizeof(response));
+    ChapGenChallenge(cstate);
+    BCOPY(cstate->challenge, response.PeerChallenge, 
+		sizeof(response.PeerChallenge));
+    ChallengeHash(response.PeerChallenge, AuthenticatorChallenge, 
+		cstate->resp_name, Challenge);
+    NtPasswordHash(Password, PasswordLen, PasswordHash);
+    ChallengeResponse(Challenge, PasswordHash, response.NTResp);
+    BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
+    cstate->resp_length = MS_CHAP_RESPONSE_LEN;
+#ifdef MPPE
+    mppe_gen_master_key_v2(Password, PasswordLen, response.NTResp, 0);
+#endif
+}
+
+int
+ChapMS_v2_Resp(cstate, Password, PasswordLen, remmd, UserName)
+    chap_state *cstate;
+    char *Password;
+    int PasswordLen;
+    u_char *remmd;
+    char *UserName;
+{
+    u_char Challenge[8];
+    u_char PasswordHash[MD4_SIGNATURE_SIZE];
+    MS_ChapResponse_v2 response, response1;
+    int i;
+  
+    BCOPY(remmd, &response, MS_CHAP_RESPONSE_LEN);
+    ChallengeHash(response.PeerChallenge,cstate->challenge,UserName,Challenge);
+    NtPasswordHash(Password, PasswordLen, PasswordHash);
+    ChallengeResponse(Challenge, PasswordHash, response1.NTResp);
+    i = memcmp(response.NTResp, response1.NTResp, sizeof(response.NTResp));
+#ifdef MPPE
+    if(i == 0)
+      mppe_gen_master_key_v2(Password, PasswordLen, response1.NTResp, 1);
+#endif
+    return(i);
+}
+
+void
+ChapMS_v2_Auth(cstate, Password, PasswordLen, remmd, UserName)
+    chap_state *cstate;
+    char *Password;
+    int  PasswordLen;
+    u_char *remmd;
+    char *UserName;
+{
+    u_char PasswordHash[MD4_SIGNATURE_SIZE];
+    u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
+    u_char Challenge[8];
+    static char Magic1[] = "Magic server to client signing constant";
+    static char Magic2[] = "Pad to make it do more than one iteration";
+
+    SHA_CTX Context;
+    u_char Digest[SHA_DIGEST_LENGTH];
+    MS_ChapResponse_v2 *response = (MS_ChapResponse_v2 *)remmd;
+    char   StrResponse[SHA_DIGEST_LENGTH * 2 + 3], *s;
+    int i;
+    static char HexDigs[] = "0123456789ABCDEF";
+    
+    NtPasswordHash(Password, PasswordLen, PasswordHash);
+    md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
+
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, PasswordHashHash, 16);
+    SHA1_Update(&Context, response->NTResp, 24);
+    SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1);
+    SHA1_Final(Digest, &Context);
+
+    ChallengeHash(response->PeerChallenge,cstate->challenge,UserName,Challenge);
+    
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, Digest, SHA_DIGEST_LENGTH);
+    SHA1_Update(&Context, Challenge, 8);
+    SHA1_Update(&Context, Magic2, sizeof(Magic2) - 1);
+    SHA1_Final(Digest, &Context);
+    s = stpcpy(StrResponse, "S=");
+    for(i = 0; i < SHA_DIGEST_LENGTH; ++i) {
+      *s++ = HexDigs[Digest[i] >> 4];
+      *s++ = HexDigs[Digest[i] & 0x0F];
+    }
+    *s = '\0';
+    BCOPY(StrResponse, cstate->response, sizeof(StrResponse));
+    cstate->resp_length = sizeof(StrResponse) - 1;
+}
+
+/*
+ * functions called from config options
+ */
+int 
+reqchapms(char **argv)
+{
+    lcp_wantoptions[0].neg_chap = 1;
+    lcp_wantoptions[0].use_chapms = 1;
+    auth_required = 1;
+
+    return 1;
+}
+
+int 
+nochapms(char **argv)
+{
+    lcp_wantoptions[0].use_chapms = 0;
+    return 1;
+}
+
+int 
+reqchapms_v2(char **argv)
+{
+    lcp_wantoptions[0].neg_chap = 1;
+    lcp_wantoptions[0].use_chapms_v2 = 1;
+    auth_required = 1;
+
+    return 1;
+}
+
+int 
+nochapms_v2(char **argv)
+{
+    lcp_wantoptions[0].use_chapms_v2 = 0;
+    return 1;
+}
+
+#endif /* CHAPMS */
diff --git a/ap/app/ppp-2.4.1/pppd/chap_ms.h b/ap/app/ppp-2.4.1/pppd/chap_ms.h
new file mode 100644
index 0000000..0a009ee
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/chap_ms.h
@@ -0,0 +1,39 @@
+/*
+ * chap.h - Challenge Handshake Authentication Protocol definitions.
+ *
+ * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
+ * http://www.strataware.com/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Eric Rosenquist.  The name of the author may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: chap_ms.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+#ifndef __CHAPMS_INCLUDE__
+
+void ChapMS __P((chap_state *, char *, int, char *, int));
+int  ChapMS_Resp __P((chap_state *, char *, int, u_char *));
+void ChapMS_v2 __P((chap_state *, char *, int, char *, int));
+int  ChapMS_v2_Resp __P((chap_state *, char *, int, u_char *, char *));
+void ChapMS_v2_Auth __P((chap_state *, char *, int, u_char *, char *));
+
+int reqchapms(char **);
+int nochapms(char **);
+int reqchapms_v2(char **);
+int nochapms_v2(char **);
+
+#define __CHAPMS_INCLUDE__
+#endif /* __CHAPMS_INCLUDE__ */
diff --git a/ap/app/ppp-2.4.1/pppd/demand.c b/ap/app/ppp-2.4.1/pppd/demand.c
new file mode 100644
index 0000000..ae55aac
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/demand.c
@@ -0,0 +1,351 @@
+/*
+ * demand.c - Support routines for demand-dialling.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University.  The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: demand.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef PPP_FILTER
+#include <net/if.h>
+#include <net/bpf.h>
+#include <pcap.h>
+#endif
+
+#include <pppd.h>
+#include "fsm.h"
+#include "ipcp.h"
+#include "lcp.h"
+
+static const char rcsid[] = RCSID;
+
+char *frame;
+int framelen;
+int framemax;
+int escape_flag;
+int flush_flag;
+int fcs;
+
+struct packet {
+    int length;
+    struct packet *next;
+    unsigned char data[1];
+};
+
+struct packet *pend_q;
+struct packet *pend_qtail;
+
+static int active_packet __P((unsigned char *, int));
+
+/*
+ * demand_conf - configure the interface for doing dial-on-demand.
+ */
+void
+demand_conf()
+{
+    int i;
+    struct protent *protp;
+
+/*    framemax = lcp_allowoptions[0].mru;
+    if (framemax < PPP_MRU) */
+	framemax = PPP_MRU;
+    framemax += PPP_HDRLEN + PPP_FCSLEN;
+    frame = malloc(framemax);
+    if (frame == NULL)
+	novm("demand frame");
+    framelen = 0;
+    pend_q = NULL;
+    escape_flag = 0;
+    flush_flag = 0;
+    fcs = PPP_INITFCS;
+
+    netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
+    ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
+    ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
+
+#ifdef PPP_FILTER
+    set_filters(&pass_filter, &active_filter);
+#endif
+
+    /*
+     * Call the demand_conf procedure for each protocol that's got one.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->enabled_flag && protp->demand_conf != NULL)
+	    if (!((*protp->demand_conf)(0)))
+		die(1);
+}
+
+
+/*
+ * demand_block - set each network protocol to block further packets.
+ */
+void
+demand_block()
+{
+    int i;
+    struct protent *protp;
+
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->enabled_flag && protp->demand_conf != NULL)
+	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
+    get_loop_output();
+}
+
+/*
+ * demand_discard - set each network protocol to discard packets
+ * with an error.
+ */
+void
+demand_discard()
+{
+    struct packet *pkt, *nextpkt;
+    int i;
+    struct protent *protp;
+
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->enabled_flag && protp->demand_conf != NULL)
+	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
+    get_loop_output();
+
+    /* discard all saved packets */
+    for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
+	nextpkt = pkt->next;
+	free(pkt);
+    }
+    pend_q = NULL;
+    framelen = 0;
+    flush_flag = 0;
+    escape_flag = 0;
+    fcs = PPP_INITFCS;
+}
+
+/*
+ * demand_unblock - set each enabled network protocol to pass packets.
+ */
+void
+demand_unblock()
+{
+    int i;
+    struct protent *protp;
+
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->enabled_flag && protp->demand_conf != NULL)
+	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
+}
+
+/*
+ * FCS lookup table as calculated by genfcstab.
+ */
+static u_short fcstab[256] = {
+	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
+	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
+	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
+	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
+	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
+	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
+	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
+	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
+	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
+	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
+	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
+	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
+	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
+	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
+	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
+	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
+	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
+	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
+	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
+	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
+	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
+	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
+	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
+	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
+	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
+	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
+	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
+	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
+	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
+	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
+	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
+	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
+};
+
+/*
+ * loop_chars - process characters received from the loopback.
+ * Calls loop_frame when a complete frame has been accumulated.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+loop_chars(p, n)
+    unsigned char *p;
+    int n;
+{
+    int c, rv;
+
+    rv = 0;
+    for (; n > 0; --n) {
+	c = *p++;
+	if (c == PPP_FLAG) {
+	    if (!escape_flag && !flush_flag
+		&& framelen > 2 && fcs == PPP_GOODFCS) {
+		framelen -= 2;
+		if (loop_frame((unsigned char *)frame, framelen))
+		    rv = 1;
+	    }
+	    framelen = 0;
+	    flush_flag = 0;
+	    escape_flag = 0;
+	    fcs = PPP_INITFCS;
+	    continue;
+	}
+	if (flush_flag)
+	    continue;
+	if (escape_flag) {
+	    c ^= PPP_TRANS;
+	    escape_flag = 0;
+	} else if (c == PPP_ESCAPE) {
+	    escape_flag = 1;
+	    continue;
+	}
+	if (framelen >= framemax) {
+	    flush_flag = 1;
+	    continue;
+	}
+	frame[framelen++] = c;
+	fcs = PPP_FCS(fcs, c);
+    }
+    return rv;
+}
+
+/*
+ * loop_frame - given a frame obtained from the loopback,
+ * decide whether to bring up the link or not, and, if we want
+ * to transmit this frame later, put it on the pending queue.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ * We assume that the kernel driver has already applied the
+ * pass_filter, so we won't get packets it rejected.
+ * We apply the active_filter to see if we want this packet to
+ * bring up the link.
+ */
+int
+loop_frame(frame, len)
+    unsigned char *frame;
+    int len;
+{
+    struct packet *pkt;
+
+    /* dbglog("from loop: %P", frame, len); */
+    if (len < PPP_HDRLEN)
+	return 0;
+    if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
+	return 0;		/* shouldn't get any of these anyway */
+    if (!active_packet(frame, len))
+	return 0;
+
+    pkt = (struct packet *) malloc(sizeof(struct packet) + len);
+    if (pkt != NULL) {
+	pkt->length = len;
+	pkt->next = NULL;
+	memcpy(pkt->data, frame, len);
+	if (pend_q == NULL)
+	    pend_q = pkt;
+	else
+	    pend_qtail->next = pkt;
+	pend_qtail = pkt;
+    }
+    return 1;
+}
+
+/*
+ * demand_rexmit - Resend all those frames which we got via the
+ * loopback, now that the real serial link is up.
+ */
+void
+demand_rexmit(proto)
+    int proto;
+{
+    struct packet *pkt, *prev, *nextpkt;
+
+    prev = NULL;
+    pkt = pend_q;
+    pend_q = NULL;
+    for (; pkt != NULL; pkt = nextpkt) {
+	nextpkt = pkt->next;
+	if (PPP_PROTOCOL(pkt->data) == proto) {
+	    output(0, pkt->data, pkt->length);
+	    free(pkt);
+	} else {
+	    if (prev == NULL)
+		pend_q = pkt;
+	    else
+		prev->next = pkt;
+	    prev = pkt;
+	}
+    }
+    pend_qtail = prev;
+    if (prev != NULL)
+	prev->next = NULL;
+}
+
+/*
+ * Scan a packet to decide whether it is an "active" packet,
+ * that is, whether it is worth bringing up the link for.
+ */
+static int
+active_packet(p, len)
+    unsigned char *p;
+    int len;
+{
+    int proto, i;
+    struct protent *protp;
+
+    if (len < PPP_HDRLEN)
+	return 0;
+    proto = PPP_PROTOCOL(p);
+#ifdef PPP_FILTER
+    if (pass_filter.bf_len != 0
+	&& bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
+	return 0;
+    if (active_filter.bf_len != 0
+	&& bpf_filter(active_filter.bf_insns, p, len, len) == 0)
+	return 0;
+#endif
+    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+	if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
+	    if (!protp->enabled_flag)
+		return 0;
+	    if (protp->active_pkt == NULL)
+		return 1;
+	    return (*protp->active_pkt)(p, len);
+	}
+    }
+    return 0;			/* not a supported protocol !!?? */
+}
diff --git a/ap/app/ppp-2.4.1/pppd/extra_crypto.c b/ap/app/ppp-2.4.1/pppd/extra_crypto.c
new file mode 100644
index 0000000..45fedb0
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/extra_crypto.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) Tim Hockin, Cobalt Networks Inc. and others
+ *
+ * crypto routines used by multiple c files 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "extra_crypto.h"
+#include "pppd.h"
+#include "md4.h"
+#ifndef USE_CRYPT
+#include <des.h>
+#endif
+
+/* quick wrapper for easy md4 */
+void
+md4(unsigned char *from, int from_len, unsigned char *to)
+{
+  MD4_CTX Context;
+
+#ifndef __NetBSD__
+  from_len <<= 3; /* bytes->bits */
+#endif
+
+  MD4Init(&Context);
+  MD4Update(&Context, from, from_len);
+  MD4Final(to, &Context);
+}
+
+
+/* Microsoft LANMAN Password hashing */
+static u_char *MSStdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
+
+void
+LmPasswordHash(char *password, int len, char *hash)
+{
+    int	i;
+    u_char up_pass[MAX_NT_PASSWORD]; /* max is actually 14 */
+
+    /* LANMan password is case insensitive */
+    BZERO(up_pass, sizeof(up_pass));
+    for (i = 0; i < len; i++)
+       up_pass[i] = (u_char)toupper(up_pass[i]);
+    DesEncrypt(MSStdText, up_pass + 0, hash + 0);
+    DesEncrypt(MSStdText, up_pass + 7, hash + 8);
+}
+
+void
+NtPasswordHash(char *secret, int secret_len, unsigned char *hash)
+{
+    int	i;
+    u_char unicodePassword[MAX_NT_PASSWORD * 2];
+
+    /* Initialize the Unicode version of the secret (== password). */
+    /* This implicitly supports 8-bit ISO8859/1 characters. */
+    BZERO(unicodePassword, sizeof(unicodePassword));
+    for (i = 0; i < secret_len; i++)
+	unicodePassword[i * 2] = (u_char)secret[i];
+
+    /* Unicode is 2 bytes per char */
+    md4(unicodePassword, secret_len * 2, hash);
+}
+
+
+static u_char Get7Bits(unsigned char *input, int startBit)
+{
+    register unsigned int       word;
+
+    word  = (unsigned)input[startBit / 8] << 8;
+    word |= (unsigned)input[startBit / 8 + 1];
+
+    word >>= 15 - (startBit % 8 + 7);
+
+    return word & 0xFE;
+}
+
+
+static void MakeKey(unsigned char *key, unsigned char *des_key)
+{
+    des_key[0] = Get7Bits(key,  0);
+    des_key[1] = Get7Bits(key,  7);
+    des_key[2] = Get7Bits(key, 14);
+    des_key[3] = Get7Bits(key, 21);
+    des_key[4] = Get7Bits(key, 28);
+    des_key[5] = Get7Bits(key, 35);
+    des_key[6] = Get7Bits(key, 42);
+    des_key[7] = Get7Bits(key, 49);
+
+#ifndef USE_CRYPT
+    des_set_odd_parity((des_cblock *)des_key);
+#endif
+}
+
+
+#ifdef USE_CRYPT
+/* in == 8-byte string (expanded version of the 56-bit key)
+ * out == 64-byte string where each byte is either 1 or 0
+ * Note that the low-order "bit" is always ignored by by setkey()
+ */
+static void Expand(unsigned char *in, unsigned char *out)
+{
+        int j, c;
+        int i;
+
+        for(i = 0; i < 64; in++){
+		c = *in;
+                for(j = 7; j >= 0; j--)
+                        *out++ = (c >> j) & 01;
+                i += 8;
+        }
+}
+
+/* The inverse of Expand
+ */
+static void Collapse(unsigned char *in, unsigned char *out)
+{
+        int j;
+        int i;
+	unsigned int c;
+
+	for (i = 0; i < 64; i += 8, out++) {
+	    c = 0;
+	    for (j = 7; j >= 0; j--, in++)
+		c |= *in << j;
+	    *out = c & 0xff;
+	}
+}
+void
+DesEncrypt(unsigned char *clear, unsigned char *key, unsigned char *cipher)
+{
+    u_char des_key[8];
+    u_char crypt_key[66];
+    u_char des_input[66];
+
+    MakeKey(key, des_key);
+
+    Expand(des_key, crypt_key);
+    setkey(crypt_key);
+
+    Expand(clear, des_input);
+    encrypt(des_input, 0);
+    Collapse(des_input, cipher);
+}
+#else /* don't USE_CRYPT */
+void
+DesEncrypt(unsigned char *clear, unsigned char *key, unsigned char *cipher)
+{
+    des_cblock		des_key;
+    des_key_schedule	key_schedule;
+
+    MakeKey(key, des_key);
+
+    des_set_key(&des_key, key_schedule);
+
+    des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
+}
+#endif /* USE_CRYPT */
+
+
diff --git a/ap/app/ppp-2.4.1/pppd/extra_crypto.h b/ap/app/ppp-2.4.1/pppd/extra_crypto.h
new file mode 100644
index 0000000..6169c5d
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/extra_crypto.h
@@ -0,0 +1,16 @@
+#ifndef __EXTRA_CRYPTO_INCLUDE__
+/* 
+ * This is just a bunch of crypto routines that are needed by more than one 
+ * piece of functionality, so they were broken out 
+ */
+
+void md4 __P((unsigned char *, int, unsigned char *));
+void LmPasswordHash __P((char *, int, char *));
+void NtPasswordHash __P((char *, int, unsigned char *));
+void DesEncrypt __P((unsigned char *, unsigned char *, unsigned char *));
+
+#define MAX_NT_PASSWORD		256	/* Max len of a (Unicode) NT passwd */
+#define MD4_SIGNATURE_SIZE	16	/* 16 bytes in a MD4 message digest */
+
+#define __EXTRA_CRYPTO_INCLUDE__
+#endif /* __EXTRA_CRYPTO_INCLUDE__ */
diff --git a/ap/app/ppp-2.4.1/pppd/fsm.c b/ap/app/ppp-2.4.1/pppd/fsm.c
new file mode 100644
index 0000000..2c19db0
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/fsm.c
@@ -0,0 +1,762 @@
+/*
+ * fsm.c - {Link, IP} Control Protocol Finite State Machine.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: fsm.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+/*
+ * TODO:
+ * Randomize fsm id on link/init.
+ * Deal with variable outgoing MTU.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <pppd.h>
+#include "fsm.h"
+
+static const char rcsid[] = RCSID;
+
+static void fsm_timeout __P((void *));
+static void fsm_rconfreq __P((fsm *, int, u_char *, int));
+static void fsm_rconfack __P((fsm *, int, u_char *, int));
+static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
+static void fsm_rtermreq __P((fsm *, int, u_char *, int));
+static void fsm_rtermack __P((fsm *));
+static void fsm_rcoderej __P((fsm *, u_char *, int));
+static void fsm_sconfreq __P((fsm *, int));
+
+#define PROTO_NAME(f)	((f)->callbacks->proto_name)
+
+int peer_mru[NUM_PPP];
+
+
+/*
+ * fsm_init - Initialize fsm.
+ *
+ * Initialize fsm state.
+ */
+void
+fsm_init(f)
+    fsm *f;
+{
+    f->state = INITIAL;
+    f->flags = 0;
+    f->id = 0;				
+    f->timeouttime = DEFTIMEOUT;
+    f->maxconfreqtransmits = DEFMAXCONFREQS;
+    f->maxtermtransmits = DEFMAXTERMREQS;
+    f->maxnakloops = DEFMAXNAKLOOPS;
+    f->term_reason_len = 0;
+}
+
+
+/*
+ * fsm_lowerup - The lower layer is up.
+ */
+void
+fsm_lowerup(f)
+    fsm *f;
+{
+    switch( f->state ){
+    case INITIAL:
+	f->state = CLOSED;
+	break;
+
+    case STARTING:
+	if( f->flags & OPT_SILENT )
+	    f->state = STOPPED;
+	else {
+	    /* Send an initial configure-request */
+	    fsm_sconfreq(f, 0);
+	    f->state = REQSENT;
+	}
+	break;
+
+    default:
+	FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state));
+    }
+}
+
+
+/*
+ * fsm_lowerdown - The lower layer is down.
+ *
+ * Cancel all timeouts and inform upper layers.
+ */
+void
+fsm_lowerdown(f)
+    fsm *f;
+{
+    switch( f->state ){
+    case CLOSED:
+	f->state = INITIAL;
+	break;
+
+    case STOPPED:
+	f->state = STARTING;
+	if( f->callbacks->starting )
+	    (*f->callbacks->starting)(f);
+	break;
+
+    case CLOSING:
+	f->state = INITIAL;
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	break;
+
+    case STOPPING:
+    case REQSENT:
+    case ACKRCVD:
+    case ACKSENT:
+	f->state = STARTING;
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	break;
+
+    case OPENED:
+	if( f->callbacks->down )
+	    (*f->callbacks->down)(f);
+	f->state = STARTING;
+	break;
+
+    default:
+	FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state));
+    }
+}
+
+
+/*
+ * fsm_open - Link is allowed to come up.
+ */
+void
+fsm_open(f)
+    fsm *f;
+{
+    switch( f->state ){
+    case INITIAL:
+	f->state = STARTING;
+	if( f->callbacks->starting )
+	    (*f->callbacks->starting)(f);
+	break;
+
+    case CLOSED:
+	if( f->flags & OPT_SILENT )
+	    f->state = STOPPED;
+	else {
+	    /* Send an initial configure-request */
+	    fsm_sconfreq(f, 0);
+	    f->state = REQSENT;
+	}
+	break;
+
+    case CLOSING:
+	f->state = STOPPING;
+	/* fall through */
+    case STOPPED:
+    case OPENED:
+	if( f->flags & OPT_RESTART ){
+	    fsm_lowerdown(f);
+	    fsm_lowerup(f);
+	}
+	break;
+    }
+}
+
+
+/*
+ * fsm_close - Start closing connection.
+ *
+ * Cancel timeouts and either initiate close or possibly go directly to
+ * the CLOSED state.
+ */
+void
+fsm_close(f, reason)
+    fsm *f;
+    char *reason;
+{
+    f->term_reason = reason;
+    f->term_reason_len = (reason == NULL? 0: strlen(reason));
+    switch( f->state ){
+    case STARTING:
+	f->state = INITIAL;
+	break;
+    case STOPPED:
+	f->state = CLOSED;
+	break;
+    case STOPPING:
+	f->state = CLOSING;
+	break;
+
+    case REQSENT:
+    case ACKRCVD:
+    case ACKSENT:
+    case OPENED:
+	if( f->state != OPENED )
+	    UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	else if( f->callbacks->down )
+	    (*f->callbacks->down)(f);	/* Inform upper layers we're down */
+
+	/* Init restart counter, send Terminate-Request */
+	f->retransmits = f->maxtermtransmits;
+	fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+		  (u_char *) f->term_reason, f->term_reason_len);
+	TIMEOUT(fsm_timeout, f, f->timeouttime);
+	--f->retransmits;
+
+	f->state = CLOSING;
+	break;
+    }
+}
+
+
+/*
+ * fsm_timeout - Timeout expired.
+ */
+static void
+fsm_timeout(arg)
+    void *arg;
+{
+    fsm *f = (fsm *) arg;
+
+    switch (f->state) {
+    case CLOSING:
+    case STOPPING:
+	if( f->retransmits <= 0 ){
+	    /*
+	     * We've waited for an ack long enough.  Peer probably heard us.
+	     */
+	    f->state = (f->state == CLOSING)? CLOSED: STOPPED;
+	    if( f->callbacks->finished )
+		(*f->callbacks->finished)(f);
+	} else {
+	    /* Send Terminate-Request */
+	    fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+		      (u_char *) f->term_reason, f->term_reason_len);
+	    TIMEOUT(fsm_timeout, f, f->timeouttime);
+	    --f->retransmits;
+	}
+	break;
+
+    case REQSENT:
+    case ACKRCVD:
+    case ACKSENT:
+	if (f->retransmits <= 0) {
+	    warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));
+	    f->state = STOPPED;
+	    if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
+		(*f->callbacks->finished)(f);
+
+	} else {
+	    /* Retransmit the configure-request */
+	    if (f->callbacks->retransmit)
+		(*f->callbacks->retransmit)(f);
+	    fsm_sconfreq(f, 1);		/* Re-send Configure-Request */
+	    if( f->state == ACKRCVD )
+		f->state = REQSENT;
+	}
+	break;
+
+    default:
+	FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));
+    }
+}
+
+
+/*
+ * fsm_input - Input packet.
+ */
+void
+fsm_input(f, inpacket, l)
+    fsm *f;
+    u_char *inpacket;
+    int l;
+{
+    u_char *inp;
+    u_char code, id;
+    int len;
+
+    /*
+     * Parse header (code, id and length).
+     * If packet too short, drop it.
+     */
+    inp = inpacket;
+    if (l < HEADERLEN) {
+	FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
+	return;
+    }
+    GETCHAR(code, inp);
+    GETCHAR(id, inp);
+    GETSHORT(len, inp);
+    if (len < HEADERLEN) {
+	FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
+	return;
+    }
+    if (len > l) {
+	FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
+	return;
+    }
+    len -= HEADERLEN;		/* subtract header length */
+
+    if( f->state == INITIAL || f->state == STARTING ){
+	FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
+		  f->protocol, f->state));
+	return;
+    }
+
+    /*
+     * Action depends on code.
+     */
+    switch (code) {
+    case CONFREQ:
+	fsm_rconfreq(f, id, inp, len);
+	break;
+    
+    case CONFACK:
+	fsm_rconfack(f, id, inp, len);
+	break;
+    
+    case CONFNAK:
+    case CONFREJ:
+	fsm_rconfnakrej(f, code, id, inp, len);
+	break;
+    
+    case TERMREQ:
+	fsm_rtermreq(f, id, inp, len);
+	break;
+    
+    case TERMACK:
+	fsm_rtermack(f);
+	break;
+    
+    case CODEREJ:
+	fsm_rcoderej(f, inp, len);
+	break;
+    
+    default:
+	if( !f->callbacks->extcode
+	   || !(*f->callbacks->extcode)(f, code, id, inp, len) )
+	    fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
+	break;
+    }
+}
+
+
+/*
+ * fsm_rconfreq - Receive Configure-Request.
+ */
+static void
+fsm_rconfreq(f, id, inp, len)
+    fsm *f;
+    u_char id;
+    u_char *inp;
+    int len;
+{
+    int code, reject_if_disagree;
+
+    switch( f->state ){
+    case CLOSED:
+	/* Go away, we're closed */
+	fsm_sdata(f, TERMACK, id, NULL, 0);
+	return;
+    case CLOSING:
+    case STOPPING:
+	return;
+
+    case OPENED:
+	/* Go down and restart negotiation */
+	if( f->callbacks->down )
+	    (*f->callbacks->down)(f);	/* Inform upper layers */
+	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
+	break;
+
+    case STOPPED:
+	/* Negotiation started by our peer */
+	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
+	f->state = REQSENT;
+	break;
+    }
+
+    /*
+     * Pass the requested configuration options
+     * to protocol-specific code for checking.
+     */
+    if (f->callbacks->reqci){		/* Check CI */
+	reject_if_disagree = (f->nakloops >= f->maxnakloops);
+	code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
+    } else if (len)
+	code = CONFREJ;			/* Reject all CI */
+    else
+	code = CONFACK;
+
+    /* send the Ack, Nak or Rej to the peer */
+    fsm_sdata(f, code, id, inp, len);
+
+    if (code == CONFACK) {
+	if (f->state == ACKRCVD) {
+	    UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	    f->state = OPENED;
+	    if (f->callbacks->up)
+		(*f->callbacks->up)(f);	/* Inform upper layers */
+	} else
+	    f->state = ACKSENT;
+	f->nakloops = 0;
+
+    } else {
+	/* we sent CONFACK or CONFREJ */
+	if (f->state != ACKRCVD)
+	    f->state = REQSENT;
+	if( code == CONFNAK )
+	    ++f->nakloops;
+    }
+}
+
+
+/*
+ * fsm_rconfack - Receive Configure-Ack.
+ */
+static void
+fsm_rconfack(f, id, inp, len)
+    fsm *f;
+    int id;
+    u_char *inp;
+    int len;
+{
+    if (id != f->reqid || f->seen_ack)		/* Expected id? */
+	return;					/* Nope, toss... */
+    if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
+	  (len == 0)) ){
+	/* Ack is bad - ignore it */
+	error("Received bad configure-ack: %P", inp, len);
+	return;
+    }
+    f->seen_ack = 1;
+
+    switch (f->state) {
+    case CLOSED:
+    case STOPPED:
+	fsm_sdata(f, TERMACK, id, NULL, 0);
+	break;
+
+    case REQSENT:
+	f->state = ACKRCVD;
+	f->retransmits = f->maxconfreqtransmits;
+	break;
+
+    case ACKRCVD:
+	/* Huh? an extra valid Ack? oh well... */
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	fsm_sconfreq(f, 0);
+	f->state = REQSENT;
+	break;
+
+    case ACKSENT:
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	f->state = OPENED;
+	f->retransmits = f->maxconfreqtransmits;
+	if (f->callbacks->up)
+	    (*f->callbacks->up)(f);	/* Inform upper layers */
+	break;
+
+    case OPENED:
+	/* Go down and restart negotiation */
+	if (f->callbacks->down)
+	    (*f->callbacks->down)(f);	/* Inform upper layers */
+	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
+	f->state = REQSENT;
+	break;
+    }
+}
+
+
+/*
+ * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
+ */
+static void
+fsm_rconfnakrej(f, code, id, inp, len)
+    fsm *f;
+    int code, id;
+    u_char *inp;
+    int len;
+{
+    int (*proc) __P((fsm *, u_char *, int));
+    int ret;
+
+    if (id != f->reqid || f->seen_ack)	/* Expected id? */
+	return;				/* Nope, toss... */
+    proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
+    if (!proc || !(ret = proc(f, inp, len))) {
+	/* Nak/reject is bad - ignore it */
+	error("Received bad configure-nak/rej: %P", inp, len);
+	return;
+    }
+    f->seen_ack = 1;
+
+    switch (f->state) {
+    case CLOSED:
+    case STOPPED:
+	fsm_sdata(f, TERMACK, id, NULL, 0);
+	break;
+
+    case REQSENT:
+    case ACKSENT:
+	/* They didn't agree to what we wanted - try another request */
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	if (ret < 0)
+	    f->state = STOPPED;		/* kludge for stopping CCP */
+	else
+	    fsm_sconfreq(f, 0);		/* Send Configure-Request */
+	break;
+
+    case ACKRCVD:
+	/* Got a Nak/reject when we had already had an Ack?? oh well... */
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	fsm_sconfreq(f, 0);
+	f->state = REQSENT;
+	break;
+
+    case OPENED:
+	/* Go down and restart negotiation */
+	if (f->callbacks->down)
+	    (*f->callbacks->down)(f);	/* Inform upper layers */
+	fsm_sconfreq(f, 0);		/* Send initial Configure-Request */
+	f->state = REQSENT;
+	break;
+    }
+}
+
+
+/*
+ * fsm_rtermreq - Receive Terminate-Req.
+ */
+static void
+fsm_rtermreq(f, id, p, len)
+    fsm *f;
+    int id;
+    u_char *p;
+    int len;
+{
+    switch (f->state) {
+    case ACKRCVD:
+    case ACKSENT:
+	f->state = REQSENT;		/* Start over but keep trying */
+	break;
+
+    case OPENED:
+	if (len > 0) {
+	    info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p);
+	} else
+	    info("%s terminated by peer", PROTO_NAME(f));
+	if (f->callbacks->down)
+	    (*f->callbacks->down)(f);	/* Inform upper layers */
+	f->retransmits = 0;
+	f->state = STOPPING;
+	TIMEOUT(fsm_timeout, f, f->timeouttime);
+	break;
+    }
+
+    fsm_sdata(f, TERMACK, id, NULL, 0);
+}
+
+
+/*
+ * fsm_rtermack - Receive Terminate-Ack.
+ */
+static void
+fsm_rtermack(f)
+    fsm *f;
+{
+    switch (f->state) {
+    case CLOSING:
+	UNTIMEOUT(fsm_timeout, f);
+	f->state = CLOSED;
+	if( f->callbacks->finished )
+	    (*f->callbacks->finished)(f);
+	break;
+    case STOPPING:
+	UNTIMEOUT(fsm_timeout, f);
+	f->state = STOPPED;
+	if( f->callbacks->finished )
+	    (*f->callbacks->finished)(f);
+	break;
+
+    case ACKRCVD:
+	f->state = REQSENT;
+	break;
+
+    case OPENED:
+	if (f->callbacks->down)
+	    (*f->callbacks->down)(f);	/* Inform upper layers */
+	fsm_sconfreq(f, 0);
+	break;
+    }
+}
+
+
+/*
+ * fsm_rcoderej - Receive an Code-Reject.
+ */
+static void
+fsm_rcoderej(f, inp, len)
+    fsm *f;
+    u_char *inp;
+    int len;
+{
+    u_char code, id;
+
+    if (len < HEADERLEN) {
+	FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!"));
+	return;
+    }
+    GETCHAR(code, inp);
+    GETCHAR(id, inp);
+    warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
+
+    if( f->state == ACKRCVD )
+	f->state = REQSENT;
+}
+
+
+/*
+ * fsm_protreject - Peer doesn't speak this protocol.
+ *
+ * Treat this as a catastrophic error (RXJ-).
+ */
+void
+fsm_protreject(f)
+    fsm *f;
+{
+    switch( f->state ){
+    case CLOSING:
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	/* fall through */
+    case CLOSED:
+	f->state = CLOSED;
+	if( f->callbacks->finished )
+	    (*f->callbacks->finished)(f);
+	break;
+
+    case STOPPING:
+    case REQSENT:
+    case ACKRCVD:
+    case ACKSENT:
+	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
+	/* fall through */
+    case STOPPED:
+	f->state = STOPPED;
+	if( f->callbacks->finished )
+	    (*f->callbacks->finished)(f);
+	break;
+
+    case OPENED:
+	if( f->callbacks->down )
+	    (*f->callbacks->down)(f);
+
+	/* Init restart counter, send Terminate-Request */
+	f->retransmits = f->maxtermtransmits;
+	fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+		  (u_char *) f->term_reason, f->term_reason_len);
+	TIMEOUT(fsm_timeout, f, f->timeouttime);
+	--f->retransmits;
+
+	f->state = STOPPING;
+	break;
+
+    default:
+	FSMDEBUG(("%s: Protocol-reject event in state %d!",
+		  PROTO_NAME(f), f->state));
+    }
+}
+
+
+/*
+ * fsm_sconfreq - Send a Configure-Request.
+ */
+static void
+fsm_sconfreq(f, retransmit)
+    fsm *f;
+    int retransmit;
+{
+    u_char *outp;
+    int cilen;
+
+    if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
+	/* Not currently negotiating - reset options */
+	if( f->callbacks->resetci )
+	    (*f->callbacks->resetci)(f);
+	f->nakloops = 0;
+    }
+
+    if( !retransmit ){
+	/* New request - reset retransmission counter, use new ID */
+	f->retransmits = f->maxconfreqtransmits;
+	f->reqid = ++f->id;
+    }
+
+    f->seen_ack = 0;
+
+    /*
+     * Make up the request packet
+     */
+    outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
+    if( f->callbacks->cilen && f->callbacks->addci ){
+	cilen = (*f->callbacks->cilen)(f);
+	if( cilen > peer_mru[f->unit] - HEADERLEN )
+	    cilen = peer_mru[f->unit] - HEADERLEN;
+	if (f->callbacks->addci)
+	    (*f->callbacks->addci)(f, outp, &cilen);
+    } else
+	cilen = 0;
+
+    /* send the request to our peer */
+    fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
+
+    /* start the retransmit timer */
+    --f->retransmits;
+    TIMEOUT(fsm_timeout, f, f->timeouttime);
+}
+
+
+/*
+ * fsm_sdata - Send some data.
+ *
+ * Used for all packets sent to our peer by this module.
+ */
+void
+fsm_sdata(f, code, id, data, datalen)
+    fsm *f;
+    u_char code, id;
+    u_char *data;
+    int datalen;
+{
+    u_char *outp;
+    int outlen;
+
+    /* Adjust length to be smaller than MTU */
+    outp = outpacket_buf;
+    if (datalen > peer_mru[f->unit] - HEADERLEN)
+	datalen = peer_mru[f->unit] - HEADERLEN;
+    if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
+	BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
+    outlen = datalen + HEADERLEN;
+    MAKEHEADER(outp, f->protocol);
+    PUTCHAR(code, outp);
+    PUTCHAR(id, outp);
+    PUTSHORT(outlen, outp);
+    output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
diff --git a/ap/app/ppp-2.4.1/pppd/fsm.h b/ap/app/ppp-2.4.1/pppd/fsm.h
new file mode 100644
index 0000000..f9129b7
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/fsm.h
@@ -0,0 +1,144 @@
+/*
+ * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: fsm.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+/*
+ * Packet header = Code, id, length.
+ */
+#define HEADERLEN	4
+
+
+/*
+ *  CP (LCP, IPCP, etc.) codes.
+ */
+#define CONFREQ		1	/* Configuration Request */
+#define CONFACK		2	/* Configuration Ack */
+#define CONFNAK		3	/* Configuration Nak */
+#define CONFREJ		4	/* Configuration Reject */
+#define TERMREQ		5	/* Termination Request */
+#define TERMACK		6	/* Termination Ack */
+#define CODEREJ		7	/* Code Reject */
+
+
+/*
+ * Each FSM is described by an fsm structure and fsm callbacks.
+ */
+typedef struct fsm {
+    int unit;			/* Interface unit number */
+    int protocol;		/* Data Link Layer Protocol field value */
+    int state;			/* State */
+    int flags;			/* Contains option bits */
+    u_char id;			/* Current id */
+    u_char reqid;		/* Current request id */
+    u_char seen_ack;		/* Have received valid Ack/Nak/Rej to Req */
+    int timeouttime;		/* Timeout time in milliseconds */
+    int maxconfreqtransmits;	/* Maximum Configure-Request transmissions */
+    int retransmits;		/* Number of retransmissions left */
+    int maxtermtransmits;	/* Maximum Terminate-Request transmissions */
+    int nakloops;		/* Number of nak loops since last ack */
+    int maxnakloops;		/* Maximum number of nak loops tolerated */
+    struct fsm_callbacks *callbacks;	/* Callback routines */
+    char *term_reason;		/* Reason for closing protocol */
+    int term_reason_len;	/* Length of term_reason */
+} fsm;
+
+
+typedef struct fsm_callbacks {
+    void (*resetci)		/* Reset our Configuration Information */
+		__P((fsm *));
+    int  (*cilen)		/* Length of our Configuration Information */
+		__P((fsm *));
+    void (*addci) 		/* Add our Configuration Information */
+		__P((fsm *, u_char *, int *));
+    int  (*ackci)		/* ACK our Configuration Information */
+		__P((fsm *, u_char *, int));
+    int  (*nakci)		/* NAK our Configuration Information */
+		__P((fsm *, u_char *, int));
+    int  (*rejci)		/* Reject our Configuration Information */
+		__P((fsm *, u_char *, int));
+    int  (*reqci)		/* Request peer's Configuration Information */
+		__P((fsm *, u_char *, int *, int));
+    void (*up)			/* Called when fsm reaches OPENED state */
+		__P((fsm *));
+    void (*down)		/* Called when fsm leaves OPENED state */
+		__P((fsm *));
+    void (*starting)		/* Called when we want the lower layer */
+		__P((fsm *));
+    void (*finished)		/* Called when we don't want the lower layer */
+		__P((fsm *));
+    void (*protreject)		/* Called when Protocol-Reject received */
+		__P((int));
+    void (*retransmit)		/* Retransmission is necessary */
+		__P((fsm *));
+    int  (*extcode)		/* Called when unknown code received */
+		__P((fsm *, int, int, u_char *, int));
+    char *proto_name;		/* String name for protocol (for messages) */
+} fsm_callbacks;
+
+
+/*
+ * Link states.
+ */
+#define INITIAL		0	/* Down, hasn't been opened */
+#define STARTING	1	/* Down, been opened */
+#define CLOSED		2	/* Up, hasn't been opened */
+#define STOPPED		3	/* Open, waiting for down event */
+#define CLOSING		4	/* Terminating the connection, not open */
+#define STOPPING	5	/* Terminating, but open */
+#define REQSENT		6	/* We've sent a Config Request */
+#define ACKRCVD		7	/* We've received a Config Ack */
+#define ACKSENT		8	/* We've sent a Config Ack */
+#define OPENED		9	/* Connection available */
+
+
+/*
+ * Flags - indicate options controlling FSM operation
+ */
+#define OPT_PASSIVE	1	/* Don't die if we don't get a response */
+#define OPT_RESTART	2	/* Treat 2nd OPEN as DOWN, UP */
+#define OPT_SILENT	4	/* Wait for peer to speak first */
+
+
+/*
+ * Timeouts.
+ */
+#define DEFTIMEOUT	3	/* Timeout time in seconds */
+#define DEFMAXTERMREQS	2	/* Maximum Terminate-Request transmissions */
+#define DEFMAXCONFREQS	10	/* Maximum Configure-Request transmissions */
+#define DEFMAXNAKLOOPS	5	/* Maximum number of nak loops */
+
+
+/*
+ * Prototypes
+ */
+void fsm_init __P((fsm *));
+void fsm_lowerup __P((fsm *));
+void fsm_lowerdown __P((fsm *));
+void fsm_open __P((fsm *));
+void fsm_close __P((fsm *, char *));
+void fsm_input __P((fsm *, u_char *, int));
+void fsm_protreject __P((fsm *));
+void fsm_sdata __P((fsm *, int, int, u_char *, int));
+
+
+/*
+ * Variables
+ */
+extern int peer_mru[];		/* currently negotiated peer MRU (per unit) */
diff --git a/ap/app/ppp-2.4.1/pppd/ipcp.c b/ap/app/ppp-2.4.1/pppd/ipcp.c
new file mode 100644
index 0000000..385ea83
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/ipcp.c
@@ -0,0 +1,2131 @@
+/*
+ * ipcp.c - PPP IP Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: ipcp.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#ifdef UNNUMBERIP_SUPPORT
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <pppd.h>
+#include "fsm.h"
+#include "ipcp.h"
+#include "pathnames.h"
+
+static const char rcsid[] = RCSID;
+
+/* global vars */
+ipcp_options ipcp_wantoptions[NUM_PPP];	/* Options that we want to request */
+ipcp_options ipcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
+ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+ipcp_options ipcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
+
+u_int32_t netmask = 0;		/* IP netmask to set on interface */
+
+//bool	disable_defaultip = 0;	/* Don't use hostname for default IP adrs */
+bool	disable_defaultip = 1;	/* Don't use hostname for default IP adrs */
+
+/* Hook for a plugin to know when IP protocol has come up */
+void (*ip_up_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to know when IP protocol has come down */
+void (*ip_down_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to choose the remote IP address */
+void (*ip_choose_hook) __P((u_int32_t *)) = NULL;
+
+/* local vars */
+static int default_route_set[NUM_PPP];	/* Have set up a default route */
+static int proxy_arp_set[NUM_PPP];	/* Have created proxy arp entry */
+static bool usepeerdns;			/* Ask peer for DNS addrs */
+static int ipcp_is_up;			/* have called np_up() */
+static bool ask_for_local;		/* request our address from peer */
+static char vj_value[8];		/* string form of vj option value */
+static char netmask_str[20];		/* string form of netmask value */
+
+/*
+ * Callbacks for fsm code.  (CI = Configuration Information)
+ */
+static void ipcp_resetci __P((fsm *));	/* Reset our CI */
+static int  ipcp_cilen __P((fsm *));	        /* Return length of our CI */
+static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
+static int  ipcp_ackci __P((fsm *, u_char *, int));	/* Peer ack'd our CI */
+static int  ipcp_nakci __P((fsm *, u_char *, int));	/* Peer nak'd our CI */
+static int  ipcp_rejci __P((fsm *, u_char *, int));	/* Peer rej'd our CI */
+static int  ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
+static void ipcp_up __P((fsm *));		/* We're UP */
+static void ipcp_down __P((fsm *));		/* We're DOWN */
+static void ipcp_finished __P((fsm *));	/* Don't need lower layer */
+
+fsm ipcp_fsm[NUM_PPP];		/* IPCP fsm structure */
+
+static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
+    ipcp_resetci,		/* Reset our Configuration Information */
+    ipcp_cilen,			/* Length of our Configuration Information */
+    ipcp_addci,			/* Add our Configuration Information */
+    ipcp_ackci,			/* ACK our Configuration Information */
+    ipcp_nakci,			/* NAK our Configuration Information */
+    ipcp_rejci,			/* Reject our Configuration Information */
+    ipcp_reqci,			/* Request peer's Configuration Information */
+    ipcp_up,			/* Called when fsm reaches OPENED state */
+    ipcp_down,			/* Called when fsm leaves OPENED state */
+    NULL,			/* Called when we want the lower layer up */
+    ipcp_finished,		/* Called when we want the lower layer down */
+    NULL,			/* Called when Protocol-Reject received */
+    NULL,			/* Retransmission is necessary */
+    NULL,			/* Called to handle protocol-specific codes */
+    "IPCP"			/* String name of protocol */
+};
+
+/*
+ * Command-line options.
+ */
+static int setvjslots __P((char **));
+static int setdnsaddr __P((char **));
+static int setwinsaddr __P((char **));
+static int setnetmask __P((char **));
+static int setipaddr __P((char *, char **, int));
+static void printipaddr __P((option_t *, void (*)(void *, char *,...),void *));
+
+static option_t ipcp_option_list[] = {
+    { "noip", o_bool, &ipcp_protent.enabled_flag,
+      "Disable IP and IPCP" },
+    { "-ip", o_bool, &ipcp_protent.enabled_flag,
+      "Disable IP and IPCP", OPT_ALIAS },
+
+    { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
+      "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj },
+    { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
+      "Disable VJ compression", OPT_ALIAS | OPT_A2CLR,
+      &ipcp_allowoptions[0].neg_vj },
+
+    { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+      "Disable VJ connection-ID compression", OPT_A2CLR,
+      &ipcp_allowoptions[0].cflag },
+    { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+      "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR,
+      &ipcp_allowoptions[0].cflag },
+
+    { "vj-max-slots", o_special, (void *)setvjslots,
+      "Set maximum VJ header slots",
+      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value },
+
+    { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
+      "Accept peer's address for us", 1 },
+    { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
+      "Accept peer's address for it", 1 },
+
+    { "ipparam", o_string, &ipparam,
+      "Set ip script parameter", OPT_PRIO },
+
+    { "noipdefault", o_bool, &disable_defaultip,
+      "Don't use name for default IP adrs", 1 },
+
+    { "ms-dns", 1, (void *)setdnsaddr,
+      "DNS address for the peer's use" },
+    { "dns-addr", 1, setdnsaddr,
+      "DNS address for the peer's use" },
+    { "ms-wins", 1, (void *)setwinsaddr,
+      "Nameserver for SMB over TCP/IP for peer" },
+
+    { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
+      "Set timeout for IPCP", OPT_PRIO },
+    { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
+      "Set max #xmits for term-reqs", OPT_PRIO },
+    { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
+      "Set max #xmits for conf-reqs", OPT_PRIO },
+    { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
+      "Set max #conf-naks for IPCP", OPT_PRIO },
+
+    { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
+      "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
+    { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+      "disable defaultroute option", OPT_A2CLR,
+      &ipcp_wantoptions[0].default_route },
+    { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+      "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
+      &ipcp_wantoptions[0].default_route },
+
+    { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
+      "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
+    { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+      "disable proxyarp option", OPT_A2CLR,
+      &ipcp_wantoptions[0].proxy_arp },
+    { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+      "disable proxyarp option", OPT_ALIAS | OPT_A2CLR,
+      &ipcp_wantoptions[0].proxy_arp },
+
+    { "usepeerdns", o_bool, &usepeerdns,
+      "Ask peer for DNS address(es)", 1 },
+
+    { "netmask", o_special, (void *)setnetmask,
+      "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str },
+
+    { "IP addresses", o_wild, (void *) &setipaddr,
+      "set local and remote IP addresses",
+      OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr },
+
+    { NULL }
+};
+
+/*
+ * Protocol entry points from main code.
+ */
+static void ipcp_init __P((int));
+static void ipcp_open __P((int));
+static void ipcp_close __P((int, char *));
+static void ipcp_lowerup __P((int));
+static void ipcp_lowerdown __P((int));
+static void ipcp_input __P((int, u_char *, int));
+static void ipcp_protrej __P((int));
+static int  ipcp_printpkt __P((u_char *, int,
+			       void (*) __P((void *, char *, ...)), void *));
+static void ip_check_options __P((void));
+static int  ip_demand_conf __P((int));
+static int  ip_active_pkt __P((u_char *, int));
+static void create_resolv __P((u_int32_t, u_int32_t));
+
+struct protent ipcp_protent = {
+    PPP_IPCP,
+    ipcp_init,
+    ipcp_input,
+    ipcp_protrej,
+    ipcp_lowerup,
+    ipcp_lowerdown,
+    ipcp_open,
+    ipcp_close,
+    ipcp_printpkt,
+    NULL,
+    1,
+    "IPCP",
+    "IP",
+    ipcp_option_list,
+    ip_check_options,
+    ip_demand_conf,
+    ip_active_pkt
+};
+
+static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
+static void ipcp_script __P((char *));		/* Run an up/down script */
+static void ipcp_script_done __P((void *));
+
+#ifdef UNNUMBERIP_SUPPORT
+/*
+ * get_lan_ip - get LAN IP for unnumber ip use.
+ */
+static unsigned int get_lan_ip(void); // tallest 0129
+#endif
+
+/*
+ * Lengths of configuration options.
+ */
+#define CILEN_VOID	2
+#define CILEN_COMPRESS	4	/* min length for compression protocol opt. */
+#define CILEN_VJ	6	/* length for RFC1332 Van-Jacobson opt. */
+#define CILEN_ADDR	6	/* new-style single address option */
+#define CILEN_ADDRS	10	/* old-style dual address option */
+
+
+#define CODENAME(x)	((x) == CONFACK ? "ACK" : \
+			 (x) == CONFNAK ? "NAK" : "REJ")
+
+/*
+ * This state variable is used to ensure that we don't
+ * run an ipcp-up/down script while one is already running.
+ */
+static enum script_state {
+    s_down,
+    s_up,
+} ipcp_script_state;
+static pid_t ipcp_script_pid;
+
+/*
+ * Make a string representation of a network IP address.
+ */
+char *
+ip_ntoa(ipaddr)
+u_int32_t ipaddr;
+{
+    static char b[64];
+
+    slprintf(b, sizeof(b), "%I", ipaddr);
+    return b;
+}
+
+/*
+ * Option parsing.
+ */
+
+/*
+ * setvjslots - set maximum number of connection slots for VJ compression
+ */
+static int
+setvjslots(argv)
+    char **argv;
+{
+    int value = 0;
+
+    if (!int_option(*argv, &value))
+	return 0;
+    if (value < 2 || value > 16) {
+	option_error("vj-max-slots value must be between 2 and 16");
+	return 0;
+    }
+    ipcp_wantoptions [0].maxslotindex =
+        ipcp_allowoptions[0].maxslotindex = value - 1;
+    slprintf(vj_value, sizeof(vj_value), "%d", value);
+    return 1;
+}
+
+/*
+ * setdnsaddr - set the dns address(es)
+ */
+static int
+setdnsaddr(argv)
+    char **argv;
+{
+    u_int32_t dns;
+    struct hostent *hp;
+
+    dns = inet_addr(*argv);
+    if (dns == (u_int32_t) -1) {
+	if ((hp = gethostbyname(*argv)) == NULL) {
+	    option_error("invalid address parameter '%s' for ms-dns option",
+			 *argv);
+	    return 0;
+	}
+	dns = *(u_int32_t *)hp->h_addr;
+    }
+
+    /* We take the last 2 values given, the 2nd-last as the primary
+       and the last as the secondary.  If only one is given it
+       becomes both primary and secondary. */
+    if (ipcp_allowoptions[0].dnsaddr[1] == 0)
+	ipcp_allowoptions[0].dnsaddr[0] = dns;
+    else
+	ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1];
+
+    /* always set the secondary address value. */
+    ipcp_allowoptions[0].dnsaddr[1] = dns;
+
+    return (1);
+}
+
+/*
+ * setwinsaddr - set the wins address(es)
+ * This is primrarly used with the Samba package under UNIX or for pointing
+ * the caller to the existing WINS server on a Windows NT platform.
+ */
+static int
+setwinsaddr(argv)
+    char **argv;
+{
+    u_int32_t wins;
+    struct hostent *hp;
+
+    wins = inet_addr(*argv);
+    if (wins == (u_int32_t) -1) {
+	if ((hp = gethostbyname(*argv)) == NULL) {
+	    option_error("invalid address parameter '%s' for ms-wins option",
+			 *argv);
+	    return 0;
+	}
+	wins = *(u_int32_t *)hp->h_addr;
+    }
+
+    /* We take the last 2 values given, the 2nd-last as the primary
+       and the last as the secondary.  If only one is given it
+       becomes both primary and secondary. */
+    if (ipcp_allowoptions[0].winsaddr[1] == 0)
+	ipcp_allowoptions[0].winsaddr[0] = wins;
+    else
+	ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1];
+
+    /* always set the secondary address value. */
+    ipcp_allowoptions[0].winsaddr[1] = wins;
+
+    return (1);
+}
+
+/*
+ * setipaddr - Set the IP address
+ * If doit is 0, the call is to check whether this option is
+ * potentially an IP address specification.
+ */
+static int
+setipaddr(arg, argv, doit)
+    char *arg;
+    char **argv;
+    int doit;
+{
+    struct hostent *hp;
+    char *colon;
+    u_int32_t local, remote;
+    ipcp_options *wo = &ipcp_wantoptions[0];
+    static int prio_local = 0, prio_remote = 0;
+
+    /*
+     * IP address pair separated by ":".
+     */
+    if ((colon = strchr(arg, ':')) == NULL)
+	return 0;
+    if (!doit)
+	return 1;
+  
+    /*
+     * If colon first character, then no local addr.
+     */
+    if (colon != arg && option_priority >= prio_local) {
+	*colon = '\0';
+	if ((local = inet_addr(arg)) == (u_int32_t) -1) {
+	    if ((hp = gethostbyname(arg)) == NULL) {
+		option_error("unknown host: %s", arg);
+		return 0;
+	    }
+	    local = *(u_int32_t *)hp->h_addr;
+	}
+	if (bad_ip_adrs(local)) {
+	    option_error("bad local IP address %s", ip_ntoa(local));
+	    return 0;
+	}
+	if (local != 0)
+	    wo->ouraddr = local;
+	*colon = ':';
+	prio_local = option_priority;
+    }
+  
+    /*
+     * If colon last character, then no remote addr.
+     */
+    if (*++colon != '\0' && option_priority >= prio_remote) {
+	if ((remote = inet_addr(colon)) == (u_int32_t) -1) {
+	    if ((hp = gethostbyname(colon)) == NULL) {
+		option_error("unknown host: %s", colon);
+		return 0;
+	    }
+	    remote = *(u_int32_t *)hp->h_addr;
+	    if (remote_name[0] == 0)
+		strlcpy(remote_name, colon, sizeof(remote_name));
+	}
+	if (bad_ip_adrs(remote)) {
+	    option_error("bad remote IP address %s", ip_ntoa(remote));
+	    return 0;
+	}
+	if (remote != 0)
+	    wo->hisaddr = remote;
+	prio_remote = option_priority;
+    }
+
+    return 1;
+}
+
+static void
+printipaddr(opt, printer, arg)
+    option_t *opt;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+	ipcp_options *wo = &ipcp_wantoptions[0];
+
+	if (wo->ouraddr != 0)
+		printer(arg, "%I", wo->ouraddr);
+	printer(arg, ":");
+	if (wo->hisaddr != 0)
+		printer(arg, "%I", wo->hisaddr);
+}
+
+/*
+ * setnetmask - set the netmask to be used on the interface.
+ */
+static int
+setnetmask(argv)
+    char **argv;
+{
+    u_int32_t mask;
+    int n;
+    char *p;
+
+    /*
+     * Unfortunately, if we use inet_addr, we can't tell whether
+     * a result of all 1s is an error or a valid 255.255.255.255.
+     */
+    p = *argv;
+    n = parse_dotted_ip(p, &mask);
+
+    mask = htonl(mask);
+
+    if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) {
+	option_error("invalid netmask value '%s'", *argv);
+	return 0;
+    }
+
+    netmask = mask;
+    slprintf(netmask_str, sizeof(netmask_str), "%I", mask);
+
+    return (1);
+}
+
+int
+parse_dotted_ip(p, vp)
+    char *p;
+    u_int32_t *vp;
+{
+    int n;
+    u_int32_t v, b;
+    char *endp, *p0 = p;
+
+    v = 0;
+    for (n = 3;; --n) {
+	b = strtoul(p, &endp, 0);
+	if (endp == p)
+	    return 0;
+	if (b > 255) {
+	    if (n < 3)
+		return 0;
+	    /* accept e.g. 0xffffff00 */
+	    *vp = b;
+	    return endp - p0;
+	}
+	v |= b << (n * 8);
+	p = endp;
+	if (n == 0)
+	    break;
+	if (*p != '.')
+	    return 0;
+	++p;
+    }
+    *vp = v;
+    return p - p0;
+}
+
+
+/*
+ * ipcp_init - Initialize IPCP.
+ */
+static void
+ipcp_init(unit)
+    int unit;
+{
+    fsm *f = &ipcp_fsm[unit];
+    ipcp_options *wo = &ipcp_wantoptions[unit];
+    ipcp_options *ao = &ipcp_allowoptions[unit];
+
+    f->unit = unit;
+    f->protocol = PPP_IPCP;
+    f->callbacks = &ipcp_callbacks;
+    fsm_init(&ipcp_fsm[unit]);
+
+    memset(wo, 0, sizeof(*wo));
+    memset(ao, 0, sizeof(*ao));
+
+    wo->neg_addr = 1;
+    wo->neg_vj = 1;
+    wo->vj_protocol = IPCP_VJ_COMP;
+    wo->maxslotindex = MAX_STATES - 1; /* really max index */
+    wo->cflag = 1;
+
+
+    /* max slots and slot-id compression are currently hardwired in */
+    /* ppp_if.c to 16 and 1, this needs to be changed (among other */
+    /* things) gmc */
+
+    ao->neg_addr = 1;
+    ao->neg_vj = 1;
+    ao->maxslotindex = MAX_STATES - 1;
+    ao->cflag = 1;
+
+    ao->proxy_arp = 1;
+    ao->default_route = 1;
+}
+
+
+/*
+ * ipcp_open - IPCP is allowed to come up.
+ */
+static void
+ipcp_open(unit)
+    int unit;
+{
+    fsm_open(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_close - Take IPCP down.
+ */
+static void
+ipcp_close(unit, reason)
+    int unit;
+    char *reason;
+{
+    fsm_close(&ipcp_fsm[unit], reason);
+}
+
+
+/*
+ * ipcp_lowerup - The lower layer is up.
+ */
+static void
+ipcp_lowerup(unit)
+    int unit;
+{
+    fsm_lowerup(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_lowerdown - The lower layer is down.
+ */
+static void
+ipcp_lowerdown(unit)
+    int unit;
+{
+    fsm_lowerdown(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_input - Input IPCP packet.
+ */
+static void
+ipcp_input(unit, p, len)
+    int unit;
+    u_char *p;
+    int len;
+{
+    fsm_input(&ipcp_fsm[unit], p, len);
+}
+
+
+/*
+ * ipcp_protrej - A Protocol-Reject was received for IPCP.
+ *
+ * Pretend the lower layer went down, so we shut up.
+ */
+static void
+ipcp_protrej(unit)
+    int unit;
+{
+    fsm_lowerdown(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_resetci - Reset our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+ipcp_resetci(f)
+    fsm *f;
+{
+    ipcp_options *wo = &ipcp_wantoptions[f->unit];
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+
+    wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
+    if (wo->ouraddr == 0)
+	wo->accept_local = 1;
+    if (wo->hisaddr == 0)
+	wo->accept_remote = 1;
+    wo->req_dns1 = usepeerdns;	/* Request DNS addresses from the peer */
+    wo->req_dns2 = usepeerdns;
+    *go = *wo;
+    if (!ask_for_local)
+	go->ouraddr = 0;
+    if (ip_choose_hook)
+	ip_choose_hook(&wo->hisaddr);
+}
+
+
+/*
+ * ipcp_cilen - Return length of our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static int
+ipcp_cilen(f)
+    fsm *f;
+{
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    ipcp_options *wo = &ipcp_wantoptions[f->unit];
+    ipcp_options *ho = &ipcp_hisoptions[f->unit];
+
+#define LENCIVJ(neg, old)	(neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
+#define LENCIADDR(neg, old)	(neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
+#define LENCIDNS(neg)		(neg ? (CILEN_ADDR) : 0)
+
+    /*
+     * First see if we want to change our options to the old
+     * forms because we have received old forms from the peer.
+     */
+    if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
+	/* use the old style of address negotiation */
+	go->neg_addr = 1;
+	go->old_addrs = 1;
+    }
+    if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
+	/* try an older style of VJ negotiation */
+	/* use the old style only if the peer did */
+	if (ho->neg_vj && ho->old_vj) {
+	    go->neg_vj = 1;
+	    go->old_vj = 1;
+	    go->vj_protocol = ho->vj_protocol;
+	}
+    }
+
+    return (LENCIADDR(go->neg_addr, go->old_addrs) +
+	    LENCIVJ(go->neg_vj, go->old_vj) +
+	    LENCIDNS(go->req_dns1) +
+	    LENCIDNS(go->req_dns2)) ;
+}
+
+
+/*
+ * ipcp_addci - Add our desired CIs to a packet.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+ipcp_addci(f, ucp, lenp)
+    fsm *f;
+    u_char *ucp;
+    int *lenp;
+{
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    int len = *lenp;
+
+#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
+    if (neg) { \
+	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
+	if (len >= vjlen) { \
+	    PUTCHAR(opt, ucp); \
+	    PUTCHAR(vjlen, ucp); \
+	    PUTSHORT(val, ucp); \
+	    if (!old) { \
+		PUTCHAR(maxslotindex, ucp); \
+		PUTCHAR(cflag, ucp); \
+	    } \
+	    len -= vjlen; \
+	} else \
+	    neg = 0; \
+    }
+
+#define ADDCIADDR(opt, neg, old, val1, val2) \
+    if (neg) { \
+	int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
+	if (len >= addrlen) { \
+	    u_int32_t l; \
+	    PUTCHAR(opt, ucp); \
+	    PUTCHAR(addrlen, ucp); \
+	    l = ntohl(val1); \
+	    PUTLONG(l, ucp); \
+	    if (old) { \
+		l = ntohl(val2); \
+		PUTLONG(l, ucp); \
+	    } \
+	    len -= addrlen; \
+	} else \
+	    neg = 0; \
+    }
+
+#define ADDCIDNS(opt, neg, addr) \
+    if (neg) { \
+	if (len >= CILEN_ADDR) { \
+	    u_int32_t l; \
+	    PUTCHAR(opt, ucp); \
+	    PUTCHAR(CILEN_ADDR, ucp); \
+	    l = ntohl(addr); \
+	    PUTLONG(l, ucp); \
+	    len -= CILEN_ADDR; \
+	} else \
+	    neg = 0; \
+    }
+
+    ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
+	      go->old_addrs, go->ouraddr, go->hisaddr);
+
+    ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
+	    go->maxslotindex, go->cflag);
+
+    ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
+
+    ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
+
+    *lenp -= len;
+}
+
+
+/*
+ * ipcp_ackci - Ack our CIs.
+ * Called by fsm_rconfack, Receive Configure ACK.
+ *
+ * Returns:
+ *	0 - Ack was bad.
+ *	1 - Ack was good.
+ */
+static int
+ipcp_ackci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    u_short cilen, citype, cishort;
+    u_int32_t cilong;
+    u_char cimaxslotindex, cicflag;
+
+    /*
+     * CIs must be in exactly the same order that we sent...
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+
+#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
+    if (neg) { \
+	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
+	if ((len -= vjlen) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != vjlen || \
+	    citype != opt)  \
+	    goto bad; \
+	GETSHORT(cishort, p); \
+	if (cishort != val) \
+	    goto bad; \
+	if (!old) { \
+	    GETCHAR(cimaxslotindex, p); \
+	    if (cimaxslotindex != maxslotindex) \
+		goto bad; \
+	    GETCHAR(cicflag, p); \
+	    if (cicflag != cflag) \
+		goto bad; \
+	} \
+    }
+
+#define ACKCIADDR(opt, neg, old, val1, val2) \
+    if (neg) { \
+	int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
+	u_int32_t l; \
+	if ((len -= addrlen) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != addrlen || \
+	    citype != opt) \
+	    goto bad; \
+	GETLONG(l, p); \
+	cilong = htonl(l); \
+	if (val1 != cilong) \
+	    goto bad; \
+	if (old) { \
+	    GETLONG(l, p); \
+	    cilong = htonl(l); \
+	    if (val2 != cilong) \
+		goto bad; \
+	} \
+    }
+
+#define ACKCIDNS(opt, neg, addr) \
+    if (neg) { \
+	u_int32_t l; \
+	if ((len -= CILEN_ADDR) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_ADDR || citype != opt) \
+	    goto bad; \
+	GETLONG(l, p); \
+	cilong = htonl(l); \
+	if (addr != cilong) \
+	    goto bad; \
+    }
+
+    ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
+	      go->old_addrs, go->ouraddr, go->hisaddr);
+
+    ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
+	    go->maxslotindex, go->cflag);
+
+    ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
+
+    ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
+
+    /*
+     * If there are any remaining CIs, then this packet is bad.
+     */
+    if (len != 0)
+	goto bad;
+    return (1);
+
+bad:
+    IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
+    return (0);
+}
+
+/*
+ * ipcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if IPCP is in the OPENED state.
+ * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
+ *
+ * Returns:
+ *	0 - Nak was bad.
+ *	1 - Nak was good.
+ */
+static int
+ipcp_nakci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    u_char cimaxslotindex, cicflag;
+    u_char citype, cilen, *next;
+    u_short cishort;
+    u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
+    ipcp_options no;		/* options we've seen Naks for */
+    ipcp_options try;		/* options to request next time */
+
+    BZERO(&no, sizeof(no));
+    try = *go;
+
+    /*
+     * Any Nak'd CIs must be in exactly the same order that we sent.
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+#define NAKCIADDR(opt, neg, old, code) \
+    if (go->neg && \
+	len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
+	p[1] == cilen && \
+	p[0] == opt) { \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	ciaddr1 = htonl(l); \
+	if (old) { \
+	    GETLONG(l, p); \
+	    ciaddr2 = htonl(l); \
+	    no.old_addrs = 1; \
+	} else \
+	    ciaddr2 = 0; \
+	no.neg = 1; \
+	code \
+    }
+
+#define NAKCIVJ(opt, neg, code) \
+    if (go->neg && \
+	((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
+	len >= cilen && \
+	p[0] == opt) { \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	no.neg = 1; \
+        code \
+    }
+
+#define NAKCIDNS(opt, neg, code) \
+    if (go->neg && \
+	((cilen = p[1]) == CILEN_ADDR) && \
+	len >= cilen && \
+	p[0] == opt) { \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	cidnsaddr = htonl(l); \
+	no.neg = 1; \
+	code \
+    }
+
+    /*
+     * Accept the peer's idea of {our,his} address, if different
+     * from our idea, only if the accept_{local,remote} flag is set.
+     */
+    NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
+	      if (go->accept_local && ciaddr1) { /* Do we know our address? */
+		  try.ouraddr = ciaddr1;
+	      }
+	      if (go->accept_remote && ciaddr2) { /* Does he know his? */
+		  try.hisaddr = ciaddr2;
+	      }
+	      );
+
+    /*
+     * Accept the peer's value of maxslotindex provided that it
+     * is less than what we asked for.  Turn off slot-ID compression
+     * if the peer wants.  Send old-style compress-type option if
+     * the peer wants.
+     */
+    NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
+	    if (cilen == CILEN_VJ) {
+		GETCHAR(cimaxslotindex, p);
+		GETCHAR(cicflag, p);
+		if (cishort == IPCP_VJ_COMP) {
+		    try.old_vj = 0;
+		    if (cimaxslotindex < go->maxslotindex)
+			try.maxslotindex = cimaxslotindex;
+		    if (!cicflag)
+			try.cflag = 0;
+		} else {
+		    try.neg_vj = 0;
+		}
+	    } else {
+		if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
+		    try.old_vj = 1;
+		    try.vj_protocol = cishort;
+		} else {
+		    try.neg_vj = 0;
+		}
+	    }
+	    );
+
+    NAKCIDNS(CI_MS_DNS1, req_dns1,
+	    try.dnsaddr[0] = cidnsaddr;
+	    );
+
+    NAKCIDNS(CI_MS_DNS2, req_dns2,
+	    try.dnsaddr[1] = cidnsaddr;
+	    );
+
+    /*
+     * There may be remaining CIs, if the peer is requesting negotiation
+     * on an option that we didn't include in our request packet.
+     * If they want to negotiate about IP addresses, we comply.
+     * If they want us to ask for compression, we refuse.
+     */
+    while (len > CILEN_VOID) {
+	GETCHAR(citype, p);
+	GETCHAR(cilen, p);
+	if( (len -= cilen) < 0 )
+	    goto bad;
+	next = p + cilen - 2;
+
+	switch (citype) {
+	case CI_COMPRESSTYPE:
+	    if (go->neg_vj || no.neg_vj ||
+		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
+		goto bad;
+	    no.neg_vj = 1;
+	    break;
+	case CI_ADDRS:
+	    if ((go->neg_addr && go->old_addrs) || no.old_addrs
+		|| cilen != CILEN_ADDRS)
+		goto bad;
+	    try.neg_addr = 1;
+	    try.old_addrs = 1;
+	    GETLONG(l, p);
+	    ciaddr1 = htonl(l);
+	    if (ciaddr1 && go->accept_local)
+		try.ouraddr = ciaddr1;
+	    GETLONG(l, p);
+	    ciaddr2 = htonl(l);
+	    if (ciaddr2 && go->accept_remote)
+		try.hisaddr = ciaddr2;
+	    no.old_addrs = 1;
+	    break;
+	case CI_ADDR:
+	    if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
+		goto bad;
+	    try.old_addrs = 0;
+	    GETLONG(l, p);
+	    ciaddr1 = htonl(l);
+	    if (ciaddr1 && go->accept_local)
+		try.ouraddr = ciaddr1;
+	    if (try.ouraddr != 0)
+		try.neg_addr = 1;
+	    no.neg_addr = 1;
+	    break;
+	}
+	p = next;
+    }
+
+    /*
+     * OK, the Nak is good.  Now we can update state.
+     * If there are any remaining options, we ignore them.
+     */
+    if (f->state != OPENED)
+	*go = try;
+
+    return 1;
+
+bad:
+    IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
+    return 0;
+}
+
+
+/*
+ * ipcp_rejci - Reject some of our CIs.
+ * Callback from fsm_rconfnakrej.
+ */
+static int
+ipcp_rejci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    u_char cimaxslotindex, ciflag, cilen;
+    u_short cishort;
+    u_int32_t cilong;
+    ipcp_options try;		/* options to request next time */
+
+    try = *go;
+    /*
+     * Any Rejected CIs must be in exactly the same order that we sent.
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+#define REJCIADDR(opt, neg, old, val1, val2) \
+    if (go->neg && \
+	len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
+	p[1] == cilen && \
+	p[0] == opt) { \
+	u_int32_t l; \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	cilong = htonl(l); \
+	/* Check rejected value. */ \
+	if (cilong != val1) \
+	    goto bad; \
+	if (old) { \
+	    GETLONG(l, p); \
+	    cilong = htonl(l); \
+	    /* Check rejected value. */ \
+	    if (cilong != val2) \
+		goto bad; \
+	} \
+	try.neg = 0; \
+    }
+
+#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
+    if (go->neg && \
+	p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
+	len >= p[1] && \
+	p[0] == opt) { \
+	len -= p[1]; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	/* Check rejected value. */  \
+	if (cishort != val) \
+	    goto bad; \
+	if (!old) { \
+	   GETCHAR(cimaxslotindex, p); \
+	   if (cimaxslotindex != maxslot) \
+	     goto bad; \
+	   GETCHAR(ciflag, p); \
+	   if (ciflag != cflag) \
+	     goto bad; \
+        } \
+	try.neg = 0; \
+     }
+
+#define REJCIDNS(opt, neg, dnsaddr) \
+    if (go->neg && \
+	((cilen = p[1]) == CILEN_ADDR) && \
+	len >= cilen && \
+	p[0] == opt) { \
+	u_int32_t l; \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	cilong = htonl(l); \
+	/* Check rejected value. */ \
+	if (cilong != dnsaddr) \
+	    goto bad; \
+	try.neg = 0; \
+    }
+
+
+    REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
+	      go->old_addrs, go->ouraddr, go->hisaddr);
+
+    REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
+	    go->maxslotindex, go->cflag);
+
+    REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
+
+    REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
+
+    /*
+     * If there are any remaining CIs, then this packet is bad.
+     */
+    if (len != 0)
+	goto bad;
+    /*
+     * Now we can update state.
+     */
+    if (f->state != OPENED)
+	*go = try;
+    return 1;
+
+bad:
+    IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
+    return 0;
+}
+
+
+/*
+ * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
+ * Callback from fsm_rconfreq, Receive Configure Request
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately.  If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+ipcp_reqci(f, inp, len, reject_if_disagree)
+    fsm *f;
+    u_char *inp;		/* Requested CIs */
+    int *len;			/* Length of requested CIs */
+    int reject_if_disagree;
+{
+    ipcp_options *wo = &ipcp_wantoptions[f->unit];
+    ipcp_options *ho = &ipcp_hisoptions[f->unit];
+    ipcp_options *ao = &ipcp_allowoptions[f->unit];
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    u_char *cip, *next;		/* Pointer to current and next CIs */
+    u_short cilen, citype;	/* Parsed len, type */
+    u_short cishort;		/* Parsed short value */
+    u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
+    int rc = CONFACK;		/* Final packet return code */
+    int orc;			/* Individual option return code */
+    u_char *p;			/* Pointer to next char to parse */
+    u_char *ucp = inp;		/* Pointer to current output char */
+    int l = *len;		/* Length left */
+    u_char maxslotindex, cflag;
+    int d;
+
+    /*
+     * Reset all his options.
+     */
+    BZERO(ho, sizeof(*ho));
+    
+    /*
+     * Process all his options.
+     */
+    next = inp;
+    while (l) {
+	orc = CONFACK;			/* Assume success */
+	cip = p = next;			/* Remember begining of CI */
+	if (l < 2 ||			/* Not enough data for CI header or */
+	    p[1] < 2 ||			/*  CI length too small or */
+	    p[1] > l) {			/*  CI length too big? */
+	    IPCPDEBUG(("ipcp_reqci: bad CI length!"));
+	    orc = CONFREJ;		/* Reject bad CI */
+	    cilen = l;			/* Reject till end of packet */
+	    l = 0;			/* Don't loop again */
+	    goto endswitch;
+	}
+	GETCHAR(citype, p);		/* Parse CI type */
+	GETCHAR(cilen, p);		/* Parse CI length */
+	l -= cilen;			/* Adjust remaining length */
+	next += cilen;			/* Step to next CI */
+
+	switch (citype) {		/* Check CI type */
+	case CI_ADDRS:
+	    if (!ao->neg_addr ||
+		cilen != CILEN_ADDRS) {	/* Check CI length */
+		orc = CONFREJ;		/* Reject CI */
+		break;
+	    }
+
+	    /*
+	     * If he has no address, or if we both have his address but
+	     * disagree about it, then NAK it with our idea.
+	     * In particular, if we don't know his address, but he does,
+	     * then accept it.
+	     */
+	    GETLONG(tl, p);		/* Parse source address (his) */
+	    ciaddr1 = htonl(tl);
+#ifdef DYNAMIC
+	    if(!auth_ip_addr(f->unit, ciaddr1))
+		if(get_ip_addr_dynamic(f->unit, &tl))
+		{
+		    wo->hisaddr = tl;
+		    ciaddr1 = 0;
+		}
+#endif
+	    if (ciaddr1 != wo->hisaddr
+		&& (ciaddr1 == 0 || !wo->accept_remote)) {
+		orc = CONFNAK;
+		if (!reject_if_disagree) {
+		    DECPTR(sizeof(u_int32_t), p);
+		    tl = ntohl(wo->hisaddr);
+		    PUTLONG(tl, p);
+		}
+	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
+		/*
+		 * If neither we nor he knows his address, reject the option.
+		 */
+		orc = CONFREJ;
+		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
+		break;
+	    }
+
+	    /*
+	     * If he doesn't know our address, or if we both have our address
+	     * but disagree about it, then NAK it with our idea.
+	     */
+	    GETLONG(tl, p);		/* Parse desination address (ours) */
+	    ciaddr2 = htonl(tl);
+	    if (ciaddr2 != wo->ouraddr) {
+		if (ciaddr2 == 0 || !wo->accept_local) {
+		    orc = CONFNAK;
+		    if (!reject_if_disagree) {
+			DECPTR(sizeof(u_int32_t), p);
+			tl = ntohl(wo->ouraddr);
+			PUTLONG(tl, p);
+		    }
+		} else {
+		    go->ouraddr = ciaddr2;	/* accept peer's idea */
+		}
+	    }
+
+	    ho->neg_addr = 1;
+	    ho->old_addrs = 1;
+	    ho->hisaddr = ciaddr1;
+	    ho->ouraddr = ciaddr2;
+	    break;
+
+	case CI_ADDR:
+	    if (!ao->neg_addr ||
+		cilen != CILEN_ADDR) {	/* Check CI length */
+		orc = CONFREJ;		/* Reject CI */
+		break;
+	    }
+
+	    /*
+	     * If he has no address, or if we both have his address but
+	     * disagree about it, then NAK it with our idea.
+	     * In particular, if we don't know his address, but he does,
+	     * then accept it.
+	     */
+	    GETLONG(tl, p);	/* Parse source address (his) */
+	    ciaddr1 = htonl(tl);
+#ifdef DYNAMIC
+	    if(!auth_ip_addr(f->unit, ciaddr1))
+		if(get_ip_addr_dynamic(f->unit, &tl))
+		{
+		    wo->hisaddr = tl;
+		    ciaddr1 = 0;
+		}
+#endif
+	    if (ciaddr1 != wo->hisaddr
+		&& (ciaddr1 == 0 || !wo->accept_remote)) {
+		orc = CONFNAK;
+		if (!reject_if_disagree) {
+		    DECPTR(sizeof(u_int32_t), p);
+		    tl = ntohl(wo->hisaddr);
+		    PUTLONG(tl, p);
+		}
+	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
+		/*
+		 * Don't ACK an address of 0.0.0.0 - reject it instead.
+		 */
+		orc = CONFREJ;
+		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
+		break;
+	    }
+	
+	    ho->neg_addr = 1;
+	    ho->hisaddr = ciaddr1;
+	    break;
+
+	case CI_MS_DNS1:
+	case CI_MS_DNS2:
+	    /* Microsoft primary or secondary DNS request */
+	    d = citype == CI_MS_DNS2;
+
+	    /* If we do not have a DNS address then we cannot send it */
+	    if (ao->dnsaddr[d] == 0 ||
+		cilen != CILEN_ADDR) {	/* Check CI length */
+		orc = CONFREJ;		/* Reject CI */
+		break;
+	    }
+	    GETLONG(tl, p);
+	    if (htonl(tl) != ao->dnsaddr[d]) {
+                DECPTR(sizeof(u_int32_t), p);
+		tl = ntohl(ao->dnsaddr[d]);
+		PUTLONG(tl, p);
+		orc = CONFNAK;
+            }
+            break;
+
+	case CI_MS_WINS1:
+	case CI_MS_WINS2:
+	    /* Microsoft primary or secondary WINS request */
+	    d = citype == CI_MS_WINS2;
+
+	    /* If we do not have a DNS address then we cannot send it */
+	    if (ao->winsaddr[d] == 0 ||
+		cilen != CILEN_ADDR) {	/* Check CI length */
+		orc = CONFREJ;		/* Reject CI */
+		break;
+	    }
+	    GETLONG(tl, p);
+	    if (htonl(tl) != ao->winsaddr[d]) {
+                DECPTR(sizeof(u_int32_t), p);
+		tl = ntohl(ao->winsaddr[d]);
+		PUTLONG(tl, p);
+		orc = CONFNAK;
+            }
+            break;
+	
+	case CI_COMPRESSTYPE:
+	    if (!ao->neg_vj ||
+		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
+		orc = CONFREJ;
+		break;
+	    }
+	    GETSHORT(cishort, p);
+
+	    if (!(cishort == IPCP_VJ_COMP ||
+		  (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
+		orc = CONFREJ;
+		break;
+	    }
+
+	    ho->neg_vj = 1;
+	    ho->vj_protocol = cishort;
+	    if (cilen == CILEN_VJ) {
+		GETCHAR(maxslotindex, p);
+		if (maxslotindex > ao->maxslotindex) { 
+		    orc = CONFNAK;
+		    if (!reject_if_disagree){
+			DECPTR(1, p);
+			PUTCHAR(ao->maxslotindex, p);
+		    }
+		}
+		GETCHAR(cflag, p);
+		if (cflag && !ao->cflag) {
+		    orc = CONFNAK;
+		    if (!reject_if_disagree){
+			DECPTR(1, p);
+			PUTCHAR(wo->cflag, p);
+		    }
+		}
+		ho->maxslotindex = maxslotindex;
+		ho->cflag = cflag;
+	    } else {
+		ho->old_vj = 1;
+		ho->maxslotindex = MAX_STATES - 1;
+		ho->cflag = 1;
+	    }
+	    break;
+
+	default:
+	    orc = CONFREJ;
+	    break;
+	}
+endswitch:
+	if (orc == CONFACK &&		/* Good CI */
+	    rc != CONFACK)		/*  but prior CI wasnt? */
+	    continue;			/* Don't send this one */
+
+	if (orc == CONFNAK) {		/* Nak this CI? */
+	    if (reject_if_disagree)	/* Getting fed up with sending NAKs? */
+		orc = CONFREJ;		/* Get tough if so */
+	    else {
+		if (rc == CONFREJ)	/* Rejecting prior CI? */
+		    continue;		/* Don't send this one */
+		if (rc == CONFACK) {	/* Ack'd all prior CIs? */
+		    rc = CONFNAK;	/* Not anymore... */
+		    ucp = inp;		/* Backup */
+		}
+	    }
+	}
+
+	if (orc == CONFREJ &&		/* Reject this CI */
+	    rc != CONFREJ) {		/*  but no prior ones? */
+	    rc = CONFREJ;
+	    ucp = inp;			/* Backup */
+	}
+
+	/* Need to move CI? */
+	if (ucp != cip)
+	    BCOPY(cip, ucp, cilen);	/* Move it */
+
+	/* Update output pointer */
+	INCPTR(cilen, ucp);
+    }
+
+    /*
+     * If we aren't rejecting this packet, and we want to negotiate
+     * their address, and they didn't send their address, then we
+     * send a NAK with a CI_ADDR option appended.  We assume the
+     * input buffer is long enough that we can append the extra
+     * option safely.
+     */
+    if (rc != CONFREJ && !ho->neg_addr &&
+	wo->req_addr && !reject_if_disagree) {
+	if (rc == CONFACK) {
+	    rc = CONFNAK;
+	    ucp = inp;			/* reset pointer */
+	    wo->req_addr = 0;		/* don't ask again */
+	}
+	PUTCHAR(CI_ADDR, ucp);
+	PUTCHAR(CILEN_ADDR, ucp);
+	tl = ntohl(wo->hisaddr);
+	PUTLONG(tl, ucp);
+    }
+
+    *len = ucp - inp;			/* Compute output length */
+    IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
+    return (rc);			/* Return final code */
+}
+
+
+/*
+ * ip_check_options - check that any IP-related options are OK,
+ * and assign appropriate defaults.
+ */
+static void
+ip_check_options()
+{
+    struct hostent *hp;
+    u_int32_t local;
+    ipcp_options *wo = &ipcp_wantoptions[0];
+
+    /*
+     * Default our local IP address based on our hostname.
+     * If local IP address already given, don't bother.
+     */
+    if (wo->ouraddr == 0 && !disable_defaultip) {
+	/*
+	 * Look up our hostname (possibly with domain name appended)
+	 * and take the first IP address as our local IP address.
+	 * If there isn't an IP address for our hostname, too bad.
+	 */
+	wo->accept_local = 1;	/* don't insist on this default value */
+	if ((hp = gethostbyname(hostname)) != NULL) {
+	    local = *(u_int32_t *)hp->h_addr;
+	    if (local != 0 && !bad_ip_adrs(local))
+		wo->ouraddr = local;
+	}
+    }
+    ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
+}
+
+
+/*
+ * ip_demand_conf - configure the interface as though
+ * IPCP were up, for use with dial-on-demand.
+ */
+static int
+ip_demand_conf(u)
+    int u;
+{
+    ipcp_options *wo = &ipcp_wantoptions[u];
+
+    if (wo->hisaddr == 0) {
+	/* make up an arbitrary address for the peer */
+	wo->hisaddr = htonl(0x0a707070 + ifunit);
+	wo->accept_remote = 1;
+    }
+    if (wo->ouraddr == 0) {
+	/* make up an arbitrary address for us */
+	wo->ouraddr = htonl(0x0a404040 + ifunit);
+	wo->accept_local = 1;
+	ask_for_local = 0;	/* don't tell the peer this address */
+    }
+    if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
+	return 0;
+    if (!sifup(u))
+	return 0;
+    if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+	return 0;
+    if (wo->default_route)
+	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
+	    default_route_set[u] = 1;
+    if (wo->proxy_arp)
+	if (sifproxyarp(u, wo->hisaddr))
+	    proxy_arp_set[u] = 1;
+
+    notice("local  IP address %I", wo->ouraddr);
+    notice("remote IP address %I", wo->hisaddr);
+
+    //sc_cfg_set("ppp_status","ppp_on_demand"); //linxu
+
+    return 1;
+}
+
+
+/*
+ * ipcp_up - IPCP has come UP.
+ *
+ * Configure the IP network interface appropriately and bring it up.
+ */
+static void
+ipcp_up(f)
+    fsm *f;
+{
+    u_int32_t mask;
+    ipcp_options *ho = &ipcp_hisoptions[f->unit];
+    ipcp_options *go = &ipcp_gotoptions[f->unit];
+    ipcp_options *wo = &ipcp_wantoptions[f->unit];
+
+    IPCPDEBUG(("ipcp: up"));
+
+    /*
+     * We must have a non-zero IP address for both ends of the link.
+     */
+    if (!ho->neg_addr)
+	ho->hisaddr = wo->hisaddr;
+
+    if (go->ouraddr == 0) {
+	error("Could not determine local IP address");
+	ipcp_close(f->unit, "Could not determine local IP address");
+	return;
+    }
+    if (ho->hisaddr == 0) {
+	ho->hisaddr = htonl(0x0a404040 + ifunit);
+	warn("Could not determine remote IP address: defaulting to %I",
+	     ho->hisaddr);
+    }
+#ifdef UNNUMBERIP_SUPPORT
+    if(is_unnumber_ip == 1){
+	go->ouraddr = get_lan_ip(); // tallest 0129
+    }
+#endif
+    script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
+    script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
+
+    if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
+	script_setenv("USEPEERDNS", "1", 0);
+	if (go->dnsaddr[0])
+	    script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
+	if (go->dnsaddr[1])
+	    script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
+	create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
+    }
+
+    /*
+     * Check that the peer is allowed to use the IP address it wants.
+     */
+    if (!auth_ip_addr(f->unit, ho->hisaddr)) {
+	error("Peer is not authorized to use remote address %I", ho->hisaddr);
+	ipcp_close(f->unit, "Unauthorized remote IP address");
+	return;
+    }
+
+    /* set tcp compression */
+    sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
+
+    /*
+     * If we are doing dial-on-demand, the interface is already
+     * configured, so we put out any saved-up packets, then set the
+     * interface to pass IP packets.
+     */
+    if (demand) {
+	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
+	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
+	    if (go->ouraddr != wo->ouraddr) {
+		warn("Local IP address changed to %I", go->ouraddr);
+		script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
+		wo->ouraddr = go->ouraddr;
+	    } else
+		script_unsetenv("OLDIPLOCAL");
+	    if (ho->hisaddr != wo->hisaddr) {
+		warn("Remote IP address changed to %I", ho->hisaddr);
+		script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
+		wo->hisaddr = ho->hisaddr;
+	    } else
+		script_unsetenv("OLDIPREMOTE");
+
+	    /* Set the interface to the new addresses */
+	    mask = GetMask(go->ouraddr);
+	    if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+		if (debug)
+		    warn("Interface configuration failed");
+		ipcp_close(f->unit, "Interface configuration failed");
+		return;
+	    }
+
+	    /* assign a default route through the interface if required */
+	    if (ipcp_wantoptions[f->unit].default_route) 
+		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+		    default_route_set[f->unit] = 1;
+
+	    /* Make a proxy ARP entry if requested. */
+	    if (ipcp_wantoptions[f->unit].proxy_arp)
+		if (sifproxyarp(f->unit, ho->hisaddr))
+		    proxy_arp_set[f->unit] = 1;
+
+	}
+	demand_rexmit(PPP_IP);
+	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+    } else {
+	/*
+	 * Set IP addresses and (if specified) netmask.
+	 */
+	mask = GetMask(go->ouraddr);
+
+#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+	    if (debug)
+		warn("Interface configuration failed");
+	    ipcp_close(f->unit, "Interface configuration failed");
+	    return;
+	}
+#endif
+
+	/* bring the interface up for IP */
+	if (!sifup(f->unit)) {
+	    if (debug)
+		warn("Interface failed to come up");
+	    ipcp_close(f->unit, "Interface configuration failed");
+	    return;
+	}
+
+#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+	    if (debug)
+		warn("Interface configuration failed");
+	    ipcp_close(f->unit, "Interface configuration failed");
+	    return;
+	}
+#endif
+	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+	/* assign a default route through the interface if required */
+	if (ipcp_wantoptions[f->unit].default_route) 
+	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+		default_route_set[f->unit] = 1;
+
+	/* Make a proxy ARP entry if requested. */
+	if (ipcp_wantoptions[f->unit].proxy_arp)
+	    if (sifproxyarp(f->unit, ho->hisaddr))
+		proxy_arp_set[f->unit] = 1;
+
+	ipcp_wantoptions[0].ouraddr = go->ouraddr;
+
+	notice("local  IP address %I", go->ouraddr);
+	notice("remote IP address %I", ho->hisaddr);
+	if (go->dnsaddr[0])
+	    notice("primary   DNS address %I", go->dnsaddr[0]);
+	if (go->dnsaddr[1])
+	    notice("secondary DNS address %I", go->dnsaddr[1]);
+    }
+
+    np_up(f->unit, PPP_IP);
+    ipcp_is_up = 1;
+
+    if (ip_up_hook)
+	ip_up_hook();
+
+    /*
+     * Execute the ip-up script, like this:
+     *	/etc/ppp/ip-up interface tty speed local-IP remote-IP
+     */
+    if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
+	ipcp_script_state = s_up;
+	ipcp_script(_PATH_IPUP);
+    }
+}
+
+//=============================================================================
+//by tallest 0407
+static void
+kill_ppp(int  ppp_num)
+{
+#ifdef MPPPOE_SUPPORT
+        char buf[500];
+
+	if(demand)
+	{
+        	sprintf(buf,"%.500s %d",ppp_disconnect_func,ppp_num);
+        	info("tallest:=====(Executing external command - %s)=====\n",buf);
+        	system(buf);
+	}
+#endif
+}
+//=============================================================================
+
+/*
+ * ipcp_down - IPCP has gone DOWN.
+ *
+ * Take the IP network interface down, clear its addresses
+ * and delete routes through it.
+ */
+static void
+ipcp_down(f)
+    fsm *f;
+{
+    IPCPDEBUG(("ipcp: down"));
+    update_link_stats(f->unit);
+    if (ip_down_hook)
+	ip_down_hook();
+    if (ipcp_is_up) {
+	ipcp_is_up = 0;
+	np_down(f->unit, PPP_IP);
+    }
+    sifvjcomp(f->unit, 0, 0, 0);
+
+    /*
+     * If we are doing dial-on-demand, set the interface
+     * to queue up outgoing packets (for now).
+     */
+    if (demand) {
+	sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
+    } else {
+	sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
+	sifdown(f->unit);
+	ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
+			 ipcp_hisoptions[f->unit].hisaddr);
+    }
+
+    /* Execute the ip-down script */
+    if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
+	ipcp_script_state = s_down;
+	ipcp_script(_PATH_IPDOWN);
+#ifdef MPPPOE_SUPPORT
+	kill_ppp(atoi(ipparam)); // by tallest 0407
+#endif
+    }
+}
+
+
+/*
+ * ipcp_clear_addrs() - clear the interface addresses, routes,
+ * proxy arp entries, etc.
+ */
+static void
+ipcp_clear_addrs(unit, ouraddr, hisaddr)
+    int unit;
+    u_int32_t ouraddr;  /* local address */
+    u_int32_t hisaddr;  /* remote address */
+{
+    if (proxy_arp_set[unit]) {
+	cifproxyarp(unit, hisaddr);
+	proxy_arp_set[unit] = 0;
+    }
+    if (default_route_set[unit]) {
+	cifdefaultroute(unit, ouraddr, hisaddr);
+	default_route_set[unit] = 0;
+    }
+    cifaddr(unit, ouraddr, hisaddr);
+}
+
+
+/*
+ * ipcp_finished - possibly shut down the lower layers.
+ */
+static void
+ipcp_finished(f)
+    fsm *f;
+{
+    np_finished(f->unit, PPP_IP);
+}
+
+
+/*
+ * ipcp_script_done - called when the ip-up or ip-down script
+ * has finished.
+ */
+static void
+ipcp_script_done(arg)
+    void *arg;
+{
+    ipcp_script_pid = 0;
+    switch (ipcp_script_state) {
+    case s_up:
+	if (ipcp_fsm[0].state != OPENED) {
+	    ipcp_script_state = s_down;
+	    ipcp_script(_PATH_IPDOWN);
+	}
+	break;
+    case s_down:
+	if (ipcp_fsm[0].state == OPENED) {
+	    ipcp_script_state = s_up;
+	    ipcp_script(_PATH_IPUP);
+	}
+	break;
+    }
+}
+
+
+/*
+ * ipcp_script - Execute a script with arguments
+ * interface-name tty-name speed local-IP remote-IP.
+ */
+static void
+ipcp_script(script)
+    char *script;
+{
+    char strspeed[32], strlocal[32], strremote[32];
+    char *argv[8];
+
+    slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
+    slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr);
+    slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr);
+
+    argv[0] = script;
+    argv[1] = ifname;
+    argv[2] = devnam;
+    argv[3] = strspeed;
+    argv[4] = strlocal;
+    argv[5] = strremote;
+    argv[6] = ipparam;
+    argv[7] = NULL;
+    ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
+}
+
+#ifdef UNNUMBERIP_SUPPORT
+/*
+ * get_lan_ip - get LAN IP for unnumber ip use.
+ */
+#define s_addr(s) ( (((struct sockaddr_in *)(s))->sin_addr).s_addr )
+static unsigned int 
+get_lan_ip( void ) // tallest 0129
+{
+	struct ifreq ifr;
+	int timeout, s;
+
+	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
+                return;
+	strncpy(ifr.ifr_name, "br0", IFNAMSIZ);
+
+	timeout = 3;
+	while (ioctl(s, SIOCGIFADDR, &ifr) && timeout--)
+	{
+		info("Wait br0 inteface to init (%d) ...\n",timeout);
+	};
+	info("tallest:Using Unnumber IP ==> ifr.ifr_addr = %x <==\n", s_addr(&(ifr.ifr_addr)));
+	return s_addr( &(ifr.ifr_addr) );
+}
+#endif
+
+/*
+ * create_resolv - create the replacement resolv.conf file
+ */
+static void
+create_resolv(peerdns1, peerdns2)
+    u_int32_t peerdns1, peerdns2;
+{
+    FILE *f;
+
+    f = fopen(_PATH_RESOLV, "w");
+    if (f == NULL) {
+	error("Failed to create %s: %m", _PATH_RESOLV);
+	return;
+    }
+
+    if (peerdns1)
+	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1));
+
+    if (peerdns2)
+	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2));
+
+    if (ferror(f))
+	error("Write failed to %s: %m", _PATH_RESOLV);
+
+    fclose(f);
+}
+
+/*
+ * ipcp_printpkt - print the contents of an IPCP packet.
+ */
+static char *ipcp_codenames[] = {
+    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+    "TermReq", "TermAck", "CodeRej"
+};
+
+static int
+ipcp_printpkt(p, plen, printer, arg)
+    u_char *p;
+    int plen;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int code, id, len, olen;
+    u_char *pstart, *optend;
+    u_short cishort;
+    u_int32_t cilong;
+
+    if (plen < HEADERLEN)
+	return 0;
+    pstart = p;
+    GETCHAR(code, p);
+    GETCHAR(id, p);
+    GETSHORT(len, p);
+    if (len < HEADERLEN || len > plen)
+	return 0;
+
+    if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
+	printer(arg, " %s", ipcp_codenames[code-1]);
+    else
+	printer(arg, " code=0x%x", code);
+    printer(arg, " id=0x%x", id);
+    len -= HEADERLEN;
+    switch (code) {
+    case CONFREQ:
+    case CONFACK:
+    case CONFNAK:
+    case CONFREJ:
+	/* print option list */
+	while (len >= 2) {
+	    GETCHAR(code, p);
+	    GETCHAR(olen, p);
+	    p -= 2;
+	    if (olen < 2 || olen > len) {
+		break;
+	    }
+	    printer(arg, " <");
+	    len -= olen;
+	    optend = p + olen;
+	    switch (code) {
+	    case CI_ADDRS:
+		if (olen == CILEN_ADDRS) {
+		    p += 2;
+		    GETLONG(cilong, p);
+		    printer(arg, "addrs %I", htonl(cilong));
+		    GETLONG(cilong, p);
+		    printer(arg, " %I", htonl(cilong));
+		}
+		break;
+	    case CI_COMPRESSTYPE:
+		if (olen >= CILEN_COMPRESS) {
+		    p += 2;
+		    GETSHORT(cishort, p);
+		    printer(arg, "compress ");
+		    switch (cishort) {
+		    case IPCP_VJ_COMP:
+			printer(arg, "VJ");
+			break;
+		    case IPCP_VJ_COMP_OLD:
+			printer(arg, "old-VJ");
+			break;
+		    default:
+			printer(arg, "0x%x", cishort);
+		    }
+		}
+		break;
+	    case CI_ADDR:
+		if (olen == CILEN_ADDR) {
+		    p += 2;
+		    GETLONG(cilong, p);
+		    printer(arg, "addr %I", htonl(cilong));
+		}
+		break;
+	    case CI_MS_DNS1:
+	    case CI_MS_DNS2:
+	        p += 2;
+		GETLONG(cilong, p);
+		printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,
+			htonl(cilong));
+		break;
+	    case CI_MS_WINS1:
+	    case CI_MS_WINS2:
+	        p += 2;
+		GETLONG(cilong, p);
+		printer(arg, "ms-wins %I", htonl(cilong));
+		break;
+	    }
+	    while (p < optend) {
+		GETCHAR(code, p);
+		printer(arg, " %.2x", code);
+	    }
+	    printer(arg, ">");
+	}
+	break;
+
+    case TERMACK:
+    case TERMREQ:
+	if (len > 0 && *p >= ' ' && *p < 0x7f) {
+	    printer(arg, " ");
+	    print_string((char *)p, len, printer, arg);
+	    p += len;
+	    len = 0;
+	}
+	break;
+    }
+
+    /* print the rest of the bytes in the packet */
+    for (; len > 0; --len) {
+	GETCHAR(code, p);
+	printer(arg, " %.2x", code);
+    }
+
+    return p - pstart;
+}
+
+/*
+ * ip_active_pkt - see if this IP packet is worth bringing the link up for.
+ * We don't bring the link up for IP fragments or for TCP FIN packets
+ * with no data.
+ */
+#define IP_HDRLEN	20	/* bytes */
+#define IP_OFFMASK	0x1fff
+#define TCP_HDRLEN	20
+#define TH_FIN		0x01
+
+/*
+ * We use these macros because the IP header may be at an odd address,
+ * and some compilers might use word loads to get th_off or ip_hl.
+ */
+
+#define net_short(x)	(((x)[0] << 8) + (x)[1])
+#define get_iphl(x)	(((unsigned char *)(x))[0] & 0xF)
+#define get_ipoff(x)	net_short((unsigned char *)(x) + 6)
+#define get_ipproto(x)	(((unsigned char *)(x))[9])
+#define get_tcpoff(x)	(((unsigned char *)(x))[12] >> 4)
+#define get_tcpflags(x)	(((unsigned char *)(x))[13])
+
+static int
+ip_active_pkt(pkt, len)
+    u_char *pkt;
+    int len;
+{
+    u_char *tcp;
+    int hlen;
+
+    len -= PPP_HDRLEN;
+    pkt += PPP_HDRLEN;
+    if (len < IP_HDRLEN)
+	return 0;
+    if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
+	return 0;
+    if (get_ipproto(pkt) != IPPROTO_TCP)
+	return 1;
+    hlen = get_iphl(pkt) * 4;
+    if (len < hlen + TCP_HDRLEN)
+	return 0;
+    tcp = pkt + hlen;
+    if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
+	return 0;
+    return 1;
+}
diff --git a/ap/app/ppp-2.4.1/pppd/ipcp.h b/ap/app/ppp-2.4.1/pppd/ipcp.h
new file mode 100644
index 0000000..0f66679
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/ipcp.h
@@ -0,0 +1,73 @@
+/*
+ * ipcp.h - IP Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: ipcp.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+/*
+ * Options.
+ */
+#define CI_ADDRS	1	/* IP Addresses */
+#define CI_COMPRESSTYPE	2	/* Compression Type */
+#define	CI_ADDR		3
+
+#define CI_MS_DNS1	129	/* Primary DNS value */
+#define CI_MS_WINS1	130	/* Primary WINS value */
+#define CI_MS_DNS2	131	/* Secondary DNS value */
+#define CI_MS_WINS2	132	/* Secondary WINS value */
+
+#define MAX_STATES 16		/* from slcompress.h */
+
+#define IPCP_VJMODE_OLD 1	/* "old" mode (option # = 0x0037) */
+#define IPCP_VJMODE_RFC1172 2	/* "old-rfc"mode (option # = 0x002d) */
+#define IPCP_VJMODE_RFC1332 3	/* "new-rfc"mode (option # = 0x002d, */
+                                /*  maxslot and slot number compression) */
+
+#define IPCP_VJ_COMP 0x002d	/* current value for VJ compression option*/
+#define IPCP_VJ_COMP_OLD 0x0037	/* "old" (i.e, broken) value for VJ */
+				/* compression option*/ 
+
+typedef struct ipcp_options {
+    bool neg_addr;		/* Negotiate IP Address? */
+    bool old_addrs;		/* Use old (IP-Addresses) option? */
+    bool req_addr;		/* Ask peer to send IP address? */
+    bool default_route;		/* Assign default route through interface? */
+    bool proxy_arp;		/* Make proxy ARP entry for peer? */
+    bool neg_vj;		/* Van Jacobson Compression? */
+    bool old_vj;		/* use old (short) form of VJ option? */
+    bool accept_local;		/* accept peer's value for ouraddr */
+    bool accept_remote;		/* accept peer's value for hisaddr */
+    bool req_dns1;		/* Ask peer to send primary DNS address? */
+    bool req_dns2;		/* Ask peer to send secondary DNS address? */
+    int  vj_protocol;		/* protocol value to use in VJ option */
+    int  maxslotindex;		/* values for RFC1332 VJ compression neg. */
+    bool cflag;
+    u_int32_t ouraddr, hisaddr;	/* Addresses in NETWORK BYTE ORDER */
+    u_int32_t dnsaddr[2];	/* Primary and secondary MS DNS entries */
+    u_int32_t winsaddr[2];	/* Primary and secondary MS WINS entries */
+} ipcp_options;
+
+extern fsm ipcp_fsm[];
+extern ipcp_options ipcp_wantoptions[];
+extern ipcp_options ipcp_gotoptions[];
+extern ipcp_options ipcp_allowoptions[];
+extern ipcp_options ipcp_hisoptions[];
+
+char *ip_ntoa __P((u_int32_t));
+
+extern struct protent ipcp_protent;
diff --git a/ap/app/ppp-2.4.1/pppd/lcp.c b/ap/app/ppp-2.4.1/pppd/lcp.c
new file mode 100644
index 0000000..7b90094
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/lcp.c
@@ -0,0 +1,2336 @@
+/*
+ * lcp.c - PPP Link Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: lcp.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <pppd.h>
+#include "fsm.h"
+#include "lcp.h"
+#include "chap.h"
+#include "magic.h"
+
+static const char rcsid[] = RCSID;
+
+extern bool refuse_chap;
+
+/*
+ * When the link comes up we want to be able to wait for a short while,
+ * or until seeing some input from the peer, before starting to send
+ * configure-requests.  We do this by delaying the fsm_lowerup call.
+ */
+/* steal a bit in fsm flags word */
+#define DELAYED_UP	0x100
+
+static void lcp_delayed_up __P((void *));
+
+/*
+ * LCP-related command-line options.
+ */
+int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
+int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
+bool	lax_recv = 0;		/* accept control chars in asyncmap */
+bool	noendpoint = 0;		/* don't send/accept endpoint discriminator */
+
+static int noopt __P((char **));
+
+#ifdef HAVE_MULTILINK
+static int setendpoint __P((char **));
+static void printendpoint __P((option_t *, void (*)(void *, char *, ...),
+			       void *));
+#endif /* HAVE_MULTILINK */
+
+static option_t lcp_option_list[] = {
+    /* LCP options */
+    { "-all", o_special_noarg, (void *)noopt,
+      "Don't request/allow any LCP options" },
+
+    { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
+      "Disable address/control compression",
+      OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
+    { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
+      "Disable address/control compression",
+      OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
+
+    { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Set asyncmap (for received packets)",
+      OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+    { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Set asyncmap (for received packets)",
+      OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+    { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Disable asyncmap negotiation",
+      OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
+      &lcp_allowoptions[0].neg_asyncmap },
+    { "-am", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Disable asyncmap negotiation",
+      OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
+      &lcp_allowoptions[0].neg_asyncmap },
+
+    { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+      "Disable magic number negotiation (looped-back line detection)",
+      OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
+    { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+      "Disable magic number negotiation (looped-back line detection)",
+      OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
+
+    { "mru", o_int, &lcp_wantoptions[0].mru,
+      "Set MRU (maximum received packet size) for negotiation",
+      OPT_PRIO, &lcp_wantoptions[0].neg_mru },
+    { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+      "Disable MRU negotiation (use default 1500)",
+      OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
+    { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+      "Disable MRU negotiation (use default 1500)",
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
+
+    { "mtu", o_int, &lcp_allowoptions[0].mru,
+      "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
+
+    { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
+      "Disable protocol field compression",
+      OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
+    { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
+      "Disable protocol field compression",
+      OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
+
+    { "passive", o_bool, &lcp_wantoptions[0].passive,
+      "Set passive mode", 1 },
+    { "-p", o_bool, &lcp_wantoptions[0].passive,
+      "Set passive mode", OPT_ALIAS | 1 },
+
+    { "silent", o_bool, &lcp_wantoptions[0].silent,
+      "Set silent mode", 1 },
+
+    { "lcp-echo-failure", o_int, &lcp_echo_fails,
+      "Set number of consecutive echo failures to indicate link failure",
+      OPT_PRIO },
+    { "lcp-echo-interval", o_int, &lcp_echo_interval,
+      "Set time in seconds between LCP echo requests", OPT_PRIO },
+    { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
+      "Set time in seconds between LCP retransmissions", OPT_PRIO },
+    { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
+      "Set maximum number of LCP terminate-request transmissions", OPT_PRIO },
+    { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
+      "Set maximum number of LCP configure-request transmissions", OPT_PRIO },
+    { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
+      "Set limit on number of LCP configure-naks", OPT_PRIO },
+
+    { "receive-all", o_bool, &lax_recv,
+      "Accept all received control characters", 1 },
+
+#ifdef HAVE_MULTILINK
+    { "mrru", o_int, &lcp_wantoptions[0].mrru,
+      "Maximum received packet size for multilink bundle",
+      OPT_PRIO, &lcp_wantoptions[0].neg_mrru },
+
+    { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
+      "Use short sequence numbers in multilink headers",
+      OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf },
+    { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
+      "Don't use short sequence numbers in multilink headers",
+      OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf },
+
+    { "endpoint", o_special, (void *) setendpoint,
+      "Endpoint discriminator for multilink",
+      OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint },
+#endif /* HAVE_MULTILINK */
+
+    { "noendpoint", o_bool, &noendpoint,
+      "Don't send or accept multilink endpoint discriminator", 1 },
+
+    {NULL}
+};
+
+/* global vars */
+fsm lcp_fsm[NUM_PPP];			/* LCP fsm structure (global)*/
+lcp_options lcp_wantoptions[NUM_PPP];	/* Options that we want to request */
+lcp_options lcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
+lcp_options lcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */
+lcp_options lcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
+
+static int lcp_echos_pending = 0;	/* Number of outstanding echo msgs */
+static int lcp_echo_number   = 0;	/* ID number of next echo frame */
+static int lcp_echo_timer_running = 0;  /* set if a timer is running */
+
+static u_char nak_buffer[PPP_MRU];	/* where we construct a nak packet */
+static int now_unit;
+
+/*
+ * Callbacks for fsm code.  (CI = Configuration Information)
+ */
+static void lcp_resetci __P((fsm *));	/* Reset our CI */
+static int  lcp_cilen __P((fsm *));		/* Return length of our CI */
+static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
+static int  lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
+static int  lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
+static int  lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
+static int  lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
+static void lcp_up __P((fsm *));		/* We're UP */
+static void lcp_down __P((fsm *));		/* We're DOWN */
+static void lcp_starting __P((fsm *));	/* We need lower layer up */
+static void lcp_finished __P((fsm *));	/* We need lower layer down */
+static int  lcp_extcode __P((fsm *, int, int, u_char *, int));
+static void lcp_rprotrej __P((fsm *, u_char *, int));
+
+/*
+ * routines to send LCP echos to peer
+ */
+
+static void lcp_echo_lowerup __P((int));
+static void lcp_echo_lowerdown __P((int));
+static void LcpEchoTimeout __P((void *));
+static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));
+static void LcpSendEchoRequest __P((fsm *));
+static void LcpLinkFailure __P((fsm *));
+static void LcpEchoCheck __P((fsm *));
+
+static fsm_callbacks lcp_callbacks = {	/* LCP callback routines */
+    lcp_resetci,		/* Reset our Configuration Information */
+    lcp_cilen,			/* Length of our Configuration Information */
+    lcp_addci,			/* Add our Configuration Information */
+    lcp_ackci,			/* ACK our Configuration Information */
+    lcp_nakci,			/* NAK our Configuration Information */
+    lcp_rejci,			/* Reject our Configuration Information */
+    lcp_reqci,			/* Request peer's Configuration Information */
+    lcp_up,			/* Called when fsm reaches OPENED state */
+    lcp_down,			/* Called when fsm leaves OPENED state */
+    lcp_starting,		/* Called when we want the lower layer up */
+    lcp_finished,		/* Called when we want the lower layer down */
+    NULL,			/* Called when Protocol-Reject received */
+    NULL,			/* Retransmission is necessary */
+    lcp_extcode,		/* Called to handle LCP-specific codes */
+    "LCP"			/* String name of protocol */
+};
+
+/*
+ * Protocol entry points.
+ * Some of these are called directly.
+ */
+
+static void lcp_init __P((int));
+static void lcp_input __P((int, u_char *, int));
+static void lcp_protrej __P((int));
+static int  lcp_printpkt __P((u_char *, int,
+			      void (*) __P((void *, char *, ...)), void *));
+
+struct protent lcp_protent = {
+    PPP_LCP,
+    lcp_init,
+    lcp_input,
+    lcp_protrej,
+    lcp_lowerup,
+    lcp_lowerdown,
+    lcp_open,
+    lcp_close,
+    lcp_printpkt,
+    NULL,
+    1,
+    "LCP",
+    NULL,
+    lcp_option_list,
+    NULL,
+    NULL,
+    NULL
+};
+
+int lcp_loopbackfail = DEFLOOPBACKFAIL;
+
+/*
+ * Length of each type of configuration option (in octets)
+ */
+#define CILEN_VOID	2
+#define CILEN_CHAR	3
+#define CILEN_SHORT	4	/* CILEN_VOID + 2 */
+#define CILEN_CHAP	5	/* CILEN_VOID + 2 + 1 */
+#define CILEN_LONG	6	/* CILEN_VOID + 4 */
+#define CILEN_LQR	8	/* CILEN_VOID + 2 + 4 */
+#define CILEN_CBCP	3
+
+#define CODENAME(x)	((x) == CONFACK ? "ACK" : \
+			 (x) == CONFNAK ? "NAK" : "REJ")
+
+/*
+ * noopt - Disable all options (why?).
+ */
+static int
+noopt(argv)
+    char **argv;
+{
+    BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
+    BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
+
+    return (1);
+}
+
+#ifdef HAVE_MULTILINK
+static int
+setendpoint(argv)
+    char **argv;
+{
+    if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
+	lcp_wantoptions[0].neg_endpoint = 1;
+	return 1;
+    }
+    option_error("Can't parse '%s' as an endpoint discriminator", *argv);
+    return 0;
+}
+
+static void
+printendpoint(opt, printer, arg)
+    option_t *opt;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+	printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
+}
+#endif /* HAVE_MULTILINK */
+
+/*
+ * lcp_init - Initialize LCP.
+ */
+static void
+lcp_init(unit)
+    int unit;
+{
+    fsm *f = &lcp_fsm[unit];
+    lcp_options *wo = &lcp_wantoptions[unit];
+    lcp_options *ao = &lcp_allowoptions[unit];
+
+    f->unit = unit;
+    f->protocol = PPP_LCP;
+    f->callbacks = &lcp_callbacks;
+
+    fsm_init(f);
+
+    BZERO(wo, sizeof(*wo));
+    wo->neg_mru = 1;
+    wo->mru = DEFMRU;
+    wo->neg_asyncmap = 1;
+    wo->use_digest = 1;
+#ifdef CHAPMS
+    if(wo->use_chapms_v2)
+	wo->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(wo->use_chapms)
+	wo->chap_mdtype = CHAP_MICROSOFT;
+    else
+#endif
+    if(wo->use_digest)
+	wo->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+	refuse_chap = 1;
+    wo->neg_magicnumber = 1;
+    wo->neg_pcompression = 1;
+    wo->neg_accompression = 1;
+
+    BZERO(ao, sizeof(*ao));
+    ao->neg_mru = 1;
+    ao->mru = MAXMRU;
+    ao->neg_asyncmap = 1;
+    ao->neg_chap = 1;
+    ao->use_digest = 1;
+#ifdef CHAPMS
+    ao->use_chapms_v2 = ao->use_chapms = 1;
+    if(ao->use_chapms_v2)
+	ao->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(ao->use_chapms)
+	ao->chap_mdtype = CHAP_MICROSOFT;
+    else
+#else
+    if(ao->use_digest)
+	ao->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+	refuse_chap = 1;
+#endif
+    ao->neg_upap = 1;
+    ao->neg_magicnumber = 1;
+    ao->neg_pcompression = 1;
+    ao->neg_accompression = 1;
+#ifdef CBCP_SUPPORT
+    ao->neg_cbcp = 1;
+#endif
+    ao->neg_endpoint = 1;
+}
+
+
+/*
+ * lcp_open - LCP is allowed to come up.
+ */
+void
+lcp_open(unit)
+    int unit;
+{
+    fsm *f = &lcp_fsm[unit];
+    lcp_options *wo = &lcp_wantoptions[unit];
+
+    f->flags &= ~(OPT_PASSIVE | OPT_SILENT);
+    if (wo->passive)
+	f->flags |= OPT_PASSIVE;
+    if (wo->silent)
+	f->flags |= OPT_SILENT;
+    fsm_open(f);
+}
+
+
+/*
+ * lcp_close - Take LCP down.
+ */
+void
+lcp_close(unit, reason)
+    int unit;
+    char *reason;
+{
+    fsm *f = &lcp_fsm[unit];
+
+    if (phase != PHASE_DEAD)
+	new_phase(PHASE_TERMINATE);
+    if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
+	/*
+	 * This action is not strictly according to the FSM in RFC1548,
+	 * but it does mean that the program terminates if you do a
+	 * lcp_close() in passive/silent mode when a connection hasn't
+	 * been established.
+	 */
+	f->state = CLOSED;
+	lcp_finished(f);
+
+    } else
+	fsm_close(&lcp_fsm[unit], reason);
+}
+
+
+/*
+ * lcp_lowerup - The lower layer is up.
+ */
+void
+lcp_lowerup(unit)
+    int unit;
+{
+    lcp_options *wo = &lcp_wantoptions[unit];
+    fsm *f = &lcp_fsm[unit];
+
+    /*
+     * Don't use A/C or protocol compression on transmission,
+     * but accept A/C and protocol compressed packets
+     * if we are going to ask for A/C and protocol compression.
+     */
+    ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
+    ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff),
+		    wo->neg_pcompression, wo->neg_accompression);
+    peer_mru[unit] = PPP_MRU;
+
+    if (listen_time != 0) {
+	f->flags |= DELAYED_UP;
+	timeout(lcp_delayed_up, f, 0, listen_time * 1000);
+    } else
+	fsm_lowerup(f);
+}
+
+
+/*
+ * lcp_lowerdown - The lower layer is down.
+ */
+void
+lcp_lowerdown(unit)
+    int unit;
+{
+    fsm *f = &lcp_fsm[unit];
+
+    if (f->flags & DELAYED_UP)
+	f->flags &= ~DELAYED_UP;
+    else
+	fsm_lowerdown(&lcp_fsm[unit]);
+}
+
+
+/*
+ * lcp_delayed_up - Bring the lower layer up now.
+ */
+static void
+lcp_delayed_up(arg)
+    void *arg;
+{
+    fsm *f = arg;
+
+    if (f->flags & DELAYED_UP) {
+	f->flags &= ~DELAYED_UP;
+	fsm_lowerup(f);
+    }
+}
+
+
+/*
+ * lcp_input - Input LCP packet.
+ */
+static void
+lcp_input(unit, p, len)
+    int unit;
+    u_char *p;
+    int len;
+{
+    fsm *f = &lcp_fsm[unit];
+
+    if (f->flags & DELAYED_UP) {
+	f->flags &= ~DELAYED_UP;
+	fsm_lowerup(f);
+    }
+    fsm_input(f, p, len);
+}
+
+
+/*
+ * lcp_extcode - Handle a LCP-specific code.
+ */
+static int
+lcp_extcode(f, code, id, inp, len)
+    fsm *f;
+    int code, id;
+    u_char *inp;
+    int len;
+{
+    u_char *magp;
+
+    switch( code ){
+    case PROTREJ:
+	lcp_rprotrej(f, inp, len);
+	break;
+    
+    case ECHOREQ:
+	if (f->state != OPENED)
+	    break;
+	magp = inp;
+	PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
+	fsm_sdata(f, ECHOREP, id, inp, len);
+	break;
+    
+    case ECHOREP:
+	lcp_received_echo_reply(f, id, inp, len);
+	break;
+
+    case DISCREQ:
+	break;
+
+    default:
+	return 0;
+    }
+    return 1;
+}
+
+    
+/*
+ * lcp_rprotrej - Receive an Protocol-Reject.
+ *
+ * Figure out which protocol is rejected and inform it.
+ */
+static void
+lcp_rprotrej(f, inp, len)
+    fsm *f;
+    u_char *inp;
+    int len;
+{
+    int i;
+    struct protent *protp;
+    u_short prot;
+
+    if (len < 2) {
+	LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
+	return;
+    }
+
+    GETSHORT(prot, inp);
+
+    /*
+     * Protocol-Reject packets received in any state other than the LCP
+     * OPENED state SHOULD be silently discarded.
+     */
+    if( f->state != OPENED ){
+	LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
+	return;
+    }
+
+    /*
+     * Upcall the proper Protocol-Reject routine.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->protocol == prot && protp->enabled_flag) {
+	    (*protp->protrej)(f->unit);
+	    return;
+	}
+
+    warn("Protocol-Reject for unsupported protocol 0x%x", prot);
+}
+
+
+/*
+ * lcp_protrej - A Protocol-Reject was received.
+ */
+/*ARGSUSED*/
+static void
+lcp_protrej(unit)
+    int unit;
+{
+    /*
+     * Can't reject LCP!
+     */
+    error("Received Protocol-Reject for LCP!");
+    fsm_protreject(&lcp_fsm[unit]);
+}
+
+
+/*
+ * lcp_sprotrej - Send a Protocol-Reject for some protocol.
+ */
+void
+lcp_sprotrej(unit, p, len)
+    int unit;
+    u_char *p;
+    int len;
+{
+    /*
+     * Send back the protocol and the information field of the
+     * rejected packet.  We only get here if LCP is in the OPENED state.
+     */
+    p += 2;
+    len -= 2;
+
+    fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
+	      p, len);
+}
+
+
+/*
+ * lcp_resetci - Reset our CI.
+ */
+static void
+lcp_resetci(f)
+    fsm *f;
+{
+    lcp_options *wo = &lcp_wantoptions[f->unit];
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    lcp_options *ao = &lcp_allowoptions[f->unit];
+
+    wo->magicnumber = magic();
+    wo->numloops = 0;
+    *go = *wo;
+    if (!multilink) {
+	go->neg_mrru = 0;
+	go->neg_ssnhf = 0;
+	go->neg_endpoint = 0;
+    }
+    if (noendpoint)
+	ao->neg_endpoint = 0;
+    peer_mru[f->unit] = PPP_MRU;
+    auth_reset(f->unit);
+}
+
+
+/*
+ * lcp_cilen - Return length of our CI.
+ */
+static int
+lcp_cilen(f)
+    fsm *f;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+
+#define LENCIVOID(neg)	((neg) ? CILEN_VOID : 0)
+#define LENCICHAP(neg)	((neg) ? CILEN_CHAP : 0)
+#define LENCISHORT(neg)	((neg) ? CILEN_SHORT : 0)
+#define LENCILONG(neg)	((neg) ? CILEN_LONG : 0)
+#define LENCILQR(neg)	((neg) ? CILEN_LQR: 0)
+#define LENCICBCP(neg)	((neg) ? CILEN_CBCP: 0)
+    /*
+     * NB: we only ask for one of CHAP and UPAP, even if we will
+     * accept either.
+     */
+#ifdef CHAPMS
+    if(go->use_chapms_v2)
+	go->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(go->use_chapms)
+	go->chap_mdtype = CHAP_MICROSOFT;
+    else
+#endif
+    if(go->use_digest)
+	go->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+	go->neg_chap = 0;
+
+    return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
+	    LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
+	    LENCICHAP(go->neg_chap) +
+	    LENCISHORT(!go->neg_chap && go->neg_upap) +
+	    LENCILQR(go->neg_lqr) +
+	    LENCICBCP(go->neg_cbcp) +
+	    LENCILONG(go->neg_magicnumber) +
+	    LENCIVOID(go->neg_pcompression) +
+	    LENCIVOID(go->neg_accompression) +
+	    LENCISHORT(go->neg_mrru) +
+	    LENCIVOID(go->neg_ssnhf) +
+	    (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
+}
+
+
+/*
+ * lcp_addci - Add our desired CIs to a packet.
+ */
+static void
+lcp_addci(f, ucp, lenp)
+    fsm *f;
+    u_char *ucp;
+    int *lenp;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    u_char *start_ucp = ucp;
+
+#define ADDCIVOID(opt, neg) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_VOID, ucp); \
+    }
+#define ADDCISHORT(opt, neg, val) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_SHORT, ucp); \
+	PUTSHORT(val, ucp); \
+    }
+#define ADDCICHAP(opt, neg, val, digest) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_CHAP, ucp); \
+	PUTSHORT(val, ucp); \
+	PUTCHAR(digest, ucp); \
+    }
+#define ADDCILONG(opt, neg, val) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_LONG, ucp); \
+	PUTLONG(val, ucp); \
+    }
+#define ADDCILQR(opt, neg, val) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_LQR, ucp); \
+	PUTSHORT(PPP_LQR, ucp); \
+	PUTLONG(val, ucp); \
+    }
+#define ADDCICHAR(opt, neg, val) \
+    if (neg) { \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_CHAR, ucp); \
+	PUTCHAR(val, ucp); \
+    }
+#define ADDCIENDP(opt, neg, class, val, len) \
+    if (neg) { \
+	int i; \
+	PUTCHAR(opt, ucp); \
+	PUTCHAR(CILEN_CHAR + len, ucp); \
+	PUTCHAR(class, ucp); \
+	for (i = 0; i < len; ++i) \
+	    PUTCHAR(val[i], ucp); \
+    }
+
+    ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+    ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
+	      go->asyncmap);
+    ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
+    ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
+    ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
+    ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
+    ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
+    ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
+    ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
+    ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
+    ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
+    ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
+	      go->endpoint.value, go->endpoint.length);
+
+    if (ucp - start_ucp != *lenp) {
+	/* this should never happen, because peer_mtu should be 1500 */
+	error("Bug in lcp_addci: wrong length");
+    }
+}
+
+
+/*
+ * lcp_ackci - Ack our CIs.
+ * This should not modify any state if the Ack is bad.
+ *
+ * Returns:
+ *	0 - Ack was bad.
+ *	1 - Ack was good.
+ */
+static int
+lcp_ackci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    u_char cilen, citype, cichar;
+    u_short cishort;
+    u_int32_t cilong;
+
+    /*
+     * CIs must be in exactly the same order that we sent.
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+#define ACKCIVOID(opt, neg) \
+    if (neg) { \
+	if ((len -= CILEN_VOID) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_VOID || \
+	    citype != opt) \
+	    goto bad; \
+    }
+#define ACKCISHORT(opt, neg, val) \
+    if (neg) { \
+	if ((len -= CILEN_SHORT) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_SHORT || \
+	    citype != opt) \
+	    goto bad; \
+	GETSHORT(cishort, p); \
+	if (cishort != val) \
+	    goto bad; \
+    }
+#define ACKCICHAR(opt, neg, val) \
+    if (neg) { \
+	if ((len -= CILEN_CHAR) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_CHAR || \
+	    citype != opt) \
+	    goto bad; \
+	GETCHAR(cichar, p); \
+	if (cichar != val) \
+	    goto bad; \
+    }
+#define ACKCICHAP(opt, neg, val, digest) \
+    if (neg) { \
+	if ((len -= CILEN_CHAP) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_CHAP || \
+	    citype != opt) \
+	    goto bad; \
+	GETSHORT(cishort, p); \
+	if (cishort != val) \
+	    goto bad; \
+	GETCHAR(cichar, p); \
+	if (cichar != digest) \
+	  goto bad; \
+    }
+#define ACKCILONG(opt, neg, val) \
+    if (neg) { \
+	if ((len -= CILEN_LONG) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_LONG || \
+	    citype != opt) \
+	    goto bad; \
+	GETLONG(cilong, p); \
+	if (cilong != val) \
+	    goto bad; \
+    }
+#define ACKCILQR(opt, neg, val) \
+    if (neg) { \
+	if ((len -= CILEN_LQR) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_LQR || \
+	    citype != opt) \
+	    goto bad; \
+	GETSHORT(cishort, p); \
+	if (cishort != PPP_LQR) \
+	    goto bad; \
+	GETLONG(cilong, p); \
+	if (cilong != val) \
+	  goto bad; \
+    }
+#define ACKCIENDP(opt, neg, class, val, vlen) \
+    if (neg) { \
+	int i; \
+	if ((len -= CILEN_CHAR + vlen) < 0) \
+	    goto bad; \
+	GETCHAR(citype, p); \
+	GETCHAR(cilen, p); \
+	if (cilen != CILEN_CHAR + vlen || \
+	    citype != opt) \
+	    goto bad; \
+	GETCHAR(cichar, p); \
+	if (cichar != class) \
+	    goto bad; \
+	for (i = 0; i < vlen; ++i) { \
+	    GETCHAR(cichar, p); \
+	    if (cichar != val[i]) \
+		goto bad; \
+	} \
+    }
+
+    ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+    ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
+	      go->asyncmap);
+    ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
+    ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
+    ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
+    ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
+    ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
+    ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
+    ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
+    ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
+    ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
+    ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
+	      go->endpoint.value, go->endpoint.length);
+
+    /*
+     * If there are any remaining CIs, then this packet is bad.
+     */
+    if (len != 0)
+	goto bad;
+    return (1);
+bad:
+    LCPDEBUG(("lcp_acki: received bad Ack!"));
+    return (0);
+}
+
+
+/*
+ * lcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if LCP is in the OPENED state.
+ *
+ * Returns:
+ *	0 - Nak was bad.
+ *	1 - Nak was good.
+ */
+static int
+lcp_nakci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    lcp_options *wo = &lcp_wantoptions[f->unit];
+    u_char citype, cichar, *next;
+    u_short cishort;
+    u_int32_t cilong;
+    lcp_options no;		/* options we've seen Naks for */
+    lcp_options try;		/* options to request next time */
+    int looped_back = 0;
+    int cilen;
+
+    BZERO(&no, sizeof(no));
+    try = *go;
+
+    /*
+     * Any Nak'd CIs must be in exactly the same order that we sent.
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+#define NAKCIVOID(opt, neg) \
+    if (go->neg && \
+	len >= CILEN_VOID && \
+	p[1] == CILEN_VOID && \
+	p[0] == opt) { \
+	len -= CILEN_VOID; \
+	INCPTR(CILEN_VOID, p); \
+	no.neg = 1; \
+	try.neg = 0; \
+    }
+#define NAKCICHAP(opt, neg, code) \
+    if (go->neg && \
+	len >= CILEN_CHAP && \
+	p[1] == CILEN_CHAP && \
+	p[0] == opt) { \
+	len -= CILEN_CHAP; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	GETCHAR(cichar, p); \
+	no.neg = 1; \
+	code \
+    }
+#define NAKCICHAR(opt, neg, code) \
+    if (go->neg && \
+	len >= CILEN_CHAR && \
+	p[1] == CILEN_CHAR && \
+	p[0] == opt) { \
+	len -= CILEN_CHAR; \
+	INCPTR(2, p); \
+	GETCHAR(cichar, p); \
+	no.neg = 1; \
+	code \
+    }
+#define NAKCISHORT(opt, neg, code) \
+    if (go->neg && \
+	len >= CILEN_SHORT && \
+	p[1] == CILEN_SHORT && \
+	p[0] == opt) { \
+	len -= CILEN_SHORT; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	no.neg = 1; \
+	code \
+    }
+#define NAKCILONG(opt, neg, code) \
+    if (go->neg && \
+	len >= CILEN_LONG && \
+	p[1] == CILEN_LONG && \
+	p[0] == opt) { \
+	len -= CILEN_LONG; \
+	INCPTR(2, p); \
+	GETLONG(cilong, p); \
+	no.neg = 1; \
+	code \
+    }
+#define NAKCILQR(opt, neg, code) \
+    if (go->neg && \
+	len >= CILEN_LQR && \
+	p[1] == CILEN_LQR && \
+	p[0] == opt) { \
+	len -= CILEN_LQR; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	GETLONG(cilong, p); \
+	no.neg = 1; \
+	code \
+    }
+#define NAKCIENDP(opt, neg) \
+    if (go->neg && \
+	len >= CILEN_CHAR && \
+	p[0] == opt && \
+	p[1] >= CILEN_CHAR && \
+	p[1] <= len) { \
+	len -= p[1]; \
+	INCPTR(p[1], p); \
+	no.neg = 1; \
+	try.neg = 0; \
+    }
+
+    /*
+     * We don't care if they want to send us smaller packets than
+     * we want.  Therefore, accept any MRU less than what we asked for,
+     * but then ignore the new value when setting the MRU in the kernel.
+     * If they send us a bigger MRU than what we asked, accept it, up to
+     * the limit of the default MRU we'd get if we didn't negotiate.
+     */
+    if (go->neg_mru && go->mru != DEFMRU) {
+	NAKCISHORT(CI_MRU, neg_mru,
+		   if (cishort <= wo->mru || cishort <= DEFMRU)
+		       try.mru = cishort;
+		   );
+    }
+
+    /*
+     * Add any characters they want to our (receive-side) asyncmap.
+     */
+    if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
+	NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
+		  try.asyncmap = go->asyncmap | cilong;
+		  );
+    }
+
+    /*
+     * If they've nak'd our authentication-protocol, check whether
+     * they are proposing a different protocol, or a different
+     * hash algorithm for CHAP.
+     */
+    if ((go->neg_chap || go->neg_upap)
+	&& len >= CILEN_SHORT
+	&& p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
+	cilen = p[1];
+	len -= cilen;
+	no.neg_chap = go->neg_chap;
+	no.neg_upap = go->neg_upap;
+	INCPTR(2, p);
+        GETSHORT(cishort, p);
+	if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
+	    /*
+	     * If we were asking for CHAP, they obviously don't want to do it.
+	     * If we weren't asking for CHAP, then we were asking for PAP,
+	     * in which case this Nak is bad.
+	     */
+	    if (!go->neg_chap)
+		goto bad;
+	    try.neg_chap = 0;
+
+	} else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
+	    GETCHAR(cichar, p);
+	    if (go->neg_chap) {
+		/*
+		 * We were asking for CHAP/MD5; they must want a different
+		 * algorithm.  If they can't do MD5, we can ask for M$-CHAP
+		 * if we support it, otherwise we'll have to stop
+		 * asking for CHAP.
+		 */
+ 		if (go->chap_mdtype == CHAP_MICROSOFT_V2)
+ 		{
+ 		    try.use_chapms_v2 = 0;
+ 		    if(try.use_chapms)
+ 			try.chap_mdtype = CHAP_MICROSOFT;
+ 		    else if(try.use_digest)
+ 			try.chap_mdtype = CHAP_DIGEST_MD5;
+ 		    else
+ 			try.neg_chap = 0;
+ 		}
+ 		else if(go->chap_mdtype == CHAP_MICROSOFT)
+ 		{
+ 		    try.use_chapms = 0;
+ 		    if(try.use_digest)
+ 			try.chap_mdtype = CHAP_DIGEST_MD5;
+ 		    else
+ 			try.neg_chap = 0;
+ 		}
+ 		else if(go->chap_mdtype == CHAP_DIGEST_MD5)
+ 		{
+ 		    try.use_digest = 0;
+ 		    try.neg_chap = 0;
+ 		}
+ 		else
+ 		    try.neg_chap = 0;
+ 		if ((cichar != CHAP_MICROSOFT_V2) &&
+ 		    (cichar != CHAP_MICROSOFT) &&
+ 		    (cichar != CHAP_DIGEST_MD5))
+			try.neg_chap = 0;
+	    } else {
+		/*
+		 * Stop asking for PAP if we were asking for it.
+		 */
+		try.neg_upap = 0;
+	    }
+
+	} else {
+	    /*
+	     * We don't recognize what they're suggesting.
+	     * Stop asking for what we were asking for.
+	     */
+	    if (go->neg_chap)
+		try.neg_chap = 0;
+	    else
+		try.neg_upap = 0;
+	    p += cilen - CILEN_SHORT;
+	}
+    }
+
+    NAKCILQR(CI_QUALITY, neg_lqr,
+	     if (cishort != PPP_LQR)
+		 try.neg_lqr = 0;
+	     else
+		 try.lqr_period = cilong;
+	     );
+
+    /*
+     * Only implementing CBCP...not the rest of the callback options
+     */
+    NAKCICHAR(CI_CALLBACK, neg_cbcp,
+              try.neg_cbcp = 0;
+              );
+
+    /*
+     * Check for a looped-back line.
+     */
+    NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
+	      try.magicnumber = magic();
+	      looped_back = 1;
+	      );
+
+    /*
+     * Peer shouldn't send Nak for protocol compression or
+     * address/control compression requests; they should send
+     * a Reject instead.  If they send a Nak, treat it as a Reject.
+     */
+    NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
+    NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
+
+    /*
+     * Nak for MRRU option - accept their value if it is smaller
+     * than the one we want.
+     */
+    if (go->neg_mrru) {
+	NAKCISHORT(CI_MRRU, neg_mrru,
+		   if (cishort <= wo->mrru)
+		       try.mrru = cishort;
+		   );
+    }
+
+    /*
+     * Nak for short sequence numbers shouldn't be sent, treat it
+     * like a reject.
+     */
+    NAKCIVOID(CI_SSNHF, neg_ssnhf);
+
+    /*
+     * Nak of the endpoint discriminator option is not permitted,
+     * treat it like a reject.
+     */
+    NAKCIENDP(CI_EPDISC, neg_endpoint);
+
+    /*
+     * There may be remaining CIs, if the peer is requesting negotiation
+     * on an option that we didn't include in our request packet.
+     * If we see an option that we requested, or one we've already seen
+     * in this packet, then this packet is bad.
+     * If we wanted to respond by starting to negotiate on the requested
+     * option(s), we could, but we don't, because except for the
+     * authentication type and quality protocol, if we are not negotiating
+     * an option, it is because we were told not to.
+     * For the authentication type, the Nak from the peer means
+     * `let me authenticate myself with you' which is a bit pointless.
+     * For the quality protocol, the Nak means `ask me to send you quality
+     * reports', but if we didn't ask for them, we don't want them.
+     * An option we don't recognize represents the peer asking to
+     * negotiate some option we don't support, so ignore it.
+     */
+    while (len > CILEN_VOID) {
+	GETCHAR(citype, p);
+	GETCHAR(cilen, p);
+	if (cilen < CILEN_VOID || (len -= cilen) < 0)
+	    goto bad;
+	next = p + cilen - 2;
+
+	switch (citype) {
+	case CI_MRU:
+	    if ((go->neg_mru && go->mru != DEFMRU)
+		|| no.neg_mru || cilen != CILEN_SHORT)
+		goto bad;
+	    GETSHORT(cishort, p);
+	    if (cishort < DEFMRU) {
+		try.neg_mru = 1;
+		try.mru = cishort;
+	    }
+	    break;
+	case CI_ASYNCMAP:
+	    if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
+		|| no.neg_asyncmap || cilen != CILEN_LONG)
+		goto bad;
+	    break;
+	case CI_AUTHTYPE:
+	    if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
+		goto bad;
+	    break;
+	case CI_MAGICNUMBER:
+	    if (go->neg_magicnumber || no.neg_magicnumber ||
+		cilen != CILEN_LONG)
+		goto bad;
+	    break;
+	case CI_PCOMPRESSION:
+	    if (go->neg_pcompression || no.neg_pcompression
+		|| cilen != CILEN_VOID)
+		goto bad;
+	    break;
+	case CI_ACCOMPRESSION:
+	    if (go->neg_accompression || no.neg_accompression
+		|| cilen != CILEN_VOID)
+		goto bad;
+	    break;
+	case CI_QUALITY:
+	    if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
+		goto bad;
+	    break;
+	case CI_MRRU:
+	    if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
+		goto bad;
+	    break;
+	case CI_SSNHF:
+	    if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
+		goto bad;
+	    try.neg_ssnhf = 1;
+	    break;
+	case CI_EPDISC:
+	    if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
+		goto bad;
+	    break;
+	}
+	p = next;
+    }
+
+    /*
+     * OK, the Nak is good.  Now we can update state.
+     * If there are any options left we ignore them.
+     */
+    if (f->state != OPENED) {
+	if (looped_back) {
+	    if (++try.numloops >= lcp_loopbackfail) {
+		notice("Serial line is looped back.");
+		lcp_close(f->unit, "Loopback detected");
+		status = EXIT_LOOPBACK;
+	    }
+	} else
+	    try.numloops = 0;
+	*go = try;
+    }
+
+    return 1;
+
+bad:
+    LCPDEBUG(("lcp_nakci: received bad Nak!"));
+    return 0;
+}
+
+
+/*
+ * lcp_rejci - Peer has Rejected some of our CIs.
+ * This should not modify any state if the Reject is bad
+ * or if LCP is in the OPENED state.
+ *
+ * Returns:
+ *	0 - Reject was bad.
+ *	1 - Reject was good.
+ */
+static int
+lcp_rejci(f, p, len)
+    fsm *f;
+    u_char *p;
+    int len;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    u_char cichar;
+    u_short cishort;
+    u_int32_t cilong;
+    lcp_options try;		/* options to request next time */
+
+    try = *go;
+
+    /*
+     * Any Rejected CIs must be in exactly the same order that we sent.
+     * Check packet length and CI length at each step.
+     * If we find any deviations, then this packet is bad.
+     */
+#define REJCIVOID(opt, neg) \
+    if (go->neg && \
+	len >= CILEN_VOID && \
+	p[1] == CILEN_VOID && \
+	p[0] == opt) { \
+	len -= CILEN_VOID; \
+	INCPTR(CILEN_VOID, p); \
+	try.neg = 0; \
+    }
+#define REJCISHORT(opt, neg, val) \
+    if (go->neg && \
+	len >= CILEN_SHORT && \
+	p[1] == CILEN_SHORT && \
+	p[0] == opt) { \
+	len -= CILEN_SHORT; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	/* Check rejected value. */ \
+	if (cishort != val) \
+	    goto bad; \
+	try.neg = 0; \
+    }
+#define REJCICHAP(opt, neg, val, digest) \
+    if (go->neg && \
+	len >= CILEN_CHAP && \
+	p[1] == CILEN_CHAP && \
+	p[0] == opt) { \
+	len -= CILEN_CHAP; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	GETCHAR(cichar, p); \
+	/* Check rejected value. */ \
+	if (cishort != val || cichar != digest) \
+	    goto bad; \
+	switch(digest) \
+	{ \
+	    case CHAP_MICROSOFT_V2: \
+		try.use_chapms_v2 = 0; \
+		break; \
+	    case CHAP_MICROSOFT: \
+		try.use_chapms = 0; \
+		break; \
+	    case CHAP_DIGEST_MD5: \
+		try.use_digest = 0; \
+	} \
+	if(!try.use_chapms_v2 && !try.use_chapms && !try.use_digest) \
+	{ \
+	    try.neg = 0; \
+	    try.neg_upap = 0; \
+	} \
+    }
+#define REJCILONG(opt, neg, val) \
+    if (go->neg && \
+	len >= CILEN_LONG && \
+	p[1] == CILEN_LONG && \
+	p[0] == opt) { \
+	len -= CILEN_LONG; \
+	INCPTR(2, p); \
+	GETLONG(cilong, p); \
+	/* Check rejected value. */ \
+	if (cilong != val) \
+	    goto bad; \
+	try.neg = 0; \
+    }
+#define REJCILQR(opt, neg, val) \
+    if (go->neg && \
+	len >= CILEN_LQR && \
+	p[1] == CILEN_LQR && \
+	p[0] == opt) { \
+	len -= CILEN_LQR; \
+	INCPTR(2, p); \
+	GETSHORT(cishort, p); \
+	GETLONG(cilong, p); \
+	/* Check rejected value. */ \
+	if (cishort != PPP_LQR || cilong != val) \
+	    goto bad; \
+	try.neg = 0; \
+    }
+#define REJCICBCP(opt, neg, val) \
+    if (go->neg && \
+	len >= CILEN_CBCP && \
+	p[1] == CILEN_CBCP && \
+	p[0] == opt) { \
+	len -= CILEN_CBCP; \
+	INCPTR(2, p); \
+	GETCHAR(cichar, p); \
+	/* Check rejected value. */ \
+	if (cichar != val) \
+	    goto bad; \
+	try.neg = 0; \
+    }
+#define REJCIENDP(opt, neg, class, val, vlen) \
+    if (go->neg && \
+	len >= CILEN_CHAR + vlen && \
+	p[0] == opt && \
+	p[1] == CILEN_CHAR + vlen) { \
+	int i; \
+	len -= CILEN_CHAR + vlen; \
+	INCPTR(2, p); \
+	GETCHAR(cichar, p); \
+	if (cichar != class) \
+	    goto bad; \
+	for (i = 0; i < vlen; ++i) { \
+	    GETCHAR(cichar, p); \
+	    if (cichar != val[i]) \
+		goto bad; \
+	} \
+	try.neg = 0; \
+    }
+
+    REJCISHORT(CI_MRU, neg_mru, go->mru);
+    REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
+    REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
+    if (!go->neg_chap) {
+	REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
+    }
+    REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
+    REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
+    REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
+    REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
+    REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
+    REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
+    REJCIVOID(CI_SSNHF, neg_ssnhf);
+    REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
+	      go->endpoint.value, go->endpoint.length);
+
+    /*
+     * If there are any remaining CIs, then this packet is bad.
+     */
+    if (len != 0)
+	goto bad;
+    /*
+     * Now we can update state.
+     */
+    if (f->state != OPENED)
+	*go = try;
+    return 1;
+
+bad:
+    LCPDEBUG(("lcp_rejci: received bad Reject!"));
+    return 0;
+}
+
+
+/*
+ * lcp_reqci - Check the peer's requested CIs and send appropriate response.
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately.  If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+lcp_reqci(f, inp, lenp, reject_if_disagree)
+    fsm *f;
+    u_char *inp;		/* Requested CIs */
+    int *lenp;			/* Length of requested CIs */
+    int reject_if_disagree;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    lcp_options *ho = &lcp_hisoptions[f->unit];
+    lcp_options *ao = &lcp_allowoptions[f->unit];
+    u_char *cip, *next;		/* Pointer to current and next CIs */
+    int cilen, citype, cichar;	/* Parsed len, type, char value */
+    u_short cishort;		/* Parsed short value */
+    u_int32_t cilong;		/* Parse long value */
+    int rc = CONFACK;		/* Final packet return code */
+    int orc;			/* Individual option return code */
+    u_char *p;			/* Pointer to next char to parse */
+    u_char *rejp;		/* Pointer to next char in reject frame */
+    u_char *nakp;		/* Pointer to next char in Nak frame */
+    int l = *lenp;		/* Length left */
+
+    /*
+     * Reset all his options.
+     */
+    BZERO(ho, sizeof(*ho));
+
+    /*
+     * Process all his options.
+     */
+    next = inp;
+    nakp = nak_buffer;
+    rejp = inp;
+    while (l) {
+	orc = CONFACK;			/* Assume success */
+	cip = p = next;			/* Remember begining of CI */
+	if (l < 2 ||			/* Not enough data for CI header or */
+	    p[1] < 2 ||			/*  CI length too small or */
+	    p[1] > l) {			/*  CI length too big? */
+	    LCPDEBUG(("lcp_reqci: bad CI length!"));
+	    orc = CONFREJ;		/* Reject bad CI */
+	    cilen = l;			/* Reject till end of packet */
+	    l = 0;			/* Don't loop again */
+	    citype = 0;
+	    goto endswitch;
+	}
+	GETCHAR(citype, p);		/* Parse CI type */
+	GETCHAR(cilen, p);		/* Parse CI length */
+	l -= cilen;			/* Adjust remaining length */
+	next += cilen;			/* Step to next CI */
+
+	switch (citype) {		/* Check CI type */
+	case CI_MRU:
+	    if (!ao->neg_mru ||		/* Allow option? */
+		cilen != CILEN_SHORT) {	/* Check CI length */
+		orc = CONFREJ;		/* Reject CI */
+		break;
+	    }
+	    GETSHORT(cishort, p);	/* Parse MRU */
+
+	    /*
+	     * He must be able to receive at least our minimum.
+	     * No need to check a maximum.  If he sends a large number,
+	     * we'll just ignore it.
+	     */
+	    if (cishort < MINMRU) {
+		orc = CONFNAK;		/* Nak CI */
+		PUTCHAR(CI_MRU, nakp);
+		PUTCHAR(CILEN_SHORT, nakp);
+		PUTSHORT(MINMRU, nakp);	/* Give him a hint */
+		break;
+	    }
+	    else if (cishort > 1492) {
+		orc = CONFNAK;		/* Nak CI */
+		PUTCHAR(CI_MRU, nakp);
+		PUTCHAR(CILEN_SHORT, nakp);
+		PUTSHORT(1492, nakp);	/* Give him a hint */
+		break;
+	    }
+	    ho->neg_mru = 1;		/* Remember he sent MRU */
+	    ho->mru = cishort;		/* And remember value */
+	    break;
+
+	case CI_ASYNCMAP:
+	    if (!ao->neg_asyncmap ||
+		cilen != CILEN_LONG) {
+		orc = CONFREJ;
+		break;
+	    }
+	    GETLONG(cilong, p);
+
+	    /*
+	     * Asyncmap must have set at least the bits
+	     * which are set in lcp_allowoptions[unit].asyncmap.
+	     */
+	    if ((ao->asyncmap & ~cilong) != 0) {
+		orc = CONFNAK;
+		PUTCHAR(CI_ASYNCMAP, nakp);
+		PUTCHAR(CILEN_LONG, nakp);
+		PUTLONG(ao->asyncmap | cilong, nakp);
+		break;
+	    }
+	    ho->neg_asyncmap = 1;
+	    ho->asyncmap = cilong;
+	    break;
+
+	case CI_AUTHTYPE:
+	    if (cilen < CILEN_SHORT ||
+		!(ao->neg_upap || ao->neg_chap)) {
+		/*
+		 * Reject the option if we're not willing to authenticate.
+		 */
+		orc = CONFREJ;
+		break;
+	    }
+	    GETSHORT(cishort, p);
+
+	    /*
+	     * Authtype must be PAP or CHAP.
+	     *
+	     * Note: if both ao->neg_upap and ao->neg_chap are set,
+	     * and the peer sends a Configure-Request with two
+	     * authenticate-protocol requests, one for CHAP and one
+	     * for UPAP, then we will reject the second request.
+	     * Whether we end up doing CHAP or UPAP depends then on
+	     * the ordering of the CIs in the peer's Configure-Request.
+	     */
+
+	    if (cishort == PPP_PAP) {
+		if (ho->neg_chap ||	/* we've already accepted CHAP */
+		    cilen != CILEN_SHORT) {
+		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
+		    orc = CONFREJ;
+		    break;
+		}
+		if (!ao->neg_upap) {	/* we don't want to do PAP */
+		    orc = CONFNAK;	/* NAK it and suggest CHAP */
+		    PUTCHAR(CI_AUTHTYPE, nakp);
+		    PUTCHAR(CILEN_CHAP, nakp);
+		    PUTSHORT(PPP_CHAP, nakp);
+		    PUTCHAR(ao->chap_mdtype, nakp);
+		    break;
+		}
+		ho->neg_upap = 1;
+		break;
+	    }
+	    if (cishort == PPP_CHAP) {
+		if (ho->neg_upap ||	/* we've already accepted PAP */
+		    cilen != CILEN_CHAP) {
+		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
+		    orc = CONFREJ;
+		    break;
+		}
+		if (!ao->neg_chap) {	/* we don't want to do CHAP */
+		    orc = CONFNAK;	/* NAK it and suggest PAP */
+		    PUTCHAR(CI_AUTHTYPE, nakp);
+		    PUTCHAR(CILEN_SHORT, nakp);
+		    PUTSHORT(PPP_PAP, nakp);
+		    break;
+		}
+		GETCHAR(cichar, p);	/* get digest type*/
+		if (cichar != CHAP_DIGEST_MD5
+#ifdef CHAPMS
+		    && cichar != CHAP_MICROSOFT
+		    && cichar != CHAP_MICROSOFT_V2
+#endif
+		    ) {
+		    orc = CONFREJ; /* !!! CONFNAK !!! */
+		    PUTCHAR(CI_AUTHTYPE, nakp);
+		    PUTCHAR(CILEN_CHAP, nakp);
+		    PUTSHORT(PPP_CHAP, nakp);
+		    PUTCHAR(ao->chap_mdtype, nakp);
+		    break;
+		}
+		ho->chap_mdtype = cichar; /* save md type */
+		ho->neg_chap = 1;
+		break;
+	    }
+
+	    /*
+	     * We don't recognize the protocol they're asking for.
+	     * Nak it with something we're willing to do.
+	     * (At this point we know ao->neg_upap || ao->neg_chap.)
+	     */
+	    orc = CONFNAK;
+	    PUTCHAR(CI_AUTHTYPE, nakp);
+	    if (ao->neg_chap) {
+		PUTCHAR(CILEN_CHAP, nakp);
+		PUTSHORT(PPP_CHAP, nakp);
+		PUTCHAR(ao->chap_mdtype, nakp);
+	    } else {
+		PUTCHAR(CILEN_SHORT, nakp);
+		PUTSHORT(PPP_PAP, nakp);
+	    }
+	    break;
+
+	case CI_QUALITY:
+	    if (!ao->neg_lqr ||
+		cilen != CILEN_LQR) {
+		orc = CONFREJ;
+		break;
+	    }
+
+	    GETSHORT(cishort, p);
+	    GETLONG(cilong, p);
+
+	    if (cishort != PPP_LQR) {
+		orc = CONFNAK;
+		PUTCHAR(CI_QUALITY, nakp);
+		PUTCHAR(CILEN_LQR, nakp);
+		PUTSHORT(PPP_LQR, nakp);
+		PUTLONG(ao->lqr_period, nakp);
+		break;
+	    }
+	    break;
+
+	case CI_MAGICNUMBER:
+	    if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
+		cilen != CILEN_LONG) {
+		orc = CONFREJ;
+		break;
+	    }
+	    GETLONG(cilong, p);
+
+	    /*
+	     * He must have a different magic number.
+	     */
+	    if (go->neg_magicnumber &&
+		cilong == go->magicnumber) {
+		cilong = magic();	/* Don't put magic() inside macro! */
+		orc = CONFNAK;
+		PUTCHAR(CI_MAGICNUMBER, nakp);
+		PUTCHAR(CILEN_LONG, nakp);
+		PUTLONG(cilong, nakp);
+		break;
+	    }
+	    ho->neg_magicnumber = 1;
+	    ho->magicnumber = cilong;
+	    break;
+
+#ifdef CBCP_SUPPORT
+	case CI_CALLBACK:
+	    LCPDEBUG(("lcp_reqci: rcvd CBCP"));
+	    if (!ao->neg_cbcp ||
+		cilen != CILEN_CHAR) {
+		orc = CONFREJ;
+		break;
+	    }
+	    GETCHAR(cichar, p);
+	    if(cichar != CBCP_OPT)
+	    {
+		orc = CONFREJ;
+		break;
+	    }
+	    ho->neg_cbcp = 1;
+	    break;
+#endif
+
+	case CI_PCOMPRESSION:
+	    if (!ao->neg_pcompression ||
+		cilen != CILEN_VOID) {
+		orc = CONFREJ;
+		break;
+	    }
+	    ho->neg_pcompression = 1;
+	    break;
+
+	case CI_ACCOMPRESSION:
+	    if (!ao->neg_accompression ||
+		cilen != CILEN_VOID) {
+		orc = CONFREJ;
+		break;
+	    }
+	    ho->neg_accompression = 1;
+	    break;
+
+	case CI_MRRU:
+	    if (!ao->neg_mrru || !multilink ||
+		cilen != CILEN_SHORT) {
+		orc = CONFREJ;
+		break;
+	    }
+
+	    GETSHORT(cishort, p);
+	    /* possibly should insist on a minimum/maximum MRRU here */
+	    ho->neg_mrru = 1;
+	    ho->mrru = cishort;
+	    break;
+
+	case CI_SSNHF:
+	    if (!ao->neg_ssnhf || !multilink ||
+		cilen != CILEN_VOID) {
+		orc = CONFREJ;
+		break;
+	    }
+	    ho->neg_ssnhf = 1;
+	    break;
+
+	case CI_EPDISC:
+	    if (!ao->neg_endpoint ||
+		cilen < CILEN_CHAR ||
+		cilen > CILEN_CHAR + MAX_ENDP_LEN) {
+		orc = CONFREJ;
+		break;
+	    }
+	    GETCHAR(cichar, p);
+	    cilen -= CILEN_CHAR;
+	    ho->neg_endpoint = 1;
+	    ho->endpoint.class = cichar;
+	    ho->endpoint.length = cilen;
+	    BCOPY(p, ho->endpoint.value, cilen);
+	    INCPTR(cilen, p);
+	    break;
+
+	default:
+	    LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
+	    orc = CONFREJ;
+	    break;
+	}
+
+endswitch:
+	if (orc == CONFACK &&		/* Good CI */
+	    rc != CONFACK)		/*  but prior CI wasnt? */
+	    continue;			/* Don't send this one */
+
+	if (orc == CONFNAK) {		/* Nak this CI? */
+	    if (reject_if_disagree	/* Getting fed up with sending NAKs? */
+		&& citype != CI_MAGICNUMBER) {
+		orc = CONFREJ;		/* Get tough if so */
+	    } else {
+		if (rc == CONFREJ)	/* Rejecting prior CI? */
+		    continue;		/* Don't send this one */
+		rc = CONFNAK;
+	    }
+	}
+	if (orc == CONFREJ) {		/* Reject this CI */
+	    rc = CONFREJ;
+	    if (cip != rejp)		/* Need to move rejected CI? */
+		BCOPY(cip, rejp, cilen); /* Move it */
+	    INCPTR(cilen, rejp);	/* Update output pointer */
+	}
+    }
+
+    /*
+     * If we wanted to send additional NAKs (for unsent CIs), the
+     * code would go here.  The extra NAKs would go at *nakp.
+     * At present there are no cases where we want to ask the
+     * peer to negotiate an option.
+     */
+
+    switch (rc) {
+    case CONFACK:
+	*lenp = next - inp;
+	break;
+    case CONFNAK:
+	/*
+	 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
+	 */
+	*lenp = nakp - nak_buffer;
+	BCOPY(nak_buffer, inp, *lenp);
+	break;
+    case CONFREJ:
+	*lenp = rejp - inp;
+	break;
+    }
+
+    LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
+    return (rc);			/* Return final code */
+}
+
+
+/*
+ * lcp_up - LCP has come UP.
+ */
+static void
+lcp_up(f)
+    fsm *f;
+{
+    lcp_options *wo = &lcp_wantoptions[f->unit];
+    lcp_options *ho = &lcp_hisoptions[f->unit];
+    lcp_options *go = &lcp_gotoptions[f->unit];
+    lcp_options *ao = &lcp_allowoptions[f->unit];
+    int mtu;
+    char runmtu[10];
+
+    if (!go->neg_magicnumber)
+	go->magicnumber = 0;
+    if (!ho->neg_magicnumber)
+	ho->magicnumber = 0;
+
+    /*
+     * Set our MTU to the smaller of the MTU we wanted and
+     * the MRU our peer wanted.  If we negotiated an MRU,
+     * set our MRU to the larger of value we wanted and
+     * the value we got in the negotiation.
+     * Note on the MTU: the link MTU can be the MRU the peer wanted,
+     * the interface MTU is set to the lower of that and the
+     * MTU we want to use.
+     */
+    mtu = MIN(ho->neg_mru? ho->mru: PPP_MRU, ao->mru);
+    sprintf(runmtu, "%d", mtu);	// by honor 20040618
+    script_setenv("MTU", runmtu, 1);
+#ifdef HAVE_MULTILINK
+    if (!(multilink && go->neg_mrru && ho->neg_mrru))
+#endif /* HAVE_MULTILINK */
+	netif_set_mtu(f->unit, mtu);
+    ppp_send_config(f->unit, mtu,
+		    (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
+		    ho->neg_pcompression, ho->neg_accompression);
+    ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
+		    (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
+		    go->neg_pcompression, go->neg_accompression);
+
+    if (ho->neg_mru)
+	peer_mru[f->unit] = ho->mru;
+
+    lcp_echo_lowerup(f->unit);  /* Enable echo messages */
+
+    link_established(f->unit);
+}
+
+
+/*
+ * lcp_down - LCP has gone DOWN.
+ *
+ * Alert other protocols.
+ */
+static void
+lcp_down(f)
+    fsm *f;
+{
+    lcp_options *go = &lcp_gotoptions[f->unit];
+
+    lcp_echo_lowerdown(f->unit);
+
+    link_down(f->unit);
+
+    ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
+    ppp_recv_config(f->unit, PPP_MRU,
+		    (go->neg_asyncmap? go->asyncmap: 0xffffffff),
+		    go->neg_pcompression, go->neg_accompression);
+    peer_mru[f->unit] = PPP_MRU;
+}
+
+
+/*
+ * lcp_starting - LCP needs the lower layer up.
+ */
+static void
+lcp_starting(f)
+    fsm *f;
+{
+    link_required(f->unit);
+}
+
+
+/*
+ * lcp_finished - LCP has finished with the lower layer.
+ */
+static void
+lcp_finished(f)
+    fsm *f;
+{
+    link_terminated(f->unit);
+}
+
+
+/*
+ * lcp_printpkt - print the contents of an LCP packet.
+ */
+static char *lcp_codenames[] = {
+    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+    "TermReq", "TermAck", "CodeRej", "ProtRej",
+    "EchoReq", "EchoRep", "DiscReq"
+};
+
+static int
+lcp_printpkt(p, plen, printer, arg)
+    u_char *p;
+    int plen;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int code, id, len, olen, i;
+    u_char *pstart, *optend;
+    u_short cishort;
+    u_int32_t cilong;
+
+    if (plen < HEADERLEN)
+	return 0;
+    pstart = p;
+    GETCHAR(code, p);
+    GETCHAR(id, p);
+    GETSHORT(len, p);
+    if (len < HEADERLEN || len > plen)
+	return 0;
+
+    if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
+	printer(arg, " pid=(%d) %s", getpid(), lcp_codenames[code-1]);
+    else
+	printer(arg, " code=0x%x", code);
+    printer(arg, " id=0x%x", id);
+    len -= HEADERLEN;
+    switch (code) {
+    case CONFREQ:
+    case CONFACK:
+    case CONFNAK:
+    case CONFREJ:
+	/* print option list */
+	while (len >= 2) {
+	    GETCHAR(code, p);
+	    GETCHAR(olen, p);
+	    p -= 2;
+	    if (olen < 2 || olen > len) {
+		break;
+	    }
+	    printer(arg, " <");
+	    len -= olen;
+	    optend = p + olen;
+	    switch (code) {
+	    case CI_MRU:
+		if (olen == CILEN_SHORT) {
+		    p += 2;
+		    GETSHORT(cishort, p);
+		    printer(arg, "mru %d", cishort);
+		}
+		break;
+	    case CI_ASYNCMAP:
+		if (olen == CILEN_LONG) {
+		    p += 2;
+		    GETLONG(cilong, p);
+		    printer(arg, "asyncmap 0x%x", cilong);
+		}
+		break;
+	    case CI_AUTHTYPE:
+		if (olen >= CILEN_SHORT) {
+		    p += 2;
+		    printer(arg, "auth ");
+		    GETSHORT(cishort, p);
+		    switch (cishort) {
+		    case PPP_PAP:
+			printer(arg, "pap");
+			break;
+		    case PPP_CHAP:
+			printer(arg, "chap");
+			if (p < optend) {
+			    switch (*p) {
+			    case CHAP_DIGEST_MD5:
+				printer(arg, " MD5");
+				++p;
+				break;
+#ifdef CHAPMS
+			    case CHAP_MICROSOFT:
+				printer(arg, " m$oft");
+				++p;
+				break;
+#endif
+			    }
+			}
+			break;
+		    default:
+			printer(arg, "0x%x", cishort);
+		    }
+		}
+		break;
+	    case CI_QUALITY:
+		if (olen >= CILEN_SHORT) {
+		    p += 2;
+		    printer(arg, "quality ");
+		    GETSHORT(cishort, p);
+		    switch (cishort) {
+		    case PPP_LQR:
+			printer(arg, "lqr");
+			break;
+		    default:
+			printer(arg, "0x%x", cishort);
+		    }
+		}
+		break;
+#ifdef CBCP_SUPPORT
+	    case CI_CALLBACK:
+		if (olen == CILEN_CHAR) {
+    		    u_char cichar;
+		    p += 2;
+		    printer(arg, "callback ");
+		    GETCHAR(cichar, p);
+		    switch (cichar) {
+		    case CBCP_OPT:
+			printer(arg, "CBCP");
+			break;
+		    default:
+			printer(arg, "0x%x", cichar);
+		    }
+		}
+		break;
+#endif
+	    case CI_MAGICNUMBER:
+		if (olen == CILEN_LONG) {
+		    p += 2;
+		    GETLONG(cilong, p);
+		    printer(arg, "magic 0x%x", cilong);
+		}
+		break;
+	    case CI_PCOMPRESSION:
+		if (olen == CILEN_VOID) {
+		    p += 2;
+		    printer(arg, "pcomp");
+		}
+		break;
+	    case CI_ACCOMPRESSION:
+		if (olen == CILEN_VOID) {
+		    p += 2;
+		    printer(arg, "accomp");
+		}
+		break;
+	    case CI_MRRU:
+		if (olen == CILEN_SHORT) {
+		    p += 2;
+		    GETSHORT(cishort, p);
+		    printer(arg, "mrru %d", cishort);
+		}
+		break;
+	    case CI_SSNHF:
+		if (olen == CILEN_VOID) {
+		    p += 2;
+		    printer(arg, "ssnhf");
+		}
+		break;
+	    case CI_EPDISC:
+#ifdef HAVE_MULTILINK
+		if (olen >= CILEN_CHAR) {
+		    struct epdisc epd;
+		    p += 2;
+		    GETCHAR(epd.class, p);
+		    epd.length = olen - CILEN_CHAR;
+		    if (epd.length > MAX_ENDP_LEN)
+			epd.length = MAX_ENDP_LEN;
+		    if (epd.length > 0) {
+			BCOPY(p, epd.value, epd.length);
+			p += epd.length;
+		    }
+		    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
+		}
+#else
+		printer(arg, "endpoint");
+#endif
+		break;
+	    }
+	    while (p < optend) {
+		GETCHAR(code, p);
+		printer(arg, " %.2x", code);
+	    }
+	    printer(arg, ">");
+	}
+	break;
+
+    case TERMACK:
+    case TERMREQ:
+	if (len > 0 && *p >= ' ' && *p < 0x7f) {
+	    printer(arg, " ");
+	    print_string((char *)p, len, printer, arg);
+	    p += len;
+	    len = 0;
+	}
+	break;
+
+    case ECHOREQ:
+    case ECHOREP:
+    case DISCREQ:
+	if (len >= 4) {
+	    GETLONG(cilong, p);
+	    printer(arg, " magic=0x%x", cilong);
+	    p += 4;
+	    len -= 4;
+	}
+	break;
+    }
+
+    /* print the rest of the bytes in the packet */
+    for (i = 0; i < len && i < 32; ++i) {
+	GETCHAR(code, p);
+	printer(arg, " %.2x", code);
+    }
+    if (i < len) {
+	printer(arg, " ...");
+	p += len - i;
+    }
+
+    return p - pstart;
+}
+
+/*
+ * Time to shut down the link because there is nothing out there.
+ */
+
+static
+void LcpLinkFailure (f)
+    fsm *f;
+{
+    if (f->state == OPENED) {
+	info("No response to %d echo-requests", lcp_echos_pending);
+        notice("Serial link appears to be disconnected.");
+        lcp_close(f->unit, "Peer not responding");
+	status = EXIT_PEER_DEAD;
+    }
+}
+
+/*
+ * Check if we have been received "echo reply" packet
+ */
+
+static void
+LcpCheckReply (arg)
+    void *arg;
+{
+    fsm *f1 = &lcp_fsm[ifunit];
+
+    if(lcp_echos_pending >= 1)
+        TIMEOUT (LcpEchoTimeout, f1, 1);
+    else
+        TIMEOUT (LcpEchoTimeout, f1, lcp_echo_interval-1);
+}
+
+/*
+ * Timer expired for the LCP echo requests from this process.
+ */
+
+static void
+LcpEchoCheck (f)
+    fsm *f;
+{
+    LcpSendEchoRequest (f);
+    if (f->state != OPENED)
+	return;
+
+    /*
+     * Start the timer for the next interval.
+     */
+    if (lcp_echo_timer_running)
+	warn("assertion lcp_echo_timer_running==0 failed");
+    
+    TIMEOUT (LcpCheckReply, f, 1);
+    
+    lcp_echo_timer_running = 1;
+}
+
+/*
+ * LcpEchoTimeout - Timer expired on the LCP echo
+ */
+
+static void
+LcpEchoTimeout (arg)
+    void *arg;
+{
+    if (lcp_echo_timer_running != 0) {
+        lcp_echo_timer_running = 0;
+        LcpEchoCheck ((fsm *) arg);
+    }
+}
+
+/*
+ * LcpEchoReply - LCP has received a reply to the echo
+ */
+
+static void
+lcp_received_echo_reply (f, id, inp, len)
+    fsm *f;
+    int id;
+    u_char *inp;
+    int len;
+{
+    u_int32_t magic;
+
+    /* Check the magic number - don't count replies from ourselves. */
+    if (len < 4) {
+	dbglog("lcp: received short Echo-Reply, length %d", len);
+	return;
+    }
+    GETLONG(magic, inp);
+    if (lcp_gotoptions[f->unit].neg_magicnumber
+	&& magic == lcp_gotoptions[f->unit].magicnumber) {
+	warn("appear to have received our own echo-reply!");
+	return;
+    }
+
+    /* Reset the number of outstanding echo frames */
+    lcp_echos_pending = 0;
+}
+
+/*
+ * LcpSendEchoRequest - Send an echo request frame to the peer
+ */
+
+static void
+LcpSendEchoRequest (f)
+    fsm *f;
+{
+    u_int32_t lcp_magic;
+    u_char pkt[4], *pktp;
+
+    /*
+     * Detect the failure of the peer at this point.
+     */
+    if (lcp_echo_fails != 0) {
+        if (lcp_echos_pending >= lcp_echo_fails) {
+            LcpLinkFailure(f);
+	    lcp_echos_pending = 0;
+	}
+    }
+
+    /*
+     * Make and send the echo request frame.
+     */
+    if (f->state == OPENED) {
+        lcp_magic = lcp_gotoptions[f->unit].magicnumber;
+	pktp = pkt;
+	PUTLONG(lcp_magic, pktp);
+        fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
+	++lcp_echos_pending;
+    }
+}
+
+/*
+ * lcp_echo_lowerup - Start the timer for the LCP frame
+ */
+
+static void
+lcp_echo_lowerup (unit)
+    int unit;
+{
+    fsm *f = &lcp_fsm[unit];
+    
+    /* Clear the parameters for generating echo frames */
+    lcp_echos_pending      = 0;
+    lcp_echo_number        = 0;
+    lcp_echo_timer_running = 0;
+  
+    /* If a timeout interval is specified then start the timer */
+    if (lcp_echo_interval != 0)
+        LcpEchoCheck (f);
+}
+
+/*
+ * lcp_echo_lowerdown - Stop the timer for the LCP frame
+ */
+
+static void
+lcp_echo_lowerdown (unit)
+    int unit;
+{
+    fsm *f = &lcp_fsm[unit];
+
+    if (lcp_echo_timer_running != 0) {
+        UNTIMEOUT (LcpEchoTimeout, f);
+        lcp_echo_timer_running = 0;
+    }
+}
diff --git a/ap/app/ppp-2.4.1/pppd/lcp.h b/ap/app/ppp-2.4.1/pppd/lcp.h
new file mode 100644
index 0000000..6948f62
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/lcp.h
@@ -0,0 +1,98 @@
+/*
+ * lcp.h - Link Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: lcp.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+/*
+ * Options.
+ */
+#define CI_MRU		1	/* Maximum Receive Unit */
+#define CI_ASYNCMAP	2	/* Async Control Character Map */
+#define CI_AUTHTYPE	3	/* Authentication Type */
+#define CI_QUALITY	4	/* Quality Protocol */
+#define CI_MAGICNUMBER	5	/* Magic Number */
+#define CI_PCOMPRESSION	7	/* Protocol Field Compression */
+#define CI_ACCOMPRESSION 8	/* Address/Control Field Compression */
+#define CI_CALLBACK	13	/* callback */
+#define CI_MRRU		17	/* max reconstructed receive unit; multilink */
+#define CI_SSNHF	18	/* short sequence numbers for multilink */
+#define CI_EPDISC	19	/* endpoint discriminator */
+
+/*
+ * LCP-specific packet types.
+ */
+#define PROTREJ		8	/* Protocol Reject */
+#define ECHOREQ		9	/* Echo Request */
+#define ECHOREP		10	/* Echo Reply */
+#define DISCREQ		11	/* Discard Request */
+#define CBCP_OPT	6	/* Use callback control protocol */
+
+/*
+ * The state of options is described by an lcp_options structure.
+ */
+typedef struct lcp_options {
+    bool passive;		/* Don't die if we don't get a response */
+    bool silent;		/* Wait for the other end to start first */
+    bool restart;		/* Restart vs. exit after close */
+    bool neg_mru;		/* Negotiate the MRU? */
+    bool neg_asyncmap;		/* Negotiate the async map? */
+    bool neg_upap;		/* Ask for UPAP authentication? */
+    bool neg_chap;		/* Ask for CHAP authentication? */
+    bool neg_magicnumber;	/* Ask for magic number? */
+    bool neg_pcompression;	/* HDLC Protocol Field Compression? */
+    bool neg_accompression;	/* HDLC Address/Control Field Compression? */
+    bool neg_lqr;		/* Negotiate use of Link Quality Reports */
+    bool neg_cbcp;		/* Negotiate use of CBCP */
+    bool use_digest;
+    bool use_chapms;
+    bool use_chapms_v2;
+    bool neg_mrru;		/* negotiate multilink MRRU */
+    bool neg_ssnhf;		/* negotiate short sequence numbers */
+    bool neg_endpoint;		/* negotiate endpoint discriminator */
+    int  mru;			/* Value of MRU */
+    int	 mrru;			/* Value of MRRU, and multilink enable */
+    u_char chap_mdtype;		/* which MD type (hashing algorithm) */
+    u_int32_t asyncmap;		/* Value of async map */
+    u_int32_t magicnumber;
+    int  numloops;		/* Number of loops during magic number neg. */
+    u_int32_t lqr_period;	/* Reporting period for LQR 1/100ths second */
+    struct epdisc endpoint;	/* endpoint discriminator */
+} lcp_options;
+
+extern fsm lcp_fsm[];
+extern lcp_options lcp_wantoptions[];
+extern lcp_options lcp_gotoptions[];
+extern lcp_options lcp_allowoptions[];
+extern lcp_options lcp_hisoptions[];
+
+#define DEFMRU	1500		/* Try for this */
+#define MINMRU	128		/* No MRUs below this */
+#define MAXMRU	16384		/* Normally limit MRU to this */
+
+void lcp_open __P((int));
+void lcp_close __P((int, char *));
+void lcp_lowerup __P((int));
+void lcp_lowerdown __P((int));
+void lcp_sprotrej __P((int, u_char *, int));	/* send protocol reject */
+
+extern struct protent lcp_protent;
+
+/* Default number of times we receive our magic number from the peer
+   before deciding the link is looped-back. */
+#define DEFLOOPBACKFAIL	10
diff --git a/ap/app/ppp-2.4.1/pppd/magic.c b/ap/app/ppp-2.4.1/pppd/magic.c
new file mode 100644
index 0000000..4931389
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/magic.c
@@ -0,0 +1,87 @@
+/*
+ * magic.c - PPP Magic Number routines.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: magic.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <pppd.h>
+#include "magic.h"
+
+static const char rcsid[] = RCSID;
+
+extern long mrand48 __P((void));
+extern void srand48 __P((long));
+
+/*
+ * magic_init - Initialize the magic number generator.
+ *
+ * Attempts to compute a random number seed which will not repeat.
+ * The current method uses the current hostid, current process ID
+ * and current time, currently.
+ */
+void
+magic_init()
+{
+    long seed;
+    struct timeval t;
+
+    gettimeofday(&t, NULL);
+    seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid();
+    srand48(seed);
+}
+
+/*
+ * magic - Returns the next magic number.
+ */
+u_int32_t
+magic()
+{
+    return (u_int32_t) mrand48();
+}
+
+#ifdef NO_DRAND48
+/*
+ * Substitute procedures for those systems which don't have
+ * drand48 et al.
+ */
+
+double
+drand48()
+{
+    return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
+}
+
+long
+mrand48()
+{
+    return random();
+}
+
+void
+srand48(seedval)
+long seedval;
+{
+    srandom((int)seedval);
+}
+
+#endif
diff --git a/ap/app/ppp-2.4.1/pppd/magic.h b/ap/app/ppp-2.4.1/pppd/magic.h
new file mode 100644
index 0000000..0bf3885
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/magic.h
@@ -0,0 +1,23 @@
+/*
+ * magic.h - PPP Magic Number definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: magic.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+void magic_init __P((void));	/* Initialize the magic number generator */
+u_int32_t magic __P((void));	/* Returns the next magic number */
diff --git a/ap/app/ppp-2.4.1/pppd/md32_common.h b/ap/app/ppp-2.4.1/pppd/md32_common.h
new file mode 100644
index 0000000..1a404a4
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/md32_common.h
@@ -0,0 +1,607 @@
+/* crypto/md32_common.h */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This is a generic 32 bit "collector" for message digest algorithms.
+ * Whenever needed it collects input character stream into chunks of
+ * 32 bit values and invokes a block function that performs actual hash
+ * calculations.
+ *
+ * Porting guide.
+ *
+ * Obligatory macros:
+ *
+ * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
+ *	this macro defines byte order of input stream.
+ * HASH_CBLOCK
+ *	size of a unit chunk HASH_BLOCK operates on.
+ * HASH_LONG
+ *	has to be at lest 32 bit wide, if it's wider, then
+ *	HASH_LONG_LOG2 *has to* be defined along
+ * HASH_CTX
+ *	context structure that at least contains following
+ *	members:
+ *		typedef struct {
+ *			...
+ *			HASH_LONG	Nl,Nh;
+ *			HASH_LONG	data[HASH_LBLOCK];
+ *			int		num;
+ *			...
+ *			} HASH_CTX;
+ * HASH_UPDATE
+ *	name of "Update" function, implemented here.
+ * HASH_TRANSFORM
+ *	name of "Transform" function, implemented here.
+ * HASH_FINAL
+ *	name of "Final" function, implemented here.
+ * HASH_BLOCK_HOST_ORDER
+ *	name of "block" function treating *aligned* input message
+ *	in host byte order, implemented externally.
+ * HASH_BLOCK_DATA_ORDER
+ *	name of "block" function treating *unaligned* input message
+ *	in original (data) byte order, implemented externally (it
+ *	actually is optional if data and host are of the same
+ *	"endianess").
+ * HASH_MAKE_STRING
+ *	macro convering context variables to an ASCII hash string.
+ *
+ * Optional macros:
+ *
+ * B_ENDIAN or L_ENDIAN
+ *	defines host byte-order.
+ * HASH_LONG_LOG2
+ *	defaults to 2 if not states otherwise.
+ * HASH_LBLOCK
+ *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
+ * HASH_BLOCK_DATA_ORDER_ALIGNED
+ *	alternative "block" function capable of treating
+ *	aligned input message in original (data) order,
+ *	implemented externally.
+ *
+ * MD5 example:
+ *
+ *	#define DATA_ORDER_IS_LITTLE_ENDIAN
+ *
+ *	#define HASH_LONG		MD5_LONG
+ *	#define HASH_LONG_LOG2		MD5_LONG_LOG2
+ *	#define HASH_CTX		MD5_CTX
+ *	#define HASH_CBLOCK		MD5_CBLOCK
+ *	#define HASH_LBLOCK		MD5_LBLOCK
+ *	#define HASH_UPDATE		MD5_Update
+ *	#define HASH_TRANSFORM		MD5_Transform
+ *	#define HASH_FINAL		MD5_Final
+ *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
+ *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
+ *
+ *					<appro@fy.chalmers.se>
+ */
+
+#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#error "DATA_ORDER must be defined!"
+#endif
+
+#ifndef HASH_CBLOCK
+#error "HASH_CBLOCK must be defined!"
+#endif
+#ifndef HASH_LONG
+#error "HASH_LONG must be defined!"
+#endif
+#ifndef HASH_CTX
+#error "HASH_CTX must be defined!"
+#endif
+
+#ifndef HASH_UPDATE
+#error "HASH_UPDATE must be defined!"
+#endif
+#ifndef HASH_TRANSFORM
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#ifndef HASH_FINAL
+#error "HASH_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_HOST_ORDER
+#error "HASH_BLOCK_HOST_ORDER must be defined!"
+#endif
+
+#if 0
+/*
+ * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
+ * isn't defined.
+ */
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#ifndef HASH_LBLOCK
+#define HASH_LBLOCK	(HASH_CBLOCK/4)
+#endif
+
+#ifndef HASH_LONG_LOG2
+#define HASH_LONG_LOG2	2
+#endif
+
+/*
+ * Engage compiler specific rotate intrinsic function if available.
+ */
+#undef ROTATE
+#ifndef PEDANTIC
+# if defined(_MSC_VER)
+#  define ROTATE(a,n)	_lrotl(a,n)
+# elif defined(__MWERKS__)
+#  if defined(__POWERPC__)
+#   define ROTATE(a,n)	__rlwinm(a,n,0,31)
+#  elif defined(__MC68K__)
+    /* Motorola specific tweak. <appro@fy.chalmers.se> */
+#   define ROTATE(a,n)	( n<24 ? __rol(a,n) : __ror(a,32-n) )
+#  else
+#   define ROTATE(a,n)	__rol(a,n)
+#  endif
+# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /*
+   * Some GNU C inline assembler templates. Note that these are
+   * rotates by *constant* number of bits! But that's exactly
+   * what we need here...
+   *
+   * 					<appro@fy.chalmers.se>
+   */
+#  if defined(__i386)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"roll %1,%0"		\
+				: "=r"(ret)		\
+				: "I"(n), "0"(a)	\
+				: "cc");		\
+			   ret;				\
+			})
+#  elif defined(__powerpc) || defined(__ppc)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"rlwinm %0,%1,%2,0,31"	\
+				: "=r"(ret)		\
+				: "r"(a), "I"(n));	\
+			   ret;				\
+			})
+#  endif
+# endif
+
+/*
+ * Engage compiler specific "fetch in reverse byte order"
+ * intrinsic function if available.
+ */
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
+#  if defined(__i386) && !defined(I386_ONLY)
+#   define BE_FETCH32(a)	({ register unsigned int l=(a);\
+				asm (			\
+				"bswapl %0"		\
+				: "=r"(l) : "0"(l));	\
+			  l;				\
+			})
+#  elif defined(__powerpc)
+#   define LE_FETCH32(a)	({ register unsigned int l;	\
+				asm (			\
+				"lwbrx %0,0,%1"		\
+				: "=r"(l)		\
+				: "r"(a));		\
+			   l;				\
+			})
+
+#  elif defined(__sparc) && defined(ULTRASPARC)
+#  define LE_FETCH32(a)	({ register unsigned int l;		\
+				asm (				\
+				"lda [%1]#ASI_PRIMARY_LITTLE,%0"\
+				: "=r"(l)			\
+				: "r"(a));			\
+			   l;					\
+			})
+#  endif
+# endif
+#endif /* PEDANTIC */
+
+#if HASH_LONG_LOG2==2	/* Engage only if sizeof(HASH_LONG)== 4 */
+/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
+#ifdef ROTATE
+/* 5 instructions with rotate instruction, else 9 */
+#define REVERSE_FETCH32(a,l)	(					\
+		l=*(const HASH_LONG *)(a),				\
+		((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))	\
+				)
+#else
+/* 6 instructions with rotate instruction, else 8 */
+#define REVERSE_FETCH32(a,l)	(				\
+		l=*(const HASH_LONG *)(a),			\
+		l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),	\
+		ROTATE(l,16)					\
+				)
+/*
+ * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
+ * It's rewritten as above for two reasons:
+ *	- RISCs aren't good at long constants and have to explicitely
+ *	  compose 'em with several (well, usually 2) instructions in a
+ *	  register before performing the actual operation and (as you
+ *	  already realized:-) having same constant should inspire the
+ *	  compiler to permanently allocate the only register for it;
+ *	- most modern CPUs have two ALUs, but usually only one has
+ *	  circuitry for shifts:-( this minor tweak inspires compiler
+ *	  to schedule shift instructions in a better way...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#endif
+#endif
+
+#ifndef ROTATE
+#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
+#endif
+
+/*
+ * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
+ * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
+ * and host are of the same "endianess". It's possible to mask
+ * this with blank #define HASH_BLOCK_DATA_ORDER though...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#if defined(B_ENDIAN)
+#  if defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef LE_FETCH32
+#        define HOST_FETCH32(p,l)	LE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#elif defined(L_ENDIAN)
+#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef BE_FETCH32
+#        define HOST_FETCH32(p,l)	BE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#endif
+
+#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))    ),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 3: l|=((unsigned long)(*((c)++)));		\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l|=((unsigned long)(*(--(c))))<<24;	\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 l)
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<<24),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 3: l|=((unsigned long)(*((c)++)))<<24;	\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<<16;	\
+			case 2: l|=((unsigned long)(*(--(c))))<< 8;	\
+			case 1: l|=((unsigned long)(*(--(c))));		\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 l)
+
+#endif
+
+/*
+ * Time for some action:-)
+ */
+
+void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
+	{
+	const unsigned char *data=data_;
+	register HASH_LONG * p;
+	register unsigned long l;
+	int sw,sc,ew,ec;
+
+	if (len==0) return;
+
+	l=(c->Nl+(len<<3))&0xffffffffL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(len>>29);
+	c->Nl=l;
+
+	if (c->num != 0)
+		{
+		p=c->data;
+		sw=c->num>>2;
+		sc=c->num&0x03;
+
+		if ((c->num+len) >= HASH_CBLOCK)
+			{
+			l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+			for (; sw<HASH_LBLOCK; sw++)
+				{
+				HOST_c2l(data,l); p[sw]=l;
+				}
+			HASH_BLOCK_HOST_ORDER (c,p,1);
+			len-=(HASH_CBLOCK-c->num);
+			c->num=0;
+			/* drop through and do the rest */
+			}
+		else
+			{
+			c->num+=len;
+			if ((sc+len) < 4) /* ugly, add char's to a word */
+				{
+				l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
+				}
+			else
+				{
+				ew=(c->num>>2);
+				ec=(c->num&0x03);
+				l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+				for (; sw < ew; sw++)
+					{
+					HOST_c2l(data,l); p[sw]=l;
+					}
+				if (ec)
+					{
+					HOST_c2l_p(data,l,ec); p[sw]=l;
+					}
+				}
+			return;
+			}
+		}
+
+	sw=len/HASH_CBLOCK;
+	if (sw > 0)
+		{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+		/*
+		 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
+		 * only if sizeof(HASH_LONG)==4.
+		 */
+		if ((((unsigned long)data)%4) == 0)
+			{
+			/* data is properly aligned so that we can cast it: */
+			HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+		else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+			while (sw--)
+				{
+				memcpy (p=c->data,data,HASH_CBLOCK);
+				HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
+				data+=HASH_CBLOCK;
+				len-=HASH_CBLOCK;
+				}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+			{
+			HASH_BLOCK_DATA_ORDER(c,data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+#endif
+		}
+
+	if (len!=0)
+		{
+		p = c->data;
+		c->num = len;
+		ew=len>>2;	/* words to copy */
+		ec=len&0x03;
+		for (; ew; ew--,p++)
+			{
+			HOST_c2l(data,l); *p=l;
+			}
+		HOST_c2l_p(data,l,ec);
+		*p=l;
+		}
+	}
+
+
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+	{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+	if ((((unsigned long)data)%4) == 0)
+		/* data is properly aligned so that we can cast it: */
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
+	else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+		{
+		memcpy (c->data,data,HASH_CBLOCK);
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
+		}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+	HASH_BLOCK_DATA_ORDER (c,data,1);
+#endif
+	}
+
+
+void HASH_FINAL (unsigned char *md, HASH_CTX *c)
+	{
+	register HASH_LONG *p;
+	register unsigned long l;
+	register int i,j;
+	static const unsigned char end[4]={0x80,0x00,0x00,0x00};
+	const unsigned char *cp=end;
+
+	/* c->num should definitly have room for at least one more byte. */
+	p=c->data;
+	i=c->num>>2;
+	j=c->num&0x03;
+
+#if 0
+	/* purify often complains about the following line as an
+	 * Uninitialized Memory Read.  While this can be true, the
+	 * following p_c2l macro will reset l when that case is true.
+	 * This is because j&0x03 contains the number of 'valid' bytes
+	 * already in p[i].  If and only if j&0x03 == 0, the UMR will
+	 * occur but this is also the only time p_c2l will do
+	 * l= *(cp++) instead of l|= *(cp++)
+	 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
+	 * 'potential bug' */
+#ifdef PURIFY
+	if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
+#endif
+	l=p[i];
+#else
+	l = (j==0) ? 0 : p[i];
+#endif
+	HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
+
+	if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
+		{
+		if (i<HASH_LBLOCK) p[i]=0;
+		HASH_BLOCK_HOST_ORDER (c,p,1);
+		i=0;
+		}
+	for (; i<(HASH_LBLOCK-2); i++)
+		p[i]=0;
+
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nh;
+	p[HASH_LBLOCK-1]=c->Nl;
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nl;
+	p[HASH_LBLOCK-1]=c->Nh;
+#endif
+	HASH_BLOCK_HOST_ORDER (c,p,1);
+
+#ifndef HASH_MAKE_STRING
+#error "HASH_MAKE_STRING must be defined!"
+#else
+	HASH_MAKE_STRING(c,md);
+#endif
+
+	c->num=0;
+	/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
+	 * but I'm not worried :-)
+	memset((void *)c,0,sizeof(HASH_CTX));
+	 */
+	}
diff --git a/ap/app/ppp-2.4.1/pppd/md4.c b/ap/app/ppp-2.4.1/pppd/md4.c
new file mode 100644
index 0000000..cda9f94
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/md4.c
@@ -0,0 +1,298 @@
+/*
+** ********************************************************************
+** md4.c -- Implementation of MD4 Message Digest Algorithm           **
+** Updated: 2/16/90 by Ronald L. Rivest                              **
+** (C) 1990 RSA Data Security, Inc.                                  **
+** ********************************************************************
+*/
+
+/*
+** To use MD4:
+**   -- Include md4.h in your program
+**   -- Declare an MDstruct MD to hold the state of the digest
+**          computation.
+**   -- Initialize MD using MDbegin(&MD)
+**   -- For each full block (64 bytes) X you wish to process, call
+**          MD4Update(&MD,X,512)
+**      (512 is the number of bits in a full block.)
+**   -- For the last block (less than 64 bytes) you wish to process,
+**          MD4Update(&MD,X,n)
+**      where n is the number of bits in the partial block. A partial
+**      block terminates the computation, so every MD computation
+**      should terminate by processing a partial block, even if it
+**      has n = 0.
+**   -- The message digest is available in MD.buffer[0] ...
+**      MD.buffer[3].  (Least-significant byte of each word
+**      should be output first.)
+**   -- You can print out the digest using MDprint(&MD)
+*/
+
+/* Implementation notes:
+** This implementation assumes that ints are 32-bit quantities.
+*/
+
+#define TRUE  1
+#define FALSE 0
+
+/* Compile-time includes
+*/
+#include <stdio.h>
+#include "md4.h"
+#include "pppd.h"
+
+/* Compile-time declarations of MD4 "magic constants".
+*/
+#define I0  0x67452301       /* Initial values for MD buffer */
+#define I1  0xefcdab89
+#define I2  0x98badcfe
+#define I3  0x10325476
+#define C2  013240474631     /* round 2 constant = sqrt(2) in octal */
+#define C3  015666365641     /* round 3 constant = sqrt(3) in octal */
+/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+** Table 2, page 660.
+*/
+
+#define fs1  3               /* round 1 shift amounts */
+#define fs2  7
+#define fs3 11
+#define fs4 19
+#define gs1  3               /* round 2 shift amounts */
+#define gs2  5
+#define gs3  9
+#define gs4 13
+#define hs1  3               /* round 3 shift amounts */
+#define hs2  9
+#define hs3 11
+#define hs4 15
+
+/* Compile-time macro declarations for MD4.
+** Note: The "rot" operator uses the variable "tmp".
+** It assumes tmp is declared as unsigned int, so that the >>
+** operator will shift in zeros rather than extending the sign bit.
+*/
+#define f(X,Y,Z)             ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z)             ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z)             (X^Y^Z)
+#define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s)      A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s)      A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s)      A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+/* MD4print(MDp)
+** Print message digest buffer MDp as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte of
+** buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+** This is a user-callable routine.
+*/
+void
+MD4Print(MDp)
+MD4_CTX *MDp;
+{
+  int i,j;
+  for (i=0;i<4;i++)
+    for (j=0;j<32;j=j+8)
+      printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+}
+
+/* MD4Init(MDp)
+** Initialize message digest buffer MDp.
+** This is a user-callable routine.
+*/
+void
+MD4Init(MDp)
+MD4_CTX *MDp;
+{
+  int i;
+  MDp->buffer[0] = I0;
+  MDp->buffer[1] = I1;
+  MDp->buffer[2] = I2;
+  MDp->buffer[3] = I3;
+  for (i=0;i<8;i++) MDp->count[i] = 0;
+  MDp->done = 0;
+}
+
+/* MDblock(MDp,X)
+** Update message digest buffer MDp->buffer using 16-word data block X.
+** Assumes all 16 words of X are full of data.
+** Does not update MDp->count.
+** This routine is not user-callable.
+*/
+static void
+MDblock(MDp,Xb)
+MD4_CTX *MDp;
+unsigned char *Xb;
+{
+  register unsigned int tmp, A, B, C, D;
+  unsigned int X[16];
+  int i;
+
+  for (i = 0; i < 16; ++i) {
+    X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
+    Xb += 4;
+  }
+
+  A = MDp->buffer[0];
+  B = MDp->buffer[1];
+  C = MDp->buffer[2];
+  D = MDp->buffer[3];
+  /* Update the message digest buffer */
+  ff(A , B , C , D ,  0 , fs1); /* Round 1 */
+  ff(D , A , B , C ,  1 , fs2);
+  ff(C , D , A , B ,  2 , fs3);
+  ff(B , C , D , A ,  3 , fs4);
+  ff(A , B , C , D ,  4 , fs1);
+  ff(D , A , B , C ,  5 , fs2);
+  ff(C , D , A , B ,  6 , fs3);
+  ff(B , C , D , A ,  7 , fs4);
+  ff(A , B , C , D ,  8 , fs1);
+  ff(D , A , B , C ,  9 , fs2);
+  ff(C , D , A , B , 10 , fs3);
+  ff(B , C , D , A , 11 , fs4);
+  ff(A , B , C , D , 12 , fs1);
+  ff(D , A , B , C , 13 , fs2);
+  ff(C , D , A , B , 14 , fs3);
+  ff(B , C , D , A , 15 , fs4);
+  gg(A , B , C , D ,  0 , gs1); /* Round 2 */
+  gg(D , A , B , C ,  4 , gs2);
+  gg(C , D , A , B ,  8 , gs3);
+  gg(B , C , D , A , 12 , gs4);
+  gg(A , B , C , D ,  1 , gs1);
+  gg(D , A , B , C ,  5 , gs2);
+  gg(C , D , A , B ,  9 , gs3);
+  gg(B , C , D , A , 13 , gs4);
+  gg(A , B , C , D ,  2 , gs1);
+  gg(D , A , B , C ,  6 , gs2);
+  gg(C , D , A , B , 10 , gs3);
+  gg(B , C , D , A , 14 , gs4);
+  gg(A , B , C , D ,  3 , gs1);
+  gg(D , A , B , C ,  7 , gs2);
+  gg(C , D , A , B , 11 , gs3);
+  gg(B , C , D , A , 15 , gs4);
+  hh(A , B , C , D ,  0 , hs1); /* Round 3 */
+  hh(D , A , B , C ,  8 , hs2);
+  hh(C , D , A , B ,  4 , hs3);
+  hh(B , C , D , A , 12 , hs4);
+  hh(A , B , C , D ,  2 , hs1);
+  hh(D , A , B , C , 10 , hs2);
+  hh(C , D , A , B ,  6 , hs3);
+  hh(B , C , D , A , 14 , hs4);
+  hh(A , B , C , D ,  1 , hs1);
+  hh(D , A , B , C ,  9 , hs2);
+  hh(C , D , A , B ,  5 , hs3);
+  hh(B , C , D , A , 13 , hs4);
+  hh(A , B , C , D ,  3 , hs1);
+  hh(D , A , B , C , 11 , hs2);
+  hh(C , D , A , B ,  7 , hs3);
+  hh(B , C , D , A , 15 , hs4);
+  MDp->buffer[0] += A;
+  MDp->buffer[1] += B;
+  MDp->buffer[2] += C;
+  MDp->buffer[3] += D;
+}
+
+/* MD4Update(MDp,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+**        count -- the number of bits of X to use.
+**          (if not a multiple of 8, uses high bits of last byte.)
+** Update MDp using the number of bits of X given by count.
+** This is the basic input routine for an MD4 user.
+** The routine completes the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512.  A call with count 0 will be ignored if the
+** MD has already been terminated (done != 0), so an extra call with
+** count 0 can be given as a "courtesy close" to force termination
+** if desired.
+*/
+void
+MD4Update(MDp,X,count)
+MD4_CTX *MDp;
+unsigned char *X;
+unsigned int count;
+{
+  unsigned int i, tmp, bit, byte, mask;
+  unsigned char XX[64];
+  unsigned char *p;
+
+  /* return with no error if this is a courtesy close with count
+  ** zero and MDp->done is true.
+  */
+  if (count == 0 && MDp->done) return;
+  /* check to see if MD is already done and report error */
+  if (MDp->done)
+  { printf("\nError: MD4Update MD already done."); return; }
+
+  /* Add count to MDp->count */
+  tmp = count;
+  p = MDp->count;
+  while (tmp)
+  { tmp += *p;
+  *p++ = tmp;
+  tmp = tmp >> 8;
+  }
+
+  /* Process data */
+  if (count == 512)
+  { /* Full block of data to handle */
+    MDblock(MDp,X);
+  }
+  else if (count > 512) /* Check for count too large */
+  {
+    printf("\nError: MD4Update called with illegal count value %d.",
+	   count);
+    return;
+  }
+  else /* partial block -- must be last block so finish up */
+  {
+    /* Find out how many bytes and residual bits there are */
+    byte = count >> 3;
+    bit =  count & 7;
+    /* Copy X into XX since we need to modify it */
+    for (i=0;i<=byte;i++)   XX[i] = X[i];
+    for (i=byte+1;i<64;i++) XX[i] = 0;
+    /* Add padding '1' bit and low-order zeros in last byte */
+    mask = 1 << (7 - bit);
+    XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+    /* If room for bit count, finish up with this block */
+    if (byte <= 55)
+    {
+      for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+      MDblock(MDp,XX);
+    }
+    else /* need to do two blocks to finish up */
+    {
+      MDblock(MDp,XX);
+      for (i=0;i<56;i++) XX[i] = 0;
+      for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
+      MDblock(MDp,XX);
+    }
+    /* Set flag saying we're done with MD computation */
+    MDp->done = 1;
+  }
+}
+
+/*
+** Finish up MD4 computation and return message digest.
+*/
+void
+MD4Final(buf, MD)
+unsigned char *buf;
+MD4_CTX *MD;
+{
+  int i, j;
+  unsigned int w;
+
+  MD4Update(MD, NULL, 0);
+  for (i = 0; i < 4; ++i) {
+    w = MD->buffer[i];
+    for (j = 0; j < 4; ++j) {
+      *buf++ = w;
+      w >>= 8;
+    }
+  }
+}
+
+/*
+** End of md4.c
+****************************(cut)***********************************/
diff --git a/ap/app/ppp-2.4.1/pppd/md4.h b/ap/app/ppp-2.4.1/pppd/md4.h
new file mode 100644
index 0000000..80e8f9a
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/md4.h
@@ -0,0 +1,64 @@
+
+/*
+** ********************************************************************
+** md4.h -- Header file for implementation of                        **
+** MD4 Message Digest Algorithm                                      **
+** Updated: 2/13/90 by Ronald L. Rivest                              **
+** (C) 1990 RSA Data Security, Inc.                                  **
+** ********************************************************************
+*/
+
+#ifndef __P
+# if defined(__STDC__) || defined(__GNUC__)
+#  define __P(x) x
+# else
+#  define __P(x) ()
+# endif
+#endif
+
+
+/* MDstruct is the data structure for a message digest computation.
+*/
+typedef struct {
+	unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+	unsigned char count[8]; /* Number of bits processed so far */
+	unsigned int done;      /* Nonzero means MD computation finished */
+} MD4_CTX;
+
+/* MD4Init(MD4_CTX *)
+** Initialize the MD4_CTX prepatory to doing a message digest
+** computation.
+*/
+extern void MD4Init __P((MD4_CTX *MD));
+
+/* MD4Update(MD,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+**        count -- the number of bits of X to use (an unsigned int).
+** Updates MD using the first "count" bits of X.
+** The array pointed to by X is not modified.
+** If count is not a multiple of 8, MD4Update uses high bits of
+** last byte.
+** This is the basic input routine for a user.
+** The routine terminates the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512.  Zero is OK for a count.
+*/
+extern void MD4Update __P((MD4_CTX *MD, unsigned char *X, unsigned int count));
+
+/* MD4Print(MD)
+** Prints message digest buffer MD as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte
+** of buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+*/
+extern void MD4Print __P((MD4_CTX *));
+
+/* MD4Final(buf, MD)
+** Returns message digest from MD and terminates the message
+** digest computation.
+*/
+extern void MD4Final __P((unsigned char *, MD4_CTX *));
+
+/*
+** End of md4.h
+****************************(cut)***********************************/
diff --git a/ap/app/ppp-2.4.1/pppd/md5.c b/ap/app/ppp-2.4.1/pppd/md5.c
new file mode 100644
index 0000000..52c113a
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/md5.c
@@ -0,0 +1,307 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines                         **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#include <string.h>
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ **  Message-digest routines:                                         **
+ **  To form the message digest for a message M                       **
+ **    (1) Initialize a context buffer mdContext using MD5Init        **
+ **    (2) Call MD5Update on mdContext and M                          **
+ **    (3) Call MD5Final on mdContext                                 **
+ **  The message digest is now in mdContext->digest[0...15]           **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform ();
+
+static unsigned char PADDING[64] = {
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+  {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) \
+  {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) \
+  {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) \
+  {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+
+#ifdef __STDC__
+#define UL(x)	x##U
+#else
+#define UL(x)	x
+#endif
+
+/* The routine MD5Init initializes the message-digest context
+   mdContext. All fields are set to zero.
+ */
+void MD5Init (mdContext)
+MD5_CTX *mdContext;
+{
+  mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+  /* Load magic initialization constants.
+   */
+  mdContext->buf[0] = (UINT4)0x67452301;
+  mdContext->buf[1] = (UINT4)0xefcdab89;
+  mdContext->buf[2] = (UINT4)0x98badcfe;
+  mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+   account for the presence of each of the characters inBuf[0..inLen-1]
+   in the message whose digest is being computed.
+ */
+void MD5Update (mdContext, inBuf, inLen)
+MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+    mdContext->i[1]++;
+  mdContext->i[0] += ((UINT4)inLen << 3);
+  mdContext->i[1] += ((UINT4)inLen >> 29);
+
+  while (inLen--) {
+    /* add new character to buffer, increment mdi */
+    mdContext->in[mdi++] = *inBuf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4)
+        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+                (((UINT4)mdContext->in[ii+2]) << 16) |
+                (((UINT4)mdContext->in[ii+1]) << 8) |
+                ((UINT4)mdContext->in[ii]);
+      Transform (mdContext->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+   ends with the desired message digest in mdContext->digest[0...15].
+ */
+void MD5Final (hash, mdContext)
+unsigned char hash[];
+MD5_CTX *mdContext;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int padLen;
+
+  /* save number of bits */
+  in[14] = mdContext->i[0];
+  in[15] = mdContext->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  MD5Update (mdContext, PADDING, padLen);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4)
+    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+            (((UINT4)mdContext->in[ii+2]) << 16) |
+            (((UINT4)mdContext->in[ii+1]) << 8) |
+            ((UINT4)mdContext->in[ii]);
+  Transform (mdContext->buf, in);
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+    mdContext->digest[ii+1] =
+      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+    mdContext->digest[ii+2] =
+      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+    mdContext->digest[ii+3] =
+      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+  }
+  memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+  /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+  FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+  FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+  FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+  FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+  FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+  FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+  FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+  FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+  FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+  FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+  FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+  FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+  FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+  FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+  FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+  FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+  /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+  GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+  GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+  GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+  GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+  GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+  GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
+  GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+  GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+  GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+  GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+  GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+  GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+  GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+  GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+  GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+  GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+  /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+  HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+  HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+  HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+  HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+  HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+  HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+  HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+  HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+  HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+  HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+  HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+  HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
+  HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+  HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+  HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+  HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+  /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+  II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+  II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+  II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+  II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+  II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+  II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+  II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+  II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+  II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+  II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+  II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+  II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+  II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+  II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+  II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+  II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c                                                      **
+ ******************************** (cut) ********************************
+ */
diff --git a/ap/app/ppp-2.4.1/pppd/md5.h b/ap/app/ppp-2.4.1/pppd/md5.h
new file mode 100644
index 0000000..7492b22
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/md5.h
@@ -0,0 +1,58 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5                    **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
+ ** Revised (for MD5): RLR 4/27/91                                    **
+ **   -- G modified to have y&~z instead of y&z                       **
+ **   -- FF, GG, HH modified to add in last register done             **
+ **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
+ **   -- distinct additive constant for each step                     **
+ **   -- round 4 added, working mod 7                                 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+typedef unsigned int UINT4;
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */
+  UINT4 buf[4];                                    /* scratch buffer */
+  unsigned char in[64];                              /* input buffer */
+  unsigned char digest[16];     /* actual digest after MD5Final call */
+} MD5_CTX;
+
+void MD5Init ();
+void MD5Update ();
+void MD5Final ();
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */
diff --git a/ap/app/ppp-2.4.1/pppd/mppe.c b/ap/app/ppp-2.4.1/pppd/mppe.c
new file mode 100644
index 0000000..0e08c40
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/mppe.c
@@ -0,0 +1,230 @@
+/*
+ * mppe - Mucking with PpP Encription
+ *
+ * Copyright (c) 1995 Árpád Magossányi
+ * All rights reserved.
+ *
+ * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Pedro Roque Marques.  The name of the author may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef MPPE
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pppd.h"
+#include "chap.h"
+#include "fsm.h"
+#include "ccp.h"
+#include "md4.h" 
+#include <openssl/sha.h>
+#include "chap_ms.h"
+#include "extra_crypto.h"
+
+static void
+mppe_get_start_key __P((unsigned char *, unsigned char *, unsigned char *));
+static void
+mppe_get_master_key __P((unsigned char *, unsigned char *, unsigned char *));
+static void
+GetAsymetricStartKey __P((unsigned char *, unsigned char *, int, int, int));
+
+unsigned char mppe_master_send_key_40[8];
+unsigned char mppe_master_recv_key_40[8];
+unsigned char mppe_master_send_key_128[16];
+unsigned char mppe_master_recv_key_128[16];
+unsigned int mppe_allowed = 0;
+
+/*
+ * Pads used in key derivation - from sha1dgst.c
+ */
+static unsigned char  SHApad1[40] =
+  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char  SHApad2[40] =
+  {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+   0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+   0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+   0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
+
+
+/* This is used with chap-ms (v1) */
+void
+mppe_gen_master_key(char *secret, int secret_len, unsigned char *challenge)
+{
+    unsigned char PasswordHash[MD4_SIGNATURE_SIZE];
+    unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE];
+
+    /* 40 bit */
+    LmPasswordHash(secret, secret_len, PasswordHash);
+    BCOPY(PasswordHash, mppe_master_send_key_40, 8);
+    BCOPY(mppe_master_send_key_40, mppe_master_recv_key_40, 8);
+
+    /* 128 bit */
+    NtPasswordHash(secret, secret_len, PasswordHash);
+    md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
+    mppe_get_start_key(challenge, PasswordHashHash, mppe_master_send_key_128);
+    BCOPY(mppe_master_send_key_128, mppe_master_recv_key_128, 16);
+
+    mppe_allowed = 1;
+}
+
+
+/* This is used with chap-ms-v2 (per MS' draft RFC) - 2 different keys */
+void
+mppe_gen_master_key_v2(char *secret, int secret_len, unsigned char *response, 
+			int is_server)
+{
+    unsigned char PasswordHash[MD4_SIGNATURE_SIZE];
+    unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE];
+    unsigned char MasterKey[MD4_SIGNATURE_SIZE];
+
+    /* 128 bit - 2 keys */
+    NtPasswordHash(secret, secret_len, PasswordHash);
+    md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
+    mppe_get_master_key(PasswordHashHash, response, MasterKey);
+    GetAsymetricStartKey(MasterKey, mppe_master_send_key_128, 16,1, is_server);
+    GetAsymetricStartKey(MasterKey, mppe_master_recv_key_128, 16,0, is_server);
+
+    /* 40 bit - 2 keys */
+    BCOPY(mppe_master_send_key_128, mppe_master_send_key_40, 8);
+    BCOPY(mppe_master_recv_key_128, mppe_master_recv_key_40, 8);
+
+    mppe_allowed = 1;
+}
+
+
+static void
+mppe_get_start_key(unsigned char *Challenge, unsigned char *NtPasswordHashHash,
+			unsigned char *InitialSessionKey)
+{
+    unsigned char Digest[SHA_DIGEST_LENGTH];
+    SHA_CTX Context;
+    
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, NtPasswordHashHash, 16);
+    SHA1_Update(&Context, NtPasswordHashHash, 16);
+    SHA1_Update(&Context, Challenge, 8);
+    SHA1_Final(Digest, &Context);
+    BCOPY(Digest, InitialSessionKey, 16);
+}
+
+static void
+mppe_get_master_key(unsigned char *PasswordHashHash, unsigned char *NtResponse,
+			unsigned char *MasterKey)
+{
+    unsigned char Digest[SHA_DIGEST_LENGTH];
+    SHA_CTX Context;
+    static char Magic1[] = "This is the MPPE Master Key";
+    
+    BZERO(Digest, sizeof(Digest));
+    
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, PasswordHashHash, 16);
+    SHA1_Update(&Context, NtResponse, 24);
+    SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1);
+    SHA1_Final(Digest, &Context);
+    
+    BCOPY(Digest, MasterKey, 16);
+}
+
+static void
+GetAsymetricStartKey(unsigned char *MasterKey, unsigned char *SessionKey, 
+			int SessionKeyLength, int IsSend, int IsServer)
+{
+    unsigned char Digest[SHA_DIGEST_LENGTH];
+    SHA_CTX Context;
+    char *s;
+    static char Magic2[] = "On the client side, this is the send key; on the server side, it is the receive key.";
+    static char Magic3[] = "On the client side, this is the receive key; on the server side, it is the send key.";
+    
+    BZERO(Digest, sizeof(Digest));
+    if(IsSend)
+    {
+      if(IsServer)
+        s = Magic3;
+      else
+        s = Magic2;
+    }
+    else
+    {
+      if(IsServer)
+        s = Magic2;
+      else
+        s = Magic3;
+    }
+    
+    SHA1_Init(&Context);
+    SHA1_Update(&Context, MasterKey, 16);
+    SHA1_Update(&Context, SHApad1, 40);
+    SHA1_Update(&Context, s, 84);
+    SHA1_Update(&Context, SHApad2, 40);
+    SHA1_Final(Digest, &Context);
+    BCOPY(Digest, SessionKey, SessionKeyLength);
+}
+
+/*
+ * Functions called from config options
+ */
+int
+setmppe_40(char **argv)
+{   
+    ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1;
+    ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 1;
+    return 1;
+}
+
+int
+setnomppe_40(char **argv)
+{   
+    ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 0;
+    return 1;
+}
+
+int
+setmppe_128(char **argv)
+{   
+    ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1;
+    ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 1;
+    return 1;
+}
+
+int
+setnomppe_128(char **argv)
+{   
+    ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 0;
+    return 1;
+}
+
+int
+setmppe_stateless(char **argv)
+{
+    ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 1;
+    return 1;
+}
+
+int
+setnomppe_stateless(char **argv)
+{
+    ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 0;
+    return 1;
+}
+#endif /* MPPE */
diff --git a/ap/app/ppp-2.4.1/pppd/mppe.h b/ap/app/ppp-2.4.1/pppd/mppe.h
new file mode 100644
index 0000000..e111793
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/mppe.h
@@ -0,0 +1,56 @@
+#ifndef __MPPE_INCLUDE__
+
+typedef struct mppe_state {
+    int    us_unit;	/* Interface unit number */
+    u_char us_id;		/* Current id */
+    u_char us_allowed;
+    int    us_type;
+    char   *us_number;    /* Telefone Number */
+} mppe_state;
+
+
+extern struct protent mppe_protent;
+
+#define MPPE_CONFOPTION 18		/* p[0] */
+#define MPPE_STATELESS  0x01		/* p[2] */
+#define MPPE_40BIT	0x20		/* p[5] */
+#define MPPE_128BIT	0x40		/* p[5] */
+
+#define PPP_MPPE	0x00FD
+
+#define MPPE_BIT_A	0x80
+#define MPPE_BIT_B	0x40
+#define MPPE_BIT_C	0x20
+#define MPPE_BIT_D	0x10
+#define MPPE_BIT_FLUSHED MPPE_BIT_A
+#define MPPE_BIT_ENCRYPTED MPPE_BIT_D
+#define MPPE_CCOUNT	0x0FFF
+
+#define MPPE_40_SALT0	0xD1
+#define MPPE_40_SALT1	0x26
+#define MPPE_40_SALT2	0x9E
+
+#define MPPE_MINLEN 4
+
+#define MPPE_REQ    1
+#define MPPE_RESP   2
+#define MPPE_ACK    3
+
+extern char mppe_master_send_key_40[8];
+extern char mppe_master_send_key_128[16];
+extern char mppe_master_recv_key_40[8];
+extern char mppe_master_recv_key_128[16];
+extern unsigned int mppe_allowed;
+
+void mppe_gen_master_key __P((char *, int, unsigned char *));
+void mppe_gen_master_key_v2 __P((char *, int, unsigned char *, int));
+
+int setmppe_40(char **);
+int setnomppe_40(char **);
+int setmppe_128(char **);
+int setnomppe_128(char **);
+int setmppe_stateless(char **);
+int setnomppe_stateless(char **);
+
+#define __MPPE_INCLUDE__
+#endif /* __MPPE_INCLUDE__ */
diff --git a/ap/app/ppp-2.4.1/pppd/options.c b/ap/app/ppp-2.4.1/pppd/options.c
new file mode 100644
index 0000000..f4244c6
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/options.c
@@ -0,0 +1,1503 @@
+/*
+ * options.c - handles option processing for PPP.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: options.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <pwd.h>
+#ifdef PLUGIN
+#include <dlfcn.h>
+#endif
+#ifdef PPP_FILTER
+#include <pcap.h>
+#include <pcap-int.h>	
+#endif
+
+#include "pppd.h"
+#include "pathnames.h"
+
+#if defined(ultrix) || defined(NeXT)
+char *strdup __P((char *));
+#endif
+
+static const char rcsid[] = RCSID;
+
+struct option_value {
+    struct option_value *next;
+    const char *source;
+    char value[1];
+};
+
+/*
+ * Option variables and default values.
+ */
+#ifdef PPP_FILTER
+int	dflag = 0;		/* Tell libpcap we want debugging */
+#endif
+int	debug = 0;		/* Debug flag */
+int	kdebugflag = 0;		/* Tell kernel to print debug messages */
+int	default_device = 1;	/* Using /dev/tty or equivalent */
+char	devnam[MAXPATHLEN];	/* Device name */
+bool	nodetach = 0;		/* Don't detach from controlling tty */
+bool	updetach = 0;		/* Detach once link is up */
+int	maxconnect = 0;		/* Maximum connect time */
+char	user[MAXNAMELEN];	/* Username for PAP */
+char	passwd[MAXSECRETLEN];	/* Password for PAP */
+bool	persist = 0;		/* Reopen link after it goes down */
+char	our_name[MAXNAMELEN];	/* Our name for authentication purposes */
+bool	demand = 0;		/* do dial-on-demand */
+char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
+int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */
+int	holdoff = 30;		/* # seconds to pause before reconnecting */
+bool	holdoff_specified;	/* true if a holdoff value has been given */
+int	log_to_fd = 1;		/* send log messages to this fd too */
+bool	log_default = 1;	/* log_to_fd is default (stdout) */
+int	maxfail = 10;		/* max # of unsuccessful connection attempts */
+char	linkname[MAXPATHLEN];	/* logical name for link */
+bool	tune_kernel;		/* may alter kernel settings */
+int	connect_delay = 1000;	/* wait this many ms after connect script */
+int	req_unit = -1;		/* requested interface unit */
+bool	multilink = 0;		/* Enable multilink operation */
+char	*bundle_name = NULL;	/* bundle name for multilink */
+bool	dump_options;		/* print out option values */
+bool	dryrun;			/* print out option values and exit */
+char	*domain;		/* domain name set by domain option */
+
+extern option_t auth_options[];
+extern struct stat devstat;
+
+#ifdef PPP_FILTER
+struct	bpf_program pass_filter;/* Filter program for packets to pass */
+struct	bpf_program active_filter; /* Filter program for link-active pkts */
+pcap_t  pc;			/* Fake struct pcap so we can compile expr */
+#endif
+
+char *current_option;		/* the name of the option being parsed */
+int  privileged_option;		/* set iff the current option came from root */
+char *option_source;		/* string saying where the option came from */
+int  option_priority = OPRIO_CFGFILE; /* priority of the current options */
+bool devnam_fixed;		/* can no longer change device name */
+
+static int logfile_fd = -1;	/* fd opened for log file */
+static char logfile_name[MAXPATHLEN];	/* name of log file */
+
+/*
+ * Prototypes
+ */
+static int setdomain __P((char **));
+static int readfile __P((char **));
+static int callfile __P((char **));
+static int showversion __P((char **));
+static int showhelp __P((char **));
+static void usage __P((void));
+static int setlogfile __P((char **));
+#ifdef PLUGIN
+static int loadplugin __P((char **));
+#endif
+
+#ifdef PPP_FILTER
+static int setpassfilter __P((char **));
+static int setactivefilter __P((char **));
+#endif
+
+static option_t *find_option __P((const char *name));
+static int process_option __P((option_t *, char *, char **));
+static int n_arguments __P((option_t *));
+static int number_option __P((char *, u_int32_t *, int));
+
+/*
+ * Structure to store extra lists of options.
+ */
+struct option_list {
+    option_t *options;
+    struct option_list *next;
+};
+
+static struct option_list *extra_options = NULL;
+
+/*
+ * Valid arguments.
+ */
+option_t general_options[] = {
+    { "debug", o_int, &debug,
+      "Increase debugging level", OPT_INC | OPT_NOARG | 1 },
+    { "-d", o_int, &debug,
+      "Increase debugging level",
+      OPT_ALIAS | OPT_INC | OPT_NOARG | 1 },
+
+    { "kdebug", o_int, &kdebugflag,
+      "Set kernel driver debug level", OPT_PRIO },
+
+    { "nodetach", o_bool, &nodetach,
+      "Don't detach from controlling tty", OPT_PRIO | 1 },
+    { "-detach", o_bool, &nodetach,
+      "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 },
+    { "updetach", o_bool, &updetach,
+      "Detach from controlling tty once link is up",
+      OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach },
+
+    { "holdoff", o_int, &holdoff,
+      "Set time in seconds before retrying connection", OPT_PRIO },
+
+    { "idle", o_int, &idle_time_limit,
+      "Set time in seconds before disconnecting idle link", OPT_PRIO },
+
+    { "maxconnect", o_int, &maxconnect,
+      "Set connection time limit",
+      OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
+
+    { "domain", o_special, (void *)setdomain,
+      "Add given domain name to hostname",
+      OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain },
+
+    { "file", o_special, (void *)readfile,
+      "Take options from a file", OPT_NOPRINT },
+    { "call", o_special, (void *)callfile,
+      "Take options from a privileged file", OPT_NOPRINT },
+
+    { "persist", o_bool, &persist,
+      "Keep on reopening connection after close", OPT_PRIO | 1 },
+    { "nopersist", o_bool, &persist,
+      "Turn off persist option", OPT_PRIOSUB },
+
+    { "demand", o_bool, &demand,
+      "Dial on demand", OPT_INITONLY | 1, &persist },
+
+    { "--version", o_special_noarg, (void *)showversion,
+      "Show version number" },
+    { "--help", o_special_noarg, (void *)showhelp,
+      "Show brief listing of options" },
+    { "-h", o_special_noarg, (void *)showhelp,
+      "Show brief listing of options", OPT_ALIAS },
+
+    { "logfile", o_special, (void *)setlogfile,
+      "Append log messages to this file",
+      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name },
+    { "logfd", o_int, &log_to_fd,
+      "Send log messages to this file descriptor",
+      OPT_PRIOSUB | OPT_A2CLR, &log_default },
+    { "nolog", o_int, &log_to_fd,
+      "Don't send log messages to any file",
+      OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) },
+    { "nologfd", o_int, &log_to_fd,
+      "Don't send log messages to any file descriptor",
+      OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },
+
+    { "linkname", o_string, linkname,
+      "Set logical name for link",
+      OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },
+
+    { "maxfail", o_int, &maxfail,
+      "Maximum number of unsuccessful connection attempts to allow",
+      OPT_PRIO },
+
+    { "ktune", o_bool, &tune_kernel,
+      "Alter kernel settings as necessary", OPT_PRIO | 1 },
+    { "noktune", o_bool, &tune_kernel,
+      "Don't alter kernel settings", OPT_PRIOSUB },
+
+    { "connect-delay", o_int, &connect_delay,
+      "Maximum time (in ms) to wait after connect script finishes",
+      OPT_PRIO },
+
+    { "unit", o_int, &req_unit,
+      "PPP interface unit number to use if possible",
+      OPT_PRIO | OPT_LLIMIT, 0, 0 },
+
+    { "dump", o_bool, &dump_options,
+      "Print out option values after parsing all options", 1 },
+    { "dryrun", o_bool, &dryrun,
+      "Stop after parsing, printing, and checking options", 1 },
+
+#ifdef HAVE_MULTILINK
+    { "multilink", o_bool, &multilink,
+      "Enable multilink operation", OPT_PRIO | 1 },
+    { "mp", o_bool, &multilink,
+      "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
+    { "nomultilink", o_bool, &multilink,
+      "Disable multilink operation", OPT_PRIOSUB | 0 },
+    { "nomp", o_bool, &multilink,
+      "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
+
+    { "bundle", o_string, &bundle_name,
+      "Bundle name for multilink", OPT_PRIO },
+#endif /* HAVE_MULTILINK */
+
+#ifdef PLUGIN
+    { "plugin", o_special, (void *)loadplugin,
+      "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },
+#endif
+
+#ifdef PPP_FILTER
+    { "pdebug", o_int, &dflag,
+      "libpcap debugging", OPT_PRIO },
+
+    { "pass-filter", 1, setpassfilter,
+      "set filter for packets to pass", OPT_PRIO },
+
+    { "active-filter", 1, setactivefilter,
+      "set filter for active pkts", OPT_PRIO },
+#endif
+
+    { NULL }
+};
+
+#ifndef IMPLEMENTATION
+#define IMPLEMENTATION ""
+#endif
+
+static char *usage_string = "\
+pppd version %s\n\
+Usage: %s [ options ], where options are:\n\
+	<device>	Communicate over the named device\n\
+	<speed>		Set the baud rate to <speed>\n\
+	<loc>:<rem>	Set the local and/or remote interface IP\n\
+			addresses.  Either one may be omitted.\n\
+	asyncmap <n>	Set the desired async map to hex <n>\n\
+	auth		Require authentication from peer\n\
+        connect <p>     Invoke shell command <p> to set up the serial line\n\
+	crtscts		Use hardware RTS/CTS flow control\n\
+	defaultroute	Add default route through interface\n\
+	file <f>	Take options from file <f>\n\
+	modem		Use modem control lines\n\
+	mru <n>		Set MRU value to <n> for negotiation\n\
+See pppd(8) for more options.\n\
+";
+
+/*
+ * parse_args - parse a string of arguments from the command line.
+ */
+int
+parse_args(argc, argv)
+    int argc;
+    char **argv;
+{
+    char *arg;
+    option_t *opt;
+    int n;
+
+    privileged_option = privileged;
+    option_source = "command line";
+    option_priority = OPRIO_CMDLINE;
+    while (argc > 0) {
+	arg = *argv++;
+	--argc;
+	opt = find_option(arg);
+	if (opt == NULL) {
+	    option_error("unrecognized option '%s'", arg);
+	    usage();
+	    return 0;
+	}
+	n = n_arguments(opt);
+	if (argc < n) {
+	    option_error("too few parameters for option %s", arg);
+	    return 0;
+	}
+	if (!process_option(opt, arg, argv))
+	    return 0;
+	argc -= n;
+	argv += n;
+    }
+    return 1;
+}
+
+/*
+ * options_from_file - Read a string of options from a file,
+ * and interpret them.
+ */
+int
+options_from_file(filename, must_exist, check_prot, priv)
+    char *filename;
+    int must_exist;
+    int check_prot;
+    int priv;
+{
+    FILE *f;
+    int i, newline, ret, err;
+    option_t *opt;
+    int oldpriv, n;
+    char *oldsource;
+    char *argv[MAXARGS];
+    char args[MAXARGS][MAXWORDLEN];
+    char cmd[MAXWORDLEN];
+
+    if (check_prot)
+	seteuid(getuid());
+    f = fopen(filename, "r");
+    err = errno;
+    if (check_prot)
+	seteuid(0);
+    if (f == NULL) {
+	errno = err;
+	if (!must_exist) {
+	    if (err != ENOENT && err != ENOTDIR)
+		warn("Warning: can't open options file %s: %m", filename);
+	    return 1;
+	}
+	option_error("Can't open options file %s: %m", filename);
+	return 0;
+    }
+
+    oldpriv = privileged_option;
+    privileged_option = priv;
+    oldsource = option_source;
+    option_source = strdup(filename);
+    if (option_source == NULL)
+	option_source = "file";
+    ret = 0;
+    while (getword(f, cmd, &newline, filename)) {
+	opt = find_option(cmd);
+	if (opt == NULL) {
+	    option_error("In file %s: unrecognized option '%s'",
+			 filename, cmd);
+	    goto err;
+	}
+	n = n_arguments(opt);
+	for (i = 0; i < n; ++i) {
+	    if (!getword(f, args[i], &newline, filename)) {
+		option_error(
+			"In file %s: too few parameters for option '%s'",
+			filename, cmd);
+		goto err;
+	    }
+	    argv[i] = args[i];
+	}
+	if (!process_option(opt, cmd, argv))
+	    goto err;
+    }
+    ret = 1;
+
+err:
+    fclose(f);
+    privileged_option = oldpriv;
+    option_source = oldsource;
+    return ret;
+}
+
+/*
+ * options_from_user - See if the use has a ~/.ppprc file,
+ * and if so, interpret options from it.
+ */
+int
+options_from_user()
+{
+    char *user, *path, *file;
+    int ret;
+    struct passwd *pw;
+    size_t pl;
+
+    pw = getpwuid(getuid());
+    if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
+	return 1;
+    file = _PATH_USEROPT;
+    pl = strlen(user) + strlen(file) + 2;
+    path = malloc(pl);
+    if (path == NULL)
+	novm("init file name");
+    slprintf(path, pl, "%s/%s", user, file);
+    option_priority = OPRIO_CFGFILE;
+    ret = options_from_file(path, 0, 1, privileged);
+    free(path);
+    return ret;
+}
+
+/*
+ * options_for_tty - See if an options file exists for the serial
+ * device, and if so, interpret options from it.
+ * We only allow the per-tty options file to override anything from
+ * the command line if it is something that the user can't override
+ * once it has been set by root; this is done by giving configuration
+ * files a lower priority than the command line.
+ */
+int
+options_for_tty()
+{
+    char *dev, *path, *p;
+    int ret;
+    size_t pl;
+
+    dev = devnam;
+    if (strncmp(dev, "/dev/", 5) == 0)
+	dev += 5;
+    if (dev[0] == 0 || strcmp(dev, "tty") == 0)
+	return 1;		/* don't look for /etc/ppp/options.tty */
+    pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;
+    path = malloc(pl);
+    if (path == NULL)
+	novm("tty init file name");
+    slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);
+    /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
+    for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p)
+	if (*p == '/')
+	    *p = '.';
+    option_priority = OPRIO_CFGFILE;
+    ret = options_from_file(path, 0, 0, 1);
+    free(path);
+    return ret;
+}
+
+/*
+ * options_from_list - process a string of options in a wordlist.
+ */
+int
+options_from_list(w, priv)
+    struct wordlist *w;
+    int priv;
+{
+    char *argv[MAXARGS];
+    option_t *opt;
+    int i, n, ret = 0;
+    struct wordlist *w0;
+
+    privileged_option = priv;
+    option_source = "secrets file";
+    option_priority = OPRIO_SECFILE;
+
+    while (w != NULL) {
+	opt = find_option(w->word);
+	if (opt == NULL) {
+	    option_error("In secrets file: unrecognized option '%s'",
+			 w->word);
+	    goto err;
+	}
+	n = n_arguments(opt);
+	w0 = w;
+	for (i = 0; i < n; ++i) {
+	    w = w->next;
+	    if (w == NULL) {
+		option_error(
+			"In secrets file: too few parameters for option '%s'",
+			w0->word);
+		goto err;
+	    }
+	    argv[i] = w->word;
+	}
+	if (!process_option(opt, w0->word, argv))
+	    goto err;
+	w = w->next;
+    }
+    ret = 1;
+
+err:
+    return ret;
+}
+
+/*
+ * match_option - see if this option matches an option_t structure.
+ */
+static int
+match_option(name, opt, dowild)
+    char *name;
+    option_t *opt;
+    int dowild;
+{
+	int (*match) __P((char *, char **, int));
+
+	if (dowild != (opt->type == o_wild))
+		return 0;
+	if (!dowild)
+		return strcmp(name, opt->name) == 0;
+	match = (int (*) __P((char *, char **, int))) opt->addr;
+	return (*match)(name, NULL, 0);
+}
+
+/*
+ * find_option - scan the option lists for the various protocols
+ * looking for an entry with the given name.
+ * This could be optimized by using a hash table.
+ */
+static option_t *
+find_option(name)
+    const char *name;
+{
+	option_t *opt;
+	struct option_list *list;
+	int i, dowild;
+
+	for (dowild = 0; dowild <= 1; ++dowild) {
+		for (opt = general_options; opt->name != NULL; ++opt)
+			if (match_option(name, opt, dowild))
+				return opt;
+		for (opt = auth_options; opt->name != NULL; ++opt)
+			if (match_option(name, opt, dowild))
+				return opt;
+		for (list = extra_options; list != NULL; list = list->next)
+			for (opt = list->options; opt->name != NULL; ++opt)
+				if (match_option(name, opt, dowild))
+					return opt;
+		for (opt = the_channel->options; opt->name != NULL; ++opt)
+			if (match_option(name, opt, dowild))
+				return opt;
+		for (i = 0; protocols[i] != NULL; ++i)
+			if ((opt = protocols[i]->options) != NULL)
+				for (; opt->name != NULL; ++opt)
+					if (match_option(name, opt, dowild))
+						return opt;
+	}
+	return NULL;
+}
+
+/*
+ * process_option - process one new-style option.
+ */
+static int
+process_option(opt, cmd, argv)
+    option_t *opt;
+    char *cmd;
+    char **argv;
+{
+    u_int32_t v;
+    int iv, a;
+    char *sv;
+    int (*parser) __P((char **));
+    int (*wildp) __P((char *, char **, int));
+    char *optopt = (opt->type == o_wild)? "": " option";
+    int prio = option_priority;
+    option_t *mainopt = opt;
+
+    if ((opt->flags & OPT_PRIVFIX) && privileged_option)
+	prio += OPRIO_ROOT;
+    while (mainopt->flags & OPT_PRIOSUB)
+	--mainopt;
+    if (mainopt->flags & OPT_PRIO) {
+	if (prio < mainopt->priority) {
+	    /* new value doesn't override old */
+	    if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) {
+		option_error("%s%s set in %s cannot be overridden\n",
+			     opt->name, optopt, mainopt->source);
+		return 0;
+	    }
+	    return 1;
+	}
+	if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE)
+	    warn("%s%s from %s overrides command line",
+		 opt->name, optopt, option_source);
+    }
+
+    if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
+	option_error("%s%s cannot be changed after initialization",
+		     opt->name, optopt);
+	return 0;
+    }
+    if ((opt->flags & OPT_PRIV) && !privileged_option) {
+	option_error("using the %s%s requires root privilege",
+		     opt->name, optopt);
+	return 0;
+    }
+    if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
+	option_error("%s%s is disabled", opt->name, optopt);
+	return 0;
+    }
+    if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
+	option_error("the %s%s may not be changed in %s",
+		     opt->name, optopt, option_source);
+	return 0;
+    }
+
+    switch (opt->type) {
+    case o_bool:
+	v = opt->flags & OPT_VALUE;
+	*(bool *)(opt->addr) = v;
+	if (opt->addr2 && (opt->flags & OPT_A2COPY))
+	    *(bool *)(opt->addr2) = v;
+	break;
+
+    case o_int:
+	iv = 0;
+	if ((opt->flags & OPT_NOARG) == 0) {
+	    if (!int_option(*argv, &iv))
+		return 0;
+	    if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
+		 || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
+		&& !((opt->flags & OPT_ZEROOK && iv == 0))) {
+		char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
+		switch (opt->flags & OPT_LIMITS) {
+		case OPT_LLIMIT:
+		    option_error("%s value must be%s >= %d",
+				 opt->name, zok, opt->lower_limit);
+		    break;
+		case OPT_ULIMIT:
+		    option_error("%s value must be%s <= %d",
+				 opt->name, zok, opt->upper_limit);
+		    break;
+		case OPT_LIMITS:
+		    option_error("%s value must be%s between %d and %d",
+				opt->name, opt->lower_limit, opt->upper_limit);
+		    break;
+		}
+		return 0;
+	    }
+	}
+	a = opt->flags & OPT_VALUE;
+	if (a >= 128)
+	    a -= 256;		/* sign extend */
+	iv += a;
+	if (opt->flags & OPT_INC)
+	    iv += *(int *)(opt->addr);
+	if ((opt->flags & OPT_NOINCR) && !privileged_option) {
+	    int oldv = *(int *)(opt->addr);
+	    if ((opt->flags & OPT_ZEROINF) ?
+		(oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
+		option_error("%s value cannot be increased", opt->name);
+		return 0;
+	    }
+	}
+	*(int *)(opt->addr) = iv;
+	if (opt->addr2 && (opt->flags & OPT_A2COPY))
+	    *(int *)(opt->addr2) = iv;
+	break;
+
+    case o_uint32:
+	if (opt->flags & OPT_NOARG) {
+	    v = opt->flags & OPT_VALUE;
+	    if (v & 0x80)
+		    v |= 0xffffff00U;
+	} else if (!number_option(*argv, &v, 16))
+	    return 0;
+	if (opt->flags & OPT_OR)
+	    v |= *(u_int32_t *)(opt->addr);
+	*(u_int32_t *)(opt->addr) = v;
+	if (opt->addr2 && (opt->flags & OPT_A2COPY))
+	    *(u_int32_t *)(opt->addr2) = v;
+	break;
+
+    case o_string:
+	if (opt->flags & OPT_STATIC) {
+	    strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
+	} else {
+	    sv = strdup(*argv);
+	    if (sv == NULL)
+		novm("option argument");
+	    *(char **)(opt->addr) = sv;
+	}
+	break;
+
+    case o_special_noarg:
+    case o_special:
+	parser = (int (*) __P((char **))) opt->addr;
+	if (!(*parser)(argv))
+	    return 0;
+	if (opt->flags & OPT_A2LIST) {
+	    struct option_value *ovp, **pp;
+
+	    ovp = malloc(sizeof(*ovp) + strlen(*argv));
+	    if (ovp != 0) {
+		strcpy(ovp->value, *argv);
+		ovp->source = option_source;
+		ovp->next = NULL;
+		pp = (struct option_value **) &opt->addr2;
+		while (*pp != 0)
+		    pp = &(*pp)->next;
+		*pp = ovp;
+	    }
+	}
+	break;
+
+    case o_wild:
+	wildp = (int (*) __P((char *, char **, int))) opt->addr;
+	if (!(*wildp)(cmd, argv, 1))
+	    return 0;
+	break;
+    }
+
+    if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
+		|OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST)) == 0)
+	*(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
+
+    mainopt->source = option_source;
+    mainopt->priority = prio;
+    mainopt->winner = opt - mainopt;
+
+    return 1;
+}
+
+/*
+ * override_value - if the option priorities would permit us to
+ * override the value of option, return 1 and update the priority
+ * and source of the option value.  Otherwise returns 0.
+ */
+int
+override_value(option, priority, source)
+    const char *option;
+    int priority;
+    const char *source;
+{
+	option_t *opt;
+
+	opt = find_option(option);
+	if (opt == NULL)
+		return 0;
+	while (opt->flags & OPT_PRIOSUB)
+		--opt;
+	if ((opt->flags & OPT_PRIO) && priority < opt->priority)
+		return 0;
+	opt->priority = priority;
+	opt->source = source;
+	opt->winner = -1;
+	return 1;
+}
+
+/*
+ * n_arguments - tell how many arguments an option takes
+ */
+static int
+n_arguments(opt)
+    option_t *opt;
+{
+	return (opt->type == o_bool || opt->type == o_special_noarg
+		|| (opt->flags & OPT_NOARG))? 0: 1;
+}
+
+/*
+ * add_options - add a list of options to the set we grok.
+ */
+void
+add_options(opt)
+    option_t *opt;
+{
+    struct option_list *list;
+
+    list = malloc(sizeof(*list));
+    if (list == 0)
+	novm("option list entry");
+    list->options = opt;
+    list->next = extra_options;
+    extra_options = list;
+}
+
+/*
+ * remove_option - permanently remove an option from consideration...
+ * for use by modules to remove choices which no longer make sense.
+ * returns true if found an option
+ */
+int
+remove_option(name)
+    char *name;
+{
+    option_t *o;
+    o = find_option(name);
+    if (o == NULL)
+	return 0;
+    o->name = "";
+    return 1;
+}
+
+/*
+ * check_options - check that options are valid and consistent.
+ */
+void
+check_options()
+{
+	if (logfile_fd >= 0 && logfile_fd != log_to_fd)
+		close(logfile_fd);
+}
+
+/*
+ * print_option - print out an option and its value
+ */
+static void
+print_option(opt, mainopt, printer, arg)
+    option_t *opt, *mainopt;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+	int i, v;
+	char *p;
+
+	if (opt->flags & OPT_NOPRINT)
+		return;
+	switch (opt->type) {
+	case o_bool:
+		v = opt->flags & OPT_VALUE;
+		if (*(bool *)opt->addr != v)
+			/* this can happen legitimately, e.g. lock
+			   option turned off for default device */
+			break;
+		printer(arg, "%s", opt->name);
+		break;
+	case o_int:
+		v = opt->flags & OPT_VALUE;
+		if (v >= 128)
+			v -= 256;
+		i = *(int *)opt->addr;
+		if (opt->flags & OPT_NOARG) {
+			printer(arg, "%s", opt->name);
+			if (i != v) {
+				if (opt->flags & OPT_INC) {
+					for (; i > v; i -= v)
+						printer(arg, " %s", opt->name);
+				} else
+					printer(arg, " # oops: %d not %d\n",
+						i, v);
+			}
+		} else {
+			printer(arg, "%s %d", opt->name, i);
+		}
+		break;
+	case o_uint32:
+		printer(arg, "%s", opt->name);
+		if ((opt->flags & OPT_NOARG) == 0)
+			printer(arg, " %x", *(u_int32_t *)opt->addr);
+		break;
+
+	case o_string:
+		if (opt->flags & OPT_HIDE) {
+			p = "??????";
+		} else {
+			p = (char *) opt->addr;
+			if ((opt->flags & OPT_STATIC) == 0)
+				p = *(char **)p;
+		}
+		printer(arg, "%s %q", opt->name, p);
+		break;
+
+	case o_special:
+	case o_special_noarg:
+	case o_wild:
+		if (opt->type != o_wild) {
+			printer(arg, "%s", opt->name);
+			if (n_arguments(opt) == 0)
+				break;
+			printer(arg, " ");
+		}
+		if (opt->flags & OPT_A2PRINTER) {
+			void (*oprt) __P((option_t *,
+					  void ((*)__P((void *, char *, ...))),
+					  void *));
+			oprt = opt->addr2;
+			(*oprt)(opt, printer, arg);
+		} else if (opt->flags & OPT_A2STRVAL) {
+			p = (char *) opt->addr2;
+			if ((opt->flags & OPT_STATIC) == 0)
+				p = *(char **)p;
+			printer("%q", p);
+		} else if (opt->flags & OPT_A2LIST) {
+			struct option_value *ovp;
+
+			ovp = (struct option_value *) opt->addr2;
+			for (;;) {
+				printer(arg, "%q", ovp->value);
+				if ((ovp = ovp->next) == NULL)
+					break;
+				printer(arg, "\t\t# (from %s)\n%s ",
+					ovp->source, opt->name);
+			}
+		} else {
+			printer(arg, "xxx # [don't know how to print value]");
+		}
+		break;
+
+	default:
+		printer(arg, "# %s value (type %d??)", opt->name, opt->type);
+		break;
+	}
+	printer(arg, "\t\t# (from %s)\n", mainopt->source);
+}
+
+/*
+ * print_option_list - print out options in effect from an
+ * array of options.
+ */
+static void
+print_option_list(opt, printer, arg)
+    option_t *opt;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+	while (opt->name != NULL) {
+		if (opt->priority != OPRIO_DEFAULT
+		    && opt->winner != (short int) -1)
+			print_option(opt + opt->winner, opt, printer, arg);
+		do {
+			++opt;
+		} while (opt->flags & OPT_PRIOSUB);
+	}
+}
+
+/*
+ * print_options - print out what options are in effect.
+ */
+void
+print_options(printer, arg)
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+	struct option_list *list;
+	int i;
+
+	printer(arg, "pppd options in effect:\n");
+	print_option_list(general_options, printer, arg);
+	print_option_list(auth_options, printer, arg);
+	for (list = extra_options; list != NULL; list = list->next)
+		print_option_list(list->options, printer, arg);
+	print_option_list(the_channel->options, printer, arg);
+	for (i = 0; protocols[i] != NULL; ++i)
+		print_option_list(protocols[i]->options, printer, arg);
+}
+
+/*
+ * usage - print out a message telling how to use the program.
+ */
+static void
+usage()
+{
+    if (phase == PHASE_INITIALIZE)
+	fprintf(stderr, usage_string, VERSION, progname);
+}
+
+/*
+ * showhelp - print out usage message and exit.
+ */
+static int
+showhelp(argv)
+    char **argv;
+{
+    if (phase == PHASE_INITIALIZE) {
+	usage();
+	exit(0);
+    }
+    return 0;
+}
+
+/*
+ * showversion - print out the version number and exit.
+ */
+static int
+showversion(argv)
+    char **argv;
+{
+    if (phase == PHASE_INITIALIZE) {
+	fprintf(stderr, "pppd version %s\n", VERSION);
+	exit(0);
+    }
+    return 0;
+}
+
+/*
+ * option_error - print a message about an error in an option.
+ * The message is logged, and also sent to
+ * stderr if phase == PHASE_INITIALIZE.
+ */
+void
+option_error __V((char *fmt, ...))
+{
+    va_list args;
+    char buf[1024];
+
+#if defined(__STDC__)
+    va_start(args, fmt);
+#else
+    char *fmt;
+    va_start(args);
+    fmt = va_arg(args, char *);
+#endif
+    vslprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+    if (phase == PHASE_INITIALIZE)
+	fprintf(stderr, "%s: %s\n", progname, buf);
+    syslog(LOG_ERR, "%s", buf);
+}
+
+
+/*
+ * Read a word from a file.
+ * Words are delimited by white-space or by quotes (" or ').
+ * Quotes, white-space and \ may be escaped with \.
+ * \<newline> is ignored.
+ */
+int
+getword(f, word, newlinep, filename)
+    FILE *f;
+    char *word;
+    int *newlinep;
+    char *filename;
+{
+    int c, len, escape;
+    int quoted, comment;
+    int value, digit, got, n;
+
+#define isoctal(c) ((c) >= '0' && (c) < '8')
+
+    *newlinep = 0;
+    len = 0;
+    escape = 0;
+    comment = 0;
+
+    /*
+     * First skip white-space and comments.
+     */
+    for (;;) {
+	c = getc(f);
+	if (c == EOF)
+	    break;
+
+	/*
+	 * A newline means the end of a comment; backslash-newline
+	 * is ignored.  Note that we cannot have escape && comment.
+	 */
+	if (c == '\n') {
+	    if (!escape) {
+		*newlinep = 1;
+		comment = 0;
+	    } else
+		escape = 0;
+	    continue;
+	}
+
+	/*
+	 * Ignore characters other than newline in a comment.
+	 */
+	if (comment)
+	    continue;
+
+	/*
+	 * If this character is escaped, we have a word start.
+	 */
+	if (escape)
+	    break;
+
+	/*
+	 * If this is the escape character, look at the next character.
+	 */
+	if (c == '\\') {
+	    escape = 1;
+	    continue;
+	}
+
+	/*
+	 * If this is the start of a comment, ignore the rest of the line.
+	 */
+	if (c == '#') {
+	    comment = 1;
+	    continue;
+	}
+
+	/*
+	 * A non-whitespace character is the start of a word.
+	 */
+	if (!isspace(c))
+	    break;
+    }
+
+    /*
+     * Save the delimiter for quoted strings.
+     */
+    if (!escape && (c == '"' || c == '\'')) {
+        quoted = c;
+	c = getc(f);
+    } else
+        quoted = 0;
+
+    /*
+     * Process characters until the end of the word.
+     */
+    while (c != EOF) {
+	if (escape) {
+	    /*
+	     * This character is escaped: backslash-newline is ignored,
+	     * various other characters indicate particular values
+	     * as for C backslash-escapes.
+	     */
+	    escape = 0;
+	    if (c == '\n') {
+	        c = getc(f);
+		continue;
+	    }
+
+	    got = 0;
+	    switch (c) {
+	    case 'a':
+		value = '\a';
+		break;
+	    case 'b':
+		value = '\b';
+		break;
+	    case 'f':
+		value = '\f';
+		break;
+	    case 'n':
+		value = '\n';
+		break;
+	    case 'r':
+		value = '\r';
+		break;
+	    case 's':
+		value = ' ';
+		break;
+	    case 't':
+		value = '\t';
+		break;
+
+	    default:
+		if (isoctal(c)) {
+		    /*
+		     * \ddd octal sequence
+		     */
+		    value = 0;
+		    for (n = 0; n < 3 && isoctal(c); ++n) {
+			value = (value << 3) + (c & 07);
+			c = getc(f);
+		    }
+		    got = 1;
+		    break;
+		}
+
+		if (c == 'x') {
+		    /*
+		     * \x<hex_string> sequence
+		     */
+		    value = 0;
+		    c = getc(f);
+		    for (n = 0; n < 2 && isxdigit(c); ++n) {
+			digit = toupper(c) - '0';
+			if (digit > 10)
+			    digit += '0' + 10 - 'A';
+			value = (value << 4) + digit;
+			c = getc (f);
+		    }
+		    got = 1;
+		    break;
+		}
+
+		/*
+		 * Otherwise the character stands for itself.
+		 */
+		value = c;
+		break;
+	    }
+
+	    /*
+	     * Store the resulting character for the escape sequence.
+	     */
+	    if (len < MAXWORDLEN-1)
+		word[len] = value;
+	    ++len;
+
+	    if (!got)
+		c = getc(f);
+	    continue;
+
+	}
+
+	/*
+	 * Not escaped: see if we've reached the end of the word.
+	 */
+	if (quoted) {
+	    if (c == quoted)
+		break;
+	} else {
+	    if (isspace(c) || c == '#') {
+		ungetc (c, f);
+		break;
+	    }
+	}
+
+	/*
+	 * Backslash starts an escape sequence.
+	 */
+	if (c == '\\') {
+	    escape = 1;
+	    c = getc(f);
+	    continue;
+	}
+
+	/*
+	 * An ordinary character: store it in the word and get another.
+	 */
+	if (len < MAXWORDLEN-1)
+	    word[len] = c;
+	++len;
+
+	c = getc(f);
+    }
+
+    /*
+     * End of the word: check for errors.
+     */
+    if (c == EOF) {
+	if (ferror(f)) {
+	    if (errno == 0)
+		errno = EIO;
+	    option_error("Error reading %s: %m", filename);
+	    die(1);
+	}
+	/*
+	 * If len is zero, then we didn't find a word before the
+	 * end of the file.
+	 */
+	if (len == 0)
+	    return 0;
+    }
+
+    /*
+     * Warn if the word was too long, and append a terminating null.
+     */
+    if (len >= MAXWORDLEN) {
+	option_error("warning: word in file %s too long (%.20s...)",
+		     filename, word);
+	len = MAXWORDLEN - 1;
+    }
+    word[len] = 0;
+
+    return 1;
+
+#undef isoctal
+
+}
+
+/*
+ * number_option - parse an unsigned numeric parameter for an option.
+ */
+static int
+number_option(str, valp, base)
+    char *str;
+    u_int32_t *valp;
+    int base;
+{
+    char *ptr;
+
+    *valp = strtoul(str, &ptr, base);
+    if (ptr == str) {
+	option_error("invalid numeric parameter '%s' for %s option",
+		     str, current_option);
+	return 0;
+    }
+    return 1;
+}
+
+
+/*
+ * int_option - like number_option, but valp is int *,
+ * the base is assumed to be 0, and *valp is not changed
+ * if there is an error.
+ */
+int
+int_option(str, valp)
+    char *str;
+    int *valp;
+{
+    u_int32_t v;
+
+    if (!number_option(str, &v, 0))
+	return 0;
+    *valp = (int) v;
+    return 1;
+}
+
+
+/*
+ * The following procedures parse options.
+ */
+
+/*
+ * readfile - take commands from a file.
+ */
+static int
+readfile(argv)
+    char **argv;
+{
+    return options_from_file(*argv, 1, 1, privileged_option);
+}
+
+/*
+ * callfile - take commands from /etc/ppp/peers/<name>.
+ * Name may not contain /../, start with / or ../, or end in /..
+ */
+static int
+callfile(argv)
+    char **argv;
+{
+    char *fname, *arg, *p;
+    int l, ok;
+
+    arg = *argv;
+    ok = 1;
+    if (arg[0] == '/' || arg[0] == 0)
+	ok = 0;
+    else {
+	for (p = arg; *p != 0; ) {
+	    if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+		ok = 0;
+		break;
+	    }
+	    while (*p != '/' && *p != 0)
+		++p;
+	    if (*p == '/')
+		++p;
+	}
+    }
+    if (!ok) {
+	option_error("call option value may not contain .. or start with /");
+	return 0;
+    }
+
+    l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
+    if ((fname = (char *) malloc(l)) == NULL)
+	novm("call file name");
+    slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
+
+    ok = options_from_file(fname, 1, 1, 1);
+
+    free(fname);
+    return ok;
+}
+
+#ifdef PPP_FILTER
+/*
+ * setpassfilter - Set the pass filter for packets
+ */
+static int
+setpassfilter(argv)
+    char **argv;
+{
+    pc.linktype = DLT_PPP;
+    pc.snapshot = PPP_HDRLEN;
+
+    if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
+	return 1;
+    option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
+    return 0;
+}
+
+/*
+ * setactivefilter - Set the active filter for packets
+ */
+static int
+setactivefilter(argv)
+    char **argv;
+{
+    pc.linktype = DLT_PPP;
+    pc.snapshot = PPP_HDRLEN;
+
+    if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
+	return 1;
+    option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
+    return 0;
+}
+#endif
+
+/*
+ * setdomain - Set domain name to append to hostname
+ */
+static int
+setdomain(argv)
+    char **argv;
+{
+    gethostname(hostname, MAXNAMELEN);
+    if (**argv != 0) {
+	if (**argv != '.')
+	    strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
+	domain = hostname + strlen(hostname);
+	strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+    }
+    hostname[MAXNAMELEN-1] = 0;
+    return (1);
+}
+
+
+static int
+setlogfile(argv)
+    char **argv;
+{
+    int fd, err;
+
+    if (!privileged_option)
+	seteuid(getuid());
+    fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
+    if (fd < 0 && errno == EEXIST)
+	fd = open(*argv, O_WRONLY | O_APPEND);
+    err = errno;
+    if (!privileged_option)
+	seteuid(0);
+    if (fd < 0) {
+	errno = err;
+	option_error("Can't open log file %s: %m", *argv);
+	return 0;
+    }
+    strlcpy(logfile_name, *argv, sizeof(logfile_name));
+    if (logfile_fd >= 0)
+	close(logfile_fd);
+    logfile_fd = fd;
+    log_to_fd = fd;
+    log_default = 0;
+    return 1;
+}
+
+#ifdef PLUGIN
+static int
+loadplugin(argv)
+    char **argv;
+{
+    char *arg = *argv;
+    void *handle;
+    const char *err;
+    void (*init) __P((void));
+    char *path = arg;
+    const char *vers;
+
+    if (strchr(arg, '/') == 0) {
+	const char *base = _PATH_PLUGIN;
+	int l = strlen(base) + strlen(arg) + 2;
+	path = malloc(l);
+	if (path == 0)
+	    novm("plugin file path");
+	strlcpy(path, base, l);
+	strlcat(path, "/", l);
+	strlcat(path, arg, l);
+    }
+    handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
+    if (handle == 0) {
+	err = dlerror();
+	if (err != 0)
+	    option_error("%s", err);
+	option_error("Couldn't load plugin %s", arg);
+	goto err;
+    }
+    init = (void (*)(void))dlsym(handle, "plugin_init");
+    if (init == 0) {
+	option_error("%s has no initialization entry point", arg);
+	goto errclose;
+    }
+    vers = (const char *) dlsym(handle, "pppd_version");
+    if (vers == 0) {
+	warn("Warning: plugin %s has no version information", arg);
+    } else if (strcmp(vers, VERSION) != 0) {
+	option_error("Plugin %s is for pppd version %s, this is %s",
+		     vers, VERSION);
+	goto errclose;
+    }
+    info("Plugin %s loaded.", arg);
+    (*init)();
+    return 1;
+
+ errclose:
+    dlclose(handle);
+ err:
+    if (path != arg)
+	free(path);
+    return 0;
+}
+#endif /* PLUGIN */
diff --git a/ap/app/ppp-2.4.1/pppd/patchlevel.h b/ap/app/ppp-2.4.1/pppd/patchlevel.h
new file mode 100644
index 0000000..c67b0ae
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/patchlevel.h
@@ -0,0 +1,4 @@
+/* $Id: patchlevel.h,v 1.1 2008-08-04 06:11:51 winfred Exp $ */
+
+#define VERSION		"2.4.1"
+#define DATE		"25 March 2001"
diff --git a/ap/app/ppp-2.4.1/pppd/pathnames.h b/ap/app/ppp-2.4.1/pppd/pathnames.h
new file mode 100644
index 0000000..107d522
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/pathnames.h
@@ -0,0 +1,58 @@
+/*
+ * define path names
+ *
+ * $Id: pathnames.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+
+#else /* HAVE_PATHS_H */
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN 	"/tmp/ppp/"
+#endif
+#define _PATH_DEVNULL	"/dev/null"
+#endif /* HAVE_PATHS_H */
+
+#ifndef _ROOT_PATH
+#define _ROOT_PATH
+#endif
+
+#define _PATH_UPAPFILE 	 _ROOT_PATH "/tmp/ppp/pap-secrets"
+#define _PATH_CHAPFILE 	 _ROOT_PATH "/tmp/ppp/chap-secrets"
+#define _PATH_SYSOPTIONS _ROOT_PATH "/tmp/ppp/options"
+#define _PATH_IPUP	 _ROOT_PATH "/bin/pppoe-up"
+#define _PATH_IPDOWN	 _ROOT_PATH "/bin/pppoe-down"
+#define _PATH_AUTHUP	 _ROOT_PATH "/tmp/ppp/auth-up"
+#define _PATH_AUTHDOWN	 _ROOT_PATH "/tmp/ppp/auth-down"
+#define _PATH_TTYOPT	 _ROOT_PATH "/tmp/ppp/options."
+#define _PATH_CONNERRS	 _ROOT_PATH "/tmp/ppp/connect-errors"
+#define _PATH_PEERFILES	 _ROOT_PATH "/tmp/ppp/peers/"
+#define _PATH_RESOLV	 _ROOT_PATH "/etc/resolv.conf"
+#define _PATH_SETPPPOEPID     _ROOT_PATH "/tmp/ppp/set-pppoepid" // tallest 1219
+
+#define _PATH_USEROPT	 ".ppprc"
+
+#ifdef INET6
+#define _PATH_IPV6UP     _ROOT_PATH "/tmp/ppp/ipv6-up"
+#define _PATH_IPV6DOWN   _ROOT_PATH "/tmp/ppp/ipv6-down"
+#endif
+
+#ifdef IPX_CHANGE
+#define _PATH_IPXUP	 _ROOT_PATH "/tmp/ppp/ipx-up"
+#define _PATH_IPXDOWN	 _ROOT_PATH "/tmp/ppp/ipx-down"
+#endif /* IPX_CHANGE */
+
+#ifdef __STDC__
+#define _PATH_PPPDB	_ROOT_PATH _PATH_VARRUN "pppd.tdb"
+#else /* __STDC__ */
+#ifdef HAVE_PATHS_H
+#define _PATH_PPPDB	"/var/run/pppd.tdb"
+#else
+#define _PATH_PPPDB	"/tmp/ppp/pppd.tdb"
+#endif
+#endif /* __STDC__ */
+
+#ifdef PLUGIN
+#define _PATH_PLUGIN	"/usr/lib/pppd/" VERSION
+#endif /* PLUGIN */
diff --git a/ap/app/ppp-2.4.1/pppd/plugins/pppoe/libpppoe.c b/ap/app/ppp-2.4.1/pppd/plugins/pppoe/libpppoe.c
new file mode 100755
index 0000000..8592e0e
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/plugins/pppoe/libpppoe.c
@@ -0,0 +1,615 @@
+/* PPPoE support library "libpppoe"
+ *
+ * Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
+ *		  Jamal Hadi Salim <hadi@cyberus.ca>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#include <pppoe.h>
+
+int disc_sock=-1;
+int retransmit_time=5;
+
+int verify_packet( struct session *ses, struct pppoe_packet *p);
+
+#define TAG_DATA(type,tag_ptr) ((type *) ((struct pppoe_tag*)tag_ptr)->tag_data)
+
+
+/***************************************************************************
+ *
+ * Return the location where the next tag can be pu
+ *
+ **************************************************************************/
+static  struct pppoe_tag *next_tag(struct pppoe_hdr *ph)
+{
+    return (struct pppoe_tag *)
+	(((char *) &ph->tag) + ntohs(ph->length));
+}
+
+/**************************************************************************
+ *
+ * Update header to reflect the addition of a new tag
+ *
+ **************************************************************************/
+static  void add_tag(struct pppoe_hdr *ph, struct pppoe_tag *pt)
+{
+    int len = (ntohs(ph->length) +
+	       ntohs(pt->tag_len) +
+	       sizeof(struct pppoe_tag));
+
+    if (pt != next_tag(ph))
+	printf("PPPoE add_tag caller is buggy\n");
+
+    ph->length = htons(len);
+}
+
+/*************************************************************************
+ *
+ * Look for a tag of a specific type
+ *
+ ************************************************************************/
+struct pppoe_tag *get_tag(struct pppoe_hdr *ph, u_int16_t idx)
+{
+    char *end = (char *) next_tag(ph);
+    char *ptn = NULL;
+    struct pppoe_tag *pt = &ph->tag[0];
+
+    /*
+     * Keep processing tags while a tag header will still fit.
+     *
+     * This check will ensure that the entire tag header pointed
+     * to by pt will fit inside the message, and thus it will be
+     * valid to check the tag_type and tag_len fields.
+     */
+    while ((char *)(pt + 1) <= end) {
+	/*
+	 * If the tag data would go past the end of the packet, abort.
+	 */
+	ptn = (((char *) (pt + 1)) + ntohs(pt->tag_len));
+	if (ptn > end)
+	    return NULL;
+
+	if (pt->tag_type == idx)
+	    return pt;
+
+	pt = (struct pppoe_tag *) ptn;
+    }
+
+    return NULL;
+}
+
+/* We want to use tag names to reference into arrays  containing the tag data.
+   This takes an RFC 2516 tag identifier and maps it into a local one.
+   The reverse mapping is accomplished via the tag_map array */
+#define UNMAP_TAG(x) case PTT_##x : return TAG_##x
+static inline int tag_index(int tag){
+    switch(tag){
+	UNMAP_TAG(SRV_NAME);
+	UNMAP_TAG(AC_NAME);
+	UNMAP_TAG(HOST_UNIQ);
+	UNMAP_TAG(AC_COOKIE);
+	UNMAP_TAG(VENDOR);
+	UNMAP_TAG(RELAY_SID);
+	UNMAP_TAG(SRV_ERR);
+	UNMAP_TAG(SYS_ERR);
+	UNMAP_TAG(GEN_ERR);
+	UNMAP_TAG(EOL);
+    };
+    return -1;
+}
+
+/*************************************************************************
+ *
+ * Makes a copy of a tag into a PPPoE packe
+ *
+ ************************************************************************/
+void copy_tag(struct pppoe_packet *dest, struct pppoe_tag *pt)
+{
+    struct pppoe_tag *end_tag = get_tag(dest->hdr, PTT_EOL);
+    int tagid;
+    int tag_len;
+    if( !pt ) {
+	return;
+    }
+    tagid = tag_index(pt->tag_type);
+
+    tag_len = sizeof(struct pppoe_tag) + ntohs(pt->tag_len);
+
+    if( end_tag ){
+	memcpy(((char*)end_tag)+tag_len ,
+	       end_tag, sizeof(struct pppoe_tag));
+
+	dest->tags[tagid]=end_tag;
+	dest->tags[TAG_EOL] = (struct pppoe_tag*)((char*)dest->tags[TAG_EOL] + tag_len);
+	memcpy(end_tag, pt, tag_len);
+	dest->hdr->length = htons(ntohs(dest->hdr->length) + tag_len);
+
+    }else{
+	memcpy(next_tag(dest->hdr),pt, tag_len);
+	dest->tags[tagid]=next_tag(dest->hdr);
+	add_tag(dest->hdr,next_tag(dest->hdr));
+    }
+
+
+}
+
+
+/*************************************************************************
+ *
+ * Put tags from a packet into a nice array
+ *
+ ************************************************************************/
+static void extract_tags(struct pppoe_hdr *ph, struct pppoe_tag** buf){
+    int i=0;
+    for(;i<MAX_TAGS;++i){
+	buf[i] = get_tag(ph,tag_map[i]);
+    }
+}
+
+
+/*************************************************************************
+ *
+ * Verify that a packet has a tag containint a specific value
+ *
+ ************************************************************************/
+static int verify_tag(struct session* ses,
+		      struct pppoe_packet* p,
+		      unsigned short id,
+		      char* data,
+		      int data_len)
+{
+    int len;
+    struct pppoe_tag *pt = p->tags[id];
+
+    if( !pt ){
+	poe_info(ses,"Missing tag %d. Expected %s\n",
+		 id,data);
+	return 0;
+    }
+    len = ntohs(pt->tag_len);
+    if(len != data_len){
+	poe_info(ses,"Length mismatch on tag %d: expect: %d got: %d\n",
+		 id, data_len, len);
+	return 0;
+    }
+
+    if( 0!=memcmp(pt->tag_data,data,data_len)){
+	poe_info(ses,"Tag data mismatch on tag %d: expect: %s vs %s\n",
+		 id, data,pt->tag_data);
+	return 0;
+    }
+    return 1;
+}
+
+
+/*************************************************************************
+ *
+ * Verify the existence of an ethernet device.
+ * Construct an AF_PACKET address struct to match.
+ *
+ ************************************************************************/
+int get_sockaddr_ll(const char *devnam,struct sockaddr_ll* sll){
+    struct ifreq ifr;
+    int retval;
+
+    if(disc_sock<0){
+
+	disc_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+	if( disc_sock < 0 ){
+	    return -1;
+	}
+    }
+
+    strncpy(ifr.ifr_name, devnam, sizeof(ifr.ifr_name));
+
+    retval = ioctl( disc_sock , SIOCGIFINDEX, &ifr);
+
+    if( retval < 0 ){
+//	error("Bad device name: %s  (%m)",devnam);
+	return 0;
+    }
+
+    if(sll) sll->sll_ifindex = ifr.ifr_ifindex;
+
+    retval = ioctl (disc_sock, SIOCGIFHWADDR, &ifr);
+    if( retval < 0 ){
+//	error("Bad device name: %s  (%m)",devnam);
+	return 0;
+    }
+
+    if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+	error("Interface %s is not Ethernet!", devnam);
+	return 0;
+    }
+    if(sll){
+	sll->sll_family	= AF_PACKET;
+	sll->sll_protocol= ntohs(ETH_P_PPP_DISC);
+	sll->sll_hatype	= ARPHRD_ETHER;
+	sll->sll_pkttype = PACKET_BROADCAST;
+	sll->sll_hatype	= ETH_ALEN;
+	memcpy( sll->sll_addr , ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+    }
+    return 1;
+}
+
+
+
+
+/*************************************************************************
+ *
+ * Construct and send a discovery message.
+ *
+ ************************************************************************/
+int send_disc(struct session *ses, struct pppoe_packet *p)
+{
+    char buf[MAX_PAYLOAD + sizeof(struct pppoe_hdr)];
+    int data_len = sizeof(struct pppoe_hdr);
+
+    struct pppoe_hdr *ph = NULL;
+    struct pppoe_tag *tag = NULL;
+    int i, err = 0;
+    int got_host_uniq = 0;
+    int got_srv_name = 0;
+    int got_ac_name = 0;
+
+    for (i = 0; i < MAX_TAGS; i++) {
+	if (!p->tags[i])
+	    continue;
+
+	got_host_uniq |= (p->tags[i]->tag_type == PTT_HOST_UNIQ);
+
+	/* Relay identifiers qualify as HOST_UNIQ's:
+	   we need HOST_UNIQ to uniquely identify the packet,
+	   PTT_RELAY_SID is sufficient for us for outgoing packets */
+	got_host_uniq |= (p->tags[i]->tag_type == PTT_RELAY_SID);
+
+	got_srv_name |= (p->tags[i]->tag_type == PTT_SRV_NAME);
+	got_ac_name  |= (p->tags[i]->tag_type == PTT_AC_NAME);
+
+	data_len += (ntohs(p->tags[i]->tag_len) +
+		     sizeof(struct pppoe_tag));
+    }
+
+    ph = (struct pppoe_hdr *) buf;
+
+
+    memcpy(ph, p->hdr, sizeof(struct pppoe_hdr));
+    ph->length = __constant_htons(0);
+
+    /* if no HOST_UNIQ tags --- add one with process id */
+    if (!got_host_uniq){
+	data_len += (sizeof(struct pppoe_tag) +
+		     sizeof(struct session *));
+	tag = next_tag(ph);
+	tag->tag_type = PTT_HOST_UNIQ;
+	tag->tag_len = htons(sizeof(struct session *));
+	memcpy(tag->tag_data,
+	       &ses,
+	       sizeof(struct session *));
+
+	add_tag(ph, tag);
+    }
+
+    if( !got_srv_name ){
+	data_len += sizeof(struct pppoe_tag);
+	tag = next_tag(ph);
+	tag->tag_type = PTT_SRV_NAME;
+	tag->tag_len = 0;
+	add_tag(ph, tag);
+    }
+
+    if(!got_ac_name && ph->code==PADO_CODE){
+	data_len += sizeof(struct pppoe_tag);
+	tag = next_tag(ph);
+	tag->tag_type = PTT_AC_NAME;
+	tag->tag_len = 0;
+	add_tag(ph, tag);
+    }
+
+    for (i = 0; i < MAX_TAGS; i++) {
+	if (!p->tags[i])
+	    continue;
+
+	tag = next_tag(ph);
+	memcpy(tag, p->tags[i],
+	       sizeof(struct pppoe_tag) + ntohs(p->tags[i]->tag_len));
+
+	add_tag(ph, tag);
+    }
+
+    /* Now fixup the packet struct to make sure all of its pointers
+       are self-contained */
+    memcpy( p->hdr , ph, data_len );
+    extract_tags( p->hdr, p->tags);
+
+    err = sendto(disc_sock, buf, data_len, 0,
+		   (struct sockaddr*) &p->addr,
+		   sizeof(struct sockaddr_ll));
+
+    if(err < 0)
+	poe_error(ses,"sendto returned: %m\n");
+
+    return err;
+}
+
+/*************************************************************************
+ *
+ * Verify that a packet is legal
+ *
+ *************************************************************************/
+int verify_packet( struct session *ses, struct pppoe_packet *p){
+    struct session * hu_val;
+
+    /* This code here should do all of the error checking and
+       validation on the incoming packet */
+
+
+    /* If we receive any error tags, abort */
+#define CHECK_TAG(name, val)					\
+    if((NULL==p->tags[name])== val){				\
+	poe_error(ses,"Tag error: " #name );			\
+	return -1;						\
+    }
+
+
+    /* If packet is not directed to our MAC address, forget it */
+    if (ses->state == PADS_CODE) {
+	    if (memcmp(p->addr.sll_addr, ses->remote.sll_addr, ETH_ALEN)) {
+		poe_info(ses,"ETH_DEST mismatch: %E %E \n",p->addr.sll_addr, ses->remote.sll_addr);
+		return -1;
+	    }
+    }
+
+    CHECK_TAG(TAG_SRV_ERR,0);
+    CHECK_TAG(TAG_SYS_ERR,0);
+    CHECK_TAG(TAG_GEN_ERR,0);
+
+    /* A HOST_UNIQ must be present */
+    CHECK_TAG(TAG_HOST_UNIQ,1);
+
+    hu_val = *TAG_DATA(struct session* ,p->tags[TAG_HOST_UNIQ]);
+
+    if( hu_val != ses ){
+	poe_info(ses,"HOST_UNIQ mismatch: %08x %i\n",(int)hu_val,getpid());
+	return -1;
+    }
+
+    if(ses->filt->htag &&
+       !verify_tag(ses,p,TAG_HOST_UNIQ,ses->filt->htag->tag_data,(int)ntohs(ses->filt->htag->tag_len))) {
+	poe_info(ses,"HOST_UNIQ failure");
+	return -1;
+    }
+
+
+    if(ses->filt->ntag && ses->state == PADO_CODE &&
+       !verify_tag(ses,p,TAG_AC_NAME,ses->filt->ntag->tag_data,(int)ntohs(ses->filt->ntag->tag_len))){
+	poe_info(ses,"AC_NAME failure");
+	return -1;
+    }
+
+    if(ses->filt->stag &&
+       !verify_tag(ses,p,TAG_SRV_NAME,ses->filt->stag->tag_data,(int)ntohs(ses->filt->stag->tag_len))){
+	poe_info(ses,"SRV_NAME failure");
+	return -1;
+    }
+
+    return 0;
+}
+
+
+/*************************************************************************
+ *
+ * Receive and verify an incoming packet.
+ *
+ *************************************************************************/
+static int recv_disc( struct session *ses,
+		      struct pppoe_packet *p){
+    int error = 0;
+    unsigned int from_len = sizeof(struct sockaddr_ll);
+
+    p->hdr = (struct pppoe_hdr*)p->buf;
+
+    error = recvfrom( disc_sock, p->buf, 1500, 0,
+		      (struct sockaddr*)&p->addr, &from_len);
+
+    if(error < 0) return error;
+
+    extract_tags(p->hdr,p->tags);
+
+    return 1;
+}
+
+
+/*************************************************************************
+ *
+ * Send a PADT
+ *
+ *************************************************************************/
+int session_disconnect(struct session *ses){
+    struct pppoe_packet padt;
+
+    memset(&padt,0,sizeof(struct pppoe_packet));
+    memcpy(&padt.addr, &ses->remote, sizeof(struct sockaddr_ll));
+
+    padt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf;
+    padt.hdr->ver  = 1;
+    padt.hdr->type = 1;
+    padt.hdr->code = PADT_CODE;
+    padt.hdr->sid  = ses->sp.sa_addr.pppoe.sid;
+
+    send_disc(ses,&padt);
+    ses->sp.sa_addr.pppoe.sid = 0 ;
+    ses->state = PADO_CODE;
+    return 0;
+
+}
+
+
+/*************************************************************************
+ *
+ * Make a connection -- behaviour depends on callbacks specified in "ses"
+ *
+ *************************************************************************/
+int session_connect(struct session *ses)
+{
+
+    struct pppoe_packet *p_out=NULL;
+    struct pppoe_packet rcv_packet;
+    int ret;
+
+
+    if(ses->init_disc){
+	ret = (*ses->init_disc)(ses, NULL, &p_out);
+	if( ret != 0 ) return ret;
+    }
+
+    /* main discovery loop */
+
+
+    while(ses->retransmits < ses->retries || ses->retries==-1 ){
+
+	fd_set in;
+	struct timeval tv;
+	FD_ZERO(&in);
+
+	FD_SET(disc_sock,&in);
+
+	if(ses->retransmits < 0)
+	    ret = select(disc_sock+1, &in, NULL, NULL, NULL);
+	else {
+	    ++ses->retransmits;
+	    tv.tv_sec = 1 << ses->retransmits;
+	    //tv.tv_sec = retransmit_time;
+	    tv.tv_usec = 0;
+again:
+	    ret = select(disc_sock+1, &in, NULL, NULL, &tv);
+	}
+	if( ret < 0 && errno != EINTR){
+	    return -1;
+	}
+	else 	if( ret == 0 ) {
+
+	    if( ses->timeout ) {
+		ret = (*ses->timeout)(ses, NULL, &p_out);
+		if( ret != 0 )
+		    return ret;
+	    }
+	    else if(p_out)
+		send_disc(ses,p_out);
+		
+	    continue;
+	}
+
+	ret = recv_disc(ses, &rcv_packet);
+	/* Should differentiate between system errors and
+	   bad packets and the like... */
+	if( ret < 0 && errno )
+	    return -1;
+
+	switch (rcv_packet.hdr->code) {
+
+	case PADI_CODE:
+	{
+	    if(ses->rcv_padi){
+		ret = (*ses->rcv_padi)(ses,&rcv_packet,&p_out);
+
+		if( ret != 0){
+		    return ret;
+		}
+	    }
+	    break;
+	}
+
+	case PADO_CODE:		/* wait for PADO */
+	{
+	    if(ses->rcv_pado){
+		ret = (*ses->rcv_pado)(ses,&rcv_packet,&p_out);
+
+		if( ret != 0){
+		    return ret;
+		}
+		else
+		    goto again;
+	    }
+	    break;
+	}
+
+	case PADR_CODE:
+	{
+	    if(ses->rcv_padr){
+		ret = (*ses->rcv_padr)(ses,&rcv_packet,&p_out);
+
+		if( ret != 0){
+		    return ret;
+		}
+	    }
+	    break;
+	}
+
+	case PADS_CODE:		/* wait for PADS */
+	{
+	    if(ses->rcv_pads){
+		ret = (*ses->rcv_pads)(ses,&rcv_packet,&p_out);
+
+		if( ret != 0){
+		    return ret;
+		}
+		else
+		    goto again;
+	    }
+	    break;
+	}
+
+	case PADT_CODE:
+	{
+	    if( rcv_packet.hdr->sid != ses->sp.sa_addr.pppoe.sid ){
+		--ses->retransmits;
+		continue;
+	    }
+	    if(ses->rcv_padt){
+		ret = (*ses->rcv_padt)(ses,&rcv_packet,&p_out);
+
+		if( ret != 0){
+		    return ret;
+		}
+		else
+		    goto again;
+	    }else{
+		poe_error (ses,"connection terminated");
+		return (-1);
+	    }
+	    break;
+	}
+	default:
+	    poe_error(ses,"invalid packet %P",&rcv_packet);
+	    return (-1);
+	}
+    }
+    return (0);
+}
+
+
+/*************************************************************************
+ *
+ * Register an ethernet address as a client of relaying services.
+ *
+ *************************************************************************/
+
+struct pppoe_tag *make_filter_tag(short type, short length, char* data){
+    struct pppoe_tag *pt =
+	(struct pppoe_tag* )malloc( sizeof(struct pppoe_tag) + length );
+
+    if(pt == NULL) return NULL;
+
+    pt->tag_len=htons(length);
+    pt->tag_type=type;
+
+    if(length>0 && data){
+	memcpy( pt+1, data, length);
+    }
+    return pt;
+}
diff --git a/ap/app/ppp-2.4.1/pppd/plugins/pppoe/pppoe_client.c b/ap/app/ppp-2.4.1/pppd/plugins/pppoe/pppoe_client.c
new file mode 100755
index 0000000..5f84828
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/plugins/pppoe/pppoe_client.c
@@ -0,0 +1,429 @@
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <pppoe.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#include <linux/if_ppp.h>
+#include <pppd.h>
+#include <fsm.h>
+#include <lcp.h>
+#include <ipcp.h>
+#include <ccp.h>
+#include <pathnames.h>
+
+extern int kill_link;
+struct session *ses = NULL;
+char	*pppoe_srv_name=NULL;
+char	*pppoe_ac_name=NULL;
+char    *hostuniq = NULL;
+int     retries = 0;
+
+#define PPPOE_MTU	1492
+#define _PATH_ETHOPT         _ROOT_PATH "/etc/ppp/options."
+
+int setdevname_pppoe(const char *cp);
+
+extern int disc_sock;
+
+static int std_rcv_pado(struct session* ses,
+			struct pppoe_packet *p_in,
+			struct pppoe_packet **p_out){
+
+    
+    if(ses->state != PADO_CODE ){
+	return 0;
+    }
+    
+    if( verify_packet(ses, p_in) < 0)
+	return 0;
+
+    char ac[1024], srv[1024];
+    struct pppoe_tag *ac_name, *srv_name;
+	
+    sc_cfg_set("pppoe_reply","1");
+    
+    memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll));
+    memcpy(&ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
+    
+    ses->curr_pkt.hdr->code = PADR_CODE;
+    copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_HOST_UNIQ));	
+    
+    if (ses->filt->ntag) {
+    	ses->curr_pkt.tags[TAG_AC_NAME]=NULL;
+    }
+    
+    srv_name = get_tag(p_in->hdr,PTT_SRV_NAME);
+    ac_name = get_tag(p_in->hdr,PTT_AC_NAME);
+
+    memset(srv, 0, sizeof(srv)); 	 
+    memset(ac, 0, sizeof(ac)); 	 
+    
+    strncpy(srv, srv_name->tag_data, ntohs(srv_name->tag_len));
+    strncpy(ac, ac_name->tag_data, ntohs(ac_name->tag_len));
+
+    script_setenv("SRV_NAME", srv, 1);
+    script_setenv("AC_NAME", ac, 1);
+    
+    if(ses->filt->stag) {
+    	ses->curr_pkt.tags[TAG_SRV_NAME]=NULL;
+    }
+    copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_COOKIE));
+    copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME));
+    copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_RELAY_SID));
+    
+    ses->retransmits = 0;
+    ses->state = PADS_CODE;
+    send_disc(ses, &ses->curr_pkt);
+    (*p_out) = &ses->curr_pkt;
+    
+    if (!ses->np)
+    {
+		return 0;
+	}
+	else
+	{
+	    return 1;
+	}
+}
+
+static int std_init_disc(struct session* ses,
+			 struct pppoe_packet *p_in,
+			 struct pppoe_packet **p_out){
+    
+    if( ses->state != PADO_CODE ){
+	return -1;
+    }
+    
+    memset(&ses->curr_pkt,0, sizeof(struct pppoe_packet));
+
+    ses->curr_pkt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf;
+    ses->curr_pkt.hdr->ver  = 1;
+    ses->curr_pkt.hdr->type = 1;
+    ses->curr_pkt.hdr->code = PADI_CODE;
+    
+    
+    memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
+    ses->retransmits = 0 ;
+    if(ses->filt->stag)
+	ses->curr_pkt.tags[TAG_SRV_NAME]=ses->filt->stag;
+    if(ses->filt->ntag)
+	ses->curr_pkt.tags[TAG_AC_NAME]=ses->filt->ntag;
+    if(ses->filt->htag)
+	ses->curr_pkt.tags[TAG_HOST_UNIQ]=ses->filt->htag;
+    ses->retransmits = 0 ;
+    send_disc(ses, &ses->curr_pkt);
+    (*p_out)= &ses->curr_pkt;
+
+    return 0;
+}
+
+
+static int std_rcv_pads(struct session* ses,
+			struct pppoe_packet *p_in,
+			struct pppoe_packet **p_out){
+    if(ses->state != PADS_CODE ){
+	return 0;
+    }
+    
+    if( verify_packet(ses, p_in) < 0)
+	return 0;
+    
+    ses->sp.sa_addr.pppoe.sid = p_in->hdr->sid;
+    ses->sp.sa_protocol = PX_PROTO_OE;
+    ses->sp.sa_family = AF_PPPOX;
+    memcpy(ses->sp.sa_addr.pppoe.remote, p_in->addr.sll_addr, ETH_ALEN);
+    memcpy(ses->sp.sa_addr.pppoe.dev,ses->name, IFNAMSIZ);
+    
+    return 1;
+}
+
+static int std_rcv_padt(struct session* ses,
+			struct pppoe_packet *p_in,
+			struct pppoe_packet **p_out){
+    ses->state = PADO_CODE;
+    return 0;
+}
+
+int retry_num = 10;
+
+static int connect_pppoe_ses(void)
+{
+    int err=-1;
+
+    client_init_ses(ses,devnam);
+
+    strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
+
+    err= session_connect ( ses );
+    if(err < 0){
+    }
+    err = connect(ses->fd, (struct sockaddr*)&ses->sp,
+		  sizeof(struct sockaddr_pppox));
+
+    if( err < 0 ){
+	return err;
+    }
+    /* Once the logging is fixed, print a message here indicating
+       connection parameters */
+
+    return ses->fd;
+}
+
+static void disconnect_pppoe_ses(void)
+{
+    int ret;
+    printf("Doing disconnect");
+    session_disconnect(ses);
+    ses->sp.sa_addr.pppoe.sid = 0;
+    ret = connect(ses->fd, (struct sockaddr*)&ses->sp,
+	    sizeof(struct sockaddr_pppox));
+}
+
+static void init_device_pppoe(void)
+{
+    struct filter *filt;
+    ses=(void *)malloc(sizeof(struct session));
+    if(!ses){
+	printf("No memory for new PPPoE session");
+    }
+    memset(ses,0,sizeof(struct session));
+
+    if ((ses->filt=malloc(sizeof(struct filter))) == NULL) {
+	return;
+    }
+
+    filt=ses->filt;  /* makes the code more readable */
+    memset(filt,0,sizeof(struct filter));
+
+    if (pppoe_ac_name !=NULL) {
+	if (strlen (pppoe_ac_name) > 255) {
+	    return;
+	}
+	ses->filt->ntag = make_filter_tag(PTT_AC_NAME,
+					  strlen(pppoe_ac_name),
+					  pppoe_ac_name);
+
+	if ( ses->filt->ntag== NULL) {
+	    return;
+	}
+
+    }
+
+
+    if (pppoe_srv_name !=NULL) {
+	if (strlen (pppoe_srv_name) > 255) {
+	    return;
+	}
+	ses->filt->stag = make_filter_tag(PTT_SRV_NAME,
+					  strlen(pppoe_srv_name),
+					  pppoe_srv_name);
+	if ( ses->filt->stag == NULL) {
+	    return;
+	}
+    }
+
+    if (hostuniq) {
+	ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ,
+					  strlen(hostuniq),
+					  hostuniq);
+	if ( ses->filt->htag == NULL) {
+	    return;
+	}
+    }
+
+    if (retries) {
+	ses->retries=retries;
+    }
+    memcpy( ses->name, devnam, IFNAMSIZ);
+    ses->opt_debug=1;
+    ses->fd = -1;
+}
+
+static void send_config_pppoe(int mtu,
+			      u_int32_t asyncmap,
+			      int pcomp,
+			      int accomp)
+{
+    int sock;
+    struct ifreq ifr;
+
+    if (mtu > PPPOE_MTU)
+	printf("Couldn't increase MTU to %d", mtu);
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0)
+	printf("Couldn't create IP socket: %m");
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    ifr.ifr_mtu = mtu;
+    if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+	printf("ioctl(SIOCSIFMTU): %m");
+    (void) close (sock);
+}
+
+int client_init_ses (struct session *ses, char* devnam)
+{
+  int retval;
+  char dev[IFNAMSIZ+1];
+  int addr[ETH_ALEN];
+  int sid;
+  
+  if( disc_sock < 0 ){
+  
+  disc_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+  if( disc_sock < 0 ){
+  }
+  
+  }
+  
+  retval =sscanf(devnam, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
+		 addr+3, addr+4, addr+5,&sid,dev);
+  if( retval != 8 ){
+  retval = get_sockaddr_ll(devnam,&ses->local);
+  if (retval < 0)
+  {}
+  
+  
+  ses->state = PADO_CODE;
+  memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
+  
+  memset( ses->remote.sll_addr, 0xff, ETH_ALEN);
+  }
+  else
+  {
+  retval = get_sockaddr_ll(dev,&ses->local);
+  if (retval < 0)
+  {}
+  ses->state = PADS_CODE;
+  ses->sp.sa_family = AF_PPPOX;
+  ses->sp.sa_protocol = PX_PROTO_OE;
+  ses->sp.sa_addr.pppoe.sid = sid;
+  
+  memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
+  int i=0;
+  for(; i < ETH_ALEN ; ++i ){
+	  ses->sp.sa_addr.pppoe.remote[i] = addr[i];
+	  ses->remote.sll_addr[i]=addr[i];
+  }
+  memcpy(ses->sp.sa_addr.pppoe.dev, dev, IFNAMSIZ);
+  
+  
+  
+  }
+  if( retval < 0 )
+  {}
+  retval = bind( disc_sock ,
+		 (struct sockaddr*)&ses->local,
+		 sizeof(struct sockaddr_ll));
+  if( retval < 0 ){
+  }
+  if (ses->fd < 0) {
+	  ses->fd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE);
+	  if(ses->fd < 0)
+	  {
+	  }
+  }
+  ses->init_disc = std_init_disc;
+  ses->rcv_pado  = std_rcv_pado;
+  ses->rcv_pads  = std_rcv_pads;
+  ses->rcv_padt  = std_rcv_padt;
+  ses->retries = retry_num;
+  return ses->fd;
+}
+
+
+static void recv_config_pppoe(int mru,
+			      u_int32_t asyncmap,
+			      int pcomp,
+			      int accomp)
+{
+    if (mru > PPPOE_MTU)
+	printf("Couldn't increase MRU to %d", mru);
+}
+
+struct channel pppoe_channel;
+/* Check is cp is a valid ethernet device
+ * return either 1 if "cp" is a reasonable thing to name a device
+ * or die.
+ * Note that we don't actually open the device at this point
+ * We do need to fill in:
+ *   devnam: a string representation of the device
+ */
+
+int (*old_setdevname_hook)(const char* cp) = NULL;
+int setdevname_pppoe(const char *cp)
+{
+    int ret;
+    char dev[IFNAMSIZ+1];
+    int addr[ETH_ALEN];
+    int sid;
+    option_t *opt;
+
+    ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
+		addr+3, addr+4, addr+5,&sid,dev);
+    if( ret != 8 ){
+
+	ret = get_sockaddr_ll(cp,NULL);
+        if (ret < 0)
+	    printf("Cannot create PF_PACKET socket for PPPoE discovery\n");
+	if (ret == 1)
+	    strncpy(devnam, cp, sizeof(devnam));
+    }else{
+	/* long form parsed */
+	ret = get_sockaddr_ll(dev,NULL);
+        if (ret < 0)
+	    printf("Cannot create PF_PACKET socket for PPPoE discovery\n");
+
+	strncpy(devnam, cp, sizeof(devnam));
+	ret = 1;
+    }
+
+    if( ret == 1 && the_channel != &pppoe_channel ){
+
+	the_channel = &pppoe_channel;
+
+	lcp_allowoptions[0].neg_accompression = 0;
+	lcp_wantoptions[0].neg_accompression = 0;
+
+	lcp_allowoptions[0].neg_asyncmap = 0;
+	lcp_wantoptions[0].neg_asyncmap = 0;
+
+	lcp_allowoptions[0].neg_pcompression = 0;
+	lcp_wantoptions[0].neg_pcompression = 0;
+
+	ipcp_allowoptions[0].neg_vj=0;
+	ipcp_wantoptions[0].neg_vj=0;
+
+	ipcp_allowoptions[0].default_route=1;
+	
+	/* remove for add -R parameter set default route. by tallest.*/
+	//ipcp_wantoptions[0].default_route=0;
+	
+	for (opt = ipcp_protent.options; opt->name != NULL; ++opt) {
+		if (!strncmp(opt->name, "usepeerdns", 10)) {
+			*(bool *)(opt->addr) = 1;
+			break;
+		}
+	}
+	init_device_pppoe();
+    }
+    return ret;
+}
+
+struct channel pppoe_channel = {
+    options: NULL,
+    process_extra_options: NULL,
+    check_options: NULL,
+    connect: &connect_pppoe_ses,
+    disconnect: &disconnect_pppoe_ses,
+    establish_ppp: &generic_establish_ppp,
+    disestablish_ppp: &generic_disestablish_ppp,
+    send_config: &send_config_pppoe,
+    recv_config: &recv_config_pppoe,
+    close: NULL,
+    cleanup: NULL
+};
+
diff --git a/ap/app/ppp-2.4.1/pppd/pppd.h b/ap/app/ppp-2.4.1/pppd/pppd.h
new file mode 100644
index 0000000..8ddddcc
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/pppd.h
@@ -0,0 +1,795 @@
+/*
+ * pppd.h - PPP daemon global declarations.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: pppd.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+/*
+ * TODO:
+ */
+
+#ifndef __PPPD_H__
+#define __PPPD_H__
+
+#include <stdio.h>		/* for FILE */
+#include <syslog.h>
+#include <limits.h>		/* for NGROUPS_MAX */
+#include <sys/param.h>		/* for MAXPATHLEN and BSD4_4, if defined */
+#include <sys/types.h>		/* for u_int32_t, if defined */
+#include <sys/time.h>		/* for struct timeval */
+#include <net/ppp_defs.h>
+#include "patchlevel.h"
+
+#if defined(__STDC__)
+#include <stdarg.h>
+#define __V(x)	x
+#else
+#include <varargs.h>
+#define __V(x)	(va_alist) va_dcl
+#define const
+#define volatile
+#endif
+
+#ifdef INET6
+#include "eui64.h"
+#endif
+
+/*
+ * Limits.
+ */
+
+#define NUM_PPP		1	/* One PPP interface supported (per process) */
+#define MAXWORDLEN	1024	/* max length of word in file (incl null) */
+#define MAXARGS		1	/* max # args to a command */
+#define MAXNAMELEN	256	/* max length of hostname or name for auth */
+#define MAXSECRETLEN	256	/* max length of password or secret */
+
+/*
+ * Option descriptor structure.
+ */
+
+typedef unsigned char	bool;
+
+enum opt_type {
+	o_special_noarg = 0,
+	o_special = 1,
+	o_bool,
+	o_int,
+	o_uint32,
+	o_string,
+	o_wild,
+};
+
+typedef struct {
+	char	*name;		/* name of the option */
+	enum opt_type type;
+	void	*addr;
+	char	*description;
+	int	flags;
+	void	*addr2;
+	int	upper_limit;
+	int	lower_limit;
+	const char *source;
+	short int priority;
+	short int winner;
+} option_t;
+
+/* Values for flags */
+#define OPT_VALUE	0xff	/* mask for presupplied value */
+#define OPT_HEX		0x100	/* int option is in hex */
+#define OPT_NOARG	0x200	/* option doesn't take argument */
+#define OPT_OR		0x400	/* OR in argument to value */
+#define OPT_INC		0x800	/* increment value */
+#define OPT_PRIV	0x1000	/* privileged option */
+#define OPT_STATIC	0x2000	/* string option goes into static array */
+#define OPT_LLIMIT	0x4000	/* check value against lower limit */
+#define OPT_ULIMIT	0x8000	/* check value against upper limit */
+#define OPT_LIMITS	(OPT_LLIMIT|OPT_ULIMIT)
+#define OPT_ZEROOK	0x10000	/* 0 value is OK even if not within limits */
+#define OPT_HIDE	0x10000	/* for o_string, print value as ?????? */
+#define OPT_A2LIST	0x10000 /* for o_special, keep list of values */
+#define OPT_NOINCR	0x20000	/* value mustn't be increased */
+#define OPT_ZEROINF	0x40000	/* with OPT_NOINCR, 0 == infinity */
+#define OPT_PRIO	0x80000	/* process option priorities for this option */
+#define OPT_PRIOSUB	0x100000 /* subsidiary member of priority group */
+#define OPT_ALIAS	0x200000 /* option is alias for previous option */
+#define OPT_A2COPY	0x400000 /* addr2 -> second location to rcv value */
+#define OPT_ENABLE	0x800000 /* use *addr2 as enable for option */
+#define OPT_A2CLR	0x1000000 /* clear *(bool *)addr2 */
+#define OPT_PRIVFIX	0x2000000 /* user can't override if set by root */
+#define OPT_INITONLY	0x4000000 /* option can only be set in init phase */
+#define OPT_DEVEQUIV	0x8000000 /* equiv to device name */
+#define OPT_DEVNAM	(OPT_INITONLY | OPT_DEVEQUIV)
+#define OPT_A2PRINTER	0x10000000 /* *addr2 is a fn for printing option */
+#define OPT_A2STRVAL	0x20000000 /* *addr2 points to current string value */
+#define OPT_NOPRINT	0x40000000 /* don't print this option at all */
+
+#define OPT_VAL(x)	((x) & OPT_VALUE)
+
+/* Values for priority */
+#define OPRIO_DEFAULT	0	/* a default value */
+#define OPRIO_CFGFILE	1	/* value from a configuration file */
+#define OPRIO_CMDLINE	2	/* value from the command line */
+#define OPRIO_SECFILE	3	/* value from options in a secrets file */
+#define OPRIO_ROOT	100	/* added to priority if OPT_PRIVFIX && root */
+
+#ifndef GIDSET_TYPE
+#define GIDSET_TYPE	gid_t
+#endif
+
+/* Structure representing a list of permitted IP addresses. */
+struct permitted_ip {
+    int		permit;		/* 1 = permit, 0 = forbid */
+    u_int32_t	base;		/* match if (addr & mask) == base */
+    u_int32_t	mask;		/* base and mask are in network byte order */
+};
+
+/*
+ * Unfortunately, the linux kernel driver uses a different structure
+ * for statistics from the rest of the ports.
+ * This structure serves as a common representation for the bits
+ * pppd needs.
+ */
+struct pppd_stats {
+    unsigned int	bytes_in;
+    unsigned int	bytes_out;
+};
+
+/* Used for storing a sequence of words.  Usually malloced. */
+struct wordlist {
+    struct wordlist	*next;
+    char		*word;
+};
+
+/* An endpoint discriminator, used with multilink. */
+#define MAX_ENDP_LEN	20	/* maximum length of discriminator value */
+struct epdisc {
+    unsigned char	class;
+    unsigned char	length;
+    unsigned char	value[MAX_ENDP_LEN];
+};
+
+/* values for epdisc.class */
+#define EPD_NULL	0	/* null discriminator, no data */
+#define EPD_LOCAL	1
+#define EPD_IP		2
+#define EPD_MAC		3
+#define EPD_MAGIC	4
+#define EPD_PHONENUM	5
+
+typedef void (*notify_func) __P((void *, int));
+
+struct notifier {
+    struct notifier *next;
+    notify_func	    func;
+    void	    *arg;
+};
+
+/*
+ * Global variables.
+ */
+
+extern int	hungup;		/* Physical layer has disconnected */
+extern int	ifunit;		/* Interface unit number */
+extern char	ifname[];	/* Interface name */
+extern char	hostname[];	/* Our hostname */
+extern u_char	outpacket_buf[]; /* Buffer for outgoing packets */
+extern int	phase;		/* Current state of link - see values below */
+extern int	baud_rate;	/* Current link speed in bits/sec */
+extern char	*progname;	/* Name of this program */
+extern int	redirect_stderr;/* Connector's stderr should go to file */
+extern char	peer_authname[];/* Authenticated name of peer */
+extern int	privileged;	/* We were run by real-uid root */
+extern int	need_holdoff;	/* Need holdoff period after link terminates */
+extern char	**script_env;	/* Environment variables for scripts */
+extern int	detached;	/* Have detached from controlling tty */
+extern GIDSET_TYPE groups[NGROUPS_MAX];	/* groups the user is in */
+extern int	ngroups;	/* How many groups valid in groups */
+extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */
+extern int	link_stats_valid; /* set if link_stats is valid */
+extern int	link_connect_time; /* time the link was up for */
+extern int	using_pty;	/* using pty as device (notty or pty opt.) */
+extern int	log_to_fd;	/* logging to this fd as well as syslog */
+extern bool	log_default;	/* log_to_fd is default (stdout) */
+extern char	*no_ppp_msg;	/* message to print if ppp not in kernel */
+extern volatile int status;	/* exit status for pppd */
+extern bool	devnam_fixed;	/* can no longer change devnam */
+extern int	unsuccess;	/* # unsuccessful connection attempts */
+extern int	do_callback;	/* set if we want to do callback next */
+extern int	doing_callback;	/* set if this is a callback */
+extern char	ppp_devnam[MAXPATHLEN];
+extern struct notifier *pidchange;   /* for notifications of pid changing */
+extern struct notifier *phasechange; /* for notifications of phase changes */
+extern struct notifier *exitnotify;  /* for notification that we're exiting */
+extern struct notifier *sigreceived; /* notification of received signal */
+extern int	listen_time;	/* time to listen first (ms) */
+
+/* Values for do_callback and doing_callback */
+#define CALLBACK_DIALIN		1	/* we are expecting the call back */
+#define CALLBACK_DIALOUT	2	/* we are dialling out to call back */
+
+/*
+ * Variables set by command-line options.
+ */
+
+extern int	debug;		/* Debug flag */
+extern int	kdebugflag;	/* Tell kernel to print debug messages */
+extern int	default_device;	/* Using /dev/tty or equivalent */
+extern char	devnam[MAXPATHLEN];	/* Device name */
+extern int	crtscts;	/* Use hardware flow control */
+extern bool	modem;		/* Use modem control lines */
+extern int	inspeed;	/* Input/Output speed requested */
+extern u_int32_t netmask;	/* IP netmask to set on interface */
+extern bool	lockflag;	/* Create lock file to lock the serial dev */
+extern bool	nodetach;	/* Don't detach from controlling tty */
+extern bool	updetach;	/* Detach from controlling tty when link up */
+extern char	*initializer;	/* Script to initialize physical link */
+extern char	*connect_script; /* Script to establish physical link */
+extern char	*disconnect_script; /* Script to disestablish physical link */
+extern char	*welcomer;	/* Script to welcome client after connection */
+extern char	*ptycommand;	/* Command to run on other side of pty */
+extern int	maxconnect;	/* Maximum connect time (seconds) */
+extern char	user[MAXNAMELEN];/* Our name for authenticating ourselves */
+extern char	passwd[MAXSECRETLEN];	/* Password for PAP or CHAP */
+extern bool	auth_required;	/* Peer is required to authenticate */
+extern bool	persist;	/* Reopen link after it goes down */
+extern bool	uselogin;	/* Use /etc/passwd for checking PAP */
+extern char	our_name[MAXNAMELEN];/* Our name for authentication purposes */
+extern char	remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+extern bool	explicit_remote;/* remote_name specified with remotename opt */
+extern bool	demand;		/* Do dial-on-demand */
+extern char	*ipparam;	/* Extra parameter for ip up/down scripts */
+extern bool	cryptpap;	/* Others' PAP passwords are encrypted */
+extern int	idle_time_limit;/* Shut down link if idle for this long */
+extern int	holdoff;	/* Dead time before restarting */
+extern bool	holdoff_specified; /* true if user gave a holdoff value */
+extern bool	notty;		/* Stdin/out is not a tty */
+extern char	*pty_socket;	/* Socket to connect to pty */
+extern char	*record_file;	/* File to record chars sent/received */
+extern bool	sync_serial;	/* Device is synchronous serial device */
+extern int	maxfail;	/* Max # of unsuccessful connection attempts */
+extern char	linkname[MAXPATHLEN]; /* logical name for link */
+extern bool	tune_kernel;	/* May alter kernel settings as necessary */
+extern int	connect_delay;	/* Time to delay after connect script */
+extern int	max_data_rate;	/* max bytes/sec through charshunt */
+extern int	req_unit;	/* interface unit number to use */
+extern bool	multilink;	/* enable multilink operation */
+extern bool	noendpoint;	/* don't send or accept endpt. discrim. */
+extern char	*bundle_name;	/* bundle name for multilink */
+extern bool	dump_options;	/* print out option values */
+extern bool	dryrun;		/* check everything, print options, exit */
+
+#ifdef PPP_FILTER
+extern struct	bpf_program pass_filter;   /* Filter for pkts to pass */
+extern struct	bpf_program active_filter; /* Filter for link-active pkts */
+#endif
+
+#ifdef MSLANMAN
+extern bool	ms_lanman;	/* Use LanMan password instead of NT */
+				/* Has meaning only with MS-CHAP challenges */
+#endif
+
+extern char *current_option;	/* the name of the option being parsed */
+extern int  privileged_option;	/* set iff the current option came from root */
+extern char *option_source;	/* string saying where the option came from */
+extern int  option_priority;	/* priority of current options */
+
+/*
+ * Values for phase.
+ */
+#define PHASE_DEAD		0
+#define PHASE_INITIALIZE	1
+#define PHASE_SERIALCONN	2
+#define PHASE_DORMANT		3
+#define PHASE_ESTABLISH		4
+#define PHASE_AUTHENTICATE	5
+#define PHASE_CALLBACK		6
+#define PHASE_NETWORK		7
+#define PHASE_RUNNING		8
+#define PHASE_TERMINATE		9
+#define PHASE_DISCONNECT	10
+#define PHASE_HOLDOFF		11
+
+/*
+ * The following struct gives the addresses of procedures to call
+ * for a particular protocol.
+ */
+struct protent {
+    u_short protocol;		/* PPP protocol number */
+    /* Initialization procedure */
+    void (*init) __P((int unit));
+    /* Process a received packet */
+    void (*input) __P((int unit, u_char *pkt, int len));
+    /* Process a received protocol-reject */
+    void (*protrej) __P((int unit));
+    /* Lower layer has come up */
+    void (*lowerup) __P((int unit));
+    /* Lower layer has gone down */
+    void (*lowerdown) __P((int unit));
+    /* Open the protocol */
+    void (*open) __P((int unit));
+    /* Close the protocol */
+    void (*close) __P((int unit, char *reason));
+    /* Print a packet in readable form */
+    int  (*printpkt) __P((u_char *pkt, int len,
+			  void (*printer) __P((void *, char *, ...)),
+			  void *arg));
+    /* Process a received data packet */
+    void (*datainput) __P((int unit, u_char *pkt, int len));
+    bool enabled_flag;		/* 0 iff protocol is disabled */
+    char *name;			/* Text name of protocol */
+    char *data_name;		/* Text name of corresponding data protocol */
+    option_t *options;		/* List of command-line options */
+    /* Check requested options, assign defaults */
+    void (*check_options) __P((void));
+    /* Configure interface for demand-dial */
+    int  (*demand_conf) __P((int unit));
+    /* Say whether to bring up link for this pkt */
+    int  (*active_pkt) __P((u_char *pkt, int len));
+};
+
+/* Table of pointers to supported protocols */
+extern struct protent *protocols[];
+
+/*
+ * This struct contains pointers to a set of procedures for
+ * doing operations on a "channel".  A channel provides a way
+ * to send and receive PPP packets - the canonical example is
+ * a serial port device in PPP line discipline (or equivalently
+ * with PPP STREAMS modules pushed onto it).
+ */
+struct channel {
+	/* set of options for this channel */
+	option_t *options;
+	/* find and process a per-channel options file */
+	void (*process_extra_options) __P((void));
+	/* check all the options that have been given */
+	void (*check_options) __P((void));
+	/* get the channel ready to do PPP, return a file descriptor */
+	int  (*connect) __P((void));
+	/* we're finished with the channel */
+	void (*disconnect) __P((void));
+	/* put the channel into PPP `mode' */
+	int  (*establish_ppp) __P((int));
+	/* take the channel out of PPP `mode', restore loopback if demand */
+	void (*disestablish_ppp) __P((int));
+	/* set the transmit-side PPP parameters of the channel */
+	void (*send_config) __P((int, u_int32_t, int, int));
+	/* set the receive-side PPP parameters of the channel */
+	void (*recv_config) __P((int, u_int32_t, int, int));
+	/* cleanup on error or normal exit */
+	void (*cleanup) __P((void));
+	/* close the device, called in children after fork */
+	void (*close) __P((void));
+};
+
+extern struct channel *the_channel;
+
+#define ppp_send_config(unit, mtu, accm, pc, acc)			 \
+do {									 \
+	if (the_channel->send_config)					 \
+		(*the_channel->send_config)((mtu), (accm), (pc), (acc)); \
+} while (0)
+
+#define ppp_recv_config(unit, mtu, accm, pc, acc)			 \
+do {									 \
+	if (the_channel->send_config)					 \
+		(*the_channel->recv_config)((mtu), (accm), (pc), (acc)); \
+} while (0)
+
+/*
+ * Prototypes.
+ */
+
+/* Procedures exported from main.c. */
+void set_ifunit __P((int));	/* set stuff that depends on ifunit */
+void detach __P((void));	/* Detach from controlling tty */
+void die __P((int));		/* Cleanup and exit */
+void quit __P((void));		/* like die(1) */
+void novm __P((char *));	/* Say we ran out of memory, and die */
+void timeout __P((void (*func)(void *), void *arg, int s, int us));
+				/* Call func(arg) after s.us seconds */
+void untimeout __P((void (*func)(void *), void *arg));
+				/* Cancel call to func(arg) */
+void record_child __P((int, char *, void (*) (void *), void *));
+int  device_script __P((char *cmd, int in, int out, int dont_wait));
+				/* Run `cmd' with given stdin and stdout */
+pid_t run_program __P((char *prog, char **args, int must_exist,
+		       void (*done)(void *), void *arg));
+				/* Run program prog with args in child */
+void reopen_log __P((void));	/* (re)open the connection to syslog */
+void update_link_stats __P((int)); /* Get stats at link termination */
+void script_setenv __P((char *, char *, int));	/* set script env var */
+void script_unsetenv __P((char *));		/* unset script env var */
+void new_phase __P((int));	/* signal start of new phase */
+void add_notifier __P((struct notifier **, notify_func, void *));
+void remove_notifier __P((struct notifier **, notify_func, void *));
+void notify __P((struct notifier *, int));
+
+/* Procedures exported from tty.c. */
+void tty_init __P((void));
+
+/* Procedures exported from utils.c. */
+void log_packet __P((u_char *, int, char *, int));
+				/* Format a packet and log it with syslog */
+void print_string __P((char *, int,  void (*) (void *, char *, ...),
+		void *));	/* Format a string for output */
+int slprintf __P((char *, int, char *, ...));		/* sprintf++ */
+int vslprintf __P((char *, int, char *, va_list));	/* vsprintf++ */
+size_t strlcpy __P((char *, const char *, size_t));	/* safe strcpy */
+size_t strlcat __P((char *, const char *, size_t));	/* safe strncpy */
+void dbglog __P((char *, ...));	/* log a debug message */
+void info __P((char *, ...));	/* log an informational message */
+void notice __P((char *, ...));	/* log a notice-level message */
+void warn __P((char *, ...));	/* log a warning message */
+void error __P((char *, ...));	/* log an error message */
+void fatal __P((char *, ...));	/* log an error message and die(1) */
+void init_pr_log __P((char *, int));	/* initialize for using pr_log */
+void pr_log __P((void *, char *, ...));	/* printer fn, output to syslog */
+void end_pr_log __P((void));	/* finish up after using pr_log */
+
+/* Procedures exported from auth.c */
+void link_required __P((int));	  /* we are starting to use the link */
+void link_terminated __P((int));  /* we are finished with the link */
+void link_down __P((int));	  /* the LCP layer has left the Opened state */
+void link_established __P((int)); /* the link is up; authenticate now */
+void start_networks __P((void));  /* start all the network control protos */
+void np_up __P((int, int));	  /* a network protocol has come up */
+void np_down __P((int, int));	  /* a network protocol has gone down */
+void np_finished __P((int, int)); /* a network protocol no longer needs link */
+void auth_peer_fail __P((int, int));
+				/* peer failed to authenticate itself */
+void auth_peer_success __P((int, int, char *, int));
+				/* peer successfully authenticated itself */
+void auth_withpeer_fail __P((int, int));
+				/* we failed to authenticate ourselves */
+void auth_withpeer_success __P((int, int));
+				/* we successfully authenticated ourselves */
+void auth_check_options __P((void));
+				/* check authentication options supplied */
+void auth_reset __P((int));	/* check what secrets we have */
+int  check_passwd __P((int, char *, int, char *, int, char **));
+				/* Check peer-supplied username/password */
+int  get_secret __P((int, char *, char *, char *, int *, int));
+				/* get "secret" for chap */
+int  auth_ip_addr __P((int, u_int32_t));
+				/* check if IP address is authorized */
+int  bad_ip_adrs __P((u_int32_t));
+				/* check if IP address is unreasonable */
+int  get_ip_addr_dynamic __P((int, u_int32_t *));
+				/* get dynamically-allocated IP address */
+
+/* Procedures exported from demand.c */
+void demand_conf __P((void));	/* config interface(s) for demand-dial */
+void demand_block __P((void));	/* set all NPs to queue up packets */
+void demand_unblock __P((void)); /* set all NPs to pass packets */
+void demand_discard __P((void)); /* set all NPs to discard packets */
+void demand_rexmit __P((int));	/* retransmit saved frames for an NP */
+int  loop_chars __P((unsigned char *, int)); /* process chars from loopback */
+int  loop_frame __P((unsigned char *, int)); /* should we bring link up? */
+
+/* Procedures exported from multilink.c */
+void mp_check_options __P((void)); /* Check multilink-related options */
+int  mp_join_bundle __P((void));  /* join our link to an appropriate bundle */
+char *epdisc_to_str __P((struct epdisc *)); /* string from endpoint discrim. */
+int  str_to_epdisc __P((struct epdisc *, char *)); /* endpt disc. from str */
+
+/* Procedures exported from sys-*.c */
+void sys_init __P((void));	/* Do system-dependent initialization */
+void sys_cleanup __P((void));	/* Restore system state before exiting */
+int  sys_check_options __P((void)); /* Check options specified */
+void sys_close __P((void));	/* Clean up in a child before execing */
+int  ppp_available __P((void));	/* Test whether ppp kernel support exists */
+int  get_pty __P((int *, int *, char *, int));	/* Get pty master/slave */
+int  open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */
+int  tty_establish_ppp __P((int));  /* Turn serial port into a ppp interface */
+void tty_disestablish_ppp __P((int)); /* Restore port to normal operation */
+void generic_disestablish_ppp __P((int dev_fd)); /* Restore device setting */
+int  generic_establish_ppp __P((int dev_fd)); /* Make a ppp interface */
+void make_new_bundle __P((int, int, int, int)); /* Create new bundle */
+int  bundle_attach __P((int));	/* Attach link to existing bundle */
+void cfg_bundle __P((int, int, int, int)); /* Configure existing bundle */
+void clean_check __P((void));	/* Check if line was 8-bit clean */
+void set_up_tty __P((int, int)); /* Set up port's speed, parameters, etc. */
+void restore_tty __P((int));	/* Restore port's original parameters */
+void setdtr __P((int, int));	/* Raise or lower port's DTR line */
+void output __P((int, u_char *, int)); /* Output a PPP packet */
+void wait_input __P((struct timeval *));
+				/* Wait for input, with timeout */
+void add_fd __P((int));		/* Add fd to set to wait for */
+void remove_fd __P((int));	/* Remove fd from set to wait for */
+int  read_packet __P((u_char *)); /* Read PPP packet */
+int  get_loop_output __P((void)); /* Read pkts from loopback */
+void tty_send_config __P((int, u_int32_t, int, int));
+				/* Configure i/f transmit parameters */
+void tty_set_xaccm __P((ext_accm));
+				/* Set extended transmit ACCM */
+void tty_recv_config __P((int, u_int32_t, int, int));
+				/* Configure i/f receive parameters */
+int  ccp_test __P((int, u_char *, int, int));
+				/* Test support for compression scheme */
+void ccp_flags_set __P((int, int, int));
+				/* Set kernel CCP state */
+int  ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */
+int  get_idle_time __P((int, struct ppp_idle *));
+				/* Find out how long link has been idle */
+int  get_ppp_stats __P((int, struct pppd_stats *));
+				/* Return link statistics */
+void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */
+int  sifvjcomp __P((int, int, int, int));
+				/* Configure VJ TCP header compression */
+int  sifup __P((int));		/* Configure i/f up for one protocol */
+int  sifnpmode __P((int u, int proto, enum NPmode mode));
+				/* Set mode for handling packets for proto */
+int  sifdown __P((int));	/* Configure i/f down for one protocol */
+int  sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
+				/* Configure IPv4 addresses for i/f */
+int  cifaddr __P((int, u_int32_t, u_int32_t));
+				/* Reset i/f IP addresses */
+#ifdef INET6
+int  sif6addr __P((int, eui64_t, eui64_t));
+				/* Configure IPv6 addresses for i/f */
+int  cif6addr __P((int, eui64_t, eui64_t));
+				/* Remove an IPv6 address from i/f */
+#endif
+int  sifdefaultroute __P((int, u_int32_t, u_int32_t));
+				/* Create default route through i/f */
+int  cifdefaultroute __P((int, u_int32_t, u_int32_t));
+				/* Delete default route through i/f */
+int  sifproxyarp __P((int, u_int32_t));
+				/* Add proxy ARP entry for peer */
+int  cifproxyarp __P((int, u_int32_t));
+				/* Delete proxy ARP entry for peer */
+u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */
+int  lock __P((char *));	/* Create lock file for device */
+int  relock __P((int));		/* Rewrite lock file with new pid */
+void unlock __P((void));	/* Delete previously-created lock file */
+void logwtmp __P((const char *, const char *, const char *));
+				/* Write entry to wtmp file */
+int  get_host_seed __P((void));	/* Get host-dependent random number seed */
+int  have_route_to __P((u_int32_t)); /* Check if route to addr exists */
+#ifdef PPP_FILTER
+int  set_filters __P((struct bpf_program *pass, struct bpf_program *active));
+				/* Set filter programs in kernel */
+#endif
+#ifdef IPX_CHANGE
+int  sipxfaddr __P((int, unsigned long, unsigned char *));
+int  cipxfaddr __P((int));
+#endif
+int  get_if_hwaddr __P((u_char *addr, char *name));
+char *get_first_ethernet __P((void));
+
+/* Procedures exported from options.c */
+int  parse_args __P((int argc, char **argv));
+				/* Parse options from arguments given */
+int  options_from_file __P((char *filename, int must_exist, int check_prot,
+			    int privileged));
+				/* Parse options from an options file */
+int  options_from_user __P((void)); /* Parse options from user's .ppprc */
+int  options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */
+int  options_from_list __P((struct wordlist *, int privileged));
+				/* Parse options from a wordlist */
+int  getword __P((FILE *f, char *word, int *newlinep, char *filename));
+				/* Read a word from a file */
+void option_error __P((char *fmt, ...));
+				/* Print an error message about an option */
+int int_option __P((char *, int *));
+				/* Simplified number_option for decimal ints */
+void add_options __P((option_t *)); /* Add extra options */
+void check_options __P((void));	/* check values after all options parsed */
+int remove_option __P((char *)); /* Disable the specified option */
+int  override_value __P((const char *, int, const char *));
+				/* override value if permitted by priority */
+void print_options __P((void (*) __P((void *, char *, ...)), void *));
+				/* print out values of all options */
+
+int parse_dotted_ip __P((char *, u_int32_t *));
+
+/*
+ * Hooks to enable plugins to change various things.
+ */
+extern int (*new_phase_hook) __P((int));
+extern int (*idle_time_hook) __P((struct ppp_idle *));
+extern int (*holdoff_hook) __P((void));
+extern int (*pap_check_hook) __P((void));
+extern int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp,
+				 struct wordlist **paddrs,
+				 struct wordlist **popts));
+extern void (*pap_logout_hook) __P((void));
+extern int (*pap_passwd_hook) __P((char *user, char *passwd));
+extern void (*ip_up_hook) __P((void));
+extern void (*ip_down_hook) __P((void));
+extern void (*ip_choose_hook) __P((u_int32_t *));
+
+/*
+ * Inline versions of get/put char/short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETCHAR(c, cp) { \
+	(c) = *(cp)++; \
+}
+#define PUTCHAR(c, cp) { \
+	*(cp)++ = (u_char) (c); \
+}
+
+
+#define GETSHORT(s, cp) { \
+	(s) = *(cp)++ << 8; \
+	(s) |= *(cp)++; \
+}
+#define PUTSHORT(s, cp) { \
+	*(cp)++ = (u_char) ((s) >> 8); \
+	*(cp)++ = (u_char) (s); \
+}
+
+#define GETLONG(l, cp) { \
+	(l) = *(cp)++ << 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; \
+}
+#define PUTLONG(l, cp) { \
+	*(cp)++ = (u_char) ((l) >> 24); \
+	*(cp)++ = (u_char) ((l) >> 16); \
+	*(cp)++ = (u_char) ((l) >> 8); \
+	*(cp)++ = (u_char) (l); \
+}
+
+#define INCPTR(n, cp)	((cp) += (n))
+#define DECPTR(n, cp)	((cp) -= (n))
+
+/*
+ * System dependent definitions for user-level 4.3BSD UNIX implementation.
+ */
+
+#define TIMEOUT(r, f, t)	timeout((r), (f), (t), 0)
+#define UNTIMEOUT(r, f)		untimeout((r), (f))
+
+#define BCOPY(s, d, l)		memcpy(d, s, l)
+#define BZERO(s, n)		memset(s, 0, n)
+
+#define PRINTMSG(m, l)		{ info("Remote message: %0.*v", l, m); }
+
+/*
+ * MAKEHEADER - Add Header fields to a packet.
+ */
+#define MAKEHEADER(p, t) { \
+    PUTCHAR(PPP_ALLSTATIONS, p); \
+    PUTCHAR(PPP_UI, p); \
+    PUTSHORT(t, p); }
+
+/*
+ * Exit status values.
+ */
+#define EXIT_OK			0
+#define EXIT_FATAL_ERROR	1
+#define EXIT_OPTION_ERROR	2
+#define EXIT_NOT_ROOT		3
+#define EXIT_NO_KERNEL_SUPPORT	4
+#define EXIT_USER_REQUEST	5
+#define EXIT_LOCK_FAILED	6
+#define EXIT_OPEN_FAILED	7
+#define EXIT_CONNECT_FAILED	8
+#define EXIT_PTYCMD_FAILED	9
+#define EXIT_NEGOTIATION_FAILED	10
+#define EXIT_PEER_AUTH_FAILED	11
+#define EXIT_IDLE_TIMEOUT	12
+#define EXIT_CONNECT_TIME	13
+#define EXIT_CALLBACK		14
+#define EXIT_PEER_DEAD		15
+#define EXIT_HANGUP		16
+#define EXIT_LOOPBACK		17
+#define EXIT_INIT_FAILED	18
+#define EXIT_AUTH_TOPEER_FAILED	19
+
+/*
+ * Debug macros.  Slightly useful for finding bugs in pppd, not particularly
+ * useful for finding out why your connection isn't being established.
+ */
+#ifdef DEBUGALL
+#define DEBUGMAIN	1
+#define DEBUGFSM	1
+#define DEBUGLCP	1
+#define DEBUGIPCP	1
+#define DEBUGIPV6CP	1
+#define DEBUGUPAP	1
+#define DEBUGCHAP	1
+#endif
+
+#ifndef LOG_PPP			    /* we use LOG_LOCAL2 for syslog by default */
+#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
+  || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
+  || defined(DEBUGCHAP) || defined(DEBUG) || defined(DEBUGIPV6CP)
+#define LOG_PPP LOG_LOCAL2
+#else
+#define LOG_PPP LOG_DAEMON
+#endif
+#endif /* LOG_PPP */
+
+#ifdef DEBUGMAIN
+#define MAINDEBUG(x)	if (debug) dbglog x
+#else
+#define MAINDEBUG(x)
+#endif
+
+#ifdef DEBUGSYS
+#define SYSDEBUG(x)	if (debug) dbglog x
+#else
+#define SYSDEBUG(x)
+#endif
+
+#ifdef DEBUGFSM
+#define FSMDEBUG(x)	if (debug) dbglog x
+#else
+#define FSMDEBUG(x)
+#endif
+
+#ifdef DEBUGLCP
+#define LCPDEBUG(x)	if (debug) dbglog x
+#else
+#define LCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPCP
+#define IPCPDEBUG(x)	if (debug) dbglog x
+#else
+#define IPCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPV6CP
+#define IPV6CPDEBUG(x)  if (debug) dbglog x
+#else
+#define IPV6CPDEBUG(x)
+#endif
+
+#ifdef DEBUGUPAP
+#define UPAPDEBUG(x)	if (debug) dbglog x
+#else
+#define UPAPDEBUG(x)
+#endif
+
+#ifdef DEBUGCHAP
+#define CHAPDEBUG(x)	if (debug) dbglog x
+#else
+#define CHAPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPXCP
+#define IPXCPDEBUG(x)	if (debug) dbglog x
+#else
+#define IPXCPDEBUG(x)
+#endif
+
+#ifndef SIGTYPE
+#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
+#define SIGTYPE void
+#else
+#define SIGTYPE int
+#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
+#endif /* SIGTYPE */
+
+#ifndef MIN
+#define MIN(a, b)	((a) < (b)? (a): (b))
+#endif
+#ifndef MAX
+#define MAX(a, b)	((a) > (b)? (a): (b))
+#endif
+
+#endif /* __PPP_H__ */
diff --git a/ap/app/ppp-2.4.1/pppd/sha1dgst.c b/ap/app/ppp-2.4.1/pppd/sha1dgst.c
new file mode 100644
index 0000000..c09edb4
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/sha1dgst.c
@@ -0,0 +1,73 @@
+/* crypto/sha/sha1dgst.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#if !defined(NO_SHA1) && !defined(NO_SHA)
+
+#undef  SHA_0
+#define SHA_1
+
+#include <openssl/opensslv.h>
+
+const char *SHA1_version="SHA1" OPENSSL_VERSION_PTEXT;
+
+/* The implementation is in ../md32_common.h */
+
+#include "sha_locl.h"
+
+#endif
+
diff --git a/ap/app/ppp-2.4.1/pppd/sha_locl.h b/ap/app/ppp-2.4.1/pppd/sha_locl.h
new file mode 100644
index 0000000..a4a67ec
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/sha_locl.h
@@ -0,0 +1,473 @@
+/* crypto/sha/sha_locl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <openssl/opensslconf.h>
+#include <openssl/sha.h>
+
+#ifndef SHA_LONG_LOG2
+#define SHA_LONG_LOG2	2	/* default to 32 bits */
+#endif
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG               SHA_LONG
+#define HASH_LONG_LOG2          SHA_LONG_LOG2
+#define HASH_CTX                SHA_CTX
+#define HASH_CBLOCK             SHA_CBLOCK
+#define HASH_LBLOCK             SHA_LBLOCK
+#define HASH_MAKE_STRING(c,s)   do {	\
+	unsigned long ll;		\
+	ll=(c)->h0; HOST_l2c(ll,(s));	\
+	ll=(c)->h1; HOST_l2c(ll,(s));	\
+	ll=(c)->h2; HOST_l2c(ll,(s));	\
+	ll=(c)->h3; HOST_l2c(ll,(s));	\
+	ll=(c)->h4; HOST_l2c(ll,(s));	\
+	} while (0)
+
+#if defined(SHA_0)
+
+# define HASH_UPDATE             	SHA_Update
+# define HASH_TRANSFORM          	SHA_Transform
+# define HASH_FINAL              	SHA_Final
+# define HASH_INIT			SHA_Init
+# define HASH_BLOCK_HOST_ORDER   	sha_block_host_order
+# define HASH_BLOCK_DATA_ORDER   	sha_block_data_order
+# define Xupdate(a,ix,ia,ib,ic,id)	(ix=(a)=(ia^ib^ic^id))
+
+  void sha_block_host_order (SHA_CTX *c, const void *p,int num);
+  void sha_block_data_order (SHA_CTX *c, const void *p,int num);
+
+#elif defined(SHA_1)
+
+# define HASH_UPDATE             	SHA1_Update
+# define HASH_TRANSFORM          	SHA1_Transform
+# define HASH_FINAL              	SHA1_Final
+# define HASH_INIT			SHA1_Init
+# define HASH_BLOCK_HOST_ORDER   	sha1_block_host_order
+# define HASH_BLOCK_DATA_ORDER   	sha1_block_data_order
+# if defined(__MWERKS__) && defined(__MC68K__)
+   /* Metrowerks for Motorola fails otherwise:-( <appro@fy.chalmers.se> */
+#  define Xupdate(a,ix,ia,ib,ic,id)	do { (a)=(ia^ib^ic^id);		\
+					     ix=(a)=ROTATE((a),1);	\
+					} while (0)
+# else
+#  define Xupdate(a,ix,ia,ib,ic,id)	( (a)=(ia^ib^ic^id),	\
+					  ix=(a)=ROTATE((a),1)	\
+					)
+# endif
+
+# ifdef SHA1_ASM
+#  if defined(__i386) || defined(_M_IX86) || defined(__INTEL__)
+#   define sha1_block_host_order		sha1_block_asm_host_order
+#   define DONT_IMPLEMENT_BLOCK_HOST_ORDER
+#   define sha1_block_data_order		sha1_block_asm_data_order
+#   define DONT_IMPLEMENT_BLOCK_DATA_ORDER
+#   define HASH_BLOCK_DATA_ORDER_ALIGNED	sha1_block_asm_data_order
+#  endif
+# endif
+  void sha1_block_host_order (SHA_CTX *c, const void *p,int num);
+  void sha1_block_data_order (SHA_CTX *c, const void *p,int num);
+
+#else
+# error "Either SHA_0 or SHA_1 must be defined."
+#endif
+
+#include "md32_common.h"
+
+#define INIT_DATA_h0 0x67452301UL
+#define INIT_DATA_h1 0xefcdab89UL
+#define INIT_DATA_h2 0x98badcfeUL
+#define INIT_DATA_h3 0x10325476UL
+#define INIT_DATA_h4 0xc3d2e1f0UL
+
+void HASH_INIT (SHA_CTX *c)
+	{
+	c->h0=INIT_DATA_h0;
+	c->h1=INIT_DATA_h1;
+	c->h2=INIT_DATA_h2;
+	c->h3=INIT_DATA_h3;
+	c->h4=INIT_DATA_h4;
+	c->Nl=0;
+	c->Nh=0;
+	c->num=0;
+	}
+
+#define K_00_19	0x5a827999UL
+#define K_20_39 0x6ed9eba1UL
+#define K_40_59 0x8f1bbcdcUL
+#define K_60_79 0xca62c1d6UL
+
+/* As  pointed out by Wei Dai <weidai@eskimo.com>, F() below can be
+ * simplified to the code in F_00_19.  Wei attributes these optimisations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ * #define F(x,y,z) (((x) & (y))  |  ((~(x)) & (z)))
+ * I've just become aware of another tweak to be made, again from Wei Dai,
+ * in F_40_59, (x&a)|(y&a) -> (x|y)&a
+ */
+#define	F_00_19(b,c,d)	((((c) ^ (d)) & (b)) ^ (d)) 
+#define	F_20_39(b,c,d)	((b) ^ (c) ^ (d))
+#define F_40_59(b,c,d)	(((b) & (c)) | (((b)|(c)) & (d))) 
+#define	F_60_79(b,c,d)	F_20_39(b,c,d)
+
+#define BODY_00_15(i,a,b,c,d,e,f,xi) \
+	(f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
+	Xupdate(f,xi,xa,xb,xc,xd); \
+	(f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
+	Xupdate(f,xi,xa,xb,xc,xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#ifdef X
+#undef X
+#endif
+#ifndef MD32_XARRAY
+  /*
+   * Originally X was an array. As it's automatic it's natural
+   * to expect RISC compiler to accomodate at least part of it in
+   * the register bank, isn't it? Unfortunately not all compilers
+   * "find" this expectation reasonable:-( On order to make such
+   * compilers generate better code I replace X[] with a bunch of
+   * X0, X1, etc. See the function body below...
+   *					<appro@fy.chalmers.se>
+   */
+# define X(i)	XX##i
+#else
+  /*
+   * However! Some compilers (most notably HP C) get overwhelmed by
+   * that many local variables so that we have to have the way to
+   * fall down to the original behavior.
+   */
+# define X(i)	XX[i]
+#endif
+
+#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER
+void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num)
+	{
+	const SHA_LONG *W=d;
+	register unsigned long A,B,C,D,E,T;
+#ifndef MD32_XARRAY
+	unsigned long	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+			XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
+#else
+	SHA_LONG	XX[16];
+#endif
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	for (;;)
+		{
+	BODY_00_15( 0,A,B,C,D,E,T,W[ 0]);
+	BODY_00_15( 1,T,A,B,C,D,E,W[ 1]);
+	BODY_00_15( 2,E,T,A,B,C,D,W[ 2]);
+	BODY_00_15( 3,D,E,T,A,B,C,W[ 3]);
+	BODY_00_15( 4,C,D,E,T,A,B,W[ 4]);
+	BODY_00_15( 5,B,C,D,E,T,A,W[ 5]);
+	BODY_00_15( 6,A,B,C,D,E,T,W[ 6]);
+	BODY_00_15( 7,T,A,B,C,D,E,W[ 7]);
+	BODY_00_15( 8,E,T,A,B,C,D,W[ 8]);
+	BODY_00_15( 9,D,E,T,A,B,C,W[ 9]);
+	BODY_00_15(10,C,D,E,T,A,B,W[10]);
+	BODY_00_15(11,B,C,D,E,T,A,W[11]);
+	BODY_00_15(12,A,B,C,D,E,T,W[12]);
+	BODY_00_15(13,T,A,B,C,D,E,W[13]);
+	BODY_00_15(14,E,T,A,B,C,D,W[14]);
+	BODY_00_15(15,D,E,T,A,B,C,W[15]);
+
+	BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]);
+	BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]);
+	BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]);
+	BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0));
+
+	BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1));
+	BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2));
+	BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3));
+	BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4));
+	BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5));
+	BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6));
+	BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7));
+	BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8));
+	BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9));
+	BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10));
+	BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11));
+	BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12));
+
+	BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
+	BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
+	BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
+	BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
+	BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
+	BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
+	BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
+	BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
+
+	BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
+	BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
+	BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
+	BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
+	BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
+	BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
+	BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
+	BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
+	BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
+	BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
+	BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
+	BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
+	BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
+	BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
+
+	BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
+	BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
+	BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
+	BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
+	BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
+	BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
+	BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
+	BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
+	BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
+	BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
+	BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
+	BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
+	BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
+	BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
+	BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
+	BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
+	
+	c->h0=(c->h0+E)&0xffffffffL; 
+	c->h1=(c->h1+T)&0xffffffffL;
+	c->h2=(c->h2+A)&0xffffffffL;
+	c->h3=(c->h3+B)&0xffffffffL;
+	c->h4=(c->h4+C)&0xffffffffL;
+
+	if (--num <= 0) break;
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	W+=SHA_LBLOCK;
+		}
+	}
+#endif
+
+#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER
+void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num)
+	{
+	const unsigned char *data=p;
+	register unsigned long A,B,C,D,E,T,l;
+#ifndef MD32_XARRAY
+	unsigned long	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+			XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
+#else
+	SHA_LONG	XX[16];
+#endif
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	for (;;)
+		{
+
+	HOST_c2l(data,l); X( 0)=l;		HOST_c2l(data,l); X( 1)=l;
+	BODY_00_15( 0,A,B,C,D,E,T,X( 0));	HOST_c2l(data,l); X( 2)=l;
+	BODY_00_15( 1,T,A,B,C,D,E,X( 1));	HOST_c2l(data,l); X( 3)=l;
+	BODY_00_15( 2,E,T,A,B,C,D,X( 2));	HOST_c2l(data,l); X( 4)=l;
+	BODY_00_15( 3,D,E,T,A,B,C,X( 3));	HOST_c2l(data,l); X( 5)=l;
+	BODY_00_15( 4,C,D,E,T,A,B,X( 4));	HOST_c2l(data,l); X( 6)=l;
+	BODY_00_15( 5,B,C,D,E,T,A,X( 5));	HOST_c2l(data,l); X( 7)=l;
+	BODY_00_15( 6,A,B,C,D,E,T,X( 6));	HOST_c2l(data,l); X( 8)=l;
+	BODY_00_15( 7,T,A,B,C,D,E,X( 7));	HOST_c2l(data,l); X( 9)=l;
+	BODY_00_15( 8,E,T,A,B,C,D,X( 8));	HOST_c2l(data,l); X(10)=l;
+	BODY_00_15( 9,D,E,T,A,B,C,X( 9));	HOST_c2l(data,l); X(11)=l;
+	BODY_00_15(10,C,D,E,T,A,B,X(10));	HOST_c2l(data,l); X(12)=l;
+	BODY_00_15(11,B,C,D,E,T,A,X(11));	HOST_c2l(data,l); X(13)=l;
+	BODY_00_15(12,A,B,C,D,E,T,X(12));	HOST_c2l(data,l); X(14)=l;
+	BODY_00_15(13,T,A,B,C,D,E,X(13));	HOST_c2l(data,l); X(15)=l;
+	BODY_00_15(14,E,T,A,B,C,D,X(14));
+	BODY_00_15(15,D,E,T,A,B,C,X(15));
+
+	BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13));
+	BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14));
+	BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15));
+	BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0));
+
+	BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1));
+	BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2));
+	BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3));
+	BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4));
+	BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5));
+	BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6));
+	BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7));
+	BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8));
+	BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9));
+	BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10));
+	BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11));
+	BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12));
+
+	BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
+	BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
+	BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
+	BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
+	BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
+	BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
+	BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
+	BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
+
+	BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
+	BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
+	BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
+	BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
+	BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
+	BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
+	BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
+	BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
+	BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
+	BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
+	BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
+	BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
+	BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
+	BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
+
+	BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
+	BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
+	BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
+	BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
+	BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
+	BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
+	BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
+	BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
+	BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
+	BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
+	BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
+	BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
+	BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
+	BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
+	BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
+	BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
+	
+	c->h0=(c->h0+E)&0xffffffffL; 
+	c->h1=(c->h1+T)&0xffffffffL;
+	c->h2=(c->h2+A)&0xffffffffL;
+	c->h3=(c->h3+B)&0xffffffffL;
+	c->h4=(c->h4+C)&0xffffffffL;
+
+	if (--num <= 0) break;
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+		}
+	}
+#endif
diff --git a/ap/app/ppp-2.4.1/pppd/upap.c b/ap/app/ppp-2.4.1/pppd/upap.c
new file mode 100644
index 0000000..1a31d01
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/upap.c
@@ -0,0 +1,644 @@
+/*
+ * upap.c - User/Password Authentication Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: upap.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <pppd.h>
+#include "upap.h"
+
+static const char rcsid[] = RCSID;
+
+static bool hide_password = 1;
+
+/*
+ * Command-line options.
+ */
+static option_t pap_option_list[] = {
+    { "hide-password", o_bool, &hide_password,
+      "Don't output passwords to log", OPT_PRIO | 1 },
+    { "show-password", o_bool, &hide_password,
+      "Show password string in debug log messages", OPT_PRIOSUB | 0 },
+
+    { "pap-restart", o_int, &upap[0].us_timeouttime,
+      "Set retransmit timeout for PAP", OPT_PRIO },
+    { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
+      "Set max number of transmissions for auth-reqs", OPT_PRIO },
+    { "pap-timeout", o_int, &upap[0].us_reqtimeout,
+      "Set time limit for peer PAP authentication", OPT_PRIO },
+
+    { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+static void upap_init __P((int));
+static void upap_lowerup __P((int));
+static void upap_lowerdown __P((int));
+static void upap_input __P((int, u_char *, int));
+static void upap_protrej __P((int));
+static int  upap_printpkt __P((u_char *, int,
+			       void (*) __P((void *, char *, ...)), void *));
+
+struct protent pap_protent = {
+    PPP_PAP,
+    upap_init,
+    upap_input,
+    upap_protrej,
+    upap_lowerup,
+    upap_lowerdown,
+    NULL,
+    NULL,
+    upap_printpkt,
+    NULL,
+    1,
+    "PAP",
+    NULL,
+    pap_option_list,
+    NULL,
+    NULL,
+    NULL
+};
+
+upap_state upap[NUM_PPP];		/* UPAP state; one for each unit */
+
+static void upap_timeout __P((void *));
+static void upap_reqtimeout __P((void *));
+static void upap_rauthreq __P((upap_state *, u_char *, int, int));
+static void upap_rauthack __P((upap_state *, u_char *, int, int));
+static void upap_rauthnak __P((upap_state *, u_char *, int, int));
+static void upap_sauthreq __P((upap_state *));
+static void upap_sresp __P((upap_state *, int, int, char *, int));
+
+
+/*
+ * upap_init - Initialize a UPAP unit.
+ */
+static void
+upap_init(unit)
+    int unit;
+{
+    upap_state *u = &upap[unit];
+
+    u->us_unit = unit;
+    u->us_user = NULL;
+    u->us_userlen = 0;
+    u->us_passwd = NULL;
+    u->us_passwdlen = 0;
+    u->us_clientstate = UPAPCS_INITIAL;
+    u->us_serverstate = UPAPSS_INITIAL;
+    u->us_id = 0;
+    u->us_timeouttime = UPAP_DEFTIMEOUT;
+    u->us_maxtransmits = 10;
+    u->us_reqtimeout = UPAP_DEFREQTIME;
+}
+
+
+/*
+ * upap_authwithpeer - Authenticate us with our peer (start client).
+ *
+ * Set new state and send authenticate's.
+ */
+void
+upap_authwithpeer(unit, user, password)
+    int unit;
+    char *user, *password;
+{
+    upap_state *u = &upap[unit];
+
+    /* Save the username and password we're given */
+    u->us_user = user;
+    u->us_userlen = strlen(user);
+    u->us_passwd = password;
+    u->us_passwdlen = strlen(password);
+    u->us_transmits = 0;
+
+    /* Lower layer up yet? */
+    if (u->us_clientstate == UPAPCS_INITIAL ||
+	u->us_clientstate == UPAPCS_PENDING) {
+	u->us_clientstate = UPAPCS_PENDING;
+	return;
+    }
+
+    upap_sauthreq(u);			/* Start protocol */
+}
+
+
+/*
+ * upap_authpeer - Authenticate our peer (start server).
+ *
+ * Set new state.
+ */
+void
+upap_authpeer(unit)
+    int unit;
+{
+    upap_state *u = &upap[unit];
+
+    /* Lower layer up yet? */
+    if (u->us_serverstate == UPAPSS_INITIAL ||
+	u->us_serverstate == UPAPSS_PENDING) {
+	u->us_serverstate = UPAPSS_PENDING;
+	return;
+    }
+
+    u->us_serverstate = UPAPSS_LISTEN;
+    if (u->us_reqtimeout > 0)
+	TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
+}
+
+
+/*
+ * upap_timeout - Retransmission timer for sending auth-reqs expired.
+ */
+static void
+upap_timeout(arg)
+    void *arg;
+{
+    upap_state *u = (upap_state *) arg;
+
+    if (u->us_clientstate != UPAPCS_AUTHREQ)
+	return;
+
+    if (u->us_transmits >= u->us_maxtransmits) {
+	/* give up in disgust */
+	error("No response to PAP authenticate-requests");
+	u->us_clientstate = UPAPCS_BADAUTH;
+	auth_withpeer_fail(u->us_unit, PPP_PAP);
+	return;
+    }
+
+    upap_sauthreq(u);		/* Send Authenticate-Request */
+}
+
+
+/*
+ * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
+ */
+static void
+upap_reqtimeout(arg)
+    void *arg;
+{
+    upap_state *u = (upap_state *) arg;
+
+    if (u->us_serverstate != UPAPSS_LISTEN)
+	return;			/* huh?? */
+
+    auth_peer_fail(u->us_unit, PPP_PAP);
+    u->us_serverstate = UPAPSS_BADAUTH;
+}
+
+
+/*
+ * upap_lowerup - The lower layer is up.
+ *
+ * Start authenticating if pending.
+ */
+static void
+upap_lowerup(unit)
+    int unit;
+{
+    upap_state *u = &upap[unit];
+
+    if (u->us_clientstate == UPAPCS_INITIAL)
+	u->us_clientstate = UPAPCS_CLOSED;
+    else if (u->us_clientstate == UPAPCS_PENDING) {
+	upap_sauthreq(u);	/* send an auth-request */
+    }
+
+    if (u->us_serverstate == UPAPSS_INITIAL)
+	u->us_serverstate = UPAPSS_CLOSED;
+    else if (u->us_serverstate == UPAPSS_PENDING) {
+	u->us_serverstate = UPAPSS_LISTEN;
+	if (u->us_reqtimeout > 0)
+	    TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
+    }
+}
+
+
+/*
+ * upap_lowerdown - The lower layer is down.
+ *
+ * Cancel all timeouts.
+ */
+static void
+upap_lowerdown(unit)
+    int unit;
+{
+    upap_state *u = &upap[unit];
+
+    if (u->us_clientstate == UPAPCS_AUTHREQ)	/* Timeout pending? */
+	UNTIMEOUT(upap_timeout, u);		/* Cancel timeout */
+    if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
+	UNTIMEOUT(upap_reqtimeout, u);
+
+    u->us_clientstate = UPAPCS_INITIAL;
+    u->us_serverstate = UPAPSS_INITIAL;
+}
+
+
+/*
+ * upap_protrej - Peer doesn't speak this protocol.
+ *
+ * This shouldn't happen.  In any case, pretend lower layer went down.
+ */
+static void
+upap_protrej(unit)
+    int unit;
+{
+    upap_state *u = &upap[unit];
+
+    if (u->us_clientstate == UPAPCS_AUTHREQ) {
+	error("PAP authentication failed due to protocol-reject");
+	auth_withpeer_fail(unit, PPP_PAP);
+    }
+    if (u->us_serverstate == UPAPSS_LISTEN) {
+	error("PAP authentication of peer failed (protocol-reject)");
+	auth_peer_fail(unit, PPP_PAP);
+    }
+    upap_lowerdown(unit);
+}
+
+
+/*
+ * upap_input - Input UPAP packet.
+ */
+static void
+upap_input(unit, inpacket, l)
+    int unit;
+    u_char *inpacket;
+    int l;
+{
+    upap_state *u = &upap[unit];
+    u_char *inp;
+    u_char code, id;
+    int len;
+
+    /*
+     * Parse header (code, id and length).
+     * If packet too short, drop it.
+     */
+    inp = inpacket;
+    if (l < UPAP_HEADERLEN) {
+	UPAPDEBUG(("pap_input: rcvd short header."));
+	return;
+    }
+    GETCHAR(code, inp);
+    GETCHAR(id, inp);
+    GETSHORT(len, inp);
+    if (len < UPAP_HEADERLEN) {
+	UPAPDEBUG(("pap_input: rcvd illegal length."));
+	return;
+    }
+    if (len > l) {
+	UPAPDEBUG(("pap_input: rcvd short packet."));
+	return;
+    }
+    len -= UPAP_HEADERLEN;
+
+    /*
+     * Action depends on code.
+     */
+    switch (code) {
+    case UPAP_AUTHREQ:
+	upap_rauthreq(u, inp, id, len);
+	break;
+
+    case UPAP_AUTHACK:
+	upap_rauthack(u, inp, id, len);
+	break;
+
+    case UPAP_AUTHNAK:
+	upap_rauthnak(u, inp, id, len);
+	break;
+
+    default:				
+	break;
+    }
+}
+
+
+/*
+ * upap_rauth - Receive Authenticate.
+ */
+static void
+upap_rauthreq(u, inp, id, len)
+    upap_state *u;
+    u_char *inp;
+    int id;
+    int len;
+{
+    u_char ruserlen, rpasswdlen;
+    char *ruser, *rpasswd;
+    int retcode;
+    char *msg = NULL;
+    int msglen;
+
+    if (u->us_serverstate < UPAPSS_LISTEN)
+	return;
+
+    /*
+     * If we receive a duplicate authenticate-request, we are
+     * supposed to return the same status as for the first request.
+     */
+    if (u->us_serverstate == UPAPSS_OPEN) {
+	upap_sresp(u, UPAP_AUTHACK, id, "", 0);	/* return auth-ack */
+	return;
+    }
+    if (u->us_serverstate == UPAPSS_BADAUTH) {
+	upap_sresp(u, UPAP_AUTHNAK, id, "", 0);	/* return auth-nak */
+	return;
+    }
+
+    /*
+     * Parse user/passwd.
+     */
+    if (len < 1) {
+	UPAPDEBUG(("pap_rauth: rcvd short packet."));
+	return;
+    }
+    GETCHAR(ruserlen, inp);
+    len -= sizeof (u_char) + ruserlen + sizeof (u_char);
+    if (len < 0) {
+	UPAPDEBUG(("pap_rauth: rcvd short packet."));
+	return;
+    }
+    ruser = (char *) inp;
+    INCPTR(ruserlen, inp);
+    GETCHAR(rpasswdlen, inp);
+    if (len < rpasswdlen) {
+	UPAPDEBUG(("pap_rauth: rcvd short packet."));
+	return;
+    }
+    rpasswd = (char *) inp;
+
+    /*
+     * Check the username and password given.
+     */
+    retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
+			   rpasswdlen, &msg);
+    BZERO(rpasswd, rpasswdlen);
+    msglen = strlen(msg);
+    if (msglen > 255)
+	msglen = 255;
+
+    upap_sresp(u, retcode, id, msg, msglen);
+
+    if (retcode == UPAP_AUTHACK) {
+	u->us_serverstate = UPAPSS_OPEN;
+	auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
+    } else {
+	u->us_serverstate = UPAPSS_BADAUTH;
+	auth_peer_fail(u->us_unit, PPP_PAP);
+    }
+
+    if (u->us_reqtimeout > 0)
+	UNTIMEOUT(upap_reqtimeout, u);
+}
+
+
+/*
+ * upap_rauthack - Receive Authenticate-Ack.
+ */
+static void
+upap_rauthack(u, inp, id, len)
+    upap_state *u;
+    u_char *inp;
+    int id;
+    int len;
+{
+    u_char msglen;
+    char *msg;
+
+    if (u->us_clientstate != UPAPCS_AUTHREQ) 
+	return;
+
+    /*
+     * Parse message.
+     */
+    if (len < 1) {
+	UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
+    } else {
+	GETCHAR(msglen, inp);
+	if (msglen > 0) {
+	    len -= sizeof (u_char);
+	    if (len < msglen) {
+		UPAPDEBUG(("pap_rauthack: rcvd short packet."));
+		return;
+	    }
+	    msg = (char *) inp;
+	    PRINTMSG(msg, msglen);
+	}
+    }
+
+    u->us_clientstate = UPAPCS_OPEN;
+
+    auth_withpeer_success(u->us_unit, PPP_PAP);
+}
+
+
+/*
+ * upap_rauthnak - Receive Authenticate-Nakk.
+ */
+static void
+upap_rauthnak(u, inp, id, len)
+    upap_state *u;
+    u_char *inp;
+    int id;
+    int len;
+{
+    u_char msglen;
+    char *msg;
+
+    if (u->us_clientstate != UPAPCS_AUTHREQ) 
+	return;
+
+    /*
+     * Parse message.
+     */
+    if (len < 1) {
+	UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
+    } else {
+	GETCHAR(msglen, inp);
+	if (msglen > 0) {
+	    len -= sizeof (u_char);
+	    if (len < msglen) {
+		UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
+		return;
+	    }
+	    msg = (char *) inp;
+	    PRINTMSG(msg, msglen);
+	}
+    }
+
+    u->us_clientstate = UPAPCS_BADAUTH;
+
+    error("PAP authentication failed");
+   	
+    //log_to_file("PAP_AUTH_FAIL");	// add by honor
+    system("ppp_event -t PAP_AUTH_FAIL &");
+
+    auth_withpeer_fail(u->us_unit, PPP_PAP);
+}
+
+
+/*
+ * upap_sauthreq - Send an Authenticate-Request.
+ */
+static void
+upap_sauthreq(u)
+    upap_state *u;
+{
+    u_char *outp;
+    int outlen;
+
+    outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
+	u->us_userlen + u->us_passwdlen;
+    outp = outpacket_buf;
+    
+    MAKEHEADER(outp, PPP_PAP);
+
+    PUTCHAR(UPAP_AUTHREQ, outp);
+    PUTCHAR(++u->us_id, outp);
+    PUTSHORT(outlen, outp);
+    PUTCHAR(u->us_userlen, outp);
+    BCOPY(u->us_user, outp, u->us_userlen);
+    INCPTR(u->us_userlen, outp);
+    PUTCHAR(u->us_passwdlen, outp);
+    BCOPY(u->us_passwd, outp, u->us_passwdlen);
+
+    output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
+
+    TIMEOUT(upap_timeout, u, u->us_timeouttime);
+    ++u->us_transmits;
+    u->us_clientstate = UPAPCS_AUTHREQ;
+}
+
+
+/*
+ * upap_sresp - Send a response (ack or nak).
+ */
+static void
+upap_sresp(u, code, id, msg, msglen)
+    upap_state *u;
+    u_char code, id;
+    char *msg;
+    int msglen;
+{
+    u_char *outp;
+    int outlen;
+
+    outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
+    outp = outpacket_buf;
+    MAKEHEADER(outp, PPP_PAP);
+
+    PUTCHAR(code, outp);
+    PUTCHAR(id, outp);
+    PUTSHORT(outlen, outp);
+    PUTCHAR(msglen, outp);
+    BCOPY(msg, outp, msglen);
+    output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
+
+/*
+ * upap_printpkt - print the contents of a PAP packet.
+ */
+static char *upap_codenames[] = {
+    "AuthReq", "AuthAck", "AuthNak"
+};
+
+static int
+upap_printpkt(p, plen, printer, arg)
+    u_char *p;
+    int plen;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int code, id, len;
+    int mlen, ulen, wlen;
+    char *user, *pwd, *msg;
+    u_char *pstart;
+
+    if (plen < UPAP_HEADERLEN)
+	return 0;
+    pstart = p;
+    GETCHAR(code, p);
+    GETCHAR(id, p);
+    GETSHORT(len, p);
+    if (len < UPAP_HEADERLEN || len > plen)
+	return 0;
+
+    if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
+	printer(arg, " %s", upap_codenames[code-1]);
+    else
+	printer(arg, " code=0x%x", code);
+    printer(arg, " id=0x%x", id);
+    len -= UPAP_HEADERLEN;
+    switch (code) {
+    case UPAP_AUTHREQ:
+	if (len < 1)
+	    break;
+	ulen = p[0];
+	if (len < ulen + 2)
+	    break;
+	wlen = p[ulen + 1];
+	if (len < ulen + wlen + 2)
+	    break;
+	user = (char *) (p + 1);
+	pwd = (char *) (p + ulen + 2);
+	p += ulen + wlen + 2;
+	len -= ulen + wlen + 2;
+	printer(arg, " user=");
+	print_string(user, ulen, printer, arg);
+	printer(arg, " password=");
+	if (!hide_password)
+	    print_string(pwd, wlen, printer, arg);
+	else
+	    printer(arg, "<hidden>");
+	break;
+    case UPAP_AUTHACK:
+    case UPAP_AUTHNAK:
+	if (len < 1)
+	    break;
+	mlen = p[0];
+	if (len < mlen + 1)
+	    break;
+	msg = (char *) (p + 1);
+	p += mlen + 1;
+	len -= mlen + 1;
+	printer(arg, " ");
+	print_string(msg, mlen, printer, arg);
+	break;
+    }
+
+    /* print the rest of the bytes in the packet */
+    for (; len > 0; --len) {
+	GETCHAR(code, p);
+	printer(arg, " %.2x", code);
+    }
+
+    return p - pstart;
+}
diff --git a/ap/app/ppp-2.4.1/pppd/upap.h b/ap/app/ppp-2.4.1/pppd/upap.h
new file mode 100644
index 0000000..4807077
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppd/upap.h
@@ -0,0 +1,87 @@
+/*
+ * upap.h - User/Password Authentication Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: upap.h,v 1.1 2008-08-04 06:11:51 winfred Exp $
+ */
+
+/*
+ * Packet header = Code, id, length.
+ */
+#define UPAP_HEADERLEN	4
+
+
+/*
+ * UPAP codes.
+ */
+#define UPAP_AUTHREQ	1	/* Authenticate-Request */
+#define UPAP_AUTHACK	2	/* Authenticate-Ack */
+#define UPAP_AUTHNAK	3	/* Authenticate-Nak */
+
+
+/*
+ * Each interface is described by upap structure.
+ */
+typedef struct upap_state {
+    int us_unit;		/* Interface unit number */
+    char *us_user;		/* User */
+    int us_userlen;		/* User length */
+    char *us_passwd;		/* Password */
+    int us_passwdlen;		/* Password length */
+    int us_clientstate;		/* Client state */
+    int us_serverstate;		/* Server state */
+    u_char us_id;		/* Current id */
+    int us_timeouttime;		/* Timeout (seconds) for auth-req retrans. */
+    int us_transmits;		/* Number of auth-reqs sent */
+    int us_maxtransmits;	/* Maximum number of auth-reqs to send */
+    int us_reqtimeout;		/* Time to wait for auth-req from peer */
+} upap_state;
+
+
+/*
+ * Client states.
+ */
+#define UPAPCS_INITIAL	0	/* Connection down */
+#define UPAPCS_CLOSED	1	/* Connection up, haven't requested auth */
+#define UPAPCS_PENDING	2	/* Connection down, have requested auth */
+#define UPAPCS_AUTHREQ	3	/* We've sent an Authenticate-Request */
+#define UPAPCS_OPEN	4	/* We've received an Ack */
+#define UPAPCS_BADAUTH	5	/* We've received a Nak */
+
+/*
+ * Server states.
+ */
+#define UPAPSS_INITIAL	0	/* Connection down */
+#define UPAPSS_CLOSED	1	/* Connection up, haven't requested auth */
+#define UPAPSS_PENDING	2	/* Connection down, have requested auth */
+#define UPAPSS_LISTEN	3	/* Listening for an Authenticate */
+#define UPAPSS_OPEN	4	/* We've sent an Ack */
+#define UPAPSS_BADAUTH	5	/* We've sent a Nak */
+
+
+/*
+ * Timeouts.
+ */
+#define UPAP_DEFTIMEOUT	3	/* Timeout (seconds) for retransmitting req */
+#define UPAP_DEFREQTIME	30	/* Time to wait for auth-req from peer */
+
+extern upap_state upap[];
+
+void upap_authwithpeer __P((int, char *, char *));
+void upap_authpeer __P((int));
+
+extern struct protent pap_protent;
diff --git a/ap/app/ppp-2.4.1/pppoecd/Makefile b/ap/app/ppp-2.4.1/pppoecd/Makefile
new file mode 100755
index 0000000..40ba3dd
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/Makefile
@@ -0,0 +1,107 @@
+#
+# PPPoEcd Makefile
+#
+# Copyright 2007, Broadcom Corporation
+# All Rights Reserved.
+# 
+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+#
+# $Id: Makefile,v 1.1 2008-08-04 06:11:52 winfred Exp $
+#
+
+#include ../../net_team.mk 
+include $(COMMON_BASE_MK)
+ifneq ($(wildcard $(SRCBASE)/cy_conf.mak),)
+  include $(SRCBASE)/cy_conf.mak
+endif
+
+# Uncomment the following line to enable CCP compression
+# CCP_SUPPORT=y
+
+# Uncomment the following line to enable standard CHAP authentication
+CHAP_SUPPORT=y
+
+# Uncomment the following line to enable MS CHAP authentication
+CHAPMS_SUPPORT=y
+
+# Uncomment the following to enable debugging
+# DFLAGS	+= -g -DDEBUG
+ifeq ($(LOG_PPPOE),2)
+DFLAGS += -DDEBUG -DDEBUGALL
+endif
+
+ifeq ($(MPPPOE_SUPPORT),1)
+DFLAGS += -DMPPPOE_SUPPORT
+endif
+
+CFLAGS	:= -D_linux_=1 -DHAVE_PATHS_H -DHAVE_MMAP
+CFLAGS	+= -I. -I../pppd -O2 -pipe -Wall
+CFLAGS	+= $(DFLAGS) -g
+CFLAGS	+= -I ../include
+CFLAGS	+= -I../../include
+
+CFLAGS += -I$(LIB_DIR)/libnvram
+LDLIBS += -lnvram_sc
+LDLIBS  += -L$(LIB_DIR)/libnvram
+#CFLAGS    += -I$(CROSS_ROOT)/usr/include --sysroot=$(CROSS_ROOT)
+#LDFLAGS    +=  -L$(CROSS_ROOT)/usr/lib/ --sysroot=$(CROSS_ROOT)
+LDFLAGS  += -lcrypt
+
+vpath	%.c ../pppd
+OBJS	:= magic.o fsm.o lcp.o ipcp.o upap.o
+vpath	%.c ../pppd/plugins/pppoe
+OBJS	+= pppoe_client.o libpppoe.o
+OBJS	+= main.o auth.o options.o demand.o utils.o sys-linux.o
+#OBJS	+= ipxcp.o tdb.o tty.o multilink.o
+
+ifdef CCP_SUPPORT
+CFLAGS	+= -DCCP_SUPPORT=1
+OBJS	+= ccp.o
+endif
+
+ifdef CHAP_SUPPORT
+CFLAGS	+= -DCHAP_SUPPORT=1
+OBJS	+= md5.o chap.o
+endif
+
+ifdef CHAPMS_SUPPORT
+CFLAGS	+= -DCHAPMS=1 -DUSE_CRYPT=1 -DHAVE_CRYPT_H=1
+OBJS	+= md4.o chap_ms.o
+OBJS	+= sha1dgst.o mppe.o extra_crypto.o
+endif
+
+# ifneq ($(wildcard $(LIBDIR)/libcrypt.a),)
+# LIBCRYPT := $(LIBDIR)/libcrypt.a
+# else
+# LIBCRYPT := $(USRLIBDIR)/libcrypt.a
+# endif
+
+all: pppoecd poeupdown
+
+romfs:
+	cp pppoecd pppoecd.elf
+	cp poeupdown poeupdown.elf
+	$(ROMFSINST) pppoecd /bin/pppoecd
+	$(ROMFSINST) poeupdown /bin/poeupdown
+	cp poeupdown pppoe-up
+	cp poeupdown pppoe-down
+	$(ROMFSINST) pppoe-up /bin/pppoe-up
+	$(ROMFSINST) pppoe-down /bin/pppoe-down
+#	$(LN) -sf /bin/poeupdown $(ROOTFS_DIR)/etc_ro/ppp/pppoe-up
+#	$(LN) -sf /bin/poeupdown $(ROOTFS_DIR)/etc_ro/ppp/pppoe-down
+pppoecd: $(OBJS)
+	$(LD) -r  -o .$@ $^
+	$(CC) $(CFLAGS) -o $@ .$@ $(LDFLAGS) $(LDLIBS)
+#	rm -f .$@
+
+poeupdown: poeupdown.o 
+	$(CC) $(CFLAGS) -o poeupdown poeupdown.c $(LDFLAGS) $(LDLIBS)
+	
+
+clean:
+	-rm -f *.o *.elf pppoecd poeupdown pppoe-up pppoe-down $(ROOTFS_DIR)/etc_ro/ppp/pppoe-up /etc_ro/ppp/pppoe-down
+
+#$(OBJS): $(CY_DEPS)
diff --git a/ap/app/ppp-2.4.1/pppoecd/auth.c b/ap/app/ppp-2.4.1/pppoecd/auth.c
new file mode 100644
index 0000000..39eeb71
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/auth.c
@@ -0,0 +1,445 @@
+/*
+ * auth.c - PPP authentication and phase control.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University.  The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: auth.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
+
+#include <string.h>
+#include <netinet/in.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "upap.h"
+#include "chap.h"
+
+/* The name by which the peer authenticated itself to us. */
+char peer_authname[MAXNAMELEN];
+
+/* Records which authentication operations haven't completed yet. */
+static int auth_pending[NUM_PPP];
+
+/* Number of network protocols which we have opened. */
+static int num_np_open;
+
+/* Number of network protocols which have come up. */
+static int num_np_up;
+
+/*
+ * Option variables.
+ */
+bool uselogin = 0;		/* Use /etc/passwd for checking PAP */
+bool cryptpap = 0;		/* Passwords in pap-secrets are encrypted */
+bool refuse_pap = 0;		/* Don't wanna auth. ourselves with PAP */
+bool refuse_chap = 0;		/* Don't wanna auth. ourselves with CHAP */
+bool usehostname = 0;		/* Use hostname for our_name */
+bool auth_required = 0;		/* Always require authentication from peer */
+bool allow_any_ip = 0;		/* Allow peer to use any IP address */
+bool explicit_remote = 0;	/* User specified explicit remote name */
+char remote_name[MAXNAMELEN];	/* Peer's name for authentication */
+
+/* Bits in auth_pending[] */
+#define PAP_WITHPEER	1
+#define PAP_PEER	2
+#define CHAP_WITHPEER	4
+#define CHAP_PEER	8
+
+/* Prototypes for procedures local to this file. */
+
+static void network_phase __P((int));
+static void check_idle __P((void *));
+static void connect_time_expired __P((void *));
+
+/*
+ * LCP has terminated the link; go to the Dead phase and take the
+ * physical layer down.
+ */
+void
+link_terminated(unit)
+    int unit;
+{
+    if (phase == PHASE_DEAD)
+	return;
+    new_phase(PHASE_DEAD);
+    notice("Connection terminated.");
+}
+
+/*
+ * LCP has gone down; it will either die or try to re-establish.
+ */
+void
+link_down(unit)
+    int unit;
+{
+    int i;
+    struct protent *protp;
+
+    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+	if (!protp->enabled_flag)
+	    continue;
+        if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
+	    (*protp->lowerdown)(unit);
+        if (protp->protocol < 0xC000 && protp->close != NULL)
+	    (*protp->close)(unit, "LCP down");
+    }
+    num_np_open = 0;
+    num_np_up = 0;
+    if (phase != PHASE_DEAD)
+	new_phase(PHASE_TERMINATE);
+}
+
+/*
+ * The link is established.
+ * Proceed to the Dead, Authenticate or Network phase as appropriate.
+ */
+void
+link_established(unit)
+    int unit;
+{
+    int auth;
+    lcp_options *ho = &lcp_hisoptions[unit];
+    int i;
+    struct protent *protp;
+
+    /*
+     * Tell higher-level protocols that LCP is up.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+        if (protp->protocol != PPP_LCP && protp->enabled_flag
+	    && protp->lowerup != NULL)
+	    (*protp->lowerup)(unit);
+
+    new_phase(PHASE_AUTHENTICATE);
+    auth = 0;
+    if (ho->neg_chap) {
+#ifdef CHAP_SUPPORT
+	ChapAuthWithPeer(unit, user, ho->chap_mdtype);
+	auth |= CHAP_WITHPEER;
+#else
+	error("CHAP unsupported");
+#endif
+    } else if (ho->neg_upap) {
+	if (passwd[0] == 0) {
+	    error("No secret found for PAP login");
+	}
+	upap_authwithpeer(unit, user, passwd);
+	auth |= PAP_WITHPEER;
+    }
+    auth_pending[unit] = auth;
+
+    if (!auth)
+	network_phase(unit);
+}
+
+/*
+ * Proceed to the network phase.
+ */
+static void
+network_phase(unit)
+    int unit;
+{
+    start_networks();
+}
+
+void
+start_networks()
+{
+    int i;
+    struct protent *protp;
+
+    new_phase(PHASE_NETWORK);
+
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+        if (protp->protocol < 0xC000 && protp->enabled_flag
+	    && protp->open != NULL) {
+	    (*protp->open)(0);
+	    if (protp->protocol != PPP_CCP)
+		++num_np_open;
+	}
+
+    if (num_np_open == 0)
+	/* nothing to do */
+	lcp_close(0, "No network protocols running");
+}
+
+/*
+ * The peer has failed to authenticate himself using `protocol'.
+ */
+void
+auth_peer_fail(unit, protocol)
+    int unit, protocol;
+{
+    /*
+     * Authentication failure: take the link down
+     */
+    lcp_close(unit, "Authentication failed");
+    status = EXIT_PEER_AUTH_FAILED;
+}
+
+/*
+ * The peer has been successfully authenticated using `protocol'.
+ */
+void
+auth_peer_success(unit, protocol, name, namelen)
+    int unit, protocol;
+    char *name;
+    int namelen;
+{
+    int bit;
+
+    switch (protocol) {
+    case PPP_CHAP:
+	bit = CHAP_PEER;
+	break;
+    case PPP_PAP:
+	bit = PAP_PEER;
+	break;
+    default:
+	warn("auth_peer_success: unknown protocol %x", protocol);
+	return;
+    }
+
+    /*
+     * Save the authenticated name of the peer for later.
+     */
+    if (namelen > sizeof(peer_authname) - 1)
+	namelen = sizeof(peer_authname) - 1;
+    BCOPY(name, peer_authname, namelen);
+    peer_authname[namelen] = 0;
+    script_setenv("PEERNAME", peer_authname, 0);
+
+    /*
+     * If there is no more authentication still to be done,
+     * proceed to the network (or callback) phase.
+     */
+    if ((auth_pending[unit] &= ~bit) == 0)
+        network_phase(unit);
+}
+
+/*
+ * We have failed to authenticate ourselves to the peer using `protocol'.
+ */
+void
+auth_withpeer_fail(unit, protocol)
+    int unit, protocol;
+{
+    /*
+     * We've failed to authenticate ourselves to our peer.
+     * Some servers keep sending CHAP challenges, but there
+     * is no point in persisting without any way to get updated
+     * authentication secrets.
+     */
+    lcp_close(unit, "Failed to authenticate ourselves to peer");
+    status = EXIT_AUTH_TOPEER_FAILED;
+}
+
+/*
+ * We have successfully authenticated ourselves with the peer using `protocol'.
+ */
+void
+auth_withpeer_success(unit, protocol)
+    int unit, protocol;
+{
+    int bit;
+
+    switch (protocol) {
+    case PPP_CHAP:
+	bit = CHAP_WITHPEER;
+	break;
+    case PPP_PAP:
+	bit = PAP_WITHPEER;
+	break;
+    default:
+	warn("auth_withpeer_success: unknown protocol %x", protocol);
+	bit = 0;
+    }
+
+    /*
+     * If there is no more authentication still being done,
+     * proceed to the network (or callback) phase.
+     */
+    if ((auth_pending[unit] &= ~bit) == 0)
+	network_phase(unit);
+}
+
+
+/*
+ * np_up - a network protocol has come up.
+ */
+void
+np_up(unit, proto)
+    int unit, proto;
+{
+    int tlim;
+
+    if (num_np_up == 0) {
+	/*
+	 * At this point we consider that the link has come up successfully.
+	 */
+	status = EXIT_OK;
+	unsuccess = 0;
+	new_phase(PHASE_RUNNING);
+
+	tlim = idle_time_limit;
+	if (tlim > 0)
+	    TIMEOUT(check_idle, NULL, tlim);
+
+	/*
+	 * Set a timeout to close the connection once the maximum
+	 * connect time has expired.
+	 */
+	if (maxconnect > 0)
+	    TIMEOUT(connect_time_expired, 0, maxconnect);
+
+	/*
+	 * Detach now, if the updetach option was given.
+	 */
+	if (updetach && !nodetach)
+	    detach();
+    }
+    ++num_np_up;
+}
+
+/*
+ * np_down - a network protocol has gone down.
+ */
+void
+np_down(unit, proto)
+    int unit, proto;
+{
+    if (--num_np_up == 0) {
+	UNTIMEOUT(check_idle, NULL);
+	new_phase(PHASE_NETWORK);
+    }
+}
+
+/*
+ * np_finished - a network protocol has finished using the link.
+ */
+void
+np_finished(unit, proto)
+    int unit, proto;
+{
+    if (--num_np_open <= 0) {
+	/* no further use for the link: shut up shop. */
+	lcp_close(0, "No network protocols running");
+    }
+}
+
+/*
+ * check_idle - check whether the link has been idle for long
+ * enough that we can shut it down.
+ */
+static void
+check_idle(arg)
+    void *arg;
+{
+    struct ppp_idle idle;
+    time_t itime;
+    int tlim;
+
+    if (!get_idle_time(0, &idle))
+	return;
+    itime = MIN(idle.xmit_idle, idle.recv_idle);
+    tlim = idle_time_limit - itime;
+    if (tlim <= 0) {
+	/* link is idle: shut it down. */
+	notice("Terminating connection due to lack of activity.");
+	lcp_close(0, "Link inactive");
+	need_holdoff = 0;
+	status = EXIT_IDLE_TIMEOUT;
+    } else {
+	TIMEOUT(check_idle, NULL, tlim);
+    }
+}
+
+/*
+ * connect_time_expired - log a message and close the connection.
+ */
+static void
+connect_time_expired(arg)
+    void *arg;
+{
+    info("Connect time expired");
+    lcp_close(0, "Connect time expired");	/* Close connection */
+    status = EXIT_CONNECT_TIME;
+}
+
+/*
+ * auth_reset - called when LCP is starting negotiations to recheck
+ * authentication options, i.e. whether we have appropriate secrets
+ * to use for authenticating ourselves and/or the peer.
+ */
+void
+auth_reset(unit)
+    int unit;
+{
+    lcp_options *ao = &lcp_allowoptions[0];
+
+    ao->neg_upap = !refuse_pap && (passwd[0] != 0);
+    ao->neg_chap = !refuse_chap	&& (passwd[0] != 0);
+}
+
+/*
+ * get_secret - open the CHAP secret file and return the secret
+ * for authenticating the given client on the given server.
+ * (We could be either client or server).
+ */
+int
+get_secret(unit, client, server, secret, secret_len, am_server)
+    int unit;
+    char *client;
+    char *server;
+    char *secret;
+    int *secret_len;
+    int am_server;
+{
+    *secret_len = strlen(passwd);
+    BCOPY(passwd, secret, *secret_len);
+    return 1;
+}
+
+/*
+ * bad_ip_adrs - return 1 if the IP address is one we don't want
+ * to use, such as an address in the loopback net or a multicast address.
+ * addr is in network byte order.
+ */
+int
+bad_ip_adrs(addr)
+    u_int32_t addr;
+{
+    addr = ntohl(addr);
+    return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
+	|| IN_MULTICAST(addr) || IN_BADCLASS(addr);
+}
diff --git a/ap/app/ppp-2.4.1/pppoecd/main.c b/ap/app/ppp-2.4.1/pppoecd/main.c
new file mode 100644
index 0000000..b086a0d
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/main.c
@@ -0,0 +1,1543 @@
+/*
+ * main.c - Point-to-Point Protocol main module
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: main.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <utmp.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+
+
+#include "pppd.h"
+#include "magic.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "upap.h"
+#include "chap.h"
+#include "ccp.h"
+#include "pathnames.h"
+#include "../../include/netapi.h"
+
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+
+#ifdef IPX_CHANGE
+#include "ipxcp.h"
+#endif /* IPX_CHANGE */
+#ifdef AT_CHANGE
+#include "atcp.h"
+#endif
+
+static const char rcsid[] = RCSID;
+
+/* interface vars */
+char ifname[32];		/* Interface name */
+int ifunit;			/* Interface unit number */
+
+struct channel *the_channel;
+
+char *progname;			/* Name of this program */
+char hostname[MAXNAMELEN];	/* Our hostname */
+static char pidfilename[MAXPATHLEN];	/* name of pid file */
+static char linkpidfile[MAXPATHLEN];	/* name of linkname pid file */
+char ppp_devnam[MAXPATHLEN];	/* name of PPP tty (maybe ttypx) */
+uid_t uid;			/* Our real user-id */
+
+int hungup;			/* terminal has been hung up */
+int privileged;			/* we're running as real uid root */
+int need_holdoff;		/* need holdoff period before restarting */
+int detached;			/* have detached from terminal */
+volatile int status;		/* exit status for pppd */
+int unsuccess;			/* # unsuccessful connection attempts */
+int do_callback;		/* != 0 if we should do callback next */
+int doing_callback;		/* != 0 if we are doing callback */
+
+
+#define pppdb NULL
+
+int (*holdoff_hook) __P((void)) = NULL;
+int (*new_phase_hook) __P((int)) = NULL;
+
+static int conn_running;	/* we have a [dis]connector running */
+static int devfd;		/* fd of underlying device */
+static int fd_ppp = -1;		/* fd for talking PPP */
+static int fd_loop;		/* fd for getting demand-dial packets */
+
+int phase;			/* where the link is at */
+int kill_link;
+int open_ccp_flag;
+int listen_time;
+int got_sigusr2;
+int got_sigterm;
+int got_sighup;
+
+static int waiting;
+static sigjmp_buf sigjmp;
+
+char **script_env;		/* Env. variable values for scripts */
+int s_env_nalloc;		/* # words avail at script_env */
+
+u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
+u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
+
+static int n_children;		/* # child processes still running */
+static int got_sigchld;		/* set if we have received a SIGCHLD */
+
+int privopen;			/* don't lock, open device as root */
+
+char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
+
+GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
+int ngroups;			/* How many groups valid in groups */
+
+static struct timeval start_time;	/* Time when link was started. */
+
+struct pppd_stats link_stats;
+int link_connect_time;
+int link_stats_valid;
+
+/*
+ * We maintain a list of child process pids and
+ * functions to call when they exit.
+ */
+struct subprocess {
+    pid_t	pid;
+    char	*prog;
+    void	(*done) __P((void *));
+    void	*arg;
+    struct subprocess *next;
+};
+
+static struct subprocess *children;
+
+/* Prototypes for procedures local to this file. */
+
+static void setup_signals __P((void));
+static void create_pidfile __P((void));
+static void create_linkpidfile __P((void));
+static void cleanup __P((void));
+static void get_input __P((void));
+static void calltimeout __P((void));
+static struct timeval *timeleft __P((struct timeval *));
+static void kill_my_pg __P((int));
+static void hup __P((int));
+static void term __P((int));
+static void chld __P((int));
+static void toggle_debug __P((int));
+static void open_ccp __P((int));
+static void bad_signal __P((int));
+static void holdoff_end __P((void *));
+static int reap_kids __P((int waitfor));
+#define update_db_entry()
+#define add_db_key(a)
+#define delete_db_key(a)
+#define cleanup_db()
+static void handle_events __P((void));
+
+extern	char	*ttyname __P((int));
+extern	char	*getlogin __P((void));
+int main __P((int, char *[]));
+
+#ifdef ultrix
+#undef	O_NONBLOCK
+#define	O_NONBLOCK	O_NDELAY
+#endif
+
+#ifdef ULTRIX
+#define setlogmask(x)
+#endif
+
+/*
+ * PPP Data Link Layer "protocol" table.
+ * One entry per supported protocol.
+ * The last entry must be NULL.
+ */
+struct protent *protocols[] = {
+    &lcp_protent,
+    &pap_protent,
+#ifdef CHAP_SUPPORT
+    &chap_protent,
+#endif
+    &ipcp_protent,
+#ifdef CCP_SUPPORT
+    &ccp_protent,
+#endif
+    NULL
+};
+
+/*
+ * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
+ */
+#if !defined(PPP_DRV_NAME)
+#define PPP_DRV_NAME	"ppp"
+#endif /* !defined(PPP_DRV_NAME) */
+
+
+/*
+ÄÚ²¿¶¨Ê±Æ÷:
+PPPOE/DHCP×ÔÊÊӦģʽÏ£¬ÓÅÏÈÖ´ÐÐPPPOE²¦ºÅ£¬
+³¬Ê±ÔòÆô¶¯DHCP
+*/
+void time_out_action(int signo)
+{
+    char pppoe_reply[8] = {0};
+    char path_sh[32] = {0};
+    char ethwan[32] = {0};
+    char cmd[100] = {0};
+    sc_cfg_get("pppoe_reply", pppoe_reply, sizeof(pppoe_reply));
+    if(0 == strcmp(pppoe_reply, "0"))
+    {
+        sc_cfg_get("path_sh", path_sh, sizeof(path_sh));
+        sc_cfg_get("ethwan", ethwan, sizeof(ethwan));
+        sprintf(cmd,"udhcpc -i %s -s %s/udhcpc.sh &",ethwan,path_sh);
+        system(cmd);    
+        exit(1);
+    }
+
+}
+
+void init_sigaction()
+{
+    struct sigaction my_act;
+    my_act.sa_handler = time_out_action;
+    my_act.sa_flags = 0;
+    sigemptyset(&my_act.sa_mask);
+    sigaction(SIGALRM,&my_act,NULL);
+    //signal(SIGALRM,time_out_action);
+}
+
+void init_time()
+{
+    struct itimerval value;
+    value.it_value.tv_sec = 10;
+    value.it_value.tv_usec = 0;
+
+    value.it_interval.tv_sec = 0;
+    value.it_interval.tv_usec = 0;
+
+    sc_cfg_set("pppoe_reply", "0");    
+    
+    setitimer(ITIMER_REAL,&value,NULL);
+}
+
+
+
+
+
+
+
+int
+main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int i, t;
+    char *p;
+    struct passwd *pw;
+    struct protent *protp;
+    char numbuf[16];
+    char eth_mode[32] = {0};
+    sc_cfg_get("ethwan_mode", eth_mode, sizeof(eth_mode));
+    
+    new_phase(PHASE_INITIALIZE);
+
+    //sc_cfg_set("ppp_status","ppp_connecting");//linxu
+
+    /*
+     * Ensure that fds 0, 1, 2 are open, to /dev/null if nowhere else.
+     * This way we can close 0, 1, 2 in detach() without clobbering
+     * a fd that we are using.
+     */
+    if ((i = open("/dev/null", O_RDWR)) >= 0) {
+	while (0 <= i && i <= 2)
+	    i = dup(i);
+	if (i >= 0)
+	    close(i);
+    }
+
+    script_env = NULL;
+
+    /* Initialize syslog facilities */
+    //reopen_log();
+
+    if (gethostname(hostname, MAXNAMELEN) < 0 ) {
+	option_error("Couldn't get hostname: %m");
+	exit(1);
+    }
+    hostname[MAXNAMELEN-1] = 0;
+
+    /* make sure we don't create world or group writable files. */
+    umask(umask(0777) | 022);
+
+    uid = getuid();
+    privileged = uid == 0;
+    slprintf(numbuf, sizeof(numbuf), "%d", uid);
+    script_setenv("ORIG_UID", numbuf, 0);
+
+    ngroups = getgroups(NGROUPS_MAX, groups);
+
+    /*
+     * Initialize magic number generator now so that protocols may
+     * use magic numbers in initialization.
+     */
+    magic_init();
+
+    /*
+     * Initialize each protocol.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+        (*protp->init)(0);
+
+    progname = *argv;
+
+    /*
+     * Parse, in order, the system options file, the user's options file,
+     * and the command line arguments.
+     */
+
+    if (!parse_args(argc, argv))
+	exit(EXIT_OPTION_ERROR);
+    devnam_fixed = 1;		/* can no longer change device name */
+
+    reopen_log();	// According to ipparam value, decide log name
+
+    /*
+     * Work out the device name, if it hasn't already been specified,
+     * and parse the tty's options file.
+     */
+    if (the_channel->process_extra_options)
+	(*the_channel->process_extra_options)();
+
+    if (debug)
+	setlogmask(LOG_UPTO(LOG_DEBUG));
+
+    /*
+     * Check that we are running as root.
+     */
+    if (geteuid() != 0) {
+	option_error("must be root to run %s, since it is not setuid-root",
+		     argv[0]);
+	exit(EXIT_NOT_ROOT);
+    }
+
+    if (!ppp_available()) {
+	option_error("%s", no_ppp_msg);
+	exit(EXIT_NO_KERNEL_SUPPORT);
+    }
+
+    /*
+     * Check that the options given are valid and consistent.
+     */
+    check_options();
+    if (!sys_check_options())
+	exit(EXIT_OPTION_ERROR);
+    auth_check_options();
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	if (protp->check_options != NULL)
+	    (*protp->check_options)();
+    if (the_channel->check_options)
+	(*the_channel->check_options)();
+
+
+    if (dump_options || dryrun) {
+	init_pr_log(NULL, LOG_INFO);
+	print_options(pr_log, NULL);
+	end_pr_log();
+	if (dryrun)
+	    die(0);
+    }
+
+    /*
+     * Initialize system-dependent stuff.
+     */
+    sys_init();
+
+    /*
+     * Detach ourselves from the terminal, if required,
+     * and identify who is running us.
+     */
+    if (!nodetach && !updetach)
+	detach();
+    p = getlogin();
+    if (p == NULL) {
+	pw = getpwuid(uid);
+	if (pw != NULL && pw->pw_name != NULL)
+	    p = pw->pw_name;
+	else
+	    p = "(unknown)";
+    }
+    syslog(LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid);
+    script_setenv("PPPLOGNAME", p, 0);
+
+    if (devnam[0])
+	script_setenv("DEVICE", devnam, 1);
+    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
+    script_setenv("PPPD_PID", numbuf, 1);
+
+    setup_signals();
+
+    if (0 == strcmp(eth_mode, "auto") || 0 == strcmp(eth_mode, "ondemand"))
+	{
+	    init_sigaction();
+        init_time();
+    }
+    waiting = 0;
+
+    create_linkpidfile();
+
+    /*
+     * If we're doing dial-on-demand, set up the interface now.
+     */
+    if (demand) {
+	/*
+	 * Open the loopback channel and set it up to be the ppp interface.
+	 */
+	fd_loop = open_ppp_loopback();
+	set_ifunit(1);
+
+	/*
+	 * Configure the interface and mark it up, etc.
+	 */
+	demand_conf();
+    }
+
+    do_callback = 0;
+    for (;;) {
+
+	listen_time = 0;
+	need_holdoff = 1;
+	devfd = -1;
+	status = EXIT_OK;
+	++unsuccess;
+	doing_callback = do_callback;
+	do_callback = 0;
+
+	if (demand && !doing_callback) {
+	    /*
+	     * Don't do anything until we see some activity.
+	     */
+	    new_phase(PHASE_DORMANT);
+	    demand_unblock();
+	    add_fd(fd_loop);
+	    for (;;) {
+		handle_events();
+		if (kill_link && !persist)
+		    break;
+		if (get_loop_output())
+		    break;
+	    }
+	    remove_fd(fd_loop);
+	    if (kill_link && !persist)
+		break;
+
+	    /*
+	     * Now we want to bring up the link.
+	     */
+	    demand_block();
+	    info("Starting link");
+	}
+
+	new_phase(PHASE_SERIALCONN);
+	
+	devfd = the_channel->connect();
+	if (devfd < 0)
+	    continue;
+
+	/* set up the serial device as a ppp interface */
+	fd_ppp = the_channel->establish_ppp(devfd);
+	if (fd_ppp < 0) {	
+	    status = EXIT_FATAL_ERROR;
+	    goto disconnect;
+	}
+
+	if (!demand && ifunit >= 0)
+	    set_ifunit(1);
+
+	/*
+	 * Start opening the connection and wait for
+	 * incoming events (reply, timeout, etc.).
+	 */
+	notice("Connect: %s <--> %s", ifname, ppp_devnam);	
+	my_gettimeofday(&start_time, NULL);
+	link_stats_valid = 0;
+	script_unsetenv("CONNECT_TIME");
+	script_unsetenv("BYTES_SENT");
+	script_unsetenv("BYTES_RCVD");
+	lcp_lowerup(0);
+
+	add_fd(fd_ppp);
+	lcp_open(0);		/* Start protocol */
+	status = EXIT_NEGOTIATION_FAILED;
+	new_phase(PHASE_ESTABLISH);
+	while (phase != PHASE_DEAD) {
+	    handle_events();
+	    get_input();
+	    if (kill_link)
+		lcp_close(0, "User request");
+#ifdef CCP_SUPPORT
+	    if (open_ccp_flag) {
+		if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) {
+		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
+		    (*ccp_protent.open)(0);
+		}
+	    }
+#endif
+	}
+
+	/*
+	 * Print connect time and statistics.
+	 */
+	if (link_stats_valid) {
+	    int t = (link_connect_time + 5) / 6;    /* 1/10ths of minutes */
+	    info("Connect time %d.%d minutes.", t/10, t%10);
+	    info("Sent %u bytes, received %u bytes.",
+		 link_stats.bytes_out, link_stats.bytes_in);
+	}
+
+	/*
+	 * Delete pid file before disestablishing ppp.  Otherwise it
+	 * can happen that another pppd gets the same unit and then
+	 * we delete its pid file.
+	 */
+	if (!demand) {
+	    if (pidfilename[0] != 0
+		&& unlink(pidfilename) < 0 && errno != ENOENT)
+		warn("unable to delete pid file %s: %m", pidfilename);
+	    pidfilename[0] = 0;
+	}
+
+	/*
+	 * If we may want to bring the link up again, transfer
+	 * the ppp unit back to the loopback.  Set the
+	 * real serial device back to its normal mode of operation.
+	 */
+	remove_fd(fd_ppp);
+	clean_check();
+	the_channel->disestablish_ppp(devfd);
+	fd_ppp = -1;
+	if (!hungup)
+	    lcp_lowerdown(0);
+	if (!demand)
+	    script_unsetenv("IFNAME");
+
+    disconnect:
+	new_phase(PHASE_DISCONNECT);
+	the_channel->disconnect();
+
+/*  fail: */
+        /*add by maxl begin, 2010-12-16*/
+        /*for setting ppp status to disconnected when pppoe down*/
+        //sc_cfg_set("ppp_status","ppp_disconnected");   //linxu
+        /*add by maxl end,2010-12-16*/
+        
+	if (the_channel->cleanup)
+	    (*the_channel->cleanup)();
+
+	if (!demand) {
+	    if (pidfilename[0] != 0
+		&& unlink(pidfilename) < 0 && errno != ENOENT)
+		warn("unable to delete pid file %s: %m", pidfilename);
+	    pidfilename[0] = 0;
+	}
+
+	if (!persist || (maxfail > 0 && unsuccess >= maxfail))
+	    break;
+
+	if (demand)
+	    demand_discard();
+	t = need_holdoff? holdoff: 0;
+	if (holdoff_hook)
+	    t = (*holdoff_hook)();
+	if (t > 0) {
+	    new_phase(PHASE_HOLDOFF);
+	    TIMEOUT(holdoff_end, NULL, t);
+	    do {
+		handle_events();
+		if (kill_link)
+		    new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
+	    } while (phase == PHASE_HOLDOFF);
+	    if (!persist)
+		break;
+	}
+    }
+
+    /* Wait for scripts to finish */
+    while (n_children > 0) {
+	if (debug) {
+	    struct subprocess *chp;
+	    dbglog("Waiting for %d child processes...", n_children);
+	    for (chp = children; chp != NULL; chp = chp->next)
+		dbglog("  script %s, pid %d", chp->prog, chp->pid);
+	}
+	if (reap_kids(1) < 0)
+	    break;
+    }
+
+    die(status);
+    return 0;
+}
+
+/*
+ * handle_events - wait for something to happen and respond to it.
+ */
+static void
+handle_events()
+{
+    struct timeval timo;
+    sigset_t mask;
+
+    kill_link = open_ccp_flag = 0;
+    if (sigsetjmp(sigjmp, 1) == 0) {
+	sigprocmask(SIG_BLOCK, &mask, NULL);
+	if (got_sighup || got_sigterm || got_sigusr2 || got_sigchld) {
+	    sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	} else {
+	    waiting = 1;
+	    sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	    wait_input(timeleft(&timo));
+	}
+    }
+    waiting = 0;
+    calltimeout();
+    if (got_sighup) {
+	kill_link = 1;
+	got_sighup = 0;
+	if (status != EXIT_HANGUP)
+	    status = EXIT_USER_REQUEST;
+    }
+    if (got_sigterm) {
+	kill_link = 1;
+	persist = 0;
+	status = EXIT_USER_REQUEST;
+	got_sigterm = 0;
+    }
+    if (got_sigchld) {
+	reap_kids(0);	/* Don't leave dead kids lying around */
+	got_sigchld = 0;
+    }
+    if (got_sigusr2) {
+	open_ccp_flag = 1;
+	got_sigusr2 = 0;
+    }
+}
+
+/*
+ * setup_signals - initialize signal handling.
+ */
+static void
+setup_signals()
+{
+    struct sigaction sa;
+    sigset_t mask;
+
+    /*
+     * Compute mask of all interesting signals and install signal handlers
+     * for each.  Only one signal handler may be active at a time.  Therefore,
+     * all other signals should be masked when any handler is executing.
+     */
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGHUP);
+    sigaddset(&mask, SIGINT);
+    sigaddset(&mask, SIGTERM);
+    sigaddset(&mask, SIGCHLD);
+    sigaddset(&mask, SIGUSR2);
+
+#define SIGNAL(s, handler)	do { \
+	sa.sa_handler = handler; \
+	if (sigaction(s, &sa, NULL) < 0) \
+	    fatal("Couldn't establish signal handler (%d): %m", s); \
+    } while (0)
+
+    sa.sa_mask = mask;
+    sa.sa_flags = 0;
+    SIGNAL(SIGHUP, hup);		/* Hangup */
+    SIGNAL(SIGINT, term);		/* Interrupt */
+    SIGNAL(SIGTERM, term);		/* Terminate */
+    SIGNAL(SIGCHLD, chld);
+
+    SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
+    SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */
+
+    /*
+     * Install a handler for other signals which would otherwise
+     * cause pppd to exit without cleaning up.
+     */
+    SIGNAL(SIGABRT, bad_signal);
+    //SIGNAL(SIGALRM, bad_signal);
+    SIGNAL(SIGFPE, bad_signal);
+    SIGNAL(SIGILL, bad_signal);
+    SIGNAL(SIGPIPE, bad_signal);
+    SIGNAL(SIGQUIT, bad_signal);
+    SIGNAL(SIGSEGV, bad_signal);
+#ifdef SIGBUS
+    SIGNAL(SIGBUS, bad_signal);
+#endif
+#ifdef SIGEMT
+    SIGNAL(SIGEMT, bad_signal);
+#endif
+#ifdef SIGPOLL
+    SIGNAL(SIGPOLL, bad_signal);
+#endif
+#ifdef SIGPROF
+    SIGNAL(SIGPROF, bad_signal);
+#endif
+#ifdef SIGSYS
+    SIGNAL(SIGSYS, bad_signal);
+#endif
+#ifdef SIGTRAP
+    SIGNAL(SIGTRAP, bad_signal);
+#endif
+#ifdef SIGVTALRM
+    SIGNAL(SIGVTALRM, bad_signal);
+#endif
+#ifdef SIGXCPU
+    SIGNAL(SIGXCPU, bad_signal);
+#endif
+#ifdef SIGXFSZ
+    SIGNAL(SIGXFSZ, bad_signal);
+#endif
+
+    /*
+     * Apparently we can get a SIGPIPE when we call syslog, if
+     * syslogd has died and been restarted.  Ignoring it seems
+     * be sufficient.
+     */
+    signal(SIGPIPE, SIG_IGN);
+}
+
+/*
+ * set_ifunit - do things we need to do once we know which ppp
+ * unit we are using.
+ */
+void
+set_ifunit(iskey)
+    int iskey;
+{
+    info("Using interface %s%d", PPP_DRV_NAME, ifunit);
+    slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
+    script_setenv("IFNAME", ifname, iskey);
+
+    char *arg[3]={_PATH_SETPPPOEPID, ipparam, NULL};  // tallest 1219
+    run_program(_PATH_SETPPPOEPID,arg,0,0,0);
+
+    if (iskey) {
+	create_pidfile();	/* write pid to file */
+	create_linkpidfile();
+    }
+}
+
+/*
+ * detach - detach us from the controlling terminal.
+ */
+void
+detach()
+{
+    int pid;
+    char numbuf[16];
+
+    if (detached)
+	return;
+    if ((pid = fork()) < 0) {
+	error("Couldn't detach (fork failed: %m)");
+	die(1);			/* or just return? */
+    }
+    if (pid != 0) {
+	/* parent */
+	exit(0);		/* parent dies */
+    }
+    setsid();
+    chdir("/");
+    close(0);
+    close(1);
+    close(2);
+    detached = 1;
+    if (log_default)
+	log_to_fd = -1;
+    /* update pid files if they have been written already */
+    if (pidfilename[0])
+	create_pidfile();
+    if (linkpidfile[0])
+	create_linkpidfile();
+    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
+    script_setenv("PPPD_PID", numbuf, 1);
+}
+
+/*
+ * reopen_log - (re)open our connection to syslog.
+ */
+void
+reopen_log()
+{
+#ifdef ULTRIX
+    openlog("pppd", LOG_PID);
+#else
+#ifdef MPPPOE_SUPPORT
+    if(!strncmp(ipparam, "0", 1))
+        openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
+    else
+        openlog("pppd-1", LOG_PID | LOG_NDELAY, LOG_PPP);
+#else
+    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
+#endif
+    setlogmask(LOG_UPTO(LOG_INFO));
+#endif
+}
+
+/*
+ * Create a file containing our process ID.
+ */
+static void
+create_pidfile()
+{
+    FILE *pidfile;
+
+    slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
+	     _PATH_VARRUN, ifname);
+    if ((pidfile = fopen(pidfilename, "w")) != NULL) {
+	fprintf(pidfile, "%d\n", getpid());
+	(void) fclose(pidfile);
+    } else {
+	error("Failed to create pid file %s: %m", pidfilename);
+	pidfilename[0] = 0;
+    }
+}
+
+static void
+create_linkpidfile()
+{
+    FILE *pidfile;
+
+    if (linkname[0] == 0)
+	return;
+    script_setenv("LINKNAME", linkname, 1);
+    slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",
+	     _PATH_VARRUN, linkname);
+    if ((pidfile = fopen(linkpidfile, "w")) != NULL) {
+	fprintf(pidfile, "%d\n", getpid());
+	if (ifname[0])
+	    fprintf(pidfile, "%s\n", ifname);
+	(void) fclose(pidfile);
+    } else {
+	error("Failed to create pid file %s: %m", linkpidfile);
+	linkpidfile[0] = 0;
+    }
+}
+
+/*
+ * holdoff_end - called via a timeout when the holdoff period ends.
+ */
+static void
+holdoff_end(arg)
+    void *arg;
+{
+    new_phase(PHASE_DORMANT);
+}
+
+/*
+ * get_input - called when incoming data is available.
+ */
+static void
+get_input()
+{
+    int len, i;
+    u_char *p;
+    u_short protocol;
+    struct protent *protp;
+
+    p = inpacket_buf;	/* point to beginning of packet buffer */
+
+    len = read_packet(inpacket_buf);
+    if (len < 0)
+	return;
+
+    if (len == 0) {
+	notice("Modem hangup");
+	hungup = 1;
+	status = EXIT_HANGUP;
+	lcp_lowerdown(0);	/* serial link is no longer available */
+	link_terminated(0);
+	return;
+    }
+
+    if (debug /*&& (debugflags & DBG_INPACKET)*/)
+	dbglog("rcvd %P", p, len);
+
+    if (len < PPP_HDRLEN) {
+	MAINDEBUG(("io(): Received short packet."));
+	return;
+    }
+
+    p += 2;				/* Skip address and control */
+    GETSHORT(protocol, p);
+    len -= PPP_HDRLEN;
+
+    /*
+     * Toss all non-LCP packets unless LCP is OPEN.
+     */
+    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
+	MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
+	return;
+    }
+
+    /*
+     * Until we get past the authentication phase, toss all packets
+     * except LCP, LQR and authentication packets.
+     */
+    if (phase <= PHASE_AUTHENTICATE
+	&& !(protocol == PPP_LCP || protocol == PPP_LQR
+	     || protocol == PPP_PAP || protocol == PPP_CHAP)) {
+	MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
+		   protocol, phase));
+	return;
+    }
+
+    /*
+     * Upcall the proper protocol input routine.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+	if (protp->protocol == protocol && protp->enabled_flag) {
+	    (*protp->input)(0, p, len);
+	    return;
+	}
+        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
+	    && protp->datainput != NULL) {
+	    (*protp->datainput)(0, p, len);
+	    return;
+	}
+    }
+
+    if (debug) {
+	warn("Unsupported protocol 0x%x received", protocol);
+    }
+    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
+}
+
+/*
+ * new_phase - signal the start of a new phase of pppd's operation.
+ */
+void
+new_phase(p)
+    int p;
+{
+    phase = p;
+    if (new_phase_hook)
+	(*new_phase_hook)(p);
+}
+
+/*
+ * die - clean up state and exit with the specified status.
+ */
+void
+die(status)
+    int status;
+{
+	char pppoe_errno[128]={0};
+	cleanup();
+	syslog(LOG_INFO, "Exit.");
+	//sc_cfg_set("ppp_status","ppp_disconnected"); //linxu
+
+	sscanf(pppoe_errno, "%d", status);
+	sc_cfg_set("pppoe_errno",pppoe_errno); 
+	exit(status);
+}
+
+/*
+ * cleanup - restore anything which needs to be restored before we exit
+ */
+/* ARGSUSED */
+static void
+cleanup()
+{
+    sys_cleanup();
+
+    if (fd_ppp >= 0)
+	the_channel->disestablish_ppp(devfd);
+    if (the_channel->cleanup)
+	(*the_channel->cleanup)();
+
+    if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
+	warn("unable to delete pid file %s: %m", pidfilename);
+    pidfilename[0] = 0;
+    if (linkpidfile[0] != 0 && unlink(linkpidfile) < 0 && errno != ENOENT)
+	warn("unable to delete pid file %s: %m", linkpidfile);
+    linkpidfile[0] = 0;
+}
+
+/*
+ * update_link_stats - get stats at link termination.
+ */
+void
+update_link_stats(u)
+    int u;
+{
+    struct timeval now;
+    char numbuf[32];
+
+    if (!get_ppp_stats(u, &link_stats)
+	|| my_gettimeofday(&now, NULL) < 0)
+	return;
+    link_connect_time = now.tv_sec - start_time.tv_sec;
+    link_stats_valid = 1;
+
+    slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time);
+    script_setenv("CONNECT_TIME", numbuf, 0);
+    slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out);
+    script_setenv("BYTES_SENT", numbuf, 0);
+    slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in);
+    script_setenv("BYTES_RCVD", numbuf, 0);
+}
+
+
+struct	callout {
+    struct timeval	c_time;		/* time at which to call routine */
+    void		*c_arg;		/* argument to routine */
+    void		(*c_func) __P((void *)); /* routine */
+    struct		callout *c_next;
+};
+
+static struct callout *callout = NULL;	/* Callout list */
+static struct timeval timenow;		/* Current time */
+
+/*
+ * timeout - Schedule a timeout.
+ *
+ * Note that this timeout takes the number of milliseconds, NOT hz (as in
+ * the kernel).
+ */
+void
+timeout(func, arg, secs, usecs)
+    void (*func) __P((void *));
+    void *arg;
+    int secs, usecs;
+{
+    struct callout *newp, *p, **pp;
+
+    // Compiler error
+    //MAINDEBUG(("Timeout %p:%p in %d.%03d seconds.", func, arg,
+    //	       time / 1000, time % 1000));
+
+    /*
+     * Allocate timeout.
+     */
+    if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
+	fatal("Out of memory in timeout()!");
+    newp->c_arg = arg;
+    newp->c_func = func;
+    my_gettimeofday(&timenow, NULL);
+    newp->c_time.tv_sec = timenow.tv_sec + secs;
+    newp->c_time.tv_usec = timenow.tv_usec + usecs;
+    if (newp->c_time.tv_usec >= 1000000) {
+	newp->c_time.tv_sec += newp->c_time.tv_usec / 1000000;
+	newp->c_time.tv_usec %= 1000000;
+    }
+
+    /*
+     * Find correct place and link it in.
+     */
+    for (pp = &callout; (p = *pp); pp = &p->c_next)
+	if (newp->c_time.tv_sec < p->c_time.tv_sec
+	    || (newp->c_time.tv_sec == p->c_time.tv_sec
+		&& newp->c_time.tv_usec < p->c_time.tv_usec))
+	    break;
+    newp->c_next = p;
+    *pp = newp;
+}
+
+
+/*
+ * untimeout - Unschedule a timeout.
+ */
+void
+untimeout(func, arg)
+    void (*func) __P((void *));
+    void *arg;
+{
+    struct callout **copp, *freep;
+
+    MAINDEBUG(("Untimeout %p:%p.", func, arg));
+
+    /*
+     * Find first matching timeout and remove it from the list.
+     */
+    for (copp = &callout; (freep = *copp); copp = &freep->c_next)
+	if (freep->c_func == func && freep->c_arg == arg) {
+	    *copp = freep->c_next;
+	    free((char *) freep);
+	    break;
+	}
+}
+
+
+/*
+ * calltimeout - Call any timeout routines which are now due.
+ */
+static void
+calltimeout()
+{
+    struct callout *p;
+
+    while (callout != NULL) {
+	p = callout;
+
+	if (my_gettimeofday(&timenow, NULL) < 0)
+	    fatal("Failed to get time of day: %m");
+	if (!(p->c_time.tv_sec < timenow.tv_sec
+	      || (p->c_time.tv_sec == timenow.tv_sec
+		  && p->c_time.tv_usec <= timenow.tv_usec)))
+	    break;		/* no, it's not time yet */
+
+	callout = p->c_next;
+	(*p->c_func)(p->c_arg);
+
+	free((char *) p);
+    }
+}
+
+
+/*
+ * timeleft - return the length of time until the next timeout is due.
+ */
+static struct timeval *
+timeleft(tvp)
+    struct timeval *tvp;
+{
+    if (callout == NULL)
+	return NULL;
+
+    my_gettimeofday(&timenow, NULL);
+    tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
+    tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
+    if (tvp->tv_usec < 0) {
+	tvp->tv_usec += 1000000;
+	tvp->tv_sec -= 1;
+    }
+    if (tvp->tv_sec < 0)
+	tvp->tv_sec = tvp->tv_usec = 0;
+
+    return tvp;
+}
+
+
+/*
+ * kill_my_pg - send a signal to our process group, and ignore it ourselves.
+ */
+static void
+kill_my_pg(sig)
+    int sig;
+{
+    struct sigaction act, oldact;
+
+    act.sa_handler = SIG_IGN;
+    act.sa_flags = 0;
+    kill(0, sig);
+    sigaction(sig, &act, &oldact);
+    sigaction(sig, &oldact, NULL);
+}
+
+
+/*
+ * hup - Catch SIGHUP signal.
+ *
+ * Indicates that the physical layer has been disconnected.
+ * We don't rely on this indication; if the user has sent this
+ * signal, we just take the link down.
+ */
+static void
+hup(sig)
+    int sig;
+{
+    info("Hangup (SIGHUP)");
+    got_sighup = 1;
+    if (conn_running)
+	/* Send the signal to the [dis]connector process(es) also */
+	kill_my_pg(sig);
+    if (waiting)
+	siglongjmp(sigjmp, 1);
+}
+
+
+/*
+ * term - Catch SIGTERM signal and SIGINT signal (^C/del).
+ *
+ * Indicates that we should initiate a graceful disconnect and exit.
+ */
+/*ARGSUSED*/
+static void
+term(sig)
+    int sig;
+{
+    info("Terminating on signal %d.", sig);
+    got_sigterm = 1;
+    if (conn_running)
+	/* Send the signal to the [dis]connector process(es) also */
+	kill_my_pg(sig);
+    if (waiting)
+	siglongjmp(sigjmp, 1);
+}
+
+
+/*
+ * chld - Catch SIGCHLD signal.
+ * Sets a flag so we will call reap_kids in the mainline.
+ */
+static void
+chld(sig)
+    int sig;
+{
+    got_sigchld = 1;
+    if (waiting)
+	siglongjmp(sigjmp, 1);
+}
+
+
+/*
+ * toggle_debug - Catch SIGUSR1 signal.
+ *
+ * Toggle debug flag.
+ */
+/*ARGSUSED*/
+static void
+toggle_debug(sig)
+    int sig;
+{
+    debug = !debug;
+    if (debug) {
+	setlogmask(LOG_UPTO(LOG_DEBUG));
+    } else {
+	setlogmask(LOG_UPTO(LOG_WARNING));
+    }
+}
+
+
+/*
+ * open_ccp - Catch SIGUSR2 signal.
+ *
+ * Try to (re)negotiate compression.
+ */
+/*ARGSUSED*/
+static void
+open_ccp(sig)
+    int sig;
+{
+    got_sigusr2 = 1;
+    if (waiting)
+	siglongjmp(sigjmp, 1);
+}
+
+
+/*
+ * bad_signal - We've caught a fatal signal.  Clean up state and exit.
+ */
+static void
+bad_signal(sig)
+    int sig;
+{
+    static int crashed = 0;
+
+    if (crashed)
+	_exit(127);
+    crashed = 1;
+    error("Fatal signal %d", sig);
+    if (conn_running)
+	kill_my_pg(SIGTERM);
+    die(127);
+}
+
+/*
+ * run-program - execute a program with given arguments,
+ * but don't wait for it.
+ * If the program can't be executed, logs an error unless
+ * must_exist is 0 and the program file doesn't exist.
+ * Returns -1 if it couldn't fork, 0 if the file doesn't exist
+ * or isn't an executable plain file, or the process ID of the child.
+ * If done != NULL, (*done)(arg) will be called later (within
+ * reap_kids) iff the return value is > 0.
+ */
+pid_t
+run_program(prog, args, must_exist, done, arg)
+    char *prog;
+    char **args;
+    int must_exist;
+    void (*done) __P((void *));
+    void *arg;
+{
+    int pid;
+    struct stat sbuf;
+
+    /*
+     * First check if the file exists and is executable.
+     * We don't use access() because that would use the
+     * real user-id, which might not be root, and the script
+     * might be accessible only to root.
+     */
+    errno = EINVAL;
+    if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
+	|| (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
+	if (must_exist || errno != ENOENT)
+	    warn("Can't execute %s: %m", prog);
+	return 0;
+    }
+
+    pid = fork();
+    if (pid == -1) {
+	error("Failed to create child process for %s: %m", prog);
+	return -1;
+    }
+    if (pid == 0) {
+	int new_fd;
+
+	/* Leave the current location */
+	(void) setsid();	/* No controlling tty. */
+	(void) umask (S_IRWXG|S_IRWXO);
+	(void) chdir ("/");	/* no current directory. */
+	setuid(0);		/* set real UID = root */
+	setgid(getegid());
+
+	/* Ensure that nothing of our device environment is inherited. */
+	sys_close();
+	closelog();
+	close (0);
+	close (1);
+	close (2);
+	if (the_channel->close)
+	    (*the_channel->close)();
+
+        /* Don't pass handles to the PPP device, even by accident. */
+	new_fd = open (_PATH_DEVNULL, O_RDWR);
+	if (new_fd >= 0) {
+	    if (new_fd != 0) {
+	        dup2  (new_fd, 0); /* stdin <- /dev/null */
+		close (new_fd);
+	    }
+	    dup2 (0, 1); /* stdout -> /dev/null */
+	    dup2 (0, 2); /* stderr -> /dev/null */
+	}
+
+#ifdef BSD
+	/* Force the priority back to zero if pppd is running higher. */
+	if (setpriority (PRIO_PROCESS, 0, 0) < 0)
+	    warn("can't reset priority to 0: %m");
+#endif
+
+	/* SysV recommends a second fork at this point. */
+
+	/* run the program */
+	execve(prog, args, script_env);
+	if (must_exist || errno != ENOENT) {
+	    /* have to reopen the log, there's nowhere else
+	       for the message to go. */
+	    reopen_log();
+	    syslog(LOG_ERR, "Can't execute %s: %m", prog);
+	    closelog();
+	}
+	_exit(-1);
+    }
+
+    if (debug)
+	dbglog("Script %s started (pid %d)", prog, pid);
+    record_child(pid, prog, done, arg);
+
+    return pid;
+}
+
+
+/*
+ * record_child - add a child process to the list for reap_kids
+ * to use.
+ */
+void
+record_child(pid, prog, done, arg)
+    int pid;
+    char *prog;
+    void (*done) __P((void *));
+    void *arg;
+{
+    struct subprocess *chp;
+
+    ++n_children;
+
+    chp = (struct subprocess *) malloc(sizeof(struct subprocess));
+    if (chp == NULL) {
+	warn("losing track of %s process", prog);
+    } else {
+	chp->pid = pid;
+	chp->prog = prog;
+	chp->done = done;
+	chp->arg = arg;
+	chp->next = children;
+	children = chp;
+    }
+}
+
+
+/*
+ * reap_kids - get status from any dead child processes,
+ * and log a message for abnormal terminations.
+ */
+static int
+reap_kids(waitfor)
+    int waitfor;
+{
+    int pid, status;
+    struct subprocess *chp, **prevp;
+
+    if (n_children == 0)
+	return 0;
+    while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
+	   && pid != 0) {
+	for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
+	    if (chp->pid == pid) {
+		--n_children;
+		*prevp = chp->next;
+		break;
+	    }
+	}
+	if (WIFSIGNALED(status)) {
+	    warn("Child process %s (pid %d) terminated with signal %d",
+		 (chp? chp->prog: "??"), pid, WTERMSIG(status));
+	} else if (debug)
+	    dbglog("Script %s finished (pid %d), status = 0x%x",
+		   (chp? chp->prog: "??"), pid, status);
+	if (chp && chp->done)
+	    (*chp->done)(chp->arg);
+	if (chp)
+	    free(chp);
+    }
+    if (pid == -1) {
+	if (errno == ECHILD)
+	    return -1;
+	if (errno != EINTR)
+	    error("Error waiting for child process: %m");
+    }
+    return 0;
+}
+
+/*
+ * script_setenv - set an environment variable value to be used
+ * for scripts that we run (e.g. ip-up, auth-up, etc.)
+ */
+void
+script_setenv(var, value, iskey)
+    char *var, *value;
+    int iskey;
+{
+    size_t varl = strlen(var);
+    size_t vl = varl + strlen(value) + 2;
+    int i;
+    char *p, *newstring;
+
+    newstring = (char *) malloc(vl+1);
+    if (newstring == 0)
+	return;
+    *newstring++ = iskey;
+    slprintf(newstring, vl, "%s=%s", var, value);
+
+    /* check if this variable is already set */
+    if (script_env != 0) {
+	for (i = 0; (p = script_env[i]) != 0; ++i) {
+	    if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
+		if (p[-1] && pppdb != NULL)
+		    delete_db_key(p);
+		free(p-1);
+		script_env[i] = newstring;
+		if (iskey && pppdb != NULL)
+		    add_db_key(newstring);
+		update_db_entry();
+		return;
+	    }
+	}
+    } else {
+	/* no space allocated for script env. ptrs. yet */
+	i = 0;
+	script_env = (char **) malloc(16 * sizeof(char *));
+	if (script_env == 0)
+	    return;
+	s_env_nalloc = 16;
+    }
+
+    /* reallocate script_env with more space if needed */
+    if (i + 1 >= s_env_nalloc) {
+	int new_n = i + 17;
+	char **newenv = (char **) realloc((void *)script_env,
+					  new_n * sizeof(char *));
+	if (newenv == 0)
+	    return;
+	script_env = newenv;
+	s_env_nalloc = new_n;
+    }
+
+    script_env[i] = newstring;
+    script_env[i+1] = 0;
+
+    if (pppdb != NULL) {
+	if (iskey)
+	    add_db_key(newstring);
+	update_db_entry();
+    }
+}
+
+/*
+ * script_unsetenv - remove a variable from the environment
+ * for scripts.
+ */
+void
+script_unsetenv(var)
+    char *var;
+{
+    int vl = strlen(var);
+    int i;
+    char *p;
+
+    if (script_env == 0)
+	return;
+    for (i = 0; (p = script_env[i]) != 0; ++i) {
+	if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
+	    if (p[-1] && pppdb != NULL)
+		delete_db_key(p);
+	    free(p-1);
+	    while ((script_env[i] = script_env[i+1]) != 0)
+		++i;
+	    break;
+	}
+    }
+    if (pppdb != NULL)
+	update_db_entry();
+}
diff --git a/ap/app/ppp-2.4.1/pppoecd/options.c b/ap/app/ppp-2.4.1/pppoecd/options.c
new file mode 100644
index 0000000..5467021
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/options.c
@@ -0,0 +1,175 @@
+/*
+ * options.c - handles option processing for PPP.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: options.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+
+int	debug = 0;		/* Debug flag */
+int	kdebugflag = 0;		/* Tell kernel to print debug messages */
+int	default_device = 1;	/* Using /dev/tty or equivalent */
+char	devnam[MAXPATHLEN];	/* Device name */
+bool	nodetach = 0;		/* Don't detach from controlling tty */
+bool	updetach = 0;		/* Detach once link is up */
+int	maxconnect = 0;		/* Maximum connect time */
+char	user[MAXNAMELEN];	/* Username for PAP */
+char	passwd[MAXSECRETLEN];	/* Password for PAP */
+bool	persist = 0;		/* Reopen link after it goes down */
+char	our_name[MAXNAMELEN];	/* Our name for authentication purposes */
+bool	demand = 0;		/* do dial-on-demand */
+char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
+int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */
+int	holdoff = 30;		/* # seconds to pause before reconnecting */
+bool	holdoff_specified;	/* true if a holdoff value has been given */
+int	log_to_fd = 1;		/* send log messages to this fd too */
+bool	log_default = 1;	/* log_to_fd is default (stdout) */
+int	maxfail = 10;		/* max # of unsuccessful connection attempts */
+char	linkname[MAXPATHLEN];	/* logical name for link */
+bool	tune_kernel = 1;	/* may alter kernel settings */
+int	connect_delay = 1000;	/* wait this many ms after connect script */
+int	req_unit = -1;		/* requested interface unit */
+char	*bundle_name = NULL;	/* bundle name for multilink */
+bool	dump_options;		/* print out option values */
+bool	dryrun;			/* print out option values and exit */
+char	*domain;		/* domain name set by domain option */
+int	baud_rate;		/* Actual bits/second for serial device */
+#ifdef UNNUMBERIP_SUPPORT
+char	is_unnumber_ip = 0;	/* This parameter use for unnumber IP. by tallest */
+#endif
+char	ppp_disconnect_func[MAXFUNCLEN]; /* This is a function for dial on demand disconnection using. by tallest 0407 */
+
+char *current_option;		/* the name of the option being parsed */
+int  privileged_option;		/* set iff the current option came from root */
+char *option_source;		/* string saying where the option came from */
+int  option_priority = OPRIO_CFGFILE; /* priority of the current options */
+bool devnam_fixed;		/* can no longer change device name */
+
+extern char *pppoe_ac_name;
+extern char *pppoe_srv_name;
+extern int lcp_echo_interval;  /* Interval between LCP echo-requests */
+extern int lcp_echo_fails;     /* Tolerance to unanswered echo-requests */
+extern int retry_num;	       /* interval of send disc */
+extern int retransmit_time;
+
+extern int setdevname_pppoe(const char *cp);
+
+static char *usage_string = "usage: %s interface -d -k [-i idle] [-u username] [-p passwd] [-a acname] [-s srvname] [-r mru] [-t mtu] [-I lcp_echo_interval] [-T lcp_echo_fails] [-P ipparam] [-L Local IP] [-N retry_num] [-R set default route] [-n use unnumber ip] [-C disconnected function]\n";
+
+/*
+ * parse_args - parse a string of arguments from the command line.
+ */
+int
+parse_args(argc, argv)
+    int argc;
+    char **argv;
+{
+    int opt;
+    struct in_addr Laddr, Naddr;
+
+    while ((opt = getopt(argc, argv, "dki:u:p:a:s:r:t:U:I:T:P:L:N:RnC:v:")) != -1) {
+	    switch (opt) {
+	    case 'd':
+		    debug = nodetach = 1;
+		    break;
+	    case 'k':
+		    persist = 1;
+		    break;
+	    case 'i':
+		    idle_time_limit = atoi(optarg);
+		    if (idle_time_limit > 0)
+			    demand = 1;
+		    break;
+	    case 'u':
+		    strncpy(user, optarg, MAXNAMELEN);
+		    strncpy(our_name, optarg, MAXNAMELEN);
+		    break;
+	    case 'p':
+		    strncpy(passwd, optarg, MAXSECRETLEN);
+		    break;
+	    case 'a':
+		    pppoe_ac_name = optarg;
+		    break;
+	    case 's':
+		    pppoe_srv_name = optarg;
+		    break;
+	    case 'r':
+		    lcp_wantoptions[0].neg_mru = 1;
+		    lcp_wantoptions[0].mru = atoi(optarg);
+		    break;
+	    case 't':
+		    lcp_allowoptions[0].mru = atoi(optarg);
+		    break;
+	    case 'I':	// by honor
+		    lcp_echo_interval = atoi(optarg);
+		    break;
+	    case 'T':	// by honor
+		    lcp_echo_fails = atoi(optarg);
+		    break;
+	    case 'P':	// by honor
+		    ipparam = optarg;
+		    break;
+	    case 'L':	// by honor, support static IP Address
+		    inet_aton(optarg, &Laddr);
+		    ipcp_wantoptions[0].ouraddr = Laddr.s_addr;
+		    break;
+	    case 'N':	// by honor
+		    retry_num = atoi(optarg);
+		    break;
+	    case 'U':
+		    req_unit = atoi(optarg);
+		    break;
+	    case 'R':	//by tallest set default route
+		    	ipcp_wantoptions[0].default_route = 1;
+		    break;
+	    case 'n':   //by tallest for unnumber ip use. 
+#ifdef UNNUMBERIP_SUPPORT
+                        is_unnumber_ip = 1;
+#endif
+		    break;
+	    case 'C': //by tallest 0407
+			strncpy(ppp_disconnect_func, optarg, MAXFUNCLEN);
+                    break;
+	    case 'v': //by tallest 0407
+			retransmit_time = atoi(optarg);
+                    break;
+	    default:
+		    fprintf(stderr, usage_string, argv[0]);
+		    return 0;
+	    }
+    }
+
+    if (optind < argc)
+	    setdevname_pppoe(argv[optind]);
+    else {
+	    fprintf(stderr, usage_string, argv[0]);
+	    return 0;
+    }
+
+    return 1;
+}
diff --git a/ap/app/ppp-2.4.1/pppoecd/poeupdown.c b/ap/app/ppp-2.4.1/pppoecd/poeupdown.c
new file mode 100644
index 0000000..89d7ef2
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/poeupdown.c
@@ -0,0 +1,98 @@
+#include <errno.h>

+#include <time.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <sys/ipc.h>

+#include <sys/msg.h>

+#include <sys/types.h>

+#include <string.h>

+#include <termios.h>

+#include "../../include/message.h"

+//#include "../../include/errorcode.h"

+

+

+#define do_cmd(format, cmds...) ({ \

+  int __STATAS__; \

+  char __TEMP__[256]; \

+  sprintf(__TEMP__, format, ##cmds); \

+  __STATAS__ = system(__TEMP__); \

+  __STATAS__; \

+})

+

+#define cprintf(fmt, args...) do {  \

+    FILE *fp = fopen("/dev/console", "w");  \

+    if (fp) {   \

+        fprintf(fp, fmt, ## args);  \

+        fclose(fp); \

+    }   \

+} while (0)

+

+int main(int argc, char **argv)

+{

+	char * name = NULL;

+	char *pValue = NULL;

+	char buf[256];

+	char ethwan[32];

+	name = strrchr(argv[0], '/');

+	name = name ? name + 1 : argv[0];    

+    sc_cfg_get("ethwan", ethwan, sizeof(ethwan));

+	char path_sh[100]={0};

+	char path_file[500]={0};

+ /*

+  	nv set $wan_if"_ip"=0.0.0.0

+    nv set $wan_if"_nm"=0.0.0.0

+    nv set $wan_if"_gw"=0.0.0.0

+    nv set $wan_if"_pridns"=0.0.0.0

+    nv set $wan_if"_secdns"=0.0.0.0*/

+    //printf(name);

+	if (strstr(name, "pppoe-up"))

+	{

+		

+		if (NULL!= (pValue = getenv("IPLOCAL")))

+		{	   	   

+			sprintf(buf,"%s_ip",ethwan);		

+			sc_cfg_set(buf, pValue);

+		}

+		if (NULL!=(pValue = getenv("IPREMOTE")))

+		{ 

+			sprintf(buf,"%s_gw",ethwan);			

+			sc_cfg_set(buf, pValue);

+		}

+ 

+		if (NULL!=(pValue = getenv("DNS1")))

+		{

+			sprintf(buf,"%s_pridns",ethwan);		

+			sc_cfg_set(buf, pValue);

+		}	

+		if (NULL!=(pValue = getenv("DNS2")))

+		{                  

+			sprintf(buf,"%s_secdns",ethwan);		

+			sc_cfg_set(buf, pValue);

+		}

+		sprintf(buf,"%s_nm",ethwan);		

+		sc_cfg_set(buf,"255.255.255.255"); 

+		

+		sc_cfg_get("path_sh", path_sh, sizeof(path_sh));

+		sprintf(path_file,"%s/pppoe_updown.sh up",path_sh);

+	 	do_cmd(path_file);  

+	}        

+	else if (strstr(name, "pppoe-down"))

+	{

+		sprintf(buf,"%s_ip",ethwan);	

+		sc_cfg_set(buf, "0.0.0.0");

+		sprintf(buf,"%s_gw",ethwan);	

+		sc_cfg_set(buf, "0.0.0.0");

+		sprintf(buf,"%s_pridns",ethwan);	

+		sc_cfg_set(buf, "0.0.0.0");

+		sprintf(buf,"%s_secdns",ethwan);	

+		sc_cfg_set(buf, "0.0.0.0");

+		sprintf(buf,"%s_nm",ethwan);	

+		sc_cfg_set(buf,"0.0.0.0");  

+	 	sc_cfg_get("path_sh", path_sh, sizeof(path_sh));

+		sprintf(path_file,"%s/pppoe_updown.sh down",path_sh);

+	 	do_cmd(path_file); 

+		//sc_cfg_set("ppp_status","ppp_disconnected");  

+	}

+	return 0;

+

+}
diff --git a/ap/app/ppp-2.4.1/pppoecd/pppd.h b/ap/app/ppp-2.4.1/pppoecd/pppd.h
new file mode 100644
index 0000000..957f229
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/pppd.h
@@ -0,0 +1,782 @@
+/*
+ * pppd.h - PPP daemon global declarations.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: pppd.h,v 1.1 2008-08-04 06:11:52 winfred Exp $
+ */
+
+/*
+ * TODO:
+ */
+
+#ifndef __PPPD_H__
+#define __PPPD_H__
+
+#include <stdio.h>		/* for FILE */
+#include <limits.h>		/* for NGROUPS_MAX */
+#include <sys/param.h>		/* for MAXPATHLEN and BSD4_4, if defined */
+#include <sys/types.h>		/* for u_int32_t, if defined */
+#include <sys/time.h>		/* for struct timeval */
+#include <net/ppp_defs.h>
+#include "patchlevel.h"
+
+#if defined(__STDC__)
+#include <stdarg.h>
+#define __V(x)	x
+#else
+#include <varargs.h>
+#define __V(x)	(va_alist) va_dcl
+#define const
+#define volatile
+#endif
+
+#ifdef INET6
+#include "eui64.h"
+#endif
+
+/*
+ * Limits.
+ */
+
+#define NUM_PPP		1	/* One PPP interface supported (per process) */
+#define MAXWORDLEN	1024	/* max length of word in file (incl null) */
+#define MAXARGS		1	/* max # args to a command */
+#define MAXNAMELEN	256	/* max length of hostname or name for auth */
+#define MAXSECRETLEN	256	/* max length of password or secret */
+
+/*
+ * Option descriptor structure.
+ */
+
+typedef unsigned char	bool;
+
+enum opt_type {
+	o_special_noarg = 0,
+	o_special = 1,
+	o_bool,
+	o_int,
+	o_uint32,
+	o_string,
+	o_wild,
+};
+
+typedef struct {
+	char	*name;		/* name of the option */
+	enum opt_type type;
+	void	*addr;
+	char	*description;
+	int	flags;
+	void	*addr2;
+	int	upper_limit;
+	int	lower_limit;
+	const char *source;
+	short int priority;
+	short int winner;
+} option_t;
+
+/* Values for flags */
+#define OPT_VALUE	0xff	/* mask for presupplied value */
+#define OPT_HEX		0x100	/* int option is in hex */
+#define OPT_NOARG	0x200	/* option doesn't take argument */
+#define OPT_OR		0x400	/* OR in argument to value */
+#define OPT_INC		0x800	/* increment value */
+#define OPT_PRIV	0x1000	/* privileged option */
+#define OPT_STATIC	0x2000	/* string option goes into static array */
+#define OPT_LLIMIT	0x4000	/* check value against lower limit */
+#define OPT_ULIMIT	0x8000	/* check value against upper limit */
+#define OPT_LIMITS	(OPT_LLIMIT|OPT_ULIMIT)
+#define OPT_ZEROOK	0x10000	/* 0 value is OK even if not within limits */
+#define OPT_HIDE	0x10000	/* for o_string, print value as ?????? */
+#define OPT_A2LIST	0x10000 /* for o_special, keep list of values */
+#define OPT_NOINCR	0x20000	/* value mustn't be increased */
+#define OPT_ZEROINF	0x40000	/* with OPT_NOINCR, 0 == infinity */
+#define OPT_PRIO	0x80000	/* process option priorities for this option */
+#define OPT_PRIOSUB	0x100000 /* subsidiary member of priority group */
+#define OPT_ALIAS	0x200000 /* option is alias for previous option */
+#define OPT_A2COPY	0x400000 /* addr2 -> second location to rcv value */
+#define OPT_ENABLE	0x800000 /* use *addr2 as enable for option */
+#define OPT_A2CLR	0x1000000 /* clear *(bool *)addr2 */
+#define OPT_PRIVFIX	0x2000000 /* user can't override if set by root */
+#define OPT_INITONLY	0x4000000 /* option can only be set in init phase */
+#define OPT_DEVEQUIV	0x8000000 /* equiv to device name */
+#define OPT_DEVNAM	(OPT_INITONLY | OPT_DEVEQUIV)
+#define OPT_A2PRINTER	0x10000000 /* *addr2 is a fn for printing option */
+#define OPT_A2STRVAL	0x20000000 /* *addr2 points to current string value */
+#define OPT_NOPRINT	0x40000000 /* don't print this option at all */
+
+#define OPT_VAL(x)	((x) & OPT_VALUE)
+
+/* Values for priority */
+#define OPRIO_DEFAULT	0	/* a default value */
+#define OPRIO_CFGFILE	1	/* value from a configuration file */
+#define OPRIO_CMDLINE	2	/* value from the command line */
+#define OPRIO_SECFILE	3	/* value from options in a secrets file */
+#define OPRIO_ROOT	100	/* added to priority if OPT_PRIVFIX && root */
+
+#ifndef GIDSET_TYPE
+#define GIDSET_TYPE	gid_t
+#endif
+
+/* Structure representing a list of permitted IP addresses. */
+struct permitted_ip {
+    int		permit;		/* 1 = permit, 0 = forbid */
+    u_int32_t	base;		/* match if (addr & mask) == base */
+    u_int32_t	mask;		/* base and mask are in network byte order */
+};
+
+/*
+ * Unfortunately, the linux kernel driver uses a different structure
+ * for statistics from the rest of the ports.
+ * This structure serves as a common representation for the bits
+ * pppd needs.
+ */
+struct pppd_stats {
+    unsigned int	bytes_in;
+    unsigned int	bytes_out;
+};
+
+/* Used for storing a sequence of words.  Usually malloced. */
+struct wordlist {
+    struct wordlist	*next;
+    char		*word;
+};
+
+/* An endpoint discriminator, used with multilink. */
+#define MAX_ENDP_LEN	20	/* maximum length of discriminator value */
+struct epdisc {
+    unsigned char	class;
+    unsigned char	length;
+    unsigned char	value[MAX_ENDP_LEN];
+};
+
+/* values for epdisc.class */
+#define EPD_NULL	0	/* null discriminator, no data */
+#define EPD_LOCAL	1
+#define EPD_IP		2
+#define EPD_MAC		3
+#define EPD_MAGIC	4
+#define EPD_PHONENUM	5
+
+typedef void (*notify_func) __P((void *, int));
+
+struct notifier {
+    struct notifier *next;
+    notify_func	    func;
+    void	    *arg;
+};
+
+/*
+ * Global variables.
+ */
+
+extern int	hungup;		/* Physical layer has disconnected */
+extern int	ifunit;		/* Interface unit number */
+extern char	ifname[];	/* Interface name */
+extern char	hostname[];	/* Our hostname */
+extern u_char	outpacket_buf[]; /* Buffer for outgoing packets */
+extern int	phase;		/* Current state of link - see values below */
+extern int	baud_rate;	/* Current link speed in bits/sec */
+extern char	*progname;	/* Name of this program */
+extern int	redirect_stderr;/* Connector's stderr should go to file */
+extern char	peer_authname[];/* Authenticated name of peer */
+extern int	privileged;	/* We were run by real-uid root */
+extern int	need_holdoff;	/* Need holdoff period after link terminates */
+extern char	**script_env;	/* Environment variables for scripts */
+extern int	detached;	/* Have detached from controlling tty */
+extern GIDSET_TYPE groups[NGROUPS_MAX];	/* groups the user is in */
+extern int	ngroups;	/* How many groups valid in groups */
+extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */
+extern int	link_stats_valid; /* set if link_stats is valid */
+extern int	link_connect_time; /* time the link was up for */
+extern int	using_pty;	/* using pty as device (notty or pty opt.) */
+extern int	log_to_fd;	/* logging to this fd as well as syslog */
+extern bool	log_default;	/* log_to_fd is default (stdout) */
+extern char	*no_ppp_msg;	/* message to print if ppp not in kernel */
+extern volatile int status;	/* exit status for pppd */
+extern bool	devnam_fixed;	/* can no longer change devnam */
+extern int	unsuccess;	/* # unsuccessful connection attempts */
+extern int	do_callback;	/* set if we want to do callback next */
+extern int	doing_callback;	/* set if this is a callback */
+extern char	ppp_devnam[MAXPATHLEN];
+extern struct notifier *pidchange;   /* for notifications of pid changing */
+extern struct notifier *phasechange; /* for notifications of phase changes */
+extern struct notifier *exitnotify;  /* for notification that we're exiting */
+extern struct notifier *sigreceived; /* notification of received signal */
+extern int	listen_time;	/* time to listen first (ms) */
+
+/* Values for do_callback and doing_callback */
+#define CALLBACK_DIALIN		1	/* we are expecting the call back */
+#define CALLBACK_DIALOUT	2	/* we are dialling out to call back */
+
+/*
+ * Variables set by command-line options.
+ */
+
+extern int	debug;		/* Debug flag */
+extern int	kdebugflag;	/* Tell kernel to print debug messages */
+extern int	default_device;	/* Using /dev/tty or equivalent */
+extern char	devnam[MAXPATHLEN];	/* Device name */
+extern int	crtscts;	/* Use hardware flow control */
+extern bool	modem;		/* Use modem control lines */
+extern int	inspeed;	/* Input/Output speed requested */
+extern u_int32_t netmask;	/* IP netmask to set on interface */
+extern bool	lockflag;	/* Create lock file to lock the serial dev */
+extern bool	nodetach;	/* Don't detach from controlling tty */
+extern bool	updetach;	/* Detach from controlling tty when link up */
+extern char	*initializer;	/* Script to initialize physical link */
+extern char	*connect_script; /* Script to establish physical link */
+extern char	*disconnect_script; /* Script to disestablish physical link */
+extern char	*welcomer;	/* Script to welcome client after connection */
+extern char	*ptycommand;	/* Command to run on other side of pty */
+extern int	maxconnect;	/* Maximum connect time (seconds) */
+extern char	user[MAXNAMELEN];/* Our name for authenticating ourselves */
+extern char	passwd[MAXSECRETLEN];	/* Password for PAP or CHAP */
+extern bool	auth_required;	/* Peer is required to authenticate */
+extern bool	persist;	/* Reopen link after it goes down */
+extern bool	uselogin;	/* Use /etc/passwd for checking PAP */
+extern char	our_name[MAXNAMELEN];/* Our name for authentication purposes */
+extern char	remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+extern bool	explicit_remote;/* remote_name specified with remotename opt */
+extern bool	demand;		/* Do dial-on-demand */
+extern char	*ipparam;	/* Extra parameter for ip up/down scripts */
+extern bool	cryptpap;	/* Others' PAP passwords are encrypted */
+extern int	idle_time_limit;/* Shut down link if idle for this long */
+extern int	holdoff;	/* Dead time before restarting */
+extern bool	holdoff_specified; /* true if user gave a holdoff value */
+extern bool	notty;		/* Stdin/out is not a tty */
+extern char	*pty_socket;	/* Socket to connect to pty */
+extern char	*record_file;	/* File to record chars sent/received */
+extern bool	sync_serial;	/* Device is synchronous serial device */
+extern int	maxfail;	/* Max # of unsuccessful connection attempts */
+extern char	linkname[MAXPATHLEN]; /* logical name for link */
+extern bool	tune_kernel;	/* May alter kernel settings as necessary */
+extern int	connect_delay;	/* Time to delay after connect script */
+extern int	max_data_rate;	/* max bytes/sec through charshunt */
+extern int	req_unit;	/* interface unit number to use */
+static const bool	multilink = 0;	/* enable multilink operation */
+extern bool	noendpoint;	/* don't send or accept endpt. discrim. */
+extern char	*bundle_name;	/* bundle name for multilink */
+extern bool	dump_options;	/* print out option values */
+extern bool	dryrun;		/* check everything, print options, exit */
+static const int new_style_driver = 1;
+
+#ifdef PPP_FILTER
+extern struct	bpf_program pass_filter;   /* Filter for pkts to pass */
+extern struct	bpf_program active_filter; /* Filter for link-active pkts */
+#endif
+
+#ifdef MSLANMAN
+extern bool	ms_lanman;	/* Use LanMan password instead of NT */
+				/* Has meaning only with MS-CHAP challenges */
+#endif
+
+extern char *current_option;	/* the name of the option being parsed */
+extern int  privileged_option;	/* set iff the current option came from root */
+extern char *option_source;	/* string saying where the option came from */
+extern int  option_priority;	/* priority of current options */
+
+#ifdef UNNUMBERIP_SUPPORT
+extern char    is_unnumber_ip;  /* This parameter use for unnumber IP. by tallest */
+#endif
+
+#define MAXFUNCLEN	256 //by tallest 0407
+extern char	ppp_disconnect_func[MAXFUNCLEN];	//by tallest 0407
+
+/*
+ * Values for phase.
+ */
+#define PHASE_DEAD		0
+#define PHASE_INITIALIZE	1
+#define PHASE_SERIALCONN	2
+#define PHASE_DORMANT		3
+#define PHASE_ESTABLISH		4
+#define PHASE_AUTHENTICATE	5
+#define PHASE_CALLBACK		6
+#define PHASE_NETWORK		7
+#define PHASE_RUNNING		8
+#define PHASE_TERMINATE		9
+#define PHASE_DISCONNECT	10
+#define PHASE_HOLDOFF		11
+
+/*
+ * The following struct gives the addresses of procedures to call
+ * for a particular protocol.
+ */
+struct protent {
+    u_short protocol;		/* PPP protocol number */
+    /* Initialization procedure */
+    void (*init) __P((int unit));
+    /* Process a received packet */
+    void (*input) __P((int unit, u_char *pkt, int len));
+    /* Process a received protocol-reject */
+    void (*protrej) __P((int unit));
+    /* Lower layer has come up */
+    void (*lowerup) __P((int unit));
+    /* Lower layer has gone down */
+    void (*lowerdown) __P((int unit));
+    /* Open the protocol */
+    void (*open) __P((int unit));
+    /* Close the protocol */
+    void (*close) __P((int unit, char *reason));
+    /* Print a packet in readable form */
+    int  (*printpkt) __P((u_char *pkt, int len,
+			  void (*printer) __P((void *, char *, ...)),
+			  void *arg));
+    /* Process a received data packet */
+    void (*datainput) __P((int unit, u_char *pkt, int len));
+    bool enabled_flag;		/* 0 iff protocol is disabled */
+    char *name;			/* Text name of protocol */
+    char *data_name;		/* Text name of corresponding data protocol */
+    option_t *options;		/* List of command-line options */
+    /* Check requested options, assign defaults */
+    void (*check_options) __P((void));
+    /* Configure interface for demand-dial */
+    int  (*demand_conf) __P((int unit));
+    /* Say whether to bring up link for this pkt */
+    int  (*active_pkt) __P((u_char *pkt, int len));
+};
+
+/* Table of pointers to supported protocols */
+extern struct protent *protocols[];
+
+/*
+ * This struct contains pointers to a set of procedures for
+ * doing operations on a "channel".  A channel provides a way
+ * to send and receive PPP packets - the canonical example is
+ * a serial port device in PPP line discipline (or equivalently
+ * with PPP STREAMS modules pushed onto it).
+ */
+struct channel {
+	/* set of options for this channel */
+	option_t *options;
+	/* find and process a per-channel options file */
+	void (*process_extra_options) __P((void));
+	/* check all the options that have been given */
+	void (*check_options) __P((void));
+	/* get the channel ready to do PPP, return a file descriptor */
+	int  (*connect) __P((void));
+	/* we're finished with the channel */
+	void (*disconnect) __P((void));
+	/* put the channel into PPP `mode' */
+	int  (*establish_ppp) __P((int));
+	/* take the channel out of PPP `mode', restore loopback if demand */
+	void (*disestablish_ppp) __P((int));
+	/* set the transmit-side PPP parameters of the channel */
+	void (*send_config) __P((int, u_int32_t, int, int));
+	/* set the receive-side PPP parameters of the channel */
+	void (*recv_config) __P((int, u_int32_t, int, int));
+	/* cleanup on error or normal exit */
+	void (*cleanup) __P((void));
+	/* close the device, called in children after fork */
+	void (*close) __P((void));
+};
+
+extern struct channel *the_channel;
+
+#define ppp_send_config(unit, mtu, accm, pc, acc)			 \
+do {									 \
+	if (the_channel->send_config)					 \
+		(*the_channel->send_config)((mtu), (accm), (pc), (acc)); \
+} while (0)
+
+#define ppp_recv_config(unit, mtu, accm, pc, acc)			 \
+do {									 \
+	if (the_channel->send_config)					 \
+		(*the_channel->recv_config)((mtu), (accm), (pc), (acc)); \
+} while (0)
+
+/*
+ * Prototypes.
+ */
+
+/* Procedures exported from main.c. */
+void set_ifunit __P((int));	/* set stuff that depends on ifunit */
+void detach __P((void));	/* Detach from controlling tty */
+void die __P((int));		/* Cleanup and exit */
+void quit __P((void));		/* like die(1) */
+#define novm fatal
+void timeout __P((void (*func)(void *), void *arg, int s, int us));
+				/* Call func(arg) after s.us seconds */
+void untimeout __P((void (*func)(void *), void *arg));
+				/* Cancel call to func(arg) */
+void record_child __P((int, char *, void (*) (void *), void *));
+#define device_script(a,b,c,d) (-1)
+pid_t run_program __P((char *prog, char **args, int must_exist,
+		       void (*done)(void *), void *arg));
+				/* Run program prog with args in child */
+void reopen_log __P((void));	/* (re)open the connection to syslog */
+void update_link_stats __P((int)); /* Get stats at link termination */
+void script_setenv __P((char *, char *, int));	/* set script env var */
+void script_unsetenv __P((char *));		/* unset script env var */
+void new_phase __P((int));	/* signal start of new phase */
+#define add_notifier(a,b)
+#define remove_notifier(a,b)
+#define notify(a,b)
+
+/* Procedures exported from tty.c. */
+#define tty_init()
+
+/* Procedures exported from utils.c. */
+int slprintf __P((char *, int, char *, ...));		/* sprintf++ */
+int vslprintf __P((char *, int, char *, va_list));	/* vsprintf++ */
+size_t strlcpy __P((char *, const char *, size_t));	/* safe strcpy */
+size_t strlcat __P((char *, const char *, size_t));	/* safe strncpy */
+#ifdef DEBUG
+void log_packet __P((u_char *, int, char *, int));
+				/* Format a packet and log it with syslog */
+void print_string __P((char *, int,  void (*) (void *, char *, ...),
+		void *));	/* Format a string for output */
+void dbglog __P((char *, ...));	/* log a debug message */
+void info __P((char *, ...));	/* log an informational message */
+void notice __P((char *, ...));	/* log a notice-level message */
+void warn __P((char *, ...));	/* log a warning message */
+void error __P((char *, ...));	/* log an error message */
+void fatal __P((char *, ...));	/* log an error message and die(1) */
+void init_pr_log __P((char *, int));	/* initialize for using pr_log */
+void pr_log __P((void *, char *, ...));	/* printer fn, output to syslog */
+void end_pr_log __P((void));	/* finish up after using pr_log */
+#else
+#define log_packet(a,b,c,d)
+#define print_string(a,b,c,d)
+#define dbglog(a,b...)
+#define info(a,b...)
+#define notice(a,b...)
+#define warn(a,b...)
+#define error(a,b...)
+#define fatal(a,b...)
+#define init_pr_log(a,b)
+#define pr_log (NULL)
+#define end_pr_log()
+#endif
+
+/* Procedures exported from auth.c */
+#define link_required(a)
+void link_terminated __P((int));  /* we are finished with the link */
+void link_down __P((int));	  /* the LCP layer has left the Opened state */
+void link_established __P((int)); /* the link is up; authenticate now */
+void start_networks __P((void));  /* start all the network control protos */
+void np_up __P((int, int));	  /* a network protocol has come up */
+void np_down __P((int, int));	  /* a network protocol has gone down */
+void np_finished __P((int, int)); /* a network protocol no longer needs link */
+void auth_peer_fail __P((int, int));
+				/* peer failed to authenticate itself */
+void auth_peer_success __P((int, int, char *, int));
+				/* peer successfully authenticated itself */
+void auth_withpeer_fail __P((int, int));
+				/* we failed to authenticate ourselves */
+void auth_withpeer_success __P((int, int));
+				/* we successfully authenticated ourselves */
+#define auth_check_options()
+void auth_reset __P((int));	/* check what secrets we have */
+#define check_passwd(a,b,c,d,e,f) (UPAP_AUTHNAK)
+int  get_secret __P((int, char *, char *, char *, int *, int));
+				/* get "secret" for chap */
+#define auth_ip_addr(a,b) (1)
+int  bad_ip_adrs __P((u_int32_t));
+				/* check if IP address is unreasonable */
+
+/* Procedures exported from demand.c */
+void demand_conf __P((void));	/* config interface(s) for demand-dial */
+void demand_block __P((void));	/* set all NPs to queue up packets */
+void demand_unblock __P((void)); /* set all NPs to pass packets */
+void demand_discard __P((void)); /* set all NPs to discard packets */
+void demand_rexmit __P((int));	/* retransmit saved frames for an NP */
+int  loop_chars __P((unsigned char *, int)); /* process chars from loopback */
+int  loop_frame __P((unsigned char *, int)); /* should we bring link up? */
+
+/* Procedures exported from multilink.c */
+#define mp_check_options()
+#define mp_join_bundle() (0)
+#define epdisc_to_str(a) (NULL)
+#define str_to_epdisc(a,b) (0)
+
+/* Procedures exported from sys-*.c */
+void sys_init __P((void));	/* Do system-dependent initialization */
+void sys_cleanup __P((void));	/* Restore system state before exiting */
+#define sys_check_options() (1)
+void sys_close __P((void));	/* Clean up in a child before execing */
+int  ppp_available __P((void));	/* Test whether ppp kernel support exists */
+#define get_pty(a,b,c,d) (0)
+int  open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */
+#define tty_establish_ppp(a) (-1)
+#define tty_disestablish_ppp(a)
+void generic_disestablish_ppp __P((int dev_fd)); /* Restore device setting */
+int  generic_establish_ppp __P((int dev_fd)); /* Make a ppp interface */
+#define make_new_bundle(a,b,c,d)
+#define bundle_attach(a) (0)
+#define cfg_bundle(a,b,c,d)
+void clean_check __P((void));	/* Check if line was 8-bit clean */
+#define set_up_tty(a,b)
+#define restore_tty(a)
+#define setdtr(a,b)
+void output __P((int, u_char *, int)); /* Output a PPP packet */
+void wait_input __P((struct timeval *));
+				/* Wait for input, with timeout */
+void add_fd __P((int));		/* Add fd to set to wait for */
+void remove_fd __P((int));	/* Remove fd from set to wait for */
+int  read_packet __P((u_char *)); /* Read PPP packet */
+int  get_loop_output __P((void)); /* Read pkts from loopback */
+#define tty_send_config(a,b,c,d)
+#define tty_set_xaccm(a)
+#define tty_recv_config(a,b,c,d)
+int  ccp_test __P((int, u_char *, int, int));
+				/* Test support for compression scheme */
+void ccp_flags_set __P((int, int, int));
+				/* Set kernel CCP state */
+int  ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */
+int  get_idle_time __P((int, struct ppp_idle *));
+				/* Find out how long link has been idle */
+int  get_ppp_stats __P((int, struct pppd_stats *));
+				/* Return link statistics */
+void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */
+int  sifvjcomp __P((int, int, int, int));
+				/* Configure VJ TCP header compression */
+int  sifup __P((int));		/* Configure i/f up for one protocol */
+int  sifnpmode __P((int u, int proto, enum NPmode mode));
+				/* Set mode for handling packets for proto */
+int  sifdown __P((int));	/* Configure i/f down for one protocol */
+int  sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
+				/* Configure IPv4 addresses for i/f */
+int  cifaddr __P((int, u_int32_t, u_int32_t));
+				/* Reset i/f IP addresses */
+// remove by tallest #define sifdefaultroute(a,b,c) (0)
+#define cifdefaultroute(a,b,c) (0)
+#define sifproxyarp(a,b) (0)
+#define cifproxyarp(a,b) (0)
+u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */
+#define lock(a) (0)
+#define relock(a) (0)
+#define unlock()
+#define logwtmp(a,b,c)
+int  get_host_seed __P((void));	/* Get host-dependent random number seed */
+#define have_route_to(a) (-1)
+#define get_if_hwaddr(a,b) (0)
+#define get_first_ethernet() ("eth0")
+
+/* Procedures exported from options.c */
+int  parse_args __P((int argc, char **argv));
+				/* Parse options from arguments given */
+#define options_from_file(a,b,c,d) (1)
+#define options_from_user() (1)
+#define options_for_tty() (1)
+#define options_from_list(a,b) (1)
+#define getword(a,b,c,d) (0)
+#define option_error error
+#define int_option(a,b) (1)
+#define add_options(a)
+#define check_options()
+#define remove_option(a) (0)
+#define override_value(a,b,c) (1)
+#define print_options(a,b)
+int parse_dotted_ip __P((char *, u_int32_t *));
+
+/*
+ * Hooks to enable plugins to change various things.
+ */
+extern int (*new_phase_hook) __P((int));
+extern int (*idle_time_hook) __P((struct ppp_idle *));
+extern int (*holdoff_hook) __P((void));
+extern int (*pap_check_hook) __P((void));
+extern int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp,
+				 struct wordlist **paddrs,
+				 struct wordlist **popts));
+extern void (*pap_logout_hook) __P((void));
+extern int (*pap_passwd_hook) __P((char *user, char *passwd));
+extern void (*ip_up_hook) __P((void));
+extern void (*ip_down_hook) __P((void));
+extern void (*ip_choose_hook) __P((u_int32_t *));
+
+/*
+ * Inline versions of get/put char/short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETCHAR(c, cp) { \
+	(c) = *(cp)++; \
+}
+#define PUTCHAR(c, cp) { \
+	*(cp)++ = (u_char) (c); \
+}
+
+
+#define GETSHORT(s, cp) { \
+	(s) = *(cp)++ << 8; \
+	(s) |= *(cp)++; \
+}
+#define PUTSHORT(s, cp) { \
+	*(cp)++ = (u_char) ((s) >> 8); \
+	*(cp)++ = (u_char) (s); \
+}
+
+#define GETLONG(l, cp) { \
+	(l) = *(cp)++ << 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; \
+}
+#define PUTLONG(l, cp) { \
+	*(cp)++ = (u_char) ((l) >> 24); \
+	*(cp)++ = (u_char) ((l) >> 16); \
+	*(cp)++ = (u_char) ((l) >> 8); \
+	*(cp)++ = (u_char) (l); \
+}
+
+#define INCPTR(n, cp)	((cp) += (n))
+#define DECPTR(n, cp)	((cp) -= (n))
+
+/*
+ * System dependent definitions for user-level 4.3BSD UNIX implementation.
+ */
+
+#define TIMEOUT(r, f, t)	timeout((r), (f), (t), 0)
+#define UNTIMEOUT(r, f)		untimeout((r), (f))
+
+#define BCOPY(s, d, l)		memcpy(d, s, l)
+#define BZERO(s, n)		memset(s, 0, n)
+
+#define PRINTMSG(m, l)		{ info("Remote message: %0.*v", l, m); }
+
+/*
+ * MAKEHEADER - Add Header fields to a packet.
+ */
+#define MAKEHEADER(p, t) { \
+    PUTCHAR(PPP_ALLSTATIONS, p); \
+    PUTCHAR(PPP_UI, p); \
+    PUTSHORT(t, p); }
+
+/*
+ * Exit status values.
+ */
+#define EXIT_OK			0
+#define EXIT_FATAL_ERROR	1
+#define EXIT_OPTION_ERROR	2
+#define EXIT_NOT_ROOT		3
+#define EXIT_NO_KERNEL_SUPPORT	4
+#define EXIT_USER_REQUEST	5
+#define EXIT_LOCK_FAILED	6
+#define EXIT_OPEN_FAILED	7
+#define EXIT_CONNECT_FAILED	8
+#define EXIT_PTYCMD_FAILED	9
+#define EXIT_NEGOTIATION_FAILED	10
+#define EXIT_PEER_AUTH_FAILED	11
+#define EXIT_IDLE_TIMEOUT	12
+#define EXIT_CONNECT_TIME	13
+#define EXIT_CALLBACK		14
+#define EXIT_PEER_DEAD		15
+#define EXIT_HANGUP		16
+#define EXIT_LOOPBACK		17
+#define EXIT_INIT_FAILED	18
+#define EXIT_AUTH_TOPEER_FAILED	19
+
+/*
+ * Debug macros.  Slightly useful for finding bugs in pppd, not particularly
+ * useful for finding out why your connection isn't being established.
+ */
+#ifdef DEBUGALL
+#define DEBUGMAIN	1
+#define DEBUGFSM	1
+#define DEBUGLCP	1
+#define DEBUGIPCP	1
+#define DEBUGIPV6CP	1
+#define DEBUGUPAP	1
+#define DEBUGCHAP	1
+#endif
+
+#ifndef LOG_PPP			    /* we use LOG_LOCAL2 for syslog by default */
+#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
+  || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
+  || defined(DEBUGCHAP) || defined(DEBUG) || defined(DEBUGIPV6CP)
+#define LOG_PPP LOG_LOCAL2
+#else
+#define LOG_PPP LOG_DAEMON
+#endif
+#endif /* LOG_PPP */
+
+#ifdef DEBUGMAIN
+#define MAINDEBUG(x)	if (debug) dbglog x
+#else
+#define MAINDEBUG(x)
+#endif
+
+#ifdef DEBUGSYS
+#define SYSDEBUG(x)	if (debug) dbglog x
+#else
+#define SYSDEBUG(x)
+#endif
+
+#ifdef DEBUGFSM
+#define FSMDEBUG(x)	if (debug) dbglog x
+#else
+#define FSMDEBUG(x)
+#endif
+
+#ifdef DEBUGLCP
+#define LCPDEBUG(x)	if (debug) dbglog x
+#else
+#define LCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPCP
+#define IPCPDEBUG(x)	if (debug) dbglog x
+#else
+#define IPCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPV6CP
+#define IPV6CPDEBUG(x)  if (debug) dbglog x
+#else
+#define IPV6CPDEBUG(x)
+#endif
+
+#ifdef DEBUGUPAP
+#define UPAPDEBUG(x)	if (debug) dbglog x
+#else
+#define UPAPDEBUG(x)
+#endif
+
+#ifdef DEBUGCHAP
+#define CHAPDEBUG(x)	if (debug) dbglog x
+#else
+#define CHAPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPXCP
+#define IPXCPDEBUG(x)	if (debug) dbglog x
+#else
+#define IPXCPDEBUG(x)
+#endif
+
+#ifndef SIGTYPE
+#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
+#define SIGTYPE void
+#else
+#define SIGTYPE int
+#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
+#endif /* SIGTYPE */
+
+#ifndef MIN
+#define MIN(a, b)	((a) < (b)? (a): (b))
+#endif
+#ifndef MAX
+#define MAX(a, b)	((a) > (b)? (a): (b))
+#endif
+
+#endif /* __PPP_H__ */
+
+extern int log_to_file(char *buf);
+extern int my_gettimeofday(struct timeval *timenow, struct timezone *tz);
diff --git a/ap/app/ppp-2.4.1/pppoecd/pppoe.h b/ap/app/ppp-2.4.1/pppoecd/pppoe.h
new file mode 100755
index 0000000..6b6b7fd
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/pppoe.h
@@ -0,0 +1,133 @@
+#ifndef PPPOE_H
+#define PPPOE_H
+#include <stdio.h>		
+#include <stdlib.h>		
+#include <unistd.h>		
+#include <string.h>		
+#include <errno.h>		
+#include <signal.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <paths.h>
+#include <sys/types.h>		
+#include <asm/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>		
+#include <sys/select.h>
+#include <sys/socket.h>		
+#include <net/if.h>		
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#include <asm/byteorder.h>
+#include <linux/if_pppox.h>
+#include "pppd.h"
+
+#define MAX_PAYLOAD 1484
+#define TAG_RELAY_SID	5
+#define TAG_SRV_ERR     6
+#define _STR(x) #x
+#define TAG_GEN_ERR  	8
+#define TAG_EOL		9
+#define TAG_SYS_ERR  	7
+#define TAG_SRV_NAME	0
+#define TAG_AC_NAME	1
+#define MAX_TAGS		11
+#define TAG_HOST_UNIQ	2
+#define FMTSTRING(size) "%x:%x:%x:%x:%x:%x/%x/%" _STR(size) "s"
+#define TAG_AC_COOKIE	3
+#define TAG_VENDOR 	4
+
+struct pppoe_packet{
+	struct sockaddr_ll addr;
+	struct pppoe_tag *tags[MAX_TAGS];
+	struct pppoe_hdr *hdr;
+	char buf[MAX_PAYLOAD];		/* buffer in which tags are held */
+};
+
+
+static int tag_map[] = { PTT_SRV_NAME,
+			 PTT_AC_NAME,
+			 PTT_HOST_UNIQ,
+			 PTT_AC_COOKIE,
+			 PTT_VENDOR,
+			 PTT_RELAY_SID,
+			 PTT_SRV_ERR,
+			 PTT_SYS_ERR,
+			 PTT_GEN_ERR,
+			 PTT_EOL
+};
+
+struct session;
+
+typedef int (*packet_cb_t)(struct session* ses,
+			   struct pppoe_packet *p_in,
+			   struct pppoe_packet **p_out);
+
+struct filter {
+	struct pppoe_tag *stag;  
+	struct pppoe_tag *ntag;  
+	struct pppoe_tag *htag;  
+	int num_restart;
+	int peermode;
+	char *fname;
+	char *pppd;
+} __attribute__ ((packed));
+
+
+struct pppoe_tag *make_filter_tag(short type, short length, char* data);
+
+struct session {
+	int type;
+	int opt_debug;
+	int detached;
+	int np;
+	int log_to_fd;
+	int ifindex;			
+	char name[IFNAMSIZ];	
+	struct pppoe_packet curr_pkt;
+	packet_cb_t init_disc;
+	packet_cb_t rcv_pado;
+	packet_cb_t rcv_padi;
+	packet_cb_t rcv_pads;
+	packet_cb_t rcv_padr;
+	packet_cb_t rcv_padt;
+	packet_cb_t timeout;
+	struct filter *filt;
+	struct sockaddr_ll local;
+	struct sockaddr_ll remote;
+	struct sockaddr_pppox sp;
+	int fd;	
+	int retransmits;
+	int retries;
+	int state;
+	int opt_daemonize;
+	int fork;
+	int fwd_sock;
+	char fwd_name[IFNAMSIZ];
+} __attribute__ ((packed));
+extern int session_connect(struct session *ses);
+extern int session_disconnect(struct session*ses);
+
+
+#define poe_dbglog(a,b...)
+#define poe_info(a,b...)
+#define poe_notice(a,b...)
+extern void copy_tag(struct pppoe_packet *dest, struct pppoe_tag *pt);
+extern struct pppoe_tag *get_tag(struct pppoe_hdr *ph, u_int16_t idx);
+#define poe_warn(a,b...)
+#define poe_error(a,b...)
+#define poe_fatal(a,b...)
+extern int get_sockaddr_ll(const char *devnam,struct sockaddr_ll* sll);
+extern int client_init_ses (struct session *ses, char* devnam);
+int log_to_fd;
+
+extern int verify_packet( struct session *ses, struct pppoe_packet *p);
+extern int send_disc(struct session *ses, struct pppoe_packet *p);
+
+#endif
diff --git a/ap/app/ppp-2.4.1/pppoecd/sys-linux.c b/ap/app/ppp-2.4.1/pppoecd/sys-linux.c
new file mode 100644
index 0000000..b18db0f
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/sys-linux.c
@@ -0,0 +1,1343 @@
+/*
+ * sys-linux.c - System-dependent procedures for setting up
+ * PPP interfaces on Linux systems
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/sysmacros.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <time.h>
+#include <memory.h>
+#include <utmp.h>
+#include <mntent.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* This is in netdevice.h. However, this compile will fail miserably if
+   you attempt to include netdevice.h because it has so many references
+   to __memcpy functions which it should not attempt to do. So, since I
+   really don't use it, but it must be defined, define it now. */
+
+#ifndef MAX_ADDR_LEN
+#define MAX_ADDR_LEN 7
+#endif
+
+#if __GLIBC__ >= 2
+#include <asm/types.h>		/* glibc 2 conflicts with linux/types.h */
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/if_ether.h>
+#else
+#include <linux/types.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/route.h>
+#include <linux/if_ether.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipcp.h"
+
+/* We can get an EIO error on an ioctl if the modem has hung up */
+#define ok_error(num) ((num)==EIO)
+
+static int tty_disc = N_TTY;	/* The TTY discipline */
+static int ppp_disc = N_PPP;	/* The PPP discpline */
+static int initfdflags = -1;	/* Initial file descriptor flags for fd */
+static int ppp_fd = -1;		/* fd which is set to PPP discipline */
+static int sock_fd = -1;	/* socket for doing interface ioctls */
+static int slave_fd = -1;
+static int master_fd = -1;
+static int ppp_dev_fd = -1;	/* fd for /dev/ppp (new style driver) */
+static int chindex;		/* channel index (new style driver) */
+
+static fd_set in_fds;		/* set of fds that wait_input waits for */
+static int max_in_fd;		/* highest fd set in in_fds */
+
+static int driver_version      = 0;
+static int driver_modification = 0;
+static int driver_patch        = 0;
+
+static char loop_name[20];
+static unsigned char inbuf[512]; /* buffer for chars read from loopback */
+
+static int	if_is_up;	/* Interface has been marked up */
+static u_int32_t our_old_addr;		/* for detecting address changes */
+static int	dynaddr_set;		/* 1 if ip_dynaddr set */
+static int	looped;			/* 1 if using loop */
+
+static int kernel_version;
+#define KVERSION(j,n,p)	((j)*1000000 + (n)*1000 + (p))
+
+#define MAX_IFS		100
+
+#define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
+#define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
+		    IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
+
+#define SIN_ADDR(x)	(((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
+
+/* Prototypes for procedures local to this file. */
+static int get_flags (int fd);
+static void set_flags (int fd, int flags);
+static int make_ppp_unit(void);
+static void restore_loop(void);	/* Transfer ppp unit back to loopback */
+
+extern u_char	inpacket_buf[];	/* borrowed from main.c */
+
+/*
+ * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
+ * if it exists.
+ */
+
+#define SET_SA_FAMILY(addr, family)			\
+    memset ((char *) &(addr), '\0', sizeof(addr));	\
+    addr.sa_family = (family);
+
+/*
+ * Determine if the PPP connection should still be present.
+ */
+
+extern int hungup;
+
+/* new_fd is the fd of a tty */
+static void set_ppp_fd (int new_fd)
+{
+	SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
+	ppp_fd = new_fd;
+	if (!new_style_driver)
+		ppp_dev_fd = new_fd;
+}
+
+static int still_ppp(void)
+{
+	if (new_style_driver)
+		return !hungup && ppp_fd >= 0;
+	if (!hungup || ppp_fd == slave_fd)
+		return 1;
+	if (slave_fd >= 0) {
+		set_ppp_fd(slave_fd);
+		return 1;
+	}
+	return 0;
+}
+
+/********************************************************************
+ *
+ * Functions to read and set the flags value in the device driver
+ */
+
+static int get_flags (int fd)
+{
+    int flags;
+
+    if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
+	if ( ok_error (errno) )
+	    flags = 0;
+	else
+	    fatal("ioctl(PPPIOCGFLAGS): %m");
+    }
+
+    SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
+    return flags;
+}
+
+/********************************************************************/
+
+static void set_flags (int fd, int flags)
+{
+    SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
+
+    if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) {
+	if (! ok_error (errno) )
+	    fatal("ioctl(PPPIOCSFLAGS, %x): %m", flags, errno);
+    }
+}
+
+/********************************************************************
+ *
+ * sys_init - System-dependent initialization.
+ */
+
+void sys_init(void)
+{
+    int flags;
+
+    if (new_style_driver) {
+	ppp_dev_fd = open("/dev/ppp", O_RDWR);
+	if (ppp_dev_fd < 0)
+	    fatal("Couldn't open /dev/ppp: %m");
+	flags = fcntl(ppp_dev_fd, F_GETFL);
+	if (flags == -1
+	    || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+	    warn("Couldn't set /dev/ppp to nonblock: %m");
+    }
+
+    /* Get an internet socket for doing socket ioctls. */
+    sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock_fd < 0)
+	fatal("Couldn't create IP socket: %m(%d)", errno);
+
+    FD_ZERO(&in_fds);
+    max_in_fd = 0;
+}
+
+/********************************************************************
+ *
+ * sys_cleanup - restore any system state we modified before exiting:
+ * mark the interface down, delete default route and/or proxy arp entry.
+ * This shouldn't call die() because it's called from die().
+ */
+
+void sys_cleanup(void)
+{
+/*
+ * Take down the device
+ */
+    if (if_is_up) {
+	if_is_up = 0;
+	sifdown(0);
+    }
+}
+
+/********************************************************************
+ *
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close(void)
+{
+	close(ppp_dev_fd);
+    if (sock_fd >= 0)
+	close(sock_fd);
+    if (slave_fd >= 0)
+	close(slave_fd);
+    if (master_fd >= 0)
+	close(master_fd);
+    closelog();
+}
+
+/********************************************************************
+ *
+ * set_kdebugflag - Define the debugging level for the kernel
+ */
+
+static int set_kdebugflag (int requested_level)
+{
+    if (new_style_driver && ifunit < 0)
+	return 1;
+    if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
+	if ( ! ok_error (errno) )
+	    error("ioctl(PPPIOCSDEBUG): %m");
+	return (0);
+    }
+    SYSDEBUG ((LOG_INFO, "set kernel debugging level to %d",
+		requested_level));
+    return (1);
+}
+
+
+/********************************************************************
+ *
+ * generic_establish_ppp - Turn the fd into a ppp interface.
+ */
+int generic_establish_ppp (int fd)
+{
+    int x;
+/*
+ * Demand mode - prime the old ppp device to relinquish the unit.
+ */
+    if (!new_style_driver && looped
+	&& ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
+	error("ioctl(transfer ppp unit): %m");
+	return -1;
+    }
+
+
+    if (new_style_driver) {
+	/* Open another instance of /dev/ppp and connect the channel to it */
+	int flags;
+
+	if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
+	    error("Couldn't get channel number: %m");
+	    goto err;
+	}
+	dbglog("using channel %d", chindex);
+	fd = open("/dev/ppp", O_RDWR);
+	if (fd < 0) {
+	    error("Couldn't reopen /dev/ppp: %m");
+	    goto err;
+	}
+	if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
+	    error("Couldn't attach to channel %d: %m", chindex);
+	    goto err_close;
+	}
+	flags = fcntl(fd, F_GETFL);
+	if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
+	    warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
+	set_ppp_fd(fd);
+
+	if (!looped)
+	    ifunit = -1;
+	if (!looped && !multilink) {
+	    /*
+	     * Create a new PPP unit.
+	     */
+	    if (make_ppp_unit() < 0)
+		goto err_close;
+	}
+
+	if (looped)
+	    set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC);
+
+	if (!multilink) {
+	    add_fd(ppp_dev_fd);
+	    if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
+		error("Couldn't attach to PPP unit %d: %m", ifunit);
+		goto err_close;
+	    }
+	}
+
+    } else {
+
+	/*
+	 * Old-style driver: find out which interface we were given.
+	 */
+	set_ppp_fd (fd);
+	if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
+	    if (ok_error (errno))
+		goto err;
+	    fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
+	}
+	/* Check that we got the same unit again. */
+	if (looped && x != ifunit)
+	    fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
+	ifunit = x;
+
+	/*
+	 * Fetch the initial file flags and reset blocking mode on the file.
+	 */
+	initfdflags = fcntl(fd, F_GETFL);
+	if (initfdflags == -1 ||
+	    fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
+	    if ( ! ok_error (errno))
+		warn("Couldn't set device to non-blocking mode: %m");
+	}
+    }
+
+
+    /*
+     * Enable debug in the driver if requested.
+     */
+    if (!looped)
+	set_kdebugflag (kdebugflag);
+
+    SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
+	    driver_version, driver_modification, driver_patch));
+
+    return ppp_fd;
+
+ err_close:
+    close(fd);
+ err:
+    if (ioctl(fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
+	warn("Couldn't reset tty to normal line discipline: %m");
+    return -1;
+}
+
+/********************************************************************
+ *
+ * generic_disestablish_ppp - Restore device components to normal
+ * operation, and reconnect the ppp unit to the loopback if in demand
+ * mode.  This shouldn't call die() because it's called from die().
+*/
+void generic_disestablish_ppp(int dev_fd){
+    /* Restore loop if needed */
+    if(demand)
+	restore_loop();
+
+    /* Finally detach the device */
+    initfdflags = -1;
+
+    if (new_style_driver) {
+	close(ppp_fd);
+	ppp_fd = -1;
+	if (!looped && ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0)
+	    error("Couldn't release PPP unit: %m");
+	if (!multilink)
+	    remove_fd(ppp_dev_fd);
+    }
+}
+
+/*
+ * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
+ * Assumes new_style_driver.
+ */
+static int make_ppp_unit()
+{
+	int x;
+
+	ifunit = req_unit;
+	x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
+	if (x < 0 && req_unit >= 0 && errno == EEXIST) {
+		warn("Couldn't allocate PPP unit %d as it is already in use");
+		ifunit = -1;
+		x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
+	}
+	if (x < 0)
+		error("Couldn't create new ppp unit: %m");
+	return x;
+}
+
+/********************************************************************
+ *
+ * clean_check - Fetch the flags for the device and generate
+ * appropriate error messages.
+ */
+void clean_check(void)
+{
+    int x;
+    char *s;
+
+    if (still_ppp()) {
+	if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
+	    s = NULL;
+	    switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
+	    case SC_RCV_B7_0:
+		s = "all had bit 7 set to 1";
+		break;
+
+	    case SC_RCV_B7_1:
+		s = "all had bit 7 set to 0";
+		break;
+
+	    case SC_RCV_EVNP:
+		s = "all had odd parity";
+		break;
+
+	    case SC_RCV_ODDP:
+		s = "all had even parity";
+		break;
+	    }
+
+	    if (s != NULL) {
+		warn("Receive serial link is not 8-bit clean:");
+		warn("Problem: %s", s);
+	    }
+	}
+    }
+}
+
+/********************************************************************
+ *
+ * output - Output PPP packet.
+ */
+
+void output (int unit, unsigned char *p, int len)
+{
+    int fd = ppp_fd;
+    int proto;
+
+    if (debug)
+	dbglog("sent %P", p, len);
+
+    if (len < PPP_HDRLEN)
+	return;
+    if (new_style_driver) {
+	p += 2;
+	len -= 2;
+	proto = (p[0] << 8) + p[1];
+	if (ifunit >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
+	    fd = ppp_dev_fd;
+    }
+    if (write(fd, p, len) < 0) {
+	if (errno == EWOULDBLOCK || errno == ENOBUFS
+	    || errno == ENXIO || errno == EIO || errno == EINTR)
+	    warn("write: warning: %m (%d)", errno);
+	else
+	    error("write: %m (%d)", errno);
+    }
+}
+
+/********************************************************************
+ *
+ * wait_input - wait until there is data available,
+ * for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+
+void wait_input(struct timeval *timo)
+{
+    fd_set ready, exc;
+    int n;
+
+    ready = in_fds;
+    exc = in_fds;
+    n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
+    if (n < 0 && errno != EINTR)
+	fatal("select: %m(%d)", errno);
+}
+
+/*
+ * add_fd - add an fd to the set that wait_input waits for.
+ */
+void add_fd(int fd)
+{
+    FD_SET(fd, &in_fds);
+    if (fd > max_in_fd)
+	max_in_fd = fd;
+}
+
+/*
+ * remove_fd - remove an fd from the set that wait_input waits for.
+ */
+void remove_fd(int fd)
+{
+    FD_CLR(fd, &in_fds);
+}
+
+
+/********************************************************************
+ *
+ * read_packet - get a PPP packet from the serial device.
+ */
+
+int read_packet (unsigned char *buf)
+{
+    int len, nr;
+
+    len = PPP_MRU + PPP_HDRLEN;
+    if (new_style_driver) {
+	*buf++ = PPP_ALLSTATIONS;
+	*buf++ = PPP_UI;
+	len -= 2;
+    }
+    nr = -1;
+    if (ppp_fd >= 0) {
+	nr = read(ppp_fd, buf, len);
+	if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
+	    error("read: %m");
+	if (nr < 0 && errno == ENXIO)
+	    return 0;
+    }
+    if (nr < 0 && new_style_driver && ifunit >= 0) {
+	/* N.B. we read ppp_fd first since LCP packets come in there. */
+	nr = read(ppp_dev_fd, buf, len);
+	if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
+	    error("read /dev/ppp: %m");
+	if (nr < 0 && errno == ENXIO)
+	    return 0;
+    }
+    return (new_style_driver && nr > 0)? nr+2: nr;
+}
+
+/********************************************************************
+ *
+ * get_loop_output - get outgoing packets from the ppp device,
+ * and detect when we want to bring the real link up.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+get_loop_output(void)
+{
+    int rv = 0;
+    int n;
+
+    if (new_style_driver) {
+	while ((n = read_packet(inpacket_buf)) > 0)
+	    if (loop_frame(inpacket_buf, n))
+		rv = 1;
+	return rv;
+    }
+
+    while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
+	if (loop_chars(inbuf, n))
+	    rv = 1;
+
+    if (n == 0)
+	fatal("eof on loopback");
+
+    if (errno != EWOULDBLOCK)
+	fatal("read from loopback: %m(%d)", errno);
+
+    return rv;
+}
+
+/*
+ * netif_set_mtu - set the MTU on the PPP network interface.
+ */
+void
+netif_set_mtu(int unit, int mtu)
+{
+    struct ifreq ifr;
+
+    SYSDEBUG ((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
+
+    memset (&ifr, '\0', sizeof (ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    ifr.ifr_mtu = mtu;
+
+    if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+	fatal("ioctl(SIOCSIFMTU): %m");
+}
+
+/********************************************************************
+ *
+ * ccp_test - ask kernel whether a given compression method
+ * is acceptable for use.
+ */
+
+int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
+{
+    struct ppp_option_data data;
+
+    memset (&data, '\0', sizeof (data));
+    data.ptr      = opt_ptr;
+    data.length   = opt_len;
+    data.transmit = for_transmit;
+
+    if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
+	return 1;
+
+    return (errno == ENOBUFS)? 0: -1;
+}
+
+/********************************************************************
+ *
+ * ccp_flags_set - inform kernel about the current state of CCP.
+ */
+
+void ccp_flags_set (int unit, int isopen, int isup)
+{
+    if (still_ppp()) {
+	int x = get_flags(ppp_dev_fd);
+	x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
+	x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
+	set_flags (ppp_dev_fd, x);
+    }
+}
+
+/********************************************************************
+ *
+ * get_idle_time - return how long the link has been idle.
+ */
+int
+get_idle_time(u, ip)
+    int u;
+    struct ppp_idle *ip;
+{
+    return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
+}
+
+/********************************************************************
+ *
+ * get_ppp_stats - return statistics for the link.
+ */
+int
+get_ppp_stats(u, stats)
+    int u;
+    struct pppd_stats *stats;
+{
+    struct ifpppstatsreq req;
+
+    memset (&req, 0, sizeof (req));
+
+    req.stats_ptr = (caddr_t) &req.stats;
+    strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
+    if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
+	error("Couldn't get PPP statistics: %m");
+	return 0;
+    }
+    stats->bytes_in = req.stats.p.ppp_ibytes;
+    stats->bytes_out = req.stats.p.ppp_obytes;
+    return 1;
+}
+
+/********************************************************************
+ *
+ * ccp_fatal_error - returns 1 if decompression was disabled as a
+ * result of an error detected after decompression of a packet,
+ * 0 otherwise.  This is necessary because of patent nonsense.
+ */
+
+int ccp_fatal_error (int unit)
+{
+    int x = get_flags(ppp_dev_fd);
+
+    return x & SC_DC_FERROR;
+}
+
+/********************************************************************
+ *
+ * Return user specified netmask, modified by any mask we might determine
+ * for address `addr' (in network byte order).
+ * Here we scan through the system's list of interfaces, looking for
+ * any non-point-to-point interfaces which might appear to be on the same
+ * network as `addr'.  If we find any, we OR in their netmask to the
+ * user-specified netmask.
+ */
+
+u_int32_t GetMask (u_int32_t addr)
+{
+    u_int32_t mask, nmask, ina;
+    struct ifreq *ifr, *ifend, ifreq;
+    struct ifconf ifc;
+    struct ifreq ifs[MAX_IFS];
+
+    addr = ntohl(addr);
+
+    if (IN_CLASSA(addr))	/* determine network mask for address class */
+	nmask = IN_CLASSA_NET;
+    else if (IN_CLASSB(addr))
+	    nmask = IN_CLASSB_NET;
+    else
+	    nmask = IN_CLASSC_NET;
+
+    /* class D nets are disallowed by bad_ip_adrs */
+    mask = netmask | htonl(nmask);
+/*
+ * Scan through the system's network interfaces.
+ */
+    ifc.ifc_len = sizeof(ifs);
+    ifc.ifc_req = ifs;
+    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
+	if ( ! ok_error ( errno ))
+	    warn("ioctl(SIOCGIFCONF): %m(%d)", errno);
+	return mask;
+    }
+
+    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
+/*
+ * Check the interface's internet address.
+ */
+	if (ifr->ifr_addr.sa_family != AF_INET)
+	    continue;
+	ina = SIN_ADDR(ifr->ifr_addr);
+	if (((ntohl(ina) ^ addr) & nmask) != 0)
+	    continue;
+/*
+ * Check that the interface is up, and not point-to-point nor loopback.
+ */
+	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
+	    continue;
+
+	if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
+	    continue;
+/*
+ * Get its netmask and OR it into our mask.
+ */
+	if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
+	    continue;
+	mask |= SIN_ADDR(ifreq.ifr_addr);
+	break;
+    }
+    return mask;
+}
+
+/********************************************************************
+ *
+ * ppp_available - check whether the system has any ppp interfaces
+ * (in fact we check whether we can do an ioctl on ppp0).
+ */
+
+int ppp_available(void)
+{
+    struct utsname utsname;	/* for the kernel version */
+    int osmaj, osmin, ospatch;
+
+    /* get the kernel version now, since we are called before sys_init */
+    uname(&utsname);
+    osmaj = osmin = ospatch = 0;
+    sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
+    kernel_version = KVERSION(osmaj, osmin, ospatch);
+
+    driver_version = 2;
+    driver_modification = 4;
+    driver_patch = 0;
+
+    return 1;
+}
+
+/********************************************************************
+ *
+ * sifvjcomp - config tcp header compression
+ */
+
+int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
+{
+    u_int x = get_flags(ppp_dev_fd);
+
+    if (vjcomp) {
+        if (ioctl (ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
+	    if (! ok_error (errno))
+		error("ioctl(PPPIOCSMAXCID): %m(%d)", errno);
+	    vjcomp = 0;
+	}
+    }
+
+    x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
+    x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
+    set_flags (ppp_dev_fd, x);
+
+    return 1;
+}
+
+/********************************************************************
+ *
+ * sifup - Config the interface up and enable IP packets to pass.
+ */
+
+int sifup(int u)
+{
+    struct ifreq ifr;
+
+    memset (&ifr, '\0', sizeof (ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
+	return 0;
+    }
+
+    ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
+    if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
+	return 0;
+    }
+    if_is_up++;
+
+    return 1;
+}
+
+/********************************************************************
+ *
+ * sifdown - Disable the indicated protocol and config the interface
+ *	     down if there are no remaining protocols.
+ */
+
+int sifdown (int u)
+{
+    struct ifreq ifr;
+
+    if (if_is_up && --if_is_up > 0)
+	return 1;
+
+    memset (&ifr, '\0', sizeof (ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
+	return 0;
+    }
+
+    ifr.ifr_flags &= ~IFF_UP;
+    ifr.ifr_flags |= IFF_POINTOPOINT;
+    if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
+	return 0;
+    }
+    return 1;
+}
+
+/********************************************************************
+ *
+ * sifaddr - Config the interface IP addresses and netmask.
+ */
+
+int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
+	     u_int32_t net_mask)
+{
+    struct ifreq   ifr;
+    struct rtentry rt;
+
+    memset (&ifr, '\0', sizeof (ifr));
+    memset (&rt,  '\0', sizeof (rt));
+
+    SET_SA_FAMILY (ifr.ifr_addr,    AF_INET);
+    SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
+    SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
+
+    strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+/*
+ *  Set our IP address
+ */
+    SIN_ADDR(ifr.ifr_addr) = our_adr;
+    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+	if (errno != EEXIST) {
+	    if (! ok_error (errno))
+		error("ioctl(SIOCSIFADDR): %m(%d)", errno);
+	}
+        else {
+	    warn("ioctl(SIOCSIFADDR): Address already exists");
+	}
+        return (0);
+    }
+/*
+ *  Set the gateway address
+ */
+    SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
+    if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl(SIOCSIFDSTADDR): %m(%d)", errno);
+	return (0);
+    }
+/*
+ *  Set the netmask.
+ *  For recent kernels, force the netmask to 255.255.255.255.
+ */
+    if (kernel_version >= KVERSION(2,1,16))
+	net_mask = ~0L;
+    if (net_mask != 0) {
+	SIN_ADDR(ifr.ifr_netmask) = net_mask;
+	if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
+	    if (! ok_error (errno))
+		error("ioctl(SIOCSIFNETMASK): %m(%d)", errno);
+	    return (0);
+	}
+    }
+/*
+ *  Add the device route
+ */
+    if (kernel_version < KVERSION(2,1,16)) {
+	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
+	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+	rt.rt_dev = ifname;
+
+	SIN_ADDR(rt.rt_gateway) = 0L;
+	SIN_ADDR(rt.rt_dst)     = his_adr;
+	rt.rt_flags = RTF_UP | RTF_HOST;
+
+	if (kernel_version > KVERSION(2,1,0)) {
+	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+	    SIN_ADDR(rt.rt_genmask) = -1L;
+	}
+
+	if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
+	    if (! ok_error (errno))
+		error("ioctl(SIOCADDRT) device route: %m(%d)", errno);
+	    return (0);
+	}
+    }
+
+    /* set ip_dynaddr in demand mode if address changes */
+    if (demand && tune_kernel && !dynaddr_set
+	&& our_old_addr && our_old_addr != our_adr) {
+	/* set ip_dynaddr if possible */
+	char *path;
+	int fd;
+
+	path = "/proc/sys/net/ipv4/ip_dynaddr";
+	if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
+	    if (write(fd, "1", 1) != 1)
+		error("Couldn't enable dynamic IP addressing: %m");
+	    close(fd);
+	}
+	dynaddr_set = 1;	/* only 1 attempt */
+    }
+    our_old_addr = 0;
+
+    return 1;
+}
+
+/********************************************************************
+ *
+ * cifaddr - Clear the interface IP addresses, and delete routes
+ * through the interface if possible.
+ */
+
+int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
+{
+    struct ifreq ifr;
+
+    if (kernel_version < KVERSION(2,1,16)) {
+/*
+ *  Delete the route through the device
+ */
+	struct rtentry rt;
+	memset (&rt, '\0', sizeof (rt));
+
+	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
+	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+	rt.rt_dev = ifname;
+
+	SIN_ADDR(rt.rt_gateway) = 0;
+	SIN_ADDR(rt.rt_dst)     = his_adr;
+	rt.rt_flags = RTF_UP | RTF_HOST;
+
+	if (kernel_version > KVERSION(2,1,0)) {
+	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+	    SIN_ADDR(rt.rt_genmask) = -1L;
+	}
+
+	if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
+	    if (still_ppp() && ! ok_error (errno))
+		error("ioctl(SIOCDELRT) device route: %m(%d)", errno);
+	    return (0);
+	}
+    }
+
+    /* This way it is possible to have an IPX-only or IPv6-only interface */
+    memset(&ifr, 0, sizeof(ifr));
+    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+	if (! ok_error (errno)) {
+	    error("ioctl(SIOCSIFADDR): %m(%d)", errno);
+	    return 0;
+	}
+    }
+
+    our_old_addr = our_adr;
+
+    return 1;
+}
+
+//===================================================================
+
+#if 1
+/*
+ * /proc/net/route parsing stuff.
+ */
+
+#define ROUTE_MAX_COLS  12
+FILE *route_fd = (FILE *) 0;
+static char route_buffer[512];
+static int route_dev_col, route_dest_col, route_gw_col;
+static int route_flags_col, route_mask_col;
+static int route_num_cols;
+                                                                                                                             
+static int open_route_table (void);
+static void close_route_table (void);
+static int read_route_table (struct rtentry *rt);
+static char route_delims[] = " \t\n";
+
+/********************************************************************
+ *
+ * close_route_table - close the interface to the route table
+ */
+// copy from pppd/sys-linux.c by tallest                                                                                     
+static void close_route_table (void)
+{
+    if (route_fd != (FILE *) 0) {
+        fclose (route_fd);
+        route_fd = (FILE *) 0;
+    }
+}
+
+/********************************************************************
+ *
+ * read_route_table - read the next entry from the route table
+ */
+// copy from pppd/sys-linux.c by tallest
+static int read_route_table(struct rtentry *rt)
+{
+    char *cols[ROUTE_MAX_COLS], *p;
+    int col;
+                                                                                                                             
+    memset (rt, '\0', sizeof (struct rtentry));
+                                                                                                                             
+    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
+        return 0;
+                                                                                                                             
+    p = route_buffer;
+    for (col = 0; col < route_num_cols; ++col) {
+        cols[col] = strtok(p, route_delims);
+        if (cols[col] == NULL)
+            return 0;           /* didn't get enough columns */
+        p = NULL;
+    }
+                                                                                                                             
+    SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
+    SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
+    SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
+                                                                                                                             
+    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
+    rt->rt_dev   = cols[route_dev_col];
+                                                                                                                             
+    return 1;
+}
+
+/********************************************************************
+ *
+ * open_route_table - open the interface to the route table
+ */
+// copy from pppd/sys-linux.c by tallest
+                                                                                                                             
+static int open_route_table (void)
+{
+    char *path;
+                                                                                                                             
+    close_route_table();
+                                                                                                                             
+    //path = path_to_procfs("/net/route");
+    //route_fd = fopen (path, "r");
+    route_fd = fopen ("proc/net/route", "r");
+    if (route_fd == NULL) {
+        error("can't open routing table");
+        return 0;
+    }
+                                                                                                                             
+    route_dev_col = 0;          /* default to usual columns */
+    route_dest_col = 1;
+    route_gw_col = 2;
+    route_flags_col = 3;
+    route_mask_col = 7;
+    route_num_cols = 8;
+                                                                                                                             
+    /* parse header line */
+    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
+        char *p = route_buffer, *q;
+        int col;
+        for (col = 0; col < ROUTE_MAX_COLS; ++col) {
+            int used = 1;
+            if ((q = strtok(p, route_delims)) == 0)
+                break;
+            if (strcasecmp(q, "iface") == 0)
+                route_dev_col = col;
+            else if (strcasecmp(q, "destination") == 0)
+                route_dest_col = col;
+            else if (strcasecmp(q, "gateway") == 0)
+                route_gw_col = col;
+            else if (strcasecmp(q, "flags") == 0)
+                route_mask_col = col;
+            else
+                used = 0;
+            if (used && col >= route_num_cols)
+                route_num_cols = col + 1;
+            p = NULL;
+        }
+    }
+                                                                                                                             
+    return 1;
+}
+
+/********************************************************************
+ *
+ * defaultroute_exists - determine if there is a default route
+ */
+// copy from pppd/sys-linux.c by tallest
+static int defaultroute_exists (struct rtentry *rt)
+{
+    int result = 0;
+                                                                                                                             
+    if (!open_route_table())
+        return 0;
+                                                                                                                             
+    while (read_route_table(rt) != 0) {
+        if ((rt->rt_flags & RTF_UP) == 0)
+            continue;
+                                                                                                                             
+        if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
+            continue;
+        if (SIN_ADDR(rt->rt_dst) == 0L) {
+            result = 1;
+            break;
+        }
+    }
+                                                                                                                             
+    close_route_table();
+    return result;
+}
+
+/********************************************************************
+ *
+ * sifdefaultroute - assign a default route through the address given.
+ */
+// copy from pppd/sys_linux.c by tallest                                                                            
+int 
+sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
+{
+    struct rtentry rt;
+                                                                                                                             
+    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
+        u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
+                                                                                                                             
+        if (old_gateway != gateway)
+            error("not replacing existing default route to %s [%I]",
+                  rt.rt_dev, old_gateway);
+        return 0;
+    }
+                                                                                                                             
+    memset (&rt, '\0', sizeof (rt));
+    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
+    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+                                                                                                                             
+    if (kernel_version > KVERSION(2,1,0)) {
+        SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+        SIN_ADDR(rt.rt_genmask) = 0L;
+    }
+                                                                                                                             
+    SIN_ADDR(rt.rt_gateway) = gateway;
+                                                                                                                             
+    rt.rt_flags = RTF_UP | RTF_GATEWAY;
+    if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
+        if ( ! ok_error ( errno ))
+            error("default route ioctl(SIOCADDRT): %m(%d)", errno);
+        return 0;
+    }
+                                                                                                                             
+    //default_route_gateway = gateway;
+    return 1;
+}
+#endif
+//===================================================================
+
+
+/********************************************************************
+ *
+ * open_loopback - open the device we use for getting packets
+ * in demand mode.  Under Linux, we use a pty master/slave pair.
+ */
+int
+open_ppp_loopback(void)
+{
+    int flags;
+
+    looped = 1;
+    if (new_style_driver) {
+	/* allocate ourselves a ppp unit */
+	if (make_ppp_unit() < 0)
+	    die(1);
+	set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC);
+	set_kdebugflag(kdebugflag);
+	ppp_fd = -1;
+	return ppp_dev_fd;
+    }
+
+    if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
+	fatal("No free pty for loopback");
+    SYSDEBUG(("using %s for loopback", loop_name));
+
+    set_ppp_fd(slave_fd);
+
+    flags = fcntl(master_fd, F_GETFL);
+    if (flags == -1 ||
+	fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+	warn("couldn't set master loopback to nonblock: %m(%d)", errno);
+
+    flags = fcntl(ppp_fd, F_GETFL);
+    if (flags == -1 ||
+	fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+	warn("couldn't set slave loopback to nonblock: %m(%d)", errno);
+
+    if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
+	fatal("ioctl(TIOCSETD): %m(%d)", errno);
+/*
+ * Find out which interface we were given.
+ */
+    if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
+	fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
+/*
+ * Enable debug in the driver if requested.
+ */
+    set_kdebugflag (kdebugflag);
+
+    return master_fd;
+}
+
+/********************************************************************
+ *
+ * restore_loop - reattach the ppp unit to the loopback.
+ *
+ * The kernel ppp driver automatically reattaches the ppp unit to
+ * the loopback if the serial port is set to a line discipline other
+ * than ppp, or if it detects a modem hangup.  The former will happen
+ * in disestablish_ppp if the latter hasn't already happened, so we
+ * shouldn't need to do anything.
+ *
+ * Just to be sure, set the real serial port to the normal discipline.
+ */
+
+void
+restore_loop(void)
+{
+    looped = 1;
+    if (new_style_driver) {
+	set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC);
+	return;
+    }
+    if (ppp_fd != slave_fd) {
+	(void) ioctl(ppp_fd, TIOCSETD, &tty_disc);
+	set_ppp_fd(slave_fd);
+    }
+}
+
+/********************************************************************
+ *
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+
+int
+sifnpmode(u, proto, mode)
+    int u;
+    int proto;
+    enum NPmode mode;
+{
+    struct npioctl npi;
+
+    npi.protocol = proto;
+    npi.mode     = mode;
+    if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
+	if (! ok_error (errno))
+	    error("ioctl(PPPIOCSNPMODE, %d, %d): %m (%d)",
+		   proto, mode, errno);
+	return 0;
+    }
+    return 1;
+}
+
+/*
+ * Use the hostname as part of the random number seed.
+ */
+int
+get_host_seed()
+{
+    int h;
+    char *p = hostname;
+
+    h = 407;
+    for (p = hostname; *p != 0; ++p)
+	h = h * 37 + *p;
+    return h;
+}
diff --git a/ap/app/ppp-2.4.1/pppoecd/utils.c b/ap/app/ppp-2.4.1/pppoecd/utils.c
new file mode 100644
index 0000000..d1ccf74
--- /dev/null
+++ b/ap/app/ppp-2.4.1/pppoecd/utils.c
@@ -0,0 +1,822 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University.  The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID	"$Id: utils.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <utmp.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#ifdef SVR4
+#include <sys/mkdev.h>
+#endif
+
+#include "pppd.h"
+
+#include <sys/sysinfo.h>
+
+static const char rcsid[] = RCSID;
+
+#if defined(SUNOS4)
+extern char *strerror();
+#endif
+
+static void vslp_printer __P((void *, char *, ...));
+static void format_packet __P((u_char *, int, void (*) (void *, char *, ...),
+			       void *));
+
+struct buffer_info {
+    char *ptr;
+    int len;
+};
+
+/*
+ * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcpy(dest, src, len)
+    char *dest;
+    const char *src;
+    size_t len;
+{
+    size_t ret = strlen(src);
+
+    if (len != 0) {
+	if (ret < len)
+	    strcpy(dest, src);
+	else {
+	    strncpy(dest, src, len - 1);
+	    dest[len-1] = 0;
+	}
+    }
+    return ret;
+}
+
+/*
+ * strlcat - like strcat/strncat, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcat(dest, src, len)
+    char *dest;
+    const char *src;
+    size_t len;
+{
+    size_t dlen = strlen(dest);
+
+    return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
+}
+
+
+/*
+ * slprintf - format a message into a buffer.  Like sprintf except we
+ * also specify the length of the output buffer, and we handle
+ * %r (recursive format), %m (error message), %v (visible string),
+ * %q (quoted string), %t (current time) and %I (IP address) formats.
+ * Doesn't do floating-point formats.
+ * Returns the number of chars put into buf.
+ */
+int
+slprintf __V((char *buf, int buflen, char *fmt, ...))
+{
+    va_list args;
+    int n;
+
+#if defined(__STDC__)
+    va_start(args, fmt);
+#else
+    char *buf;
+    int buflen;
+    char *fmt;
+    va_start(args);
+    buf = va_arg(args, char *);
+    buflen = va_arg(args, int);
+    fmt = va_arg(args, char *);
+#endif
+    n = vslprintf(buf, buflen, fmt, args);
+    va_end(args);
+    return n;
+}
+
+/*
+ * vslprintf - like slprintf, takes a va_list instead of a list of args.
+ */
+#define OUTCHAR(c)	(buflen > 0? (--buflen, *buf++ = (c)): 0)
+
+int
+vslprintf(buf, buflen, fmt, args)
+    char *buf;
+    int buflen;
+    char *fmt;
+    va_list args;
+{
+    int c, i, n;
+    int width, prec, fillch;
+    int base, len, neg, quoted;
+    unsigned long val = 0;
+    char *str, *f, *buf0;
+    unsigned char *p;
+    char num[32];
+    time_t t;
+    u_int32_t ip;
+    static char hexchars[] = "0123456789abcdef";
+    struct buffer_info bufinfo;
+
+    buf0 = buf;
+    --buflen;
+    while (buflen > 0) {
+	for (f = fmt; *f != '%' && *f != 0; ++f)
+	    ;
+	if (f > fmt) {
+	    len = f - fmt;
+	    if (len > buflen)
+		len = buflen;
+	    memcpy(buf, fmt, len);
+	    buf += len;
+	    buflen -= len;
+	    fmt = f;
+	}
+	if (*fmt == 0)
+	    break;
+	c = *++fmt;
+	width = 0;
+	prec = -1;
+	fillch = ' ';
+	if (c == '0') {
+	    fillch = '0';
+	    c = *++fmt;
+	}
+	if (c == '*') {
+	    width = va_arg(args, int);
+	    c = *++fmt;
+	} else {
+	    while (isdigit(c)) {
+		width = width * 10 + c - '0';
+		c = *++fmt;
+	    }
+	}
+	if (c == '.') {
+	    c = *++fmt;
+	    if (c == '*') {
+		prec = va_arg(args, int);
+		c = *++fmt;
+	    } else {
+		prec = 0;
+		while (isdigit(c)) {
+		    prec = prec * 10 + c - '0';
+		    c = *++fmt;
+		}
+	    }
+	}
+	str = 0;
+	base = 0;
+	neg = 0;
+	++fmt;
+	switch (c) {
+	case 'd':
+	    i = va_arg(args, int);
+	    if (i < 0) {
+		neg = 1;
+		val = -i;
+	    } else
+		val = i;
+	    base = 10;
+	    break;
+	case 'u':
+	    val = va_arg(args, unsigned int);
+	    base = 10;
+	    break;
+	case 'o':
+	    val = va_arg(args, unsigned int);
+	    base = 8;
+	    break;
+	case 'x':
+	case 'X':
+	    val = va_arg(args, unsigned int);
+	    base = 16;
+	    break;
+	case 'p':
+	    val = (unsigned long) va_arg(args, void *);
+	    base = 16;
+	    neg = 2;
+	    break;
+	case 's':
+	    str = va_arg(args, char *);
+	    break;
+	case 'c':
+	    num[0] = va_arg(args, int);
+	    num[1] = 0;
+	    str = num;
+	    break;
+	case 'm':
+	    str = strerror(errno);
+	    break;
+	case 'I':
+	    ip = va_arg(args, u_int32_t);
+	    ip = ntohl(ip);
+	    slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
+		     (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
+	    str = num;
+	    break;
+	case 'E':
+	    p = va_arg (args, unsigned char *);
+	    for (n = ETH_ALEN; n > 0; --n) {
+		c = *p++;
+		OUTCHAR (hexchars[(c >> 4) & 0xf]);
+		OUTCHAR (hexchars[c & 0xf]);
+		if (n > 1)
+		    OUTCHAR (':');
+	    }
+	    continue;
+	case 'r':
+	    f = va_arg(args, char *);
+
+	    n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
+	    buf += n;
+	    buflen -= n;
+	    continue;
+	case 't':
+	    time(&t);
+	    str = ctime(&t);
+	    str += 4;		/* chop off the day name */
+	    str[15] = 0;	/* chop off year and newline */
+	    break;
+	case 'v':		/* "visible" string */
+	case 'q':		/* quoted string */
+	    quoted = c == 'q';
+	    p = va_arg(args, unsigned char *);
+	    if (fillch == '0' && prec >= 0) {
+		n = prec;
+	    } else {
+		n = strlen((char *)p);
+		if (prec >= 0 && n > prec)
+		    n = prec;
+	    }
+	    while (n > 0 && buflen > 0) {
+		c = *p++;
+		--n;
+		if (!quoted && c >= 0x80) {
+		    OUTCHAR('M');
+		    OUTCHAR('-');
+		    c -= 0x80;
+		}
+		if (quoted && (c == '"' || c == '\\'))
+		    OUTCHAR('\\');
+		if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
+		    if (quoted) {
+			OUTCHAR('\\');
+			switch (c) {
+			case '\t':	OUTCHAR('t');	break;
+			case '\n':	OUTCHAR('n');	break;
+			case '\b':	OUTCHAR('b');	break;
+			case '\f':	OUTCHAR('f');	break;
+			default:
+			    OUTCHAR('x');
+			    OUTCHAR(hexchars[c >> 4]);
+			    OUTCHAR(hexchars[c & 0xf]);
+			}
+		    } else {
+			if (c == '\t')
+			    OUTCHAR(c);
+			else {
+			    OUTCHAR('^');
+			    OUTCHAR(c ^ 0x40);
+			}
+		    }
+		} else
+		    OUTCHAR(c);
+	    }
+	    continue;
+	case 'P':		/* print PPP packet */
+	    bufinfo.ptr = buf;
+	    bufinfo.len = buflen + 1;
+	    p = va_arg(args, unsigned char *);
+	    n = va_arg(args, int);
+	    format_packet(p, n, vslp_printer, &bufinfo);
+	    buf = bufinfo.ptr;
+	    buflen = bufinfo.len - 1;
+	    continue;
+	case 'B':
+	    p = va_arg(args, unsigned char *);
+	    for (n = prec; n > 0; --n) {
+		c = *p++;
+		if (fillch == ' ')
+		    OUTCHAR(' ');
+		OUTCHAR(hexchars[(c >> 4) & 0xf]);
+		OUTCHAR(hexchars[c & 0xf]);
+	    }
+	    continue;
+	default:
+	    *buf++ = '%';
+	    if (c != '%')
+		--fmt;		/* so %z outputs %z etc. */
+	    --buflen;
+	    continue;
+	}
+	if (base != 0) {
+	    str = num + sizeof(num);
+	    *--str = 0;
+	    while (str > num + neg) {
+		*--str = hexchars[val % base];
+		val = val / base;
+		if (--prec <= 0 && val == 0)
+		    break;
+	    }
+	    switch (neg) {
+	    case 1:
+		*--str = '-';
+		break;
+	    case 2:
+		*--str = 'x';
+		*--str = '0';
+		break;
+	    }
+	    len = num + sizeof(num) - 1 - str;
+	} else {
+	    len = strlen(str);
+	    if (prec >= 0 && len > prec)
+		len = prec;
+	}
+	if (width > 0) {
+	    if (width > buflen)
+		width = buflen;
+	    if ((n = width - len) > 0) {
+		buflen -= n;
+		for (; n > 0; --n)
+		    *buf++ = fillch;
+	    }
+	}
+	if (len > buflen)
+	    len = buflen;
+	memcpy(buf, str, len);
+	buf += len;
+	buflen -= len;
+    }
+    *buf = 0;
+    return buf - buf0;
+}
+
+/*
+ * vslp_printer - used in processing a %P format
+ */
+static void
+vslp_printer __V((void *arg, char *fmt, ...))
+{
+    int n;
+    va_list pvar;
+    struct buffer_info *bi;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    void *arg;
+    char *fmt;
+    va_start(pvar);
+    arg = va_arg(pvar, void *);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    bi = (struct buffer_info *) arg;
+    n = vslprintf(bi->ptr, bi->len, fmt, pvar);
+    va_end(pvar);
+
+    bi->ptr += n;
+    bi->len -= n;
+}
+
+#ifdef unused
+/*
+ * log_packet - format a packet and log it.
+ */
+
+void
+log_packet(p, len, prefix, level)
+    u_char *p;
+    int len;
+    char *prefix;
+    int level;
+{
+	init_pr_log(prefix, level);
+	format_packet(p, len, pr_log, &level);
+	end_pr_log();
+}
+#endif /* unused */
+
+/*
+ * format_packet - make a readable representation of a packet,
+ * calling `printer(arg, format, ...)' to output it.
+ */
+static void
+format_packet(p, len, printer, arg)
+    u_char *p;
+    int len;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int i, n;
+    u_short proto;
+    struct protent *protp;
+
+    if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+	p += 2;
+	GETSHORT(proto, p);
+	len -= PPP_HDRLEN;
+	for (i = 0; (protp = protocols[i]) != NULL; ++i)
+	    if (proto == protp->protocol)
+		break;
+	if (protp != NULL) {
+	    printer(arg, "[%s", protp->name);
+	    n = (*protp->printpkt)(p, len, printer, arg);
+	    printer(arg, "]");
+	    p += n;
+	    len -= n;
+	} else {
+	    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+		if (proto == (protp->protocol & ~0x8000))
+		    break;
+	    if (protp != 0 && protp->data_name != 0) {
+		printer(arg, "[%s data]", protp->data_name);
+		if (len > 8)
+		    printer(arg, "%.8B ...", p);
+		else
+		    printer(arg, "%.*B", len, p);
+		len = 0;
+	    } else
+		printer(arg, "[proto=0x%x]", proto);
+	}
+    }
+
+    if (len > 32)
+	printer(arg, "%.32B ...", p);
+    else
+	printer(arg, "%.*B", len, p);
+}
+
+#ifdef DEBUG
+
+static void logit __P((int, char *, va_list));
+static void log_write __P((int, char *));
+
+/*
+ * init_pr_log, end_pr_log - initialize and finish use of pr_log.
+ */
+
+static char line[256];		/* line to be logged accumulated here */
+static char *linep;		/* current pointer within line */
+static int llevel;		/* level for logging */
+
+void
+init_pr_log(prefix, level)
+     char *prefix;
+     int level;
+{
+	linep = line;
+	if (prefix != NULL) {
+		strlcpy(line, prefix, sizeof(line));
+		linep = line + strlen(line);
+	}
+	llevel = level;
+}
+
+void
+end_pr_log()
+{
+	if (linep != line) {
+		*linep = 0;
+		log_write(llevel, line);
+	}
+}
+
+/*
+ * pr_log - printer routine for outputting to syslog
+ */
+void
+pr_log __V((void *arg, char *fmt, ...))
+{
+	int l, n;
+	va_list pvar;
+	char *p, *eol;
+	char buf[256];
+
+#if defined(__STDC__)
+	va_start(pvar, fmt);
+#else
+	void *arg;
+	char *fmt;
+	va_start(pvar);
+	arg = va_arg(pvar, void *);
+	fmt = va_arg(pvar, char *);
+#endif
+
+	n = vslprintf(buf, sizeof(buf), fmt, pvar);
+	va_end(pvar);
+
+	p = buf;
+	eol = strchr(buf, '\n');
+	if (linep != line) {
+		l = (eol == NULL)? n: eol - buf;
+		if (linep + l < line + sizeof(line)) {
+			if (l > 0) {
+				memcpy(linep, buf, l);
+				linep += l;
+			}
+			if (eol == NULL)
+				return;
+			p = eol + 1;
+			eol = strchr(p, '\n');
+		}
+		*linep = 0;
+		log_write(llevel, line);
+		linep = line;
+	}
+
+	while (eol != NULL) {
+		*eol = 0;
+		log_write(llevel, p);
+		p = eol + 1;
+		eol = strchr(p, '\n');
+	}
+
+	/* assumes sizeof(buf) <= sizeof(line) */
+	l = buf + n - p;
+	if (l > 0) {
+		memcpy(line, p, n);
+		linep = line + l;
+	}
+}
+
+/*
+ * print_string - print a readable representation of a string using
+ * printer.
+ */
+void
+print_string(p, len, printer, arg)
+    char *p;
+    int len;
+    void (*printer) __P((void *, char *, ...));
+    void *arg;
+{
+    int c;
+
+    printer(arg, "\"");
+    for (; len > 0; --len) {
+	c = *p++;
+	if (' ' <= c && c <= '~') {
+	    if (c == '\\' || c == '"')
+		printer(arg, "\\");
+	    printer(arg, "%c", c);
+	} else {
+	    switch (c) {
+	    case '\n':
+		printer(arg, "\\n");
+		break;
+	    case '\r':
+		printer(arg, "\\r");
+		break;
+	    case '\t':
+		printer(arg, "\\t");
+		break;
+	    default:
+		printer(arg, "\\%.3o", c);
+	    }
+	}
+    }
+    printer(arg, "\"");
+}
+
+/*
+ * logit - does the hard work for fatal et al.
+ */
+static void
+logit(level, fmt, args)
+    int level;
+    char *fmt;
+    va_list args;
+{
+    int n;
+    char buf[1024];
+
+    n = vslprintf(buf, sizeof(buf), fmt, args);
+    log_write(level, buf);
+}
+
+static void
+log_write(level, buf)
+    int level;
+    char *buf;
+{
+    syslog(level, "%s", buf);
+    if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
+	int n = strlen(buf);
+
+	if (n > 0 && buf[n-1] == '\n')
+	    --n;
+	if (write(log_to_fd, buf, n) != n
+	    || write(log_to_fd, "\n", 1) != 1)
+	    log_to_fd = -1;
+    }
+}
+
+/*
+ * fatal - log an error message and die horribly.
+ */
+void
+fatal __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_ERR, fmt, pvar);
+    va_end(pvar);
+
+    die(1);			/* as promised */
+}
+
+/*
+ * error - log an error message.
+ */
+void
+error __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_ERR, fmt, pvar);
+    va_end(pvar);
+}
+
+/*
+ * warn - log a warning message.
+ */
+void
+warn __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_WARNING, fmt, pvar);
+    va_end(pvar);
+}
+
+/*
+ * notice - log a notice-level message.
+ */
+void
+notice __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_NOTICE, fmt, pvar);
+    va_end(pvar);
+}
+
+/*
+ * info - log an informational message.
+ */
+void
+info __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_INFO, fmt, pvar);
+    va_end(pvar);
+}
+
+/*
+ * dbglog - log a debug message.
+ */
+void
+dbglog __V((char *fmt, ...))
+{
+    va_list pvar;
+
+#if defined(__STDC__)
+    va_start(pvar, fmt);
+#else
+    char *fmt;
+    va_start(pvar);
+    fmt = va_arg(pvar, char *);
+#endif
+
+    logit(LOG_DEBUG, fmt, pvar);
+    va_end(pvar);
+}
+
+#endif /* DEBUG */
+
+//==================================================
+#include <fcntl.h>
+#define GOT_IP                  0x01
+#define RELEASE_IP              0x02
+#define GET_IP_ERROR            0x03
+#define RELEASE_WAN_CONTROL     0x04
+#define SET_LED(val) \
+{ \
+        int filep; \
+        if ((filep = open("/dev/extio", O_RDWR,0))) \
+        { \
+                ioctl(filep, val, 0); \
+                close(filep); \
+        } \
+}
+//==================================================
+
+int
+log_to_file(char *buf)	// add by honor
+{	
+	FILE *fp;
+	
+	if ((fp = fopen("/tmp/ppp/log", "w"))) {
+		fprintf(fp, "%s", buf);
+		fclose(fp);
+		SET_LED(GET_IP_ERROR)
+		return 1;
+	}	
+	return 0;
+}
+
+int
+my_gettimeofday(struct timeval *timenow, struct timezone *tz)
+{
+	struct sysinfo info;
+
+        sysinfo(&info);
+
+	timenow->tv_sec = info.uptime;
+	timenow->tv_usec = 0;
+
+	return 0;
+}
+
diff --git a/ap/app/ppp-2.4.1/readme_pppoe.txt b/ap/app/ppp-2.4.1/readme_pppoe.txt
new file mode 100755
index 0000000..fdc61d9
--- /dev/null
+++ b/ap/app/ppp-2.4.1/readme_pppoe.txt
@@ -0,0 +1,82 @@
+°æ±¾2.4.1£¬µ«±ê×¼pppd´úÂëÖв¢Ã»ÓÐpppoecdÄ£¿é£¬¼´¸ÃʵÏÖÊÇ¿ªÔ´pppoecdÄ£¿é¾«¼òÁËpppdµÄ²Ù×÷²¢Ê¹ÓÃpppdÄ£¿éÖеĹ²ÓÐÎļþ¡£

+

+1¡¢ÈçºÎʹÓÃpppoe

+ÎÒÃÇËùʹÓõÄÓ¦Óýø³ÌÊÇpppoecd£¬¾ßÌåʹÓõķ½Ê½ÈçÏ£º

+pppoecd $wan0  -u $pppoe_user -p $pppoe_pass -N 2 -k &

+$wan0±íʾ×÷ÓÃÓÚÄĸö¿Ú£¬		ÓÉnvÏî	ethwan			¾ö¶¨

+u±íʾÓû§Ãû£¬				ÓÉnvÏî	pppoe_username	¾ö¶¨

+p±íʾÓû§ÃÜÂë,				ÓÉnvÏî	pppoe_password	¾ö¶¨

+N±íÊ¾ÖØÊÔ´ÎÊý£¬ÆäËûΪĬÈÏ£»

+

+2¡¢¹¤×÷Ô­ÀíºÍÁ÷³Ì

+PPPoE·ÖΪdiscoveryºÍsessionÁ½¸ö½×¶Î

+discovery£º

+´«Í³µÄPPPÁ¬½ÓÊÇ»ùÓڵ㵽µãµÄ£¬¶øÔÚÒÔÌ«ÍøÊÇmuti-accesss£¬¼´ÔÚÒÔÌ«ÍøÖеÄÈÎÒ»½Úµã¿ÉÒÔ·ÃÎÊÆäËû½Úµã¡£ÒÔÌ«ÍøÖеÄframe°üº¬×ÅÄ¿µÄ½ÚµãµÄMACµØÖ·ÒÔÕÒµ½Ä¿µÄ½Úµã¡£ËùÒÔÔÚת»»PPP frame֮ǰ£¬Á½¸öͨÐÅ½Úµã±ØÐëÊÂÏÈÖªµÀ¶Ô·½µÄMACµØÖ·¡£ PPPeEµÄdiscovery½×¶Î¾ÍÊÇÈÃÒÔÌ«ÍøÖеĽڵ㽻»»Í¨ÖªÆäMACµØÖ·£¬²¢½¨Á¢Ò»¸öSession ID¹©ºóÐøµÄ°ü½»»»Ê¹Óá£

+ÔÚsetdevname_pppoeÖУ¬Íê³ÉchannalµÄ¸³Öµpppoe_channel£¬¸Ã½á¹¹ÌåÖж¨ÒåÁËËùÓн׶εĻص÷º¯Êý

+client              server

+		-->PADI				¿Í»§¶Ë·¢ËÍPADIÇëÇó£¬Í¨¹ýstd_init_disc

+		<--PADO				ÔÚº¯Êýsession_connectÖе±µÈµ½PADO°üºó£¬½øÈëstd_rcv_padoº¯Êý·¢ËÍPADR_CODE°ü£»

+		-->PADR				½øÈëstd_rcv_padoº¯Êý·¢ËÍPADR_CODE°ü£¬ËæºóµÈ´ýPADS°ü

+		<--PADS				Íê³É¸Ã²½Öèºó¼´½øÈëLCP½×¶Î

+

+session£ºµ±½ÚµãÖ®¼äÖªµÀÁËÏ໥µÄMACµØÖ·ºó£¬¾Í½øÈëÁËsession½×¶Î¡£

+¸Ã½×¶Î·ÖΪLCPºÍNCP½×¶Î

+LCPÓÃÓÚ½¨Á¢¡¢²ð³ýºÍ¼à¿ØPPPÊý¾ÝÁ´Â·£»»¥Ïà·¢ËÍLCP Request¸ø¶Ô·½À´È·ÈÏ·¢Ë͵Ä×î´ó´«Êäµ¥Ôª¡¢ÊÇ·ñÈÏÖ¤ºÍ²ÉÓúÎÖÖÈÏÖ¤·½Ê½µÄЭÉÌ£¬ÕâЩ¶¼¿ÉÒÔͨ¹ýץȡwireshark·ÖÎö£»

+Õâ¸ö½×¶ÎµÄЭÒé¶¼ÊÇͨ¹ýfsm״̬»úÖ´ÐУ¬¾ßÌå¿ÉÁ˽â´úÂ룬²»ÔÙÃèÊö¡£

+

+NCPÖ÷ÒªÓÃÓÚЭÉÌÔÚ¸ÃÊý¾ÝÁ´Â·ÉÏËù´«ÊäµÄÊý¾Ý°üµÄ¸ñʽÓëÀàÐÍ¡£Í¬Ê±£¬PPP»¹ÌṩÁËÓÃÓÚÍøÂ簲ȫ·½ÃæµÄÑé֤ЭÒé×壨PAPºÍCHAP£©¡£

+

+3¡¢ÕûÌåµ÷ÓÃÁ÷³Ì

+pppoe_dail.sh µ÷ÓÃÁËpppoecd½ø³Ì£¬ÔÚÍê³ÉµØÖ··ÖÅäºóµ÷ÓÃipcp_up£¬Ö´ÐÐÁËpppoecdµÄ½ø³Ì»Øµ÷poeupdown(/bin/pppoe_up)£¬Ôڸýø³ÌÖÐÉèÖÃnvÖµºÍµ÷Óýű¾£¬¸Ã¿ªÔ´Èí¼þµÄÖ÷ÒªÐ޸ĵãÒ²¾ÍÊÇÔÚpppoe_upµÄʵÏÖÖУ¬

+ͨ¹ý¶ÁÈ¡nvÅäÖÃÏà¹Ø²ÎÊý¡£

+

+4¡¢ÏµÍ³¼äÒÆÖ²ËùÉæ¼°µ½µÄÐ޸ģ»

+a¡¢Ó¦ÓòãÈí¼þppp-2.4.1£¬ÔÚzte_appsÏ£¬ÐèÒª¹Ø×¢MakefileµÄ±àÒëÄ¿±êÊÇpppoecdºÍpoeupdown£¬ÔÚ¿½±´Ä¿±êÎļþµÄʱºò½«poeupdownÖØÃüÃûΪpppoe_upºÍpppoe_down£»

+b¡¢Äں˲㣬ÐèÒª´ò¿ªÄں˲ãµÄ±àÒëÑ¡Ïî

+	LinuxÄں˴ò¿ªÈçϼ¸Ï

+	CONFIG_PPP=y

+	CONFIG_PPP_ASYNC=y

+	CONFIG_PPP_BSDCOMP=y

+	CONFIG_PPP_DEFLATE=y

+	CONFIG_PPP_MPPE=y

+	CONFIG_PPPOE=y

+

+	UcÄں˴ò¿ªÈçϼ¸Ï

+	config.linuxÖдò¿ª

+	CONFIG_PPP=y

+	CONFIG_PPPOE=y

+	CONFIG_PPP_ASYNC=y

+	config.venderÖдò¿ª

+	CONFIG_USER_PPPD_PPPD_PPPD=y

+	

+	project/MF903/config/normal/makefile ÖмÓÈëppp,c,108,0

+	

+																									2016.04.22 update

+																									2016.08.08 update again

+								2021ɾ³ýÈßÓà´úÂë

+

+°æ±¾1.1 2008-08-04 06:11:52 winfred Exp$

+

+ÕâÊÇPPPoEcd£¬Ò»¸öPPPoE¿Í»§¶ËÊØ»¤³ÌÐò¡£Ëü±¾ÖÊÉÏÊÇÒ»¸ö

+

+PPPdµÄ¾«¼ò°æ

+

+-×îСѡÏîÖ§³Ö£¨¼ûoptions.c£©

+

+-¾²Ì¬Á´½ÓPPPoE¿Í»§¶ËÖ§³Ö

+

+-½öPAP/CHAP/CCP

+

+pppd.hºÍpppoe.hµÄ˽Óа汾ÔÚ´ËĿ¼ÖÐÓÃÓÚ

+

+-ÖØÐ´µ÷ÊÔº¯Êýµ÷ÓÃ

+

+-ÖØÐ´²»ÊÊÓõĺ¯Êýµ÷ÓÃ

+

+-ͨ¹ý¾²Ì¬³£Á¿Ñ¡Ïî±àÒë³ö²»ÊÊÓõĴúÂë·¾¶

+

+´ó¶àÊý³£¼ûµÄ´úÂëЭÒéÎļþ¶¼±»µ¥¶ÀÁôÏÂÁË¡£ºÜ¶à

+

+ËÀµôµÄ´úÂë¿ÉÄÜ»á´ÓËüÃÇÉíÉϰþÀë³öÀ´£¬µ«´ó²¿·Ö´úÂë¶¼»áÅòÕÍ

+

+ÔÚsys linux.oºÍoptions.oÖС£
\ No newline at end of file