diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-10 12:32:29 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-10 12:32:29 +0000 |
commit | 9c8997d54dc9df184bfcedeabf0b3c85cf5e6753 (patch) | |
tree | 46b83031a0da1b4458317413c00d13c252c72afa /package/ppp/patches | |
parent | eecf5b17520f6b3b6ffb45ac7dca298d93b27501 (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')
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 */ |