code:
# /etc/conf.d/net.ppp0:

# Config file for /etc/init.d/net.ppp0

PEER="MyPeer"                   # Define peer (aka ISP)
DEBUG="no"                      # Turn on debugging
PERSIST="no"                    # Redial after being dropped
ONDEMAND="no"                   # Only bring the interface up on demand?
MODEMPORT="/dev/ttyS1"          # TTY device modem is connected to
LINESPEED="115200"              # Speed pppd should try to connect at
INITSTRING=""                   # Extra init string for the modem
DEFROUTE="yes"                  # Must pppd set the default route?
HARDFLOWCTL="yes"               # Use hardware flow control?
ESCAPECHARS="yes"               # Use escape caracters ?
PPPOPTIONS=""                   # Extra options for pppd
USERNAME="user"                 # The PAP/CHAP username
PASSWORD="passwd"               # Your password/secret.  Ugly I know, but i
                                # will work on something more secure later
                                # on.  700 permission on /etc/init.d/net.ppp0
                                # should be enouth for now.
NUMBER="9180000"                # The telephone number of your ISP
                                # leave blank for leased-line operation.
REMIP=""                        # The ip of the remote box if it should be set
NETMASK=""                      # Netmask
IPADDR=""                       # Our IP if we have a static one
MRU="768"                       # Sets the MRU
MTU="768"                       # Sets the MTU
RETRYTIMEOUT="60"               # Retry timeout for when ONDEMAND="yes" or
                                # PERSIST="yes"
IDLETIMEOUT="600"               # Idle timeout for when ONDEMAND="yes"
PEERDNS="no"                    # Should pppd set the peer dns?

AUTOCFGFILES="yes"              # By default this scripts will generate
                                # /etc/ppp/chat-isp, /etc/ppp/chap-secrets,
                                # /etc/ppp/pap-secrets and /etc/ppp/peers/isp
                                # automatically.  Set to "no" if you experience
                                # problems, or need specialized scripts.  You
                                # will have to create these files by hand then.

AUTOCHATSCRIPT="yes"            # By default this script iwll generate
                                # /etc/ppp/chat-${PEER} automatically. Set to "no"
                                # if you experience problems, or need specialized
                                # scripts. You will have to create these files by
                                # hand then.

# Directory where the templates is stored
TEMPLATEDIR=/etc/ppp


code:
diff -ur ppp-2.4.5.orig/chat/Makefile.linux ppp-2.4.5/chat/Makefile.linux
--- ppp-2.4.5.orig/chat/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/chat/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -10,7 +10,6 @@
 CDEF4=	-DFNDELAY=O_NDELAY		# Old name value
 CDEFS=	$(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4)

-COPTS=	-O2 -g -pipe
 CFLAGS=	$(COPTS) $(CDEFS)

 INSTALL= install
@@ -18,7 +17,7 @@
 all:	chat

 chat:	chat.o
-	$(CC) -o chat chat.o
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^

 chat.o:	chat.c
 	$(CC) -c $(CFLAGS) -o chat.o chat.c
diff -ur ppp-2.4.5.orig/pppd/Makefile.linux ppp-2.4.5/pppd/Makefile.linux
--- ppp-2.4.5.orig/pppd/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -32,7 +32,7 @@

 # CC = gcc
 #
-COPTS = -O2 -pipe -Wall -g
+COPTS+= -Wall
 LIBS =

 # Uncomment the next 2 lines to include support for Microsoft's
diff -ur ppp-2.4.5.orig/pppd/plugins/Makefile.linux ppp-2.4.5/pppd/plugins/Makefile.linux
--- ppp-2.4.5.orig/pppd/plugins/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -1,7 +1,11 @@
 #CC	= gcc
-COPTS	= -O2 -g
 CFLAGS	= $(COPTS) -I.. -I../../include -fPIC
-LDFLAGS	= -shared
+LDFLAGS_PROG := $(LDFLAGS)
+export LDFLAGS LDFLAGS_PROG
+LDFLAGS	+= -shared
+# need the following option, otherwise linking plugins might fail with undef errors (Gentoo bug 210837)
+LDFLAGS += -Wl,--allow-shlib-undefined
+LIBS =
 INSTALL	= install

 DESTDIR = $(INSTROOT)@DESTDIR@
@@ -23,7 +27,7 @@
 	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all; done

 %.so: %.c
-	$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LIBS)

 VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../patchlevel.h)

diff -ur ppp-2.4.5.orig/pppd/plugins/pppoatm/Makefile.linux ppp-2.4.5/pppd/plugins/pppoatm/Makefile.linux
--- ppp-2.4.5.orig/pppd/plugins/pppoatm/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/pppoatm/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -1,7 +1,5 @@
 #CC	= gcc
-COPTS	= -O2 -g
 CFLAGS	= $(COPTS) -I../.. -I../../../include -fPIC
-LDFLAGS	= -shared
 INSTALL	= install

 #***********************************************************************
@@ -33,7 +31,7 @@
 all: $(PLUGIN)

 $(PLUGIN): $(PLUGIN_OBJS)
-	$(CC) $(CFLAGS) -o $@ -shared $^ $(LIBS)
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LIBS)

 install: all
 	$(INSTALL) -d -m 755 $(LIBDIR)
diff -ur ppp-2.4.5.orig/pppd/plugins/pppol2tp/Makefile.linux ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux
--- ppp-2.4.5.orig/pppd/plugins/pppol2tp/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux	2010-08-08 09:20:02.000000000 +0200
@@ -1,7 +1,5 @@
 #CC	= gcc
-COPTS	= -O2 -g
 CFLAGS	= $(COPTS) -I. -I../.. -I../../../include -fPIC
-LDFLAGS	= -shared
 INSTALL	= install

 #***********************************************************************
@@ -16,7 +14,7 @@
 all: $(PLUGINS)

 %.so: %.o
-	$(CC) $(CFLAGS) -o $@ -shared $^ $(LIBS)
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LIBS)

 install: all
 	$(INSTALL) -d -m 755 $(LIBDIR)
diff -ur ppp-2.4.5.orig/pppd/plugins/radius/Makefile.linux ppp-2.4.5/pppd/plugins/radius/Makefile.linux
--- ppp-2.4.5.orig/pppd/plugins/radius/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/radius/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -12,7 +12,7 @@
 INSTALL	= install

 PLUGIN=radius.so radattr.so radrealms.so
-CFLAGS=-I. -I../.. -I../../../include -O2 -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
+CFLAGS=$(COPTS) -I. -I../.. -I../../../include -fPIC -DRC_LOG_FACILITY=LOG_DAEMON

 # Uncomment the next line to include support for Microsoft's
 # MS-CHAP authentication protocol.
@@ -43,13 +43,13 @@
 	$(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR)

 radius.so: radius.o libradiusclient.a
-	$(CC) -o radius.so -shared radius.o libradiusclient.a
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^

 radattr.so: radattr.o
-	$(CC) -o radattr.so -shared radattr.o
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^

 radrealms.so: radrealms.o
-	$(CC) -o radrealms.so -shared radrealms.o
+	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^

 CLIENTOBJS = avpair.o buildreq.o config.o dict.o ip_util.o \
 	clientid.o sendserver.o lock.o util.o md5.o
diff -ur ppp-2.4.5.orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.5/pppd/plugins/rp-pppoe/Makefile.linux
--- ppp-2.4.5.orig/pppd/plugins/rp-pppoe/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/rp-pppoe/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -25,12 +25,11 @@
 # Version is set ONLY IN THE MAKEFILE!  Don't delete this!
 RP_VERSION=3.8p

-COPTS=-O2 -g
 CFLAGS=$(COPTS) -I../../../include '-DRP_VERSION="$(RP_VERSION)"'
 all: rp-pppoe.so pppoe-discovery

 pppoe-discovery: pppoe-discovery.o debug.o
-	$(CC) -o pppoe-discovery pppoe-discovery.o debug.o
+	$(CC) $(LDFLAGS_PROG) $(CFLAGS) -o pppoe-discovery pppoe-discovery.o debug.o

 pppoe-discovery.o: pppoe-discovery.c
 	$(CC) $(CFLAGS) -c -o pppoe-discovery.o pppoe-discovery.c
@@ -39,7 +38,7 @@
 	$(CC) $(CFLAGS) -c -o debug.o debug.c

 rp-pppoe.so: plugin.o discovery.o if.o common.o
-	$(CC) -o rp-pppoe.so -shared plugin.o discovery.o if.o common.o
+	$(CC) $(LDFLAGS) $(CFLAGS) -o rp-pppoe.so plugin.o discovery.o if.o common.o

 install: all
 	$(INSTALL) -d -m 755 $(LIBDIR)
diff -ur ppp-2.4.5.orig/pppdump/Makefile.linux ppp-2.4.5/pppdump/Makefile.linux
--- ppp-2.4.5.orig/pppdump/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppdump/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -2,7 +2,7 @@
 BINDIR = $(DESTDIR)/sbin
 MANDIR = $(DESTDIR)/share/man/man8

-CFLAGS= -O -I../include/net
+CFLAGS=$(COPTS) -I../include/net
 OBJS = pppdump.o bsd-comp.o deflate.o zlib.o

 INSTALL= install
@@ -10,7 +10,7 @@
 all:	pppdump

 pppdump: $(OBJS)
-	$(CC) -o pppdump $(OBJS)
+	$(CC) $(LDFLAGS) -o pppdump $(OBJS)

 clean:
 	rm -f pppdump $(OBJS) *~
diff -ur ppp-2.4.5.orig/pppstats/Makefile.linux ppp-2.4.5/pppstats/Makefile.linux
--- ppp-2.4.5.orig/pppstats/Makefile.linux	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppstats/Makefile.linux	2010-08-08 09:19:38.000000000 +0200
@@ -10,7 +10,6 @@
 PPPSTATOBJS = pppstats.o

 #CC = gcc
-COPTS = -O
 COMPILE_FLAGS = -I../include
 LIBS =

@@ -26,7 +25,7 @@
 	$(INSTALL) -c -m 444 pppstats.8 $(MANDIR)

 pppstats: $(PPPSTATSRCS)
-	$(CC) $(CFLAGS) -o pppstats pppstats.c $(LIBS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o pppstats pppstats.c $(LIBS)

 clean:
 	rm -f pppstats *~ #* core

repo_name: ayhanyalcinsoy/main


code:
diff -Nur ppp-2.4.5.orig/pppd/main.c ppp-2.4.5/pppd/main.c
--- ppp-2.4.5.orig/pppd/main.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/main.c	2010-08-08 09:30:23.000000000 +0200
@@ -96,6 +96,9 @@
 #include "fsm.h"
 #include "lcp.h"
 #include "ipcp.h"
+
+#include "mplscp.h"
+
 #ifdef INET6
 #include "ipv6cp.h"
 #endif
@@ -283,6 +286,7 @@
     &cbcp_protent,
 #endif
     &ipcp_protent,
+    &mplscp_protent,
 #ifdef INET6
     &ipv6cp_protent,
 #endif
diff -Nur ppp-2.4.5.orig/pppd/Makefile.linux ppp-2.4.5/pppd/Makefile.linux
--- ppp-2.4.5.orig/pppd/Makefile.linux	2010-08-08 09:22:22.000000000 +0200
+++ ppp-2.4.5/pppd/Makefile.linux	2010-08-08 09:31:43.000000000 +0200
@@ -13,16 +13,16 @@

 PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap-new.c md5.c ccp.c \
 	   ecp.c ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \
-	   demand.c utils.c tty.c eap.c chap-md5.c session.c
+	   demand.c utils.c tty.c eap.c chap-md5.c session.c mplscp.c

 HEADERS = ccp.h session.h chap-new.h ecp.h fsm.h ipcp.h \
 	ipxcp.h lcp.h magic.h md5.h patchlevel.h pathnames.h pppd.h \
-	upap.h eap.h
+	upap.h eap.h mplscp.h

 MANPAGES = pppd.8
 PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o md5.o ccp.o \
 	   ecp.o auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o \
-	   eap.o chap-md5.o session.o
+	   eap.o chap-md5.o session.o mplscp.o

 #
 # include dependencies if present
diff -Nur ppp-2.4.5.orig/pppd/mplscp.c ppp-2.4.5/pppd/mplscp.c
--- ppp-2.4.5.orig/pppd/mplscp.c	1970-01-01 01:00:00.000000000 +0100
+++ ppp-2.4.5/pppd/mplscp.c	2010-08-08 09:30:23.000000000 +0200
@@ -0,0 +1,371 @@
+
+/* MPLSCP - Serge.Krier@advalvas.be (C) 2001 */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "mplscp.h"
+
+
+/* local vars */
+/* static int mplscp_is_up; */                  /* have called np_up() */
+
+/*
+ * Callbacks for fsm code.  (CI = Configuration Information)
+ */
+static void mplscp_resetci __P((fsm *));	/* Reset our CI */
+static int  mplscp_cilen __P((fsm *));	        /* Return length of our CI */
+static void mplscp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
+static int  mplscp_ackci __P((fsm *, u_char *, int));	/* Peer ack'd our CI */
+static int  mplscp_nakci __P((fsm *, u_char *, int));	/* Peer nak'd our CI */
+static int  mplscp_rejci __P((fsm *, u_char *, int));	/* Peer rej'd our CI */
+static int  mplscp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
+static void mplscp_up __P((fsm *));		/* We're UP */
+static void mplscp_down __P((fsm *));		/* We're DOWN */
+static void mplscp_finished __P((fsm *));	/* Don't need lower layer */
+
+fsm mplscp_fsm[NUM_PPP];		/* MPLSCP fsm structure */
+
+static fsm_callbacks mplscp_callbacks = { /* MPLSCP callback routines */
+  mplscp_resetci,		/* Reset our Configuration Information */
+  mplscp_cilen,			/* Length of our Configuration Information */
+  mplscp_addci,			/* Add our Configuration Information */
+  mplscp_ackci,			/* ACK our Configuration Information */
+  mplscp_nakci,			/* NAK our Configuration Information */
+  mplscp_rejci,			/* Reject our Configuration Information */
+  mplscp_reqci,			/* Request peer's Configuration Information */
+  mplscp_up,			/* Called when fsm reaches OPENED state */
+  mplscp_down,			/* Called when fsm leaves OPENED state */
+  NULL,			        /* Called when we want the lower layer up */
+  mplscp_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 */
+  "MPLSCP"			/* String name of protocol */
+};
+
+static option_t mplscp_option_list[] = {
+    { "mpls", o_bool, &mplscp_protent.enabled_flag,
+      "Enable MPLSCP (and MPLS)", 1 },
+    { NULL } };
+
+/*
+ * Protocol entry points from main code.
+ */
+
+static void mplscp_init __P((int));
+static void mplscp_open __P((int));
+static void mplscp_close __P((int, char *));
+static void mplscp_lowerup __P((int));
+static void mplscp_lowerdown __P((int));
+static void mplscp_input __P((int, u_char *, int));
+static void mplscp_protrej __P((int));
+static int  mplscp_printpkt __P((u_char *, int,
+				 void (*) __P((void *, char *, ...)), void *));
+
+struct protent mplscp_protent = {
+    PPP_MPLSCP,
+    mplscp_init,
+    mplscp_input,
+    mplscp_protrej,
+    mplscp_lowerup,
+    mplscp_lowerdown,
+    mplscp_open,
+    mplscp_close,
+    mplscp_printpkt,
+    NULL,
+    0,                            /* MPLS not enabled by default */
+    "MPLSCP",
+    "MPLS",
+    mplscp_option_list,
+    NULL,
+    NULL,
+    NULL
+};
+
+/*
+ * mplscp_init - Initialize MPLSCP.
+ */
+static void
+mplscp_init(int unit) {
+
+  fsm *f = &mplscp_fsm[unit];
+
+  f->unit = unit;
+  f->protocol = PPP_MPLSCP;
+  f->callbacks = &mplscp_callbacks;
+  fsm_init(&mplscp_fsm[unit]);
+
+}
+
+/*
+ * mplscp_open - MPLSCP is allowed to come up.
+ */
+static void
+mplscp_open(int unit) {
+
+  fsm_open(&mplscp_fsm[unit]);
+
+}
+
+/*
+ * mplscp_close - Take MPLSCP down.
+ */
+static void
+mplscp_close(int unit, char *reason) {
+
+  fsm_close(&mplscp_fsm[unit], reason);
+
+}
+
+/*
+ * mplscp_lowerup - The lower layer is up.
+ */
+static void
+mplscp_lowerup(int unit) {
+
+  fsm_lowerup(&mplscp_fsm[unit]);
+}
+
+/*
+ * mplscp_lowerdown - The lower layer is down.
+ */
+static void
+mplscp_lowerdown(int unit) {
+
+  fsm_lowerdown(&mplscp_fsm[unit]);
+}
+
+/*
+ * mplscp_input - Input MPLSCP packet.
+ */
+static void
+mplscp_input(int unit, u_char *p, int len) {
+
+  fsm_input(&mplscp_fsm[unit], p, len);
+}
+
+/*
+ * mplscp_protrej - A Protocol-Reject was received for MPLSCP.
+ * Pretend the lower layer went down, so we shut up.
+ */
+static void
+mplscp_protrej(int unit) {
+
+    fsm_lowerdown(&mplscp_fsm[unit]);
+}
+
+/*
+ * mplscp_resetci - Reset our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+mplscp_resetci(fsm *f) {
+
+  return;
+}
+
+/*
+ * mplscp_cilen - Return length of our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static int
+mplscp_cilen(fsm *f) {
+
+  return 0;
+}
+
+/*
+ * mplscp_addci - Add our desired CIs to a packet.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+mplscp_addci(fsm *f, u_char *ucp, int *lenp) {
+
+}
+
+/*
+ * ipcp_ackci - Ack our CIs.
+ * Called by fsm_rconfack, Receive Configure ACK.
+ *
+ * Returns:
+ *	0 - Ack was bad.
+ *	1 - Ack was good.
+ */
+static int
+mplscp_ackci(fsm *f, u_char *p, int  len) {
+
+  return 1;
+
+}
+
+/*
+ * mplscp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if MPLSCP 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
+mplscp_nakci(fsm *f, u_char *p, int len) {
+
+  return 1;
+}
+
+/*
+ * MPLSVP_rejci - Reject some of our CIs.
+ * Callback from fsm_rconfnakrej.
+ */
+static int
+mplscp_rejci(fsm *f, u_char *p, int len) {
+
+  return 1;
+
+}
+
+/*
+ * mplscp_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
+mplscp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) {
+
+
+  int rc = CONFACK;		/* Final packet return code */
+
+  PUTCHAR(CONFACK,inp);
+
+  return rc;
+
+}
+
+static void
+mplscp_up(fsm *f) {
+
+  sifnpmode(f->unit, PPP_MPLS_UC, NPMODE_PASS);
+  /*  sifnpmode(f->unit, PPP_MPLS_MC, NPMODE_PASS);*/
+
+  np_up(f->unit, PPP_MPLS_UC);
+  /*  np_up(f->unit, PPP_MPLS_MC);*/
+  /*  ipcp_is_up = 1;*/
+
+
+#if 1
+  printf("MPLSCP is OPENED\n");
+#endif
+
+}
+
+static void
+mplscp_down(fsm *f) {
+
+  sifnpmode(f->unit, PPP_MPLS_UC, NPMODE_DROP);
+  /*  sifnpmode(f->unit, PPP_MPLS_MC, NPMODE_DROP);*/
+
+  sifdown(f->unit);
+
+#if 1
+  printf("MPLSCP is CLOSED\n");
+#endif
+
+
+}
+
+static void
+mplscp_finished(fsm *f) {
+
+  np_finished(f->unit, PPP_MPLS_UC);
+  /*  np_finished(f->unit, PPP_MPLS_MC);*/
+
+}
+
+/*
+ * mpls_printpkt - print the contents of an MPLSCP packet.
+ */
+static char *mplscp_codenames[] = {
+    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+    "TermReq", "TermAck", "CodeRej"
+};
+
+static int
+mplscp_printpkt(u_char *p, int plen,
+		void (*printer) __P((void *, char *, ...)),
+		void *arg) {
+
+    int code, id, len, olen;
+    u_char *pstart, *optend;
+
+    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(mplscp_codenames) / sizeof(char *))
+	printer(arg, " %s", mplscp_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;
+	    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;
+
+}
diff -Nur ppp-2.4.5.orig/pppd/mplscp.h ppp-2.4.5/pppd/mplscp.h
--- ppp-2.4.5.orig/pppd/mplscp.h	1970-01-01 01:00:00.000000000 +0100
+++ ppp-2.4.5/pppd/mplscp.h	2010-08-08 09:30:23.000000000 +0200
@@ -0,0 +1,8 @@
+
+/* MPLSCP - Serge.Krier@advalvas.be (C) 2001 */
+
+#define PPP_MPLSCP  0x8281
+#define PPP_MPLS_UC 0x0281
+#define PPP_MPLS_MC 0x0283
+
+extern struct protent mplscp_protent;


code:
diff -Nur ppp-2.4.5.orig/pppd/options.c ppp-2.4.5/pppd/options.c
--- ppp-2.4.5.orig/pppd/options.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/options.c	2010-08-08 09:43:47.000000000 +0200
@@ -100,6 +100,9 @@
 char	user[MAXNAMELEN];	/* Username for PAP */
 char	passwd[MAXSECRETLEN];	/* Password for PAP */
 bool	persist = 0;		/* Reopen link after it goes down */
+bool	killoldaddr = 0;		/* If our IP is reassigned on
+				    reconnect, kill active TCP
+				     connections using the old IP. */
 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 */
@@ -231,6 +234,11 @@
     { "demand", o_bool, &demand,
       "Dial on demand", OPT_INITONLY | 1, &persist },

+    { "killoldaddr", o_bool, &killoldaddr,
+      "Kill connections from an old source address", 1},
+    { "nokilloldaddr", o_bool,&killoldaddr,
+      "Don't kill connections from an old source address" },
+
     { "--version", o_special_noarg, (void *)showversion,
       "Show version number" },
     { "--help", o_special_noarg, (void *)showhelp,
diff -Nur ppp-2.4.5.orig/pppd/pppd.h ppp-2.4.5/pppd/pppd.h
--- ppp-2.4.5.orig/pppd/pppd.h	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/pppd.h	2010-08-08 09:43:47.000000000 +0200
@@ -298,6 +298,9 @@
 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 bool	killoldaddr;	/* If our IP is reassigned on
+				    reconnect, kill active TCP
+				     connections using the old IP. */
 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 */
diff -Nur ppp-2.4.5.orig/pppd/sys-linux.c ppp-2.4.5/pppd/sys-linux.c
--- ppp-2.4.5.orig/pppd/sys-linux.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/sys-linux.c	2010-08-08 09:43:47.000000000 +0200
@@ -165,6 +165,10 @@

 #endif /* INET6 */

+#ifndef SIOCKILLADDR
+#define SIOCKILLADDR	0x8939
+#endif
+
 /* We can get an EIO error on an ioctl if the modem has hung up */
 #define ok_error(num) ((num)==EIO)

@@ -209,6 +213,7 @@
 static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
 static char proxy_arp_dev[16];		/* Device for proxy arp entry */
 static u_int32_t our_old_addr;		/* for detecting address changes */
+static u_int32_t our_current_addr;
 static int	dynaddr_set;		/* 1 if ip_dynaddr set */
 static int	looped;			/* 1 if using loop */
 static int	link_mtu;		/* mtu for the link (not bundle) */
@@ -537,6 +542,27 @@
     return -1;
 }

+static void do_killaddr(u_int32_t oldaddr)
+{
+    struct ifreq   ifr;
+
+    memset(&ifr,0,sizeof ifr);
+
+    SET_SA_FAMILY (ifr.ifr_addr,    AF_INET);
+    SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
+    SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
+
+    SIN_ADDR(ifr.ifr_addr) = oldaddr;
+
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
+    if(ioctl(sock_fd,SIOCKILLADDR,&ifr) < 0) {
+      if (!ok_error (errno))
+	error("ioctl(SIOCKILLADDR): %m(%d)", errno);
+      return;
+    }
+}
+
 /********************************************************************
  *
  * tty_disestablish_ppp - Restore the serial port to normal operation.
@@ -2385,21 +2411,29 @@
 	}
     }

-    /* set ip_dynaddr in demand mode if address changes */
-    if (demand && tune_kernel && !dynaddr_set
-	&& our_old_addr && our_old_addr != our_adr) {
+    if(persist && our_old_addr && our_old_addr != our_adr) {
+
+      if(killoldaddr)
+	do_killaddr(our_old_addr);
+
+
+      /* set ip_dynaddr in persist mode if address changes */
+      if (tune_kernel && !dynaddr_set) {
 	/* set ip_dynaddr if possible */
 	char *path;
 	int fd;

 	path = path_to_procfs("/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);
+	  if (write(fd, "1", 1) != 1)
+	    error("Couldn't enable dynamic IP addressing: %m");
+	  close(fd);
 	}
 	dynaddr_set = 1;	/* only 1 attempt */
+      }
     }
+
+    our_current_addr = our_adr;
     our_old_addr = 0;

     return 1;
@@ -2455,7 +2489,8 @@
     }

     our_old_addr = our_adr;
-
+    our_current_addr = 0;
+
     return 1;
 }


code:
diff -Nur ppp-2.4.5.orig/pppd/main.c ppp-2.4.5/pppd/main.c
--- ppp-2.4.5.orig/pppd/main.c	2010-08-08 09:34:32.000000000 +0200
+++ ppp-2.4.5/pppd/main.c	2010-08-08 09:46:00.000000000 +0200
@@ -249,6 +249,7 @@
 static void forget_child __P((int pid, int status));
 static int reap_kids __P((void));
 static void childwait_end __P((void *));
+static void wait_children __P((void));

 #ifdef USE_TDB
 static void update_db_entry __P((void));
@@ -580,25 +581,11 @@
 	    if (!persist)
 		break;
 	}
+
+	wait_children();
     }

-    /* Wait for scripts to finish */
-    reap_kids();
-    if (n_children > 0) {
-	if (child_wait > 0)
-	    TIMEOUT(childwait_end, NULL, child_wait);
-	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);
-	}
-	while (n_children > 0 && !childwait_done) {
-	    handle_events();
-	    if (kill_link && !childwait_done)
-		childwait_end(NULL);
-	}
-    }
+    wait_children();

     die(status);
     return 0;
@@ -1794,6 +1781,36 @@
 }

 /*
+ * wait_children - wait for scripts to finish.
+ * if child_wait is 0, wait indefinitely.
+ * else, kill'em all at the end of timeout
+ */
+static void
+wait_children()
+{
+    /* Wait for scripts to finish */
+    reap_kids();
+    if (n_children > 0) {
+	childwait_done = 0;
+	if (child_wait > 0)
+	    TIMEOUT(childwait_end, NULL, child_wait);
+	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);
+	}
+	while (n_children > 0 && !childwait_done) {
+	    handle_events();
+	    if (asked_to_quit && !childwait_done)
+		childwait_end(NULL);
+	}
+	if (child_wait > 0)
+	    UNTIMEOUT(childwait_end, NULL);
+    }
+}
+
+/*
  * childwait_end - we got fed up waiting for the child processes to
  * exit, send them all a SIGTERM.
  */


code:
This patch reverses revision 1.114 of the pppd/sys-linux.c file.
The default gateway is needed by the openswan's %defaultroute.
diff -Nur ppp-2.4.5.orig/pppd/sys-linux.c ppp-2.4.5/pppd/sys-linux.c
--- ppp-2.4.5.orig/pppd/sys-linux.c	2010-08-08 09:44:29.000000000 +0200
+++ ppp-2.4.5/pppd/sys-linux.c	2010-08-08 09:53:02.000000000 +0200
@@ -209,7 +209,7 @@
 static unsigned char inbuf[512]; /* buffer for chars read from loopback */

 static int	if_is_up;	/* Interface has been marked up */
-static int	have_default_route;	/* Gateway for default route added */
+static u_int32_t default_route_gateway;	/* Gateway for default route added */
 static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
 static char proxy_arp_dev[16];		/* Device for proxy arp entry */
 static u_int32_t our_old_addr;		/* for detecting address changes */
@@ -346,8 +346,8 @@
 /*
  * Delete any routes through the device.
  */
-    if (have_default_route)
-	cifdefaultroute(0, 0, 0);
+    if (default_route_gateway != 0)
+	cifdefaultroute(0, 0, default_route_gateway);

     if (has_proxy_arp)
 	cifproxyarp(0, proxy_arp_addr);
@@ -1639,17 +1639,17 @@
     struct rtentry rt;

     if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
-	if (rt.rt_flags & RTF_GATEWAY)
-	    error("not replacing existing default route via %I",
-		  SIN_ADDR(rt.rt_gateway));
-	else
-	    error("not replacing existing default route through %s",
-		  rt.rt_dev);
+	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);
+    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;

@@ -1658,14 +1658,16 @@
 	SIN_ADDR(rt.rt_genmask) = 0L;
     }

-    rt.rt_flags = RTF_UP;
+    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");
 	return 0;
     }

-    have_default_route = 1;
+    default_route_gateway = gateway;
     return 1;
 }

@@ -1678,7 +1680,7 @@
 {
     struct rtentry rt;

-    have_default_route = 0;
+    default_route_gateway = 0;

     memset (&rt, '\0', sizeof (rt));
     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
@@ -1691,7 +1693,9 @@
 	SIN_ADDR(rt.rt_genmask) = 0L;
     }

-    rt.rt_flags = RTF_UP;
+    SIN_ADDR(rt.rt_gateway) = gateway;
+
+    rt.rt_flags = RTF_UP | RTF_GATEWAY;
     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
 	if (still_ppp()) {
 	    if ( ! ok_error ( errno ))


code:
diff -Nru ppp-2.4.5.orig/pppd/auth.c ppp-2.4.5/pppd/auth.c
--- ppp-2.4.5.orig/pppd/auth.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/auth.c	2010-08-08 09:57:01.000000000 +0200
@@ -637,7 +637,7 @@
      * we delete its pid file.
      */
     if (!doing_multilink && !demand)
-	remove_pidfiles();
+	remove_pidfile(pidfilename);

     /*
      * If we may want to bring the link up again, transfer
diff -Nru ppp-2.4.5.orig/pppd/main.c ppp-2.4.5/pppd/main.c
--- ppp-2.4.5.orig/pppd/main.c	2010-08-08 09:46:42.000000000 +0200
+++ ppp-2.4.5/pppd/main.c	2010-08-08 09:57:01.000000000 +0200
@@ -134,7 +134,7 @@

 char *progname;			/* Name of this program */
 char hostname[MAXNAMELEN];	/* Our hostname */
-static char pidfilename[MAXPATHLEN];	/* name of pid file */
+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 */
@@ -245,6 +245,7 @@
 static void toggle_debug __P((int));
 static void open_ccp __P((int));
 static void bad_signal __P((int));
+static void remove_pidfilenames __P((void));
 static void holdoff_end __P((void *));
 static void forget_child __P((int pid, int status));
 static int reap_kids __P((void));
@@ -835,16 +836,24 @@
 }

 /*
- * remove_pidfile - remove our pid files
+ * remove_pidfile - remove one of the 2 pidfiles (pidfilename or linkpidfile)
  */
-void remove_pidfiles()
+void
+remove_pidfile(filename)
+    char* filename;
 {
-    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;
+    if (filename[0] != 0 && unlink(filename) < 0 && errno != ENOENT)
+	warn("unable to delete pid file %s: %m", filename);
+    filename[0] = 0;
+}
+
+/*
+ * remove_pidfiles - remove our pid files
+ */
+static void remove_pidfiles()
+{
+    remove_pidfile(pidfilename);
+    remove_pidfile(linkpidfile);
 }

 /*
diff -Nru ppp-2.4.5.orig/pppd/multilink.c ppp-2.4.5/pppd/multilink.c
--- ppp-2.4.5.orig/pppd/multilink.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/multilink.c	2010-08-08 09:57:01.000000000 +0200
@@ -267,7 +267,7 @@
 	notice("Connection terminated.");
 	print_link_stats();
 	if (!demand) {
-		remove_pidfiles();
+		remove_pidfile(pidfilename);
 		script_unsetenv("IFNAME");
 	}

diff -Nru ppp-2.4.5.orig/pppd/pppd.h ppp-2.4.5/pppd/pppd.h
--- ppp-2.4.5.orig/pppd/pppd.h	2010-08-08 09:44:29.000000000 +0200
+++ ppp-2.4.5/pppd/pppd.h	2010-08-08 09:57:01.000000000 +0200
@@ -214,6 +214,7 @@
 extern int	ifunit;		/* Interface unit number */
 extern char	ifname[];	/* Interface name */
 extern char	hostname[];	/* Our hostname */
+extern char pidfilename[];	/* name of pid file */
 extern u_char	outpacket_buf[]; /* Buffer for outgoing packets */
 extern int	devfd;		/* fd of underlying device */
 extern int	fd_ppp;		/* fd for talking PPP */
@@ -497,7 +498,7 @@
 int  ppp_send_config __P((int, int, u_int32_t, int, int));
 int  ppp_recv_config __P((int, int, u_int32_t, int, int));
 const char *protocol_name __P((int));
-void remove_pidfiles __P((void));
+void remove_pidfile __P((char *));
 void lock_db __P((void));
 void unlock_db __P((void));


code:
diff -Nru ppp-2.4.5.orig/pppd/auth.c ppp-2.4.5/pppd/auth.c
--- ppp-2.4.5.orig/pppd/auth.c	2010-08-08 09:58:19.000000000 +0200
+++ ppp-2.4.5/pppd/auth.c	2010-08-08 10:06:06.000000000 +0200
@@ -259,7 +259,7 @@
 			       struct wordlist **, struct wordlist **,
 			       char *, int));
 static void free_wordlist __P((struct wordlist *));
-static void auth_script __P((char *));
+static void auth_script __P((char *, int));
 static void auth_script_done __P((void *));
 static void set_allowed_addrs __P((int, struct wordlist *, struct wordlist *));
 static int  some_ip_ok __P((struct wordlist *));
@@ -690,7 +690,7 @@
 	if (auth_script_state == s_up && auth_script_pid == 0) {
 	    update_link_stats(unit);
 	    auth_script_state = s_down;
-	    auth_script(_PATH_AUTHDOWN);
+	    auth_script(_PATH_AUTHDOWN, 0);
 	}
     }
     if (!doing_multilink) {
@@ -822,7 +822,7 @@
 	auth_state = s_up;
 	if (auth_script_state == s_down && auth_script_pid == 0) {
 	    auth_script_state = s_up;
-	    auth_script(_PATH_AUTHUP);
+	    auth_script(_PATH_AUTHUP, 0);
 	}
     }

@@ -923,6 +923,7 @@
      * Authentication failure: take the link down
      */
     status = EXIT_PEER_AUTH_FAILED;
+    auth_script(_PATH_AUTHFAIL, 1);
     lcp_close(unit, "Authentication failed");
 }

@@ -1001,6 +1002,7 @@
      * authentication secrets.
      */
     status = EXIT_AUTH_TOPEER_FAILED;
+    auth_script(_PATH_AUTHFAIL, 1);
     lcp_close(unit, "Failed to authenticate ourselves to peer");
 }

@@ -1233,6 +1235,8 @@
     if (user[0] == 0 && !explicit_user)
 	strlcpy(user, our_name, sizeof(user));

+    script_setenv("LOCALNAME", user, 0);
+
     /*
      * If we have a default route, require the peer to authenticate
      * unless the noauth option was given or the real user is root.
@@ -2314,13 +2318,13 @@
     case s_up:
 	if (auth_state == s_down) {
 	    auth_script_state = s_down;
-	    auth_script(_PATH_AUTHDOWN);
+	    auth_script(_PATH_AUTHDOWN, 0);
 	}
 	break;
     case s_down:
 	if (auth_state == s_up) {
 	    auth_script_state = s_up;
-	    auth_script(_PATH_AUTHUP);
+	    auth_script(_PATH_AUTHUP, 0);
 	}
 	break;
     }
@@ -2331,8 +2335,9 @@
  * interface-name peer-name real-user tty speed
  */
 static void
-auth_script(script)
+auth_script(script, wait)
     char *script;
+    int wait;
 {
     char strspeed[32];
     struct passwd *pw;
@@ -2356,5 +2361,8 @@
     argv[5] = strspeed;
     argv[6] = NULL;

-    auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
+    if (wait)
+	run_program(script, argv, 0, NULL, NULL, 1);
+    else
+	auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
 }
diff -Nru ppp-2.4.5.orig/pppd/pathnames.h ppp-2.4.5/pppd/pathnames.h
--- ppp-2.4.5.orig/pppd/pathnames.h	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/pathnames.h	2010-08-08 10:06:06.000000000 +0200
@@ -27,6 +27,7 @@
 #define _PATH_IPPREUP	 _ROOT_PATH "/etc/ppp/ip-pre-up"
 #define _PATH_AUTHUP	 _ROOT_PATH "/etc/ppp/auth-up"
 #define _PATH_AUTHDOWN	 _ROOT_PATH "/etc/ppp/auth-down"
+#define _PATH_AUTHFAIL	 _ROOT_PATH "/etc/ppp/auth-fail"
 #define _PATH_TTYOPT	 _ROOT_PATH "/etc/ppp/options."
 #define _PATH_CONNERRS	 _ROOT_PATH "/etc/ppp/connect-errors"
 #define _PATH_PEERFILES	 _ROOT_PATH "/etc/ppp/peers/"
diff -Nru ppp-2.4.5.orig/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8
--- ppp-2.4.5.orig/pppd/pppd.8	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/pppd.8	2010-08-08 10:06:06.000000000 +0200
@@ -1553,8 +1553,8 @@
 Pppd invokes scripts at various stages in its processing which can be
 used to perform site-specific ancillary processing.  These scripts are
 usually shell scripts, but could be executable code files instead.
-Pppd does not wait for the scripts to finish (except for the ip-pre-up
-script).  The scripts are
+Pppd does not wait for the scripts to finish (except for the ip-pre-up,
+and auth-fail scripts).  The scripts are
 executed as root (with the real and effective user-id set to 0), so
 that they can do things such as update routing tables or run
 privileged daemons.  Be careful that the contents of these scripts do
@@ -1582,6 +1582,11 @@
 The authenticated name of the peer.  This is only set if the peer
 authenticates itself.
 .TP
+.B LOCALNAME
+The username passed to the user option of the pppd daemon.  This is
+handy to identify which account was used for authentication purposes
+when multiple accounts are available.
+.TP
 .B SPEED
 The baud rate of the tty device.
 .TP
@@ -1634,6 +1639,11 @@
 /etc/ppp/auth\-up was previously executed.  It is executed in the same
 manner with the same parameters as /etc/ppp/auth\-up.
 .TP
+.B /etc/ppp/auth\-fail
+A program or script which is executed should authentication fail.  pppd
+waits for this script to finish.  It is executed in the same manner, with
+the same parameters as /etc/ppp/auth\-up.
+.TP
 .B /etc/ppp/ip\-pre\-up
 A program or script which is executed just before the ppp network
 interface is brought up.  It is executed with the same parameters as


code:
diff -Nru ppp-2.4.5.orig/pppd/options.c ppp-2.4.5/pppd/options.c
--- ppp-2.4.5.orig/pppd/options.c	2010-08-08 09:44:29.000000000 +0200
+++ ppp-2.4.5/pppd/options.c	2010-08-08 10:07:50.000000000 +0200
@@ -94,6 +94,7 @@
 int	kdebugflag = 0;		/* Tell kernel to print debug messages */
 int	default_device = 1;	/* Using /dev/tty or equivalent */
 char	devnam[MAXPATHLEN];	/* Device name */
+int defaultmetric = 0;		/* Metric of the default route */
 bool	nodetach = 0;		/* Don't detach from controlling tty */
 bool	updetach = 0;		/* Detach once link is up */
 int	maxconnect = 0;		/* Maximum connect time */
@@ -289,6 +290,10 @@
       "Number of seconds to wait for child processes at exit",
       OPT_PRIO },

+    { "defaultmetric", o_int, &defaultmetric,
+      "The metric of the default route",
+      OPT_LIMITS, 0, 32766 },
+
 #ifdef HAVE_MULTILINK
     { "multilink", o_bool, &multilink,
       "Enable multilink operation", OPT_PRIO | 1 },
diff -Nru ppp-2.4.5.orig/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8
--- ppp-2.4.5.orig/pppd/pppd.8	2010-08-08 10:06:57.000000000 +0200
+++ ppp-2.4.5/pppd/pppd.8	2010-08-08 10:07:50.000000000 +0200
@@ -121,6 +121,9 @@
 This entry is removed when the PPP connection is broken.  This option
 is privileged if the \fInodefaultroute\fR option has been specified.
 .TP
+.B defaultmetric \fIn
+The metric of the default route configured by pppd; default is 0.
+.TP
 .B disconnect \fIscript
 Execute the command specified by \fIscript\fR, by passing it to a
 shell, after
diff -Nru ppp-2.4.5.orig/pppd/pppd.h ppp-2.4.5/pppd/pppd.h
--- ppp-2.4.5.orig/pppd/pppd.h	2010-08-08 09:58:19.000000000 +0200
+++ ppp-2.4.5/pppd/pppd.h	2010-08-08 10:07:50.000000000 +0200
@@ -276,6 +276,7 @@
 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 defaultmetric;		/* Metric of the default route */
 extern int	crtscts;	/* Use hardware flow control */
 extern bool	modem;		/* Use modem control lines */
 extern int	inspeed;	/* Input/Output speed requested */
diff -Nru ppp-2.4.5.orig/pppd/sys-linux.c ppp-2.4.5/pppd/sys-linux.c
--- ppp-2.4.5.orig/pppd/sys-linux.c	2010-08-08 09:53:56.000000000 +0200
+++ ppp-2.4.5/pppd/sys-linux.c	2010-08-08 10:07:50.000000000 +0200
@@ -1465,7 +1465,7 @@
 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_flags_col, route_mask_col, route_metric_col;
 static int route_num_cols;

 static int open_route_table (void);
@@ -1508,6 +1508,7 @@
     route_dest_col = 1;
     route_gw_col = 2;
     route_flags_col = 3;
+    route_metric_col = 6;
     route_mask_col = 7;
     route_num_cols = 8;

@@ -1527,6 +1528,8 @@
 		route_gw_col = col;
 	    else if (strcasecmp(q, "flags") == 0)
 		route_flags_col = col;
+	    else if (strcasecmp(q, "metric") == 0)
+		route_metric_col = col;
 	    else if (strcasecmp(q, "mask") == 0)
 		route_mask_col = col;
 	    else
@@ -1569,6 +1572,7 @@

     rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
     rt->rt_dev   = cols[route_dev_col];
+    rt->rt_metric = (short) strtoul(cols[route_metric_col], NULL, 16);

     return 1;
 }
@@ -1591,6 +1595,8 @@

 	if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
 	    continue;
+	if (rt->rt_metric != defaultmetric) /* consider only routes with the same metric */
+	    continue;
 	if (SIN_ADDR(rt->rt_dst) == 0L) {
 	    result = 1;
 	    break;
@@ -1661,6 +1667,7 @@
     SIN_ADDR(rt.rt_gateway) = gateway;

     rt.rt_flags = RTF_UP | RTF_GATEWAY;
+    rt.rt_metric = defaultmetric + 1; /* +1 for binary compatibility */
     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
 	if ( ! ok_error ( errno ))
 	    error("default route ioctl(SIOCADDRT): %m");
@@ -1696,6 +1703,7 @@
     SIN_ADDR(rt.rt_gateway) = gateway;

     rt.rt_flags = RTF_UP | RTF_GATEWAY;
+    rt.rt_metric = defaultmetric + 1; /* +1 for binary compatibility */
     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
 	if (still_ppp()) {
 	    if ( ! ok_error ( errno ))


code:
--- ppp-2.4.6/pppd/sys-linux.c
+++ ppp-2.4.6/pppd/sys-linux.c
@@ -2031,6 +2031,17 @@
     kernel_version = KVERSION(osmaj, osmin, ospatch);

     fd = open("/dev/ppp", O_RDWR);
+    if (fd < 0) {
+	/* try making it and see if that helps. */
+	if (errno == ENOENT && mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+		  makedev(108, 0)) >= 0) {
+	    fd = open("/dev/ppp", O_RDWR);
+	    if (fd >= 0)
+		info("Created /dev/ppp device node");
+	    else
+		unlink("/dev/ppp");     /* didn't work, undo the mknod */
+	}
+    }
     if (fd >= 0) {
 	new_style_driver = 1;


code:
diff -Nru ppp-2.4.5.orig/pppd/plugins/passwordfd.c ppp-2.4.5/pppd/plugins/passwordfd.c
--- ppp-2.4.5.orig/pppd/plugins/passwordfd.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/plugins/passwordfd.c	2010-08-08 10:41:39.000000000 +0200
@@ -16,11 +16,11 @@

 char pppd_version[] = VERSION;

-static int passwdfd = -1;
 static char save_passwd[MAXSECRETLEN];

+static int readpassword __P((char **));
 static option_t options[] = {
-    { "passwordfd", o_int, &passwdfd,
+    { "passwordfd", o_special, (void *)readpassword,
       "Receive password on this file descriptor" },
     { NULL }
 };
@@ -30,43 +30,39 @@
     return 1;
 }

-static int pwfd_passwd (char *user, char *passwd)
+static int readpassword(char **argv)
 {
-    int readgood, red;
-
-    if (passwdfd == -1)
-	return -1;
-
-    if (passwd == NULL)
-	return 1;
-
-    if (passwdfd == -2) {
-	strcpy (passwd, save_passwd);
-	return 1;
+    char *arg = *argv;
+    int passwdfd = -1;
+    int chunk, len;
+
+    if (sscanf(arg, "%d", &passwdfd) != 1 || passwdfd < 0)
+    {
+	error ("\"%s\" is not a valid file descriptor number", arg);
+	return 0;
     }

-    readgood = 0;
+    len = 0;
     do {
-	red = read (passwdfd, passwd + readgood, MAXSECRETLEN - 1 - readgood);
-	if (red == 0)
-	    break;
-	if (red < 0) {
-	    error ("Can't read secret from fd\n");
-	    readgood = -1;
+	chunk = read (passwdfd, save_passwd + len, MAXSECRETLEN - 1 - len);
+	if (chunk == 0)
 	    break;
+	if (chunk < 0) {
+	    error ("Can't read secret from fd %d", passwdfd);
+	    return 0;
 	}
-	readgood += red;
-    } while (readgood < MAXSECRETLEN - 1);
-
+	len += chunk;
+    } while (len < MAXSECRETLEN - 1);
+    save_passwd[len] = 0;
     close (passwdfd);

-    if (readgood < 0)
-	return 0;
-
-    passwd[readgood] = 0;
-    strcpy (save_passwd, passwd);
-    passwdfd = -2;
+    return 1;
+}

+static int pwfd_passwd (char *user, char *passwd)
+{
+    if (passwd != NULL)
+	strcpy (passwd, save_passwd);
     return 1;
 }


code:
--- ppp-2.4.6/pppd/ipcp.c
+++ ppp-2.4.6/pppd/ipcp.c
@@ -91,6 +91,7 @@
 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 bool usepeerwins;		/* Ask peer for WINS addrs */
 static int ipcp_is_up;			/* have called np_up() */
 static int ipcp_is_open;		/* haven't called np_finished() */
 static bool ask_for_local;		/* request our address from peer */
@@ -210,6 +211,9 @@
     { "usepeerdns", o_bool, &usepeerdns,
       "Ask peer for DNS address(es)", 1 },

+    { "usepeerwins", o_bool, &usepeerwins,
+      "Ask peer for WINS address(es)", 1 },
+
     { "netmask", o_special, (void *)setnetmask,
       "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str },

@@ -703,6 +707,8 @@
 	wo->accept_remote = 1;
     wo->req_dns1 = usepeerdns;	/* Request DNS addresses from the peer */
     wo->req_dns2 = usepeerdns;
+    wo->req_wins1 = usepeerwins; /* Request WINS addresses from the peer */
+    wo->req_wins2 = usepeerwins;
     *go = *wo;
     if (!ask_for_local)
 	go->ouraddr = 0;
@@ -755,8 +761,8 @@
 	    LENCIADDR(go->neg_addr) +
 	    LENCIDNS(go->req_dns1) +
 	    LENCIDNS(go->req_dns2) +
-	    LENCIWINS(go->winsaddr[0]) +
-	    LENCIWINS(go->winsaddr[1])) ;
+	    LENCIWINS(go->req_wins1) +
+	    LENCIWINS(go->req_wins2)) ;
 }

@@ -830,8 +836,8 @@
 	    neg = 0; \
     }

-#define ADDCIWINS(opt, addr) \
-    if (addr) { \
+#define ADDCIWINS(opt, neg, addr) \
+    if (neg) { \
 	if (len >= CILEN_ADDR) { \
 	    u_int32_t l; \
 	    PUTCHAR(opt, ucp); \
@@ -840,7 +846,7 @@
 	    PUTLONG(l, ucp); \
 	    len -= CILEN_ADDR; \
 	} else \
-	    addr = 0; \
+	    neg = 0; \
     }

     ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
@@ -855,9 +861,9 @@

     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);

-    ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    ADDCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);

-    ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    ADDCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);

     *lenp -= len;
 }
@@ -962,8 +968,8 @@
 	    goto bad; \
     }

-#define ACKCIWINS(opt, addr) \
-    if (addr) { \
+#define ACKCIWINS(opt, neg, addr) \
+    if (neg) { \
 	u_int32_t l; \
 	if ((len -= CILEN_ADDR) < 0) \
 	    goto bad; \
@@ -989,9 +995,9 @@

     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);

-    ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    ACKCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);

-    ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    ACKCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);

     /*
      * If there are any remaining CIs, then this packet is bad.
@@ -1026,7 +1032,7 @@
     u_char cimaxslotindex, cicflag;
     u_char citype, cilen, *next;
     u_short cishort;
-    u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
+    u_int32_t ciaddr1, ciaddr2, l, cidnsaddr, ciwinsaddr;
     ipcp_options no;		/* options we've seen Naks for */
     ipcp_options try;		/* options to request next time */

@@ -1091,6 +1097,19 @@
 	code \
     }

+#define NAKCIWINS(opt, neg, code) \
+    if (go->neg && \
+	((cilen = p[1]) == CILEN_ADDR) && \
+	len >= cilen && \
+	p[0] == opt) { \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	ciwinsaddr = 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.
@@ -1167,6 +1186,22 @@
 	     }
 	     );

+    NAKCIWINS(CI_MS_WINS1, req_wins1,
+	     if (treat_as_reject) {
+		 try.req_wins1 = 0;
+	     } else {
+		 try.winsaddr[0] = ciwinsaddr;
+	     }
+	     );
+
+    NAKCIWINS(CI_MS_WINS2, req_wins2,
+	     if (treat_as_reject) {
+		 try.req_wins2 = 0;
+	     } else {
+		 try.winsaddr[1] = ciwinsaddr;
+	     }
+	     );
+
     /*
      * There may be remaining CIs, if the peer is requesting negotiation
      * on an option that we didn't include in our request packet.
@@ -1259,7 +1294,6 @@
     return 0;
 }

-
 /*
  * ipcp_rejci - Reject some of our CIs.
  * Callback from fsm_rconfnakrej.
@@ -1357,8 +1391,8 @@
 	try.neg = 0; \
     }

-#define REJCIWINS(opt, addr) \
-    if (addr && \
+#define REJCIWINS(opt, neg, addr) \
+    if (go->neg && \
 	((cilen = p[1]) == CILEN_ADDR) && \
 	len >= cilen && \
 	p[0] == opt) { \
@@ -1370,7 +1404,7 @@
 	/* Check rejected value. */ \
 	if (cilong != addr) \
 	    goto bad; \
-	try.winsaddr[opt == CI_MS_WINS2] = 0; \
+	try.neg = 0; \
     }

     REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
@@ -1385,9 +1419,9 @@

     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);

-    REJCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    REJCIWINS(CI_MS_WINS1, req_wins1, go->winsaddr[0]);

-    REJCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    REJCIWINS(CI_MS_WINS2, req_wins2, go->winsaddr[1]);

     /*
      * If there are any remaining CIs, then this packet is bad.
@@ -1581,7 +1615,7 @@
 	    /* 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 we do not have a WINS address then we cannot send it */
 	    if (ao->winsaddr[d] == 0 ||
 		cilen != CILEN_ADDR) {	/* Check CI length */
 		orc = CONFREJ;		/* Reject CI */
@@ -1830,6 +1864,13 @@
 	create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
     }

+    if (go->winsaddr[0])
+        script_setenv("WINS1", ip_ntoa(go->winsaddr[0]), 0);
+    if (go->winsaddr[1])
+        script_setenv("WINS2", ip_ntoa(go->winsaddr[1]), 0);
+    if (usepeerwins && (go->winsaddr[0] || go->winsaddr[1]))
+        script_setenv("USEPEERWINS", "1", 0);
+
     /*
      * Check that the peer is allowed to use the IP address it wants.
      */
--- ppp-2.4.6/pppd/ipcp.h
+++ ppp-2.4.6/pppd/ipcp.h
@@ -77,6 +77,8 @@
     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? */
+    bool req_wins1;		/* Ask peer to send primary WINS address? */
+    bool req_wins2;		/* Ask peer to send secondary WINS address? */
     int  vj_protocol;		/* protocol value to use in VJ option */
     int  maxslotindex;		/* values for RFC1332 VJ compression neg. */
     bool cflag;
--- ppp-2.4.6/pppd/pppd.8
+++ ppp-2.4.6/pppd/pppd.8
@@ -1102,6 +1102,16 @@
 /etc/ppp/resolv.conf file containing one or two nameserver lines with
 the address(es) supplied by the peer.
 .TP
+.B usepeerwins
+Ask the peer for up to 2 WINS server addresses.  The addresses supplied
+by the peer (if any) are passed to the /etc/ppp/ip\-up script in the
+environment variables WINS1 and WINS2, and the environment variable
+USEPEERWINS will be set to 1.
+.LP
+Please note that some modems (like the Huawei E220) requires this option in
+order to avoid a race condition that results in the incorrect DNS servers
+being assigned.
+.TP
 .B user \fIname
 Sets the name used for authenticating the local system to the peer to
 \fIname\fR.
@@ -1650,6 +1660,15 @@
 If the peer supplies DNS server addresses, this variable is set to the
 second DNS server address supplied (whether or not the usepeerdns
 option was given).
+.TP
+.B WINS1
+If the peer supplies WINS server addresses, this variable is set to the
+first WINS server address supplied.
+.TP
+.B WINS2
+If the peer supplies WINS server addresses, this variable is set to the
+second WINS server address supplied.
+.P
 .P
 Pppd invokes the following scripts, if they exist.  It is not an error
 if they don't exist.


code:
diff -Nru ppp-2.4.5.orig/pppd/pathnames.h ppp-2.4.5/pppd/pathnames.h
--- ppp-2.4.5.orig/pppd/pathnames.h	2010-08-08 10:06:57.000000000 +0200
+++ ppp-2.4.5/pppd/pathnames.h	2010-08-08 10:53:51.000000000 +0200
@@ -29,7 +29,7 @@
 #define _PATH_AUTHDOWN	 _ROOT_PATH "/etc/ppp/auth-down"
 #define _PATH_AUTHFAIL	 _ROOT_PATH "/etc/ppp/auth-fail"
 #define _PATH_TTYOPT	 _ROOT_PATH "/etc/ppp/options."
-#define _PATH_CONNERRS	 _ROOT_PATH "/etc/ppp/connect-errors"
+#define _PATH_CONNERRS	 _ROOT_PATH "/var/log/ppp-connect-errors"
 #define _PATH_PEERFILES	 _ROOT_PATH "/etc/ppp/peers/"
 #define _PATH_RESOLV	 _ROOT_PATH "/etc/ppp/resolv.conf"


code:
Ensure that the build process aborts if there is an error in one of
the plugin subdirectories.

2010-09-01 Martin von Gagern

References:
http://bugs.gentoo.org/334727

Index: ppp-2.4.5/pppd/plugins/Makefile.linux
===================================================================
--- ppp-2.4.5.orig/pppd/plugins/Makefile.linux
+++ ppp-2.4.5/pppd/plugins/Makefile.linux
@@ -20,7 +20,7 @@ include .depend
 endif

 all:	$(PLUGINS)
-	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all; done
+	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all || exit $?; done

 %.so: %.c
 	$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^
@@ -30,12 +30,12 @@ VERSION = $(shell awk -F '"' '/VERSION/
 install: $(PLUGINS)
 	$(INSTALL) -d $(LIBDIR)
 	$(INSTALL) $? $(LIBDIR)
-	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install; done
+	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install || exit $?; done

 clean:
 	rm -f *.o *.so *.a
-	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean; done
+	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean || exit $?; done

 depend:
 	$(CPP) -M $(CFLAGS) *.c >.depend
-	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend; done
+	for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend || exit $?; done


code:
--- ppp-2.4.6/pppd/plugins/rp-pppoe/discovery.c
+++ ppp-2.4.6/pppd/plugins/rp-pppoe/discovery.c
@@ -39,6 +39,7 @@
 #endif

 #include <signal.h>
+#include <time.h>

 /* Calculate time remaining until *exp, return 0 if now >= *exp */
 static int time_left(struct timeval *diff, struct timeval *exp)
@@ -251,6 +252,80 @@
 }

 /***********************************************************************
+*%FUNCTION: recvPacketForMe
+*%ARGUMENTS:
+* packet -- output parameter
+* len -- output parameter length
+* conn -- connection
+* start -- operation startup timestamp
+* timeout -- how long to wait (in seconds)
+*%RETURNS:
+* -1:  error
+*  0:  timed out
+*  1:  packet received
+*%DESCRIPTION:
+* receive and filter junk packets
+***********************************************************************/
+
+static int
+recvPacketForMe(PPPoEPacket *packet, int *len, PPPoEConnection *conn, time_t start, int timeout)
+{
+    fd_set readable;
+    int r;
+    struct timeval tv;
+    time_t now;
+    int time_remain;
+
+    do {
+	time(&now);
+	time_remain = timeout - (int)difftime(now, start);
+	if (time_remain <= 0) return 0;  /* Timed out */
+
+	if (BPF_BUFFER_IS_EMPTY) {
+	    tv.tv_sec = time_remain;
+	    tv.tv_usec = 0;
+
+	    FD_ZERO(&readable);
+	    FD_SET(conn->discoverySocket, &readable);
+
+	    r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
+	    if (r < 0)
+	    {
+		if (errno == EINTR)
+		{
+		    continue;   /* interrupted, so retry */
+		}else
+		{
+		    error("pppoe: recvPacketForMe: select: %m");
+		    return -1;
+		}
+	    }
+
+	    if (r == 0) return 0;	/* Timed out */
+	}
+
+	/* Get the packet */
+	receivePacket(conn->discoverySocket, packet, len);
+
+	/* Check length */
+	if (ntohs(packet->length) + HDR_SIZE > *len) {
+	    error("Bogus PPPoE length field (%u)",
+		   (unsigned int) ntohs(packet->length));
+	    continue;
+	}
+
+#ifdef USE_BPF
+	/* If it's not a Discovery packet, loop again */
+	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
+#endif
+	/* If it's not for us, loop again */
+	}while ( ! packetIsForMe(conn, packet));
+
+	return 1;
+}
+
+
+/***********************************************************************
 *%FUNCTION: sendPADI
 *%ARGUMENTS:
 * conn -- PPPoEConnection structure
@@ -344,13 +419,12 @@
 void
 waitForPADO(PPPoEConnection *conn, int timeout)
 {
-    fd_set readable;
     int r;
-    struct timeval tv;
     struct timeval expire_at;

     PPPoEPacket packet;
     int len;
+    time_t start;

     struct PacketCriteria pc;
     pc.conn          = conn;
@@ -367,43 +441,10 @@
     }
     expire_at.tv_sec += timeout;

+    time(&start);
     do {
-	if (BPF_BUFFER_IS_EMPTY) {
-	    if (!time_left(&tv, &expire_at))
-		return;		/* Timed out */
-
-	    FD_ZERO(&readable);
-	    FD_SET(conn->discoverySocket, &readable);
-
-	    while(1) {
-		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
-		if (r >= 0 || errno != EINTR) break;
-	    }
-	    if (r < 0) {
-		error("select (waitForPADO): %m");
-		return;
-	    }
-	    if (r == 0)
-		return;		/* Timed out */
-	}
-
-	/* Get the packet */
-	receivePacket(conn->discoverySocket, &packet, &len);
-
-	/* Check length */
-	if (ntohs(packet.length) + HDR_SIZE > len) {
-	    error("Bogus PPPoE length field (%u)",
-		   (unsigned int) ntohs(packet.length));
-	    continue;
-	}
-
-#ifdef USE_BPF
-	/* If it's not a Discovery packet, loop again */
-	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
-#endif
-
-	/* If it's not for us, loop again */
-	if (!packetIsForMe(conn, &packet)) continue;
+	r = recvPacketForMe(&packet, &len, conn, start, timeout);
+	if (r<=0) return;  /* Timed out or error */

 	if (packet.code == CODE_PADO) {
 	    if (NOT_UNICAST(packet.ethHdr.h_source)) {
@@ -537,13 +578,12 @@
 static void
 waitForPADS(PPPoEConnection *conn, int timeout)
 {
-    fd_set readable;
     int r;
-    struct timeval tv;
     struct timeval expire_at;

     PPPoEPacket packet;
     int len;
+    time_t start;

     if (gettimeofday(&expire_at, NULL) < 0) {
 	error("gettimeofday (waitForPADS): %m");
@@ -551,48 +591,15 @@
     }
     expire_at.tv_sec += timeout;

+    time(&start);
     conn->error = 0;
     do {
-	if (BPF_BUFFER_IS_EMPTY) {
-	    if (!time_left(&tv, &expire_at))
-		return;		/* Timed out */
-
-	    FD_ZERO(&readable);
-	    FD_SET(conn->discoverySocket, &readable);
-
-	    while(1) {
-		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
-		if (r >= 0 || errno != EINTR) break;
-	    }
-	    if (r < 0) {
-		error("select (waitForPADS): %m");
-		return;
-	    }
-	    if (r == 0)
-		return;		/* Timed out */
-	}
-
-	/* Get the packet */
-	receivePacket(conn->discoverySocket, &packet, &len);
-
-	/* Check length */
-	if (ntohs(packet.length) + HDR_SIZE > len) {
-	    error("Bogus PPPoE length field (%u)",
-		   (unsigned int) ntohs(packet.length));
-	    continue;
-	}
-
-#ifdef USE_BPF
-	/* If it's not a Discovery packet, loop again */
-	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
-#endif
+	r = recvPacketForMe(&packet, &len, conn, start, timeout);
+	if (r<=0) return;  /* Timed out or error */

 	/* If it's not from the AC, it's not for me */
 	if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue;

-	/* If it's not for us, loop again */
-	if (!packetIsForMe(conn, &packet)) continue;
-
 	/* Is it PADS?  */
 	if (packet.code == CODE_PADS) {
 	    /* Parse for goodies */
--- ppp-2.4.6/pppd/plugins/rp-pppoe/pppoe-discovery.c
+++ ppp-2.4.6/pppd/plugins/rp-pppoe/pppoe-discovery.c
@@ -14,6 +14,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
+#include <time.h>

 #include "pppoe.h"

@@ -513,6 +514,8 @@
     struct timeval tv;
     PPPoEPacket packet;
     int len;
+    time_t start, now;
+    int time_remain;

     struct PacketCriteria pc;
     pc.conn          = conn;
@@ -522,9 +525,13 @@
     pc.seenServiceName = 0;
     conn->error = 0;

+    time(&start);
     do {
+	time(&now);
+	time_remain = timeout - (int)difftime(now, start);
+	if (time_remain <= 0) return;	/* Timed out */
 	if (BPF_BUFFER_IS_EMPTY) {
-	    tv.tv_sec = timeout;
+	    tv.tv_sec = time_remain;
 	    tv.tv_usec = 0;

 	    FD_ZERO(&readable);


code:
diff -Nru ppp-2.4.5.orig/pppd/lcp.c ppp-2.4.5/pppd/lcp.c
--- ppp-2.4.5.orig/pppd/lcp.c	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/lcp.c	2010-11-27 10:46:26.000000000 +0100
@@ -73,6 +73,7 @@
  */
 int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
 int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
+bool	lcp_echo_adaptive = 0;	/* request echo only if the link was idle */
 bool	lax_recv = 0;		/* accept control chars in asyncmap */
 bool	noendpoint = 0;		/* don't send/accept endpoint discriminator */

@@ -151,6 +152,8 @@
       OPT_PRIO },
     { "lcp-echo-interval", o_int, &lcp_echo_interval,
       "Set time in seconds between LCP echo requests", OPT_PRIO },
+    { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive,
+      "Suppress LCP echo requests if traffic was received", 1 },
     { "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,
@@ -2322,6 +2325,22 @@
     }

     /*
+     * If adaptive echos have been enabled, only send the echo request if
+     * no traffic was received since the last one.
+     */
+    if (lcp_echo_adaptive) {
+       static unsigned int last_pkts_in = 0;
+
+       update_link_stats(f->unit);
+       link_stats_valid = 0;
+
+       if (link_stats.pkts_in != last_pkts_in) {
+           last_pkts_in = link_stats.pkts_in;
+           return;
+       }
+    }
+
+    /*
      * Make and send the echo request frame.
      */
     if (f->state == OPENED) {
diff -Nru ppp-2.4.5.orig/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8
--- ppp-2.4.5.orig/pppd/pppd.8	2009-11-16 23:26:07.000000000 +0100
+++ ppp-2.4.5/pppd/pppd.8	2010-11-27 10:44:58.000000000 +0100
@@ -549,6 +549,11 @@
 dynamic IP address option (i.e. set /proc/sys/net/ipv4/ip_dynaddr to
 1) in demand mode if the local address changes.
 .TP
+.B lcp\-echo\-adaptive
+If this option is used with the \fIlcp\-echo\-failure\fR option then
+pppd will send LCP echo\-request frames only if no traffic was received
+from the peer since the last echo\-request was sent.
+.TP
 .B lcp\-echo\-failure \fIn
 If this option is given, pppd will presume the peer to be dead
 if \fIn\fR LCP echo\-requests are sent without receiving a valid LCP