[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