summaryrefslogtreecommitdiff
path: root/package/ppp/patches
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-10 12:32:29 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-10 12:32:29 +0000
commit9c8997d54dc9df184bfcedeabf0b3c85cf5e6753 (patch)
tree46b83031a0da1b4458317413c00d13c252c72afa /package/ppp/patches
parenteecf5b17520f6b3b6ffb45ac7dca298d93b27501 (diff)
packages: sort network related packages into package/network/
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33688 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/ppp/patches')
-rw-r--r--package/ppp/patches/010-use_target_for_configure.patch24
-rw-r--r--package/ppp/patches/100-debian_ip-ip_option.patch96
-rw-r--r--package/ppp/patches/101-debian_close_dev_ppp.patch28
-rw-r--r--package/ppp/patches/103-debian_fix_link_pidfile.patch23
-rw-r--r--package/ppp/patches/105-debian_demand.patch172
-rw-r--r--package/ppp/patches/106-debian_stripMSdomain.patch47
-rw-r--r--package/ppp/patches/107-debian_pppoatm_wildcard.patch25
-rw-r--r--package/ppp/patches/110-debian_defaultroute.patch313
-rw-r--r--package/ppp/patches/120-debian_ipv6_updown_option.patch95
-rw-r--r--package/ppp/patches/200-makefile.patch55
-rw-r--r--package/ppp/patches/201-mppe_mppc_1.1.patch1495
-rw-r--r--package/ppp/patches/202-no_strip.patch88
-rw-r--r--package/ppp/patches/203-opt_flags.patch32
-rw-r--r--package/ppp/patches/204-radius_config.patch72
-rw-r--r--package/ppp/patches/205-no_exponential_timeout.patch29
-rw-r--r--package/ppp/patches/206-compensate_time_change.patch94
-rw-r--r--package/ppp/patches/207-lcp_mtu_max.patch25
-rw-r--r--package/ppp/patches/208-fix_status_code.patch24
-rw-r--r--package/ppp/patches/300-filter-pcap-includes-lib.patch20
-rw-r--r--package/ppp/patches/310-precompile_filter.patch196
-rw-r--r--package/ppp/patches/320-custom_iface_names.patch135
-rw-r--r--package/ppp/patches/330-retain_foreign_default_routes.patch22
-rw-r--r--package/ppp/patches/340-populate_default_gateway.patch34
-rw-r--r--package/ppp/patches/400-simplify_kernel_checks.patch154
-rw-r--r--package/ppp/patches/401-no_record_file.patch39
-rw-r--r--package/ppp/patches/403-no_wtmp.patch25
-rw-r--r--package/ppp/patches/404-remove_obsolete_protocol_names.patch151
-rw-r--r--package/ppp/patches/405-no_multilink_option.patch28
-rw-r--r--package/ppp/patches/430-pppol2tpv3-struct.patch30
-rw-r--r--package/ppp/patches/500-add-pptp-plugin.patch3065
30 files changed, 0 insertions, 6636 deletions
diff --git a/package/ppp/patches/010-use_target_for_configure.patch b/package/ppp/patches/010-use_target_for_configure.patch
deleted file mode 100644
index aff0df67f8..0000000000
--- a/package/ppp/patches/010-use_target_for_configure.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-configure: Allow overriding uname results
-
-In a cross compile setting it makes no sense to rely on the "uname" values
-reported by the build host system. This patch allows overriding the
-"uname -r", "uname -s" and "uname -m" results with the "UNAME_R", "UNAME_S"
-and "UNAME_M" environment variables.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/configure
-+++ b/configure
-@@ -8,9 +8,9 @@ SYSCONF=/etc
- # if [ -d /NextApps ]; then
- # system="NeXTStep"
- # else
-- system=`uname -s`
-- release=`uname -r`
-- arch=`uname -m`
-+ system=${UNAME_S:-`uname -s`}
-+ release=${UNAME_R:-`uname -r`}
-+ arch=${UNAME_M:-`uname -m`}
- # fi
- state="unknown"
-
diff --git a/package/ppp/patches/100-debian_ip-ip_option.patch b/package/ppp/patches/100-debian_ip-ip_option.patch
deleted file mode 100644
index ca43cb2780..0000000000
--- a/package/ppp/patches/100-debian_ip-ip_option.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-pppd: Allow specifying ip-up and ip-down scripts
-
-This patch implements the "ip-up-script" and "ip-down-script" options which
-allow to specify the path of the ip-up and ip-down scripts to call.
-
-These options default to _PATH_IPUP and _PATH_IPDOWN to retain the
-existing behaviour.
-
-The patch originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/ipcp.c
-+++ b/pppd/ipcp.c
-@@ -1939,7 +1939,7 @@ ipcp_up(f)
- */
- if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
- ipcp_script_state = s_up;
-- ipcp_script(_PATH_IPUP, 0);
-+ ipcp_script(path_ipup, 0);
- }
- }
-
-@@ -1989,7 +1989,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, 0);
-+ ipcp_script(path_ipdown, 0);
- }
- }
-
-@@ -2043,13 +2043,13 @@ ipcp_script_done(arg)
- case s_up:
- if (ipcp_fsm[0].state != OPENED) {
- ipcp_script_state = s_down;
-- ipcp_script(_PATH_IPDOWN, 0);
-+ ipcp_script(path_ipdown, 0);
- }
- break;
- case s_down:
- if (ipcp_fsm[0].state == OPENED) {
- ipcp_script_state = s_up;
-- ipcp_script(_PATH_IPUP, 0);
-+ ipcp_script(path_ipup, 0);
- }
- break;
- }
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -316,6 +316,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);
-
---- a/pppd/options.c
-+++ b/pppd/options.c
-@@ -113,6 +113,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 */
-@@ -281,6 +283,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 },
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -313,6 +313,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 */
diff --git a/package/ppp/patches/101-debian_close_dev_ppp.patch b/package/ppp/patches/101-debian_close_dev_ppp.patch
deleted file mode 100644
index 232b10b521..0000000000
--- a/package/ppp/patches/101-debian_close_dev_ppp.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-pppd: Close already open ppp descriptors
-
-When using the kernel PPPoE driver in conjunction with the "persist" option,
-the already open descriptor to /dev/ppp is not closed when the link is
-reestablished. This eventually leads to high CPU load because the stray
-descriptors are always reported as ready by select().
-
-This patch closes the descriptor if it is already open when establishing a
-new connection. It originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -453,6 +453,13 @@ int generic_establish_ppp (int fd)
- 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");
diff --git a/package/ppp/patches/103-debian_fix_link_pidfile.patch b/package/ppp/patches/103-debian_fix_link_pidfile.patch
deleted file mode 100644
index c8a23edd6a..0000000000
--- a/package/ppp/patches/103-debian_fix_link_pidfile.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-pppd: Fix creation of linkpidfile
-
-When pppd is run without "nodetach" or with "updetach", the linkpidfile is
-never created. The call to create_linkpidfile() is protected by a check for
-linkpidfile[0] but this is only filled in when create_linkpidfile() is called.
-
-This patch changes to code to allways uncondiationally call
-create_linkpidfile(), it originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -773,8 +773,7 @@ detach()
- /* 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();
diff --git a/package/ppp/patches/105-debian_demand.patch b/package/ppp/patches/105-debian_demand.patch
deleted file mode 100644
index c278656987..0000000000
--- a/package/ppp/patches/105-debian_demand.patch
+++ /dev/null
@@ -1,172 +0,0 @@
---- a/pppd/demand.c
-+++ b/pppd/demand.c
-@@ -36,6 +36,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>
-@@ -43,6 +45,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 <pcap-bpf.h>
- #endif
-@@ -221,6 +225,14 @@ loop_chars(p, n)
- 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) {
-@@ -299,17 +311,102 @@ loop_frame(frame, len)
- * 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 {
---- a/pppd/ipcp.c
-+++ b/pppd/ipcp.c
-@@ -1864,7 +1864,7 @@ ipcp_up(f)
- proxy_arp_set[f->unit] = 1;
-
- }
-- demand_rexmit(PPP_IP);
-+ demand_rexmit(PPP_IP,go->ouraddr);
- sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
-
- } else {
---- a/pppd/ipv6cp.c
-+++ b/pppd/ipv6cp.c
-@@ -1232,7 +1232,7 @@ ipv6cp_up(f)
- }
-
- }
-- demand_rexmit(PPP_IPV6);
-+ demand_rexmit(PPP_IPV6,0);
- sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
-
- } else {
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -566,7 +566,7 @@ void demand_conf __P((void)); /* config
- 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? */
-
diff --git a/package/ppp/patches/106-debian_stripMSdomain.patch b/package/ppp/patches/106-debian_stripMSdomain.patch
deleted file mode 100644
index 86af1ef412..0000000000
--- a/package/ppp/patches/106-debian_stripMSdomain.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-pppd: Implement option to strip domain part from MS CHAP response
-
-This patch implements a new boolean option "chapms-strip-domain" which
-strips the leading domain part of the username in a received MS Chap
-response.
-
-When the option is set, all leading chars up to and including the last
-backslash in the username are stripped. The option defaults to false.
-
-The patch originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/chap-new.c
-+++ b/pppd/chap-new.c
-@@ -58,6 +58,7 @@ int (*chap_verify_hook)(char *name, char
- int chap_timeout_time = 3;
- int chap_max_transmits = 10;
- int chap_rechallenge_time = 0;
-+int chapms_strip_domain = 0;
-
- /*
- * Command-line options.
-@@ -69,6 +70,8 @@ static option_t chap_option_list[] = {
- "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 }
- };
-
-@@ -336,6 +339,14 @@ chap_handle_response(struct chap_server_
- /* 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)
diff --git a/package/ppp/patches/107-debian_pppoatm_wildcard.patch b/package/ppp/patches/107-debian_pppoatm_wildcard.patch
deleted file mode 100644
index eaad2cdaae..0000000000
--- a/package/ppp/patches/107-debian_pppoatm_wildcard.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-pppoatm: Allow wildcard ATM devices
-
-When operating pppd's pppoatm plugin with an USB ADSL modem, e.g. an
-Alcatel Speedtouch, the ATM device number might change when the modem is
-reconnected to the USB port or when the host controller resets the USB
-device.
-
-This patch allows to specify the ATM device as wildcard which gives
-enough flexibility to cope with changing device names.
-
-The patch originated from the Debain project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/plugins/pppoatm/pppoatm.c
-+++ b/pppd/plugins/pppoatm/pppoatm.c
-@@ -75,7 +75,7 @@ static int setdevname_pppoatm(const char
- //info("PPPoATM setdevname_pppoatm: '%s'", cp);
- memset(&addr, 0, sizeof addr);
- if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
-- T2A_PVC | T2A_NAME) < 0) {
-+ T2A_PVC | T2A_NAME | T2A_WILDCARD) < 0) {
- if(doit)
- info("atm does not recognize: %s", cp);
- return 0;
diff --git a/package/ppp/patches/110-debian_defaultroute.patch b/package/ppp/patches/110-debian_defaultroute.patch
deleted file mode 100644
index 41d28909be..0000000000
--- a/package/ppp/patches/110-debian_defaultroute.patch
+++ /dev/null
@@ -1,313 +0,0 @@
-pppd: Add "replacedefaultroute" and "noreplacedefaultroute" options
-
-This patch implements two new options, "replacedefaultroute" to replace any
-existing system default route when specified and "noreplacedefaultroute" to
-disable the "replacedefaultroute" option, which is useful in multi user
-environments where the administrator wants to allow users to dial pppd
-connections but not allow them to change the system default route.
-
-The patch originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/ipcp.c
-+++ b/pppd/ipcp.c
-@@ -198,6 +198,14 @@ static option_t ipcp_option_list[] = {
- "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
- &ipcp_wantoptions[0].default_route },
-
-+ { "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 },
- { "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,
-@@ -271,7 +279,7 @@ struct protent ipcp_protent = {
- 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 *, int)); /* Run an up/down script */
- static void ipcp_script_done __P((void *));
-
-@@ -1742,7 +1750,8 @@ ip_demand_conf(u)
- if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
- return 0;
- if (wo->default_route)
-- if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
-+ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
-+ wo->replace_default_route))
- default_route_set[u] = 1;
- if (wo->proxy_arp)
- if (sifproxyarp(u, wo->hisaddr))
-@@ -1830,7 +1839,8 @@ ipcp_up(f)
- */
- 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), 0);
-@@ -1855,7 +1865,8 @@ ipcp_up(f)
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
-- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
-+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
-+ wo->replace_default_route))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
-@@ -1905,7 +1916,8 @@ ipcp_up(f)
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
-- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
-+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
-+ wo->replace_default_route))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
-@@ -1983,7 +1995,7 @@ ipcp_down(f)
- 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 */
-@@ -1999,16 +2011,25 @@ ipcp_down(f)
- * 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;
- }
---- a/pppd/ipcp.h
-+++ b/pppd/ipcp.h
-@@ -70,6 +70,7 @@ typedef struct ipcp_options {
- 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? */
---- a/pppd/pppd.8
-+++ b/pppd/pppd.8
-@@ -121,6 +121,11 @@ the gateway, when IPCP negotiation is su
- This entry is removed when the PPP connection is broken. This option
- is privileged if the \fInodefaultroute\fR option has been specified.
- .TP
-+.B replacedefaultroute
-+This option is a flag to the defaultroute option. If defaultroute is
-+set and this flag is also set, pppd replaces an existing default route
-+with the new default route.
-+.TP
- .B disconnect \fIscript
- Execute the command specified by \fIscript\fR, by passing it to a
- shell, after
-@@ -717,7 +722,12 @@ disable both forms of hardware flow cont
- .TP
- .B nodefaultroute
- Disable the \fIdefaultroute\fR option. The system administrator who
--wishes to prevent users from creating default routes with pppd
-+wishes to prevent users from adding a default route with pppd
-+can do so by placing this option in the /etc/ppp/options file.
-+.TP
-+.B noreplacedefaultroute
-+Disable the \fIreplacedefaultroute\fR option. The system administrator who
-+wishes to prevent users from replacing a default route with pppd
- can do so by placing this option in the /etc/ppp/options file.
- .TP
- .B nodeflate
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -645,7 +645,7 @@ int sif6addr __P((int, eui64_t, eui64_t
- int cif6addr __P((int, eui64_t, eui64_t));
- /* Remove an IPv6 address from i/f */
- #endif
--int sifdefaultroute __P((int, u_int32_t, u_int32_t));
-+int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
- /* Create default route through i/f */
- int cifdefaultroute __P((int, u_int32_t, u_int32_t));
- /* Delete default route through i/f */
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -206,6 +206,8 @@ static unsigned char inbuf[512]; /* buff
-
- static int if_is_up; /* Interface has been marked up */
- static int have_default_route; /* 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 */
-@@ -1544,6 +1546,9 @@ static int read_route_table(struct rtent
- 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);
-@@ -1613,20 +1618,51 @@ int have_route_to(u_int32_t addr)
- /********************************************************************
- *
- * sifdefaultroute - assign a default route through the address given.
-- */
--
--int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
--{
-- struct rtentry rt;
--
-- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
-- if (rt.rt_flags & RTF_GATEWAY)
-- error("not replacing existing default route via %I",
-- SIN_ADDR(rt.rt_gateway));
-- else
-+ *
-+ * 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, bool replace)
-+{
-+ struct rtentry rt, tmp_rt;
-+ struct rtentry *del_rt = NULL;
-+
-+ 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: */
-+ if (old_def_rt.rt_flags & RTF_GATEWAY) {
-+ if (!replace) {
-+ error("not replacing existing default route via %I",
-+ SIN_ADDR(old_def_rt.rt_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, SIN_ADDR(old_def_rt.rt_gateway));
-+ default_rt_repl_rest = 1;
-+ del_rt = &old_def_rt;
-+ }
-+ } else
- error("not replacing existing default route through %s",
-- rt.rt_dev);
-- return 0;
-+ old_def_rt.rt_dev);
- }
-
- memset (&rt, 0, sizeof (rt));
-@@ -1641,10 +1677,16 @@ int sifdefaultroute (int unit, u_int32_t
-
- rt.rt_flags = RTF_UP;
- if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
-- if ( ! ok_error ( errno ))
-+ if (!ok_error(errno))
- error("default route ioctl(SIOCADDRT): %m");
- 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");
-+ return 0;
-+ }
-
- have_default_route = 1;
- return 1;
-@@ -1675,11 +1717,21 @@ int cifdefaultroute (int unit, u_int32_t
- rt.rt_flags = RTF_UP;
- if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
- if (still_ppp()) {
-- if ( ! ok_error ( errno ))
-+ if (!ok_error(errno))
- error("default route ioctl(SIOCDELRT): %m");
- 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");
-+ return 0;
-+ }
-+ default_rt_repl_rest = 0;
-+ }
-
- return 1;
- }
---- a/pppd/sys-solaris.c
-+++ b/pppd/sys-solaris.c
-@@ -2036,12 +2036,18 @@ cifaddr(u, o, h)
- * sifdefaultroute - assign a default route through the address given.
- */
- int
--sifdefaultroute(u, l, g)
-+sifdefaultroute(u, l, g, replace)
- int u;
- u_int32_t l, g;
-+ bool replace;
- {
- struct rtentry rt;
-
-+ if (replace) {
-+ error("replacedefaultroute not supported on this platform");
-+ return 0;
-+ }
-+
- #if defined(__USLC__)
- g = l; /* use the local address as gateway */
- #endif
diff --git a/package/ppp/patches/120-debian_ipv6_updown_option.patch b/package/ppp/patches/120-debian_ipv6_updown_option.patch
deleted file mode 100644
index c5457fa515..0000000000
--- a/package/ppp/patches/120-debian_ipv6_updown_option.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-pppd: Allow specifying ipv6-up and ipv6-down scripts
-
-This patch implements the "ipv6-up-script" and "ipv6-down-script" options
-which allow to specify the path of the ipv6-up and ipv6-down scripts to call.
-
-These options default to _PATH_IPV6UP and _PATH_IPV6DOWN to retain the
-existing behaviour.
-
-The patch originated from the Debian project.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -318,6 +318,8 @@ main(argc, argv)
-
- strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
- strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
-+ strlcpy(path_ipv6up, _PATH_IPV6UP, sizeof(path_ipv6up));
-+ strlcpy(path_ipv6down, _PATH_IPV6DOWN, sizeof(path_ipv6down));
-
- link_stats_valid = 0;
- new_phase(PHASE_INITIALIZE);
---- a/pppd/options.c
-+++ b/pppd/options.c
-@@ -115,6 +115,8 @@ int connect_delay = 1000; /* wait this m
- 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 */
-+char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */
-+char path_ipv6down[MAXPATHLEN];/* pathname of ipv6-down script */
- bool multilink = 0; /* Enable multilink operation */
- char *bundle_name = NULL; /* bundle name for multilink */
- bool dump_options; /* print out option values */
-@@ -290,6 +292,13 @@ option_t general_options[] = {
- "Set pathname of ip-down script",
- OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
-
-+ { "ipv6-up-script", o_string, path_ipv6up,
-+ "Set pathname of ipv6-up script",
-+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
-+ { "ipv6-down-script", o_string, path_ipv6down,
-+ "Set pathname of ipv6-down script",
-+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
-+
- #ifdef HAVE_MULTILINK
- { "multilink", o_bool, &multilink,
- "Enable multilink operation", OPT_PRIO | 1 },
---- a/pppd/ipv6cp.c
-+++ b/pppd/ipv6cp.c
-@@ -1288,7 +1288,7 @@ ipv6cp_up(f)
- */
- if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) {
- ipv6cp_script_state = s_up;
-- ipv6cp_script(_PATH_IPV6UP);
-+ ipv6cp_script(path_ipv6up);
- }
- }
-
-@@ -1339,7 +1339,7 @@ ipv6cp_down(f)
- /* Execute the ipv6-down script */
- if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) {
- ipv6cp_script_state = s_down;
-- ipv6cp_script(_PATH_IPV6DOWN);
-+ ipv6cp_script(path_ipv6down);
- }
- }
-
-@@ -1382,13 +1382,13 @@ ipv6cp_script_done(arg)
- case s_up:
- if (ipv6cp_fsm[0].state != OPENED) {
- ipv6cp_script_state = s_down;
-- ipv6cp_script(_PATH_IPV6DOWN);
-+ ipv6cp_script(path_ipv6down);
- }
- break;
- case s_down:
- if (ipv6cp_fsm[0].state == OPENED) {
- ipv6cp_script_state = s_up;
-- ipv6cp_script(_PATH_IPV6UP);
-+ ipv6cp_script(path_ipv6up);
- }
- break;
- }
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -315,6 +315,8 @@ extern int max_data_rate; /* max bytes/s
- 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 char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */
-+extern char path_ipv6down[MAXPATHLEN]; /* pathname of ipv6-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 */
diff --git a/package/ppp/patches/200-makefile.patch b/package/ppp/patches/200-makefile.patch
deleted file mode 100644
index 9db908de8d..0000000000
--- a/package/ppp/patches/200-makefile.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-pppd: tune Linux config defaults for OpenWrt
-
-This patch adjusts a number defaults to properly match the OpenWrt environment.
-It is not intended for upstream.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/Makefile.linux
-+++ b/pppd/Makefile.linux
-@@ -48,7 +48,7 @@ MPPE=y
- # 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
-@@ -58,11 +58,11 @@ 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
-+HAVE_INET6=y
-
- # Enable plugins
- PLUGIN=y
-@@ -77,7 +77,7 @@ MAXOCTETS=y
-
- 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) '-DDESTDIR="@DESTDIR@"'
-
-@@ -117,10 +117,10 @@ CFLAGS += -DHAS_SHADOW
- #LIBS += -lshadow $(LIBS)
- endif
-
--ifneq ($(wildcard /usr/include/crypt.h),)
-+#ifneq ($(wildcard /usr/include/crypt.h),)
- CFLAGS += -DHAVE_CRYPT_H=1
- LIBS += -lcrypt
--endif
-+#endif
-
- ifdef NEEDDES
- ifndef USE_CRYPT
diff --git a/package/ppp/patches/201-mppe_mppc_1.1.patch b/package/ppp/patches/201-mppe_mppc_1.1.patch
deleted file mode 100644
index 3edd11e7f6..0000000000
--- a/package/ppp/patches/201-mppe_mppc_1.1.patch
+++ /dev/null
@@ -1,1495 +0,0 @@
-pppd: add support for MPPE and MPPC encryption and compression protocols
-
-This is a forward ported version of ppp-2.4.3-mppe-mppc-1.1.patch.gz found on
-http://mppe-mppc.alphacron.de/ .
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/include/linux/ppp-comp.h
-+++ b/include/linux/ppp-comp.h
-@@ -36,7 +36,7 @@
- */
-
- /*
-- * ==FILEVERSION 20020319==
-+ * ==FILEVERSION 20020715==
- *
- * NOTE TO MAINTAINERS:
- * If you modify this file at all, please set the above date.
-@@ -201,6 +201,33 @@ struct compressor {
- #define CI_MPPE 18 /* config option for MPPE */
- #define CILEN_MPPE 6 /* length of config option */
-
-+/* 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.
- */
---- a/include/net/ppp-comp.h
-+++ b/include/net/ppp-comp.h
-@@ -168,6 +168,33 @@ struct compressor {
- #define CI_MPPE 18 /* config option for MPPE */
- #define CILEN_MPPE 6 /* length of config option */
-
-+/* 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.
- */
---- a/pppd/ccp.c
-+++ b/pppd/ccp.c
-@@ -62,12 +62,10 @@ static int setdeflate __P((char **));
- 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 @@ static option_t ccp_option_list[] = {
- "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 @@ static fsm_callbacks ccp_callbacks = {
- */
- #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 @@ setdeflate(argv)
- 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_init(unit)
- 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 @@ ccp_input(unit, p, len)
- 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 @@ ccp_extcode(f, code, id, p, len)
- 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 @@ ccp_protrej(unit)
- 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 @@ ccp_resetci(f)
- 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 @@ ccp_resetci(f)
- * 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 @@ ccp_cilen(f)
- + (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 @@ ccp_addci(f, p, lenp)
- {
- 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 @@ ccp_addci(f, p, lenp)
- * 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_addci(f, p, lenp)
-
- /*
- * 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 @@ ccp_ackci(f, p, len)
- 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)
-@@ -901,6 +1080,8 @@ ccp_nakci(f, p, len, treat_as_reject)
- int treat_as_reject;
- {
- 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 */
-
-@@ -908,28 +1089,100 @@ ccp_nakci(f, p, len, treat_as_reject)
- 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) {
-@@ -1002,14 +1255,50 @@ ccp_rejci(f, p, len)
- 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)
-@@ -1073,14 +1362,15 @@ ccp_reqci(f, p, lenp, dont_nak)
- 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;
-@@ -1103,106 +1393,302 @@ ccp_reqci(f, p, lenp, dont_nak)
- 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;
-- }
--
-- /* 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");
-- newret = CONFREJ;
-- break;
-+ 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;
-+ }
-+
-+ 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;
-+ if (wo->mppe || ao->mppe) {
-+ p[5] &= ~MPPE_MPPC;
-+ newret = CONFNAK;
-+ }
- }
- }
--
-- /* 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. */
-- 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;
-- }
-- } else if (ho->mppe & MPPE_OPT_128) {
-- if (!(ao->mppe & MPPE_OPT_128)) {
-- newret = CONFREJ;
-- break;
-- }
-- } else if (ho->mppe & MPPE_OPT_40) {
-- if (!(ao->mppe & MPPE_OPT_40)) {
-- newret = CONFREJ;
-- break;
-- }
-+ 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;
-+ }
-+ }
-+
-+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
-+ newret = CONFNAK;
-+ 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;
-+ }
-+ 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;
-+ }
-+ 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. */
-- /* We cannot accept this. */
-- newret = CONFNAK;
-- /* Give the peer our idea of what can be used,
-- so it can choose and confirm */
-- ho->mppe = ao->mppe;
-- }
--
-- /* 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;
-- }
--
-- /*
-- * We have accepted MPPE or are willing to negotiate
-- * MPPE parameters. A CONFREJ is due to subsequent
-- * (non-MPPE) processing.
-- */
-- rej_for_ci_mppe = 0;
-- break;
--#endif /* MPPE */
-+ /* 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;
-+ }
-+
-+ /*
-+ * 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 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;
-+ 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
-@@ -1344,12 +1830,6 @@ ccp_reqci(f, p, lenp, dont_nak)
- 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;
- }
-
-@@ -1371,24 +1851,35 @@ method_name(opt, opt2)
- 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)
-@@ -1444,12 +1935,12 @@ ccp_up(f)
- } 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 */
- }
-
- /*
-@@ -1472,7 +1963,7 @@ ccp_down(f)
- lcp_close(f->unit, "MPPE disabled");
- }
- }
--#endif
-+#endif /* MPPE */
- }
-
- /*
-@@ -1532,24 +2023,28 @@ ccp_printpkt(p, plen, printer, arg)
- #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) {
-@@ -1635,6 +2130,7 @@ ccp_datainput(unit, pkt, len)
- 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.
- */
-@@ -1642,9 +2138,18 @@ ccp_datainput(unit, pkt, len)
- 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.
---- a/pppd/ccp.h
-+++ b/pppd/ccp.h
-@@ -37,9 +37,17 @@ typedef struct ccp_options {
- 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;
-
---- a/pppd/chap_ms.c
-+++ b/pppd/chap_ms.c
-@@ -898,13 +898,17 @@ set_mppe_enc_types(int policy, int types
- /*
- * 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 --git a/package/ppp/patches/202-no_strip.patch b/package/ppp/patches/202-no_strip.patch
deleted file mode 100644
index 87c76ad0e7..0000000000
--- a/package/ppp/patches/202-no_strip.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-build: Do not strip binaries on install
-
-Strippign executables should be handled by the distro packaging, not by ppp
-itself. This patch removes the "-s" (strip) switch from all "install" commands
-in order to install unstripped binaries into the destination prefix.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/chat/Makefile.linux
-+++ b/chat/Makefile.linux
-@@ -25,7 +25,7 @@ chat.o: chat.c
-
- install: chat
- mkdir -p $(BINDIR) $(MANDIR)
-- $(INSTALL) -s -c chat $(BINDIR)
-+ $(INSTALL) -c chat $(BINDIR)
- $(INSTALL) -c -m 644 chat.8 $(MANDIR)
-
- clean:
---- a/pppd/Makefile.linux
-+++ b/pppd/Makefile.linux
-@@ -99,7 +99,7 @@ ifdef USE_SRP
- 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
-@@ -200,7 +200,7 @@ all: $(TARGETS)
- 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)
---- a/pppd/plugins/radius/Makefile.linux
-+++ b/pppd/plugins/radius/Makefile.linux
-@@ -36,9 +36,9 @@ all: $(PLUGIN)
-
- 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)
-
---- a/pppd/plugins/rp-pppoe/Makefile.linux
-+++ b/pppd/plugins/rp-pppoe/Makefile.linux
-@@ -43,9 +43,9 @@ rp-pppoe.so: plugin.o discovery.o if.o c
-
- 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 pppoe-discovery
---- a/pppdump/Makefile.linux
-+++ b/pppdump/Makefile.linux
-@@ -17,5 +17,5 @@ clean:
-
- install:
- mkdir -p $(BINDIR) $(MANDIR)
-- $(INSTALL) -s -c pppdump $(BINDIR)
-+ $(INSTALL) -c pppdump $(BINDIR)
- $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
---- a/pppstats/Makefile.linux
-+++ b/pppstats/Makefile.linux
-@@ -22,7 +22,7 @@ all: pppstats
-
- install: pppstats
- -mkdir -p $(MANDIR)
-- $(INSTALL) -s -c pppstats $(BINDIR)
-+ $(INSTALL) -c pppstats $(BINDIR)
- $(INSTALL) -c -m 444 pppstats.8 $(MANDIR)
-
- pppstats: $(PPPSTATSRCS)
diff --git a/package/ppp/patches/203-opt_flags.patch b/package/ppp/patches/203-opt_flags.patch
deleted file mode 100644
index a369163527..0000000000
--- a/package/ppp/patches/203-opt_flags.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-build: Move optimization flags into a separate variable
-
-Isolate optimization related compiler flags from CFLAGS and move them into a
-separate COPTS variable so that it is easier to override optimizations from
-the environment.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/plugins/radius/Makefile.linux
-+++ b/pppd/plugins/radius/Makefile.linux
-@@ -12,7 +12,8 @@ VERSION = $(shell awk -F '"' '/VERSION/
- 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.
---- a/pppdump/Makefile.linux
-+++ b/pppdump/Makefile.linux
-@@ -2,7 +2,8 @@ DESTDIR = $(INSTROOT)@DESTDIR@
- 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
diff --git a/package/ppp/patches/204-radius_config.patch b/package/ppp/patches/204-radius_config.patch
deleted file mode 100644
index c97a535079..0000000000
--- a/package/ppp/patches/204-radius_config.patch
+++ /dev/null
@@ -1,72 +0,0 @@
---- a/pppd/plugins/radius/config.c
-+++ b/pppd/plugins/radius/config.c
-@@ -369,31 +369,37 @@ static int test_config(char *filename)
- }
- #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;
- }
---- a/pppd/plugins/radius/options.h
-+++ b/pppd/plugins/radius/options.h
-@@ -31,24 +31,21 @@ typedef struct _option {
- 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},
diff --git a/package/ppp/patches/205-no_exponential_timeout.patch b/package/ppp/patches/205-no_exponential_timeout.patch
deleted file mode 100644
index 7119fb83f2..0000000000
--- a/package/ppp/patches/205-no_exponential_timeout.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-pppd: Don't use exponential timeout in discovery phase
-
-This patch removes the exponential timeout increase between PADO or PADS
-discovery attempts.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/plugins/rp-pppoe/discovery.c
-+++ b/pppd/plugins/rp-pppoe/discovery.c
-@@ -548,7 +548,9 @@ discovery(PPPoEConnection *conn)
- conn->discoveryState = STATE_SENT_PADI;
- waitForPADO(conn, timeout);
-
-+#if 0
- timeout *= 2;
-+#endif
- } while (conn->discoveryState == STATE_SENT_PADI);
-
- timeout = conn->discoveryTimeout;
-@@ -563,7 +565,9 @@ discovery(PPPoEConnection *conn)
- sendPADR(conn);
- conn->discoveryState = STATE_SENT_PADR;
- waitForPADS(conn, timeout);
-+#if 0
- timeout *= 2;
-+#endif
- } while (conn->discoveryState == STATE_SENT_PADR);
-
- /* We're done. */
diff --git a/package/ppp/patches/206-compensate_time_change.patch b/package/ppp/patches/206-compensate_time_change.patch
deleted file mode 100644
index fb6c65679e..0000000000
--- a/package/ppp/patches/206-compensate_time_change.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-pppd: Watch out for time warps
-
-On many embedded systems there is no battery backed RTC and a proper system
-time only becomes available through NTP after establishing a connection.
-
-When the clock suddenly jumps forward, the internal accounting (connect time)
-is confused resulting in unreliable data.
-
-This patch implements periodic clock checking to look for time warps, if one
-is detected, the internal counters are adjusted accordingly.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -90,6 +90,7 @@
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-+#include <sys/sysinfo.h>
-
- #include "pppd.h"
- #include "magic.h"
-@@ -228,6 +229,7 @@ static struct subprocess *children;
-
- /* Prototypes for procedures local to this file. */
-
-+static void check_time(void);
- static void setup_signals __P((void));
- static void create_pidfile __P((int pid));
- static void create_linkpidfile __P((int pid));
-@@ -535,6 +537,7 @@ main(argc, argv)
- info("Starting link");
- }
-
-+ check_time();
- gettimeofday(&start_time, NULL);
- script_unsetenv("CONNECT_TIME");
- script_unsetenv("BYTES_SENT");
-@@ -1267,6 +1270,36 @@ struct callout {
-
- static struct callout *callout = NULL; /* Callout list */
- static struct timeval timenow; /* Current time */
-+static long uptime_diff = 0;
-+static int uptime_diff_set = 0;
-+
-+static void check_time(void)
-+{
-+ long new_diff;
-+ struct timeval t;
-+ struct sysinfo i;
-+ struct callout *p;
-+
-+ gettimeofday(&t, NULL);
-+ sysinfo(&i);
-+ new_diff = t.tv_sec - i.uptime;
-+
-+ if (!uptime_diff_set) {
-+ uptime_diff = new_diff;
-+ uptime_diff_set = 1;
-+ return;
-+ }
-+
-+ if ((new_diff - 5 > uptime_diff) || (new_diff + 5 < uptime_diff)) {
-+ /* system time has changed, update counters and timeouts */
-+ info("System time change detected.");
-+ start_time.tv_sec += new_diff - uptime_diff;
-+
-+ for (p = callout; p != NULL; p = p->c_next)
-+ p->c_time.tv_sec += new_diff - uptime_diff;
-+ }
-+ uptime_diff = new_diff;
-+}
-
- /*
- * timeout - Schedule a timeout.
-@@ -1337,6 +1370,8 @@ calltimeout()
- {
- struct callout *p;
-
-+ check_time();
-+
- while (callout != NULL) {
- p = callout;
-
-@@ -1364,6 +1399,8 @@ timeleft(tvp)
- {
- if (callout == NULL)
- return NULL;
-+
-+ check_time();
-
- gettimeofday(&timenow, NULL);
- tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
diff --git a/package/ppp/patches/207-lcp_mtu_max.patch b/package/ppp/patches/207-lcp_mtu_max.patch
deleted file mode 100644
index 1ebcf412fc..0000000000
--- a/package/ppp/patches/207-lcp_mtu_max.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-pppd: Cap MTU to the user configured value
-
-This patchs caps the calculated MTU value in lcp.c to the user specified "mru"
-option value. Without this patch pppd would advertise a different MTU value
-compared to what is set on the local interface in some cases.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/lcp.c
-+++ b/pppd/lcp.c
-@@ -1904,12 +1904,12 @@ lcp_up(f)
- * the interface MTU is set to the lowest of that, the
- * MTU we want to use, and our link MRU.
- */
-- mtu = ho->neg_mru? ho->mru: PPP_MRU;
-+ mtu = MIN(ho->neg_mru? ho->mru: PPP_MRU, ao->mru);
- mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU;
- #ifdef HAVE_MULTILINK
- if (!(multilink && go->neg_mrru && ho->neg_mrru))
- #endif /* HAVE_MULTILINK */
-- netif_set_mtu(f->unit, MIN(MIN(mtu, mru), ao->mru));
-+ netif_set_mtu(f->unit, MIN(mtu, mru));
- ppp_send_config(f->unit, mtu,
- (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
- ho->neg_pcompression, ho->neg_accompression);
diff --git a/package/ppp/patches/208-fix_status_code.patch b/package/ppp/patches/208-fix_status_code.patch
deleted file mode 100644
index 25e2a10b85..0000000000
--- a/package/ppp/patches/208-fix_status_code.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-pppd: Do not clobber exit codes on hangup
-
-When a modem hangup occurs, pppd unconditionally sets the exit status code
-to EXIT_HANGUP. This patch only sets EXIT_HANGUP if the exit status code is
-not already set to an error value.
-
-The motiviation of this patch is to allow applications which remote control
-pppd to react properly on errors, e.g. only redial (relaunch pppd) if there
-was a hangup, but not if the CHAP authentication failed.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -1048,7 +1048,8 @@ get_input()
- }
- notice("Modem hangup");
- hungup = 1;
-- status = EXIT_HANGUP;
-+ if (status == EXIT_OK)
-+ status = EXIT_HANGUP;
- lcp_lowerdown(0); /* serial link is no longer available */
- link_terminated(0);
- return;
diff --git a/package/ppp/patches/300-filter-pcap-includes-lib.patch b/package/ppp/patches/300-filter-pcap-includes-lib.patch
deleted file mode 100644
index d8dcc64c8b..0000000000
--- a/package/ppp/patches/300-filter-pcap-includes-lib.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-build: Add required CFLAGS for libpcap
-
-This patch adds some flags to required to properly link libpcap within the
-OpenWrt environment.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/Makefile.linux
-+++ b/pppd/Makefile.linux
-@@ -170,8 +170,8 @@ endif
-
- ifdef FILTER
- ifneq ($(wildcard /usr/include/pcap-bpf.h),)
--LIBS += -lpcap
--CFLAGS += -DPPP_FILTER
-+LIBS += -lpcap -L$(STAGING_DIR)/usr/lib
-+CFLAGS += -DPPP_FILTER -I$(STAGING_DIR)/usr/include
- endif
- endif
-
diff --git a/package/ppp/patches/310-precompile_filter.patch b/package/ppp/patches/310-precompile_filter.patch
deleted file mode 100644
index 87b9687ef7..0000000000
--- a/package/ppp/patches/310-precompile_filter.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-pppd: Implement support for precompiled pcap filters
-
-This patch implements support for precompiled pcap filters which is useful to
-support dial-on-demand on memory constrained embedded devices without having
-to link the full libpcap into pppd to generate the filters during runtime.
-
-Two new options are introduced; "precompiled-pass-filter" specifies a pre-
-compiled filter file containing rules to match packets which should be passed,
-"precompiled-active-filter" specifies a filter file containing rules to match
-packets which are treated as active.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/Makefile.linux
-+++ b/pppd/Makefile.linux
-@@ -50,6 +50,9 @@ MPPE=y
- # and that the kernel driver support PPP packet filtering.
- #FILTER=y
-
-+# Support for precompiled filters
-+PRECOMPILED_FILTER=y
-+
- # Uncomment the next line to enable multilink PPP (enabled by default)
- # Linux distributions: Please leave multilink ENABLED in your builds
- # of pppd!
-@@ -175,6 +178,14 @@ CFLAGS += -DPPP_FILTER -I$(STAGING_DIR)
- endif
- endif
-
-+ifdef PRECOMPILED_FILTER
-+PPPDSRCS += pcap_pcc.c
-+HEADERS += pcap_pcc.h
-+PPPDOBJS += pcap_pcc.o
-+LIBS += $(STAGING_DIR)/usr/lib/libpcap.a
-+CFLAGS += -DPPP_FILTER -DPPP_PRECOMPILED_FILTER -I$(STAGING_DIR)/usr/include
-+endif
-+
- ifdef HAVE_INET6
- PPPDSRCS += ipv6cp.c eui64.c
- HEADERS += ipv6cp.h eui64.h
---- a/pppd/options.c
-+++ b/pppd/options.c
-@@ -57,6 +57,7 @@
-
- #ifdef PPP_FILTER
- #include <pcap.h>
-+#include <pcap-bpf.h>
- /*
- * There have been 3 or 4 different names for this in libpcap CVS, but
- * this seems to be what they have settled on...
-@@ -162,6 +163,13 @@ static int setlogfile __P((char **));
- static int loadplugin __P((char **));
- #endif
-
-+#ifdef PPP_PRECOMPILED_FILTER
-+#include "pcap_pcc.h"
-+static int setprecompiledpassfilter __P((char **));
-+static int setprecompiledactivefilter __P((char **));
-+#undef PPP_FILTER
-+#endif
-+
- #ifdef PPP_FILTER
- static int setpassfilter __P((char **));
- static int setactivefilter __P((char **));
-@@ -326,6 +334,14 @@ option_t general_options[] = {
- "set filter for active pkts", OPT_PRIO },
- #endif
-
-+#ifdef PPP_PRECOMPILED_FILTER
-+ { "precompiled-pass-filter", 1, setprecompiledpassfilter,
-+ "set precompiled filter for packets to pass", OPT_PRIO },
-+
-+ { "precompiled-active-filter", 1, setprecompiledactivefilter,
-+ "set precompiled filter for active pkts", OPT_PRIO },
-+#endif
-+
- #ifdef MAXOCTETS
- { "maxoctets", o_int, &maxoctets,
- "Set connection traffic limit",
-@@ -1472,6 +1488,29 @@ callfile(argv)
- return ok;
- }
-
-+#ifdef PPP_PRECOMPILED_FILTER
-+/*
-+ * setprecompiledpassfilter - Set the pass filter for packets using a
-+ * precompiled expression
-+ */
-+static int
-+setprecompiledpassfilter(argv)
-+ char **argv;
-+{
-+ return pcap_pre_compiled (*argv, &pass_filter);
-+}
-+
-+/*
-+ * setactivefilter - Set the active filter for packets
-+ */
-+static int
-+setprecompiledactivefilter(argv)
-+ char **argv;
-+{
-+ return pcap_pre_compiled (*argv, &active_filter);
-+}
-+#endif
-+
- #ifdef PPP_FILTER
- /*
- * setpassfilter - Set the pass filter for packets
---- /dev/null
-+++ b/pppd/pcap_pcc.c
-@@ -0,0 +1,74 @@
-+#include <pcap.h>
-+#include <pcap-bpf.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include "pppd.h"
-+
-+int pcap_pre_compiled (char * fname, struct bpf_program *p)
-+{
-+ char buf[128];
-+ int line = 0, size = 0, index=0, ret=1;
-+ FILE *f = fopen (fname, "r");
-+ if (!f)
-+ {
-+ option_error("error opening precompiled active-filter '%s': %s",
-+ fname, strerror (errno));
-+ return 0;
-+ }
-+ while (fgets (buf, 127, f))
-+ {
-+ line++;
-+ if (*buf == '#')
-+ continue;
-+ if (size)
-+ {
-+ /*
-+ struct bpf_insn {
-+ u_short code;
-+ u_char jt;
-+ u_char jf;
-+ bpf_int32 k;
-+ }
-+ */
-+ struct bpf_insn * insn = & p->bf_insns[index];
-+ unsigned code, jt, jf, k;
-+ if (sscanf (buf, "%u %u %u %u", &code, &jt, &jf, &k) != 4)
-+ {
-+ goto err;
-+ }
-+ insn->code = code;
-+ insn->jt = jt;
-+ insn->jf = jf;
-+ insn->k = k;
-+ index++;
-+ }
-+ else
-+ {
-+ if (sscanf (buf, "%u", &size) != 1)
-+ {
-+ goto err;
-+ }
-+ p->bf_len = size;
-+ p->bf_insns = (struct bpf_insn *)
-+ malloc (size * sizeof (struct bpf_insn));
-+ }
-+ }
-+ if (size != index)
-+ {
-+ option_error("error in precompiled active-filter,"
-+ " expected %d expressions, got %dn",
-+ size, index);
-+ ret = 0;
-+ }
-+ fclose(f);
-+ return ret;
-+
-+err:
-+ option_error("error in precompiled active-filter"
-+ " expression line %s:%d (wrong size)\n",
-+ fname, line);
-+ fclose (f);
-+ return 0;
-+}
---- /dev/null
-+++ b/pppd/pcap_pcc.h
-@@ -0,0 +1,7 @@
-+#ifndef PCAP_PCC_H
-+#define PCAP_PCC_H
-+
-+#include <pcap.h>
-+
-+int pcap_pre_compiled (char * fname, struct bpf_program *p);
-+#endif /* PCAP_PCC_H */
diff --git a/package/ppp/patches/320-custom_iface_names.patch b/package/ppp/patches/320-custom_iface_names.patch
deleted file mode 100644
index a95f4f8c81..0000000000
--- a/package/ppp/patches/320-custom_iface_names.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-pppd: Support arbitrary interface names
-
-This patch implements a new string option "ifname" which allows to specify
-fully custom PPP interface names on Linux. It does so by renaming the
-allocated pppX device immediately after it has been created to the requested
-interface name.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -745,8 +745,11 @@ void
- set_ifunit(iskey)
- int iskey;
- {
-- info("Using interface %s%d", PPP_DRV_NAME, ifunit);
-- slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
-+ if (use_ifname[0] == 0)
-+ slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
-+ else
-+ slprintf(ifname, sizeof(ifname), "%s", use_ifname);
-+ info("Using interface %s", ifname);
- script_setenv("IFNAME", ifname, iskey);
- if (iskey) {
- create_pidfile(getpid()); /* write pid to file */
---- a/pppd/options.c
-+++ b/pppd/options.c
-@@ -111,6 +111,7 @@ int log_to_fd = 1; /* send log messages
- bool log_default = 1; /* log_to_fd is default (stdout) */
- int maxfail = 10; /* max # of unsuccessful connection attempts */
- char linkname[MAXPATHLEN]; /* logical name for link */
-+char use_ifname[IFNAMSIZ]; /* physical name for PPP link */
- bool tune_kernel; /* may alter kernel settings */
- int connect_delay = 1000; /* wait this many ms after connect script */
- int req_unit = -1; /* requested interface unit */
-@@ -266,6 +267,9 @@ option_t general_options[] = {
- { "linkname", o_string, linkname,
- "Set logical name for link",
- OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },
-+ { "ifname", o_string, use_ifname,
-+ "Set physical name for PPP interface",
-+ OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, IFNAMSIZ },
-
- { "maxfail", o_int, &maxfail,
- "Maximum number of unsuccessful connection attempts to allow",
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -71,6 +71,10 @@
- #include "eui64.h"
- #endif
-
-+#ifndef IFNAMSIZ
-+#define IFNAMSIZ 16
-+#endif
-+
- /*
- * Limits.
- */
-@@ -309,6 +313,7 @@ extern char *record_file; /* File to rec
- extern bool sync_serial; /* Device is synchronous serial device */
- extern int maxfail; /* Max # of unsuccessful connection attempts */
- extern char linkname[MAXPATHLEN]; /* logical name for link */
-+extern char use_ifname[IFNAMSIZ]; /* physical name for PPP interface */
- extern bool tune_kernel; /* May alter kernel settings as necessary */
- extern int connect_delay; /* Time to delay after connect script */
- extern int max_data_rate; /* max bytes/sec through charshunt */
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -168,6 +168,10 @@ struct in6_ifreq {
- /* We can get an EIO error on an ioctl if the modem has hung up */
- #define ok_error(num) ((num)==EIO)
-
-+#if !defined(PPP_DRV_NAME)
-+#define PPP_DRV_NAME "ppp"
-+#endif /* !defined(PPP_DRV_NAME) */
-+
- static int tty_disc = N_TTY; /* The TTY discipline */
- static int ppp_disc = N_PPP; /* The PPP discpline */
- static int initfdflags = -1; /* Initial file descriptor flags for fd */
-@@ -622,7 +626,8 @@ void generic_disestablish_ppp(int dev_fd
- */
- static int make_ppp_unit()
- {
-- int x, flags;
-+ struct ifreq ifr;
-+ int x, flags, s;
-
- if (ppp_dev_fd >= 0) {
- dbglog("in make_ppp_unit, already had /dev/ppp open?");
-@@ -645,6 +650,30 @@ static int make_ppp_unit()
- }
- if (x < 0)
- error("Couldn't create new ppp unit: %m");
-+
-+ if (use_ifname[0] != 0) {
-+ s = socket(PF_INET, SOCK_DGRAM, 0);
-+ if (s < 0)
-+ s = socket(PF_PACKET, SOCK_DGRAM, 0);
-+ if (s < 0)
-+ s = socket(PF_INET6, SOCK_DGRAM, 0);
-+ if (s < 0)
-+ s = socket(PF_UNIX, SOCK_DGRAM, 0);
-+ if (s >= 0) {
-+ slprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", PPP_DRV_NAME, ifunit);
-+ slprintf(ifr.ifr_newname, sizeof(ifr.ifr_newname), "%s", use_ifname);
-+ x = ioctl(s, SIOCSIFNAME, &ifr);
-+ close(s);
-+ } else {
-+ x = s;
-+ }
-+ if (x < 0) {
-+ error("Couldn't rename %s to %s", ifr.ifr_name, ifr.ifr_newname);
-+ close(ppp_dev_fd);
-+ ppp_dev_fd = -1;
-+ }
-+ }
-+
- return x;
- }
-
---- a/pppstats/pppstats.c
-+++ b/pppstats/pppstats.c
-@@ -506,10 +506,12 @@ main(argc, argv)
- if (argc > 0)
- interface = argv[0];
-
-+#if 0
- if (sscanf(interface, PPP_DRV_NAME "%d", &unit) != 1) {
- fprintf(stderr, "%s: invalid interface '%s' specified\n",
- progname, interface);
- }
-+#endif
-
- #ifndef STREAMS
- {
diff --git a/package/ppp/patches/330-retain_foreign_default_routes.patch b/package/ppp/patches/330-retain_foreign_default_routes.patch
deleted file mode 100644
index 0d7fff9b4b..0000000000
--- a/package/ppp/patches/330-retain_foreign_default_routes.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-pppd: Retain foreign default routes on Linux
-
-On Linux, when pppd attempts to delete its default route it does not fill
-the rt_dev field of the struct rtentry used to match the system default route.
-As a consequence, pppd happily deletes any default route even if it belongs
-to another interface.
-
-This patch makes pppd fill out the rt_dev field so that only own default
-routes are ever matched.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -1743,6 +1743,7 @@ int cifdefaultroute (int unit, u_int32_t
- SIN_ADDR(rt.rt_genmask) = 0L;
- }
-
-+ rt.rt_dev = ifname;
- rt.rt_flags = RTF_UP;
- if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
- if (still_ppp()) {
diff --git a/package/ppp/patches/340-populate_default_gateway.patch b/package/ppp/patches/340-populate_default_gateway.patch
deleted file mode 100644
index 9a0284eb23..0000000000
--- a/package/ppp/patches/340-populate_default_gateway.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-pppd: Fill in default gateway on Linux
-
-On Linux, when pppd creates the default route, it does not set the peer
-address as gateway, leading to a default route without gateway address.
-
-This behaviour breaks various downstream programs which attempt to infer
-the default gateway IP address from the system default route entry.
-
-This patch addresses the issue by filling in the peer address as gateway
-when generating the default route entry.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -1697,6 +1697,9 @@ int sifdefaultroute (int unit, u_int32_t
- memset (&rt, 0, sizeof (rt));
- SET_SA_FAMILY (rt.rt_dst, AF_INET);
-
-+ SET_SA_FAMILY(rt.rt_gateway, AF_INET);
-+ SIN_ADDR(rt.rt_gateway) = gateway;
-+
- rt.rt_dev = ifname;
-
- if (kernel_version > KVERSION(2,1,0)) {
-@@ -1704,7 +1707,7 @@ int sifdefaultroute (int unit, u_int32_t
- SIN_ADDR(rt.rt_genmask) = 0L;
- }
-
-- rt.rt_flags = RTF_UP;
-+ rt.rt_flags = RTF_UP | RTF_GATEWAY;
- if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
- if (!ok_error(errno))
- error("default route ioctl(SIOCADDRT): %m");
diff --git a/package/ppp/patches/400-simplify_kernel_checks.patch b/package/ppp/patches/400-simplify_kernel_checks.patch
deleted file mode 100644
index ec82576cbc..0000000000
--- a/package/ppp/patches/400-simplify_kernel_checks.patch
+++ /dev/null
@@ -1,154 +0,0 @@
-pppd: Remove runtime kernel checks
-
-On embedded system distributions the required kernel features for pppd are
-more or less guaranteed to be present, so there is not much point in
-performing runtime checks, it just increases the binary size.
-
-This patch removes the runtime kernel feature checks.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -203,7 +203,7 @@ static int driver_is_old = 0;
- static int restore_term = 0; /* 1 => we've munged the terminal */
- static struct termios inittermios; /* Initial TTY termios */
-
--int new_style_driver = 0;
-+static const int new_style_driver = 1;
-
- static char loop_name[20];
- static unsigned char inbuf[512]; /* buffer for chars read from loopback */
-@@ -220,8 +220,8 @@ static int looped; /* 1 if using loop
- static int link_mtu; /* mtu for the link (not bundle) */
-
- static struct utsname utsname; /* for the kernel version */
--static int kernel_version;
- #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
-+static const int kernel_version = KVERSION(2,6,37);
-
- #define MAX_IFS 100
-
-@@ -1438,11 +1438,12 @@ int ccp_fatal_error (int unit)
- *
- * path_to_procfs - find the path to the proc file system mount point
- */
--static char proc_path[MAXPATHLEN];
--static int proc_path_len;
-+static char proc_path[MAXPATHLEN] = "/proc";
-+static int proc_path_len = 5;
-
- static char *path_to_procfs(const char *tail)
- {
-+#if 0
- struct mntent *mntent;
- FILE *fp;
-
-@@ -1464,6 +1465,7 @@ static char *path_to_procfs(const char *
- fclose (fp);
- }
- }
-+#endif
-
- strlcpy(proc_path + proc_path_len, tail,
- sizeof(proc_path) - proc_path_len);
-@@ -2116,15 +2118,19 @@ int ppp_available(void)
- int my_version, my_modification, my_patch;
- int osmaj, osmin, ospatch;
-
-+#if 0
- /* get the kernel version now, since we are called before sys_init */
- uname(&utsname);
- osmaj = osmin = ospatch = 0;
- sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
- kernel_version = KVERSION(osmaj, osmin, ospatch);
-+#endif
-
- fd = open("/dev/ppp", O_RDWR);
- if (fd >= 0) {
-+#if 0
- new_style_driver = 1;
-+#endif
-
- /* XXX should get from driver */
- driver_version = 2;
-@@ -2185,6 +2191,7 @@ int ppp_available(void)
-
- if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
- ok = 0;
-+ return ok;
-
- /*
- * This is the PPP device. Validate the version of the driver at this
-@@ -2678,6 +2685,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
- }
- #endif /* TIOCGPTN */
-
-+#if 0
- if (sfd < 0) {
- /* the old way - scan through the pty name space */
- for (i = 0; i < 64; ++i) {
-@@ -2696,6 +2704,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
- }
- }
- }
-+#endif
-
- if (sfd < 0)
- return 0;
---- a/pppd/plugins/pppoatm/pppoatm.c
-+++ b/pppd/plugins/pppoatm/pppoatm.c
-@@ -170,14 +170,6 @@ static void disconnect_pppoatm(void)
-
- void plugin_init(void)
- {
--#if defined(__linux__)
-- extern int new_style_driver; /* From sys-linux.c */
-- if (!ppp_available() && !new_style_driver)
-- fatal("Kernel doesn't support ppp_generic - "
-- "needed for PPPoATM");
--#else
-- fatal("No PPPoATM support on this OS");
--#endif
- info("PPPoATM plugin_init");
- add_options(pppoa_options);
- }
---- a/pppd/plugins/rp-pppoe/plugin.c
-+++ b/pppd/plugins/rp-pppoe/plugin.c
-@@ -60,9 +60,6 @@ static char const RCSID[] =
-
- char pppd_version[] = VERSION;
-
--/* From sys-linux.c in pppd -- MUST FIX THIS! */
--extern int new_style_driver;
--
- char *pppd_pppoe_service = NULL;
- static char *acName = NULL;
- static char *existingSession = NULL;
-@@ -340,10 +337,6 @@ PPPoEDevnameHook(char *cmd, char **argv,
- void
- plugin_init(void)
- {
-- if (!ppp_available() && !new_style_driver) {
-- fatal("Linux kernel does not support PPPoE -- are you running 2.4.x?");
-- }
--
- add_options(Options);
-
- info("RP-PPPoE plugin version %s compiled against pppd %s",
---- a/pppd/plugins/pppol2tp/pppol2tp.c
-+++ b/pppd/plugins/pppol2tp/pppol2tp.c
-@@ -500,12 +500,7 @@ static void pppol2tp_cleanup(void)
-
- void plugin_init(void)
- {
--#if defined(__linux__)
-- extern int new_style_driver; /* From sys-linux.c */
-- if (!ppp_available() && !new_style_driver)
-- fatal("Kernel doesn't support ppp_generic - "
-- "needed for PPPoL2TP");
--#else
-+#if !defined(__linux__)
- fatal("No PPPoL2TP support on this OS");
- #endif
- add_options(pppol2tp_options);
diff --git a/package/ppp/patches/401-no_record_file.patch b/package/ppp/patches/401-no_record_file.patch
deleted file mode 100644
index 94c0263eaa..0000000000
--- a/package/ppp/patches/401-no_record_file.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-pppd: Remove the "record" option
-
-On many embedded systems there is not enough space to record PPP session
-information to the permanent storage, therfore remove this option.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/pppd.h
-+++ b/pppd/pppd.h
-@@ -309,7 +309,6 @@ extern int holdoff; /* Dead time before
- extern bool holdoff_specified; /* true if user gave a holdoff value */
- extern bool notty; /* Stdin/out is not a tty */
- extern char *pty_socket; /* Socket to connect to pty */
--extern char *record_file; /* File to record chars sent/received */
- extern bool sync_serial; /* Device is synchronous serial device */
- extern int maxfail; /* Max # of unsuccessful connection attempts */
- extern char linkname[MAXPATHLEN]; /* logical name for link */
---- a/pppd/tty.c
-+++ b/pppd/tty.c
-@@ -145,7 +145,7 @@ char *disconnect_script = NULL; /* Scrip
- char *welcomer = NULL; /* Script to run after phys link estab. */
- char *ptycommand = NULL; /* Command to run on other side of pty */
- bool notty = 0; /* Stdin/out is not a tty */
--char *record_file = NULL; /* File to record chars sent/received */
-+static char *const record_file = NULL; /* File to record chars sent/received */
- int max_data_rate; /* max bytes/sec through charshunt */
- bool sync_serial = 0; /* Device is synchronous serial device */
- char *pty_socket = NULL; /* Socket to connect to pty */
-@@ -201,8 +201,10 @@ option_t tty_options[] = {
- "Send and receive over socket, arg is host:port",
- OPT_PRIO | OPT_DEVNAM },
-
-+#if 0
- { "record", o_string, &record_file,
- "Record characters sent/received to file", OPT_PRIO },
-+#endif
-
- { "crtscts", o_int, &crtscts,
- "Set hardware (RTS/CTS) flow control",
diff --git a/package/ppp/patches/403-no_wtmp.patch b/package/ppp/patches/403-no_wtmp.patch
deleted file mode 100644
index 71233200e7..0000000000
--- a/package/ppp/patches/403-no_wtmp.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-pppd: Disable wtmp support
-
-Many uClibc based environments lack wtmp and utmp support, therfore remove
-the code updating the wtmp information.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/sys-linux.c
-+++ b/pppd/sys-linux.c
-@@ -2254,6 +2254,7 @@ int ppp_available(void)
-
- void logwtmp (const char *line, const char *name, const char *host)
- {
-+#if 0
- struct utmp ut, *utp;
- pid_t mypid = getpid();
- #if __GLIBC__ < 2
-@@ -2319,6 +2320,7 @@ void logwtmp (const char *line, const ch
- close (wtmp);
- }
- #endif
-+#endif
- }
-
-
diff --git a/package/ppp/patches/404-remove_obsolete_protocol_names.patch b/package/ppp/patches/404-remove_obsolete_protocol_names.patch
deleted file mode 100644
index edbca7603c..0000000000
--- a/package/ppp/patches/404-remove_obsolete_protocol_names.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-pppd: Remove historical protocol names
-
-Remove a number of historical protocol entries from pppd's builtin list, this
-reduced the binary size without loss of features.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/main.c
-+++ b/pppd/main.c
-@@ -882,14 +882,17 @@ struct protocol_list {
- const char *name;
- } protocol_list[] = {
- { 0x21, "IP" },
-+#if 0
- { 0x23, "OSI Network Layer" },
- { 0x25, "Xerox NS IDP" },
- { 0x27, "DECnet Phase IV" },
- { 0x29, "Appletalk" },
- { 0x2b, "Novell IPX" },
-+#endif
- { 0x2d, "VJ compressed TCP/IP" },
- { 0x2f, "VJ uncompressed TCP/IP" },
- { 0x31, "Bridging PDU" },
-+#if 0
- { 0x33, "Stream Protocol ST-II" },
- { 0x35, "Banyan Vines" },
- { 0x39, "AppleTalk EDDP" },
-@@ -903,8 +906,11 @@ struct protocol_list {
- { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
- { 0x4b, "SNA over 802.2" },
- { 0x4d, "SNA" },
-+#endif
- { 0x4f, "IP6 Header Compression" },
-+#if 0
- { 0x51, "KNX Bridging Data" },
-+#endif
- { 0x53, "Encryption" },
- { 0x55, "Individual Link Encryption" },
- { 0x57, "IPv6" },
-@@ -915,12 +921,15 @@ struct protocol_list {
- { 0x65, "RTP IPHC Compressed non-TCP" },
- { 0x67, "RTP IPHC Compressed UDP 8" },
- { 0x69, "RTP IPHC Compressed RTP 8" },
-+#if 0
- { 0x6f, "Stampede Bridging" },
- { 0x73, "MP+" },
- { 0xc1, "NTCITS IPI" },
-+#endif
- { 0xfb, "single-link compression" },
- { 0xfd, "Compressed Datagram" },
- { 0x0201, "802.1d Hello Packets" },
-+#if 0
- { 0x0203, "IBM Source Routing BPDU" },
- { 0x0205, "DEC LANBridge100 Spanning Tree" },
- { 0x0207, "Cisco Discovery Protocol" },
-@@ -932,15 +941,19 @@ struct protocol_list {
- { 0x0231, "Luxcom" },
- { 0x0233, "Sigma Network Systems" },
- { 0x0235, "Apple Client Server Protocol" },
-+#endif
- { 0x0281, "MPLS Unicast" },
- { 0x0283, "MPLS Multicast" },
-+#if 0
- { 0x0285, "IEEE p1284.4 standard - data packets" },
- { 0x0287, "ETSI TETRA Network Protocol Type 1" },
-+#endif
- { 0x0289, "Multichannel Flow Treatment Protocol" },
- { 0x2063, "RTP IPHC Compressed TCP No Delta" },
- { 0x2065, "RTP IPHC Context State" },
- { 0x2067, "RTP IPHC Compressed UDP 16" },
- { 0x2069, "RTP IPHC Compressed RTP 16" },
-+#if 0
- { 0x4001, "Cray Communications Control Protocol" },
- { 0x4003, "CDPD Mobile Network Registration Protocol" },
- { 0x4005, "Expand accelerator protocol" },
-@@ -951,8 +964,10 @@ struct protocol_list {
- { 0x4023, "RefTek Protocol" },
- { 0x4025, "Fibre Channel" },
- { 0x4027, "EMIT Protocols" },
-+#endif
- { 0x405b, "Vendor-Specific Protocol (VSP)" },
- { 0x8021, "Internet Protocol Control Protocol" },
-+#if 0
- { 0x8023, "OSI Network Layer Control Protocol" },
- { 0x8025, "Xerox NS IDP Control Protocol" },
- { 0x8027, "DECnet Phase IV Control Protocol" },
-@@ -961,7 +976,9 @@ struct protocol_list {
- { 0x8031, "Bridging NCP" },
- { 0x8033, "Stream Protocol Control Protocol" },
- { 0x8035, "Banyan Vines Control Protocol" },
-+#endif
- { 0x803d, "Multi-Link Control Protocol" },
-+#if 0
- { 0x803f, "NETBIOS Framing Control Protocol" },
- { 0x8041, "Cisco Systems Control Protocol" },
- { 0x8043, "Ascom Timeplex" },
-@@ -970,18 +987,24 @@ struct protocol_list {
- { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
- { 0x804b, "SNA over 802.2 Control Protocol" },
- { 0x804d, "SNA Control Protocol" },
-+#endif
- { 0x804f, "IP6 Header Compression Control Protocol" },
-+#if 0
- { 0x8051, "KNX Bridging Control Protocol" },
-+#endif
- { 0x8053, "Encryption Control Protocol" },
- { 0x8055, "Individual Link Encryption Control Protocol" },
- { 0x8057, "IPv6 Control Protocol" },
- { 0x8059, "PPP Muxing Control Protocol" },
- { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" },
-+#if 0
- { 0x806f, "Stampede Bridging Control Protocol" },
- { 0x8073, "MP+ Control Protocol" },
- { 0x80c1, "NTCITS IPI Control Protocol" },
-+#endif
- { 0x80fb, "Single Link Compression Control Protocol" },
- { 0x80fd, "Compression Control Protocol" },
-+#if 0
- { 0x8207, "Cisco Discovery Protocol Control" },
- { 0x8209, "Netcs Twin Routing" },
- { 0x820b, "STP - Control Protocol" },
-@@ -990,24 +1013,29 @@ struct protocol_list {
- { 0x8281, "MPLSCP" },
- { 0x8285, "IEEE p1284.4 standard - Protocol Control" },
- { 0x8287, "ETSI TETRA TNP1 Control Protocol" },
-+#endif
- { 0x8289, "Multichannel Flow Treatment Protocol" },
- { 0xc021, "Link Control Protocol" },
- { 0xc023, "Password Authentication Protocol" },
- { 0xc025, "Link Quality Report" },
-+#if 0
- { 0xc027, "Shiva Password Authentication Protocol" },
- { 0xc029, "CallBack Control Protocol (CBCP)" },
- { 0xc02b, "BACP Bandwidth Allocation Control Protocol" },
- { 0xc02d, "BAP" },
-+#endif
- { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" },
- { 0xc081, "Container Control Protocol" },
- { 0xc223, "Challenge Handshake Authentication Protocol" },
- { 0xc225, "RSA Authentication Protocol" },
- { 0xc227, "Extensible Authentication Protocol" },
-+#if 0
- { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" },
- { 0xc26f, "Stampede Bridging Authorization Protocol" },
- { 0xc281, "Proprietary Authentication Protocol" },
- { 0xc283, "Proprietary Authentication Protocol" },
- { 0xc481, "Proprietary Node ID Authentication Protocol" },
-+#endif
- { 0, NULL },
- };
-
diff --git a/package/ppp/patches/405-no_multilink_option.patch b/package/ppp/patches/405-no_multilink_option.patch
deleted file mode 100644
index 97a79c474a..0000000000
--- a/package/ppp/patches/405-no_multilink_option.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-pppd: Support "nomp" option even if multilink support is off
-
-This patch moves the "nomp" option entry outside of the defines protecting
-the multilink specific code. The motivation is to allow "nomp" even if pppd
-does not support multilink, so that controlling programs can unconditionally
-pass it to pppd regardless of the compile time features.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/pppd/options.c
-+++ b/pppd/options.c
-@@ -318,13 +318,14 @@ option_t general_options[] = {
- "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
- { "nomultilink", o_bool, &multilink,
- "Disable multilink operation", OPT_PRIOSUB | 0 },
-- { "nomp", o_bool, &multilink,
-- "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
-
- { "bundle", o_string, &bundle_name,
- "Bundle name for multilink", OPT_PRIO },
- #endif /* HAVE_MULTILINK */
-
-+ { "nomp", o_bool, &multilink,
-+ "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
-+
- #ifdef PLUGIN
- { "plugin", o_special, (void *)loadplugin,
- "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },
diff --git a/package/ppp/patches/430-pppol2tpv3-struct.patch b/package/ppp/patches/430-pppol2tpv3-struct.patch
deleted file mode 100644
index 4f517df764..0000000000
--- a/package/ppp/patches/430-pppol2tpv3-struct.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-pppol2tp: Provide struct pppol2tpv3_addr to align with Linux
-
-The struct pppol2tpv3_addr is referenced in the current Linux kernel sources
-but not provided by the shipped kernel headers, add it.
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
---- a/include/linux/if_pppol2tp.h
-+++ b/include/linux/if_pppol2tp.h
-@@ -32,6 +32,20 @@ struct pppol2tp_addr
- __u16 d_tunnel, d_session; /* For sending outgoing packets */
- };
-
-+/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
-+ * bits. So we need a different sockaddr structure.
-+ */
-+struct pppol2tpv3_addr {
-+ pid_t pid; /* pid that owns the fd.
-+ * 0 => current */
-+ int fd; /* FD of UDP or IP socket to use */
-+
-+ struct sockaddr_in addr; /* IP address and port to send to */
-+
-+ __u32 s_tunnel, s_session; /* For matching incoming packets */
-+ __u32 d_tunnel, d_session; /* For sending outgoing packets */
-+};
-+
- /* Socket options:
- * DEBUG - bitmask of debug message categories
- * SENDSEQ - 0 => don't send packets with sequence numbers
diff --git a/package/ppp/patches/500-add-pptp-plugin.patch b/package/ppp/patches/500-add-pptp-plugin.patch
deleted file mode 100644
index d984e1b162..0000000000
--- a/package/ppp/patches/500-add-pptp-plugin.patch
+++ /dev/null
@@ -1,3065 +0,0 @@
---- a/configure
-+++ b/configure
-@@ -195,7 +195,7 @@ if [ -d "$ksrc" ]; then
- mkmkf $ksrc/Makedefs$compiletype Makedefs.com
- for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe \
- pppd/plugins/radius pppd/plugins/pppoatm \
-- pppd/plugins/pppol2tp; do
-+ pppd/plugins/pppol2tp pppd/plugins/pptp ; do
- mkmkf $dir/Makefile.$makext $dir/Makefile
- done
- if [ -f $ksrc/Makefile.$makext$archvariant ]; then
---- a/pppd/plugins/Makefile.linux
-+++ b/pppd/plugins/Makefile.linux
-@@ -9,7 +9,7 @@ BINDIR = $(DESTDIR)/sbin
- MANDIR = $(DESTDIR)/share/man/man8
- LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
-
--SUBDIRS := rp-pppoe pppoatm pppol2tp
-+SUBDIRS := rp-pppoe pppoatm pppol2tp pptp
- # Uncomment the next line to include the radius authentication plugin
- SUBDIRS += radius
- PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
---- /dev/null
-+++ b/pppd/plugins/pptp/Makefile.linux
-@@ -0,0 +1,31 @@
-+#
-+# This program may be distributed according to the terms of the GNU
-+# General Public License, version 2 or (at your option) any later version.
-+#
-+# $Id: Makefile.linux,v 1.9 2012/05/04 21:48:00 dgolle Exp $
-+#***********************************************************************
-+
-+DESTDIR = $(INSTROOT)@DESTDIR@
-+LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION)
-+
-+PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h)
-+
-+INSTALL = install
-+
-+COPTS=-O2 -g
-+CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC -DPPPD_VERSION=\"$(PPPDVERSION)\"
-+all: pptp.so
-+
-+%.o: %.c
-+ $(CC) $(CFLAGS) -c -o $@ $<
-+
-+pptp.so: dirutil.o orckit_quirks.o pptp.o pptp_callmgr.o pptp_ctrl.o pptp_quirks.o util.o vector.o
-+ $(CC) -o pptp.so -shared dirutil.o orckit_quirks.o pptp.o pptp_callmgr.o pptp_ctrl.o pptp_quirks.o util.o vector.o
-+
-+install: all
-+ $(INSTALL) -d -m 755 $(LIBDIR)
-+ $(INSTALL) -c -m 4550 pptp.so $(LIBDIR)
-+
-+clean:
-+ rm -f *.o *.so
-+
---- /dev/null
-+++ b/pppd/plugins/pptp/dirutil.c
-@@ -0,0 +1,68 @@
-+/* dirutil.c ... directory utilities.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: dirutil.c,v 1.2 2003/06/17 17:25:47 reink Exp $
-+ */
-+
-+#include <sys/stat.h>
-+#include <sys/types.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include "dirutil.h"
-+
-+/* Returned malloc'ed string representing basename */
-+char *basenamex(char *pathname)
-+{
-+ char *dup = strdup(pathname);
-+ char *ptr = strrchr(stripslash(dup), '/');
-+ if (ptr == NULL) return dup;
-+ ptr = strdup(ptr+1);
-+ free(dup);
-+ return ptr;
-+}
-+
-+/* Return malloc'ed string representing directory name (no trailing slash) */
-+char *dirnamex(char *pathname)
-+{
-+ char *dup = strdup(pathname);
-+ char *ptr = strrchr(stripslash(dup), '/');
-+ if (ptr == NULL) { free(dup); return strdup("."); }
-+ if (ptr == dup && dup[0] == '/') ptr++;
-+ *ptr = '\0';
-+ return dup;
-+}
-+
-+/* In-place modify a string to remove trailing slashes. Returns arg.
-+ * stripslash("/") returns "/";
-+ */
-+char *stripslash(char *pathname) {
-+ int len = strlen(pathname);
-+ while (len > 1 && pathname[len - 1] == '/')
-+ pathname[--len] = '\0';
-+ return pathname;
-+}
-+
-+/* ensure dirname exists, creating it if necessary. */
-+int make_valid_path(char *dir, mode_t mode)
-+{
-+ struct stat st;
-+ char *tmp = NULL, *path = stripslash(strdup(dir));
-+ int retval;
-+ if (stat(path, &st) == 0) { /* file exists */
-+ if (S_ISDIR(st.st_mode)) { retval = 1; goto end; }
-+ else { retval = 0; goto end; } /* not a directory. Oops. */
-+ }
-+ /* Directory doesn't exist. Let's make it. */
-+ /* Make parent first. */
-+ if (!make_valid_path(tmp = dirnamex(path), mode)) { retval = 0; goto end; }
-+ /* Now make this 'un. */
-+ if (mkdir(path, mode) < 0) { retval = 0; goto end; }
-+ /* Success. */
-+ retval = 1;
-+
-+end:
-+ if (tmp != NULL) free(tmp);
-+ if (path != NULL) free(path);
-+ return retval;
-+}
---- /dev/null
-+++ b/pppd/plugins/pptp/dirutil.h
-@@ -0,0 +1,14 @@
-+/* dirutil.h ... directory utilities.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: dirutil.h,v 1.1.1.1 2000/12/23 08:19:51 scott Exp $
-+ */
-+
-+/* Returned malloc'ed string representing basename */
-+char *basenamex(char *pathname);
-+/* Return malloc'ed string representing directory name (no trailing slash) */
-+char *dirnamex(char *pathname);
-+/* In-place modify a string to remove trailing slashes. Returns arg. */
-+char *stripslash(char *pathname);
-+/* ensure dirname exists, creating it if necessary. */
-+int make_valid_path(char *dirname, mode_t mode);
---- /dev/null
-+++ b/pppd/plugins/pptp/orckit_quirks.c
-@@ -0,0 +1,86 @@
-+/* orckit_quirks.c ...... fix quirks in orckit adsl modems
-+ * mulix <mulix@actcom.co.il>
-+ *
-+ * $Id: orckit_quirks.c,v 1.3 2002/03/01 01:23:36 quozl Exp $
-+ */
-+
-+#include <string.h>
-+#include <sys/types.h>
-+#include <netinet/in.h>
-+#include "pptp_msg.h"
-+#include "pptp_options.h"
-+#include "pptp_ctrl.h"
-+#include "util.h"
-+
-+
-+
-+/* return 0 on success, non zero otherwise */
-+int
-+orckit_atur3_build_hook(struct pptp_out_call_rqst* packet)
-+{
-+ unsigned int name_length = 10;
-+
-+ struct pptp_out_call_rqst fixed_packet = {
-+ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST),
-+ 0, /* hton16(call->callid) */
-+ 0, /* hton16(call->sernum) */
-+ hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX),
-+ hton32(PPTP_BEARER_DIGITAL), hton32(PPTP_FRAME_ANY),
-+ hton16(PPTP_WINDOW), 0, hton16(name_length), 0,
-+ {'R','E','L','A','Y','_','P','P','P','1',0}, {0}
-+ };
-+
-+ if (!packet)
-+ return -1;
-+
-+ memcpy(packet, &fixed_packet, sizeof(*packet));
-+
-+ return 0;
-+}
-+
-+/* return 0 on success, non zero otherwise */
-+int
-+orckit_atur3_set_link_hook(struct pptp_set_link_info* packet,
-+ int peer_call_id)
-+{
-+ struct pptp_set_link_info fixed_packet = {
-+ PPTP_HEADER_CTRL(PPTP_SET_LINK_INFO),
-+ hton16(peer_call_id),
-+ 0,
-+ 0xffffffff,
-+ 0xffffffff};
-+
-+ if (!packet)
-+ return -1;
-+
-+ memcpy(packet, &fixed_packet, sizeof(*packet));
-+ return 0;
-+}
-+
-+/* return 0 on success, non 0 otherwise */
-+int
-+orckit_atur3_start_ctrl_conn_hook(struct pptp_start_ctrl_conn* packet)
-+{
-+ struct pptp_start_ctrl_conn fixed_packet = {
-+ {0}, /* we'll set the header later */
-+ hton16(PPTP_VERSION), 0, 0,
-+ hton32(PPTP_FRAME_ASYNC), hton32(PPTP_BEARER_ANALOG),
-+ hton16(0) /* max channels */,
-+ hton16(0x6021),
-+ {'R','E','L','A','Y','_','P','P','P','1',0}, /* hostname */
-+ {'M','S',' ','W','i','n',' ','N','T',0} /* vendor */
-+ };
-+
-+ if (!packet)
-+ return -1;
-+
-+ /* grab the header from the original packet, since we dont
-+ know if this is a request or a reply */
-+ memcpy(&fixed_packet.header, &packet->header, sizeof(struct pptp_header));
-+
-+ /* and now overwrite the full packet, effectively preserving the header */
-+ memcpy(packet, &fixed_packet, sizeof(*packet));
-+ return 0;
-+}
-+
-+
---- /dev/null
-+++ b/pppd/plugins/pptp/orckit_quirks.h
-@@ -0,0 +1,27 @@
-+/* orckit_quirks.h ...... fix quirks in orckit adsl modems
-+ * mulix <mulix@actcom.co.il>
-+ *
-+ * $Id: orckit_quirks.h,v 1.2 2001/11/23 03:42:51 quozl Exp $
-+ */
-+
-+#ifndef INC_ORCKIT_QUIRKS_H_
-+#define INC_ORCKIT_QUIRKS_H_
-+
-+#include "pptp_options.h"
-+#include "pptp_ctrl.h"
-+#include "pptp_msg.h"
-+
-+/* return 0 on success, non zero otherwise */
-+int
-+orckit_atur3_build_hook(struct pptp_out_call_rqst* packt);
-+
-+/* return 0 on success, non zero otherwise */
-+int
-+orckit_atur3_set_link_hook(struct pptp_set_link_info* packet,
-+ int peer_call_id);
-+
-+/* return 0 on success, non zero otherwise */
-+int
-+orckit_atur3_start_ctrl_conn_hook(struct pptp_start_ctrl_conn* packet);
-+
-+#endif /* INC_ORCKIT_QUIRKS_H_ */
---- /dev/null
-+++ b/pppd/plugins/pptp/pppd-pptp.8
-@@ -0,0 +1,68 @@
-+.\" manual page [] for PPTP plugin for pppd 2.4
-+.\" $Id: pppd-pptp.8,v 1.0 2007/10/17 13:27:17 kad Exp $
-+.\" SH section heading
-+.\" SS subsection heading
-+.\" LP paragraph
-+.\" IP indented paragraph
-+.\" TP hanging label
-+.TH PPPD-PPTP 8
-+.SH NAME
-+pptp.so \- PPTP VPN plugin for
-+.BR pppd (8)
-+.SH SYNOPSIS
-+.B pppd
-+[
-+.I options
-+]
-+plugin pptp.so
-+.SH DESCRIPTION
-+.LP
-+The PPTP plugin for pppd performs interaction with pptp kernel module
-+and has built-in call manager (client part of PPTP).
-+It pasees necessary paremeters from \fIoptions\fR into kernel module
-+to configure ppp-pptp channel. If it runs in client mode, then additionally
-+call manager starts up. PPTPD daemon automaticaly invokes this plugin
-+in server mode and passes necessary options, so additional configuration
-+is not needed.
-+
-+.SH OPTIONS for client mode
-+The PPTP plugin introduces one additional pppd option:
-+.TP
-+.BI "pptp_server " server " (required)"
-+Specifies ip address or hostname of pptp server.
-+.TP
-+.BI "pptp_window " packets " (optional)"
-+The amount of sliding window size.
-+Set to 0 to turn off sliding window.
-+ to 3-10 for low speed connections.
-+ to >10 for hi speed connections.
-+Default is 50
-+.TP
-+.BI "pptp_phone " phone " (optional)"
-+The phone string that sended to pptp server.
-+.SH USAGE
-+Sample configuration file:
-+.nf
-+plugin "pptp.so"
-+pptp_server 192.168.0.1
-+pptp_window 100
-+name myname
-+remotename pptp
-+noauth
-+refuse-eap
-+refuse-chap
-+refuse-mschap
-+nobsdcomp
-+nodeflate
-+novj
-+novjccomp
-+require-mppe-128
-+lcp-echo-interval 20
-+lcp-echo-failure 3
-+.fi
-+
-+.SH SEE ALSO
-+.BR pppd (8) " " pptpd (8) " " pptpd.conf (5)
-+
-+.SH AUTHOR
-+xeb xeb@mail.ru
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp.c
-@@ -0,0 +1,323 @@
-+/***************************************************************************
-+ * Copyright (C) 2006 by Kozlov D. <xeb@mail.ru> *
-+ * some cleanup done (C) 2012 by Daniel Golle <dgolle@allnet.de> *
-+ * *
-+ * This program is free software; you can redistribute it and/or modify *
-+ * it under the terms of the GNU General Public License as published by *
-+ * the Free Software Foundation; either version 2 of the License, or *
-+ * (at your option) any later version. *
-+ * *
-+ * This program is distributed in the hope that it will be useful, *
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-+ * GNU General Public License for more details. *
-+ * *
-+ * You should have received a copy of the GNU General Public License *
-+ * along with this program; if not, write to the *
-+ * Free Software Foundation, Inc., *
-+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
-+ ***************************************************************************/
-+
-+#define PPTP_VERSION "1.00"
-+
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
-+#endif
-+
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <sys/un.h>
-+#include <netdb.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <syslog.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <sys/wait.h>
-+#include <sys/ioctl.h>
-+
-+#include "pppd.h"
-+#include "fsm.h"
-+#include "lcp.h"
-+#include "ipcp.h"
-+#include "ccp.h"
-+#include "pathnames.h"
-+
-+#include "pptp_callmgr.h"
-+#include <net/if.h>
-+#include <net/ethernet.h>
-+#include <linux/if_pppox.h>
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+
-+
-+extern char** environ;
-+
-+char pppd_version[] = PPPD_VERSION;
-+extern int new_style_driver;
-+
-+
-+char *pptp_server = NULL;
-+char *pptp_client = NULL;
-+char *pptp_phone = NULL;
-+int pptp_window=50;
-+int pptp_sock=-1;
-+struct in_addr localbind = { INADDR_NONE };
-+
-+static int callmgr_sock;
-+static int pptp_fd;
-+int call_ID;
-+
-+static int open_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window);
-+static void launch_callmgr(int call_is,struct in_addr inetaddr, char *phonenr,int window);
-+static int get_call_id(int sock, pid_t gre, pid_t pppd, u_int16_t *peer_call_id);
-+
-+static option_t Options[] =
-+{
-+ { "pptp_server", o_string, &pptp_server,
-+ "PPTP Server" },
-+ { "pptp_client", o_string, &pptp_client,
-+ "PPTP Client" },
-+ { "pptp_sock",o_int, &pptp_sock,
-+ "PPTP socket" },
-+ { "pptp_phone", o_string, &pptp_phone,
-+ "PPTP Phone number" },
-+ { "pptp_window",o_int, &pptp_window,
-+ "PPTP window" },
-+ { NULL }
-+};
-+
-+static int pptp_connect(void);
-+static void pptp_disconnect(void);
-+
-+struct channel pptp_channel = {
-+ options: Options,
-+ check_options: NULL,
-+ connect: &pptp_connect,
-+ disconnect: &pptp_disconnect,
-+ establish_ppp: &generic_establish_ppp,
-+ disestablish_ppp: &generic_disestablish_ppp,
-+ close: NULL,
-+ cleanup: NULL
-+};
-+
-+static int pptp_start_server(void)
-+{
-+ pptp_fd=pptp_sock;
-+ sprintf(ppp_devnam,"pptp (%s)",pptp_client);
-+
-+ return pptp_fd;
-+}
-+static int pptp_start_client(void)
-+{
-+ socklen_t len;
-+ struct sockaddr_pppox src_addr,dst_addr;
-+ struct hostent *hostinfo;
-+
-+ hostinfo=gethostbyname(pptp_server);
-+ if (!hostinfo)
-+ {
-+ error("PPTP: Unknown host %s\n", pptp_server);
-+ return -1;
-+ }
-+ dst_addr.sa_addr.pptp.sin_addr=*(struct in_addr*)hostinfo->h_addr;
-+ {
-+ int sock;
-+ struct sockaddr_in addr;
-+ len=sizeof(addr);
-+ addr.sin_addr=dst_addr.sa_addr.pptp.sin_addr;
-+ addr.sin_family=AF_INET;
-+ addr.sin_port=htons(1700);
-+ sock=socket(AF_INET,SOCK_DGRAM,0);
-+ if (connect(sock,(struct sockaddr*)&addr,sizeof(addr)))
-+ {
-+ close(sock);
-+ error("PPTP: connect failed (%s)\n",strerror(errno));
-+ return -1;
-+ }
-+ getsockname(sock,(struct sockaddr*)&addr,&len);
-+ src_addr.sa_addr.pptp.sin_addr=addr.sin_addr;
-+ close(sock);
-+ }
-+
-+ src_addr.sa_family=AF_PPPOX;
-+ src_addr.sa_protocol=PX_PROTO_PPTP;
-+ src_addr.sa_addr.pptp.call_id=0;
-+
-+ dst_addr.sa_family=AF_PPPOX;
-+ dst_addr.sa_protocol=PX_PROTO_PPTP;
-+ dst_addr.sa_addr.pptp.call_id=0;
-+
-+ pptp_fd=socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_PPTP);
-+ if (pptp_fd<0)
-+ {
-+ error("PPTP: failed to create PPTP socket (%s)\n",strerror(errno));
-+ return -1;
-+ }
-+ if (bind(pptp_fd,(struct sockaddr*)&src_addr,sizeof(src_addr)))
-+ {
-+ close(pptp_fd);
-+ error("PPTP: failed to bind PPTP socket (%s)\n",strerror(errno));
-+ return -1;
-+ }
-+ len=sizeof(src_addr);
-+ getsockname(pptp_fd,(struct sockaddr*)&src_addr,&len);
-+ call_ID=src_addr.sa_addr.pptp.call_id;
-+
-+ do {
-+ /*
-+ * Open connection to call manager (Launch call manager if necessary.)
-+ */
-+ callmgr_sock = open_callmgr(src_addr.sa_addr.pptp.call_id,dst_addr.sa_addr.pptp.sin_addr, pptp_phone, pptp_window);
-+ if (callmgr_sock<0)
-+ {
-+ close(pptp_fd);
-+ return -1;
-+ }
-+ /* Exchange PIDs, get call ID */
-+ } while (get_call_id(callmgr_sock, getpid(), getpid(), &dst_addr.sa_addr.pptp.call_id) < 0);
-+
-+ if (connect(pptp_fd,(struct sockaddr*)&dst_addr,sizeof(dst_addr)))
-+ {
-+ close(callmgr_sock);
-+ close(pptp_fd);
-+ error("PPTP: failed to connect PPTP socket (%s)\n",strerror(errno));
-+ return -1;
-+ }
-+
-+ sprintf(ppp_devnam,"pptp (%s)",pptp_server);
-+
-+ return pptp_fd;
-+}
-+static int pptp_connect(void)
-+{
-+ if ((!pptp_server && !pptp_client) || (pptp_server && pptp_client))
-+ {
-+ fatal("PPTP: unknown mode (you must specify pptp_server or pptp_client option)");
-+ return -1;
-+ }
-+
-+ if (pptp_server) return pptp_start_client();
-+ return pptp_start_server();
-+}
-+
-+static void pptp_disconnect(void)
-+{
-+ if (pptp_server) close(callmgr_sock);
-+ close(pptp_fd);
-+}
-+
-+static int open_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window)
-+{
-+ /* Try to open unix domain socket to call manager. */
-+ struct sockaddr_un where;
-+ const int NUM_TRIES = 3;
-+ int i, fd;
-+ pid_t pid;
-+ int status;
-+ /* Open socket */
-+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-+ {
-+ fatal("Could not create unix domain socket: %s", strerror(errno));
-+ }
-+ /* Make address */
-+ callmgr_name_unixsock(&where, inetaddr, localbind);
-+ for (i = 0; i < NUM_TRIES; i++)
-+ {
-+ if (connect(fd, (struct sockaddr *) &where, sizeof(where)) < 0)
-+ {
-+ /* couldn't connect. We'll have to launch this guy. */
-+
-+ unlink (where.sun_path);
-+
-+ /* fork and launch call manager process */
-+ switch (pid = fork())
-+ {
-+ case -1: /* failure */
-+ fatal("fork() to launch call manager failed.");
-+ case 0: /* child */
-+ {
-+ /* close the pty and gre in the call manager */
-+ close(fd);
-+ close(pptp_fd);
-+ launch_callmgr(call_id,inetaddr,phonenr,window);
-+ }
-+ default: /* parent */
-+ waitpid(pid, &status, 0);
-+ if (status!= 0)
-+ {
-+ close(fd);
-+ error("Call manager exited with error %d", status);
-+ return -1;
-+ }
-+ break;
-+ }
-+ sleep(1);
-+ }
-+ else return fd;
-+ }
-+ close(fd);
-+ error("Could not launch call manager after %d tries.", i);
-+ return -1; /* make gcc happy */
-+}
-+
-+/*** call the call manager main ***********************************************/
-+static void launch_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window)
-+{
-+ dbglog("pptp: call manager for %s\n", inet_ntoa(inetaddr));
-+ dbglog("window size:\t%d\n",window);
-+ if (phonenr) dbglog("phone number:\t'%s'\n",phonenr);
-+ dbglog("call id:\t%d\n",call_id);
-+ exit(callmgr_main(inetaddr, phonenr, window, call_id));
-+}
-+
-+/*** exchange data with the call manager *************************************/
-+/* XXX need better error checking XXX */
-+static int get_call_id(int sock, pid_t gre, pid_t pppd,
-+ u_int16_t *peer_call_id)
-+{
-+ u_int16_t m_call_id, m_peer_call_id;
-+ /* write pid's to socket */
-+ /* don't bother with network byte order, because pid's are meaningless
-+ * outside the local host.
-+ */
-+ int rc;
-+ rc = write(sock, &gre, sizeof(gre));
-+ if (rc != sizeof(gre))
-+ return -1;
-+ rc = write(sock, &pppd, sizeof(pppd));
-+ if (rc != sizeof(pppd))
-+ return -1;
-+ rc = read(sock, &m_call_id, sizeof(m_call_id));
-+ if (rc != sizeof(m_call_id))
-+ return -1;
-+ rc = read(sock, &m_peer_call_id, sizeof(m_peer_call_id));
-+ if (rc != sizeof(m_peer_call_id))
-+ return -1;
-+ /*
-+ * XXX FIXME ... DO ERROR CHECKING & TIME-OUTS XXX
-+ * (Rhialto: I am assuming for now that timeouts are not relevant
-+ * here, because the read and write calls would return -1 (fail) when
-+ * the peer goes away during the process. We know it is (or was)
-+ * running because the connect() call succeeded.)
-+ * (James: on the other hand, if the route to the peer goes away, we
-+ * wouldn't get told by read() or write() for quite some time.)
-+ */
-+ *peer_call_id = m_peer_call_id;
-+ return 0;
-+}
-+
-+void plugin_init(void)
-+{
-+ add_options(Options);
-+
-+ info("PPTP plugin version %s", PPTP_VERSION);
-+
-+ the_channel = &pptp_channel;
-+ modem = 0;
-+}
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_callmgr.c
-@@ -0,0 +1,381 @@
-+/* pptp_callmgr.c ... Call manager for PPTP connections.
-+ * Handles TCP port 1723 protocol.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_callmgr.c,v 1.20 2005/03/31 07:42:39 quozl Exp $
-+ */
-+#include <signal.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <sys/un.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <assert.h>
-+#include <setjmp.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include "pptp_callmgr.h"
-+#include "pptp_ctrl.h"
-+#include "pptp_msg.h"
-+#include "dirutil.h"
-+#include "vector.h"
-+#include "util.h"
-+#include "pppd.h"
-+
-+extern struct in_addr localbind; /* from pptp.c */
-+extern int call_ID;
-+
-+int open_inetsock(struct in_addr inetaddr);
-+int open_unixsock(struct in_addr inetaddr);
-+void close_inetsock(int fd, struct in_addr inetaddr);
-+void close_unixsock(int fd, struct in_addr inetaddr);
-+
-+sigjmp_buf callmgr_env;
-+
-+void callmgr_sighandler(int sig) {
-+ /* TODO: according to signal(2), siglongjmp() is unsafe used here */
-+ siglongjmp (callmgr_env, 1);
-+}
-+
-+void callmgr_do_nothing(int sig) {
-+ /* do nothing signal handler */
-+}
-+
-+struct local_callinfo {
-+ int unix_sock;
-+ pid_t pid[2];
-+};
-+
-+struct local_conninfo {
-+ VECTOR * call_list;
-+ fd_set * call_set;
-+};
-+
-+/* Call callback */
-+void call_callback(PPTP_CONN *conn, PPTP_CALL *call, enum call_state state)
-+{
-+ struct local_callinfo *lci;
-+ struct local_conninfo *conninfo;
-+ u_int16_t call_id[2];
-+ switch(state) {
-+ case CALL_OPEN_DONE:
-+ /* okey dokey. This means that the call_id and peer_call_id are
-+ * now valid, so lets send them on to our friends who requested
-+ * this call. */
-+ lci = pptp_call_closure_get(conn, call); assert(lci != NULL);
-+ pptp_call_get_ids(conn, call, &call_id[0], &call_id[1]);
-+ write(lci->unix_sock, &call_id, sizeof(call_id));
-+ /* Our duty to the fatherland is now complete. */
-+ break;
-+ case CALL_OPEN_FAIL:
-+ case CALL_CLOSE_RQST:
-+ case CALL_CLOSE_DONE:
-+ /* don't need to do anything here, except make sure tables
-+ * are sync'ed */
-+ dbglog("Closing connection (call state)");
-+ conninfo = pptp_conn_closure_get(conn);
-+ lci = pptp_call_closure_get(conn, call);
-+ assert(lci != NULL && conninfo != NULL);
-+ if (vector_contains(conninfo->call_list, lci->unix_sock)) {
-+ vector_remove(conninfo->call_list, lci->unix_sock);
-+ close(lci->unix_sock);
-+ FD_CLR(lci->unix_sock, conninfo->call_set);
-+ }
-+ break;
-+ default:
-+ dbglog("Unhandled call callback state [%d].", (int) state);
-+ break;
-+ }
-+}
-+
-+/******************************************************************************
-+ * NOTE ABOUT 'VOLATILE':
-+ * several variables here get a volatile qualifier to silence warnings
-+ * from older (before 3.0) gccs. if the longjmp stuff is removed,
-+ * the volatile qualifiers should be removed as well.
-+ *****************************************************************************/
-+
-+/*** Call Manager *************************************************************/
-+int callmgr_main(struct in_addr inetaddr, char phonenr[], int window, int pcallid)
-+{
-+ int inet_sock, unix_sock;
-+ fd_set call_set;
-+ PPTP_CONN * conn;
-+ VECTOR * call_list;
-+ int max_fd = 0;
-+ volatile int first = 1;
-+ int retval;
-+ int i;
-+ if (pcallid>0) call_ID=pcallid;
-+
-+ /* Step 1: Open sockets. */
-+ if ((inet_sock = open_inetsock(inetaddr)) < 0)
-+ fatal("Could not open control connection to %s", inet_ntoa(inetaddr));
-+ dbglog("control connection");
-+ if ((unix_sock = open_unixsock(inetaddr)) < 0)
-+ fatal("Could not open unix socket for %s", inet_ntoa(inetaddr));
-+ /* Step 1b: FORK and return status to calling process. */
-+ dbglog("unix_sock");
-+
-+ switch (fork()) {
-+ case 0: /* child. stick around. */
-+ break;
-+ case -1: /* failure. Fatal. */
-+ fatal("Could not fork.");
-+ default: /* Parent. Return status to caller. */
-+ exit(0);
-+ }
-+ /* re-open stderr as /dev/null to release it */
-+ file2fd("/dev/null", "wb", STDERR_FILENO);
-+ /* Step 1c: Clean up unix socket on TERM */
-+ if (sigsetjmp(callmgr_env, 1) != 0)
-+ goto cleanup;
-+ signal(SIGINT, callmgr_sighandler);
-+ signal(SIGTERM, callmgr_sighandler);
-+ signal(SIGPIPE, callmgr_do_nothing);
-+ signal(SIGUSR1, callmgr_do_nothing); /* signal state change
-+ wake up accept */
-+ /* Step 2: Open control connection and register callback */
-+ if ((conn = pptp_conn_open(inet_sock, 1, NULL/* callback */)) == NULL) {
-+ close(unix_sock); close(inet_sock); fatal("Could not open connection.");
-+ }
-+ FD_ZERO(&call_set);
-+ call_list = vector_create();
-+ {
-+ struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
-+ if (conninfo == NULL) {
-+ close(unix_sock); close(inet_sock); fatal("No memory.");
-+ }
-+ conninfo->call_list = call_list;
-+ conninfo->call_set = &call_set;
-+ pptp_conn_closure_put(conn, conninfo);
-+ }
-+ if (sigsetjmp(callmgr_env, 1) != 0) goto shutdown;
-+ /* Step 3: Get FD_SETs */
-+ max_fd = unix_sock;
-+ do {
-+ int rc;
-+ fd_set read_set = call_set, write_set;
-+ FD_ZERO (&write_set);
-+ if (pptp_conn_established(conn)) {
-+ FD_SET (unix_sock, &read_set);
-+ if (unix_sock > max_fd) max_fd = unix_sock;
-+ }
-+ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
-+ for (; max_fd > 0 ; max_fd--) {
-+ if (FD_ISSET (max_fd, &read_set) ||
-+ FD_ISSET (max_fd, &write_set))
-+ break;
-+ }
-+ /* Step 4: Wait on INET or UNIX event */
-+ if ((rc = select(max_fd + 1, &read_set, &write_set, NULL, NULL)) <0) {
-+ if (errno == EBADF) break;
-+ /* a signal or somesuch. */
-+ continue;
-+ }
-+ /* Step 5a: Handle INET events */
-+ rc = pptp_dispatch(conn, &read_set, &write_set);
-+ if (rc < 0)
-+ break;
-+ /* Step 5b: Handle new connection to UNIX socket */
-+ if (FD_ISSET(unix_sock, &read_set)) {
-+ /* New call! */
-+ struct sockaddr_un from;
-+ int len = sizeof(from);
-+ PPTP_CALL * call;
-+ struct local_callinfo *lci;
-+ int s;
-+ /* Accept the socket */
-+ FD_CLR (unix_sock, &read_set);
-+ if ((s = accept(unix_sock, (struct sockaddr *) &from, &len)) < 0) {
-+ warn("Socket not accepted: %s", strerror(errno));
-+ goto skip_accept;
-+ }
-+ /* Allocate memory for local call information structure. */
-+ if ((lci = malloc(sizeof(*lci))) == NULL) {
-+ warn("Out of memory."); close(s); goto skip_accept;
-+ }
-+ lci->unix_sock = s;
-+ /* Give the initiator time to write the PIDs while we open
-+ * the call */
-+ call = pptp_call_open(conn, call_ID,call_callback, phonenr,window);
-+ /* Read and store the associated pids */
-+ read(s, &lci->pid[0], sizeof(lci->pid[0]));
-+ read(s, &lci->pid[1], sizeof(lci->pid[1]));
-+ /* associate the local information with the call */
-+ pptp_call_closure_put(conn, call, (void *) lci);
-+ /* The rest is done on callback. */
-+ /* Keep alive; wait for close */
-+ retval = vector_insert(call_list, s, call); assert(retval);
-+ if (s > max_fd) max_fd = s;
-+ FD_SET(s, &call_set);
-+ first = 0;
-+ }
-+skip_accept: /* Step 5c: Handle socket close */
-+ for (i = 0; i < max_fd + 1; i++)
-+ if (FD_ISSET(i, &read_set)) {
-+ /* close it */
-+ PPTP_CALL * call;
-+ retval = vector_search(call_list, i, &call);
-+ if (retval) {
-+ struct local_callinfo *lci =
-+ pptp_call_closure_get(conn, call);
-+ dbglog("Closing connection (unhandled)");
-+ free(lci);
-+ /* soft shutdown. Callback will do hard shutdown later */
-+ pptp_call_close(conn, call);
-+ vector_remove(call_list, i);
-+ }
-+ FD_CLR(i, &call_set);
-+ close(i);
-+ }
-+ } while (vector_size(call_list) > 0 || first);
-+shutdown:
-+ {
-+ int rc;
-+ fd_set read_set, write_set;
-+ struct timeval tv;
-+ signal(SIGINT, callmgr_do_nothing);
-+ signal(SIGTERM, callmgr_do_nothing);
-+ /* warn("Shutdown"); */
-+ /* kill all open calls */
-+ for (i = 0; i < vector_size(call_list); i++) {
-+ PPTP_CALL *call = vector_get_Nth(call_list, i);
-+ dbglog("Closing connection (shutdown)");
-+ pptp_call_close(conn, call);
-+ }
-+ /* attempt to dispatch these messages */
-+ FD_ZERO(&read_set);
-+ FD_ZERO(&write_set);
-+ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
-+ tv.tv_sec = 0;
-+ tv.tv_usec = 0;
-+ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
-+ rc = pptp_dispatch(conn, &read_set, &write_set);
-+ if (rc > 0) {
-+ /* wait for a respond, a timeout because there might not be one */
-+ FD_ZERO(&read_set);
-+ FD_ZERO(&write_set);
-+ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
-+ tv.tv_sec = 2;
-+ tv.tv_usec = 0;
-+ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
-+ rc = pptp_dispatch(conn, &read_set, &write_set);
-+ if (rc > 0) {
-+ if (i > 0) sleep(2);
-+ /* no more open calls. Close the connection. */
-+ pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN);
-+ /* wait for a respond, a timeout because there might not be one */
-+ FD_ZERO(&read_set);
-+ FD_ZERO(&write_set);
-+ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
-+ tv.tv_sec = 2;
-+ tv.tv_usec = 0;
-+ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
-+ pptp_dispatch(conn, &read_set, &write_set);
-+ if (rc > 0) sleep(2);
-+ }
-+ }
-+ /* with extreme prejudice */
-+ pptp_conn_destroy(conn);
-+ vector_destroy(call_list);
-+ }
-+cleanup:
-+ signal(SIGINT, callmgr_do_nothing);
-+ signal(SIGTERM, callmgr_do_nothing);
-+ close_inetsock(inet_sock, inetaddr);
-+ close_unixsock(unix_sock, inetaddr);
-+ return 0;
-+}
-+
-+/*** open_inetsock ************************************************************/
-+int open_inetsock(struct in_addr inetaddr)
-+{
-+ struct sockaddr_in dest, src;
-+ int s;
-+ dest.sin_family = AF_INET;
-+ dest.sin_port = htons(PPTP_PORT);
-+ dest.sin_addr = inetaddr;
-+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-+ warn("socket: %s", strerror(errno));
-+ return s;
-+ }
-+ if (localbind.s_addr != INADDR_NONE) {
-+ bzero(&src, sizeof(src));
-+ src.sin_family = AF_INET;
-+ src.sin_addr = localbind;
-+ if (bind(s, (struct sockaddr *) &src, sizeof(src)) != 0) {
-+ warn("bind: %s", strerror(errno));
-+ close(s); return -1;
-+ }
-+ }
-+ if (connect(s, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
-+ warn("connect: %s", strerror(errno));
-+ close(s); return -1;
-+ }
-+ return s;
-+}
-+
-+/*** open_unixsock ************************************************************/
-+int open_unixsock(struct in_addr inetaddr)
-+{
-+ struct sockaddr_un where;
-+ struct stat st;
-+ char *dir;
-+ int s;
-+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-+ warn("socket: %s", strerror(errno));
-+ return s;
-+ }
-+ callmgr_name_unixsock( &where, inetaddr, localbind);
-+ if (stat(where.sun_path, &st) >= 0)
-+ {
-+ warn("Call manager for %s is already running.", inet_ntoa(inetaddr));
-+ close(s); return -1;
-+ }
-+ /* Make sure path is valid. */
-+ dir = dirnamex(where.sun_path);
-+ if (!make_valid_path(dir, 0770))
-+ fatal("Could not make path to %s: %s", where.sun_path, strerror(errno));
-+ free(dir);
-+ if (bind(s, (struct sockaddr *) &where, sizeof(where)) < 0) {
-+ warn("bind: %s", strerror(errno));
-+ close(s); return -1;
-+ }
-+ chmod(where.sun_path, 0777);
-+ listen(s, 127);
-+ return s;
-+}
-+
-+/*** close_inetsock ***********************************************************/
-+void close_inetsock(int fd, struct in_addr inetaddr)
-+{
-+ close(fd);
-+}
-+
-+/*** close_unixsock ***********************************************************/
-+void close_unixsock(int fd, struct in_addr inetaddr)
-+{
-+ struct sockaddr_un where;
-+ close(fd);
-+ callmgr_name_unixsock(&where, inetaddr, localbind);
-+ unlink(where.sun_path);
-+}
-+
-+/*** make a unix socket address ***********************************************/
-+void callmgr_name_unixsock(struct sockaddr_un *where,
-+ struct in_addr inetaddr,
-+ struct in_addr localbind)
-+{
-+ char localaddr[16], remoteaddr[16];
-+ where->sun_family = AF_UNIX;
-+ strncpy(localaddr, inet_ntoa(localbind), 16);
-+ strncpy(remoteaddr, inet_ntoa(inetaddr), 16);
-+ snprintf(where->sun_path, sizeof(where->sun_path),
-+ PPTP_SOCKET_PREFIX "%s:%i", remoteaddr,call_ID);
-+}
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_callmgr.h
-@@ -0,0 +1,17 @@
-+/* pptp_callmgr.h ... Call manager for PPTP connections.
-+ * Handles TCP port 1723 protocol.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_callmgr.h,v 1.3 2003/02/17 00:22:17 quozl Exp $
-+ */
-+
-+#define PPTP_SOCKET_PREFIX "/var/run/pptp/"
-+
-+int callmgr_main(struct in_addr inetaddr,
-+ char phonenr[],
-+ int window,
-+ int pcallid);
-+
-+void callmgr_name_unixsock(struct sockaddr_un *where,
-+ struct in_addr inetaddr,
-+ struct in_addr localbind);
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_ctrl.c
-@@ -0,0 +1,1077 @@
-+/* pptp_ctrl.c ... handle PPTP control connection.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_ctrl.c,v 1.31 2005/03/31 07:42:39 quozl Exp $
-+ */
-+
-+#include <errno.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <assert.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <ctype.h>
-+#include <fcntl.h>
-+#include "pptp_msg.h"
-+#include "pptp_ctrl.h"
-+#include "pptp_options.h"
-+#include "vector.h"
-+#include "util.h"
-+#include "pptp_quirks.h"
-+
-+/* BECAUSE OF SIGNAL LIMITATIONS, EACH PROCESS CAN ONLY MANAGE ONE
-+ * CONNECTION. SO THIS 'PPTP_CONN' STRUCTURE IS A BIT MISLEADING.
-+ * WE'LL KEEP CONNECTION-SPECIFIC INFORMATION IN THERE ANYWAY (AS
-+ * OPPOSED TO USING GLOBAL VARIABLES), BUT BEWARE THAT THE ENTIRE
-+ * UNIX SIGNAL-HANDLING SEMANTICS WOULD HAVE TO CHANGE (OR THE
-+ * TIME-OUT CODE DRASTICALLY REWRITTEN) BEFORE YOU COULD DO A
-+ * PPTP_CONN_OPEN MORE THAN ONCE PER PROCESS AND GET AWAY WITH IT.
-+ */
-+
-+/* This structure contains connection-specific information that the
-+ * signal handler needs to see. Thus, it needs to be in a global
-+ * variable. If you end up using pthreads or something (why not
-+ * just processes?), this would have to be placed in a thread-specific
-+ * data area, using pthread_get|set_specific, etc., so I've
-+ * conveniently encapsulated it for you.
-+ * [linux threads will have to support thread-specific signals
-+ * before this would work at all, which, as of this writing
-+ * (linux-threads v0.6, linux kernel 2.1.72), it does not.]
-+ */
-+
-+/* Globals */
-+
-+/* control the number of times echo packets will be logged */
-+static int nlogecho = 10;
-+
-+static struct thread_specific {
-+ struct sigaction old_sigaction; /* evil signals */
-+ PPTP_CONN * conn;
-+} global;
-+
-+#define INITIAL_BUFSIZE 512 /* initial i/o buffer size. */
-+
-+struct PPTP_CONN {
-+ int inet_sock;
-+ /* Connection States */
-+ enum {
-+ CONN_IDLE, CONN_WAIT_CTL_REPLY, CONN_WAIT_STOP_REPLY, CONN_ESTABLISHED
-+ } conn_state; /* on startup: CONN_IDLE */
-+ /* Keep-alive states */
-+ enum {
-+ KA_NONE, KA_OUTSTANDING
-+ } ka_state; /* on startup: KA_NONE */
-+ /* Keep-alive ID; monotonically increasing (watch wrap-around!) */
-+ u_int32_t ka_id; /* on startup: 1 */
-+ /* Other properties. */
-+ u_int16_t version;
-+ u_int16_t firmware_rev;
-+ u_int8_t hostname[64], vendor[64];
-+ /* XXX these are only PNS properties, currently XXX */
-+ /* Call assignment information. */
-+ u_int16_t call_serial_number;
-+ VECTOR *call;
-+ void * closure;
-+ pptp_conn_cb callback;
-+ /******* IO buffers ******/
-+ char * read_buffer, *write_buffer;
-+ size_t read_alloc, write_alloc;
-+ size_t read_size, write_size;
-+};
-+
-+struct PPTP_CALL {
-+ /* Call properties */
-+ enum {
-+ PPTP_CALL_PAC, PPTP_CALL_PNS
-+ } call_type;
-+ union {
-+ enum pptp_pac_state {
-+ PAC_IDLE, PAC_WAIT_REPLY, PAC_ESTABLISHED, PAC_WAIT_CS_ANS
-+ } pac;
-+ enum pptp_pns_state {
-+ PNS_IDLE, PNS_WAIT_REPLY, PNS_ESTABLISHED, PNS_WAIT_DISCONNECT
-+ } pns;
-+ } state;
-+ u_int16_t call_id, peer_call_id;
-+ u_int16_t sernum;
-+ u_int32_t speed;
-+ /* For user data: */
-+ pptp_call_cb callback;
-+ void * closure;
-+};
-+
-+
-+/* PPTP error codes: ----------------------------------------------*/
-+
-+/* (General Error Codes) */
-+static const struct {
-+ const char *name, *desc;
-+} pptp_general_errors[] = {
-+#define PPTP_GENERAL_ERROR_NONE 0
-+ { "(None)", "No general error" },
-+#define PPTP_GENERAL_ERROR_NOT_CONNECTED 1
-+ { "(Not-Connected)", "No control connection exists yet for this "
-+ "PAC-PNS pair" },
-+#define PPTP_GENERAL_ERROR_BAD_FORMAT 2
-+ { "(Bad-Format)", "Length is wrong or Magic Cookie value is incorrect" },
-+#define PPTP_GENERAL_ERROR_BAD_VALUE 3
-+ { "(Bad-Value)", "One of the field values was out of range or "
-+ "reserved field was non-zero" },
-+#define PPTP_GENERAL_ERROR_NO_RESOURCE 4
-+ { "(No-Resource)", "Insufficient resources to handle this command now" },
-+#define PPTP_GENERAL_ERROR_BAD_CALLID 5
-+ { "(Bad-Call ID)", "The Call ID is invalid in this context" },
-+#define PPTP_GENERAL_ERROR_PAC_ERROR 6
-+ { "(PAC-Error)", "A generic vendor-specific error occured in the PAC" }
-+};
-+
-+#define MAX_GENERAL_ERROR ( sizeof(pptp_general_errors) / \
-+ sizeof(pptp_general_errors[0]) - 1)
-+
-+/* Outgoing Call Reply Result Codes */
-+static const char *pptp_out_call_reply_result[] = {
-+/* 0 */ "Unknown Result Code",
-+/* 1 */ "Connected",
-+/* 2 */ "General Error",
-+/* 3 */ "No Carrier Detected",
-+/* 4 */ "Busy Signal",
-+/* 5 */ "No Dial Tone",
-+/* 6 */ "Time Out",
-+/* 7 */ "Not Accepted, Call is administratively prohibited" };
-+
-+#define MAX_OUT_CALL_REPLY_RESULT 7
-+
-+/* Call Disconnect Notify Result Codes */
-+static const char *pptp_call_disc_ntfy[] = {
-+/* 0 */ "Unknown Result Code",
-+/* 1 */ "Lost Carrier",
-+/* 2 */ "General Error",
-+/* 3 */ "Administrative Shutdown",
-+/* 4 */ "(your) Request" };
-+
-+#define MAX_CALL_DISC_NTFY 4
-+
-+/* Call Disconnect Notify Result Codes */
-+static const char *pptp_start_ctrl_conn_rply[] = {
-+/* 0 */ "Unknown Result Code",
-+/* 1 */ "Successful Channel Establishment",
-+/* 2 */ "General Error",
-+/* 3 */ "Command Channel Already Exists",
-+/* 4 */ "Requester is not Authorized" };
-+
-+#define MAX_START_CTRL_CONN_REPLY 4
-+
-+/* timing options */
-+int idle_wait = PPTP_TIMEOUT;
-+int max_echo_wait = PPTP_TIMEOUT;
-+
-+/* Local prototypes */
-+static void pptp_reset_timer(void);
-+static void pptp_handle_timer();
-+/* Write/read as much as we can without blocking. */
-+int pptp_write_some(PPTP_CONN * conn);
-+int pptp_read_some(PPTP_CONN * conn);
-+/* Make valid packets from read_buffer */
-+int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size);
-+/* Add packet to write_buffer */
-+int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size);
-+/* Dispatch packets (general) */
-+int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size);
-+/* Dispatch packets (control messages) */
-+int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size);
-+/* Set link info, for pptp servers that need it.
-+ this is a noop, unless the user specified a quirk and
-+ there's a set_link hook defined in the quirks table
-+ for that quirk */
-+void pptp_set_link(PPTP_CONN * conn, int peer_call_id);
-+
-+/*** log error information in control packets *********************************/
-+static void ctrlp_error( int result, int error, int cause,
-+ const char *result_text[], int max_result)
-+{
-+ if( cause >= 0)
-+ warn("Result code is %d '%s'. Error code is %d, Cause code is %d",
-+ result, result_text[result <= max_result ? result : 0], error,
-+ cause );
-+ else
-+ warn("Reply result code is %d '%s'. Error code is %d",
-+ result, result_text[result <= max_result ? result : 0], error);
-+ if ((error > 0) && (error <= MAX_GENERAL_ERROR)){
-+ if( result != PPTP_RESULT_GENERAL_ERROR )
-+ warn("Result code is something else then \"general error\", "
-+ "so the following error is probably bogus.");
-+ warn("Error is '%s', Error message: '%s'",
-+ pptp_general_errors[error].name,
-+ pptp_general_errors[error].desc);
-+ }
-+}
-+
-+static const char *ctrl_msg_types[] = {
-+ "invalid control message type",
-+/* (Control Connection Management) */
-+ "Start-Control-Connection-Request", /* 1 */
-+ "Start-Control-Connection-Reply", /* 2 */
-+ "Stop-Control-Connection-Request", /* 3 */
-+ "Stop-Control-Connection-Reply", /* 4 */
-+ "Echo-Request", /* 5 */
-+ "Echo-Reply", /* 6 */
-+/* (Call Management) */
-+ "Outgoing-Call-Request", /* 7 */
-+ "Outgoing-Call-Reply", /* 8 */
-+ "Incoming-Call-Request", /* 9 */
-+ "Incoming-Call-Reply", /* 10 */
-+ "Incoming-Call-Connected", /* 11 */
-+ "Call-Clear-Request", /* 12 */
-+ "Call-Disconnect-Notify", /* 13 */
-+/* (Error Reporting) */
-+ "WAN-Error-Notify", /* 14 */
-+/* (PPP Session Control) */
-+ "Set-Link-Info" /* 15 */
-+};
-+#define MAX_CTRLMSG_TYPE 15
-+
-+/*** report a sent packet ****************************************************/
-+static void ctrlp_rep( void * buffer, int size, int isbuff)
-+{
-+ struct pptp_header *packet = buffer;
-+ unsigned int type;
-+ if(size < sizeof(struct pptp_header)) return;
-+ type = ntoh16(packet->ctrl_type);
-+ /* FIXME: do not report sending echo requests as long as they are
-+ * sent in a signal handler. This may dead lock as the syslog call
-+ * is not reentrant */
-+ if( type == PPTP_ECHO_RQST ) return;
-+ /* don't keep reporting sending of echo's */
-+ if( (type == PPTP_ECHO_RQST || type == PPTP_ECHO_RPLY) && nlogecho <= 0 ) return;
-+ dbglog("%s control packet type is %d '%s'\n",isbuff ? "Buffered" : "Sent",
-+ type, ctrl_msg_types[type <= MAX_CTRLMSG_TYPE ? type : 0]);
-+
-+}
-+
-+
-+
-+/* Open new pptp_connection. Returns NULL on failure. */
-+PPTP_CONN * pptp_conn_open(int inet_sock, int isclient, pptp_conn_cb callback)
-+{
-+ PPTP_CONN *conn;
-+ /* Allocate structure */
-+ if ((conn = malloc(sizeof(*conn))) == NULL) return NULL;
-+ if ((conn->call = vector_create()) == NULL) { free(conn); return NULL; }
-+ /* Initialize */
-+ conn->inet_sock = inet_sock;
-+ conn->conn_state = CONN_IDLE;
-+ conn->ka_state = KA_NONE;
-+ conn->ka_id = 1;
-+ conn->call_serial_number = 0;
-+ conn->callback = callback;
-+ /* Create I/O buffers */
-+ conn->read_size = conn->write_size = 0;
-+ conn->read_alloc = conn->write_alloc = INITIAL_BUFSIZE;
-+ conn->read_buffer =
-+ malloc(sizeof(*(conn->read_buffer)) * conn->read_alloc);
-+ conn->write_buffer =
-+ malloc(sizeof(*(conn->write_buffer)) * conn->write_alloc);
-+ if (conn->read_buffer == NULL || conn->write_buffer == NULL) {
-+ if (conn->read_buffer != NULL) free(conn->read_buffer);
-+ if (conn->write_buffer != NULL) free(conn->write_buffer);
-+ vector_destroy(conn->call); free(conn); return NULL;
-+ }
-+ /* Make this socket non-blocking. */
-+ fcntl(conn->inet_sock, F_SETFL, O_NONBLOCK);
-+ /* Request connection from server, if this is a client */
-+ if (isclient) {
-+ struct pptp_start_ctrl_conn packet = {
-+ PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RQST),
-+ hton16(PPTP_VERSION), 0, 0,
-+ hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),
-+ hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),
-+ PPTP_HOSTNAME, PPTP_VENDOR
-+ };
-+ /* fix this packet, if necessary */
-+ int idx, rc;
-+ idx = get_quirk_index();
-+ if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {
-+ if ((rc = pptp_fixups[idx].start_ctrl_conn(&packet)))
-+ warn("calling the start_ctrl_conn hook failed (%d)", rc);
-+ }
-+ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet)))
-+ conn->conn_state = CONN_WAIT_CTL_REPLY;
-+ else
-+ return NULL; /* could not send initial start request. */
-+ }
-+ /* Set up interval/keep-alive timer */
-+ /* First, register handler for SIGALRM */
-+ sigpipe_create();
-+ sigpipe_assign(SIGALRM);
-+ global.conn = conn;
-+ /* Reset event timer */
-+ pptp_reset_timer();
-+ /* all done. */
-+ return conn;
-+}
-+
-+int pptp_conn_established(PPTP_CONN *conn) {
-+ return (conn->conn_state == CONN_ESTABLISHED);
-+}
-+
-+/* This currently *only* works for client call requests.
-+ * We need to do something else to allocate calls for incoming requests.
-+ */
-+PPTP_CALL * pptp_call_open(PPTP_CONN * conn, int call_id,pptp_call_cb callback,
-+ char *phonenr,int window)
-+{
-+ PPTP_CALL * call;
-+ int idx, rc;
-+ /* Send off the call request */
-+ struct pptp_out_call_rqst packet = {
-+ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST),
-+ 0,0, /*call_id, sernum */
-+ hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX),
-+ hton32(PPTP_BEARER_CAP), hton32(PPTP_FRAME_CAP),
-+ hton16(window), 0, 0, 0, {0}, {0}
-+ };
-+ assert(conn && conn->call);
-+ assert(conn->conn_state == CONN_ESTABLISHED);
-+ /* Assign call id */
-+ if (!call_id && !vector_scan(conn->call, 0, PPTP_MAX_CHANNELS - 1, &call_id))
-+ /* no more calls available! */
-+ return NULL;
-+ /* allocate structure. */
-+ if ((call = malloc(sizeof(*call))) == NULL) return NULL;
-+ /* Initialize call structure */
-+ call->call_type = PPTP_CALL_PNS;
-+ call->state.pns = PNS_IDLE;
-+ call->call_id = (u_int16_t) call_id;
-+ call->sernum = conn->call_serial_number++;
-+ call->callback = callback;
-+ call->closure = NULL;
-+ packet.call_id = htons(call->call_id);
-+ packet.call_sernum = htons(call->sernum);
-+ /* if we have a quirk, build a new packet to fit it */
-+ idx = get_quirk_index();
-+ if (idx != -1 && pptp_fixups[idx].out_call_rqst_hook) {
-+ if ((rc = pptp_fixups[idx].out_call_rqst_hook(&packet)))
-+ warn("calling the out_call_rqst hook failed (%d)", rc);
-+ }
-+ /* fill in the phone number if it was specified */
-+ if (phonenr) {
-+ strncpy(packet.phone_num, phonenr, sizeof(packet.phone_num));
-+ packet.phone_len = strlen(phonenr);
-+ if( packet.phone_len > sizeof(packet.phone_num))
-+ packet.phone_len = sizeof(packet.phone_num);
-+ packet.phone_len = hton16 (packet.phone_len);
-+ }
-+ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) {
-+ pptp_reset_timer();
-+ call->state.pns = PNS_WAIT_REPLY;
-+ /* and add it to the call vector */
-+ vector_insert(conn->call, call_id, call);
-+ return call;
-+ } else { /* oops, unsuccessful. Deallocate. */
-+ free(call);
-+ return NULL;
-+ }
-+}
-+
-+/*** pptp_call_close **********************************************************/
-+void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call)
-+{
-+ struct pptp_call_clear_rqst rqst = {
-+ PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_RQST), 0, 0
-+ };
-+ assert(conn && conn->call); assert(call);
-+ assert(vector_contains(conn->call, call->call_id));
-+ /* haven't thought about PAC yet */
-+ assert(call->call_type == PPTP_CALL_PNS);
-+ assert(call->state.pns != PNS_IDLE);
-+ rqst.call_id = hton16(call->call_id);
-+ /* don't check state against WAIT_DISCONNECT... allow multiple disconnect
-+ * requests to be made.
-+ */
-+ pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));
-+ pptp_reset_timer();
-+ call->state.pns = PNS_WAIT_DISCONNECT;
-+ /* call structure will be freed when we have confirmation of disconnect. */
-+}
-+
-+/*** hard close ***************************************************************/
-+void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call)
-+{
-+ assert(conn && conn->call); assert(call);
-+ assert(vector_contains(conn->call, call->call_id));
-+ /* notify */
-+ if (call->callback != NULL) call->callback(conn, call, CALL_CLOSE_DONE);
-+ /* deallocate */
-+ vector_remove(conn->call, call->call_id);
-+ free(call);
-+}
-+
-+/*** this is a soft close *****************************************************/
-+void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason)
-+{
-+ struct pptp_stop_ctrl_conn rqst = {
-+ PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST),
-+ hton8(close_reason), 0, 0
-+ };
-+ int i;
-+ assert(conn && conn->call);
-+ /* avoid repeated close attempts */
-+ if (conn->conn_state == CONN_IDLE || conn->conn_state == CONN_WAIT_STOP_REPLY)
-+ return;
-+ /* close open calls, if any */
-+ for (i = 0; i < vector_size(conn->call); i++)
-+ pptp_call_close(conn, vector_get_Nth(conn->call, i));
-+ /* now close connection */
-+ info("Closing PPTP connection");
-+ pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));
-+ pptp_reset_timer(); /* wait 60 seconds for reply */
-+ conn->conn_state = CONN_WAIT_STOP_REPLY;
-+ return;
-+}
-+
-+/*** this is a hard close *****************************************************/
-+void pptp_conn_destroy(PPTP_CONN * conn)
-+{
-+ int i;
-+ assert(conn != NULL); assert(conn->call != NULL);
-+ /* destroy all open calls */
-+ for (i = 0; i < vector_size(conn->call); i++)
-+ pptp_call_destroy(conn, vector_get_Nth(conn->call, i));
-+ /* notify */
-+ if (conn->callback != NULL) conn->callback(conn, CONN_CLOSE_DONE);
-+ sigpipe_close();
-+ close(conn->inet_sock);
-+ /* deallocate */
-+ vector_destroy(conn->call);
-+ free(conn);
-+}
-+
-+/*** Deal with messages, in a non-blocking manner
-+ * Add file descriptors used by pptp to fd_set.
-+ */
-+void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set,
-+ int * max_fd)
-+{
-+ assert(conn && conn->call);
-+ /* Add fd to write_set if there are outstanding writes. */
-+ if (conn->write_size > 0)
-+ FD_SET(conn->inet_sock, write_set);
-+ /* Always add fd to read_set. (always want something to read) */
-+ FD_SET(conn->inet_sock, read_set);
-+ if (*max_fd < conn->inet_sock) *max_fd = conn->inet_sock;
-+ /* Add signal pipe file descriptor to set */
-+ int sig_fd = sigpipe_fd();
-+ FD_SET(sig_fd, read_set);
-+ if (*max_fd < sig_fd) *max_fd = sig_fd;
-+}
-+
-+/*** handle any pptp file descriptors set in fd_set, and clear them ***********/
-+int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set)
-+{
-+ int r = 0;
-+ assert(conn && conn->call);
-+ /* Check for signals */
-+ if (FD_ISSET(sigpipe_fd(), read_set)) {
-+ if (sigpipe_read() == SIGALRM) pptp_handle_timer();
-+ FD_CLR(sigpipe_fd(), read_set);
-+ }
-+ /* Check write_set could be set. */
-+ if (FD_ISSET(conn->inet_sock, write_set)) {
-+ FD_CLR(conn->inet_sock, write_set);
-+ if (conn->write_size > 0)
-+ r = pptp_write_some(conn);/* write as much as we can without blocking */
-+ }
-+ /* Check read_set */
-+ if (r >= 0 && FD_ISSET(conn->inet_sock, read_set)) {
-+ void *buffer; size_t size;
-+ FD_CLR(conn->inet_sock, read_set);
-+ r = pptp_read_some(conn); /* read as much as we can without blocking */
-+ if (r < 0)
-+ return r;
-+ /* make packets of the buffer, while we can. */
-+ while (r >= 0 && pptp_make_packet(conn, &buffer, &size)) {
-+ r = pptp_dispatch_packet(conn, buffer, size);
-+ free(buffer);
-+ }
-+ }
-+ /* That's all, folks. Simple, eh? */
-+ return r;
-+}
-+
-+/*** Non-blocking write *******************************************************/
-+int pptp_write_some(PPTP_CONN * conn) {
-+ ssize_t retval;
-+ assert(conn && conn->call);
-+ retval = write(conn->inet_sock, conn->write_buffer, conn->write_size);
-+ if (retval < 0) { /* error. */
-+ if (errno == EAGAIN || errno == EINTR) {
-+ return 0;
-+ } else { /* a real error */
-+ warn("write error: %s", strerror(errno));
-+ return -1;
-+ }
-+ }
-+ assert(retval <= conn->write_size);
-+ conn->write_size -= retval;
-+ memmove(conn->write_buffer, conn->write_buffer + retval, conn->write_size);
-+ ctrlp_rep(conn->write_buffer, retval, 0);
-+ return 0;
-+}
-+
-+/*** Non-blocking read ********************************************************/
-+int pptp_read_some(PPTP_CONN * conn)
-+{
-+ ssize_t retval;
-+ assert(conn && conn->call);
-+ if (conn->read_size == conn->read_alloc) { /* need to alloc more memory */
-+ char *new_buffer = realloc(conn->read_buffer,
-+ sizeof(*(conn->read_buffer)) * conn->read_alloc * 2);
-+ if (new_buffer == NULL) {
-+ warn("Out of memory"); return -1;
-+ }
-+ conn->read_alloc *= 2;
-+ conn->read_buffer = new_buffer;
-+ }
-+ retval = read(conn->inet_sock, conn->read_buffer + conn->read_size,
-+ conn->read_alloc - conn->read_size);
-+ if (retval == 0) {
-+ warn("read returned zero, peer has closed");
-+ return -1;
-+ }
-+ if (retval < 0) {
-+ if (errno == EINTR || errno == EAGAIN)
-+ return 0;
-+ else { /* a real error */
-+ warn("read error: %s", strerror(errno));
-+ return -1;
-+ }
-+ }
-+ conn->read_size += retval;
-+ assert(conn->read_size <= conn->read_alloc);
-+ return 0;
-+}
-+
-+/*** Packet formation *********************************************************/
-+int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size)
-+{
-+ struct pptp_header *header;
-+ size_t bad_bytes = 0;
-+ assert(conn && conn->call); assert(buf != NULL); assert(size != NULL);
-+ /* Give up unless there are at least sizeof(pptp_header) bytes */
-+ while ((conn->read_size-bad_bytes) >= sizeof(struct pptp_header)) {
-+ /* Throw out bytes until we have a valid header. */
-+ header = (struct pptp_header *) (conn->read_buffer + bad_bytes);
-+ if (ntoh32(header->magic) != PPTP_MAGIC) goto throwitout;
-+ if (ntoh16(header->reserved0) != 0)
-+ warn("reserved0 field is not zero! (0x%x) Cisco feature? \n",
-+ ntoh16(header->reserved0));
-+ if (ntoh16(header->length) < sizeof(struct pptp_header)) goto throwitout;
-+ if (ntoh16(header->length) > PPTP_CTRL_SIZE_MAX) goto throwitout;
-+ /* well. I guess it's good. Let's see if we've got it all. */
-+ if (ntoh16(header->length) > (conn->read_size-bad_bytes))
-+ /* nope. Let's wait until we've got it, then. */
-+ goto flushbadbytes;
-+ /* One last check: */
-+ if ((ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL) &&
-+ (ntoh16(header->length) !=
-+ PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))))
-+ goto throwitout;
-+ /* well, I guess we've got it. */
-+ *size = ntoh16(header->length);
-+ *buf = malloc(*size);
-+ if (*buf == NULL) { warn("Out of memory."); return 0; /* ack! */ }
-+ memcpy(*buf, conn->read_buffer + bad_bytes, *size);
-+ /* Delete this packet from the read_buffer. */
-+ conn->read_size -= (bad_bytes + *size);
-+ memmove(conn->read_buffer, conn->read_buffer + bad_bytes + *size,
-+ conn->read_size);
-+ if (bad_bytes > 0)
-+ warn("%lu bad bytes thrown away.", (unsigned long) bad_bytes);
-+ return 1;
-+throwitout:
-+ bad_bytes++;
-+ }
-+flushbadbytes:
-+ /* no more packets. Let's get rid of those bad bytes */
-+ conn->read_size -= bad_bytes;
-+ memmove(conn->read_buffer, conn->read_buffer + bad_bytes, conn->read_size);
-+ if (bad_bytes > 0)
-+ warn("%lu bad bytes thrown away.", (unsigned long) bad_bytes);
-+ return 0;
-+}
-+
-+/*** pptp_send_ctrl_packet ****************************************************/
-+int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size)
-+{
-+ assert(conn && conn->call); assert(buffer);
-+ if( conn->write_size > 0) pptp_write_some( conn);
-+ if( conn->write_size == 0) {
-+ ssize_t retval;
-+ retval = write(conn->inet_sock, buffer, size);
-+ if (retval < 0) { /* error. */
-+ if (errno == EAGAIN || errno == EINTR) {
-+ /* ignore */;
-+ retval = 0;
-+ } else { /* a real error */
-+ warn("write error: %s", strerror(errno));
-+ pptp_conn_destroy(conn); /* shut down fast. */
-+ return 0;
-+ }
-+ }
-+ ctrlp_rep( buffer, retval, 0);
-+ size -= retval;
-+ if( size <= 0) return 1;
-+ }
-+ /* Shove anything not written into the write buffer */
-+ if (conn->write_size + size > conn->write_alloc) { /* need more memory */
-+ char *new_buffer = realloc(conn->write_buffer,
-+ sizeof(*(conn->write_buffer)) * conn->write_alloc * 2);
-+ if (new_buffer == NULL) {
-+ warn("Out of memory"); return 0;
-+ }
-+ conn->write_alloc *= 2;
-+ conn->write_buffer = new_buffer;
-+ }
-+ memcpy(conn->write_buffer + conn->write_size, buffer, size);
-+ conn->write_size += size;
-+ ctrlp_rep( buffer,size,1);
-+ return 1;
-+}
-+
-+/*** Packet Dispatch **********************************************************/
-+int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size)
-+{
-+ int r = 0;
-+ struct pptp_header *header = (struct pptp_header *)buffer;
-+ assert(conn && conn->call); assert(buffer);
-+ assert(ntoh32(header->magic) == PPTP_MAGIC);
-+ assert(ntoh16(header->length) == size);
-+ switch (ntoh16(header->pptp_type)) {
-+ case PPTP_MESSAGE_CONTROL:
-+ r = ctrlp_disp(conn, buffer, size);
-+ break;
-+ case PPTP_MESSAGE_MANAGE:
-+ /* MANAGEMENT messages aren't even part of the spec right now. */
-+ dbglog("PPTP management message received, but not understood.");
-+ break;
-+ default:
-+ dbglog("Unknown PPTP control message type received: %u",
-+ (unsigned int) ntoh16(header->pptp_type));
-+ break;
-+ }
-+ return r;
-+}
-+
-+/*** log echo request/replies *************************************************/
-+static void logecho( int type)
-+{
-+ /* hack to stop flooding the log files (the most interesting part is right
-+ * after the connection built-up) */
-+ if( nlogecho > 0) {
-+ dbglog("Echo Re%s received.", type == PPTP_ECHO_RQST ? "quest" :"ply");
-+ if( --nlogecho == 0)
-+ dbglog("no more Echo Reply/Request packets will be reported.");
-+ }
-+}
-+
-+/*** pptp_dispatch_ctrl_packet ************************************************/
-+int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size)
-+{
-+ struct pptp_header *header = (struct pptp_header *)buffer;
-+ u_int8_t close_reason = PPTP_STOP_NONE;
-+ assert(conn && conn->call); assert(buffer);
-+ assert(ntoh32(header->magic) == PPTP_MAGIC);
-+ assert(ntoh16(header->length) == size);
-+ assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL);
-+ if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) {
-+ warn("Invalid packet received [type: %d; length: %d].",
-+ (int) ntoh16(header->ctrl_type), (int) size);
-+ return 0;
-+ }
-+ switch (ntoh16(header->ctrl_type)) {
-+ /* ----------- STANDARD Start-Session MESSAGES ------------ */
-+ case PPTP_START_CTRL_CONN_RQST:
-+ {
-+ struct pptp_start_ctrl_conn *packet =
-+ (struct pptp_start_ctrl_conn *) buffer;
-+ struct pptp_start_ctrl_conn reply = {
-+ PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),
-+ hton16(PPTP_VERSION), 0, 0,
-+ hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),
-+ hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),
-+ PPTP_HOSTNAME, PPTP_VENDOR };
-+ int idx, rc;
-+ dbglog("Received Start Control Connection Request");
-+ /* fix this packet, if necessary */
-+ idx = get_quirk_index();
-+ if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {
-+ if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply)))
-+ warn("calling the start_ctrl_conn hook failed (%d)", rc);
-+ }
-+ if (conn->conn_state == CONN_IDLE) {
-+ if (ntoh16(packet->version) < PPTP_VERSION) {
-+ /* Can't support this (earlier) PPTP_VERSION */
-+ reply.version = packet->version;
-+ /* protocol version not supported */
-+ reply.result_code = hton8(5);
-+ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
-+ pptp_reset_timer(); /* give sender a chance for a retry */
-+ } else { /* same or greater version */
-+ if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
-+ conn->conn_state = CONN_ESTABLISHED;
-+ dbglog("server connection ESTABLISHED.");
-+ pptp_reset_timer();
-+ }
-+ }
-+ }
-+ break;
-+ }
-+ case PPTP_START_CTRL_CONN_RPLY:
-+ {
-+ struct pptp_start_ctrl_conn *packet =
-+ (struct pptp_start_ctrl_conn *) buffer;
-+ dbglog("Received Start Control Connection Reply");
-+ if (conn->conn_state == CONN_WAIT_CTL_REPLY) {
-+ /* XXX handle collision XXX [see rfc] */
-+ if (ntoh16(packet->version) != PPTP_VERSION) {
-+ if (conn->callback != NULL)
-+ conn->callback(conn, CONN_OPEN_FAIL);
-+ close_reason = PPTP_STOP_PROTOCOL;
-+ goto pptp_conn_close;
-+ }
-+ if (ntoh8(packet->result_code) != 1 &&
-+ /* J'ai change le if () afin que la connection ne se ferme
-+ * pas pour un "rien" :p adel@cybercable.fr -
-+ *
-+ * Don't close the connection if the result code is zero
-+ * (feature found in certain ADSL modems)
-+ */
-+ ntoh8(packet->result_code) != 0) {
-+ dbglog("Negative reply received to our Start Control "
-+ "Connection Request");
-+ ctrlp_error(packet->result_code, packet->error_code,
-+ -1, pptp_start_ctrl_conn_rply,
-+ MAX_START_CTRL_CONN_REPLY);
-+ if (conn->callback != NULL)
-+ conn->callback(conn, CONN_OPEN_FAIL);
-+ close_reason = PPTP_STOP_PROTOCOL;
-+ goto pptp_conn_close;
-+ }
-+ conn->conn_state = CONN_ESTABLISHED;
-+ /* log session properties */
-+ conn->version = ntoh16(packet->version);
-+ conn->firmware_rev = ntoh16(packet->firmware_rev);
-+ memcpy(conn->hostname, packet->hostname, sizeof(conn->hostname));
-+ memcpy(conn->vendor, packet->vendor, sizeof(conn->vendor));
-+ pptp_reset_timer(); /* 60 seconds until keep-alive */
-+ dbglog("Client connection established.");
-+ if (conn->callback != NULL)
-+ conn->callback(conn, CONN_OPEN_DONE);
-+ } /* else goto pptp_conn_close; */
-+ break;
-+ }
-+ /* ----------- STANDARD Stop-Session MESSAGES ------------ */
-+ case PPTP_STOP_CTRL_CONN_RQST:
-+ {
-+ /* conn_state should be CONN_ESTABLISHED, but it could be
-+ * something else */
-+ struct pptp_stop_ctrl_conn reply = {
-+ PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY),
-+ hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
-+ };
-+ dbglog("Received Stop Control Connection Request.");
-+ if (conn->conn_state == CONN_IDLE) break;
-+ if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
-+ if (conn->callback != NULL)
-+ conn->callback(conn, CONN_CLOSE_RQST);
-+ conn->conn_state = CONN_IDLE;
-+ return -1;
-+ }
-+ break;
-+ }
-+ case PPTP_STOP_CTRL_CONN_RPLY:
-+ {
-+ dbglog("Received Stop Control Connection Reply.");
-+ /* conn_state should be CONN_WAIT_STOP_REPLY, but it
-+ * could be something else */
-+ if (conn->conn_state == CONN_IDLE) break;
-+ conn->conn_state = CONN_IDLE;
-+ return -1;
-+ }
-+ /* ----------- STANDARD Echo/Keepalive MESSAGES ------------ */
-+ case PPTP_ECHO_RPLY:
-+ {
-+ struct pptp_echo_rply *packet =
-+ (struct pptp_echo_rply *) buffer;
-+ logecho( PPTP_ECHO_RPLY);
-+ if ((conn->ka_state == KA_OUTSTANDING) &&
-+ (ntoh32(packet->identifier) == conn->ka_id)) {
-+ conn->ka_id++;
-+ conn->ka_state = KA_NONE;
-+ pptp_reset_timer();
-+ }
-+ break;
-+ }
-+ case PPTP_ECHO_RQST:
-+ {
-+ struct pptp_echo_rqst *packet =
-+ (struct pptp_echo_rqst *) buffer;
-+ struct pptp_echo_rply reply = {
-+ PPTP_HEADER_CTRL(PPTP_ECHO_RPLY),
-+ packet->identifier, /* skip hton32(ntoh32(id)) */
-+ hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
-+ };
-+ logecho( PPTP_ECHO_RQST);
-+ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
-+ pptp_reset_timer();
-+ break;
-+ }
-+ /* ----------- OUTGOING CALL MESSAGES ------------ */
-+ case PPTP_OUT_CALL_RQST:
-+ {
-+ struct pptp_out_call_rqst *packet =
-+ (struct pptp_out_call_rqst *)buffer;
-+ struct pptp_out_call_rply reply = {
-+ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY),
-+ 0 /* callid */, packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0,
-+ hton32(PPTP_CONNECT_SPEED),
-+ hton16(PPTP_WINDOW), hton16(PPTP_DELAY), 0
-+ };
-+ dbglog("Received Outgoing Call Request.");
-+ /* XXX PAC: eventually this should make an outgoing call. XXX */
-+ reply.result_code = hton8(7); /* outgoing calls verboten */
-+ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
-+ break;
-+ }
-+ case PPTP_OUT_CALL_RPLY:
-+ {
-+ struct pptp_out_call_rply *packet =
-+ (struct pptp_out_call_rply *)buffer;
-+ PPTP_CALL * call;
-+ u_int16_t callid = ntoh16(packet->call_id_peer);
-+ dbglog("Received Outgoing Call Reply.");
-+ if (!vector_search(conn->call, (int) callid, &call)) {
-+ dbglog("PPTP_OUT_CALL_RPLY received for non-existant call: "
-+ "peer call ID (us) %d call ID (them) %d.",
-+ callid, ntoh16(packet->call_id));
-+ break;
-+ }
-+ if (call->call_type != PPTP_CALL_PNS) {
-+ dbglog("Ack! How did this call_type get here?"); /* XXX? */
-+ break;
-+ }
-+ if (call->state.pns != PNS_WAIT_REPLY) {
-+ warn("Unexpected(?) Outgoing Call Reply will be ignored.");
-+ break;
-+ }
-+ /* check for errors */
-+ if (packet->result_code != 1) {
-+ /* An error. Log it verbosely. */
-+ dbglog("Our outgoing call request [callid %d] has not been "
-+ "accepted.", (int) callid);
-+ ctrlp_error(packet->result_code, packet->error_code,
-+ packet->cause_code, pptp_out_call_reply_result,
-+ MAX_OUT_CALL_REPLY_RESULT);
-+ call->state.pns = PNS_IDLE;
-+ if (call->callback != NULL)
-+ call->callback(conn, call, CALL_OPEN_FAIL);
-+ pptp_call_destroy(conn, call);
-+ } else {
-+ /* connection established */
-+ call->state.pns = PNS_ESTABLISHED;
-+ call->peer_call_id = ntoh16(packet->call_id);
-+ call->speed = ntoh32(packet->speed);
-+ pptp_reset_timer();
-+ /* call pptp_set_link. unless the user specified a quirk
-+ and this quirk has a set_link hook, this is a noop */
-+ pptp_set_link(conn, call->peer_call_id);
-+ if (call->callback != NULL)
-+ call->callback(conn, call, CALL_OPEN_DONE);
-+ dbglog("Outgoing call established (call ID %u, peer's "
-+ "call ID %u).\n", call->call_id, call->peer_call_id);
-+ }
-+ break;
-+ }
-+ /* ----------- INCOMING CALL MESSAGES ------------ */
-+ /* XXX write me XXX */
-+ /* ----------- CALL CONTROL MESSAGES ------------ */
-+ case PPTP_CALL_CLEAR_RQST:
-+ {
-+ struct pptp_call_clear_rqst *packet =
-+ (struct pptp_call_clear_rqst *)buffer;
-+ struct pptp_call_clear_ntfy reply = {
-+ PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_NTFY), packet->call_id,
-+ 1, PPTP_GENERAL_ERROR_NONE, 0, 0, {0}
-+ };
-+ dbglog("Received Call Clear Request.");
-+ if (vector_contains(conn->call, ntoh16(packet->call_id))) {
-+ PPTP_CALL * call;
-+ vector_search(conn->call, ntoh16(packet->call_id), &call);
-+ if (call->callback != NULL)
-+ call->callback(conn, call, CALL_CLOSE_RQST);
-+ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
-+ pptp_call_destroy(conn, call);
-+ dbglog("Call closed (RQST) (call id %d)", (int) call->call_id);
-+ }
-+ break;
-+ }
-+ case PPTP_CALL_CLEAR_NTFY:
-+ {
-+ struct pptp_call_clear_ntfy *packet =
-+ (struct pptp_call_clear_ntfy *)buffer;
-+ dbglog("Call disconnect notification received (call id %d)",
-+ ntoh16(packet->call_id));
-+ if (vector_contains(conn->call, ntoh16(packet->call_id))) {
-+ PPTP_CALL * call;
-+ ctrlp_error(packet->result_code, packet->error_code,
-+ packet->cause_code, pptp_call_disc_ntfy,
-+ MAX_CALL_DISC_NTFY);
-+ vector_search(conn->call, ntoh16(packet->call_id), &call);
-+ pptp_call_destroy(conn, call);
-+ }
-+ /* XXX we could log call stats here XXX */
-+ /* XXX not all servers send this XXX */
-+ break;
-+ }
-+ case PPTP_SET_LINK_INFO:
-+ {
-+ /* I HAVE NO CLUE WHAT TO DO IF send_accm IS NOT 0! */
-+ /* this is really dealt with in the HDLC deencapsulation, anyway. */
-+ struct pptp_set_link_info *packet =
-+ (struct pptp_set_link_info *)buffer;
-+ /* log it. */
-+ dbglog("PPTP_SET_LINK_INFO received from peer_callid %u",
-+ (unsigned int) ntoh16(packet->call_id_peer));
-+ dbglog(" send_accm is %08lX, recv_accm is %08lX",
-+ (unsigned long) ntoh32(packet->send_accm),
-+ (unsigned long) ntoh32(packet->recv_accm));
-+ if (!(ntoh32(packet->send_accm) == 0 &&
-+ ntoh32(packet->recv_accm) == 0))
-+ warn("Non-zero Async Control Character Maps are not supported!");
-+ break;
-+ }
-+ default:
-+ dbglog("Unrecognized Packet %d received.",
-+ (int) ntoh16(((struct pptp_header *)buffer)->ctrl_type));
-+ /* goto pptp_conn_close; */
-+ break;
-+ }
-+ return 0;
-+pptp_conn_close:
-+ warn("pptp_conn_close(%d)", (int) close_reason);
-+ pptp_conn_close(conn, close_reason);
-+ return 0;
-+}
-+
-+/*** pptp_set_link **************************************************************/
-+void pptp_set_link(PPTP_CONN* conn, int peer_call_id)
-+{
-+ int idx, rc;
-+ /* if we need to send a set_link packet because of buggy
-+ hardware or pptp server, do it now */
-+ if ((idx = get_quirk_index()) != -1 && pptp_fixups[idx].set_link_hook) {
-+ struct pptp_set_link_info packet;
-+ if ((rc = pptp_fixups[idx].set_link_hook(&packet, peer_call_id)))
-+ warn("calling the set_link hook failed (%d)", rc);
-+ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) {
-+ pptp_reset_timer();
-+ }
-+ }
-+}
-+
-+/*** Get info from call structure *********************************************/
-+/* NOTE: The peer_call_id is undefined until we get a server response. */
-+void pptp_call_get_ids(PPTP_CONN * conn, PPTP_CALL * call,
-+ u_int16_t * call_id, u_int16_t * peer_call_id)
-+{
-+ assert(conn != NULL); assert(call != NULL);
-+ *call_id = call->call_id;
-+ *peer_call_id = call->peer_call_id;
-+}
-+
-+/*** pptp_call_closure_put ****************************************************/
-+void pptp_call_closure_put(PPTP_CONN * conn, PPTP_CALL * call, void *cl)
-+{
-+ assert(conn != NULL); assert(call != NULL);
-+ call->closure = cl;
-+}
-+
-+/*** pptp_call_closure_get ****************************************************/
-+void * pptp_call_closure_get(PPTP_CONN * conn, PPTP_CALL * call)
-+{
-+ assert(conn != NULL); assert(call != NULL);
-+ return call->closure;
-+}
-+
-+/*** pptp_conn_closure_put ****************************************************/
-+void pptp_conn_closure_put(PPTP_CONN * conn, void *cl)
-+{
-+ assert(conn != NULL);
-+ conn->closure = cl;
-+}
-+
-+/*** pptp_conn_closure_get ****************************************************/
-+void * pptp_conn_closure_get(PPTP_CONN * conn)
-+{
-+ assert(conn != NULL);
-+ return conn->closure;
-+}
-+
-+/*** Reset keep-alive timer ***************************************************/
-+static void pptp_reset_timer(void)
-+{
-+ const struct itimerval tv = { { 0, 0 }, /* stop on time-out */
-+ { idle_wait, 0 } };
-+ if (idle_wait) setitimer(ITIMER_REAL, &tv, NULL);
-+}
-+
-+
-+/*** Handle keep-alive timer **************************************************/
-+static void pptp_handle_timer()
-+{
-+ int i;
-+ /* "Keep Alives and Timers, 1": check connection state */
-+ if (global.conn->conn_state != CONN_ESTABLISHED) {
-+ if (global.conn->conn_state == CONN_WAIT_STOP_REPLY)
-+ /* hard close. */
-+ pptp_conn_destroy(global.conn);
-+ else /* soft close */
-+ pptp_conn_close(global.conn, PPTP_STOP_NONE);
-+ }
-+ /* "Keep Alives and Timers, 2": check echo status */
-+ if (global.conn->ka_state == KA_OUTSTANDING) {
-+ /* no response to keep-alive */
-+ info("closing control connection due to missing echo reply");
-+ pptp_conn_close(global.conn, PPTP_STOP_NONE);
-+ } else { /* ka_state == NONE */ /* send keep-alive */
-+ struct pptp_echo_rqst rqst = {
-+ PPTP_HEADER_CTRL(PPTP_ECHO_RQST), hton32(global.conn->ka_id) };
-+ pptp_send_ctrl_packet(global.conn, &rqst, sizeof(rqst));
-+ global.conn->ka_state = KA_OUTSTANDING;
-+ }
-+ /* check incoming/outgoing call states for !IDLE && !ESTABLISHED */
-+ for (i = 0; i < vector_size(global.conn->call); i++) {
-+ PPTP_CALL * call = vector_get_Nth(global.conn->call, i);
-+ if (call->call_type == PPTP_CALL_PNS) {
-+ if (call->state.pns == PNS_WAIT_REPLY) {
-+ /* send close request */
-+ pptp_call_close(global.conn, call);
-+ assert(call->state.pns == PNS_WAIT_DISCONNECT);
-+ } else if (call->state.pns == PNS_WAIT_DISCONNECT) {
-+ /* hard-close the call */
-+ pptp_call_destroy(global.conn, call);
-+ }
-+ } else if (call->call_type == PPTP_CALL_PAC) {
-+ if (call->state.pac == PAC_WAIT_REPLY) {
-+ /* XXX FIXME -- drop the PAC connection XXX */
-+ } else if (call->state.pac == PAC_WAIT_CS_ANS) {
-+ /* XXX FIXME -- drop the PAC connection XXX */
-+ }
-+ }
-+ }
-+ pptp_reset_timer();
-+}
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_ctrl.h
-@@ -0,0 +1,57 @@
-+/* pptp_ctrl.h ... handle PPTP control connection.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_ctrl.h,v 1.5 2004/11/09 01:42:32 quozl Exp $
-+ */
-+
-+#ifndef INC_PPTP_CTRL_H
-+#define INC_PPTP_CTRL_H
-+#include <sys/types.h>
-+
-+typedef struct PPTP_CONN PPTP_CONN;
-+typedef struct PPTP_CALL PPTP_CALL;
-+
-+enum call_state { CALL_OPEN_RQST, CALL_OPEN_DONE, CALL_OPEN_FAIL,
-+ CALL_CLOSE_RQST, CALL_CLOSE_DONE };
-+enum conn_state { CONN_OPEN_RQST, CONN_OPEN_DONE, CONN_OPEN_FAIL,
-+ CONN_CLOSE_RQST, CONN_CLOSE_DONE };
-+
-+typedef void (*pptp_call_cb)(PPTP_CONN*, PPTP_CALL*, enum call_state);
-+typedef void (*pptp_conn_cb)(PPTP_CONN*, enum conn_state);
-+
-+/* if 'isclient' is true, then will send 'conn open' packet to other host.
-+ * not necessary if this is being opened by a server process after
-+ * receiving a conn_open packet from client.
-+ */
-+PPTP_CONN * pptp_conn_open(int inet_sock, int isclient,
-+ pptp_conn_cb callback);
-+PPTP_CALL * pptp_call_open(PPTP_CONN * conn, int call_id,
-+ pptp_call_cb callback, char *phonenr,int window);
-+int pptp_conn_established(PPTP_CONN * conn);
-+/* soft close. Will callback on completion. */
-+void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call);
-+/* hard close. */
-+void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call);
-+/* soft close. Will callback on completion. */
-+void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason);
-+/* hard close */
-+void pptp_conn_destroy(PPTP_CONN * conn);
-+
-+/* Add file descriptors used by pptp to fd_set. */
-+void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set, int *max_fd);
-+/* handle any pptp file descriptors set in fd_set, and clear them */
-+int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set);
-+
-+/* Get info about connection, call */
-+void pptp_call_get_ids(PPTP_CONN * conn, PPTP_CALL * call,
-+ u_int16_t * call_id, u_int16_t * peer_call_id);
-+/* Arbitrary user data about this call/connection.
-+ * It is the caller's responsibility to free this data before calling
-+ * pptp_call|conn_close()
-+ */
-+void * pptp_conn_closure_get(PPTP_CONN * conn);
-+void pptp_conn_closure_put(PPTP_CONN * conn, void *cl);
-+void * pptp_call_closure_get(PPTP_CONN * conn, PPTP_CALL * call);
-+void pptp_call_closure_put(PPTP_CONN * conn, PPTP_CALL * call, void *cl);
-+
-+#endif /* INC_PPTP_CTRL_H */
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_msg.h
-@@ -0,0 +1,303 @@
-+/* pptp.h: packet structures and magic constants for the PPTP protocol
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_msg.h,v 1.3 2003/02/15 10:37:21 quozl Exp $
-+ */
-+
-+#ifndef INC_PPTP_H
-+#define INC_PPTP_H
-+
-+/* Grab definitions of int16, int32, etc. */
-+#include <sys/types.h>
-+/* define "portable" htons, etc. */
-+#define hton8(x) (x)
-+#define ntoh8(x) (x)
-+#define hton16(x) htons(x)
-+#define ntoh16(x) ntohs(x)
-+#define hton32(x) htonl(x)
-+#define ntoh32(x) ntohl(x)
-+
-+/* PPTP magic numbers: ----------------------------------------- */
-+
-+#define PPTP_MAGIC 0x1A2B3C4D /* Magic cookie for PPTP datagrams */
-+#define PPTP_PORT 1723 /* PPTP TCP port number */
-+#define PPTP_PROTO 47 /* PPTP IP protocol number */
-+
-+/* Control Connection Message Types: --------------------------- */
-+
-+#define PPTP_MESSAGE_CONTROL 1
-+#define PPTP_MESSAGE_MANAGE 2
-+
-+/* Control Message Types: -------------------------------------- */
-+
-+/* (Control Connection Management) */
-+#define PPTP_START_CTRL_CONN_RQST 1
-+#define PPTP_START_CTRL_CONN_RPLY 2
-+#define PPTP_STOP_CTRL_CONN_RQST 3
-+#define PPTP_STOP_CTRL_CONN_RPLY 4
-+#define PPTP_ECHO_RQST 5
-+#define PPTP_ECHO_RPLY 6
-+
-+/* (Call Management) */
-+#define PPTP_OUT_CALL_RQST 7
-+#define PPTP_OUT_CALL_RPLY 8
-+#define PPTP_IN_CALL_RQST 9
-+#define PPTP_IN_CALL_RPLY 10
-+#define PPTP_IN_CALL_CONNECT 11
-+#define PPTP_CALL_CLEAR_RQST 12
-+#define PPTP_CALL_CLEAR_NTFY 13
-+
-+/* (Error Reporting) */
-+#define PPTP_WAN_ERR_NTFY 14
-+
-+/* (PPP Session Control) */
-+#define PPTP_SET_LINK_INFO 15
-+
-+/* PPTP version information: --------------------------------------*/
-+#define PPTP_VERSION_STRING "1.00"
-+#define PPTP_VERSION 0x100
-+#define PPTP_FIRMWARE_STRING "0.01"
-+#define PPTP_FIRMWARE_VERSION 0x001
-+
-+/* PPTP capabilities: ---------------------------------------------*/
-+
-+/* (Framing capabilities for msg sender) */
-+#define PPTP_FRAME_ASYNC 1
-+#define PPTP_FRAME_SYNC 2
-+#define PPTP_FRAME_ANY 3
-+
-+/* (Bearer capabilities for msg sender) */
-+#define PPTP_BEARER_ANALOG 1
-+#define PPTP_BEARER_DIGITAL 2
-+#define PPTP_BEARER_ANY 3
-+
-+#define PPTP_RESULT_GENERAL_ERROR 2
-+
-+/* (Reasons to close a connection) */
-+#define PPTP_STOP_NONE 1 /* no good reason */
-+#define PPTP_STOP_PROTOCOL 2 /* can't support peer's protocol version */
-+#define PPTP_STOP_LOCAL_SHUTDOWN 3 /* requester is being shut down */
-+
-+/* PPTP datagram structures (all data in network byte order): ----------*/
-+
-+struct pptp_header {
-+ u_int16_t length; /* message length in octets, including header */
-+ u_int16_t pptp_type; /* PPTP message type. 1 for control message. */
-+ u_int32_t magic; /* this should be PPTP_MAGIC. */
-+ u_int16_t ctrl_type; /* Control message type (0-15) */
-+ u_int16_t reserved0; /* reserved. MUST BE ZERO. */
-+};
-+
-+struct pptp_start_ctrl_conn { /* for control message types 1 and 2 */
-+ struct pptp_header header;
-+
-+ u_int16_t version; /* PPTP protocol version. = PPTP_VERSION */
-+ u_int8_t result_code; /* these two fields should be zero on rqst msg*/
-+ u_int8_t error_code; /* 0 unless result_code==2 (General Error) */
-+ u_int32_t framing_cap; /* Framing capabilities */
-+ u_int32_t bearer_cap; /* Bearer Capabilities */
-+ u_int16_t max_channels; /* Maximum Channels (=0 for PNS, PAC ignores) */
-+ u_int16_t firmware_rev; /* Firmware or Software Revision */
-+ u_int8_t hostname[64]; /* Host Name (64 octets, zero terminated) */
-+ u_int8_t vendor[64]; /* Vendor string (64 octets, zero term.) */
-+ /* MS says that end of hostname/vendor fields should be filled with */
-+ /* octets of value 0, but Win95 PPTP driver doesn't do this. */
-+};
-+
-+struct pptp_stop_ctrl_conn { /* for control message types 3 and 4 */
-+ struct pptp_header header;
-+
-+ u_int8_t reason_result; /* reason for rqst, result for rply */
-+ u_int8_t error_code; /* MUST be 0, unless rply result==2 (general err)*/
-+ u_int16_t reserved1; /* MUST be 0 */
-+};
-+
-+struct pptp_echo_rqst { /* for control message type 5 */
-+ struct pptp_header header;
-+ u_int32_t identifier; /* arbitrary value set by sender which is used */
-+ /* to match up reply and request */
-+};
-+
-+struct pptp_echo_rply { /* for control message type 6 */
-+ struct pptp_header header;
-+ u_int32_t identifier; /* should correspond to id of rqst */
-+ u_int8_t result_code;
-+ u_int8_t error_code; /* =0, unless result_code==2 (general error) */
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+};
-+
-+struct pptp_out_call_rqst { /* for control message type 7 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (unique id used to multiplex data) */
-+ u_int16_t call_sernum; /* Call Serial Number (used for logging) */
-+ u_int32_t bps_min; /* Minimum BPS (lowest acceptable line speed) */
-+ u_int32_t bps_max; /* Maximum BPS (highest acceptable line speed) */
-+ u_int32_t bearer; /* Bearer type */
-+ u_int32_t framing; /* Framing type */
-+ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
-+ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
-+ u_int16_t phone_len; /* Phone Number Length (num. of valid digits) */
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+ u_int8_t phone_num[64]; /* Phone Number (64 octets, null term.) */
-+ u_int8_t subaddress[64]; /* Subaddress (64 octets, null term.) */
-+};
-+
-+struct pptp_out_call_rply { /* for control message type 8 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
-+ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
-+ u_int8_t result_code; /* Result Code (1 is no errors) */
-+ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
-+ u_int16_t cause_code; /* Cause Code (addt'l failure information) */
-+ u_int32_t speed; /* Connect Speed (in BPS) */
-+ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
-+ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
-+ u_int32_t channel; /* Physical Channel ID (for logging) */
-+};
-+
-+struct pptp_in_call_rqst { /* for control message type 9 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (unique id used to multiplex data) */
-+ u_int16_t call_sernum; /* Call Serial Number (used for logging) */
-+ u_int32_t bearer; /* Bearer type */
-+ u_int32_t channel; /* Physical Channel ID (for logging) */
-+ u_int16_t dialed_len; /* Dialed Number Length (# of valid digits) */
-+ u_int16_t dialing_len; /* Dialing Number Length (# of valid digits) */
-+ u_int8_t dialed_num[64]; /* Dialed Number (64 octets, zero term.) */
-+ u_int8_t dialing_num[64]; /* Dialing Number (64 octets, zero term.) */
-+ u_int8_t subaddress[64]; /* Subaddress (64 octets, zero term.) */
-+};
-+
-+struct pptp_in_call_rply { /* for control message type 10 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
-+ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
-+ u_int8_t result_code; /* Result Code (1 is no errors) */
-+ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
-+ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
-+ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+};
-+
-+struct pptp_in_call_connect { /* for control message type 11 */
-+ struct pptp_header header;
-+ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+ u_int32_t speed; /* Connect Speed (in BPS) */
-+ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
-+ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
-+ u_int32_t framing; /* Framing type */
-+};
-+
-+struct pptp_call_clear_rqst { /* for control message type 12 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+};
-+
-+struct pptp_call_clear_ntfy { /* for control message type 13 */
-+ struct pptp_header header;
-+ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
-+ u_int8_t result_code; /* Result Code */
-+ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
-+ u_int16_t cause_code; /* Cause Code (for ISDN, is Q.931 cause code) */
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+ u_int8_t call_stats[128]; /* Call Statistics: 128 octets, ascii, 0-term */
-+};
-+
-+struct pptp_wan_err_ntfy { /* for control message type 14 */
-+ struct pptp_header header;
-+ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+ u_int32_t crc_errors; /* CRC errors */
-+ u_int32_t frame_errors; /* Framing errors */
-+ u_int32_t hard_errors; /* Hardware overruns */
-+ u_int32_t buff_errors; /* Buffer overruns */
-+ u_int32_t time_errors; /* Time-out errors */
-+ u_int32_t align_errors; /* Alignment errors */
-+};
-+
-+struct pptp_set_link_info { /* for control message type 15 */
-+ struct pptp_header header;
-+ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst) */
-+ u_int16_t reserved1; /* MUST BE ZERO */
-+ u_int32_t send_accm; /* Send ACCM (for PPP packets; default 0xFFFFFFFF)*/
-+ u_int32_t recv_accm; /* Receive ACCM (for PPP pack.;default 0xFFFFFFFF)*/
-+};
-+
-+/* helpful #defines: -------------------------------------------- */
-+#define pptp_isvalid_ctrl(header, type, length) \
-+ (!( ( ntoh16(((struct pptp_header *)header)->length) < (length) ) || \
-+ ( ntoh16(((struct pptp_header *)header)->pptp_type) !=(type) ) || \
-+ ( ntoh32(((struct pptp_header *)header)->magic) !=PPTP_MAGIC) || \
-+ ( ntoh16(((struct pptp_header *)header)->ctrl_type) > PPTP_SET_LINK_INFO) || \
-+ ( ntoh16(((struct pptp_header *)header)->reserved0) !=0 ) ))
-+
-+#define PPTP_HEADER_CTRL(type) \
-+{ hton16(PPTP_CTRL_SIZE(type)), \
-+ hton16(PPTP_MESSAGE_CONTROL), \
-+ hton32(PPTP_MAGIC), \
-+ hton16(type), 0 }
-+
-+#define PPTP_CTRL_SIZE(type) ( \
-+(type==PPTP_START_CTRL_CONN_RQST)?sizeof(struct pptp_start_ctrl_conn): \
-+(type==PPTP_START_CTRL_CONN_RPLY)?sizeof(struct pptp_start_ctrl_conn): \
-+(type==PPTP_STOP_CTRL_CONN_RQST )?sizeof(struct pptp_stop_ctrl_conn): \
-+(type==PPTP_STOP_CTRL_CONN_RPLY )?sizeof(struct pptp_stop_ctrl_conn): \
-+(type==PPTP_ECHO_RQST )?sizeof(struct pptp_echo_rqst): \
-+(type==PPTP_ECHO_RPLY )?sizeof(struct pptp_echo_rply): \
-+(type==PPTP_OUT_CALL_RQST )?sizeof(struct pptp_out_call_rqst): \
-+(type==PPTP_OUT_CALL_RPLY )?sizeof(struct pptp_out_call_rply): \
-+(type==PPTP_IN_CALL_RQST )?sizeof(struct pptp_in_call_rqst): \
-+(type==PPTP_IN_CALL_RPLY )?sizeof(struct pptp_in_call_rply): \
-+(type==PPTP_IN_CALL_CONNECT )?sizeof(struct pptp_in_call_connect): \
-+(type==PPTP_CALL_CLEAR_RQST )?sizeof(struct pptp_call_clear_rqst): \
-+(type==PPTP_CALL_CLEAR_NTFY )?sizeof(struct pptp_call_clear_ntfy): \
-+(type==PPTP_WAN_ERR_NTFY )?sizeof(struct pptp_wan_err_ntfy): \
-+(type==PPTP_SET_LINK_INFO )?sizeof(struct pptp_set_link_info): \
-+0)
-+#define max(a,b) (((a)>(b))?(a):(b))
-+#define PPTP_CTRL_SIZE_MAX ( \
-+max(sizeof(struct pptp_start_ctrl_conn), \
-+max(sizeof(struct pptp_echo_rqst), \
-+max(sizeof(struct pptp_echo_rply), \
-+max(sizeof(struct pptp_out_call_rqst), \
-+max(sizeof(struct pptp_out_call_rply), \
-+max(sizeof(struct pptp_in_call_rqst), \
-+max(sizeof(struct pptp_in_call_rply), \
-+max(sizeof(struct pptp_in_call_connect), \
-+max(sizeof(struct pptp_call_clear_rqst), \
-+max(sizeof(struct pptp_call_clear_ntfy), \
-+max(sizeof(struct pptp_wan_err_ntfy), \
-+max(sizeof(struct pptp_set_link_info), 0)))))))))))))
-+
-+
-+/* gre header structure: -------------------------------------------- */
-+
-+#define PPTP_GRE_PROTO 0x880B
-+#define PPTP_GRE_VER 0x1
-+
-+#define PPTP_GRE_FLAG_C 0x80
-+#define PPTP_GRE_FLAG_R 0x40
-+#define PPTP_GRE_FLAG_K 0x20
-+#define PPTP_GRE_FLAG_S 0x10
-+#define PPTP_GRE_FLAG_A 0x80
-+
-+#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
-+#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
-+#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
-+#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
-+#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
-+
-+struct pptp_gre_header {
-+ u_int8_t flags; /* bitfield */
-+ u_int8_t ver; /* should be PPTP_GRE_VER (enhanced GRE) */
-+ u_int16_t protocol; /* should be PPTP_GRE_PROTO (ppp-encaps) */
-+ u_int16_t payload_len; /* size of ppp payload, not inc. gre header */
-+ u_int16_t call_id; /* peer's call_id for this session */
-+ u_int32_t seq; /* sequence number. Present if S==1 */
-+ u_int32_t ack; /* seq number of highest packet recieved by */
-+ /* sender in this session */
-+};
-+
-+#endif /* INC_PPTP_H */
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_options.h
-@@ -0,0 +1,41 @@
-+/* pptp_options.h ...... various constants used in the PPTP protocol.
-+ * #define STANDARD to emulate NT 4.0 exactly.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: pptp_options.h,v 1.3 2004/11/09 01:42:32 quozl Exp $
-+ */
-+
-+#ifndef INC_PPTP_OPTIONS_H
-+#define INC_PPTP_OPTIONS_H
-+
-+#undef PPTP_FIRMWARE_STRING
-+#undef PPTP_FIRMWARE_VERSION
-+#define PPTP_BUF_MAX 65536
-+#define PPTP_TIMEOUT 60 /* seconds */
-+extern int idle_wait;
-+extern int max_echo_wait;
-+#define PPTP_CONNECT_SPEED 1000000000
-+#define PPTP_WINDOW 3
-+#define PPTP_DELAY 0
-+#define PPTP_BPS_MIN 2400
-+#define PPTP_BPS_MAX 1000000000
-+
-+#ifndef STANDARD
-+#define PPTP_MAX_CHANNELS 65535
-+#define PPTP_FIRMWARE_STRING "0.01"
-+#define PPTP_FIRMWARE_VERSION 0x001
-+#define PPTP_HOSTNAME {'l','o','c','a','l',0}
-+#define PPTP_VENDOR {'c','a','n','a','n','i','a','n',0}
-+#define PPTP_FRAME_CAP PPTP_FRAME_ANY
-+#define PPTP_BEARER_CAP PPTP_BEARER_ANY
-+#else
-+#define PPTP_MAX_CHANNELS 5
-+#define PPTP_FIRMWARE_STRING "0.01"
-+#define PPTP_FIRMWARE_VERSION 0
-+#define PPTP_HOSTNAME {'l','o','c','a','l',0}
-+#define PPTP_VENDOR {'N','T',0}
-+#define PPTP_FRAME_CAP 2
-+#define PPTP_BEARER_CAP 1
-+#endif
-+
-+#endif /* INC_PPTP_OPTIONS_H */
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_quirks.c
-@@ -0,0 +1,54 @@
-+/* pptp_quirks.c ...... various options to fix quirks found in buggy adsl modems
-+ * mulix <mulix@actcom.co.il>
-+ *
-+ * $Id: pptp_quirks.c,v 1.2 2001/11/23 03:42:51 quozl Exp $
-+ */
-+
-+#include <string.h>
-+#include "orckit_quirks.h"
-+#include "pptp_quirks.h"
-+
-+static int quirk_index = -1;
-+
-+struct pptp_fixup pptp_fixups[] = {
-+ {BEZEQ_ISRAEL, ORCKIT, ORCKIT_ATUR3,
-+ orckit_atur3_build_hook,
-+ orckit_atur3_start_ctrl_conn_hook,
-+ orckit_atur3_set_link_hook}
-+};
-+
-+static int fixups_sz = sizeof(pptp_fixups)/sizeof(pptp_fixups[0]);
-+
-+/* return 0 on success, non 0 otherwise */
-+int set_quirk_index(int index)
-+{
-+ if (index >= 0 && index < fixups_sz) {
-+ quirk_index = index;
-+ return 0;
-+ }
-+
-+ return -1;
-+}
-+
-+int get_quirk_index()
-+{
-+ return quirk_index;
-+}
-+
-+/* return the index for this isp in the quirks table, -1 if not found */
-+int find_quirk(const char* isp_name)
-+{
-+ int i = 0;
-+ if (isp_name) {
-+ while (i < fixups_sz && pptp_fixups[i].isp) {
-+ if (!strcmp(pptp_fixups[i].isp, isp_name)) {
-+ return i;
-+ }
-+ ++i;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+
---- /dev/null
-+++ b/pppd/plugins/pptp/pptp_quirks.h
-@@ -0,0 +1,59 @@
-+/* pptp_quirks.h ...... various options to fix quirks found in buggy adsl modems
-+ * mulix <mulix@actcom.co.il>
-+ *
-+ * $Id: pptp_quirks.h,v 1.1 2001/11/20 06:30:10 quozl Exp $
-+ */
-+
-+#ifndef INC_PPTP_QUIRKS_H
-+#define INC_PPTP_QUIRKS_H
-+
-+/* isp defs - correspond to slots in the fixups table */
-+#define BEZEQ_ISRAEL "BEZEQ_ISRAEL"
-+
-+/* vendor defs */
-+
-+#define ORCKIT 1
-+#define ALCATEL 2
-+
-+/* device defs */
-+
-+#define ORCKIT_ATUR2 1
-+#define ORCKIT_ATUR3 2
-+
-+#include "pptp_msg.h"
-+#include "pptp_ctrl.h"
-+
-+struct pptp_fixup {
-+ const char* isp; /* which isp? e.g. Bezeq in Israel */
-+ int vendor; /* which vendor? e.g. Orckit */
-+ int device; /* which device? e.g. Orckit Atur3 */
-+
-+ /* use this hook to build your own out call request packet */
-+ int (*out_call_rqst_hook)(struct pptp_out_call_rqst* packet);
-+
-+ /* use this hook to build your own start control connection packet */
-+ /* note that this hook is called from two different places, depending
-+ on whether this is a request or reply */
-+ int (*start_ctrl_conn)(struct pptp_start_ctrl_conn* packet);
-+
-+ /* use this hook if you need to send a 'set_link' packet once
-+ the connection is established */
-+ int (*set_link_hook)(struct pptp_set_link_info* packet,
-+ int peer_call_id);
-+};
-+
-+extern struct pptp_fixup pptp_fixups[];
-+
-+/* find the index for this isp in the quirks table */
-+/* return the index on success, -1 if not found */
-+int find_quirk(const char* isp_name);
-+
-+/* set the global quirk index. return 0 on success, non 0 otherwise */
-+int set_quirk_index(int index);
-+
-+/* get the global quirk index. return the index on success,
-+ -1 if no quirk is defined */
-+int get_quirk_index();
-+
-+
-+#endif /* INC_PPTP_QUIRKS_H */
---- /dev/null
-+++ b/pppd/plugins/pptp/util.c
-@@ -0,0 +1,109 @@
-+/* util.c ....... error message utilities.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: util.c,v 1.11 2005/08/22 00:49:48 quozl Exp $
-+ */
-+
-+#include <stdio.h>
-+#include <stdarg.h>
-+#include <syslog.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include "util.h"
-+
-+#define MAKE_STRING(label) \
-+va_list ap; \
-+char buf[256], string[256]; \
-+va_start(ap, format); \
-+vsnprintf(buf, sizeof(buf), format, ap); \
-+snprintf(string, sizeof(string), "%s %s[%s:%s:%d]: %s", \
-+ log_string, label, func, file, line, buf); \
-+va_end(ap)
-+
-+/*** connect a file to a file descriptor **************************************/
-+int file2fd(const char *path, const char *mode, int fd)
-+{
-+ int ok = 0;
-+ FILE *file = NULL;
-+ file = fopen(path, mode);
-+ if (file != NULL && dup2(fileno(file), fd) != -1)
-+ ok = 1;
-+ if (file) fclose(file);
-+ return ok;
-+}
-+
-+/* signal to pipe delivery implementation */
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <signal.h>
-+#include <string.h>
-+
-+/* pipe private to process */
-+static int sigpipe[2];
-+
-+/* create a signal pipe, returns 0 for success, -1 with errno for failure */
-+int sigpipe_create()
-+{
-+ int rc;
-+
-+ rc = pipe(sigpipe);
-+ if (rc < 0) return rc;
-+
-+ fcntl(sigpipe[0], F_SETFD, FD_CLOEXEC);
-+ fcntl(sigpipe[1], F_SETFD, FD_CLOEXEC);
-+
-+#ifdef O_NONBLOCK
-+#define FLAG_TO_SET O_NONBLOCK
-+#else
-+#ifdef SYSV
-+#define FLAG_TO_SET O_NDELAY
-+#else /* BSD */
-+#define FLAG_TO_SET FNDELAY
-+#endif
-+#endif
-+
-+ rc = fcntl(sigpipe[1], F_GETFL);
-+ if (rc != -1)
-+ rc = fcntl(sigpipe[1], F_SETFL, rc | FLAG_TO_SET);
-+ if (rc < 0) return rc;
-+ return 0;
-+#undef FLAG_TO_SET
-+}
-+
-+/* generic handler for signals, writes signal number to pipe */
-+void sigpipe_handler(int signum)
-+{
-+ write(sigpipe[1], &signum, sizeof(signum));
-+ signal(signum, sigpipe_handler);
-+}
-+
-+/* assign a signal number to the pipe */
-+void sigpipe_assign(int signum)
-+{
-+ struct sigaction sa;
-+
-+ memset(&sa, 0, sizeof(sa));
-+ sa.sa_handler = sigpipe_handler;
-+ sigaction(signum, &sa, NULL);
-+}
-+
-+/* return the signal pipe read file descriptor for select(2) */
-+int sigpipe_fd()
-+{
-+ return sigpipe[0];
-+}
-+
-+/* read and return the pending signal from the pipe */
-+int sigpipe_read()
-+{
-+ int signum;
-+ read(sigpipe[0], &signum, sizeof(signum));
-+ return signum;
-+}
-+
-+void sigpipe_close()
-+{
-+ close(sigpipe[0]);
-+ close(sigpipe[1]);
-+}
-+
---- /dev/null
-+++ b/pppd/plugins/pptp/util.h
-@@ -0,0 +1,31 @@
-+/* util.h ....... error message utilities.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: util.h,v 1.6 2005/03/10 01:18:20 quozl Exp $
-+ */
-+
-+#ifndef INC_UTIL_H
-+#define INC_UTIL_H
-+
-+int file2fd(const char *path, const char *mode, int fd);
-+
-+/* signal to pipe delivery implementation */
-+
-+/* create a signal pipe, returns 0 for success, -1 with errno for failure */
-+int sigpipe_create();
-+
-+/* generic handler for signals, writes signal number to pipe */
-+void sigpipe_handler(int signum);
-+
-+/* assign a signal number to the pipe */
-+void sigpipe_assign(int signum);
-+
-+/* return the signal pipe read file descriptor for select(2) */
-+int sigpipe_fd();
-+
-+/* read and return the pending signal from the pipe */
-+int sigpipe_read();
-+
-+void sigpipe_close();
-+
-+#endif /* INC_UTIL_H */
---- /dev/null
-+++ b/pppd/plugins/pptp/vector.c
-@@ -0,0 +1,209 @@
-+/* vector.c ..... store a vector of PPTP_CALL information and search it
-+ * efficiently.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: vector.c,v 1.3 2003/06/17 10:12:55 reink Exp $
-+ */
-+
-+#include <stdlib.h>
-+#include <string.h>
-+#include <assert.h>
-+#include "pptp_ctrl.h"
-+#include "vector.h"
-+/* #define VECTOR_DEBUG */
-+#ifndef TRUE
-+#define TRUE 1
-+#endif
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
-+
-+struct vector_item {
-+ int key;
-+ PPTP_CALL *call;
-+};
-+
-+struct vector_struct {
-+ struct vector_item *item;
-+ int size;
-+ int alloc;
-+#ifdef VECTOR_DEBUG
-+ int key_max;
-+#endif
-+};
-+
-+static struct vector_item *binary_search(VECTOR *v, int key);
-+
-+/*** vector_create ************************************************************/
-+VECTOR *vector_create()
-+{
-+ const int INITIAL_SIZE = 4;
-+
-+ VECTOR *v = malloc(sizeof(*v));
-+ if (v == NULL) return v;
-+
-+ v->size = 0;
-+ v->alloc = INITIAL_SIZE;
-+ v->item = malloc(sizeof(*(v->item)) * (v->alloc));
-+#ifdef VECTOR_DEBUG
-+ v->key_max = -1;
-+#endif
-+ if (v->item == NULL) { free(v); return NULL; }
-+ else return v;
-+}
-+
-+/*** vector_destroy ***********************************************************/
-+void vector_destroy(VECTOR *v)
-+{
-+ free(v->item);
-+#ifdef VECTOR_DEBUG
-+ v->item = NULL;
-+#endif
-+ free(v);
-+}
-+
-+/*** vector_size **************************************************************/
-+int vector_size(VECTOR *v)
-+{
-+ assert(v != NULL);
-+ return v->size;
-+}
-+
-+/*** vector_insert*************************************************************
-+ * nice thing about file descriptors is that we are assured by POSIX
-+ * that they are monotonically increasing.
-+ */
-+int vector_insert(VECTOR *v, int key, PPTP_CALL * call)
-+{
-+ int i;
-+ assert(v != NULL && call != NULL);
-+ assert(!vector_contains(v, key));
-+#ifdef VECTOR_DEBUG
-+ assert(v->key_max < key);
-+#endif
-+ if (!(v->size < v->alloc)) {
-+ void *tmp = realloc(v->item, sizeof(*(v->item)) * 2 * v->alloc);
-+ if (tmp != NULL) {
-+ v->alloc *= 2;
-+ v->item = tmp;
-+ } else return FALSE; /* failed to alloc memory. */
-+ }
-+ assert(v->size < v->alloc);
-+ /* for safety, we make this work in the general case;
-+ * but this is optimized for adding call to the end of the vector.
-+ */
-+ for(i = v->size - 1; i >= 0; i--)
-+ if (v->item[i].key < key)
-+ break;
-+ /* insert after item i */
-+ memmove(&v->item[i + 2], &v->item[i + 1],
-+ (v->size - i - 1) * sizeof(*(v->item)));
-+ v->item[i + 1].key = key;
-+ v->item[i + 1].call = call;
-+ v->size++;
-+#ifdef VECTOR_DEBUG
-+ if (v->key_max < key) /* ie, always. */
-+ v->key_max = key;
-+#endif
-+ return TRUE;
-+}
-+
-+/*** vector_remove ************************************************************/
-+int vector_remove(VECTOR *v, int key)
-+{
-+ struct vector_item *tmp;
-+ assert(v != NULL);
-+ if ((tmp =binary_search(v,key)) == NULL) return FALSE;
-+ assert(tmp >= v->item && tmp < v->item + v->size);
-+ memmove(tmp, tmp + 1, (v->size - (v->item - tmp) - 1) * sizeof(*(v->item)));
-+ v->size--;
-+ return TRUE;
-+}
-+
-+/*** vector_search ************************************************************/
-+int vector_search(VECTOR *v, int key, PPTP_CALL **call)
-+{
-+ struct vector_item *tmp;
-+ assert(v != NULL);
-+ tmp = binary_search(v, key);
-+ if (tmp ==NULL) return FALSE;
-+ *call = tmp->call;
-+ return TRUE;
-+}
-+
-+/*** vector_contains **********************************************************/
-+int vector_contains(VECTOR *v, int key)
-+{
-+ assert(v != NULL);
-+ return (binary_search(v, key) != NULL);
-+}
-+
-+/*** vector_item **************************************************************/
-+static struct vector_item *binary_search(VECTOR *v, int key)
-+{
-+ int l,r,x;
-+ l = 0;
-+ r = v->size - 1;
-+ while (r >= l) {
-+ x = (l + r)/2;
-+ if (key < v->item[x].key) r = x - 1; else l = x + 1;
-+ if (key == v->item[x].key) return &(v->item[x]);
-+ }
-+ return NULL;
-+}
-+
-+/*** vector_scan ***************************************************************
-+ * Hmm. Let's be fancy and use a binary search for the first
-+ * unused key, taking advantage of the list is stored sorted; ie
-+ * we can look at pointers and keys at two different locations,
-+ * and if (ptr1 - ptr2) = (key1 - key2) then all the slots
-+ * between ptr1 and ptr2 are filled. Note that ptr1-ptr2 should
-+ * never be greater than key1-key2 (no duplicate keys!)... we
-+ * check for this.
-+ */
-+int vector_scan(VECTOR *v, int lo, int hi, int *key)
-+{
-+ int l,r,x;
-+ assert(v != NULL);
-+ assert(key != NULL);
-+ if ((v->size<1) || (lo < v->item[0].key)) { *key = lo; return TRUE; }
-+ /* our array bounds */
-+ l = 0; r = v->size - 1;
-+ while (r > l) {
-+ /* check for a free spot right after l */
-+ if (v->item[l].key + 1 < v->item[l + 1].key) { /* found it! */
-+ *key = v->item[l].key + 1;
-+ return TRUE;
-+ }
-+ /* no dice. Let's see if the free spot is before or after the midpoint */
-+ x = (l + r)/2;
-+ /* Okay, we have right (r), left (l) and the probe (x). */
-+ assert(x - l <= v->item[x].key - v->item[l].key);
-+ assert(r - x <= v->item[r].key - v->item[x].key);
-+ if (x - l < v->item[x].key - v->item[l].key)
-+ /* room between l and x */
-+ r = x;
-+ else /* no room between l and x */
-+ if (r - x < v->item[r].key - v->item[x].key)
-+ /* room between x and r */
-+ l = x;
-+ else /* no room between x and r, either */
-+ break; /* game over, man. */
-+ }
-+ /* no room found in already allocated space. Check to see if
-+ * there's free space above allocated entries. */
-+ if (v->item[v->size - 1].key < hi) {
-+ *key = v->item[v->size - 1].key + 1;
-+ return TRUE;
-+ }
-+ /* outta luck */
-+ return FALSE;
-+}
-+
-+/*** vector_get_Nth ***********************************************************/
-+PPTP_CALL * vector_get_Nth(VECTOR *v, int n)
-+{
-+ assert(v != NULL);
-+ assert(0 <= n && n < vector_size(v));
-+ return v->item[n].call;
-+}
---- /dev/null
-+++ b/pppd/plugins/pptp/vector.h
-@@ -0,0 +1,31 @@
-+/* vector.h ..... store a vector of PPTP_CALL information and search it
-+ * efficiently.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu>
-+ *
-+ * $Id: vector.h,v 1.1.1.1 2000/12/23 08:19:51 scott Exp $
-+ */
-+
-+#ifndef INC_VECTOR_H
-+#define INC_VECTOR_H
-+
-+#include "pptp_ctrl.h" /* for definition of PPTP_CALL */
-+
-+typedef struct vector_struct VECTOR;
-+
-+VECTOR *vector_create();
-+void vector_destroy(VECTOR *v);
-+
-+int vector_size(VECTOR *v);
-+
-+/* vector_insert and vector_search return TRUE on success, FALSE on failure. */
-+int vector_insert(VECTOR *v, int key, PPTP_CALL * call);
-+int vector_remove(VECTOR *v, int key);
-+int vector_search(VECTOR *v, int key, PPTP_CALL ** call);
-+/* vector_contains returns FALSE if not found, TRUE if found. */
-+int vector_contains(VECTOR *v, int key);
-+/* find first unused key. Returns TRUE on success, FALSE if no. */
-+int vector_scan(VECTOR *v, int lo, int hi, int *key);
-+/* get a specific PPTP_CALL ... useful only when iterating. */
-+PPTP_CALL * vector_get_Nth(VECTOR *v, int n);
-+
-+#endif /* INC_VECTOR_H */