diff -Naur ppp-2.4.5.0/pppd/chap-new.c ppp-2.4.5/pppd/chap-new.c --- ppp-2.4.5.0/pppd/chap-new.c 2012-04-18 15:44:46.000000000 +0800 +++ ppp-2.4.5/pppd/chap-new.c 2012-04-19 20:24:28.000000000 +0800 @@ -37,6 +37,8 @@ #include "chap-new.h" #include "chap-md5.h" +#include "syncppp.h" + #ifdef CHAPMS #include "chap_ms.h" #define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) @@ -481,6 +483,19 @@ p[2] = len >> 8; p[3] = len; + if (npppd > 1) { + if (syncppp(npppd) < 0) { + error("syncppp sync fail"); + sem_unlink(SEM_COUNT_NAME); + sem_unlink(SEM_BLOCK_NAME); + } else { + info("syncppp sync succeeded"); + } + } else { + info("syncppp not active"); + } + + output(0, response, PPP_HDRLEN + len); } diff -Naur ppp-2.4.5.0/pppd/Makefile.linux ppp-2.4.5/pppd/Makefile.linux --- ppp-2.4.5.0/pppd/Makefile.linux 2012-04-18 15:44:46.000000000 +0800 +++ ppp-2.4.5/pppd/Makefile.linux 2012-04-19 20:01:05.000000000 +0800 @@ -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 syncppp.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 syncppp.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 syncppp.o # # include dependencies if present @@ -33,7 +33,7 @@ # CC = gcc # COPTS = -O2 -pipe -Wall -g -LIBS = +LIBS = -lpthread # Uncomment the next 2 lines to include support for Microsoft's # MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. diff -Naur ppp-2.4.5.0/pppd/options.c ppp-2.4.5/pppd/options.c --- ppp-2.4.5.0/pppd/options.c 2012-04-18 15:44:46.000000000 +0800 +++ ppp-2.4.5/pppd/options.c 2012-04-19 20:24:49.000000000 +0800 @@ -126,6 +126,7 @@ bool dryrun; /* print out option values and exit */ char *domain; /* domain name set by domain option */ int child_wait = 5; /* # seconds to wait for children at exit */ +int npppd = 0; /* synchronize between multiple pppd */ struct userenv *userenv_list; /* user environment variables */ #ifdef MAXOCTETS @@ -311,6 +312,10 @@ "Set pathname of ipv6-down script", OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, + { "syncppp", o_int, &npppd, + "sync among multiple pppd when sending chap/pap respond", OPT_PRIO }, + + #ifdef HAVE_MULTILINK { "multilink", o_bool, &multilink, "Enable multilink operation", OPT_PRIO | 1 }, diff -Naur ppp-2.4.5.0/pppd/pppd.h ppp-2.4.5/pppd/pppd.h --- ppp-2.4.5.0/pppd/pppd.h 2012-04-18 15:44:46.000000000 +0800 +++ ppp-2.4.5/pppd/pppd.h 2012-04-19 20:25:02.000000000 +0800 @@ -327,6 +327,7 @@ extern bool dump_options; /* print out option values */ extern bool dryrun; /* check everything, print options, exit */ extern int child_wait; /* # seconds to wait for children at end */ +extern int npppd; /* synchronize between multiple pppd */ #ifdef MAXOCTETS extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ diff -Naur ppp-2.4.5.0/pppd/syncppp.c ppp-2.4.5/pppd/syncppp.c --- ppp-2.4.5.0/pppd/syncppp.c 1970-01-01 08:00:00.000000000 +0800 +++ ppp-2.4.5/pppd/syncppp.c 2012-04-18 15:46:59.000000000 +0800 @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include "pppd.h" +#include "syncppp.h" + +int syncppp(int nproc) +{ + int flags; + int value; + sem_t *block; + sem_t *count; + struct timespec ts; + + if (nproc <= 1) { + error("syncppp: number of pppd should be larger than 1"); + return -1; + } + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + error("clock_gettime error"); + return -1; + } + ts.tv_sec += SYNCPPP_TIMEOUT; + + + flags = O_RDWR | O_CREAT; + block = sem_open(SEM_BLOCK_NAME, flags, 0644, 0); + count = sem_open(SEM_COUNT_NAME, flags, 0644, 0); + if (block == SEM_FAILED || count == SEM_FAILED) { + error("syncppp: sem_open failed"); + return -1; + } + + if (sem_post(count) < 0) { + error("syncppp: sem_post failed"); + return -1; + } + if (sem_getvalue(count, &value) < 0) { + error("syncppp: sem_getvalue failed"); + return -1; + } + info("%d pppd have arrived, waiting for the left %d", value, nproc-value); + if (value >= nproc) { + while (nproc-1 > 0) { + if (sem_post(block) < 0) { + error("syncppp: sem_post failed"); + return -1; + } + nproc--; + } + } else { + if (sem_timedwait(block, &ts) < 0) { + if (errno == ETIMEDOUT) { + error("syncppp: sem_timewait time out"); + } else { + error("syncppp: sem_timewait error"); + } + return -1; + } + + } + + sem_close(count); + sem_close(block); + + sem_unlink(SEM_COUNT_NAME); + sem_unlink(SEM_BLOCK_NAME); + + return 0; +} + diff -Naur ppp-2.4.5.0/pppd/syncppp.h ppp-2.4.5/pppd/syncppp.h --- ppp-2.4.5.0/pppd/syncppp.h 1970-01-01 08:00:00.000000000 +0800 +++ ppp-2.4.5/pppd/syncppp.h 2012-04-18 15:46:59.000000000 +0800 @@ -0,0 +1,3 @@ +#define SEM_BLOCK_NAME "block" +#define SEM_COUNT_NAME "count" +#define SYNCPPP_TIMEOUT 5 diff -Naur ppp-2.4.5.0/pppd/upap.c ppp-2.4.5/pppd/upap.c --- ppp-2.4.5.0/pppd/upap.c 2012-04-18 15:44:46.000000000 +0800 +++ ppp-2.4.5/pppd/upap.c 2012-04-19 20:26:22.000000000 +0800 @@ -52,6 +52,8 @@ #include "pppd.h" #include "upap.h" +#include "syncppp.h" + static const char rcsid[] = RCSID; static bool hide_password = 1; @@ -568,6 +570,18 @@ PUTCHAR(u->us_passwdlen, outp); BCOPY(u->us_passwd, outp, u->us_passwdlen); + if (npppd > 1) { + if (syncppp(npppd) < 0) { + error("syncppp sync fail"); + sem_unlink(SEM_COUNT_NAME); + sem_unlink(SEM_BLOCK_NAME); + } else { + info("syncppp sync succeeded"); + } + } else { + info("syncppp not active"); + } + output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); TIMEOUT(upap_timeout, u, u->us_timeouttime);