PKG_NAME:=ppp
PKG_VERSION:=2.4.3
-PKG_RELEASE:=4
+PKG_RELEASE:=5
PKG_MD5SUM:=848f6c3cafeb6074ffeb293c3af79b7c
PKG_SOURCE_URL:=ftp://ftp.samba.org/pub/ppp/
--- /dev/null
+From: Simon Peter <dn.tlp@gmx.net>
+Subject: Bug#306261: pppd does not properly close /dev/ppp on persist
+
+When using the kernel PPPoE driver, pppd never
+closes /dev/ppp when the link has come down.
+
+It opens superfluous fds to the device each time it re-opens the
+connection, with the unclosed ones falsely reported always ready for
+data by select().
+
+This makes pppd eat up 100% CPU time after the first persist because of
+the always instantly returning select() on the unclosed fds.
+
+The problem also occurs with the upstream version, but does not occur
+when a pty/tty device is used for the ppp connection.
+
+
+diff -u -r ppp-2.4.3/pppd/sys-linux.c ppp-2.4.3/pppd/sys-linux.c
+--- ppp-2.4.3/pppd/sys-linux.c 2005-04-29 20:08:37.000000000 +0200
++++ ppp-2.4.3/pppd/sys-linux.c 2005-04-29 20:07:03.000000000 +0200
+@@ -455,6 +455,13 @@
+ if (new_style_driver) {
+ int flags;
+
++ /* if a ppp_fd is already open, close it first */
++ if(ppp_fd > 0) {
++ close(ppp_fd);
++ remove_fd(ppp_fd);
++ ppp_fd = -1;
++ }
++
+ /* Open an instance of /dev/ppp and connect the channel to it */
+ if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
+ error("Couldn't get channel number: %m");
--- /dev/null
+diff -ruNp ppp-2.4.3.orig/pppd/ipcp.c ppp-2.4.3/pppd/ipcp.c
+--- ppp-2.4.3.orig/pppd/ipcp.c 2004-11-13 13:03:26.000000000 +0100
++++ ppp-2.4.3/pppd/ipcp.c 2005-02-20 18:45:22.241810136 +0100
+@@ -1846,7 +1846,7 @@ ipcp_up(f)
+ */
+ if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP);
++ ipcp_script(path_ipup);
+ }
+ }
+
+@@ -1896,7 +1896,7 @@ ipcp_down(f)
+ /* Execute the ip-down script */
+ if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
+ ipcp_script_state = s_down;
+- ipcp_script(_PATH_IPDOWN);
++ ipcp_script(path_ipdown);
+ }
+ }
+
+@@ -1950,13 +1950,13 @@ ipcp_script_done(arg)
+ case s_up:
+ if (ipcp_fsm[0].state != OPENED) {
+ ipcp_script_state = s_down;
+- ipcp_script(_PATH_IPDOWN);
++ ipcp_script(path_ipdown);
+ }
+ break;
+ case s_down:
+ if (ipcp_fsm[0].state == OPENED) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP);
++ ipcp_script(path_ipup);
+ }
+ break;
+ }
+diff -ruNp ppp-2.4.3.orig/pppd/main.c ppp-2.4.3/pppd/main.c
+--- ppp-2.4.3.orig/pppd/main.c 2005-02-20 18:46:14.409879384 +0100
++++ ppp-2.4.3/pppd/main.c 2005-02-20 18:45:22.243809832 +0100
+@@ -314,6 +314,9 @@ main(argc, argv)
+ struct protent *protp;
+ char numbuf[16];
+
++ strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
++ strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
++
+ link_stats_valid = 0;
+ new_phase(PHASE_INITIALIZE);
+
+diff -ruNp ppp-2.4.3.orig/pppd/options.c ppp-2.4.3/pppd/options.c
+--- ppp-2.4.3.orig/pppd/options.c 2005-02-20 18:46:14.410879232 +0100
++++ ppp-2.4.3/pppd/options.c 2005-02-20 18:46:02.154742448 +0100
+@@ -108,6 +108,8 @@ char linkname[MAXPATHLEN]; /* logical na
+ 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 */
++char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
++char path_ipdown[MAXPATHLEN];/* pathname of ip-down script */
+ bool multilink = 0; /* Enable multilink operation */
+ char *bundle_name = NULL; /* bundle name for multilink */
+ bool dump_options; /* print out option values */
+@@ -276,6 +278,13 @@ option_t general_options[] = {
+ "Number of seconds to wait for child processes at exit",
+ OPT_PRIO },
+
++ { "ip-up-script", o_string, path_ipup,
++ "Set pathname of ip-up script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++ { "ip-down-script", o_string, path_ipdown,
++ "Set pathname of ip-down script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++
+ #ifdef HAVE_MULTILINK
+ { "multilink", o_bool, &multilink,
+ "Enable multilink operation", OPT_PRIO | 1 },
+diff -ruNp ppp-2.4.3.orig/pppd/pppd.h ppp-2.4.3/pppd/pppd.h
+--- ppp-2.4.3.orig/pppd/pppd.h 2005-02-20 18:46:14.414878624 +0100
++++ ppp-2.4.3/pppd/pppd.h 2005-02-20 18:45:22.247809224 +0100
+@@ -312,6 +312,8 @@ extern bool tune_kernel; /* May alter ke
+ 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 char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
++extern char path_ipdown[MAXPATHLEN]; /* pathname of ip-down script */
+ extern bool multilink; /* enable multilink operation */
+ extern bool noendpoint; /* don't send or accept endpt. discrim. */
+ extern char *bundle_name; /* bundle name for multilink */
--- /dev/null
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c 2005-02-24 21:00:11.586697752 +0100
+@@ -365,8 +365,8 @@ waitForPADO(PPPoEConnection *conn, int t
+ if (!packetIsForMe(conn, &packet)) continue;
+
+ if (packet.code == CODE_PADO) {
+- if (NOT_UNICAST(packet.ethHdr.h_source)) {
+- printErr("Ignoring PADO packet from non-unicast MAC address");
++ if (BROADCAST(packet.ethHdr.h_source)) {
++ printErr("Ignoring PADO packet from broadcast MAC address");
+ continue;
+ }
+ parsePacket(&packet, parsePADOTags, &pc);
--- /dev/null
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/common.c ppp-2.4.3/pppd/plugins/rp-pppoe/common.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/common.c 2004-02-02 04:36:46.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/common.c 2005-03-11 02:09:19.000000000 +0100
+@@ -18,10 +18,6 @@ static char const RCSID[] =
+
+ #include "pppoe.h"
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <string.h>
+ #include <errno.h>
+ #include <stdlib.h>
+@@ -50,17 +46,17 @@ parsePacket(PPPoEPacket *packet, ParseFu
+ UINT16_t tagType, tagLen;
+
+ if (packet->ver != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
++ error("Invalid PPPoE version (%u)", packet->ver);
+ return -1;
+ }
+ if (packet->type != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
++ error("Invalid PPPoE type (%u)", packet->type);
+ return -1;
+ }
+
+ /* Do some sanity checks on packet */
+ if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
+- syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
++ error("Invalid PPPoE packet length (%u)", len);
+ return -1;
+ }
+
+@@ -76,7 +72,7 @@ parsePacket(PPPoEPacket *packet, ParseFu
+ return 0;
+ }
+ if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
+- syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
++ error("Invalid PPPoE tag length (%u)", tagLen);
+ return -1;
+ }
+ func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
+@@ -105,17 +101,17 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ UINT16_t tagType, tagLen;
+
+ if (packet->ver != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
++ error("Invalid PPPoE version (%u)", packet->ver);
+ return NULL;
+ }
+ if (packet->type != 1) {
+- syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
++ error("Invalid PPPoE type (%u)", packet->type);
+ return NULL;
+ }
+
+ /* Do some sanity checks on packet */
+ if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
+- syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
++ error("Invalid PPPoE packet length (%u)", len);
+ return NULL;
+ }
+
+@@ -131,7 +127,7 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ return NULL;
+ }
+ if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
+- syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
++ error("Invalid PPPoE tag length (%u)", tagLen);
+ return NULL;
+ }
+ if (tagType == type) {
+@@ -143,6 +139,7 @@ findTag(PPPoEPacket *packet, UINT16_t ty
+ return NULL;
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: printErr
+ *%ARGUMENTS:
+@@ -158,6 +155,7 @@ printErr(char const *str)
+ fprintf(stderr, "pppoe: %s\n", str);
+ syslog(LOG_ERR, "%s", str);
+ }
++#endif
+
+
+ /**********************************************************************
+@@ -172,7 +170,7 @@ strDup(char const *str)
+ {
+ char *copy = malloc(strlen(str)+1);
+ if (!copy) {
+- rp_fatal("strdup failed");
++ fatal("strdup failed");
+ }
+ strcpy(copy, str);
+ return copy;
+@@ -467,9 +465,10 @@ sendPADT(PPPoEConnection *conn, char con
+ fprintf(conn->debugFile, "\n");
+ fflush(conn->debugFile);
+ }
+- syslog(LOG_INFO,"Sent PADT");
++ info("Sent PADT");
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: parseLogErrs
+ *%ARGUMENTS:
+@@ -501,4 +500,5 @@ parseLogErrs(UINT16_t type, UINT16_t len
+ break;
+ }
+ }
++#endif
+
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/discovery.c 2005-03-11 02:12:52.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c 2005-03-10 12:24:19.000000000 +0100
+@@ -13,10 +13,6 @@ static char const RCSID[] =
+
+ #include "pppoe.h"
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <string.h>
+ #include <stdlib.h>
+ #include <errno.h>
+@@ -167,24 +163,21 @@ parsePADOTags(UINT16_t type, UINT16_t le
+ if (conn->printACNames) {
+ printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: Service-Name-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: Service-Name-Error: %.*s", (int) len, data);
+ }
+ break;
+ case TAG_AC_SYSTEM_ERROR:
+ if (conn->printACNames) {
+ printf("Got a System-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: System-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: System-Error: %.*s", (int) len, data);
+ }
+ break;
+ case TAG_GENERIC_ERROR:
+ if (conn->printACNames) {
+ printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
+ } else {
+- syslog(LOG_ERR, "PADO: Generic-Error: %.*s", (int) len, data);
+- exit(1);
++ fatal("PADO: Generic-Error: %.*s", (int) len, data);
+ }
+ break;
+ }
+@@ -209,20 +202,14 @@ parsePADSTags(UINT16_t type, UINT16_t le
+ PPPoEConnection *conn = (PPPoEConnection *) extra;
+ switch(type) {
+ case TAG_SERVICE_NAME:
+- syslog(LOG_DEBUG, "PADS: Service-Name: '%.*s'", (int) len, data);
++ dbglog("PADS: Service-Name: '%.*s'", (int) len, data);
+ break;
+ case TAG_SERVICE_NAME_ERROR:
+- syslog(LOG_ERR, "PADS: Service-Name-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: Service-Name-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: Service-Name-Error: %.*s", (int) len, data);
+ case TAG_AC_SYSTEM_ERROR:
+- syslog(LOG_ERR, "PADS: System-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: System-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: System-Error: %.*s", (int) len, data);
+ case TAG_GENERIC_ERROR:
+- syslog(LOG_ERR, "PADS: Generic-Error: %.*s", (int) len, data);
+- fprintf(stderr, "PADS: Generic-Error: %.*s\n", (int) len, data);
+- exit(1);
++ fatal("PADS: Generic-Error: %.*s", (int) len, data);
+ case TAG_RELAY_SESSION_ID:
+ conn->relayId.type = htons(type);
+ conn->relayId.length = htons(len);
+@@ -336,7 +323,7 @@ waitForPADO(PPPoEConnection *conn, int t
+ if (r >= 0 || errno != EINTR) break;
+ }
+ if (r < 0) {
+- fatalSys("select (waitForPADO)");
++ fatal("waitForPADO: select: %m");
+ }
+ if (r == 0) return; /* Timed out */
+ }
+@@ -346,8 +333,7 @@ waitForPADO(PPPoEConnection *conn, int t
+
+ /* Check length */
+ if (ntohs(packet.length) + HDR_SIZE > len) {
+- syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
+- (unsigned int) ntohs(packet.length));
++ error("Bogus PPPoE length field (%u)", ntohs(packet.length));
+ continue;
+ }
+
+@@ -366,16 +352,16 @@ waitForPADO(PPPoEConnection *conn, int t
+
+ if (packet.code == CODE_PADO) {
+ if (BROADCAST(packet.ethHdr.h_source)) {
+- printErr("Ignoring PADO packet from broadcast MAC address");
++ error("Ignoring PADO packet from broadcast MAC address");
+ continue;
+ }
+ parsePacket(&packet, parsePADOTags, &pc);
+ if (!pc.seenACName) {
+- printErr("Ignoring PADO packet with no AC-Name tag");
++ error("Ignoring PADO packet with no AC-Name tag");
+ continue;
+ }
+ if (!pc.seenServiceName) {
+- printErr("Ignoring PADO packet with no Service-Name tag");
++ error("Ignoring PADO packet with no Service-Name tag");
+ continue;
+ }
+ conn->numPADOs++;
+@@ -513,7 +499,7 @@ waitForPADS(PPPoEConnection *conn, int t
+ if (r >= 0 || errno != EINTR) break;
+ }
+ if (r < 0) {
+- fatalSys("select (waitForPADS)");
++ fatal("waitForPADS: select: %m");
+ }
+ if (r == 0) return;
+ }
+@@ -523,8 +509,7 @@ waitForPADS(PPPoEConnection *conn, int t
+
+ /* Check length */
+ if (ntohs(packet.length) + HDR_SIZE > len) {
+- syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
+- (unsigned int) ntohs(packet.length));
++ error("Bogus PPPoE length field (%u)", ntohs(packet.length));
+ continue;
+ }
+
+@@ -556,11 +541,12 @@ waitForPADS(PPPoEConnection *conn, int t
+ /* Don't bother with ntohs; we'll just end up converting it back... */
+ conn->session = packet.session;
+
+- syslog(LOG_INFO, "PPP session is %d", (int) ntohs(conn->session));
++ info("PPP session is %d", ntohs(conn->session));
+
+ /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */
+ if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {
+- syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));
++ error("Access concentrator used a session value of 0x%x"
++ " -- the AC is violating RFC 2516", ntohs(conn->session));
+ }
+ }
+
+@@ -620,7 +606,7 @@ discovery(PPPoEConnection *conn)
+
+ /* If we're only printing access concentrator names, we're done */
+ if (conn->printACNames) {
+- die(0);
++ exit(0);
+ }
+
+ timeout = PADI_TIMEOUT;
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/if.c ppp-2.4.3/pppd/plugins/rp-pppoe/if.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/if.c 2001-12-14 03:55:20.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/if.c 2005-03-10 13:32:43.000000000 +0100
+@@ -40,10 +40,6 @@ static char const RCSID[] =
+ #include <sys/ioctl.h>
+ #endif
+
+-#ifdef HAVE_SYSLOG_H
+-#include <syslog.h>
+-#endif
+-
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -127,7 +123,7 @@ etherType(PPPoEPacket *packet)
+ {
+ UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto);
+ if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) {
+- syslog(LOG_ERR, "Invalid ether type 0x%x", type);
++ error("Invalid ethernet type 0x%x", type);
+ }
+ return type;
+ }
+@@ -156,7 +152,7 @@ getHWaddr(int sock, char const *ifname,
+ ifc.ifc_len = sizeof(inbuf);
+ ifc.ifc_buf = inbuf;
+ if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
+- fatalSys("SIOCGIFCONF");
++ fatal("SIOCGIFCONF: %m");
+ }
+ ifr = ifc.ifc_req;
+ ifreq.ifr_name[0] = '\0';
+@@ -172,9 +168,7 @@ getHWaddr(int sock, char const *ifname,
+ (sdl->sdl_alen == ETH_ALEN) &&
+ !strncmp(ifname, ifr->ifr_name, sizeof(ifr->ifr_name))) {
+ if (found) {
+- char buffer[256];
+- sprintf(buffer, "interface %.16s has more than one ethernet address", ifname);
+- rp_fatal(buffer);
++ fatal("interface %s has more than one ethernet address", ifname);
+ } else {
+ found = 1;
+ memcpy(hwaddr, LLADDR(sdl), ETH_ALEN);
+@@ -183,9 +177,7 @@ getHWaddr(int sock, char const *ifname,
+ }
+ }
+ if (!found) {
+- char buffer[256];
+- sprintf(buffer, "interface %.16s has no ethernet address", ifname);
+- rp_fatal(buffer);
++ fatal("interface %s has no ethernet address", ifname);
+ }
+ }
+
+@@ -252,7 +244,7 @@ initFilter(int fd, UINT16_t type, unsign
+
+ /* Apply the filter */
+ if (ioctl(fd, BIOCSETF, &bpfProgram) < 0) {
+- fatalSys("ioctl(BIOCSETF)");
++ fatal("ioctl(BIOCSETF): %m");
+ }
+ }
+ }
+@@ -298,42 +290,36 @@ openInterface(char const *ifname, UINT16
+ if (fd < 0) {
+ switch (errno) {
+ case EACCES: /* permission denied */
+- {
+- char buffer[256];
+- sprintf(buffer, "Cannot open %.32s -- pppoe must be run as root.", bpfName);
+- rp_fatal(buffer);
+- }
++ fatal("Cannot open %s -- pppoe must be run as root.", bpfName);
+ break;
+ case EBUSY:
+ case ENOENT: /* no such file */
+ if (i == 0) {
+- rp_fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
++ fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)");
+ } else {
+- rp_fatal("All /dev/bpf* devices are in use");
++ fatal("All /dev/bpf* devices are in use");
+ }
+ break;
+ }
+- fatalSys(bpfName);
++ fatal("%s: %m", bpfName);
+ }
+
+ if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
+- fatalSys("socket");
++ fatal("socket: %m");
+ }
+
+ /* Check that the interface is up */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFFLAGS)");
++ fatal("ioctl(SIOCGIFFLAGS): %m");
+ }
+ if ((ifr.ifr_flags & IFF_UP) == 0) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s is not up\n", ifname);
+- rp_fatal(buffer);
++ fatal("Interface %s is not up", ifname);
+ }
+
+ /* Fill in hardware address and initialize the packet filter rules */
+ if (hwaddr == NULL) {
+- rp_fatal("openInterface: no hwaddr arg.");
++ fatal("openInterface: no hwaddr arg.");
+ }
+ getHWaddr(sock, ifname, hwaddr);
+ initFilter(fd, type, hwaddr);
+@@ -342,58 +328,52 @@ openInterface(char const *ifname, UINT16
+ #if !defined(__OpenBSD__)
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFMTU)");
++ fatal("ioctl(SIOCGIFMTU): %m");
+ }
+ if (ifr.ifr_mtu < ETH_DATA_LEN) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.",
++ error("Interface %s has MTU of %d -- should be %d."
++ " You may have serious connection problems.",
+ ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+- printErr(buffer);
+ }
+ #endif
+
+ /* done with the socket */
+ if (close(sock) < 0) {
+- fatalSys("close");
++ fatal("close: %m");
+ }
+
+ /* Check the BPF version number */
+ if (ioctl(fd, BIOCVERSION, &bpf_ver) < 0) {
+- fatalSys("ioctl(BIOCVERSION)");
++ fatal("ioctl(BIOCVERSION): %m");
+ }
+ if ((bpf_ver.bv_major != BPF_MAJOR_VERSION) ||
+ (bpf_ver.bv_minor < BPF_MINOR_VERSION)) {
+- char buffer[256];
+- sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)",
++ fatal("Unsupported BPF version: %d.%d (kernel: %d.%d)",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+ bpf_ver.bv_major, bpf_ver.bv_minor);
+- rp_fatal(buffer);
+ }
+
+ /* allocate a receive packet buffer */
+ if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) {
+- fatalSys("ioctl(BIOCGBLEN)");
++ fatal("ioctl(BIOCGBLEN): %m");
+ }
+ if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) {
+- rp_fatal("malloc");
++ fatal("malloc");
+ }
+
+ /* reads should return as soon as there is a packet available */
+ optval = 1;
+ if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) {
+- fatalSys("ioctl(BIOCIMMEDIATE)");
++ fatal("ioctl(BIOCIMMEDIATE): %m");
+ }
+
+ /* Bind the interface to the filter */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) < 0) {
+- char buffer[256];
+- sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s",
+- ifname);
+- rp_fatal(buffer);
++ fatal("ioctl(BIOCSETIF) can't select interface %s: %m", ifname);
+ }
+
+- syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d",
++ info("Interface=%s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%s Buffer size=%d",
+ ifname,
+ hwaddr[0], hwaddr[1], hwaddr[2],
+ hwaddr[3], hwaddr[4], hwaddr[5],
+@@ -442,48 +422,41 @@ openInterface(char const *ifname, UINT16
+ if ((fd = socket(domain, stype, htons(type))) < 0) {
+ /* Give a more helpful message for the common error case */
+ if (errno == EPERM) {
+- rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
++ fatal("Cannot create raw socket -- pppoe must be run as root.");
+ }
+- fatalSys("socket");
++ fatal("cannot create the raw socket: %m");
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) {
+- fatalSys("setsockopt");
++ fatal("setsockopt(SOL_SOCKET, SO_BROADCAST): %m");
+ }
+
+ /* Fill in hardware address */
+ if (hwaddr) {
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+- if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFHWADDR)");
+- }
++ if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
++ fatal("ioctl(SIOCGIFHWADDR): %m");
+ memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ #ifdef ARPHRD_ETHER
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s is not Ethernet", ifname);
+- rp_fatal(buffer);
++ fatal("Interface %s is not Ethernet", ifname);
+ }
+ #endif
+ if (NOT_UNICAST(hwaddr)) {
+- char buffer[256];
+- sprintf(buffer,
+- "Interface %.16s has broadcast/multicast MAC address??",
++ fatal("Interface %s has broadcast/multicast MAC address",
+ ifname);
+- rp_fatal(buffer);
+ }
+ }
+
+ /* Sanity check on MTU */
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) {
+- fatalSys("ioctl(SIOCGIFMTU)");
++ fatal("ioctl(SIOCGIFMTU): %m");
+ }
+ if (ifr.ifr_mtu < ETH_DATA_LEN) {
+- char buffer[256];
+- sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.",
++ error("Interface %s has MTU of %d -- should be %d."
++ " You may have serious connection problems.",
+ ifname, ifr.ifr_mtu, ETH_DATA_LEN);
+- printErr(buffer);
+ }
+
+ #ifdef HAVE_STRUCT_SOCKADDR_LL
+@@ -493,7 +466,7 @@ openInterface(char const *ifname, UINT16
+
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+- fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index");
++ fatal("ioctl(SIOCFIGINDEX): Could not get interface index: %m");
+ }
+ sa.sll_ifindex = ifr.ifr_ifindex;
+
+@@ -503,7 +476,7 @@ openInterface(char const *ifname, UINT16
+
+ /* We're only interested in packets on specified interface */
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+- fatalSys("bind");
++ fatal("bind: %m");
+ }
+
+ return fd;
+@@ -527,13 +500,11 @@ sendPacket(PPPoEConnection *conn, int so
+ {
+ #if defined(USE_BPF)
+ if (write(sock, pkt, size) < 0) {
+- sysErr("write (sendPacket)");
+- return -1;
++ fatal("sendPacket: write: %m");
+ }
+ #elif defined(HAVE_STRUCT_SOCKADDR_LL)
+ if (send(sock, pkt, size, 0) < 0) {
+- sysErr("send (sendPacket)");
+- return -1;
++ fatal("sendPacket: send: %m");
+ }
+ #else
+ #ifdef USE_DLPI
+@@ -577,12 +548,11 @@ sendPacket(PPPoEConnection *conn, int so
+ struct sockaddr sa;
+
+ if (!conn) {
+- rp_fatal("relay and server not supported on Linux 2.0 kernels");
++ fatal("relay and server not supported on Linux 2.0 kernels");
+ }
+ strcpy(sa.sa_data, conn->ifName);
+ if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) {
+- sysErr("sendto (sendPacket)");
+- return -1;
++ fatal("sendPacket: sendto: %m");
+ }
+ #endif
+ #endif
+@@ -632,26 +602,24 @@ receivePacket(int sock, PPPoEPacket *pkt
+ if (bpfSize <= 0) {
+ bpfOffset = 0;
+ if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) {
+- sysErr("read (receivePacket)");
+- return -1;
++ fatal("receivePacket: read: %m");
+ }
+ }
+ if (bpfSize < sizeof(hdr)) {
+- syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize);
++ error("Truncated bpf packet header: len=%d", bpfSize);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+ memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr));
+ if (hdr.bh_caplen != hdr.bh_datalen) {
+- syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d",
++ error("Truncated bpf packet: caplen=%d, datalen=%d",
+ hdr.bh_caplen, hdr.bh_datalen);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+ seglen = hdr.bh_hdrlen + hdr.bh_caplen;
+ if (seglen > bpfSize) {
+- syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d",
+- seglen, bpfSize);
++ error("Truncated bpf packet: seglen=%d, bpfSize=%d", seglen, bpfSize);
+ clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */
+ return 0;
+ }
+@@ -676,16 +644,14 @@ receivePacket(int sock, PPPoEPacket *pkt
+ data.len = 0;
+
+ if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) {
+- sysErr("read (receivePacket)");
+- return -1;
++ fatal("receivePacket: getmsg: %m");
+ }
+
+ *size = data.len;
+
+ #else
+ if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) {
+- sysErr("recv (receivePacket)");
+- return -1;
++ fatal("receivePacket: recv: %m");
+ }
+ #endif
+ #endif
+@@ -716,7 +682,7 @@ openInterface(char const *ifname, UINT16
+ int ppa;
+
+ if(strlen(ifname) > PATH_MAX) {
+- rp_fatal("socket: string to long");
++ fatal("openInterface: interface name too long");
+ }
+
+ ppa = atoi(&ifname[strlen(ifname)-1]);
+@@ -729,9 +695,9 @@ openInterface(char const *ifname, UINT16
+ if (( fd = open(base_dev, O_RDWR)) < 0) {
+ /* Give a more helpful message for the common error case */
+ if (errno == EPERM) {
+- rp_fatal("Cannot create raw socket -- pppoe must be run as root.");
++ fatal("Cannot create raw socket -- pppoe must be run as root.");
+ }
+- fatalSys("socket");
++ fatal("open(%s): %m", base_dev);
+ }
+
+ /* rearranged order of DLPI code - delphys 20010803 */
+@@ -747,17 +713,18 @@ openInterface(char const *ifname, UINT16
+ dl_abssaplen = ABS(dlp->info_ack.dl_sap_length);
+ dl_saplen = dlp->info_ack.dl_sap_length;
+ if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen))
+- fatalSys("invalid destination physical address length");
++ fatal("invalid destination physical address length");
+ dl_addrlen = dl_abssaplen + ETHERADDRL;
+
+ /* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */
+ memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL);
+
+ if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) {
+- fatalSys("DLIOCRAW");
++ fatal("DLIOCRAW: %m");
+ }
+
+- if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH");
++ if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
++ fatal("I_FLUSH: %m");
+
+ return fd;
+ }
+@@ -780,7 +747,7 @@ void dlpromisconreq(int fd, u_long level
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlpromiscon: putmsg");
++ fatal("dlpromiscon: putmsg: %m");
+
+ }
+
+@@ -799,7 +766,7 @@ void dlinforeq(int fd)
+ flags = RS_HIPRI;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlinforeq: putmsg");
++ fatal("dlinforeq: putmsg: %m");
+ }
+
+ void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen)
+@@ -827,7 +794,7 @@ void dlunitdatareq(int fd, u_char *addrp
+ data.buf = (char *) datap;
+
+ if (putmsg(fd, &ctl, &data, 0) < 0)
+- fatalSys("dlunitdatareq: putmsg");
++ fatal("dlunitdatareq: putmsg: %m");
+ }
+
+ void dlinfoack(int fd, char *bufp)
+@@ -847,18 +814,14 @@ void dlinfoack(int fd, char *bufp)
+ expecting(DL_INFO_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_info_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlinfoack: response ctl.len too short: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlinfoack: response ctl.len too short: %d", ctl.len);
+ }
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO");
++ fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_info_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlinfoack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlinfoack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -882,7 +845,7 @@ void dlbindreq(int fd, u_long sap, u_lon
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlbindreq: putmsg");
++ fatal("dlbindreq: putmsg: %m");
+ }
+
+ void dlattachreq(int fd, u_long ppa)
+@@ -901,7 +864,7 @@ void dlattachreq(int fd, u_long ppa)
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+- fatalSys("dlattachreq: putmsg");
++ fatal("dlattachreq: putmsg: %m");
+ }
+
+ void dlokack(int fd, char *bufp)
+@@ -921,18 +884,14 @@ void dlokack(int fd, char *bufp)
+ expecting(DL_OK_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_ok_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlokack: response ctl.len too short: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlokack: response ctl.len too short: %d", ctl.len);
+ }
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlokack: DL_OK_ACK was not M_PCPROTO");
++ fatal("dlokack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_ok_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlokack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlokack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -953,12 +912,10 @@ void dlbindack(int fd, char *bufp)
+ expecting(DL_BIND_ACK, dlp);
+
+ if (flags != RS_HIPRI)
+- rp_fatal("dlbindack: DL_OK_ACK was not M_PCPROTO");
++ fatal("dlbindack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_bind_ack_t)) {
+- char buffer[256];
+- sprintf(buffer, "dlbindack: short response ctl.len: %d", ctl.len);
+- rp_fatal(buffer);
++ fatal("dlbindack: short response ctl.len: %d", ctl.len);
+ }
+ }
+
+@@ -989,8 +946,7 @@ void strgetmsg(int fd, struct strbuf *ct
+ */
+ (void) signal(SIGALRM, sigalrm);
+ if (alarm(MAXWAIT) < 0) {
+- (void) sprintf(errmsg, "%s: alarm", caller);
+- fatalSys(errmsg);
++ fatal("%s: alarm", caller);
+ }
+
+ /*
+@@ -998,61 +954,48 @@ void strgetmsg(int fd, struct strbuf *ct
+ */
+ *flagsp = 0;
+ if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
+- (void) sprintf(errmsg, "%s: getmsg", caller);
+- fatalSys(errmsg);
++ fatal(errmsg, "%s: getmsg: %m", caller);
+ }
+
+ /*
+ * Stop timer.
+ */
+ if (alarm(0) < 0) {
+- (void) sprintf(errmsg, "%s: alarm", caller);
+- fatalSys(errmsg);
++ fatal("%s: alarm", caller);
+ }
+
+ /*
+ * Check for MOREDATA and/or MORECTL.
+ */
+ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) {
+- char buffer[256];
+- sprintf(buffer, "%s: MORECTL|MOREDATA", caller);
+- rp_fatal(buffer);
++ fatal("%s: MORECTL|MOREDATA", caller);
+ }
+
+ if (rc & MORECTL) {
+- char buffer[256];
+- sprintf(buffer, "%s: MORECTL", caller);
+- rp_fatal(buffer);
++ fatal("%s: MORECTL", caller);
+ }
+
+ if (rc & MOREDATA) {
+- char buffer[256];
+- sprintf(buffer, "%s: MOREDATA", caller);
+- rp_fatal(buffer);
++ fatal("%s: MOREDATA", caller);
+ }
+
+ /*
+ * Check for at least sizeof (long) control data portion.
+ */
+ if (ctlp->len < sizeof (long)) {
+- char buffer[256];
+- sprintf(buffer, "getmsg: control portion length < sizeof (long): %d", ctlp->len);
+- rp_fatal(buffer);
++ fatal("getmsg: control portion length < sizeof (long): %d", ctlp->len);
+ }
+ }
+
+ void sigalrm(int sig)
+ {
+- (void) rp_fatal("sigalrm: TIMEOUT");
++ fatal("sigalrm: TIMEOUT");
+ }
+
+ void expecting(int prim, union DL_primitives *dlp)
+ {
+ if (dlp->dl_primitive != (u_long)prim) {
+- char buffer[256];
+- sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
+- rp_fatal(buffer);
+- exit(1);
++ fatal("expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive));
+ }
+ }
+
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/Makefile.linux 2004-11-14 08:58:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux 2005-03-11 01:48:27.000000000 +0100
+@@ -28,8 +28,8 @@ COPTS=-O2 -g
+ CFLAGS=$(COPTS) -I../../../include/linux
+ all: rp-pppoe.so pppoe-discovery
+
+-pppoe-discovery: libplugin.a pppoe-discovery.o
+- $(CC) -o pppoe-discovery pppoe-discovery.o libplugin.a
++pppoe-discovery: pppoe-discovery.o utils.o libplugin.a
++ $(CC) -o pppoe-discovery pppoe-discovery.o utils.o libplugin.a
+
+ pppoe-discovery.o: pppoe-discovery.c
+ $(CC) $(CFLAGS) '-DVERSION="$(VERSION)"' -c -o pppoe-discovery.o pppoe-discovery.c
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.3/pppd/plugins/rp-pppoe/plugin.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/plugin.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/plugin.c 2005-03-11 02:12:39.000000000 +0100
+@@ -35,7 +35,6 @@ static char const RCSID[] =
+ #include "pppd/pathnames.h"
+
+ #include <linux/types.h>
+-#include <syslog.h>
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+@@ -173,10 +172,8 @@ PPPOEConnectDevice(void)
+ (unsigned) conn->peerEth[5]);
+
+ if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
+- sizeof(struct sockaddr_pppox)) < 0) {
++ sizeof(struct sockaddr_pppox)) < 0)
+ fatal("Failed to connect PPPoE socket: %d %m", errno);
+- return -1;
+- }
+
+ return conn->sessionSocket;
+ }
+@@ -365,11 +362,9 @@ plugin_init(void)
+ }
+
+ add_options(Options);
+-
+- info("RP-PPPoE plugin version %s compiled against pppd %s",
+- RP_VERSION, VERSION);
+ }
+
++#ifdef unused
+ /**********************************************************************
+ *%FUNCTION: fatalSys
+ *%ARGUMENTS:
+@@ -423,6 +418,7 @@ sysErr(char const *str)
+ {
+ rp_fatal(str);
+ }
++#endif
+
+
+ struct channel pppoe_channel = {
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe-discovery.c ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe-discovery.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe-discovery.c 2004-11-13 13:12:05.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe-discovery.c 2005-03-11 02:06:13.000000000 +0100
+@@ -17,14 +17,8 @@
+
+ #include "pppoe.h"
+
+-char *xstrdup(const char *s);
+ void usage(void);
+
+-void die(int status)
+-{
+- exit(status);
+-}
+-
+ int main(int argc, char *argv[])
+ {
+ int opt;
+@@ -32,17 +26,17 @@ int main(int argc, char *argv[])
+
+ conn = malloc(sizeof(PPPoEConnection));
+ if (!conn)
+- fatalSys("malloc");
++ fatal("malloc");
+
+ memset(conn, 0, sizeof(PPPoEConnection));
+
+ while ((opt = getopt(argc, argv, "I:D:VUAS:C:h")) > 0) {
+ switch(opt) {
+ case 'S':
+- conn->serviceName = xstrdup(optarg);
++ conn->serviceName = strDup(optarg);
+ break;
+ case 'C':
+- conn->acName = xstrdup(optarg);
++ conn->acName = strDup(optarg);
+ break;
+ case 'U':
+ conn->useHostUniq = 1;
+@@ -57,7 +51,7 @@ int main(int argc, char *argv[])
+ fprintf(conn->debugFile, "pppoe-discovery %s\n", VERSION);
+ break;
+ case 'I':
+- conn->ifName = xstrdup(optarg);
++ conn->ifName = strDup(optarg);
+ break;
+ case 'A':
+ /* this is the default */
+@@ -74,7 +68,7 @@ int main(int argc, char *argv[])
+
+ /* default interface name */
+ if (!conn->ifName)
+- conn->ifName = strdup("eth0");
++ conn->ifName = strDup("eth0");
+
+ conn->discoverySocket = -1;
+ conn->sessionSocket = -1;
+@@ -84,39 +78,6 @@ int main(int argc, char *argv[])
+ exit(0);
+ }
+
+-void rp_fatal(char const *str)
+-{
+- char buf[1024];
+-
+- printErr(str);
+- sprintf(buf, "pppoe-discovery: %.256s", str);
+- exit(1);
+-}
+-
+-void fatalSys(char const *str)
+-{
+- char buf[1024];
+- int i = errno;
+-
+- sprintf(buf, "%.256s: %.256s", str, strerror(i));
+- printErr(buf);
+- sprintf(buf, "pppoe-discovery: %.256s: %.256s", str, strerror(i));
+- exit(1);
+-}
+-
+-void sysErr(char const *str)
+-{
+- rp_fatal(str);
+-}
+-
+-char *xstrdup(const char *s)
+-{
+- register char *ret = strdup(s);
+- if (!ret)
+- sysErr("strdup");
+- return ret;
+-}
+-
+ void usage(void)
+ {
+ fprintf(stderr, "Usage: pppoe-discovery [options]\n");
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe.h ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe.h
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/pppoe.h 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/pppoe.h 2005-03-11 02:08:00.000000000 +0100
+@@ -307,12 +307,18 @@ void discovery(PPPoEConnection *conn);
+ unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType,
+ PPPoETag *tag);
+
++void dbglog(char *, ...); /* log a debug message */
++void info(char *, ...); /* log an informational message */
++void warn(char *, ...); /* log a warning message */
++void error(char *, ...); /* log an error message */
++void fatal(char *, ...); /* log an error message and die(1) */
++
+ #define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0);
+
+ #define CHECK_ROOM(cursor, start, len) \
+ do {\
+ if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \
+- syslog(LOG_ERR, "Would create too-long packet"); \
++ error("Would create too-long packet"); \
+ return; \
+ } \
+ } while(0)
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/rp-pppoe/utils.c ppp-2.4.3/pppd/plugins/rp-pppoe/utils.c
+--- ppp-2.4.3.orig/pppd/plugins/rp-pppoe/utils.c 1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/utils.c 2005-03-11 02:07:57.000000000 +0100
+@@ -0,0 +1,62 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <stdarg.h>
++#include <syslog.h>
++
++void dbglog(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_DEBUG, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void info(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_INFO, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void warn(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_WARNING, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void error(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_ERR, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++}
++
++void fatal(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vsyslog(LOG_ERR, fmt, ap);
++ vfprintf(stderr, fmt, ap);
++ fputs("\n", stderr);
++ va_end(ap);
++ exit(1);
++}
++
--- /dev/null
+Subject: Bug#284382: ppp: linkpidfile is not created upon detachment
+From: <herbert@gondor.apana.org.au>
+
+Package: ppp
+Version: 2.4.2+20040428-2
+Severity: wishlist
+
+When pppd detaches from the parent normally, that is, without nodetach
+or updetach set, the linkpidfile is not created even when linkname is
+set.
+
+This is because the create_linkpidfile call in detach() is only made
+if the linkpidfile is filled in. However, linkpidfile is never filled
+in until create_linkpidfile has been called.
+
+IMHO the call should be made uncondtionally in detach() since
+create_linkpidfile does its own check on linkname anyway.
+
+Please note that the version of pppd in woody always wrote the
+linkpidfile after detaching. It did so in main() however. That
+call has now been removed which is why I'm seeing this problem.
+
+[...]
+
+--
+Index: pppd/main.c
+===================================================================
+RCS file: /var/cvs/snwb/packages/ppp/pppd/main.c,v
+retrieving revision 1.11
+diff -u -r1.11 main.c
+--- ppp/pppd/main.c 29 Nov 2004 22:49:23 -0000 1.11
++++ ppp/pppd/main.c 5 Dec 2004 23:59:58 -0000
+@@ -819,8 +819,7 @@
+ /* update pid files if they have been written already */
+ if (pidfilename[0])
+ create_pidfile(pid);
+- if (linkpidfile[0])
+- create_linkpidfile(pid);
++ create_linkpidfile(pid);
+ exit(0); /* parent dies */
+ }
+ setsid();
+
--- /dev/null
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c
+--- ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c 2005-03-22 14:44:18.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-03-22 14:44:02.000000000 +0100
+@@ -70,18 +70,20 @@ static int setdevname_pppoatm(const char
+ {
+ struct sockaddr_atmpvc addr;
+ extern struct stat devstat;
++
+ if (device_got_set)
+ return 0;
+- //info("PPPoATM setdevname_pppoatm: '%s'", cp);
++
+ memset(&addr, 0, sizeof addr);
+ if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
+ T2A_PVC | T2A_NAME) < 0) {
+- if(doit)
+- info("atm does not recognize: %s", cp);
++ if (doit)
++ info("cannot parse the ATM address: %s", cp);
+ return 0;
+- }
+- if (!doit) return 1;
+- //if (!dev_set_ok()) return -1;
++ }
++ if (!doit)
++ return 1;
++
+ memcpy(&pvcaddr, &addr, sizeof pvcaddr);
+ strlcpy(devnam, cp, sizeof devnam);
+ devstat.st_mode = S_IFSOCK;
+@@ -93,7 +95,6 @@ static int setdevname_pppoatm(const char
+ lcp_allowoptions[0].neg_asyncmap = 0;
+ lcp_wantoptions[0].neg_pcompression = 0;
+ }
+- info("PPPoATM setdevname_pppoatm - SUCCESS:%s", cp);
+ device_got_set = 1;
+ return 1;
+ }
+@@ -108,6 +109,7 @@ static void no_device_given_pppoatm(void
+ static void set_line_discipline_pppoatm(int fd)
+ {
+ struct atm_backend_ppp be;
++
+ be.backend_num = ATM_BACKEND_PPP;
+ if (!llc_encaps)
+ be.encaps = PPPOATM_ENCAPS_VC;
+@@ -115,6 +117,7 @@ static void set_line_discipline_pppoatm(
+ be.encaps = PPPOATM_ENCAPS_LLC;
+ else
+ be.encaps = PPPOATM_ENCAPS_AUTODETECT;
++
+ if (ioctl(fd, ATM_SETBACKEND, &be) < 0)
+ fatal("ioctl(ATM_SETBACKEND): %m");
+ }
+@@ -179,16 +182,19 @@ static void send_config_pppoa(int mtu,
+ {
+ int sock;
+ struct ifreq ifr;
++
+ if (mtu > pppoatm_max_mtu)
+ error("Couldn't increase MTU to %d", mtu);
++
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ fatal("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)
+ fatal("ioctl(SIOCSIFMTU): %m");
+- (void) close (sock);
++ close(sock);
+ }
+
+ static void recv_config_pppoa(int mru,
+@@ -202,7 +208,7 @@ static void recv_config_pppoa(int mru,
+
+ void plugin_init(void)
+ {
+-#if defined(__linux__)
++#ifdef linux
+ extern int new_style_driver; /* From sys-linux.c */
+ if (!ppp_available() && !new_style_driver)
+ fatal("Kernel doesn't support ppp_generic - "
+@@ -210,9 +216,9 @@ void plugin_init(void)
+ #else
+ fatal("No PPPoATM support on this OS");
+ #endif
+- info("PPPoATM plugin_init");
+ add_options(pppoa_options);
+ }
++
+ struct channel pppoa_channel = {
+ options: pppoa_options,
+ process_extra_options: NULL,
--- /dev/null
+diff -ruNp ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c
+--- ppp-2.4.3.orig/pppd/plugins/pppoatm/pppoatm.c 2005-05-04 02:00:28.000000000 +0200
++++ ppp-2.4.3/pppd/plugins/pppoatm/pppoatm.c 2005-05-04 01:59:11.000000000 +0200
+@@ -183,8 +183,11 @@ static void send_config_pppoa(int mtu,
+ int sock;
+ struct ifreq ifr;
+
+- if (mtu > pppoatm_max_mtu)
+- error("Couldn't increase MTU to %d", mtu);
++ if (pppoatm_max_mtu && mtu > pppoatm_max_mtu) {
++ warn("Couldn't increase MTU to %d. Using %d",
++ mtu, pppoatm_max_mtu);
++ mtu = pppoatm_max_mtu;
++ }
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+@@ -202,8 +205,11 @@ static void recv_config_pppoa(int mru,
+ int pcomp,
+ int accomp)
+ {
+- if (mru > pppoatm_max_mru)
+- error("Couldn't increase MRU to %d", mru);
++ if (pppoatm_max_mru && mru > pppoatm_max_mru) {
++ warn("Couldn't increase MRU to %d. Using %d",
++ mru, pppoatm_max_mru);
++ mru = pppoatm_max_mru;
++ }
+ }
+
+ void plugin_init(void)
--- /dev/null
+diff -ruN ppp.orig/pppd/chap-new.c ppp/pppd/chap-new.c
+--- ppp.orig/pppd/chap-new.c 2003-11-27 23:25:17.000000000 +0100
++++ ppp/pppd/chap-new.c 2003-12-02 12:26:21.000000000 +0100
+@@ -57,6 +57,7 @@
+ int chap_timeout_time = 3;
+ int chap_max_transmits = 10;
+ int chap_rechallenge_time = 0;
++int chapms_strip_domain = 0;
+
+ /*
+ * Command-line options.
+@@ -68,6 +69,8 @@
+ "Set max #xmits for challenge", OPT_PRIO },
+ { "chap-interval", o_int, &chap_rechallenge_time,
+ "Set interval for rechallenge", OPT_PRIO },
++ { "chapms-strip-domain", o_bool, &chapms_strip_domain,
++ "Strip the domain prefix before the Username", 1 },
+ { NULL }
+ };
+
+@@ -338,6 +341,14 @@
+ /* Null terminate and clean remote name. */
+ slprintf(rname, sizeof(rname), "%.*v", len, name);
+ name = rname;
++
++ /* strip the MS domain name */
++ if (chapms_strip_domain && strrchr(rname, '\\')) {
++ char tmp[MAXNAMELEN+1];
++
++ strcpy(tmp, strrchr(rname, '\\') + 1);
++ strcpy(rname, tmp);
++ }
+ }
+
+ if (chap_verify_hook)
--- /dev/null
+--- ppp/pppd/ipcp.c Wed May 31 17:20:41 2000
++++ ppp/pppd/ipcp.c Wed May 31 17:27:19 2000
+@@ -145,7 +145,17 @@
+ { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+ "disable defaultroute option", OPT_A2COPY,
+ &ipcp_wantoptions[0].default_route },
+
++#ifdef __linux__
++ { "replacedefaultroute", o_bool,
++ &ipcp_wantoptions[0].replace_default_route,
++ "Replace default route", 1
++ },
++ { "noreplacedefaultroute", o_bool,
++ &ipcp_allowoptions[0].replace_default_route,
++ "Never replace default route", OPT_A2COPY,
++ &ipcp_wantoptions[0].replace_default_route },
++#endif
+ { "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,
+@@ -195,7 +205,7 @@
+ ip_active_pkt
+ };
+
+-static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
++static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool));
+ static void ipcp_script __P((char *)); /* Run an up/down script */
+ static void ipcp_script_done __P((void *));
+
+@@ -1344,7 +1354,12 @@
+ if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+ return 0;
+ if (wo->default_route)
++#ifndef __linux__
+ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
++#else
++ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[u] = 1;
+ if (wo->proxy_arp)
+ if (sifproxyarp(u, wo->hisaddr))
+@@ -1420,7 +1435,8 @@
+ */
+ if (demand) {
+ if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
+- ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
++ ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
++ wo->replace_default_route);
+ if (go->ouraddr != wo->ouraddr) {
+ warn("Local IP address changed to %I", go->ouraddr);
+ script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr));
+@@ -1445,7 +1461,12 @@
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
++#ifndef __linux__
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++#else
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1492,7 +1513,12 @@
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
++#ifndef __linux__
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++#else
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
++#endif
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1559,7 +1585,7 @@
+ 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);
++ ipcp_hisoptions[f->unit].hisaddr, 0);
+ }
+
+ /* Execute the ip-down script */
+@@ -1575,16 +1601,25 @@
+ * proxy arp entries, etc.
+ */
+ static void
+-ipcp_clear_addrs(unit, ouraddr, hisaddr)
++ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
+ int unit;
+ u_int32_t ouraddr; /* local address */
+ u_int32_t hisaddr; /* remote address */
++ bool replacedefaultroute;
+ {
+ if (proxy_arp_set[unit]) {
+ cifproxyarp(unit, hisaddr);
+ proxy_arp_set[unit] = 0;
+ }
+- if (default_route_set[unit]) {
++ /* If replacedefaultroute, sifdefaultroute will be called soon
++ * with replacedefaultroute set and that will overwrite the current
++ * default route. This is the case only when doing demand, otherwise
++ * during demand, this cifdefaultroute would restore the old default
++ * route which is not what we want in this case. In the non-demand
++ * case, we'll delete the default route and restore the old if there
++ * is one saved by an sifdefaultroute with replacedefaultroute.
++ */
++ if (!replacedefaultroute && default_route_set[unit]) {
+ cifdefaultroute(unit, ouraddr, hisaddr);
+ default_route_set[unit] = 0;
+ }
+--- ppp/pppd/ipcp.h Wed May 31 17:20:41 2000
++++ ppp/pppd/ipcp.h Wed May 31 15:56:17 2000
+@@ -47,6 +47,7 @@
+ 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 replace_default_route; /* Replace 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? */
+--- ppp/pppd/pppd.h Wed May 31 17:20:41 2000
++++ ppp/pppd/pppd.h Wed May 31 15:56:17 2000
+@@ -416,7 +416,11 @@
+ int cif6addr __P((int, eui64_t, eui64_t));
+ /* Remove an IPv6 address from i/f */
+ #endif
++#ifndef __linux__
+ int sifdefaultroute __P((int, u_int32_t, u_int32_t));
++#else
++int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
++#endif
+ /* Create default route through i/f */
+ int cifdefaultroute __P((int, u_int32_t, u_int32_t));
+ /* Delete default route through i/f */
+--- ppp/pppd/sys-linux.c Wed May 31 17:20:41 2000
++++ ppp/pppd/sys-linux.c Wed May 31 17:37:23 2000
+@@ -143,6 +143,8 @@
+
+ static int if_is_up; /* Interface has been marked up */
+ static u_int32_t default_route_gateway; /* Gateway for default route added */
++static struct rtentry old_def_rt; /* Old default route */
++static int default_rt_repl_rest; /* replace and restore old default rt */
+ 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 */
+@@ -1209,6 +1211,9 @@
+ p = NULL;
+ }
+
++ SET_SA_FAMILY (rt->rt_dst, AF_INET);
++ SET_SA_FAMILY (rt->rt_gateway, AF_INET);
++
+ 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);
+@@ -1278,19 +1283,53 @@
+ /********************************************************************
+ *
+ * sifdefaultroute - assign a default route through the address given.
++ *
++ * If the global default_rt_repl_rest flag is set, then this function
++ * already replaced the original system defaultroute with some other
++ * route and it should just replace the current defaultroute with
++ * another one, without saving the current route. Use: demand mode,
++ * when pppd sets first a defaultroute it it's temporary ppp0 addresses
++ * and then changes the temporary addresses to the addresses for the real
++ * ppp connection when it has come up.
+ */
+
+-int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
++int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
+ {
+- struct rtentry rt;
+-
+- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
+- u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
++ struct rtentry rt, tmp_rt;
++ struct rtentry *del_rt = NULL;
+
+- if (old_gateway != gateway)
+- error("not replacing existing default route to %s [%I]",
+- rt.rt_dev, old_gateway);
+- return 0;
++
++ if (default_rt_repl_rest) {
++ /* We have already reclaced the original defaultroute, if we
++ * are called again, we will delete the current default route
++ * and set the new default route in this function.
++ * - this is normally only the case the doing demand: */
++ if (defaultroute_exists( &tmp_rt ))
++ del_rt = &tmp_rt;
++ } else if ( defaultroute_exists( &old_def_rt ) &&
++ strcmp( old_def_rt.rt_dev, ifname ) != 0) {
++ /* We did not yet replace an existing default route, let's
++ * check if we should save and replace a default route:
++ */
++ u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
++
++ if (old_gateway != gateway) {
++ if (!replace) {
++ error("not replacing default route to %s [%I]",
++ old_def_rt.rt_dev, old_gateway);
++ return 0;
++ } else {
++ // we need to copy rt_dev because we need it permanent too:
++ char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1);
++ strcpy(tmp_dev, old_def_rt.rt_dev);
++ old_def_rt.rt_dev = tmp_dev;
++
++ notice("replacing old default route to %s [%I]",
++ old_def_rt.rt_dev, old_gateway);
++ default_rt_repl_rest = 1;
++ del_rt = &old_def_rt;
++ }
++ }
+ }
+
+ memset (&rt, '\0', sizeof (rt));
+@@ -1310,6 +1349,12 @@
+ error("default route ioctl(SIOCADDRT): %m(%d)", errno);
+ return 0;
+ }
++ if (default_rt_repl_rest && del_rt)
++ if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
++ if ( ! ok_error ( errno ))
++ error("del old default route ioctl(SIOCDELRT): %m(%d)", errno);
++ return 0;
++ }
+
+ default_route_gateway = gateway;
+ return 1;
+@@ -1344,6 +1389,16 @@
+ error("default route ioctl(SIOCDELRT): %m (%d)", errno);
+ return 0;
+ }
++ }
++ if (default_rt_repl_rest) {
++ notice("restoring old default route to %s [%I]",
++ old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
++ if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
++ if ( ! ok_error ( errno ))
++ error("restore default route ioctl(SIOCADDRT): %m(%d)", errno);
++ return 0;
++ }
++ default_rt_repl_rest = 0;
+ }
+
+ return 1;
--- /dev/null
+--- ppp/pppd/demand.c
++++ ppp/pppd/demand.c 2000/06/28 14:54:04
+@@ -25,6 +25,8 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <netdb.h>
++#include <unistd.h>
++#include <syslog.h>
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+@@ -32,6 +34,8 @@
+ #include <sys/resource.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
+ #ifdef PPP_FILTER
+ #include <net/if.h>
+ #include <net/bpf.h>
+@@ -210,6 +214,14 @@
+ int c, rv;
+
+ rv = 0;
++
++/* check for synchronous connection... */
++
++ if ( (p[0] == 0xFF) && (p[1] == 0x03) ) {
++ rv = loop_frame(p,n);
++ return rv;
++ }
++
+ for (; n > 0; --n) {
+ c = *p++;
+ if (c == PPP_FLAG) {
+@@ -288,17 +300,102 @@
+ * loopback, now that the real serial link is up.
+ */
+ void
+-demand_rexmit(proto)
++demand_rexmit(proto, newip)
+ int proto;
++ u_int32_t newip;
+ {
+ struct packet *pkt, *prev, *nextpkt;
++ unsigned short checksum;
++ unsigned short pkt_checksum = 0;
++ unsigned iphdr;
++ struct timeval tv;
++ char cv = 0;
++ char ipstr[16];
+
+ prev = NULL;
+ pkt = pend_q;
+ pend_q = NULL;
++ tv.tv_sec = 1;
++ tv.tv_usec = 0;
++ select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */
+ for (; pkt != NULL; pkt = nextpkt) {
+ nextpkt = pkt->next;
+ if (PPP_PROTOCOL(pkt->data) == proto) {
++ if ( (proto == PPP_IP) && newip ) {
++ /* Get old checksum */
++
++ iphdr = (pkt->data[4] & 15) << 2;
++ checksum = *((unsigned short *) (pkt->data+14));
++ if (checksum == 0xFFFF) {
++ checksum = 0;
++ }
++
++
++ if (pkt->data[13] == 17) {
++ pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr));
++ if (pkt_checksum) {
++ cv = 1;
++ if (pkt_checksum == 0xFFFF) {
++ pkt_checksum = 0;
++ }
++ }
++ else {
++ cv = 0;
++ }
++ }
++
++ if (pkt->data[13] == 6) {
++ pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr));
++ cv = 1;
++ if (pkt_checksum == 0xFFFF) {
++ pkt_checksum = 0;
++ }
++ }
++
++ /* Delete old Source-IP-Address */
++ checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ /* Change Source-IP-Address */
++ * ((u_int32_t *) (pkt->data + 16)) = newip;
++
++ /* Add new Source-IP-Address */
++ checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ /* Write new checksum */
++ if (!checksum) {
++ checksum = 0xFFFF;
++ }
++ *((unsigned short *) (pkt->data+14)) = checksum;
++ if (pkt->data[13] == 6) {
++ *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum;
++ }
++ if (cv && (pkt->data[13] == 17) ) {
++ *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum;
++ }
++
++ /* Log Packet */
++ strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16))));
++ if (pkt->data[13] == 1) {
++ syslog(LOG_INFO,"Open ICMP %s -> %s\n",
++ ipstr,
++ inet_ntoa(*( (struct in_addr *) (pkt->data+20))));
++ } else {
++ syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n",
++ pkt->data[13] == 6 ? "TCP" : "UDP",
++ ipstr,
++ ntohs(*( (short *) (pkt->data+iphdr+4))),
++ inet_ntoa(*( (struct in_addr *) (pkt->data+20))),
++ ntohs(*( (short *) (pkt->data+iphdr+6))));
++ }
++ }
+ output(0, pkt->data, pkt->length);
+ free(pkt);
+ } else {
+--- ppp/pppd/ipcp.c
++++ ppp/pppd/ipcp.c 2000/06/28 12:32:05
+@@ -1454,7 +1454,7 @@
+ proxy_arp_set[f->unit] = 1;
+
+ }
+- demand_rexmit(PPP_IP);
++ demand_rexmit(PPP_IP,go->ouraddr);
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ } else {
+--- ppp/pppd/ipv6cp.c
++++ ppp/pppd/ipv6cp.c 2000/06/28 12:32:06
+@@ -1153,7 +1153,7 @@
+ }
+
+ }
+- demand_rexmit(PPP_IPV6);
++ demand_rexmit(PPP_IPV6,0);
+ sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
+
+ } else {
+--- ppp/pppd/pppd.h
++++ ppp/pppd/pppd.h 2000/06/28 12:32:06
+@@ -359,7 +359,7 @@
+ 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 */
++void demand_rexmit __P((int, u_int32_t)); /* 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? */
+
--- /dev/null
+diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
+--- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
++++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
+@@ -48,19 +48,19 @@
+ # Uncomment the next line to include support for PPP packet filtering.
+ # This requires that the libpcap library and headers be installed
+ # and that the kernel driver support PPP packet filtering.
+-FILTER=y
++#FILTER=y
+
+ # Uncomment the next line to enable multilink PPP (enabled by default)
+ # Linux distributions: Please leave multilink ENABLED in your builds
+ # of pppd!
+-HAVE_MULTILINK=y
++#HAVE_MULTILINK=y
+
+ # Uncomment the next line to enable the TDB database (enabled by default.)
+ # If you enable multilink, then TDB is automatically enabled also.
+ # Linux distributions: Please leave TDB ENABLED in your builds.
+-USE_TDB=y
++#USE_TDB=y
+
+-HAS_SHADOW=y
++#HAS_SHADOW=y
+ #USE_PAM=y
+ #HAVE_INET6=y
+
+@@ -77,7 +77,7 @@
+
+ INCLUDE_DIRS= -I../include
+
+-COMPILE_FLAGS= -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MMAP
++COMPILE_FLAGS= -DHAVE_PATHS_H -DHAVE_MMAP
+
+ CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS)
+
+@@ -117,12 +117,12 @@
+ #LIBS += -lshadow $(LIBS)
+ endif
+
+-ifneq ($(wildcard /usr/include/crypt.h),)
++#ifneq ($(wildcard /usr/include/crypt.h),)
+ CFLAGS += -DHAVE_CRYPT_H=1
+-endif
+-ifneq ($(wildcard /usr/lib/libcrypt.*),)
++#endif
++#ifneq ($(wildcard /usr/lib/libcrypt.*),)
+ LIBS += -lcrypt
+-endif
++#endif
+
+ ifdef NEEDDES
+ ifndef USE_CRYPT
--- /dev/null
+diff -ruN ppp-2.4.3.orig/include/linux/ppp-comp.h ppp-2.4.3/include/linux/ppp-comp.h
+--- ppp-2.4.3.orig/include/linux/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
++++ ppp-2.4.3/include/linux/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -36,7 +36,7 @@
+ */
+
+ /*
+- * ==FILEVERSION 20020319==
++ * ==FILEVERSION 20020715==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+@@ -86,7 +86,7 @@
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+- unsigned char *obuf, int isize, int osize);
++ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+@@ -107,7 +107,7 @@
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+- unsigned char *obuf, int osize);
++ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+@@ -288,6 +288,33 @@
+ opts |= MPPE_OPT_UNKNOWN; \
+ } while (/* CONSTCOND */ 0)
+
++/* MPPE/MPPC definitions by J.D.*/
++#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
++#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
++#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
++#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
++#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
++
++/*
++ * Definitions for Stac LZS.
++ */
++
++#define CI_LZS 17 /* config option for Stac LZS */
++#define CILEN_LZS 5 /* length of config option */
++
++#define LZS_OVHD 4 /* max. LZS overhead */
++#define LZS_HIST_LEN 2048 /* LZS history size */
++#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
++
++#define LZS_MODE_NONE 0
++#define LZS_MODE_LCB 1
++#define LZS_MODE_CRC 2
++#define LZS_MODE_SEQ 3
++#define LZS_MODE_EXT 4
++
++#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
++#define LZS_EXT_BIT_COMP 0x20 /* bit C */
++
+ /*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+diff -ruN ppp-2.4.3.orig/include/net/ppp-comp.h ppp-2.4.3/include/net/ppp-comp.h
+--- ppp-2.4.3.orig/include/net/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
++++ ppp-2.4.3/include/net/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -255,6 +255,33 @@
+ opts |= MPPE_OPT_UNKNOWN; \
+ } while (/* CONSTCOND */ 0)
+
++/* MPPE/MPPC definitions by J.D.*/
++#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
++#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
++#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
++#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
++#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
++
++/*
++ * Definitions for Stac LZS.
++ */
++
++#define CI_LZS 17 /* config option for Stac LZS */
++#define CILEN_LZS 5 /* length of config option */
++
++#define LZS_OVHD 4 /* max. LZS overhead */
++#define LZS_HIST_LEN 2048 /* LZS history size */
++#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
++
++#define LZS_MODE_NONE 0
++#define LZS_MODE_LCB 1
++#define LZS_MODE_CRC 2
++#define LZS_MODE_SEQ 3
++#define LZS_MODE_EXT 4
++
++#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
++#define LZS_EXT_BIT_COMP 0x20 /* bit C */
++
+ /*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+diff -ruN ppp-2.4.3.orig/pppd/ccp.c ppp-2.4.3/pppd/ccp.c
+--- ppp-2.4.3.orig/pppd/ccp.c 2004-11-13 03:28:15.000000000 +0100
++++ ppp-2.4.3/pppd/ccp.c 2004-11-21 13:54:09.000000000 +0100
+@@ -62,12 +62,10 @@
+ static char bsd_value[8];
+ static char deflate_value[8];
+
+-/*
+- * Option variables.
+- */
+ #ifdef MPPE
+-bool refuse_mppe_stateful = 1; /* Allow stateful mode? */
+-#endif
++static int setmppe(char **);
++static int setnomppe(void);
++#endif /* MPPE */
+
+ static option_t ccp_option_list[] = {
+ { "noccp", o_bool, &ccp_protent.enabled_flag,
+@@ -108,54 +106,36 @@
+ "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
+ &ccp_allowoptions[0].predictor_1 },
+
++ { "lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_PRIO },
++ { "+lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_ALIAS | OPT_PRIO },
++ { "nolzs", o_bool, &ccp_wantoptions[0].lzs,
++ "don't allow Stac LZS", OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].lzs },
++ { "-lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "don't allow Stac LZS", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].lzs },
++
+ #ifdef MPPE
+- /* MPPE options are symmetrical ... we only set wantoptions here */
+- { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "require MPPE encryption",
+- OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+- { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "require MPPE encryption",
+- OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+- { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
+- "don't allow MPPE encryption", OPT_PRIO },
+- { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
+-
+- /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
+- { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+- { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+- { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 40-bit encryption",
+- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
+- { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 40-bit encryption",
+- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+-
+- { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+- { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 128-bit encryption",
+- OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+- { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 128-bit encryption",
+- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
+- { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 128-bit encryption",
+- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+-
+- /* strange one; we always request stateless, but will we allow stateful? */
+- { "mppe-stateful", o_bool, &refuse_mppe_stateful,
+- "allow MPPE stateful mode", OPT_PRIO },
+- { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
+- "disallow MPPE stateful mode", OPT_PRIO | 1 },
++ { "mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "request MPPC compression", 1, &ccp_allowoptions[0].mppc },
++ { "+mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "request MPPC compression", 1, &ccp_allowoptions[0].mppc, OPT_ALIAS },
++ { "nomppc", o_bool, &ccp_wantoptions[0].mppc,
++ "don't allow MPPC compression", OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].mppc },
++ { "-mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "don't allow MPPC compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].mppc },
++ { "mppe", o_special, (void *)setmppe,
++ "request MPPE encryption" },
++ { "+mppe", o_special, (void *)setmppe,
++ "request MPPE encryption" },
++ { "nomppe", o_special_noarg, (void *)setnomppe,
++ "don't allow MPPE encryption" },
++ { "-mppe", o_special_noarg, (void *)setnomppe,
++ "don't allow MPPE encryption" },
+ #endif /* MPPE */
+
+ { NULL }
+@@ -241,7 +221,7 @@
+ */
+ #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
+ || (opt).predictor_1 || (opt).predictor_2 \
+- || (opt).mppe)
++ || (opt).lzs || (opt).mppc || (opt).mppe)
+
+ /*
+ * Local state (mainly for handling reset-reqs and reset-acks).
+@@ -344,6 +324,100 @@
+ return 1;
+ }
+
++#ifdef MPPE
++/*
++ * Functions called from config options
++ */
++/*
++ MPPE suboptions:
++ required - require MPPE; disconnect if peer doesn't support it
++ stateless - use stateless mode
++ no40 - disable 40 bit keys
++ no56 - disable 56 bit keys
++ no128 - disable 128 bit keys
++*/
++int setmppe(char **argv)
++{
++ int i;
++ char *str, cmdbuf[16];
++
++ ccp_allowoptions[0].mppe = 1;
++ ccp_allowoptions[0].mppe_40 = 1;
++ ccp_allowoptions[0].mppe_56 = 1;
++ ccp_allowoptions[0].mppe_128 = 1;
++ ccp_allowoptions[0].mppe_stateless = 0;
++ ccp_wantoptions[0].mppe = 0;
++
++ str = *argv;
++
++ while (1) {
++ i = 0;
++ memset(cmdbuf, '\0', 16);
++ while ((i < 16) && (*str != ',') && (*str != '\0'))
++ cmdbuf[i++] = *str++;
++ cmdbuf[i] = '\0';
++ if (!strncasecmp(cmdbuf, "no40", strlen("no40"))) {
++ ccp_allowoptions[0].mppe_40 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "no56", strlen("no56"))) {
++ ccp_allowoptions[0].mppe_56 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "no128", strlen("no128"))) {
++ ccp_allowoptions[0].mppe_128 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "stateless", strlen("stateless"))) {
++ ccp_allowoptions[0].mppe_stateless = 1;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "required", strlen("required"))) {
++ ccp_wantoptions[0].mppe = 1;
++ goto next_param;
++ } else {
++ option_error("invalid parameter '%s' for mppe option", cmdbuf);
++ return 0;
++ }
++
++ next_param:
++ if (*str == ',') {
++ str++;
++ continue;
++ }
++ if (*str == '\0') {
++ if (!(ccp_allowoptions[0].mppe_40 || ccp_allowoptions[0].mppe_56 ||
++ ccp_allowoptions[0].mppe_128)) {
++ if (ccp_wantoptions[0].mppe == 1) {
++ option_error("You require MPPE but you have switched off "
++ "all encryption key lengths.");
++ return 0;
++ }
++ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_stateless =
++ ccp_allowoptions[0].mppe_stateless = 0;
++ } else {
++ ccp_allowoptions[0].mppe = 1;
++ ccp_wantoptions[0].mppe_stateless =
++ ccp_allowoptions[0].mppe_stateless;
++ if (ccp_wantoptions[0].mppe == 1) {
++ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40;
++ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56;
++ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128;
++ }
++ }
++ return 1;
++ }
++ }
++}
++
++int setnomppe(void)
++{
++ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40 = 0;
++ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56 = 0;
++ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128 = 0;
++ ccp_wantoptions[0].mppe_stateless = ccp_allowoptions[0].mppe_stateless = 0;
++ return 1;
++}
++#endif /* MPPE */
++
+ /*
+ * ccp_init - initialize CCP.
+ */
+@@ -378,6 +452,30 @@
+ ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
+
+ ccp_allowoptions[0].predictor_1 = 1;
++
++ ccp_wantoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
++ ccp_wantoptions[0].lzs_mode = LZS_MODE_SEQ;
++ ccp_wantoptions[0].lzs_hists = 1;
++ ccp_allowoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
++ ccp_allowoptions[0].lzs_mode = LZS_MODE_SEQ;
++ ccp_allowoptions[0].lzs_hists = 1;
++
++#ifdef MPPE
++ /* by default allow and request MPPC... */
++ ccp_wantoptions[0].mppc = ccp_allowoptions[0].mppc = 1;
++
++ /* ... and allow but don't request MPPE */
++ ccp_allowoptions[0].mppe = 1;
++ ccp_allowoptions[0].mppe_40 = 1;
++ ccp_allowoptions[0].mppe_56 = 1;
++ ccp_allowoptions[0].mppe_128 = 1;
++ ccp_allowoptions[0].mppe_stateless = 1;
++ ccp_wantoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_40 = 0;
++ ccp_wantoptions[0].mppe_56 = 0;
++ ccp_wantoptions[0].mppe_128 = 0;
++ ccp_wantoptions[0].mppe_stateless = 0;
++#endif /* MPPE */
+ }
+
+ /*
+@@ -455,11 +553,11 @@
+ if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
+ notice("Compression disabled by peer.");
+ #ifdef MPPE
+- if (ccp_gotoptions[unit].mppe) {
++ if (ccp_wantoptions[unit].mppe) {
+ error("MPPE disabled, closing LCP");
+ lcp_close(unit, "MPPE disabled by peer");
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -487,6 +585,15 @@
+ break;
+ /* send a reset-ack, which the transmitter will see and
+ reset its compression state. */
++
++ /* In case of MPPE/MPPC or LZS we shouldn't send CCP_RESETACK,
++ but we do it in order to reset compressor; CCP_RESETACK is
++ then silently discarded. See functions ppp_send_frame and
++ ppp_ccp_peek in ppp_generic.c (Linux only !!!). All the
++ confusion is caused by the fact that CCP code is splited
++ into two parts - one part is handled by pppd, the other one
++ is handled by kernel. */
++
+ fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
+ break;
+
+@@ -515,12 +622,11 @@
+ fsm_lowerdown(&ccp_fsm[unit]);
+
+ #ifdef MPPE
+- if (ccp_gotoptions[unit].mppe) {
++ if (ccp_wantoptions[unit].mppe) {
+ error("MPPE required but peer negotiation failed");
+ lcp_close(unit, "MPPE required but peer negotiation failed");
+ }
+-#endif
+-
++#endif /* MPPE */
+ }
+
+ /*
+@@ -537,7 +643,7 @@
+ all_rejected[f->unit] = 0;
+
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc) {
+ ccp_options *ao = &ccp_allowoptions[f->unit];
+ int auth_mschap_bits = auth_done[f->unit];
+ int numbits;
+@@ -551,80 +657,109 @@
+ * NB: If MPPE is required, all other compression opts are invalid.
+ * So, we return right away if we can't do it.
+ */
++ if (ccp_wantoptions[f->unit].mppe) {
++ /* Leave only the mschap auth bits set */
++ auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
++ CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
++ /* Count the mschap auths */
++ auth_mschap_bits >>= CHAP_MS_SHIFT;
++ numbits = 0;
++ do {
++ numbits += auth_mschap_bits & 1;
++ auth_mschap_bits >>= 1;
++ } while (auth_mschap_bits);
++ if (numbits > 1) {
++ error("MPPE required, but auth done in both directions.");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
++ }
++ if (!numbits) {
++ error("MPPE required, but MS-CHAP[v2] auth not performed.");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
++ }
+
+- /* Leave only the mschap auth bits set */
+- auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
+- CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
+- /* Count the mschap auths */
+- auth_mschap_bits >>= CHAP_MS_SHIFT;
+- numbits = 0;
+- do {
+- numbits += auth_mschap_bits & 1;
+- auth_mschap_bits >>= 1;
+- } while (auth_mschap_bits);
+- if (numbits > 1) {
+- error("MPPE required, but auth done in both directions.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+- if (!numbits) {
+- error("MPPE required, but MS-CHAP[v2] auth not performed.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+-
+- /* A plugin (eg radius) may not have obtained key material. */
+- if (!mppe_keys_set) {
+- error("MPPE required, but keys are not available. "
+- "Possible plugin problem?");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+-
+- /* LM auth not supported for MPPE */
+- if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
+- /* This might be noise */
+- if (go->mppe & MPPE_OPT_40) {
+- notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
+- go->mppe &= ~MPPE_OPT_40;
+- ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40;
++ /* A plugin (eg radius) may not have obtained key material. */
++ if (!mppe_keys_set) {
++ error("MPPE required, but keys are not available. "
++ "Possible plugin problem?");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
+ }
+ }
+
+- /* Last check: can we actually negotiate something? */
+- if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
+- /* Could be misconfig, could be 40-bit disabled above. */
+- error("MPPE required, but both 40-bit and 128-bit disabled.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
++ /*
++ * Check whether the kernel knows about the various
++ * compression methods we might request. Key material
++ * unimportant here.
++ */
++ if (go->mppc) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = 0;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_MPPC;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 0) <= 0)
++ go->mppc = 0;
++ }
++ if (go->mppe_40) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_40BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_40 = 0;
++ }
++ if (go->mppe_56) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_56BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_56 = 0;
++ }
++ if (go->mppe_128) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_128BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_128 = 0;
++ }
++ if (!go->mppe_40 && !go->mppe_56 && !go->mppe_128) {
++ if (ccp_wantoptions[f->unit].mppe) {
++ error("MPPE required, but kernel has no support.");
++ lcp_close(f->unit, "MPPE required but not available");
++ }
++ go->mppe = go->mppe_stateless = 0;
++ } else {
++ /* MPPE is not compatible with other compression types */
++ if (ccp_wantoptions[f->unit].mppe) {
++ ao->bsd_compress = go->bsd_compress = 0;
++ ao->predictor_1 = go->predictor_1 = 0;
++ ao->predictor_2 = go->predictor_2 = 0;
++ ao->deflate = go->deflate = 0;
++ ao->lzs = go->lzs = 0;
++ }
+ }
+-
+- /* sync options */
+- ao->mppe = go->mppe;
+- /* MPPE is not compatible with other compression types */
+- ao->bsd_compress = go->bsd_compress = 0;
+- ao->predictor_1 = go->predictor_1 = 0;
+- ao->predictor_2 = go->predictor_2 = 0;
+- ao->deflate = go->deflate = 0;
+ }
+ #endif /* MPPE */
+-
+- /*
+- * Check whether the kernel knows about the various
+- * compression methods we might request.
+- */
+-#ifdef MPPE
+- if (go->mppe) {
+- opt_buf[0] = CI_MPPE;
+- opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+- /* Key material unimportant here. */
+- if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) {
+- error("MPPE required, but kernel has no support.");
+- lcp_close(f->unit, "MPPE required but not available");
+- }
++ if (go->lzs) {
++ opt_buf[0] = CI_LZS;
++ opt_buf[1] = CILEN_LZS;
++ opt_buf[2] = go->lzs_hists >> 8;
++ opt_buf[3] = go->lzs_hists & 0xff;
++ opt_buf[4] = LZS_MODE_SEQ;
++ if (ccp_test(f->unit, opt_buf, CILEN_LZS, 0) <= 0)
++ go->lzs = 0;
+ }
+-#endif
+ if (go->bsd_compress) {
+ opt_buf[0] = CI_BSD_COMPRESS;
+ opt_buf[1] = CILEN_BSD_COMPRESS;
+@@ -679,7 +814,8 @@
+ + (go->deflate? CILEN_DEFLATE: 0)
+ + (go->predictor_1? CILEN_PREDICTOR_1: 0)
+ + (go->predictor_2? CILEN_PREDICTOR_2: 0)
+- + (go->mppe? CILEN_MPPE: 0);
++ + (go->lzs? CILEN_LZS: 0)
++ + ((go->mppe || go->mppc)? CILEN_MPPE: 0);
+ }
+
+ /*
+@@ -693,6 +829,8 @@
+ {
+ int res;
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ u_char *p0 = p;
+
+ /*
+@@ -701,22 +839,43 @@
+ * in case it gets Acked.
+ */
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
+ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+
+- p[0] = opt_buf[0] = CI_MPPE;
+- p[1] = opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &p[2]);
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
++ 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_56 ? MPPE_56BIT : 0) |
++ (go->mppe_128 ? MPPE_128BIT : 0) | (go->mppc ? MPPE_MPPC : 0);
++
++ BCOPY(p, opt_buf, CILEN_MPPE);
+ BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
+ res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
+- if (res > 0)
++ if (res > 0) {
+ p += CILEN_MPPE;
+- else
++ } else {
+ /* This shouldn't happen, we've already tested it! */
+- lcp_close(f->unit, "MPPE required but not available in kernel");
++ go->mppe = go->mppe_40 = go->mppe_56 = go->mppe_128 =
++ go->mppe_stateless = go->mppc = 0;
++ if (ccp_wantoptions[f->unit].mppe)
++ lcp_close(f->unit, "MPPE required but not available in kernel");
++ }
++ }
++#endif /* MPPE */
++ if (go->lzs) {
++ p[0] = CI_LZS;
++ p[1] = CILEN_LZS;
++ p[2] = go->lzs_hists >> 8;
++ p[3] = go->lzs_hists & 0xff;
++ p[4] = LZS_MODE_SEQ;
++ res = ccp_test(f->unit, p, CILEN_LZS, 0);
++ if (res > 0) {
++ p += CILEN_LZS;
++ } else
++ go->lzs = 0;
+ }
+-#endif
+ if (go->deflate) {
+ p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
+ p[1] = CILEN_DEFLATE;
+@@ -802,7 +961,7 @@
+
+ /*
+ * ccp_ackci - process a received configure-ack, and return
+- * 1 iff the packet was OK.
++ * 1 if the packet was OK.
+ */
+ static int
+ ccp_ackci(f, p, len)
+@@ -811,24 +970,44 @@
+ int len;
+ {
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ u_char *p0 = p;
+
+ #ifdef MPPE
+- if (go->mppe) {
+- u_char opt_buf[CILEN_MPPE];
+-
+- opt_buf[0] = CI_MPPE;
+- opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+- if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
++ if (go->mppe || go->mppc || (!wo->mppe && ao->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->mppc ? MPPE_MPPC : 0))
++ && p[5] != ((go->mppe_56 ? MPPE_56BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0))
++ && p[5] != ((go->mppe_128 ? MPPE_128BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0))))
+ return 0;
++ if (go->mppe_40 || go->mppe_56 || go->mppe_128)
++ go->mppe = 1;
+ p += CILEN_MPPE;
+ len -= CILEN_MPPE;
++ /* Cope with first/fast ack */
++ if (p == p0 && len == 0)
++ return 1;
++ }
++#endif /* MPPE */
++ if (go->lzs) {
++ if (len < CILEN_LZS || p[0] != CI_LZS || p[1] != CILEN_LZS
++ || p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
++ || p[4] != LZS_MODE_SEQ)
++ return 0;
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
+ /* XXX Cope with first/fast ack */
+- if (len == 0)
++ if (p == p0 && len == 0)
+ return 1;
+ }
+-#endif
+ if (go->deflate) {
+ if (len < CILEN_DEFLATE
+ || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+@@ -891,7 +1070,7 @@
+
+ /*
+ * ccp_nakci - process received configure-nak.
+- * Returns 1 iff the nak was OK.
++ * Returns 1 if the nak was OK.
+ */
+ static int
+ ccp_nakci(f, p, len, treat_as_reject)
+@@ -900,6 +1079,8 @@
+ int len;
+ {
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ ccp_options no; /* options we've seen already */
+ ccp_options try; /* options to ask for next time */
+
+@@ -907,28 +1088,100 @@
+ try = *go;
+
+ #ifdef MPPE
+- if (go->mppe && len >= CILEN_MPPE
+- && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+- no.mppe = 1;
+- /*
+- * Peer wants us to use a different strength or other setting.
+- * Fail if we aren't willing to use his suggestion.
+- */
+- MPPE_CI_TO_OPTS(&p[2], try.mppe);
+- if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) {
+- error("Refusing MPPE stateful mode offered by peer");
+- try.mppe = 0;
+- } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) {
+- /* Peer must have set options we didn't request (suggest) */
+- try.mppe = 0;
+- }
++ if ((go->mppe || go->mppc || (!wo->mppe && ao->mppe)) &&
++ len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+
+- if (!try.mppe) {
+- error("MPPE required but peer negotiation failed");
+- lcp_close(f->unit, "MPPE required but peer negotiation failed");
++ if (go->mppc) {
++ no.mppc = 1;
++ if (!(p[5] & MPPE_MPPC))
++ try.mppc = 0;
++ }
++
++ if (go->mppe)
++ no.mppe = 1;
++ if (go->mppe_40)
++ no.mppe_40 = 1;
++ if (go->mppe_56)
++ no.mppe_56 = 1;
++ if (go->mppe_128)
++ no.mppe_128 = 1;
++ if (go->mppe_stateless)
++ no.mppe_stateless = 1;
++
++ if (ao->mppe_40) {
++ if ((p[5] & MPPE_40BIT))
++ try.mppe_40 = 1;
++ else
++ try.mppe_40 = (p[5] == 0) ? 1 : 0;
++ }
++ if (ao->mppe_56) {
++ if ((p[5] & MPPE_56BIT))
++ try.mppe_56 = 1;
++ else
++ try.mppe_56 = (p[5] == 0) ? 1 : 0;
++ }
++ if (ao->mppe_128) {
++ if ((p[5] & MPPE_128BIT))
++ try.mppe_128 = 1;
++ else
++ try.mppe_128 = (p[5] == 0) ? 1 : 0;
++ }
++
++ if (ao->mppe_stateless) {
++ if ((p[2] & MPPE_STATELESS) || wo->mppe_stateless)
++ try.mppe_stateless = 1;
++ else
++ try.mppe_stateless = 0;
++ }
++
++ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128) {
++ try.mppe = try.mppe_stateless = 0;
++ if (wo->mppe) {
++ /* we require encryption, but peer doesn't support it
++ so we close connection */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
++ "key length");
++ }
++ }
++ if (wo->mppe && (wo->mppe_40 != try.mppe_40) &&
++ (wo->mppe_56 != try.mppe_56) && (wo->mppe_128 != try.mppe_128)) {
++ /* cannot negotiate key length */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "Cannot negotiate MPPE key length");
+ }
++ if (try.mppe_40 && try.mppe_56 && try.mppe_128)
++ try.mppe_40 = try.mppe_56 = 0;
++ else
++ if (try.mppe_56 && try.mppe_128)
++ try.mppe_56 = 0;
++ else
++ if (try.mppe_40 && try.mppe_128)
++ try.mppe_40 = 0;
++ else
++ if (try.mppe_40 && try.mppe_56)
++ try.mppe_40 = 0;
++
++ p += CILEN_MPPE;
++ len -= CILEN_MPPE;
+ }
+ #endif /* MPPE */
++
++ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
++ no.lzs = 1;
++ if (((p[2]<<8)|p[3]) > 1 || (p[4] != LZS_MODE_SEQ &&
++ p[4] != LZS_MODE_EXT))
++ try.lzs = 0;
++ else {
++ try.lzs_mode = p[4];
++ try.lzs_hists = (p[2] << 8) | p[3];
++ }
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
++ }
++
+ if (go->deflate && len >= CILEN_DEFLATE
+ && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+ && p[1] == CILEN_DEFLATE) {
+@@ -1001,14 +1254,50 @@
+ return -1;
+
+ #ifdef MPPE
+- if (go->mppe && len >= CILEN_MPPE
++ if ((go->mppe || go->mppc) && len >= CILEN_MPPE
+ && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+- error("MPPE required but peer refused");
+- lcp_close(f->unit, "MPPE required but peer refused");
++ ccp_options *wo = &ccp_wantoptions[f->unit];
++ if (p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) ||
++ p[3] != 0 ||
++ p[4] != 0 ||
++ p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
++ (go->mppe_56 ? MPPE_56BIT : 0) |
++ (go->mppe_128 ? MPPE_128BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0)))
++ return 0;
++ if (go->mppc)
++ try.mppc = 0;
++ if (go->mppe) {
++ try.mppe = 0;
++ if (go->mppe_40)
++ try.mppe_40 = 0;
++ if (go->mppe_56)
++ try.mppe_56 = 0;
++ if (go->mppe_128)
++ try.mppe_128 = 0;
++ if (go->mppe_stateless)
++ try.mppe_stateless = 0;
++ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128)
++ try.mppe = try.mppe_stateless = 0;
++ if (wo->mppe) { /* we want MPPE but cannot negotiate key length */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
++ "key length");
++ }
++ }
+ p += CILEN_MPPE;
+ len -= CILEN_MPPE;
+ }
+-#endif
++#endif /* MPPE */
++ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
++ if (p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
++ || p[4] != go->lzs_mode)
++ return 0;
++ try.lzs = 0;
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
++ }
+ if (go->deflate_correct && len >= CILEN_DEFLATE
+ && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
+ if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+@@ -1072,14 +1361,15 @@
+ int dont_nak;
+ {
+ int ret, newret, res;
+- u_char *p0, *retp;
++ u_char *p0, *retp, p2, p5;
+ int len, clen, type, nb;
+ ccp_options *ho = &ccp_hisoptions[f->unit];
+ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ #ifdef MPPE
+- bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
+- /* CI_MPPE, or due to other options? */
+-#endif
++ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
++/* int mtu; */
++#endif /* MPPE */
+
+ ret = CONFACK;
+ retp = p0 = p;
+@@ -1102,103 +1392,305 @@
+ switch (type) {
+ #ifdef MPPE
+ case CI_MPPE:
+- if (!ao->mppe || clen != CILEN_MPPE) {
++ if ((!ao->mppc && !ao->mppe) || clen != CILEN_MPPE) {
+ newret = CONFREJ;
+ break;
+ }
+- MPPE_CI_TO_OPTS(&p[2], ho->mppe);
+
+- /* Nak if anything unsupported or unknown are set. */
+- if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
+- newret = CONFNAK;
+- ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
+- }
+- if (ho->mppe & MPPE_OPT_UNKNOWN) {
++ p2 = p[2];
++ p5 = p[5];
++ /* not sure what they want, tell 'em what we got */
++ if (((p[2] & ~MPPE_STATELESS) != 0 || p[3] != 0 || p[4] != 0 ||
++ (p[5] & ~(MPPE_40BIT | MPPE_56BIT | MPPE_128BIT |
++ MPPE_MPPC)) != 0 || p[5] == 0) ||
++ (p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0)) {
+ newret = CONFNAK;
+- ho->mppe &= ~MPPE_OPT_UNKNOWN;
++ p[2] = (wo->mppe_stateless ? MPPE_STATELESS : 0);
++ p[3] = 0;
++ p[4] = 0;
++ p[5] = (wo->mppe_40 ? MPPE_40BIT : 0) |
++ (wo->mppe_56 ? MPPE_56BIT : 0) |
++ (wo->mppe_128 ? MPPE_128BIT : 0) |
++ (wo->mppc ? MPPE_MPPC : 0);
++ break;
+ }
+
+- /* Check state opt */
+- if (ho->mppe & MPPE_OPT_STATEFUL) {
+- /*
+- * We can Nak and request stateless, but it's a
+- * lot easier to just assume the peer will request
+- * it if he can do it; stateful mode is bad over
+- * the Internet -- which is where we expect MPPE.
+- */
+- if (refuse_mppe_stateful) {
+- error("Refusing MPPE stateful mode offered by peer");
++ if ((p[5] & MPPE_MPPC)) {
++ if (ao->mppc) {
++ ho->mppc = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ opt_buf[2] = opt_buf[3] = opt_buf[4] = 0;
++ opt_buf[5] = MPPE_MPPC;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 1) <= 0) {
++ ho->mppc = 0;
++ p[5] &= ~MPPE_MPPC;
++ newret = CONFNAK;
++ }
++ } else {
+ newret = CONFREJ;
+- break;
++ if (wo->mppe || ao->mppe) {
++ p[5] &= ~MPPE_MPPC;
++ newret = CONFNAK;
++ }
++ }
++ }
++
++ if (ao->mppe)
++ ho->mppe = 1;
++
++ if ((p[2] & MPPE_STATELESS)) {
++ if (ao->mppe_stateless) {
++ if (wo->mppe_stateless)
++ ho->mppe_stateless = 1;
++ else {
++ newret = CONFNAK;
++ if (!dont_nak)
++ p[2] &= ~MPPE_STATELESS;
++ }
++ } else {
++ newret = CONFNAK;
++ if (!dont_nak)
++ p[2] &= ~MPPE_STATELESS;
++ }
++ } else {
++ if (wo->mppe_stateless && !dont_nak) {
++ wo->mppe_stateless = 0;
++ newret = CONFNAK;
++ p[2] |= MPPE_STATELESS;
+ }
+ }
+
+- /* Find out which of {S,L} are set. */
+- if ((ho->mppe & MPPE_OPT_128)
+- && (ho->mppe & MPPE_OPT_40)) {
+- /* Both are set, negotiate the strongest. */
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
+ newret = CONFNAK;
+- if (ao->mppe & MPPE_OPT_128)
+- ho->mppe &= ~MPPE_OPT_40;
+- else if (ao->mppe & MPPE_OPT_40)
+- ho->mppe &= ~MPPE_OPT_128;
+- else {
+- newret = CONFREJ;
+- break;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~(MPPE_40BIT|MPPE_56BIT);
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= (MPPE_40BIT|MPPE_56BIT);
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56_40;
++ }
++ goto check_mppe;
+ }
+- } else if (ho->mppe & MPPE_OPT_128) {
+- if (!(ao->mppe & MPPE_OPT_128)) {
+- newret = CONFREJ;
+- break;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56_40;
++ }
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_56BIT|MPPE_128BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~MPPE_56BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= MPPE_56BIT;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56;
++ }
++ goto check_mppe;
+ }
+- } else if (ho->mppe & MPPE_OPT_40) {
+- if (!(ao->mppe & MPPE_OPT_40)) {
+- newret = CONFREJ;
+- break;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56;
++ }
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_128BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~MPPE_40BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= MPPE_40BIT;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_40;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_40;
++ }
++ if ((p[5] & ~MPPE_MPPC) == MPPE_128BIT) {
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] &= ~MPPE_128BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ newret = CONFNAK;
++ goto check_mppe;
++ }
++ check_mppe_56_40:
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_56) {
++ ho->mppe_56 = 1;
++ p[5] &= ~MPPE_40BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_56 = 0;
++ p[5] |= MPPE_40BIT;
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ goto check_mppe_40;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_56BIT;
++ goto check_mppe_40;
++ }
++ check_mppe_56:
++ if ((p[5] & ~MPPE_MPPC) == MPPE_56BIT) {
++ if (ao->mppe_56) {
++ ho->mppe_56 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_56 = 0;
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ goto check_mppe;
++ }
++ check_mppe_40:
++ if ((p[5] & ~MPPE_MPPC) == MPPE_40BIT) {
++ if (ao->mppe_40) {
++ ho->mppe_40 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_40 = 0;
++ p[5] &= ~MPPE_40BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_40BIT;
++ }
++
++ check_mppe:
++ if (!ho->mppe_40 && !ho->mppe_56 && !ho->mppe_128) {
++ if (wo->mppe_40 || wo->mppe_56 || wo->mppe_128) {
++ newret = CONFNAK;
++ p[2] |= (wo->mppe_stateless ? MPPE_STATELESS : 0);
++ p[5] |= (wo->mppe_40 ? MPPE_40BIT : 0) |
++ (wo->mppe_56 ? MPPE_56BIT : 0) |
++ (wo->mppe_128 ? MPPE_128BIT : 0) |
++ (wo->mppc ? MPPE_MPPC : 0);
++ } else {
++ ho->mppe = ho->mppe_stateless = 0;
+ }
+ } else {
+- /* Neither are set. */
++ /* MPPE is not compatible with other compression types */
++ if (wo->mppe) {
++ ao->bsd_compress = 0;
++ ao->predictor_1 = 0;
++ ao->predictor_2 = 0;
++ ao->deflate = 0;
++ ao->lzs = 0;
++ }
++ }
++ if ((!ho->mppc || !ao->mppc) && !ho->mppe) {
++ p[2] = p2;
++ p[5] = p5;
+ newret = CONFREJ;
+ break;
+ }
+
+- /* rebuild the opts */
+- MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
+- if (newret == CONFACK) {
+- u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+- int mtu;
+-
+- BCOPY(p, opt_buf, CILEN_MPPE);
+- BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
+- MPPE_MAX_KEY_LEN);
+- if (ccp_test(f->unit, opt_buf,
+- CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
+- /* This shouldn't happen, we've already tested it! */
+- error("MPPE required, but kernel has no support.");
+- lcp_close(f->unit, "MPPE required but not available");
+- newret = CONFREJ;
+- break;
+- }
+- /*
+- * We need to decrease the interface MTU by MPPE_PAD
+- * because MPPE frames **grow**. The kernel [must]
+- * allocate MPPE_PAD extra bytes in xmit buffers.
+- */
+- mtu = netif_get_mtu(f->unit);
+- if (mtu)
+- netif_set_mtu(f->unit, mtu - MPPE_PAD);
+- else
+- newret = CONFREJ;
+- }
++ /*
++ * I have commented the code below because according to RFC1547
++ * MTU is only information for higher level protocols about
++ * "the maximum allowable length for a packet (q.v.) transmitted
++ * over a point-to-point link without incurring network layer
++ * fragmentation." Of course a PPP implementation should be able
++ * to handle overhead added by MPPE - in our case apropriate code
++ * is located in drivers/net/ppp_generic.c in the kernel sources.
++ *
++ * According to RFC1661:
++ * - when negotiated MRU is less than 1500 octets, a PPP
++ * implementation must still be able to receive at least 1500
++ * octets,
++ * - when PFC is negotiated, a PPP implementation is still
++ * required to receive frames with uncompressed protocol field.
++ *
++ * So why not to handle MPPE overhead without changing MTU value?
++ * I am sure that RFC3078, unfortunately silently, assumes that.
++ */
+
+ /*
+- * We have accepted MPPE or are willing to negotiate
+- * MPPE parameters. A CONFREJ is due to subsequent
+- * (non-MPPE) processing.
++ * We need to decrease the interface MTU by MPPE_PAD
++ * because MPPE frames **grow**. The kernel [must]
++ * allocate MPPE_PAD extra bytes in xmit buffers.
+ */
+- rej_for_ci_mppe = 0;
++/*
++ mtu = netif_get_mtu(f->unit);
++ if (mtu) {
++ netif_set_mtu(f->unit, mtu - MPPE_PAD);
++ } else {
++ newret = CONFREJ;
++ if (ccp_wantoptions[f->unit].mppe) {
++ error("Cannot adjust MTU needed by MPPE.");
++ lcp_close(f->unit, "Cannot adjust MTU needed by MPPE.");
++ }
++ }
++*/
+ break;
+ #endif /* MPPE */
++
++ case CI_LZS:
++ if (!ao->lzs || clen != CILEN_LZS) {
++ newret = CONFREJ;
++ break;
++ }
++
++ ho->lzs = 1;
++ ho->lzs_hists = (p[2] << 8) | p[3];
++ ho->lzs_mode = p[4];
++ if ((ho->lzs_hists != ao->lzs_hists) ||
++ (ho->lzs_mode != ao->lzs_mode)) {
++ newret = CONFNAK;
++ if (!dont_nak) {
++ p[2] = ao->lzs_hists >> 8;
++ p[3] = ao->lzs_hists & 0xff;
++ p[4] = ao->lzs_mode;
++ } else
++ break;
++ }
++
++ if (p == p0 && ccp_test(f->unit, p, CILEN_LZS, 1) <= 0) {
++ newret = CONFREJ;
++ }
++ break;
++
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (!ao->deflate || clen != CILEN_DEFLATE
+@@ -1340,12 +1832,6 @@
+ else
+ *lenp = retp - p0;
+ }
+-#ifdef MPPE
+- if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
+- error("MPPE required but peer negotiation failed");
+- lcp_close(f->unit, "MPPE required but peer negotiation failed");
+- }
+-#endif
+ return ret;
+ }
+
+@@ -1367,24 +1853,35 @@
+ char *p = result;
+ char *q = result + sizeof(result); /* 1 past result */
+
+- slprintf(p, q - p, "MPPE ");
+- p += 5;
+- if (opt->mppe & MPPE_OPT_128) {
+- slprintf(p, q - p, "128-bit ");
+- p += 8;
+- }
+- if (opt->mppe & MPPE_OPT_40) {
+- slprintf(p, q - p, "40-bit ");
+- p += 7;
+- }
+- if (opt->mppe & MPPE_OPT_STATEFUL)
+- slprintf(p, q - p, "stateful");
+- else
+- slprintf(p, q - p, "stateless");
+-
++ if (opt->mppe) {
++ if (opt->mppc) {
++ slprintf(p, q - p, "MPPC/MPPE ");
++ p += 10;
++ } else {
++ slprintf(p, q - p, "MPPE ");
++ p += 5;
++ }
++ if (opt->mppe_128) {
++ slprintf(p, q - p, "128-bit ");
++ p += 8;
++ } else if (opt->mppe_56) {
++ slprintf(p, q - p, "56-bit ");
++ p += 7;
++ } else if (opt->mppe_40) {
++ slprintf(p, q - p, "40-bit ");
++ p += 7;
++ }
++ if (opt->mppe_stateless)
++ slprintf(p, q - p, "stateless");
++ else
++ slprintf(p, q - p, "stateful");
++ } else if (opt->mppc)
++ slprintf(p, q - p, "MPPC");
+ break;
+ }
+-#endif
++#endif /* MPPE */
++ case CI_LZS:
++ return "Stac LZS";
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
+@@ -1440,12 +1937,12 @@
+ } else if (ANY_COMPRESS(*ho))
+ notice("%s transmit compression enabled", method_name(ho, NULL));
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc) {
+ BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN);
+ BZERO(mppe_send_key, MPPE_MAX_KEY_LEN);
+ continue_networks(f->unit); /* Bring up IP et al */
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -1468,7 +1965,7 @@
+ lcp_close(f->unit, "MPPE disabled");
+ }
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -1528,24 +2025,28 @@
+ #ifdef MPPE
+ case CI_MPPE:
+ if (optlen >= CILEN_MPPE) {
+- u_char mppe_opts;
+-
+- MPPE_CI_TO_OPTS(&p[2], mppe_opts);
+- printer(arg, "mppe %s %s %s %s %s %s%s",
+- (p[2] & MPPE_H_BIT)? "+H": "-H",
+- (p[5] & MPPE_M_BIT)? "+M": "-M",
+- (p[5] & MPPE_S_BIT)? "+S": "-S",
+- (p[5] & MPPE_L_BIT)? "+L": "-L",
++ printer(arg, "mppe %s %s %s %s %s %s",
++ (p[2] & MPPE_STATELESS)? "+H": "-H",
++ (p[5] & MPPE_56BIT)? "+M": "-M",
++ (p[5] & MPPE_128BIT)? "+S": "-S",
++ (p[5] & MPPE_40BIT)? "+L": "-L",
+ (p[5] & MPPE_D_BIT)? "+D": "-D",
+- (p[5] & MPPE_C_BIT)? "+C": "-C",
+- (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
+- if (mppe_opts & MPPE_OPT_UNKNOWN)
++ (p[5] & MPPE_MPPC)? "+C": "-C");
++ if ((p[5] & ~(MPPE_56BIT | MPPE_128BIT | MPPE_40BIT |
++ MPPE_D_BIT | MPPE_MPPC)) ||
++ (p[2] & ~MPPE_STATELESS))
+ printer(arg, " (%.2x %.2x %.2x %.2x)",
+ p[2], p[3], p[4], p[5]);
+ p += CILEN_MPPE;
+ }
+ break;
+-#endif
++#endif /* MPPE */
++ case CI_LZS:
++ if (optlen >= CILEN_LZS) {
++ printer(arg, "lzs %.2x %.2x %.2x", p[2], p[3], p[4]);
++ p += CILEN_LZS;
++ }
++ break;
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (optlen >= CILEN_DEFLATE) {
+@@ -1631,6 +2132,7 @@
+ error("Lost compression sync: disabling compression");
+ ccp_close(unit, "Lost compression sync");
+ #ifdef MPPE
++ /* My module dosn't need this. J.D., 2003-07-06 */
+ /*
+ * If we were doing MPPE, we must also take the link down.
+ */
+@@ -1638,9 +2140,18 @@
+ error("Too many MPPE errors, closing LCP");
+ lcp_close(unit, "Too many MPPE errors");
+ }
+-#endif
++#endif /* MPPE */
+ } else {
+ /*
++ * When LZS or MPPE/MPPC is negotiated we just send CCP_RESETREQ
++ * and don't wait for CCP_RESETACK
++ */
++ if ((ccp_gotoptions[f->unit].method == CI_LZS) ||
++ (ccp_gotoptions[f->unit].method == CI_MPPE)) {
++ fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
++ 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.
+@@ -1671,4 +2182,3 @@
+ } else
+ ccp_localstate[f->unit] &= ~RACK_PENDING;
+ }
+-
+diff -ruN ppp-2.4.3.orig/pppd/ccp.h ppp-2.4.3/pppd/ccp.h
+--- ppp-2.4.3.orig/pppd/ccp.h 2004-11-04 11:02:26.000000000 +0100
++++ ppp-2.4.3/pppd/ccp.h 2004-11-21 13:54:09.000000000 +0100
+@@ -37,9 +37,17 @@
+ bool predictor_2; /* do Predictor-2? */
+ bool deflate_correct; /* use correct code for deflate? */
+ bool deflate_draft; /* use draft RFC code for deflate? */
++ bool lzs; /* do Stac LZS? */
++ bool mppc; /* do MPPC? */
+ bool mppe; /* do MPPE? */
++ bool mppe_40; /* allow 40 bit encryption? */
++ bool mppe_56; /* allow 56 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 */
++ u_short lzs_mode; /* LZS check mode */
++ u_short lzs_hists; /* number of LZS histories */
+ short method; /* code for chosen compression method */
+ } ccp_options;
+
+diff -ruN ppp-2.4.3.orig/pppd/chap_ms.c ppp-2.4.3/pppd/chap_ms.c
+--- ppp-2.4.3.orig/pppd/chap_ms.c 2004-11-12 10:57:43.000000000 +0100
++++ ppp-2.4.3/pppd/chap_ms.c 2004-11-21 13:54:09.000000000 +0100
+@@ -895,13 +895,17 @@
+ /*
+ * Disable undesirable encryption types. Note that we don't ENABLE
+ * any encryption types, to avoid overriding manual configuration.
++ *
++ * It seems that 56 bit keys are unsupported in MS-RADIUS (see RFC 2548)
+ */
+ switch(types) {
+ case MPPE_ENC_TYPES_RC4_40:
+- ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
++ ccp_wantoptions[0].mppe_128 = 0; /* disable 128-bit */
++ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
+ break;
+ case MPPE_ENC_TYPES_RC4_128:
+- ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */
++ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
++ ccp_wantoptions[0].mppe_40 = 0; /* disable 40-bit */
+ break;
+ default:
+ break;
+diff -ruN ppp-2.4.3.orig/pppd/pppd.8 ppp-2.4.3/pppd/pppd.8
+--- ppp-2.4.3.orig/pppd/pppd.8 2004-11-13 13:22:49.000000000 +0100
++++ ppp-2.4.3/pppd/pppd.8 2004-11-21 14:24:47.000000000 +0100
+@@ -622,9 +622,29 @@
+ Enables the use of PPP multilink; this is an alias for the `multilink'
+ option. This option is currently only available under Linux.
+ .TP
+-.B mppe\-stateful
+-Allow MPPE to use stateful mode. Stateless mode is still attempted first.
+-The default is to disallow stateful mode.
++.B mppc
++Enables MPPC (Microsoft Point to Point Compression). This is the default.
++.TP
++.B mppe \fIsubopt1[,subopt2[,subopt3[..]]]
++Modify MPPE (Microsoft Point to Point Encryption) parameters. In order
++for MPPE to successfully come up, you must have authenticated with either
++MS-CHAP or MS-CHAPv2. By default MPPE is optional, it means that pppd will
++not propose MPPE to the peer, but will negotiate MPPE if peer wants that.
++You can change this using \fIrequired\fR suboption.
++This option is presently only supported under Linux, and only if your
++kernel has been configured to include MPPE support.
++.IP
++MPPE suboptions:
++.br
++\fIrequired\fR - require MPPE; disconnect if peer doesn't support it,
++.br
++\fIstateless\fR - try to negotiate stateless mode; default is stateful,
++.br
++\fIno40\fR - disable 40 bit keys,
++.br
++\fIno56\fR - disable 56 bit keys,
++.br
++\fIno128\fR - disable 128 bit keys
+ .TP
+ .B mpshortseq
+ Enables the use of short (12-bit) sequence numbers in multilink
+@@ -757,17 +777,11 @@
+ Disables the use of PPP multilink. This option is currently only
+ available under Linux.
+ .TP
+-.B nomppe
+-Disables MPPE (Microsoft Point to Point Encryption). This is the default.
+-.TP
+-.B nomppe\-40
+-Disable 40-bit encryption with MPPE.
++.B nomppc
++Disables MPPC (Microsoft Point to Point Compression).
+ .TP
+-.B nomppe\-128
+-Disable 128-bit encryption with MPPE.
+-.TP
+-.B nomppe\-stateful
+-Disable MPPE stateful mode. This is the default.
++.B nomppe
++Disables MPPE (Microsoft Point to Point Encryption).
+ .TP
+ .B nompshortseq
+ Disables the use of short (12-bit) sequence numbers in the PPP
+@@ -948,19 +962,6 @@
+ Require the peer to authenticate itself using CHAP [Challenge
+ Handshake Authentication Protocol] authentication.
+ .TP
+-.B require\-mppe
+-Require the use of MPPE (Microsoft Point to Point Encryption). This
+-option disables all other compression types. This option enables
+-both 40-bit and 128-bit encryption. In order for MPPE to successfully
+-come up, you must have authenticated with either MS\-CHAP or MS\-CHAPv2.
+-This option is presently only supported under Linux, and only if your
+-kernel has been configured to include MPPE support.
+-.TP
+-.B require\-mppe\-40
+-Require the use of MPPE, with 40-bit encryption.
+-.TP
+-.B require\-mppe\-128
+-Require the use of MPPE, with 128-bit encryption.
+ .TP
+ .B require\-mschap
+ Require the peer to authenticate itself using MS\-CHAP [Microsoft Challenge
--- /dev/null
+diff -ruN ppp-2.4.3-orig/pppd/plugins/Makefile.linux ppp-2.4.3-3/pppd/plugins/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/Makefile.linux 2004-11-14 08:57:35.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/Makefile.linux 2004-12-05 17:03:59.000000000 +0100
+@@ -9,7 +9,7 @@
+ MANDIR = $(DESTDIR)/share/man/man8
+ LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
+
+-SUBDIRS := rp-pppoe pppoatm radius
++SUBDIRS := rp-pppoe radius
+ # Uncomment the next line to include the radius authentication plugin
+ # SUBDIRS += radius
+ PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
--- /dev/null
+diff -ruN ppp-2.4.3-orig/chat/Makefile.linux ppp-2.4.3-3/chat/Makefile.linux
+--- ppp-2.4.3-orig/chat/Makefile.linux 2004-11-03 12:51:47.000000000 +0100
++++ ppp-2.4.3-3/chat/Makefile.linux 2004-12-05 17:42:43.000000000 +0100
+@@ -25,7 +25,7 @@
+
+ install: chat
+ mkdir -p $(BINDIR)
+- $(INSTALL) -s -c chat $(BINDIR)
++ $(INSTALL) -c chat $(BINDIR)
+ $(INSTALL) -c -m 644 chat.8 $(MANDIR)
+
+ clean:
+diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
+--- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
++++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
+@@ -99,7 +99,7 @@
+ CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include
+ LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto
+ TARGETS += srp-entry
+-EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
++EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry
+ MANPAGES += srp-entry.8
+ EXTRACLEAN += srp-entry.o
+ NEEDDES=y
+@@ -202,7 +202,7 @@
+ install: pppd
+ mkdir -p $(BINDIR) $(MANDIR)
+ $(EXTRAINSTALL)
+- $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
++ $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd
+ if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
+ chmod o-rx,u+s $(BINDIR)/pppd; fi
+ $(INSTALL) -c -m 444 pppd.8 $(MANDIR)
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
+@@ -36,9 +37,9 @@
+
+ install: all
+ $(INSTALL) -d -m 755 $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radius.so $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radattr.so $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radrealms.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radius.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radattr.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radrealms.so $(LIBDIR)
+ $(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR)
+ $(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR)
+
+diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux 2004-11-14 08:58:37.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux 2004-12-05 17:43:23.000000000 +0100
+@@ -39,9 +39,9 @@
+
+ install: all
+ $(INSTALL) -d -m 755 $(LIBDIR)
+- $(INSTALL) -s -c -m 4550 rp-pppoe.so $(LIBDIR)
++ $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR)
+ $(INSTALL) -d -m 755 $(BINDIR)
+- $(INSTALL) -s -c -m 555 pppoe-discovery $(BINDIR)
++ $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
+
+ clean:
+ rm -f *.o *.so
+diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
+--- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
++++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
+@@ -17,5 +18,5 @@
+
+ install:
+ mkdir -p $(BINDIR) $(MANDIR)
+- $(INSTALL) -s -c pppdump $(BINDIR)
++ $(INSTALL) -c pppdump $(BINDIR)
+ $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
+diff -ruN ppp-2.4.3-orig/pppstats/Makefile.linux ppp-2.4.3-3/pppstats/Makefile.linux
+--- ppp-2.4.3-orig/pppstats/Makefile.linux 2004-10-31 23:09:03.000000000 +0100
++++ ppp-2.4.3-3/pppstats/Makefile.linux 2004-12-05 17:43:38.000000000 +0100
+@@ -22,7 +22,7 @@
+
+ install: pppstats
+ -mkdir -p $(MANDIR)
+- $(INSTALL) -s -c pppstats $(BINDIR)
++ $(INSTALL) -c pppstats $(BINDIR)
+ $(INSTALL) -c -m 444 pppstats.8 $(MANDIR)
+
+ pppstats: $(PPPSTATSRCS)
--- /dev/null
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
+--- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
+@@ -12,7 +12,8 @@
+ INSTALL = install
+
+ PLUGIN=radius.so radattr.so radrealms.so
+-CFLAGS=-I. -I../.. -I../../../include -O2 -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
++COPTS = -O2
++CFLAGS=-I. -I../.. -I../../../include $(COPTS) -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
+
+ # Uncomment the next line to include support for Microsoft's
+ # MS-CHAP authentication protocol.
+diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
+--- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
++++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
+@@ -2,7 +2,8 @@
+ BINDIR = $(DESTDIR)/sbin
+ MANDIR = $(DESTDIR)/share/man/man8
+
+-CFLAGS= -O -I../include/net
++COPTS = -O
++CFLAGS= $(COPTS) -I../include/net
+ OBJS = pppdump.o bsd-comp.o deflate.o zlib.o
+
+ INSTALL= install
--- /dev/null
+diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c
+--- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c 2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c 2004-12-16 01:07:22.000000000 +0100
+@@ -286,7 +286,7 @@
+ /* Strip off "nic-" */
+ cmd += 4;
+ } else if (strlen(cmd) < 4
+- || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3)
++ || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3) && strncmp(cmd, "vlan", 4)
+ && strncmp(cmd, "tap", 3) && strncmp(cmd, "br", 2))) {
+ return 0;
+ }
--- /dev/null
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/config.c ppp-2.4.3-3/pppd/plugins/radius/config.c
+--- ppp-2.4.3-orig/pppd/plugins/radius/config.c 2004-11-14 08:26:26.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/config.c 2004-12-16 04:03:46.000000000 +0100
+@@ -369,31 +369,37 @@
+ }
+ #endif
+
++#if 0
+ if (rc_conf_int("login_tries") <= 0)
+ {
+ error("%s: login_tries <= 0 is illegal", filename);
+ return (-1);
+ }
++#endif
+ if (rc_conf_str("seqfile") == NULL)
+ {
+ error("%s: seqfile not specified", filename);
+ return (-1);
+ }
++#if 0
+ if (rc_conf_int("login_timeout") <= 0)
+ {
+ error("%s: login_timeout <= 0 is illegal", filename);
+ return (-1);
+ }
++#endif
+ if (rc_conf_str("mapfile") == NULL)
+ {
+ error("%s: mapfile not specified", filename);
+ return (-1);
+ }
++#if 0
+ if (rc_conf_str("nologin") == NULL)
+ {
+ error("%s: nologin not specified", filename);
+ return (-1);
+ }
++#endif
+
+ return 0;
+ }
+diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/options.h ppp-2.4.3-3/pppd/plugins/radius/options.h
+--- ppp-2.4.3-orig/pppd/plugins/radius/options.h 2004-11-14 08:26:26.000000000 +0100
++++ ppp-2.4.3-3/pppd/plugins/radius/options.h 2004-12-16 04:09:16.000000000 +0100
+@@ -31,24 +31,21 @@
+ static SERVER acctserver = {0};
+ static SERVER authserver = {0};
+
+-int default_tries = 4;
+-int default_timeout = 60;
+-
+ static OPTION config_options[] = {
+ /* internally used options */
+ {"config_file", OT_STR, ST_UNDEF, NULL},
+ /* General options */
+ {"auth_order", OT_AUO, ST_UNDEF, NULL},
+-{"login_tries", OT_INT, ST_UNDEF, &default_tries},
+-{"login_timeout", OT_INT, ST_UNDEF, &default_timeout},
+-{"nologin", OT_STR, ST_UNDEF, "/etc/nologin"},
+-{"issue", OT_STR, ST_UNDEF, "/etc/radiusclient/issue"},
++{"login_tries", OT_INT, ST_UNDEF, NULL},
++{"login_timeout", OT_INT, ST_UNDEF, NULL},
++{"nologin", OT_STR, ST_UNDEF, NULL},
++{"issue", OT_STR, ST_UNDEF, NULL},
+ /* RADIUS specific options */
+ {"authserver", OT_SRV, ST_UNDEF, &authserver},
+ {"acctserver", OT_SRV, ST_UNDEF, &acctserver},
+ {"servers", OT_STR, ST_UNDEF, NULL},
+ {"dictionary", OT_STR, ST_UNDEF, NULL},
+-{"login_radius", OT_STR, ST_UNDEF, "/usr/sbin/login.radius"},
++{"login_radius", OT_STR, ST_UNDEF, NULL},
+ {"seqfile", OT_STR, ST_UNDEF, NULL},
+ {"mapfile", OT_STR, ST_UNDEF, NULL},
+ {"default_realm", OT_STR, ST_UNDEF, NULL},
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
---- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
-+++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
-@@ -48,19 +48,19 @@
- # Uncomment the next line to include support for PPP packet filtering.
- # This requires that the libpcap library and headers be installed
- # and that the kernel driver support PPP packet filtering.
--FILTER=y
-+#FILTER=y
-
- # Uncomment the next line to enable multilink PPP (enabled by default)
- # Linux distributions: Please leave multilink ENABLED in your builds
- # of pppd!
--HAVE_MULTILINK=y
-+#HAVE_MULTILINK=y
-
- # Uncomment the next line to enable the TDB database (enabled by default.)
- # If you enable multilink, then TDB is automatically enabled also.
- # Linux distributions: Please leave TDB ENABLED in your builds.
--USE_TDB=y
-+#USE_TDB=y
-
--HAS_SHADOW=y
-+#HAS_SHADOW=y
- #USE_PAM=y
- #HAVE_INET6=y
-
-@@ -77,7 +77,7 @@
-
- INCLUDE_DIRS= -I../include
-
--COMPILE_FLAGS= -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MMAP
-+COMPILE_FLAGS= -DHAVE_PATHS_H -DHAVE_MMAP
-
- CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS)
-
-@@ -117,12 +117,12 @@
- #LIBS += -lshadow $(LIBS)
- endif
-
--ifneq ($(wildcard /usr/include/crypt.h),)
-+#ifneq ($(wildcard /usr/include/crypt.h),)
- CFLAGS += -DHAVE_CRYPT_H=1
--endif
--ifneq ($(wildcard /usr/lib/libcrypt.*),)
-+#endif
-+#ifneq ($(wildcard /usr/lib/libcrypt.*),)
- LIBS += -lcrypt
--endif
-+#endif
-
- ifdef NEEDDES
- ifndef USE_CRYPT
+++ /dev/null
-diff -ruN ppp-2.4.3.orig/include/linux/ppp-comp.h ppp-2.4.3/include/linux/ppp-comp.h
---- ppp-2.4.3.orig/include/linux/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
-+++ ppp-2.4.3/include/linux/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
-@@ -36,7 +36,7 @@
- */
-
- /*
-- * ==FILEVERSION 20020319==
-+ * ==FILEVERSION 20020715==
- *
- * NOTE TO MAINTAINERS:
- * If you modify this file at all, please set the above date.
-@@ -86,7 +86,7 @@
-
- /* Compress a packet */
- int (*compress) (void *state, unsigned char *rptr,
-- unsigned char *obuf, int isize, int osize);
-+ unsigned char *obuf, int isize, int osize);
-
- /* Return compression statistics */
- void (*comp_stat) (void *state, struct compstat *stats);
-@@ -107,7 +107,7 @@
-
- /* Decompress a packet. */
- int (*decompress) (void *state, unsigned char *ibuf, int isize,
-- unsigned char *obuf, int osize);
-+ unsigned char *obuf, int osize);
-
- /* Update state for an incompressible packet received */
- void (*incomp) (void *state, unsigned char *ibuf, int icnt);
-@@ -288,6 +288,33 @@
- opts |= MPPE_OPT_UNKNOWN; \
- } while (/* CONSTCOND */ 0)
-
-+/* MPPE/MPPC definitions by J.D.*/
-+#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
-+#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
-+#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
-+#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
-+#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
-+
-+/*
-+ * Definitions for Stac LZS.
-+ */
-+
-+#define CI_LZS 17 /* config option for Stac LZS */
-+#define CILEN_LZS 5 /* length of config option */
-+
-+#define LZS_OVHD 4 /* max. LZS overhead */
-+#define LZS_HIST_LEN 2048 /* LZS history size */
-+#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
-+
-+#define LZS_MODE_NONE 0
-+#define LZS_MODE_LCB 1
-+#define LZS_MODE_CRC 2
-+#define LZS_MODE_SEQ 3
-+#define LZS_MODE_EXT 4
-+
-+#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
-+#define LZS_EXT_BIT_COMP 0x20 /* bit C */
-+
- /*
- * Definitions for other, as yet unsupported, compression methods.
- */
-diff -ruN ppp-2.4.3.orig/include/net/ppp-comp.h ppp-2.4.3/include/net/ppp-comp.h
---- ppp-2.4.3.orig/include/net/ppp-comp.h 2002-12-06 10:49:15.000000000 +0100
-+++ ppp-2.4.3/include/net/ppp-comp.h 2004-11-21 13:54:09.000000000 +0100
-@@ -255,6 +255,33 @@
- opts |= MPPE_OPT_UNKNOWN; \
- } while (/* CONSTCOND */ 0)
-
-+/* MPPE/MPPC definitions by J.D.*/
-+#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
-+#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
-+#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
-+#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
-+#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
-+
-+/*
-+ * Definitions for Stac LZS.
-+ */
-+
-+#define CI_LZS 17 /* config option for Stac LZS */
-+#define CILEN_LZS 5 /* length of config option */
-+
-+#define LZS_OVHD 4 /* max. LZS overhead */
-+#define LZS_HIST_LEN 2048 /* LZS history size */
-+#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
-+
-+#define LZS_MODE_NONE 0
-+#define LZS_MODE_LCB 1
-+#define LZS_MODE_CRC 2
-+#define LZS_MODE_SEQ 3
-+#define LZS_MODE_EXT 4
-+
-+#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
-+#define LZS_EXT_BIT_COMP 0x20 /* bit C */
-+
- /*
- * Definitions for other, as yet unsupported, compression methods.
- */
-diff -ruN ppp-2.4.3.orig/pppd/ccp.c ppp-2.4.3/pppd/ccp.c
---- ppp-2.4.3.orig/pppd/ccp.c 2004-11-13 03:28:15.000000000 +0100
-+++ ppp-2.4.3/pppd/ccp.c 2004-11-21 13:54:09.000000000 +0100
-@@ -62,12 +62,10 @@
- static char bsd_value[8];
- static char deflate_value[8];
-
--/*
-- * Option variables.
-- */
- #ifdef MPPE
--bool refuse_mppe_stateful = 1; /* Allow stateful mode? */
--#endif
-+static int setmppe(char **);
-+static int setnomppe(void);
-+#endif /* MPPE */
-
- static option_t ccp_option_list[] = {
- { "noccp", o_bool, &ccp_protent.enabled_flag,
-@@ -108,54 +106,36 @@
- "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
- &ccp_allowoptions[0].predictor_1 },
-
-+ { "lzs", o_bool, &ccp_wantoptions[0].lzs,
-+ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_PRIO },
-+ { "+lzs", o_bool, &ccp_wantoptions[0].lzs,
-+ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_ALIAS | OPT_PRIO },
-+ { "nolzs", o_bool, &ccp_wantoptions[0].lzs,
-+ "don't allow Stac LZS", OPT_PRIOSUB | OPT_A2CLR,
-+ &ccp_allowoptions[0].lzs },
-+ { "-lzs", o_bool, &ccp_wantoptions[0].lzs,
-+ "don't allow Stac LZS", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
-+ &ccp_allowoptions[0].lzs },
-+
- #ifdef MPPE
-- /* MPPE options are symmetrical ... we only set wantoptions here */
-- { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
-- "require MPPE encryption",
-- OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
-- { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
-- "require MPPE encryption",
-- OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
-- { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
-- "don't allow MPPE encryption", OPT_PRIO },
-- { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
-- "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
--
-- /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
-- { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
-- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
-- &ccp_wantoptions[0].mppe },
-- { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
-- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
-- &ccp_wantoptions[0].mppe },
-- { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
-- "don't allow MPPE 40-bit encryption",
-- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
-- { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
-- "don't allow MPPE 40-bit encryption",
-- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
-- &ccp_wantoptions[0].mppe },
--
-- { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
-- "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
-- &ccp_wantoptions[0].mppe },
-- { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
-- "require MPPE 128-bit encryption",
-- OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
-- &ccp_wantoptions[0].mppe },
-- { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
-- "don't allow MPPE 128-bit encryption",
-- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
-- { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
-- "don't allow MPPE 128-bit encryption",
-- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
-- &ccp_wantoptions[0].mppe },
--
-- /* strange one; we always request stateless, but will we allow stateful? */
-- { "mppe-stateful", o_bool, &refuse_mppe_stateful,
-- "allow MPPE stateful mode", OPT_PRIO },
-- { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
-- "disallow MPPE stateful mode", OPT_PRIO | 1 },
-+ { "mppc", o_bool, &ccp_wantoptions[0].mppc,
-+ "request MPPC compression", 1, &ccp_allowoptions[0].mppc },
-+ { "+mppc", o_bool, &ccp_wantoptions[0].mppc,
-+ "request MPPC compression", 1, &ccp_allowoptions[0].mppc, OPT_ALIAS },
-+ { "nomppc", o_bool, &ccp_wantoptions[0].mppc,
-+ "don't allow MPPC compression", OPT_PRIOSUB | OPT_A2CLR,
-+ &ccp_allowoptions[0].mppc },
-+ { "-mppc", o_bool, &ccp_wantoptions[0].mppc,
-+ "don't allow MPPC compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
-+ &ccp_allowoptions[0].mppc },
-+ { "mppe", o_special, (void *)setmppe,
-+ "request MPPE encryption" },
-+ { "+mppe", o_special, (void *)setmppe,
-+ "request MPPE encryption" },
-+ { "nomppe", o_special_noarg, (void *)setnomppe,
-+ "don't allow MPPE encryption" },
-+ { "-mppe", o_special_noarg, (void *)setnomppe,
-+ "don't allow MPPE encryption" },
- #endif /* MPPE */
-
- { NULL }
-@@ -241,7 +221,7 @@
- */
- #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
- || (opt).predictor_1 || (opt).predictor_2 \
-- || (opt).mppe)
-+ || (opt).lzs || (opt).mppc || (opt).mppe)
-
- /*
- * Local state (mainly for handling reset-reqs and reset-acks).
-@@ -344,6 +324,100 @@
- return 1;
- }
-
-+#ifdef MPPE
-+/*
-+ * Functions called from config options
-+ */
-+/*
-+ MPPE suboptions:
-+ required - require MPPE; disconnect if peer doesn't support it
-+ stateless - use stateless mode
-+ no40 - disable 40 bit keys
-+ no56 - disable 56 bit keys
-+ no128 - disable 128 bit keys
-+*/
-+int setmppe(char **argv)
-+{
-+ int i;
-+ char *str, cmdbuf[16];
-+
-+ ccp_allowoptions[0].mppe = 1;
-+ ccp_allowoptions[0].mppe_40 = 1;
-+ ccp_allowoptions[0].mppe_56 = 1;
-+ ccp_allowoptions[0].mppe_128 = 1;
-+ ccp_allowoptions[0].mppe_stateless = 0;
-+ ccp_wantoptions[0].mppe = 0;
-+
-+ str = *argv;
-+
-+ while (1) {
-+ i = 0;
-+ memset(cmdbuf, '\0', 16);
-+ while ((i < 16) && (*str != ',') && (*str != '\0'))
-+ cmdbuf[i++] = *str++;
-+ cmdbuf[i] = '\0';
-+ if (!strncasecmp(cmdbuf, "no40", strlen("no40"))) {
-+ ccp_allowoptions[0].mppe_40 = 0;
-+ goto next_param;
-+ } else if (!strncasecmp(cmdbuf, "no56", strlen("no56"))) {
-+ ccp_allowoptions[0].mppe_56 = 0;
-+ goto next_param;
-+ } else if (!strncasecmp(cmdbuf, "no128", strlen("no128"))) {
-+ ccp_allowoptions[0].mppe_128 = 0;
-+ goto next_param;
-+ } else if (!strncasecmp(cmdbuf, "stateless", strlen("stateless"))) {
-+ ccp_allowoptions[0].mppe_stateless = 1;
-+ goto next_param;
-+ } else if (!strncasecmp(cmdbuf, "required", strlen("required"))) {
-+ ccp_wantoptions[0].mppe = 1;
-+ goto next_param;
-+ } else {
-+ option_error("invalid parameter '%s' for mppe option", cmdbuf);
-+ return 0;
-+ }
-+
-+ next_param:
-+ if (*str == ',') {
-+ str++;
-+ continue;
-+ }
-+ if (*str == '\0') {
-+ if (!(ccp_allowoptions[0].mppe_40 || ccp_allowoptions[0].mppe_56 ||
-+ ccp_allowoptions[0].mppe_128)) {
-+ if (ccp_wantoptions[0].mppe == 1) {
-+ option_error("You require MPPE but you have switched off "
-+ "all encryption key lengths.");
-+ return 0;
-+ }
-+ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
-+ ccp_wantoptions[0].mppe_stateless =
-+ ccp_allowoptions[0].mppe_stateless = 0;
-+ } else {
-+ ccp_allowoptions[0].mppe = 1;
-+ ccp_wantoptions[0].mppe_stateless =
-+ ccp_allowoptions[0].mppe_stateless;
-+ if (ccp_wantoptions[0].mppe == 1) {
-+ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40;
-+ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56;
-+ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128;
-+ }
-+ }
-+ return 1;
-+ }
-+ }
-+}
-+
-+int setnomppe(void)
-+{
-+ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
-+ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40 = 0;
-+ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56 = 0;
-+ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128 = 0;
-+ ccp_wantoptions[0].mppe_stateless = ccp_allowoptions[0].mppe_stateless = 0;
-+ return 1;
-+}
-+#endif /* MPPE */
-+
- /*
- * ccp_init - initialize CCP.
- */
-@@ -378,6 +452,30 @@
- ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
-
- ccp_allowoptions[0].predictor_1 = 1;
-+
-+ ccp_wantoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
-+ ccp_wantoptions[0].lzs_mode = LZS_MODE_SEQ;
-+ ccp_wantoptions[0].lzs_hists = 1;
-+ ccp_allowoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
-+ ccp_allowoptions[0].lzs_mode = LZS_MODE_SEQ;
-+ ccp_allowoptions[0].lzs_hists = 1;
-+
-+#ifdef MPPE
-+ /* by default allow and request MPPC... */
-+ ccp_wantoptions[0].mppc = ccp_allowoptions[0].mppc = 1;
-+
-+ /* ... and allow but don't request MPPE */
-+ ccp_allowoptions[0].mppe = 1;
-+ ccp_allowoptions[0].mppe_40 = 1;
-+ ccp_allowoptions[0].mppe_56 = 1;
-+ ccp_allowoptions[0].mppe_128 = 1;
-+ ccp_allowoptions[0].mppe_stateless = 1;
-+ ccp_wantoptions[0].mppe = 0;
-+ ccp_wantoptions[0].mppe_40 = 0;
-+ ccp_wantoptions[0].mppe_56 = 0;
-+ ccp_wantoptions[0].mppe_128 = 0;
-+ ccp_wantoptions[0].mppe_stateless = 0;
-+#endif /* MPPE */
- }
-
- /*
-@@ -455,11 +553,11 @@
- if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
- notice("Compression disabled by peer.");
- #ifdef MPPE
-- if (ccp_gotoptions[unit].mppe) {
-+ if (ccp_wantoptions[unit].mppe) {
- error("MPPE disabled, closing LCP");
- lcp_close(unit, "MPPE disabled by peer");
- }
--#endif
-+#endif /* MPPE */
- }
-
- /*
-@@ -487,6 +585,15 @@
- break;
- /* send a reset-ack, which the transmitter will see and
- reset its compression state. */
-+
-+ /* In case of MPPE/MPPC or LZS we shouldn't send CCP_RESETACK,
-+ but we do it in order to reset compressor; CCP_RESETACK is
-+ then silently discarded. See functions ppp_send_frame and
-+ ppp_ccp_peek in ppp_generic.c (Linux only !!!). All the
-+ confusion is caused by the fact that CCP code is splited
-+ into two parts - one part is handled by pppd, the other one
-+ is handled by kernel. */
-+
- fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
- break;
-
-@@ -515,12 +622,11 @@
- fsm_lowerdown(&ccp_fsm[unit]);
-
- #ifdef MPPE
-- if (ccp_gotoptions[unit].mppe) {
-+ if (ccp_wantoptions[unit].mppe) {
- error("MPPE required but peer negotiation failed");
- lcp_close(unit, "MPPE required but peer negotiation failed");
- }
--#endif
--
-+#endif /* MPPE */
- }
-
- /*
-@@ -537,7 +643,7 @@
- all_rejected[f->unit] = 0;
-
- #ifdef MPPE
-- if (go->mppe) {
-+ if (go->mppe || go->mppc) {
- ccp_options *ao = &ccp_allowoptions[f->unit];
- int auth_mschap_bits = auth_done[f->unit];
- int numbits;
-@@ -551,80 +657,109 @@
- * NB: If MPPE is required, all other compression opts are invalid.
- * So, we return right away if we can't do it.
- */
-+ if (ccp_wantoptions[f->unit].mppe) {
-+ /* Leave only the mschap auth bits set */
-+ auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
-+ CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
-+ /* Count the mschap auths */
-+ auth_mschap_bits >>= CHAP_MS_SHIFT;
-+ numbits = 0;
-+ do {
-+ numbits += auth_mschap_bits & 1;
-+ auth_mschap_bits >>= 1;
-+ } while (auth_mschap_bits);
-+ if (numbits > 1) {
-+ error("MPPE required, but auth done in both directions.");
-+ lcp_close(f->unit, "MPPE required but not available");
-+ return;
-+ }
-+ if (!numbits) {
-+ error("MPPE required, but MS-CHAP[v2] auth not performed.");
-+ lcp_close(f->unit, "MPPE required but not available");
-+ return;
-+ }
-
-- /* Leave only the mschap auth bits set */
-- auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
-- CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
-- /* Count the mschap auths */
-- auth_mschap_bits >>= CHAP_MS_SHIFT;
-- numbits = 0;
-- do {
-- numbits += auth_mschap_bits & 1;
-- auth_mschap_bits >>= 1;
-- } while (auth_mschap_bits);
-- if (numbits > 1) {
-- error("MPPE required, but auth done in both directions.");
-- lcp_close(f->unit, "MPPE required but not available");
-- return;
-- }
-- if (!numbits) {
-- error("MPPE required, but MS-CHAP[v2] auth not performed.");
-- lcp_close(f->unit, "MPPE required but not available");
-- return;
-- }
--
-- /* A plugin (eg radius) may not have obtained key material. */
-- if (!mppe_keys_set) {
-- error("MPPE required, but keys are not available. "
-- "Possible plugin problem?");
-- lcp_close(f->unit, "MPPE required but not available");
-- return;
-- }
--
-- /* LM auth not supported for MPPE */
-- if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
-- /* This might be noise */
-- if (go->mppe & MPPE_OPT_40) {
-- notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
-- go->mppe &= ~MPPE_OPT_40;
-- ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40;
-+ /* A plugin (eg radius) may not have obtained key material. */
-+ if (!mppe_keys_set) {
-+ error("MPPE required, but keys are not available. "
-+ "Possible plugin problem?");
-+ lcp_close(f->unit, "MPPE required but not available");
-+ return;
- }
- }
-
-- /* Last check: can we actually negotiate something? */
-- if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
-- /* Could be misconfig, could be 40-bit disabled above. */
-- error("MPPE required, but both 40-bit and 128-bit disabled.");
-- lcp_close(f->unit, "MPPE required but not available");
-- return;
-+ /*
-+ * Check whether the kernel knows about the various
-+ * compression methods we might request. Key material
-+ * unimportant here.
-+ */
-+ if (go->mppc) {
-+ opt_buf[0] = CI_MPPE;
-+ opt_buf[1] = CILEN_MPPE;
-+ opt_buf[2] = 0;
-+ opt_buf[3] = 0;
-+ opt_buf[4] = 0;
-+ opt_buf[5] = MPPE_MPPC;
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 0) <= 0)
-+ go->mppc = 0;
-+ }
-+ if (go->mppe_40) {
-+ opt_buf[0] = CI_MPPE;
-+ opt_buf[1] = CILEN_MPPE;
-+ opt_buf[2] = MPPE_STATELESS;
-+ opt_buf[3] = 0;
-+ opt_buf[4] = 0;
-+ opt_buf[5] = MPPE_40BIT;
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
-+ go->mppe_40 = 0;
-+ }
-+ if (go->mppe_56) {
-+ opt_buf[0] = CI_MPPE;
-+ opt_buf[1] = CILEN_MPPE;
-+ opt_buf[2] = MPPE_STATELESS;
-+ opt_buf[3] = 0;
-+ opt_buf[4] = 0;
-+ opt_buf[5] = MPPE_56BIT;
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
-+ go->mppe_56 = 0;
-+ }
-+ if (go->mppe_128) {
-+ opt_buf[0] = CI_MPPE;
-+ opt_buf[1] = CILEN_MPPE;
-+ opt_buf[2] = MPPE_STATELESS;
-+ opt_buf[3] = 0;
-+ opt_buf[4] = 0;
-+ opt_buf[5] = MPPE_128BIT;
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
-+ go->mppe_128 = 0;
-+ }
-+ if (!go->mppe_40 && !go->mppe_56 && !go->mppe_128) {
-+ if (ccp_wantoptions[f->unit].mppe) {
-+ error("MPPE required, but kernel has no support.");
-+ lcp_close(f->unit, "MPPE required but not available");
-+ }
-+ go->mppe = go->mppe_stateless = 0;
-+ } else {
-+ /* MPPE is not compatible with other compression types */
-+ if (ccp_wantoptions[f->unit].mppe) {
-+ ao->bsd_compress = go->bsd_compress = 0;
-+ ao->predictor_1 = go->predictor_1 = 0;
-+ ao->predictor_2 = go->predictor_2 = 0;
-+ ao->deflate = go->deflate = 0;
-+ ao->lzs = go->lzs = 0;
-+ }
- }
--
-- /* sync options */
-- ao->mppe = go->mppe;
-- /* MPPE is not compatible with other compression types */
-- ao->bsd_compress = go->bsd_compress = 0;
-- ao->predictor_1 = go->predictor_1 = 0;
-- ao->predictor_2 = go->predictor_2 = 0;
-- ao->deflate = go->deflate = 0;
- }
- #endif /* MPPE */
--
-- /*
-- * Check whether the kernel knows about the various
-- * compression methods we might request.
-- */
--#ifdef MPPE
-- if (go->mppe) {
-- opt_buf[0] = CI_MPPE;
-- opt_buf[1] = CILEN_MPPE;
-- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
-- /* Key material unimportant here. */
-- if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) {
-- error("MPPE required, but kernel has no support.");
-- lcp_close(f->unit, "MPPE required but not available");
-- }
-+ if (go->lzs) {
-+ opt_buf[0] = CI_LZS;
-+ opt_buf[1] = CILEN_LZS;
-+ opt_buf[2] = go->lzs_hists >> 8;
-+ opt_buf[3] = go->lzs_hists & 0xff;
-+ opt_buf[4] = LZS_MODE_SEQ;
-+ if (ccp_test(f->unit, opt_buf, CILEN_LZS, 0) <= 0)
-+ go->lzs = 0;
- }
--#endif
- if (go->bsd_compress) {
- opt_buf[0] = CI_BSD_COMPRESS;
- opt_buf[1] = CILEN_BSD_COMPRESS;
-@@ -679,7 +814,8 @@
- + (go->deflate? CILEN_DEFLATE: 0)
- + (go->predictor_1? CILEN_PREDICTOR_1: 0)
- + (go->predictor_2? CILEN_PREDICTOR_2: 0)
-- + (go->mppe? CILEN_MPPE: 0);
-+ + (go->lzs? CILEN_LZS: 0)
-+ + ((go->mppe || go->mppc)? CILEN_MPPE: 0);
- }
-
- /*
-@@ -693,6 +829,8 @@
- {
- int res;
- ccp_options *go = &ccp_gotoptions[f->unit];
-+ ccp_options *ao = &ccp_allowoptions[f->unit];
-+ ccp_options *wo = &ccp_wantoptions[f->unit];
- u_char *p0 = p;
-
- /*
-@@ -701,22 +839,43 @@
- * in case it gets Acked.
- */
- #ifdef MPPE
-- if (go->mppe) {
-+ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
- u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
-
-- p[0] = opt_buf[0] = CI_MPPE;
-- p[1] = opt_buf[1] = CILEN_MPPE;
-- MPPE_OPTS_TO_CI(go->mppe, &p[2]);
-- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
-+ 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_56 ? MPPE_56BIT : 0) |
-+ (go->mppe_128 ? MPPE_128BIT : 0) | (go->mppc ? MPPE_MPPC : 0);
-+
-+ BCOPY(p, opt_buf, CILEN_MPPE);
- BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
- res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
-- if (res > 0)
-+ if (res > 0) {
- p += CILEN_MPPE;
-- else
-+ } else {
- /* This shouldn't happen, we've already tested it! */
-- lcp_close(f->unit, "MPPE required but not available in kernel");
-+ go->mppe = go->mppe_40 = go->mppe_56 = go->mppe_128 =
-+ go->mppe_stateless = go->mppc = 0;
-+ if (ccp_wantoptions[f->unit].mppe)
-+ lcp_close(f->unit, "MPPE required but not available in kernel");
-+ }
-+ }
-+#endif /* MPPE */
-+ if (go->lzs) {
-+ p[0] = CI_LZS;
-+ p[1] = CILEN_LZS;
-+ p[2] = go->lzs_hists >> 8;
-+ p[3] = go->lzs_hists & 0xff;
-+ p[4] = LZS_MODE_SEQ;
-+ res = ccp_test(f->unit, p, CILEN_LZS, 0);
-+ if (res > 0) {
-+ p += CILEN_LZS;
-+ } else
-+ go->lzs = 0;
- }
--#endif
- if (go->deflate) {
- p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
- p[1] = CILEN_DEFLATE;
-@@ -802,7 +961,7 @@
-
- /*
- * ccp_ackci - process a received configure-ack, and return
-- * 1 iff the packet was OK.
-+ * 1 if the packet was OK.
- */
- static int
- ccp_ackci(f, p, len)
-@@ -811,24 +970,44 @@
- int len;
- {
- ccp_options *go = &ccp_gotoptions[f->unit];
-+ ccp_options *ao = &ccp_allowoptions[f->unit];
-+ ccp_options *wo = &ccp_wantoptions[f->unit];
- u_char *p0 = p;
-
- #ifdef MPPE
-- if (go->mppe) {
-- u_char opt_buf[CILEN_MPPE];
--
-- opt_buf[0] = CI_MPPE;
-- opt_buf[1] = CILEN_MPPE;
-- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
-- if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
-+ if (go->mppe || go->mppc || (!wo->mppe && ao->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->mppc ? MPPE_MPPC : 0))
-+ && p[5] != ((go->mppe_56 ? MPPE_56BIT : 0) |
-+ (go->mppc ? MPPE_MPPC : 0))
-+ && p[5] != ((go->mppe_128 ? MPPE_128BIT : 0) |
-+ (go->mppc ? MPPE_MPPC : 0))))
- return 0;
-+ if (go->mppe_40 || go->mppe_56 || go->mppe_128)
-+ go->mppe = 1;
- p += CILEN_MPPE;
- len -= CILEN_MPPE;
-+ /* Cope with first/fast ack */
-+ if (p == p0 && len == 0)
-+ return 1;
-+ }
-+#endif /* MPPE */
-+ if (go->lzs) {
-+ if (len < CILEN_LZS || p[0] != CI_LZS || p[1] != CILEN_LZS
-+ || p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
-+ || p[4] != LZS_MODE_SEQ)
-+ return 0;
-+ p += CILEN_LZS;
-+ len -= CILEN_LZS;
- /* XXX Cope with first/fast ack */
-- if (len == 0)
-+ if (p == p0 && len == 0)
- return 1;
- }
--#endif
- if (go->deflate) {
- if (len < CILEN_DEFLATE
- || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
-@@ -891,7 +1070,7 @@
-
- /*
- * ccp_nakci - process received configure-nak.
-- * Returns 1 iff the nak was OK.
-+ * Returns 1 if the nak was OK.
- */
- static int
- ccp_nakci(f, p, len, treat_as_reject)
-@@ -900,6 +1079,8 @@
- int len;
- {
- ccp_options *go = &ccp_gotoptions[f->unit];
-+ ccp_options *ao = &ccp_allowoptions[f->unit];
-+ ccp_options *wo = &ccp_wantoptions[f->unit];
- ccp_options no; /* options we've seen already */
- ccp_options try; /* options to ask for next time */
-
-@@ -907,28 +1088,100 @@
- try = *go;
-
- #ifdef MPPE
-- if (go->mppe && len >= CILEN_MPPE
-- && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
-- no.mppe = 1;
-- /*
-- * Peer wants us to use a different strength or other setting.
-- * Fail if we aren't willing to use his suggestion.
-- */
-- MPPE_CI_TO_OPTS(&p[2], try.mppe);
-- if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) {
-- error("Refusing MPPE stateful mode offered by peer");
-- try.mppe = 0;
-- } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) {
-- /* Peer must have set options we didn't request (suggest) */
-- try.mppe = 0;
-- }
-+ if ((go->mppe || go->mppc || (!wo->mppe && ao->mppe)) &&
-+ len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
-
-- if (!try.mppe) {
-- error("MPPE required but peer negotiation failed");
-- lcp_close(f->unit, "MPPE required but peer negotiation failed");
-+ if (go->mppc) {
-+ no.mppc = 1;
-+ if (!(p[5] & MPPE_MPPC))
-+ try.mppc = 0;
-+ }
-+
-+ if (go->mppe)
-+ no.mppe = 1;
-+ if (go->mppe_40)
-+ no.mppe_40 = 1;
-+ if (go->mppe_56)
-+ no.mppe_56 = 1;
-+ if (go->mppe_128)
-+ no.mppe_128 = 1;
-+ if (go->mppe_stateless)
-+ no.mppe_stateless = 1;
-+
-+ if (ao->mppe_40) {
-+ if ((p[5] & MPPE_40BIT))
-+ try.mppe_40 = 1;
-+ else
-+ try.mppe_40 = (p[5] == 0) ? 1 : 0;
-+ }
-+ if (ao->mppe_56) {
-+ if ((p[5] & MPPE_56BIT))
-+ try.mppe_56 = 1;
-+ else
-+ try.mppe_56 = (p[5] == 0) ? 1 : 0;
-+ }
-+ if (ao->mppe_128) {
-+ if ((p[5] & MPPE_128BIT))
-+ try.mppe_128 = 1;
-+ else
-+ try.mppe_128 = (p[5] == 0) ? 1 : 0;
-+ }
-+
-+ if (ao->mppe_stateless) {
-+ if ((p[2] & MPPE_STATELESS) || wo->mppe_stateless)
-+ try.mppe_stateless = 1;
-+ else
-+ try.mppe_stateless = 0;
-+ }
-+
-+ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128) {
-+ try.mppe = try.mppe_stateless = 0;
-+ if (wo->mppe) {
-+ /* we require encryption, but peer doesn't support it
-+ so we close connection */
-+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
-+ wo->mppe_56 = wo->mppe_128 = 0;
-+ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
-+ "key length");
-+ }
-+ }
-+ if (wo->mppe && (wo->mppe_40 != try.mppe_40) &&
-+ (wo->mppe_56 != try.mppe_56) && (wo->mppe_128 != try.mppe_128)) {
-+ /* cannot negotiate key length */
-+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
-+ wo->mppe_56 = wo->mppe_128 = 0;
-+ lcp_close(f->unit, "Cannot negotiate MPPE key length");
- }
-+ if (try.mppe_40 && try.mppe_56 && try.mppe_128)
-+ try.mppe_40 = try.mppe_56 = 0;
-+ else
-+ if (try.mppe_56 && try.mppe_128)
-+ try.mppe_56 = 0;
-+ else
-+ if (try.mppe_40 && try.mppe_128)
-+ try.mppe_40 = 0;
-+ else
-+ if (try.mppe_40 && try.mppe_56)
-+ try.mppe_40 = 0;
-+
-+ p += CILEN_MPPE;
-+ len -= CILEN_MPPE;
- }
- #endif /* MPPE */
-+
-+ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
-+ no.lzs = 1;
-+ if (((p[2]<<8)|p[3]) > 1 || (p[4] != LZS_MODE_SEQ &&
-+ p[4] != LZS_MODE_EXT))
-+ try.lzs = 0;
-+ else {
-+ try.lzs_mode = p[4];
-+ try.lzs_hists = (p[2] << 8) | p[3];
-+ }
-+ p += CILEN_LZS;
-+ len -= CILEN_LZS;
-+ }
-+
- if (go->deflate && len >= CILEN_DEFLATE
- && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
- && p[1] == CILEN_DEFLATE) {
-@@ -1001,14 +1254,50 @@
- return -1;
-
- #ifdef MPPE
-- if (go->mppe && len >= CILEN_MPPE
-+ if ((go->mppe || go->mppc) && len >= CILEN_MPPE
- && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
-- error("MPPE required but peer refused");
-- lcp_close(f->unit, "MPPE required but peer refused");
-+ ccp_options *wo = &ccp_wantoptions[f->unit];
-+ if (p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) ||
-+ p[3] != 0 ||
-+ p[4] != 0 ||
-+ p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
-+ (go->mppe_56 ? MPPE_56BIT : 0) |
-+ (go->mppe_128 ? MPPE_128BIT : 0) |
-+ (go->mppc ? MPPE_MPPC : 0)))
-+ return 0;
-+ if (go->mppc)
-+ try.mppc = 0;
-+ if (go->mppe) {
-+ try.mppe = 0;
-+ if (go->mppe_40)
-+ try.mppe_40 = 0;
-+ if (go->mppe_56)
-+ try.mppe_56 = 0;
-+ if (go->mppe_128)
-+ try.mppe_128 = 0;
-+ if (go->mppe_stateless)
-+ try.mppe_stateless = 0;
-+ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128)
-+ try.mppe = try.mppe_stateless = 0;
-+ if (wo->mppe) { /* we want MPPE but cannot negotiate key length */
-+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
-+ wo->mppe_56 = wo->mppe_128 = 0;
-+ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
-+ "key length");
-+ }
-+ }
- p += CILEN_MPPE;
- len -= CILEN_MPPE;
- }
--#endif
-+#endif /* MPPE */
-+ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
-+ if (p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
-+ || p[4] != go->lzs_mode)
-+ return 0;
-+ try.lzs = 0;
-+ p += CILEN_LZS;
-+ len -= CILEN_LZS;
-+ }
- if (go->deflate_correct && len >= CILEN_DEFLATE
- && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
- if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
-@@ -1072,14 +1361,15 @@
- int dont_nak;
- {
- int ret, newret, res;
-- u_char *p0, *retp;
-+ u_char *p0, *retp, p2, p5;
- int len, clen, type, nb;
- ccp_options *ho = &ccp_hisoptions[f->unit];
- ccp_options *ao = &ccp_allowoptions[f->unit];
-+ ccp_options *wo = &ccp_wantoptions[f->unit];
- #ifdef MPPE
-- bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
-- /* CI_MPPE, or due to other options? */
--#endif
-+ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
-+/* int mtu; */
-+#endif /* MPPE */
-
- ret = CONFACK;
- retp = p0 = p;
-@@ -1102,103 +1392,305 @@
- switch (type) {
- #ifdef MPPE
- case CI_MPPE:
-- if (!ao->mppe || clen != CILEN_MPPE) {
-+ if ((!ao->mppc && !ao->mppe) || clen != CILEN_MPPE) {
- newret = CONFREJ;
- break;
- }
-- MPPE_CI_TO_OPTS(&p[2], ho->mppe);
-
-- /* Nak if anything unsupported or unknown are set. */
-- if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
-- newret = CONFNAK;
-- ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
-- }
-- if (ho->mppe & MPPE_OPT_UNKNOWN) {
-+ p2 = p[2];
-+ p5 = p[5];
-+ /* not sure what they want, tell 'em what we got */
-+ if (((p[2] & ~MPPE_STATELESS) != 0 || p[3] != 0 || p[4] != 0 ||
-+ (p[5] & ~(MPPE_40BIT | MPPE_56BIT | MPPE_128BIT |
-+ MPPE_MPPC)) != 0 || p[5] == 0) ||
-+ (p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0)) {
- newret = CONFNAK;
-- ho->mppe &= ~MPPE_OPT_UNKNOWN;
-+ p[2] = (wo->mppe_stateless ? MPPE_STATELESS : 0);
-+ p[3] = 0;
-+ p[4] = 0;
-+ p[5] = (wo->mppe_40 ? MPPE_40BIT : 0) |
-+ (wo->mppe_56 ? MPPE_56BIT : 0) |
-+ (wo->mppe_128 ? MPPE_128BIT : 0) |
-+ (wo->mppc ? MPPE_MPPC : 0);
-+ break;
- }
-
-- /* Check state opt */
-- if (ho->mppe & MPPE_OPT_STATEFUL) {
-- /*
-- * We can Nak and request stateless, but it's a
-- * lot easier to just assume the peer will request
-- * it if he can do it; stateful mode is bad over
-- * the Internet -- which is where we expect MPPE.
-- */
-- if (refuse_mppe_stateful) {
-- error("Refusing MPPE stateful mode offered by peer");
-+ if ((p[5] & MPPE_MPPC)) {
-+ if (ao->mppc) {
-+ ho->mppc = 1;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ opt_buf[2] = opt_buf[3] = opt_buf[4] = 0;
-+ opt_buf[5] = MPPE_MPPC;
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 1) <= 0) {
-+ ho->mppc = 0;
-+ p[5] &= ~MPPE_MPPC;
-+ newret = CONFNAK;
-+ }
-+ } else {
- newret = CONFREJ;
-- break;
-+ if (wo->mppe || ao->mppe) {
-+ p[5] &= ~MPPE_MPPC;
-+ newret = CONFNAK;
-+ }
-+ }
-+ }
-+
-+ if (ao->mppe)
-+ ho->mppe = 1;
-+
-+ if ((p[2] & MPPE_STATELESS)) {
-+ if (ao->mppe_stateless) {
-+ if (wo->mppe_stateless)
-+ ho->mppe_stateless = 1;
-+ else {
-+ newret = CONFNAK;
-+ if (!dont_nak)
-+ p[2] &= ~MPPE_STATELESS;
-+ }
-+ } else {
-+ newret = CONFNAK;
-+ if (!dont_nak)
-+ p[2] &= ~MPPE_STATELESS;
-+ }
-+ } else {
-+ if (wo->mppe_stateless && !dont_nak) {
-+ wo->mppe_stateless = 0;
-+ newret = CONFNAK;
-+ p[2] |= MPPE_STATELESS;
- }
- }
-
-- /* Find out which of {S,L} are set. */
-- if ((ho->mppe & MPPE_OPT_128)
-- && (ho->mppe & MPPE_OPT_40)) {
-- /* Both are set, negotiate the strongest. */
-+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
- newret = CONFNAK;
-- if (ao->mppe & MPPE_OPT_128)
-- ho->mppe &= ~MPPE_OPT_40;
-- else if (ao->mppe & MPPE_OPT_40)
-- ho->mppe &= ~MPPE_OPT_128;
-- else {
-- newret = CONFREJ;
-- break;
-+ if (ao->mppe_128) {
-+ ho->mppe_128 = 1;
-+ p[5] &= ~(MPPE_40BIT|MPPE_56BIT);
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_128 = 0;
-+ p[5] |= (MPPE_40BIT|MPPE_56BIT);
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_56_40;
-+ }
-+ goto check_mppe;
- }
-- } else if (ho->mppe & MPPE_OPT_128) {
-- if (!(ao->mppe & MPPE_OPT_128)) {
-- newret = CONFREJ;
-- break;
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_56_40;
-+ }
-+ if ((p[5] & ~MPPE_MPPC) == (MPPE_56BIT|MPPE_128BIT)) {
-+ newret = CONFNAK;
-+ if (ao->mppe_128) {
-+ ho->mppe_128 = 1;
-+ p[5] &= ~MPPE_56BIT;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_128 = 0;
-+ p[5] |= MPPE_56BIT;
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_56;
-+ }
-+ goto check_mppe;
- }
-- } else if (ho->mppe & MPPE_OPT_40) {
-- if (!(ao->mppe & MPPE_OPT_40)) {
-- newret = CONFREJ;
-- break;
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_56;
-+ }
-+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_128BIT)) {
-+ newret = CONFNAK;
-+ if (ao->mppe_128) {
-+ ho->mppe_128 = 1;
-+ p[5] &= ~MPPE_40BIT;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_128 = 0;
-+ p[5] |= MPPE_40BIT;
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_40;
-+ }
-+ goto check_mppe;
-+ }
-+ p[5] &= ~MPPE_128BIT;
-+ goto check_mppe_40;
-+ }
-+ if ((p[5] & ~MPPE_MPPC) == MPPE_128BIT) {
-+ if (ao->mppe_128) {
-+ ho->mppe_128 = 1;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_128 = 0;
-+ p[5] &= ~MPPE_128BIT;
-+ newret = CONFNAK;
-+ }
-+ goto check_mppe;
-+ }
-+ p[5] &= ~MPPE_128BIT;
-+ newret = CONFNAK;
-+ goto check_mppe;
-+ }
-+ check_mppe_56_40:
-+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT)) {
-+ newret = CONFNAK;
-+ if (ao->mppe_56) {
-+ ho->mppe_56 = 1;
-+ p[5] &= ~MPPE_40BIT;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_56 = 0;
-+ p[5] |= MPPE_40BIT;
-+ p[5] &= ~MPPE_56BIT;
-+ newret = CONFNAK;
-+ goto check_mppe_40;
-+ }
-+ goto check_mppe;
-+ }
-+ p[5] &= ~MPPE_56BIT;
-+ goto check_mppe_40;
-+ }
-+ check_mppe_56:
-+ if ((p[5] & ~MPPE_MPPC) == MPPE_56BIT) {
-+ if (ao->mppe_56) {
-+ ho->mppe_56 = 1;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_56 = 0;
-+ p[5] &= ~MPPE_56BIT;
-+ newret = CONFNAK;
-+ }
-+ goto check_mppe;
-+ }
-+ p[5] &= ~MPPE_56BIT;
-+ newret = CONFNAK;
-+ goto check_mppe;
-+ }
-+ check_mppe_40:
-+ if ((p[5] & ~MPPE_MPPC) == MPPE_40BIT) {
-+ if (ao->mppe_40) {
-+ ho->mppe_40 = 1;
-+ BCOPY(p, opt_buf, CILEN_MPPE);
-+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-+ MPPE_MAX_KEY_LEN);
-+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
-+ MPPE_MAX_KEY_LEN, 1) <= 0) {
-+ ho->mppe_40 = 0;
-+ p[5] &= ~MPPE_40BIT;
-+ newret = CONFNAK;
-+ }
-+ goto check_mppe;
-+ }
-+ p[5] &= ~MPPE_40BIT;
-+ }
-+
-+ check_mppe:
-+ if (!ho->mppe_40 && !ho->mppe_56 && !ho->mppe_128) {
-+ if (wo->mppe_40 || wo->mppe_56 || wo->mppe_128) {
-+ newret = CONFNAK;
-+ p[2] |= (wo->mppe_stateless ? MPPE_STATELESS : 0);
-+ p[5] |= (wo->mppe_40 ? MPPE_40BIT : 0) |
-+ (wo->mppe_56 ? MPPE_56BIT : 0) |
-+ (wo->mppe_128 ? MPPE_128BIT : 0) |
-+ (wo->mppc ? MPPE_MPPC : 0);
-+ } else {
-+ ho->mppe = ho->mppe_stateless = 0;
- }
- } else {
-- /* Neither are set. */
-+ /* MPPE is not compatible with other compression types */
-+ if (wo->mppe) {
-+ ao->bsd_compress = 0;
-+ ao->predictor_1 = 0;
-+ ao->predictor_2 = 0;
-+ ao->deflate = 0;
-+ ao->lzs = 0;
-+ }
-+ }
-+ if ((!ho->mppc || !ao->mppc) && !ho->mppe) {
-+ p[2] = p2;
-+ p[5] = p5;
- newret = CONFREJ;
- break;
- }
-
-- /* rebuild the opts */
-- MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
-- if (newret == CONFACK) {
-- u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
-- int mtu;
--
-- BCOPY(p, opt_buf, CILEN_MPPE);
-- BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-- MPPE_MAX_KEY_LEN);
-- if (ccp_test(f->unit, opt_buf,
-- CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
-- /* This shouldn't happen, we've already tested it! */
-- error("MPPE required, but kernel has no support.");
-- lcp_close(f->unit, "MPPE required but not available");
-- newret = CONFREJ;
-- break;
-- }
-- /*
-- * We need to decrease the interface MTU by MPPE_PAD
-- * because MPPE frames **grow**. The kernel [must]
-- * allocate MPPE_PAD extra bytes in xmit buffers.
-- */
-- mtu = netif_get_mtu(f->unit);
-- if (mtu)
-- netif_set_mtu(f->unit, mtu - MPPE_PAD);
-- else
-- newret = CONFREJ;
-- }
-+ /*
-+ * I have commented the code below because according to RFC1547
-+ * MTU is only information for higher level protocols about
-+ * "the maximum allowable length for a packet (q.v.) transmitted
-+ * over a point-to-point link without incurring network layer
-+ * fragmentation." Of course a PPP implementation should be able
-+ * to handle overhead added by MPPE - in our case apropriate code
-+ * is located in drivers/net/ppp_generic.c in the kernel sources.
-+ *
-+ * According to RFC1661:
-+ * - when negotiated MRU is less than 1500 octets, a PPP
-+ * implementation must still be able to receive at least 1500
-+ * octets,
-+ * - when PFC is negotiated, a PPP implementation is still
-+ * required to receive frames with uncompressed protocol field.
-+ *
-+ * So why not to handle MPPE overhead without changing MTU value?
-+ * I am sure that RFC3078, unfortunately silently, assumes that.
-+ */
-
- /*
-- * We have accepted MPPE or are willing to negotiate
-- * MPPE parameters. A CONFREJ is due to subsequent
-- * (non-MPPE) processing.
-+ * We need to decrease the interface MTU by MPPE_PAD
-+ * because MPPE frames **grow**. The kernel [must]
-+ * allocate MPPE_PAD extra bytes in xmit buffers.
- */
-- rej_for_ci_mppe = 0;
-+/*
-+ mtu = netif_get_mtu(f->unit);
-+ if (mtu) {
-+ netif_set_mtu(f->unit, mtu - MPPE_PAD);
-+ } else {
-+ newret = CONFREJ;
-+ if (ccp_wantoptions[f->unit].mppe) {
-+ error("Cannot adjust MTU needed by MPPE.");
-+ lcp_close(f->unit, "Cannot adjust MTU needed by MPPE.");
-+ }
-+ }
-+*/
- break;
- #endif /* MPPE */
-+
-+ case CI_LZS:
-+ if (!ao->lzs || clen != CILEN_LZS) {
-+ newret = CONFREJ;
-+ break;
-+ }
-+
-+ ho->lzs = 1;
-+ ho->lzs_hists = (p[2] << 8) | p[3];
-+ ho->lzs_mode = p[4];
-+ if ((ho->lzs_hists != ao->lzs_hists) ||
-+ (ho->lzs_mode != ao->lzs_mode)) {
-+ newret = CONFNAK;
-+ if (!dont_nak) {
-+ p[2] = ao->lzs_hists >> 8;
-+ p[3] = ao->lzs_hists & 0xff;
-+ p[4] = ao->lzs_mode;
-+ } else
-+ break;
-+ }
-+
-+ if (p == p0 && ccp_test(f->unit, p, CILEN_LZS, 1) <= 0) {
-+ newret = CONFREJ;
-+ }
-+ break;
-+
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (!ao->deflate || clen != CILEN_DEFLATE
-@@ -1340,12 +1832,6 @@
- else
- *lenp = retp - p0;
- }
--#ifdef MPPE
-- if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
-- error("MPPE required but peer negotiation failed");
-- lcp_close(f->unit, "MPPE required but peer negotiation failed");
-- }
--#endif
- return ret;
- }
-
-@@ -1367,24 +1853,35 @@
- char *p = result;
- char *q = result + sizeof(result); /* 1 past result */
-
-- slprintf(p, q - p, "MPPE ");
-- p += 5;
-- if (opt->mppe & MPPE_OPT_128) {
-- slprintf(p, q - p, "128-bit ");
-- p += 8;
-- }
-- if (opt->mppe & MPPE_OPT_40) {
-- slprintf(p, q - p, "40-bit ");
-- p += 7;
-- }
-- if (opt->mppe & MPPE_OPT_STATEFUL)
-- slprintf(p, q - p, "stateful");
-- else
-- slprintf(p, q - p, "stateless");
--
-+ if (opt->mppe) {
-+ if (opt->mppc) {
-+ slprintf(p, q - p, "MPPC/MPPE ");
-+ p += 10;
-+ } else {
-+ slprintf(p, q - p, "MPPE ");
-+ p += 5;
-+ }
-+ if (opt->mppe_128) {
-+ slprintf(p, q - p, "128-bit ");
-+ p += 8;
-+ } else if (opt->mppe_56) {
-+ slprintf(p, q - p, "56-bit ");
-+ p += 7;
-+ } else if (opt->mppe_40) {
-+ slprintf(p, q - p, "40-bit ");
-+ p += 7;
-+ }
-+ if (opt->mppe_stateless)
-+ slprintf(p, q - p, "stateless");
-+ else
-+ slprintf(p, q - p, "stateful");
-+ } else if (opt->mppc)
-+ slprintf(p, q - p, "MPPC");
- break;
- }
--#endif
-+#endif /* MPPE */
-+ case CI_LZS:
-+ return "Stac LZS";
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
-@@ -1440,12 +1937,12 @@
- } else if (ANY_COMPRESS(*ho))
- notice("%s transmit compression enabled", method_name(ho, NULL));
- #ifdef MPPE
-- if (go->mppe) {
-+ if (go->mppe || go->mppc) {
- BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN);
- BZERO(mppe_send_key, MPPE_MAX_KEY_LEN);
- continue_networks(f->unit); /* Bring up IP et al */
- }
--#endif
-+#endif /* MPPE */
- }
-
- /*
-@@ -1468,7 +1965,7 @@
- lcp_close(f->unit, "MPPE disabled");
- }
- }
--#endif
-+#endif /* MPPE */
- }
-
- /*
-@@ -1528,24 +2025,28 @@
- #ifdef MPPE
- case CI_MPPE:
- if (optlen >= CILEN_MPPE) {
-- u_char mppe_opts;
--
-- MPPE_CI_TO_OPTS(&p[2], mppe_opts);
-- printer(arg, "mppe %s %s %s %s %s %s%s",
-- (p[2] & MPPE_H_BIT)? "+H": "-H",
-- (p[5] & MPPE_M_BIT)? "+M": "-M",
-- (p[5] & MPPE_S_BIT)? "+S": "-S",
-- (p[5] & MPPE_L_BIT)? "+L": "-L",
-+ printer(arg, "mppe %s %s %s %s %s %s",
-+ (p[2] & MPPE_STATELESS)? "+H": "-H",
-+ (p[5] & MPPE_56BIT)? "+M": "-M",
-+ (p[5] & MPPE_128BIT)? "+S": "-S",
-+ (p[5] & MPPE_40BIT)? "+L": "-L",
- (p[5] & MPPE_D_BIT)? "+D": "-D",
-- (p[5] & MPPE_C_BIT)? "+C": "-C",
-- (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
-- if (mppe_opts & MPPE_OPT_UNKNOWN)
-+ (p[5] & MPPE_MPPC)? "+C": "-C");
-+ if ((p[5] & ~(MPPE_56BIT | MPPE_128BIT | MPPE_40BIT |
-+ MPPE_D_BIT | MPPE_MPPC)) ||
-+ (p[2] & ~MPPE_STATELESS))
- printer(arg, " (%.2x %.2x %.2x %.2x)",
- p[2], p[3], p[4], p[5]);
- p += CILEN_MPPE;
- }
- break;
--#endif
-+#endif /* MPPE */
-+ case CI_LZS:
-+ if (optlen >= CILEN_LZS) {
-+ printer(arg, "lzs %.2x %.2x %.2x", p[2], p[3], p[4]);
-+ p += CILEN_LZS;
-+ }
-+ break;
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (optlen >= CILEN_DEFLATE) {
-@@ -1631,6 +2132,7 @@
- error("Lost compression sync: disabling compression");
- ccp_close(unit, "Lost compression sync");
- #ifdef MPPE
-+ /* My module dosn't need this. J.D., 2003-07-06 */
- /*
- * If we were doing MPPE, we must also take the link down.
- */
-@@ -1638,9 +2140,18 @@
- error("Too many MPPE errors, closing LCP");
- lcp_close(unit, "Too many MPPE errors");
- }
--#endif
-+#endif /* MPPE */
- } else {
- /*
-+ * When LZS or MPPE/MPPC is negotiated we just send CCP_RESETREQ
-+ * and don't wait for CCP_RESETACK
-+ */
-+ if ((ccp_gotoptions[f->unit].method == CI_LZS) ||
-+ (ccp_gotoptions[f->unit].method == CI_MPPE)) {
-+ fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
-+ 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.
-@@ -1671,4 +2182,3 @@
- } else
- ccp_localstate[f->unit] &= ~RACK_PENDING;
- }
--
-diff -ruN ppp-2.4.3.orig/pppd/ccp.h ppp-2.4.3/pppd/ccp.h
---- ppp-2.4.3.orig/pppd/ccp.h 2004-11-04 11:02:26.000000000 +0100
-+++ ppp-2.4.3/pppd/ccp.h 2004-11-21 13:54:09.000000000 +0100
-@@ -37,9 +37,17 @@
- bool predictor_2; /* do Predictor-2? */
- bool deflate_correct; /* use correct code for deflate? */
- bool deflate_draft; /* use draft RFC code for deflate? */
-+ bool lzs; /* do Stac LZS? */
-+ bool mppc; /* do MPPC? */
- bool mppe; /* do MPPE? */
-+ bool mppe_40; /* allow 40 bit encryption? */
-+ bool mppe_56; /* allow 56 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 */
-+ u_short lzs_mode; /* LZS check mode */
-+ u_short lzs_hists; /* number of LZS histories */
- short method; /* code for chosen compression method */
- } ccp_options;
-
-diff -ruN ppp-2.4.3.orig/pppd/chap_ms.c ppp-2.4.3/pppd/chap_ms.c
---- ppp-2.4.3.orig/pppd/chap_ms.c 2004-11-12 10:57:43.000000000 +0100
-+++ ppp-2.4.3/pppd/chap_ms.c 2004-11-21 13:54:09.000000000 +0100
-@@ -895,13 +895,17 @@
- /*
- * Disable undesirable encryption types. Note that we don't ENABLE
- * any encryption types, to avoid overriding manual configuration.
-+ *
-+ * It seems that 56 bit keys are unsupported in MS-RADIUS (see RFC 2548)
- */
- switch(types) {
- case MPPE_ENC_TYPES_RC4_40:
-- ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
-+ ccp_wantoptions[0].mppe_128 = 0; /* disable 128-bit */
-+ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
- break;
- case MPPE_ENC_TYPES_RC4_128:
-- ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */
-+ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
-+ ccp_wantoptions[0].mppe_40 = 0; /* disable 40-bit */
- break;
- default:
- break;
-diff -ruN ppp-2.4.3.orig/pppd/pppd.8 ppp-2.4.3/pppd/pppd.8
---- ppp-2.4.3.orig/pppd/pppd.8 2004-11-13 13:22:49.000000000 +0100
-+++ ppp-2.4.3/pppd/pppd.8 2004-11-21 14:24:47.000000000 +0100
-@@ -622,9 +622,29 @@
- Enables the use of PPP multilink; this is an alias for the `multilink'
- option. This option is currently only available under Linux.
- .TP
--.B mppe\-stateful
--Allow MPPE to use stateful mode. Stateless mode is still attempted first.
--The default is to disallow stateful mode.
-+.B mppc
-+Enables MPPC (Microsoft Point to Point Compression). This is the default.
-+.TP
-+.B mppe \fIsubopt1[,subopt2[,subopt3[..]]]
-+Modify MPPE (Microsoft Point to Point Encryption) parameters. In order
-+for MPPE to successfully come up, you must have authenticated with either
-+MS-CHAP or MS-CHAPv2. By default MPPE is optional, it means that pppd will
-+not propose MPPE to the peer, but will negotiate MPPE if peer wants that.
-+You can change this using \fIrequired\fR suboption.
-+This option is presently only supported under Linux, and only if your
-+kernel has been configured to include MPPE support.
-+.IP
-+MPPE suboptions:
-+.br
-+\fIrequired\fR - require MPPE; disconnect if peer doesn't support it,
-+.br
-+\fIstateless\fR - try to negotiate stateless mode; default is stateful,
-+.br
-+\fIno40\fR - disable 40 bit keys,
-+.br
-+\fIno56\fR - disable 56 bit keys,
-+.br
-+\fIno128\fR - disable 128 bit keys
- .TP
- .B mpshortseq
- Enables the use of short (12-bit) sequence numbers in multilink
-@@ -757,17 +777,11 @@
- Disables the use of PPP multilink. This option is currently only
- available under Linux.
- .TP
--.B nomppe
--Disables MPPE (Microsoft Point to Point Encryption). This is the default.
--.TP
--.B nomppe\-40
--Disable 40-bit encryption with MPPE.
-+.B nomppc
-+Disables MPPC (Microsoft Point to Point Compression).
- .TP
--.B nomppe\-128
--Disable 128-bit encryption with MPPE.
--.TP
--.B nomppe\-stateful
--Disable MPPE stateful mode. This is the default.
-+.B nomppe
-+Disables MPPE (Microsoft Point to Point Encryption).
- .TP
- .B nompshortseq
- Disables the use of short (12-bit) sequence numbers in the PPP
-@@ -948,19 +962,6 @@
- Require the peer to authenticate itself using CHAP [Challenge
- Handshake Authentication Protocol] authentication.
- .TP
--.B require\-mppe
--Require the use of MPPE (Microsoft Point to Point Encryption). This
--option disables all other compression types. This option enables
--both 40-bit and 128-bit encryption. In order for MPPE to successfully
--come up, you must have authenticated with either MS\-CHAP or MS\-CHAPv2.
--This option is presently only supported under Linux, and only if your
--kernel has been configured to include MPPE support.
--.TP
--.B require\-mppe\-40
--Require the use of MPPE, with 40-bit encryption.
--.TP
--.B require\-mppe\-128
--Require the use of MPPE, with 128-bit encryption.
- .TP
- .B require\-mschap
- Require the peer to authenticate itself using MS\-CHAP [Microsoft Challenge
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/pppd/plugins/Makefile.linux ppp-2.4.3-3/pppd/plugins/Makefile.linux
---- ppp-2.4.3-orig/pppd/plugins/Makefile.linux 2004-11-14 08:57:35.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/Makefile.linux 2004-12-05 17:03:59.000000000 +0100
-@@ -9,7 +9,7 @@
- MANDIR = $(DESTDIR)/share/man/man8
- LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
-
--SUBDIRS := rp-pppoe pppoatm radius
-+SUBDIRS := rp-pppoe radius
- # Uncomment the next line to include the radius authentication plugin
- # SUBDIRS += radius
- PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/chat/Makefile.linux ppp-2.4.3-3/chat/Makefile.linux
---- ppp-2.4.3-orig/chat/Makefile.linux 2004-11-03 12:51:47.000000000 +0100
-+++ ppp-2.4.3-3/chat/Makefile.linux 2004-12-05 17:42:43.000000000 +0100
-@@ -25,7 +25,7 @@
-
- install: chat
- mkdir -p $(BINDIR)
-- $(INSTALL) -s -c chat $(BINDIR)
-+ $(INSTALL) -c chat $(BINDIR)
- $(INSTALL) -c -m 644 chat.8 $(MANDIR)
-
- clean:
-diff -ruN ppp-2.4.3-orig/pppd/Makefile.linux ppp-2.4.3-3/pppd/Makefile.linux
---- ppp-2.4.3-orig/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100
-+++ ppp-2.4.3-3/pppd/Makefile.linux 2004-12-16 04:43:41.000000000 +0100
-@@ -99,7 +99,7 @@
- CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include
- LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto
- TARGETS += srp-entry
--EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
-+EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry
- MANPAGES += srp-entry.8
- EXTRACLEAN += srp-entry.o
- NEEDDES=y
-@@ -202,7 +202,7 @@
- install: pppd
- mkdir -p $(BINDIR) $(MANDIR)
- $(EXTRAINSTALL)
-- $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
-+ $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd
- if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
- chmod o-rx,u+s $(BINDIR)/pppd; fi
- $(INSTALL) -c -m 444 pppd.8 $(MANDIR)
-diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
---- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
-@@ -36,9 +37,9 @@
-
- install: all
- $(INSTALL) -d -m 755 $(LIBDIR)
-- $(INSTALL) -s -c -m 755 radius.so $(LIBDIR)
-- $(INSTALL) -s -c -m 755 radattr.so $(LIBDIR)
-- $(INSTALL) -s -c -m 755 radrealms.so $(LIBDIR)
-+ $(INSTALL) -c -m 755 radius.so $(LIBDIR)
-+ $(INSTALL) -c -m 755 radattr.so $(LIBDIR)
-+ $(INSTALL) -c -m 755 radrealms.so $(LIBDIR)
- $(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR)
- $(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR)
-
-diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux
---- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/Makefile.linux 2004-11-14 08:58:37.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/Makefile.linux 2004-12-05 17:43:23.000000000 +0100
-@@ -39,9 +39,9 @@
-
- install: all
- $(INSTALL) -d -m 755 $(LIBDIR)
-- $(INSTALL) -s -c -m 4550 rp-pppoe.so $(LIBDIR)
-+ $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR)
- $(INSTALL) -d -m 755 $(BINDIR)
-- $(INSTALL) -s -c -m 555 pppoe-discovery $(BINDIR)
-+ $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
-
- clean:
- rm -f *.o *.so
-diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
---- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
-+++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
-@@ -17,5 +18,5 @@
-
- install:
- mkdir -p $(BINDIR) $(MANDIR)
-- $(INSTALL) -s -c pppdump $(BINDIR)
-+ $(INSTALL) -c pppdump $(BINDIR)
- $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
-diff -ruN ppp-2.4.3-orig/pppstats/Makefile.linux ppp-2.4.3-3/pppstats/Makefile.linux
---- ppp-2.4.3-orig/pppstats/Makefile.linux 2004-10-31 23:09:03.000000000 +0100
-+++ ppp-2.4.3-3/pppstats/Makefile.linux 2004-12-05 17:43:38.000000000 +0100
-@@ -22,7 +22,7 @@
-
- install: pppstats
- -mkdir -p $(MANDIR)
-- $(INSTALL) -s -c pppstats $(BINDIR)
-+ $(INSTALL) -c pppstats $(BINDIR)
- $(INSTALL) -c -m 444 pppstats.8 $(MANDIR)
-
- pppstats: $(PPPSTATSRCS)
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux
---- ppp-2.4.3-orig/pppd/plugins/radius/Makefile.linux 2004-11-14 08:02:31.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/radius/Makefile.linux 2004-12-05 17:43:17.000000000 +0100
-@@ -12,7 +12,8 @@
- INSTALL = install
-
- PLUGIN=radius.so radattr.so radrealms.so
--CFLAGS=-I. -I../.. -I../../../include -O2 -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
-+COPTS = -O2
-+CFLAGS=-I. -I../.. -I../../../include $(COPTS) -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
-
- # Uncomment the next line to include support for Microsoft's
- # MS-CHAP authentication protocol.
-diff -ruN ppp-2.4.3-orig/pppdump/Makefile.linux ppp-2.4.3-3/pppdump/Makefile.linux
---- ppp-2.4.3-orig/pppdump/Makefile.linux 2004-10-31 02:36:52.000000000 +0200
-+++ ppp-2.4.3-3/pppdump/Makefile.linux 2004-12-05 17:50:34.000000000 +0100
-@@ -2,7 +2,8 @@
- BINDIR = $(DESTDIR)/sbin
- MANDIR = $(DESTDIR)/share/man/man8
-
--CFLAGS= -O -I../include/net
-+COPTS = -O
-+CFLAGS= $(COPTS) -I../include/net
- OBJS = pppdump.o bsd-comp.o deflate.o zlib.o
-
- INSTALL= install
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c
---- ppp-2.4.3-orig/pppd/plugins/rp-pppoe/plugin.c 2004-11-04 11:07:37.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/rp-pppoe/plugin.c 2004-12-16 01:07:22.000000000 +0100
-@@ -286,7 +286,7 @@
- /* Strip off "nic-" */
- cmd += 4;
- } else if (strlen(cmd) < 4
-- || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3)
-+ || (strncmp(cmd, "eth", 3) && strncmp(cmd, "nas", 3) && strncmp(cmd, "vlan", 4)
- && strncmp(cmd, "tap", 3) && strncmp(cmd, "br", 2))) {
- return 0;
- }
+++ /dev/null
-diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/config.c ppp-2.4.3-3/pppd/plugins/radius/config.c
---- ppp-2.4.3-orig/pppd/plugins/radius/config.c 2004-11-14 08:26:26.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/radius/config.c 2004-12-16 04:03:46.000000000 +0100
-@@ -369,31 +369,37 @@
- }
- #endif
-
-+#if 0
- if (rc_conf_int("login_tries") <= 0)
- {
- error("%s: login_tries <= 0 is illegal", filename);
- return (-1);
- }
-+#endif
- if (rc_conf_str("seqfile") == NULL)
- {
- error("%s: seqfile not specified", filename);
- return (-1);
- }
-+#if 0
- if (rc_conf_int("login_timeout") <= 0)
- {
- error("%s: login_timeout <= 0 is illegal", filename);
- return (-1);
- }
-+#endif
- if (rc_conf_str("mapfile") == NULL)
- {
- error("%s: mapfile not specified", filename);
- return (-1);
- }
-+#if 0
- if (rc_conf_str("nologin") == NULL)
- {
- error("%s: nologin not specified", filename);
- return (-1);
- }
-+#endif
-
- return 0;
- }
-diff -ruN ppp-2.4.3-orig/pppd/plugins/radius/options.h ppp-2.4.3-3/pppd/plugins/radius/options.h
---- ppp-2.4.3-orig/pppd/plugins/radius/options.h 2004-11-14 08:26:26.000000000 +0100
-+++ ppp-2.4.3-3/pppd/plugins/radius/options.h 2004-12-16 04:09:16.000000000 +0100
-@@ -31,24 +31,21 @@
- static SERVER acctserver = {0};
- static SERVER authserver = {0};
-
--int default_tries = 4;
--int default_timeout = 60;
--
- static OPTION config_options[] = {
- /* internally used options */
- {"config_file", OT_STR, ST_UNDEF, NULL},
- /* General options */
- {"auth_order", OT_AUO, ST_UNDEF, NULL},
--{"login_tries", OT_INT, ST_UNDEF, &default_tries},
--{"login_timeout", OT_INT, ST_UNDEF, &default_timeout},
--{"nologin", OT_STR, ST_UNDEF, "/etc/nologin"},
--{"issue", OT_STR, ST_UNDEF, "/etc/radiusclient/issue"},
-+{"login_tries", OT_INT, ST_UNDEF, NULL},
-+{"login_timeout", OT_INT, ST_UNDEF, NULL},
-+{"nologin", OT_STR, ST_UNDEF, NULL},
-+{"issue", OT_STR, ST_UNDEF, NULL},
- /* RADIUS specific options */
- {"authserver", OT_SRV, ST_UNDEF, &authserver},
- {"acctserver", OT_SRV, ST_UNDEF, &acctserver},
- {"servers", OT_STR, ST_UNDEF, NULL},
- {"dictionary", OT_STR, ST_UNDEF, NULL},
--{"login_radius", OT_STR, ST_UNDEF, "/usr/sbin/login.radius"},
-+{"login_radius", OT_STR, ST_UNDEF, NULL},
- {"seqfile", OT_STR, ST_UNDEF, NULL},
- {"mapfile", OT_STR, ST_UNDEF, NULL},
- {"default_realm", OT_STR, ST_UNDEF, NULL},