# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../ppp/ppp-2.4.5-upstream-git-fixes-20110911.patch # Copyright (C) 2011 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or 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. # --- SDE-COPYRIGHT-NOTE-END --- From e7537958aee79b3f653c601e903cb31d78fb7dcc Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Tue, 9 Feb 2010 17:32:15 +0100 Subject: [PATCH 1/9] Document +ipv6 and ipv6cp-accept-local Signed-off-by: Ludwig Nussel Signed-off-by: Paul Mackerras --- pppd/pppd.8 | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git ppp-2.4.5-release/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8 index 8ea8200..b7adc77 100644 --- ppp-2.4.5-release/pppd/pppd.8 +++ ppp-2.4.5/pppd/pppd.8 @@ -193,6 +193,9 @@ will not accept a different value from the peer in the IPCP negotiation, unless the \fIipcp\-accept\-local\fR and/or \fIipcp\-accept\-remote\fR options are given, respectively. .TP +.B +ipv6 +Enable the IPv6CP and IPv6 protocols. +.TP .B ipv6 \fI\fR,\fI Set the local and/or remote 64-bit interface identifier. Either one may be omitted. The identifier must be specified in standard ascii notation of @@ -449,6 +452,11 @@ scripts. If this option is given, the \fIstring\fR supplied is given as the 6th parameter to those scripts. .TP +.B ipv6cp\-accept\-local +With this option, pppd will accept the peer's idea of our local IPv6 +interface identifier, even if the local IPv6 interface identifier +was specified in an option. +.TP .B ipv6cp\-max\-configure \fIn Set the maximum number of IPv6CP configure-request transmissions to \fIn\fR (default 10). -- 1.6.6.2 From 406215672cfadc03017341fe03802d1c7294b903 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Tue, 9 Feb 2010 17:32:16 +0100 Subject: [PATCH 2/9] Install pppol2tp plugins with sane permissions Signed-off-by: Ludwig Nussel Signed-off-by: Paul Mackerras --- pppd/plugins/pppol2tp/Makefile.linux | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git ppp-2.4.5-release/pppd/plugins/pppol2tp/Makefile.linux ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux index 19eff67..ea3538e 100644 --- ppp-2.4.5-release/pppd/plugins/pppol2tp/Makefile.linux +++ ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux @@ -20,7 +20,7 @@ all: $(PLUGINS) install: all $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -c -m 4550 $(PLUGINS) $(LIBDIR) + $(INSTALL) -c -m 755 $(PLUGINS) $(LIBDIR) clean: rm -f *.o *.so -- 1.6.6.2 From 3eb9e810cfa515543655659b72dde30c54fea0a5 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 7 Mar 2010 15:21:38 +1100 Subject: [PATCH 3/9] pppd: Terminate correctly if lcp_lowerup delayed calling fsm_lowerup Cameron Hutchison noticed that if pppd gets asked to terminate the link in the period between when lcp_lowerup() is called and when fsm_lowerup() is called from lcp_delayed_up() (i.e. when listen_time is non-zero), pppd never exits. The reason is that lcp_close() doesn't handle the delayed-up case properly. Since the FSM is still in STOPPED state, we don't call lcp_finished() and therefore never exit the main event loop. This fixes it by handling the delayed-up case in lcp_close() as if we had done the lowerup but the OPT_SILENT bit was set. We use the silent case because we don't want to actually send a configure-request at this point. Signed-off-by: Paul Mackerras --- pppd/lcp.c | 28 +++++++++++++++++++--------- 1 files changed, 19 insertions(+), 9 deletions(-) diff --git ppp-2.4.5-release/pppd/lcp.c ppp-2.4.5/pppd/lcp.c index 5c77490..8ed2778 100644 --- ppp-2.4.5-release/pppd/lcp.c +++ ppp-2.4.5/pppd/lcp.c @@ -397,21 +397,29 @@ lcp_close(unit, reason) char *reason; { fsm *f = &lcp_fsm[unit]; + int oldstate; if (phase != PHASE_DEAD && phase != PHASE_MASTER) new_phase(PHASE_TERMINATE); - if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { + + if (f->flags & DELAYED_UP) { + untimeout(lcp_delayed_up, f); + f->state = STOPPED; + } + oldstate = f->state; + + fsm_close(f, reason); + if (oldstate == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP)) { /* * This action is not strictly according to the FSM in RFC1548, * but it does mean that the program terminates if you do a - * lcp_close() in passive/silent mode when a connection hasn't - * been established. + * lcp_close() when a connection hasn't been established + * because we are in passive/silent mode or because we have + * delayed the fsm_lowerup() call and it hasn't happened yet. */ - f->state = CLOSED; + f->flags &= ~DELAYED_UP; lcp_finished(f); - - } else - fsm_close(f, reason); + } } @@ -453,9 +461,10 @@ lcp_lowerdown(unit) { fsm *f = &lcp_fsm[unit]; - if (f->flags & DELAYED_UP) + if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; - else + untimeout(lcp_delayed_up, f); + } else fsm_lowerdown(&lcp_fsm[unit]); } @@ -489,6 +498,7 @@ lcp_input(unit, p, len) if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; + untimeout(lcp_delayed_up, f); fsm_lowerup(f); } fsm_input(f, p, len); -- 1.6.6.2 From cab58617fd9d328029fffabc788020264b4fa91f Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 7 Mar 2010 16:54:00 +1100 Subject: [PATCH 4/9] rp_pppoe: Copy acName and pppd_pppoe_service after option parsing At present, the access concentrator name (acName) and service name (pppd_pppoe_service) are set by option parsing, but are used at the point of PPPOEInitDevice(), which gets called when the ethernet device name is seen. So if the rp_pppoe_service or rp_pppoe_ac options appear after the device name, they are ignored. This fixes it by using acName and pppd_pppoe_service in PPPOEConnectDevice, which gets called after all options have been parsed. Signed-off-by: Paul Mackerras --- pppd/plugins/rp-pppoe/plugin.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c index e94494b..9bd6643 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/plugin.c +++ ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c @@ -108,8 +108,6 @@ PPPOEInitDevice(void) novm("PPPoE session data"); } memset(conn, 0, sizeof(PPPoEConnection)); - conn->acName = acName; - conn->serviceName = pppd_pppoe_service; conn->ifName = devnam; conn->discoverySocket = -1; conn->sessionSocket = -1; @@ -133,6 +131,8 @@ PPPOEConnectDevice(void) { struct sockaddr_pppox sp; + conn->acName = acName; + conn->serviceName = pppd_pppoe_service; strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); if (existingSession) { unsigned int mac[ETH_ALEN]; -- 1.6.6.2 From 2b6310fd24dba8e0fca8999916a162f0a1842a84 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 23 Aug 2010 09:59:56 -0400 Subject: [PATCH 5/9] Add set and reset options to control environment variables for scripts. --- pppd/main.c | 111 +++++++++++++++++++++++++++++------ pppd/options.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- pppd/pppd.8 | 14 +++++ pppd/pppd.h | 27 +++++++-- pppd/utils.c | 7 +- 5 files changed, 302 insertions(+), 36 deletions(-) diff --git ppp-2.4.5-release/pppd/main.c ppp-2.4.5/pppd/main.c index 014d614..1b513ca 100644 --- ppp-2.4.5-release/pppd/main.c +++ ppp-2.4.5/pppd/main.c @@ -1615,6 +1615,52 @@ safe_fork(int infd, int outfd, int errfd) return 0; } +static bool +add_script_env(pos, newstring) + int pos; + char *newstring; +{ + if (pos + 1 >= s_env_nalloc) { + int new_n = pos + 17; + char **newenv = realloc(script_env, new_n * sizeof(char *)); + if (newenv == NULL) { + free(newstring - 1); + return 0; + } + script_env = newenv; + s_env_nalloc = new_n; + } + script_env[pos] = newstring; + script_env[pos + 1] = NULL; + return 1; +} + +static void +remove_script_env(pos) + int pos; +{ + free(script_env[pos] - 1); + while ((script_env[pos] = script_env[pos + 1]) != NULL) + pos++; +} + +/* + * update_system_environment - process the list of set/unset options + * and update the system environment. + */ +static void +update_system_environment() +{ + struct userenv *uep; + + for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { + if (uep->ue_isset) + setenv(uep->ue_name, uep->ue_value, 1); + else + unsetenv(uep->ue_name); + } +} + /* * device_script - run a program to talk to the specified fds * (e.g. to run the connector or disconnector script). @@ -1670,6 +1716,7 @@ device_script(program, in, out, dont_wait) fprintf(stderr, "pppd: setuid failed\n"); exit(1); } + update_system_environment(); execl("/bin/sh", "sh", "-c", program, (char *)0); perror("pppd: could not exec /bin/sh"); exit(99); @@ -1678,6 +1725,44 @@ device_script(program, in, out, dont_wait) /* + * update_script_environment - process the list of set/unset options + * and update the script environment. Note that we intentionally do + * not update the TDB. These changes are layered on top right before + * exec. It is not possible to use script_setenv() or + * script_unsetenv() safely after this routine is run. + */ +static void +update_script_environment() +{ + struct userenv *uep; + + for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { + int i; + char *p, *newstring; + int nlen = strlen(uep->ue_name); + + for (i = 0; (p = script_env[i]) != NULL; i++) { + if (strncmp(p, uep->ue_name, nlen) == 0 && p[nlen] == '=') + break; + } + if (uep->ue_isset) { + nlen += strlen(uep->ue_value) + 2; + newstring = malloc(nlen + 1); + if (newstring == NULL) + continue; + *newstring++ = 0; + slprintf(newstring, nlen, "%s=%s", uep->ue_name, uep->ue_value); + if (p != NULL) + script_env[i] = newstring; + else + add_script_env(i, newstring); + } else { + remove_script_env(i); + } + } +} + +/* * run_program - execute a program with given arguments, * but don't wait for it unless wait is non-zero. * If the program can't be executed, logs an error unless @@ -1747,6 +1832,7 @@ run_program(prog, args, must_exist, done, arg, wait) #endif /* run the program */ + update_script_environment(); execve(prog, args, script_env); if (must_exist || errno != ENOENT) { /* have to reopen the log, there's nowhere else @@ -1967,25 +2053,16 @@ script_setenv(var, value, iskey) } else { /* no space allocated for script env. ptrs. yet */ i = 0; - script_env = (char **) malloc(16 * sizeof(char *)); - if (script_env == 0) + script_env = malloc(16 * sizeof(char *)); + if (script_env == 0) { + free(newstring - 1); return; + } s_env_nalloc = 16; } - /* reallocate script_env with more space if needed */ - if (i + 1 >= s_env_nalloc) { - int new_n = i + 17; - char **newenv = (char **) realloc((void *)script_env, - new_n * sizeof(char *)); - if (newenv == 0) - return; - script_env = newenv; - s_env_nalloc = new_n; - } - - script_env[i] = newstring; - script_env[i+1] = 0; + if (!add_script_env(i, newstring)) + return; #ifdef USE_TDB if (pppdb != NULL) { @@ -2016,9 +2093,7 @@ script_unsetenv(var) if (p[-1] && pppdb != NULL) delete_db_key(p); #endif - free(p-1); - while ((script_env[i] = script_env[i+1]) != 0) - ++i; + remove_script_env(i); break; } } diff --git ppp-2.4.5-release/pppd/options.c ppp-2.4.5/pppd/options.c index 482eab9..434ab95 100644 --- ppp-2.4.5-release/pppd/options.c +++ ppp-2.4.5/pppd/options.c @@ -119,6 +119,7 @@ bool dump_options; /* print out option values */ bool dryrun; /* print out option values and exit */ char *domain; /* domain name set by domain option */ int child_wait = 5; /* # seconds to wait for children at exit */ +struct userenv *userenv_list; /* user environment variables */ #ifdef MAXOCTETS unsigned int maxoctets = 0; /* default - no limit */ @@ -135,6 +136,7 @@ struct bpf_program pass_filter;/* Filter program for packets to pass */ struct bpf_program active_filter; /* Filter program for link-active pkts */ #endif +static option_t *curopt; /* pointer to option being processed */ char *current_option; /* the name of the option being parsed */ int privileged_option; /* set iff the current option came from root */ char *option_source; /* string saying where the option came from */ @@ -167,6 +169,11 @@ static int setactivefilter __P((char **)); static int setmodir __P((char **)); #endif +static int user_setenv __P((char **)); +static void user_setprint __P((option_t *, printer_func, void *)); +static int user_unsetenv __P((char **)); +static void user_unsetprint __P((option_t *, printer_func, void *)); + static option_t *find_option __P((const char *name)); static int process_option __P((option_t *, char *, char **)); static int n_arguments __P((option_t *)); @@ -281,6 +288,13 @@ option_t general_options[] = { "Number of seconds to wait for child processes at exit", OPT_PRIO }, + { "set", o_special, (void *)user_setenv, + "Set user environment variable", + OPT_A2PRINTER | OPT_NOPRINT, (void *)user_setprint }, + { "unset", o_special, (void *)user_unsetenv, + "Unset user environment variable", + OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint }, + #ifdef HAVE_MULTILINK { "multilink", o_bool, &multilink, "Enable multilink operation", OPT_PRIO | 1 }, @@ -768,6 +782,7 @@ process_option(opt, cmd, argv) case o_special_noarg: case o_special: parser = (int (*) __P((char **))) opt->addr; + curopt = opt; if (!(*parser)(argv)) return 0; if (opt->flags & OPT_A2LIST) { @@ -881,7 +896,7 @@ check_options() static void print_option(opt, mainopt, printer, arg) option_t *opt, *mainopt; - void (*printer) __P((void *, char *, ...)); + printer_func printer; void *arg; { int i, v; @@ -944,11 +959,8 @@ print_option(opt, mainopt, printer, arg) printer(arg, " "); } if (opt->flags & OPT_A2PRINTER) { - void (*oprt) __P((option_t *, - void ((*)__P((void *, char *, ...))), - void *)); - oprt = (void (*) __P((option_t *, - void ((*)__P((void *, char *, ...))), + void (*oprt) __P((option_t *, printer_func, void *)); + oprt = (void (*) __P((option_t *, printer_func, void *)))opt->addr2; (*oprt)(opt, printer, arg); } else if (opt->flags & OPT_A2STRVAL) { @@ -986,7 +998,7 @@ print_option(opt, mainopt, printer, arg) static void print_option_list(opt, printer, arg) option_t *opt; - void (*printer) __P((void *, char *, ...)); + printer_func printer; void *arg; { while (opt->name != NULL) { @@ -1004,7 +1016,7 @@ print_option_list(opt, printer, arg) */ void print_options(printer, arg) - void (*printer) __P((void *, char *, ...)); + printer_func printer; void *arg; { struct option_list *list; @@ -1623,3 +1635,154 @@ loadplugin(argv) return 0; } #endif /* PLUGIN */ + +/* + * Set an environment variable specified by the user. + */ +static int +user_setenv(argv) + char **argv; +{ + char *arg = argv[0]; + char *eqp; + struct userenv *uep, **insp; + + if ((eqp = strchr(arg, '=')) == NULL) { + option_error("missing = in name=value: %s", arg); + return 0; + } + if (eqp == arg) { + option_error("missing variable name: %s", arg); + return 0; + } + for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { + int nlen = strlen(uep->ue_name); + if (nlen == (eqp - arg) && + strncmp(arg, uep->ue_name, nlen) == 0) + break; + } + /* Ignore attempts by unprivileged users to override privileged sources */ + if (uep != NULL && !privileged_option && uep->ue_priv) + return 1; + /* The name never changes, so allocate it with the structure */ + if (uep == NULL) { + uep = malloc(sizeof (*uep) + (eqp-arg)); + strncpy(uep->ue_name, arg, eqp-arg); + uep->ue_name[eqp-arg] = '\0'; + uep->ue_next = NULL; + insp = &userenv_list; + while (*insp != NULL) + insp = &(*insp)->ue_next; + *insp = uep; + } else { + struct userenv *uep2; + for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) { + if (uep2 != uep && !uep2->ue_isset) + break; + } + if (uep2 == NULL && !uep->ue_isset) + find_option("unset")->flags |= OPT_NOPRINT; + free(uep->ue_value); + } + uep->ue_isset = 1; + uep->ue_priv = privileged_option; + uep->ue_source = option_source; + uep->ue_value = strdup(eqp + 1); + curopt->flags &= ~OPT_NOPRINT; + return 1; +} + +static void +user_setprint(opt, printer, arg) + option_t *opt; + printer_func printer; + void *arg; +{ + struct userenv *uep, *uepnext; + + uepnext = userenv_list; + while (uepnext != NULL && !uepnext->ue_isset) + uepnext = uepnext->ue_next; + while ((uep = uepnext) != NULL) { + uepnext = uep->ue_next; + while (uepnext != NULL && !uepnext->ue_isset) + uepnext = uepnext->ue_next; + (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value); + if (uepnext != NULL) + (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name); + else + opt->source = uep->ue_source; + } +} + +static int +user_unsetenv(argv) + char **argv; +{ + struct userenv *uep, **insp; + char *arg = argv[0]; + + if (strchr(arg, '=') != NULL) { + option_error("unexpected = in name: %s", arg); + return 0; + } + if (arg == '\0') { + option_error("missing variable name for unset"); + return 0; + } + for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { + if (strcmp(arg, uep->ue_name) == 0) + break; + } + /* Ignore attempts by unprivileged users to override privileged sources */ + if (uep != NULL && !privileged_option && uep->ue_priv) + return 1; + /* The name never changes, so allocate it with the structure */ + if (uep == NULL) { + uep = malloc(sizeof (*uep) + strlen(arg)); + strcpy(uep->ue_name, arg); + uep->ue_next = NULL; + insp = &userenv_list; + while (*insp != NULL) + insp = &(*insp)->ue_next; + *insp = uep; + } else { + struct userenv *uep2; + for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) { + if (uep2 != uep && uep2->ue_isset) + break; + } + if (uep2 == NULL && uep->ue_isset) + find_option("set")->flags |= OPT_NOPRINT; + free(uep->ue_value); + } + uep->ue_isset = 0; + uep->ue_priv = privileged_option; + uep->ue_source = option_source; + uep->ue_value = NULL; + curopt->flags &= ~OPT_NOPRINT; + return 1; +} + +static void +user_unsetprint(opt, printer, arg) + option_t *opt; + printer_func printer; + void *arg; +{ + struct userenv *uep, *uepnext; + + uepnext = userenv_list; + while (uepnext != NULL && uepnext->ue_isset) + uepnext = uepnext->ue_next; + while ((uep = uepnext) != NULL) { + uepnext = uep->ue_next; + while (uepnext != NULL && uepnext->ue_isset) + uepnext = uepnext->ue_next; + (*printer)(arg, "%s", uep->ue_name); + if (uepnext != NULL) + (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name); + else + opt->source = uep->ue_source; + } +} diff --git ppp-2.4.5-release/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8 index b7adc77..7ad24c5 100644 --- ppp-2.4.5-release/pppd/pppd.8 +++ ppp-2.4.5/pppd/pppd.8 @@ -1018,6 +1018,13 @@ Authentication Protocol] authentication. Require the peer to authenticate itself using PAP [Password Authentication Protocol] authentication. .TP +.B set \fIname\fR=\fIvalue +Set an environment variable for scripts that are invoked by pppd. +When set by a privileged source, the variable specified by \fIname\fR +cannot be changed by options contained in an unprivileged source. See +also the \fIunset\fR option and the environment described in +\fISCRIPTS\fR. +.TP .B show\-password When logging the contents of PAP packets, this option causes pppd to show the password string in the log message. @@ -1058,6 +1065,13 @@ under Linux and FreeBSD 2.2.8 and later. Sets the ppp unit number (for a ppp0 or ppp1 etc interface name) for outbound connections. .TP +.B unset \fIname +Remove a variable from the environment variable for scripts that are +invoked by pppd. When specified by a privileged source, the variable +\fIname\fR cannot be set by options contained in an unprivileged +source. See also the \fIset\fR option and the environment described +in \fISCRIPTS\fR. +.TP .B updetach With this option, pppd will detach from its controlling terminal once it has successfully established the ppp connection (to the point where diff --git ppp-2.4.5-release/pppd/pppd.h ppp-2.4.5/pppd/pppd.h index cf9840a..936cc60 100644 --- ppp-2.4.5-release/pppd/pppd.h +++ ppp-2.4.5/pppd/pppd.h @@ -139,7 +139,7 @@ typedef struct { #define OPT_INITONLY 0x4000000 /* option can only be set in init phase */ #define OPT_DEVEQUIV 0x8000000 /* equiv to device name */ #define OPT_DEVNAM (OPT_INITONLY | OPT_DEVEQUIV) -#define OPT_A2PRINTER 0x10000000 /* *addr2 is a fn for printing option */ +#define OPT_A2PRINTER 0x10000000 /* *addr2 printer_func to print option */ #define OPT_A2STRVAL 0x20000000 /* *addr2 points to current string value */ #define OPT_NOPRINT 0x40000000 /* don't print this option at all */ @@ -199,6 +199,7 @@ struct epdisc { #define EPD_PHONENUM 5 typedef void (*notify_func) __P((void *, int)); +typedef void (*printer_func) __P((void *, char *, ...)); struct notifier { struct notifier *next; @@ -406,8 +407,7 @@ struct protent { /* Close the protocol */ void (*close) __P((int unit, char *reason)); /* Print a packet in readable form */ - int (*printpkt) __P((u_char *pkt, int len, - void (*printer) __P((void *, char *, ...)), + int (*printpkt) __P((u_char *pkt, int len, printer_func printer, void *arg)); /* Process a received data packet */ void (*datainput) __P((int unit, u_char *pkt, int len)); @@ -461,6 +461,21 @@ struct channel { extern struct channel *the_channel; /* + * This structure contains environment variables that are set or unset + * by the user. + */ +struct userenv { + struct userenv *ue_next; + char *ue_value; /* value (set only) */ + bool ue_isset; /* 1 for set, 0 for unset */ + bool ue_priv; /* from privileged source */ + const char *ue_source; /* source name */ + char ue_name[1]; /* variable name */ +}; + +extern struct userenv *userenv_list; + +/* * Prototypes. */ @@ -504,8 +519,8 @@ void tty_init __P((void)); /* Procedures exported from utils.c. */ void log_packet __P((u_char *, int, char *, int)); /* Format a packet and log it with syslog */ -void print_string __P((char *, int, void (*) (void *, char *, ...), - void *)); /* Format a string for output */ +void print_string __P((char *, int, printer_func, void *)); + /* Format a string for output */ int slprintf __P((char *, int, char *, ...)); /* sprintf++ */ int vslprintf __P((char *, int, char *, va_list)); /* vsprintf++ */ size_t strlcpy __P((char *, const char *, size_t)); /* safe strcpy */ @@ -691,7 +706,7 @@ void add_options __P((option_t *)); /* Add extra options */ void check_options __P((void)); /* check values after all options parsed */ int override_value __P((const char *, int, const char *)); /* override value if permitted by priority */ -void print_options __P((void (*) __P((void *, char *, ...)), void *)); +void print_options __P((printer_func, void *)); /* print out values of all options */ int parse_dotted_ip __P((char *, u_int32_t *)); diff --git ppp-2.4.5-release/pppd/utils.c ppp-2.4.5/pppd/utils.c index 062b17e..5c9ba64 100644 --- ppp-2.4.5-release/pppd/utils.c +++ ppp-2.4.5/pppd/utils.c @@ -68,8 +68,7 @@ extern char *strerror(); static void logit __P((int, char *, va_list)); static void log_write __P((int, char *)); static void vslp_printer __P((void *, char *, ...)); -static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), - void *)); +static void format_packet __P((u_char *, int, printer_func, void *)); struct buffer_info { char *ptr; @@ -475,7 +474,7 @@ static void format_packet(p, len, printer, arg) u_char *p; int len; - void (*printer) __P((void *, char *, ...)); + printer_func printer; void *arg; { int i, n; @@ -613,7 +612,7 @@ void print_string(p, len, printer, arg) char *p; int len; - void (*printer) __P((void *, char *, ...)); + printer_func printer; void *arg; { int c; -- 1.6.6.2 From 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 23 Aug 2010 10:01:48 -0400 Subject: [PATCH 6/9] Nit: use _exit when exec fails and restrict values to 0-255 per POSIX. --- pppd/main.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git ppp-2.4.5-release/pppd/main.c ppp-2.4.5/pppd/main.c index 1b513ca..6e7378b 100644 --- ppp-2.4.5-release/pppd/main.c +++ ppp-2.4.5/pppd/main.c @@ -1719,7 +1719,7 @@ device_script(program, in, out, dont_wait) update_system_environment(); execl("/bin/sh", "sh", "-c", program, (char *)0); perror("pppd: could not exec /bin/sh"); - exit(99); + _exit(99); /* NOTREACHED */ } @@ -1841,7 +1841,7 @@ run_program(prog, args, must_exist, done, arg, wait) syslog(LOG_ERR, "Can't execute %s: %m", prog); closelog(); } - _exit(-1); + _exit(99); } -- 1.6.6.2 From 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 23 Aug 2010 10:03:07 -0400 Subject: [PATCH 7/9] Fix quote handling in configuration files to be more like shell quoting. The specific case that confused a user was: ROUTES="216.220.192.0/20 10.0.100.0/24" which was interpreted as two separate words, merely because the first quote mark was in the middle of a word. --- pppd/options.c | 44 ++++++++++++++++++++++---------------------- 1 files changed, 22 insertions(+), 22 deletions(-) diff --git ppp-2.4.5-release/pppd/options.c ppp-2.4.5/pppd/options.c index 434ab95..008b482 100644 --- ppp-2.4.5-release/pppd/options.c +++ ppp-2.4.5/pppd/options.c @@ -1146,6 +1146,7 @@ getword(f, word, newlinep, filename) len = 0; escape = 0; comment = 0; + quoted = 0; /* * First skip white-space and comments. @@ -1204,15 +1205,6 @@ getword(f, word, newlinep, filename) } /* - * Save the delimiter for quoted strings. - */ - if (!escape && (c == '"' || c == '\'')) { - quoted = c; - c = getc(f); - } else - quoted = 0; - - /* * Process characters until the end of the word. */ while (c != EOF) { @@ -1300,29 +1292,34 @@ getword(f, word, newlinep, filename) if (!got) c = getc(f); continue; - } /* - * Not escaped: see if we've reached the end of the word. + * Backslash starts a new escape sequence. */ - if (quoted) { - if (c == quoted) - break; - } else { - if (isspace(c) || c == '#') { - ungetc (c, f); - break; - } + if (c == '\\') { + escape = 1; + c = getc(f); + continue; } /* - * Backslash starts an escape sequence. + * Not escaped: check for the start or end of a quoted + * section and see if we've reached the end of the word. */ - if (c == '\\') { - escape = 1; + if (quoted) { + if (c == quoted) { + quoted = 0; + c = getc(f); + continue; + } + } else if (c == '"' || c == '\'') { + quoted = c; c = getc(f); continue; + } else if (isspace(c) || c == '#') { + ungetc (c, f); + break; } /* @@ -1351,6 +1348,9 @@ getword(f, word, newlinep, filename) */ if (len == 0) return 0; + if (quoted) + option_error("warning: quoted word runs to end of file (%.20s...)", + filename, word); } /* -- 1.6.6.2 From fd1dcdf758418f040da3ed801ab001b5e46854e7 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Tue, 4 May 2010 20:06:06 +0100 Subject: [PATCH 8/9] rp-pppoe: allow MTU to be increased up to 1500 The ethernet data limit on rp-pppoe has been increased to 1508 to allow an MTU of 1500 to be used. To prevent problems the interface MTU is checked and used to lower the configured MTU/MRU. If MIN(MTU/MRU) is > 1492, PPP-Max-Payload is added to PADI and PADR. If PPP-Max-Payload is received in PADO or PADS, it will be used to lower the configured MTU/MRU as required. The MTU/MRU settings are stored and reloaded whenever a connection is made, to allow for the peer or interface MTU/MRU to increase if used with persist option. Conforming to RFC4638, if no PPP-Max-Payload is received, the negotiated MRU will be limited to 1492. --- pppd/plugins/rp-pppoe/common.c | 5 ++- pppd/plugins/rp-pppoe/discovery.c | 65 +++++++++++++++++++++++++++++++ pppd/plugins/rp-pppoe/plugin.c | 30 ++++++++++++++ pppd/plugins/rp-pppoe/pppoe-discovery.c | 2 +- pppd/plugins/rp-pppoe/pppoe.h | 22 ++++++++-- 5 files changed, 118 insertions(+), 6 deletions(-) diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/common.c ppp-2.4.5/pppd/plugins/rp-pppoe/common.c index a49efe7..3b8e014 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/common.c +++ ppp-2.4.5/pppd/plugins/rp-pppoe/common.c @@ -58,7 +58,7 @@ parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra) } /* Do some sanity checks on packet */ - if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */ + if (len > ETH_JUMBO_LEN - PPPOE_OVERHEAD) { /* 6-byte overhead for PPPoE header */ error("Invalid PPPoE packet length (%u)", len); return -1; } @@ -246,6 +246,9 @@ void pppoe_printpkt(PPPoEPacket *packet, case TAG_RELAY_SESSION_ID: printer(arg, "relay-session-id"); break; + case TAG_PPP_MAX_PAYLOAD: + printer(arg, "PPP-max-payload"); + break; case TAG_SERVICE_NAME_ERROR: printer(arg, "service-name-error"); text = 1; diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/discovery.c ppp-2.4.5/pppd/plugins/rp-pppoe/discovery.c index 6e25ae7..a856490 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/discovery.c +++ ppp-2.4.5/pppd/plugins/rp-pppoe/discovery.c @@ -14,6 +14,8 @@ static char const RCSID[] = #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" +#include "pppd/fsm.h" +#include "pppd/lcp.h" #include #include @@ -110,6 +112,7 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, { struct PacketCriteria *pc = (struct PacketCriteria *) extra; PPPoEConnection *conn = pc->conn; + UINT16_t mru; int i; switch(type) { @@ -140,6 +143,19 @@ parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, conn->relayId.length = htons(len); memcpy(conn->relayId.payload, data, len); break; + case TAG_PPP_MAX_PAYLOAD: + if (len == sizeof(mru)) { + memcpy(&mru, data, sizeof(mru)); + mru = ntohs(mru); + if (mru >= ETH_PPPOE_MTU) { + if (lcp_allowoptions[0].mru > mru) + lcp_allowoptions[0].mru = mru; + if (lcp_wantoptions[0].mru > mru) + lcp_wantoptions[0].mru = mru; + conn->seenMaxPayload = 1; + } + } + break; case TAG_SERVICE_NAME_ERROR: error("PADO: Service-Name-Error: %.*s", (int) len, data); conn->error = 1; @@ -172,10 +188,24 @@ parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { PPPoEConnection *conn = (PPPoEConnection *) extra; + UINT16_t mru; switch(type) { case TAG_SERVICE_NAME: dbglog("PADS: Service-Name: '%.*s'", (int) len, data); break; + case TAG_PPP_MAX_PAYLOAD: + if (len == sizeof(mru)) { + memcpy(&mru, data, sizeof(mru)); + mru = ntohs(mru); + if (mru >= ETH_PPPOE_MTU) { + if (lcp_allowoptions[0].mru > mru) + lcp_allowoptions[0].mru = mru; + if (lcp_wantoptions[0].mru > mru) + lcp_wantoptions[0].mru = mru; + conn->seenMaxPayload = 1; + } + } + break; case TAG_SERVICE_NAME_ERROR: error("PADS: Service-Name-Error: %.*s", (int) len, data); conn->error = 1; @@ -259,6 +289,19 @@ sendPADI(PPPoEConnection *conn) plen += sizeof(pid) + TAG_HDR_SIZE; } + /* Add our maximum MTU/MRU */ + if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { + PPPoETag maxPayload; + UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); + maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); + maxPayload.length = htons(sizeof(mru)); + memcpy(maxPayload.payload, &mru, sizeof(mru)); + CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); + memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); + cursor += sizeof(mru) + TAG_HDR_SIZE; + plen += sizeof(mru) + TAG_HDR_SIZE; + } + packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); @@ -289,6 +332,7 @@ waitForPADO(PPPoEConnection *conn, int timeout) pc.serviceNameOK = (conn->serviceName) ? 0 : 1; pc.seenACName = 0; pc.seenServiceName = 0; + conn->seenMaxPayload = 0; conn->error = 0; do { @@ -413,6 +457,19 @@ sendPADR(PPPoEConnection *conn) plen += sizeof(pid) + TAG_HDR_SIZE; } + /* Add our maximum MTU/MRU */ + if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { + PPPoETag maxPayload; + UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); + maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); + maxPayload.length = htons(sizeof(mru)); + memcpy(maxPayload.payload, &mru, sizeof(mru)); + CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); + memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); + cursor += sizeof(mru) + TAG_HDR_SIZE; + plen += sizeof(mru) + TAG_HDR_SIZE; + } + /* Copy cookie and relay-ID if needed */ if (conn->cookie.type) { CHECK_ROOM(cursor, packet.payload, @@ -566,6 +623,14 @@ discovery(PPPoEConnection *conn) timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); + if (!conn->seenMaxPayload) { + /* RFC 4638: MUST limit MTU/MRU to 1492 */ + if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU) + lcp_allowoptions[0].mru = ETH_PPPOE_MTU; + if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU) + lcp_wantoptions[0].mru = ETH_PPPOE_MTU; + } + /* We're done. */ conn->discoveryState = STATE_SESSION; return; diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/plugin.c ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c index 9bd6643..97011aa 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/plugin.c +++ ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c @@ -130,6 +130,31 @@ static int PPPOEConnectDevice(void) { struct sockaddr_pppox sp; + struct ifreq ifr; + int s; + + /* Restore configuration */ + lcp_allowoptions[0].mru = conn->mtu; + lcp_wantoptions[0].mru = conn->mru; + + /* Update maximum MRU */ + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + error("Can't get MTU for %s: %m", conn->ifName); + goto errout; + } + strncpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { + error("Can't get MTU for %s: %m", conn->ifName); + close(s); + goto errout; + } + close(s); + + if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) + lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; + if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) + lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; conn->acName = acName; conn->serviceName = pppd_pppoe_service; @@ -163,6 +188,7 @@ PPPOEConnectDevice(void) error("Failed to create PPPoE socket: %m"); goto errout; } + sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = conn->session; @@ -381,6 +407,10 @@ void pppoe_check_options(void) if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU) lcp_wantoptions[0].mru = MAX_PPPOE_MTU; + /* Save configuration */ + conn->mtu = lcp_allowoptions[0].mru; + conn->mru = lcp_wantoptions[0].mru; + ccp_allowoptions[0].deflate = 0; ccp_wantoptions[0].deflate = 0; diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/pppoe-discovery.c ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c index 318f858..3d3bf4e 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/pppoe-discovery.c +++ ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c @@ -277,7 +277,7 @@ parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra) } /* Do some sanity checks on packet */ - if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */ + if (len > ETH_JUMBO_LEN - PPPOE_OVERHEAD) { /* 6-byte overhead for PPPoE header */ fprintf(stderr, "Invalid PPPoE packet length (%u)\n", len); return -1; } diff --git ppp-2.4.5-release/pppd/plugins/rp-pppoe/pppoe.h ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe.h index 3dba439..9ab2eee 100644 --- ppp-2.4.5-release/pppd/plugins/rp-pppoe/pppoe.h +++ ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe.h @@ -129,6 +129,7 @@ extern UINT16_t Eth_PPPOE_Session; #define TAG_AC_COOKIE 0x0104 #define TAG_VENDOR_SPECIFIC 0x0105 #define TAG_RELAY_SESSION_ID 0x0110 +#define TAG_PPP_MAX_PAYLOAD 0x0120 #define TAG_SERVICE_NAME_ERROR 0x0201 #define TAG_AC_SYSTEM_ERROR 0x0202 #define TAG_GENERIC_ERROR 0x0203 @@ -167,6 +168,13 @@ extern UINT16_t Eth_PPPOE_Session; #define IPV4ALEN 4 #define SMALLBUF 256 +/* There are other fixed-size buffers preventing + this from being increased to 16110. The buffer + sizes would need to be properly de-coupled from + the default MRU. For now, getting up to 1500 is + enough. */ +#define ETH_JUMBO_LEN 1508 + /* A PPPoE Packet, including Ethernet headers */ typedef struct PPPoEPacketStruct { struct ethhdr ethHdr; /* Ethernet header */ @@ -174,7 +182,7 @@ typedef struct PPPoEPacketStruct { unsigned int code:8; /* PPPoE code */ unsigned int session:16; /* PPPoE session */ unsigned int length:16; /* Payload length */ - unsigned char payload[ETH_DATA_LEN]; /* A bit of room to spare */ + unsigned char payload[ETH_JUMBO_LEN]; /* A bit of room to spare */ } PPPoEPacket; #define PPPOE_VER(vt) ((vt) >> 4) @@ -184,15 +192,18 @@ typedef struct PPPoEPacketStruct { /* Header size of a PPPoE packet */ #define PPPOE_OVERHEAD 6 /* type, code, session, length */ #define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD) -#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD) -#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - 2) +#define MAX_PPPOE_PAYLOAD (ETH_JUMBO_LEN - PPPOE_OVERHEAD) +#define PPP_OVERHEAD 2 /* protocol */ +#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - PPP_OVERHEAD) +#define TOTAL_OVERHEAD (PPPOE_OVERHEAD + PPP_OVERHEAD) +#define ETH_PPPOE_MTU (ETH_DATA_LEN - TOTAL_OVERHEAD) /* PPPoE Tag */ typedef struct PPPoETagStruct { unsigned int type:16; /* tag type */ unsigned int length:16; /* Length of payload */ - unsigned char payload[ETH_DATA_LEN]; /* A LOT of room to spare */ + unsigned char payload[ETH_JUMBO_LEN]; /* A LOT of room to spare */ } PPPoETag; /* Header size of a PPPoE tag */ #define TAG_HDR_SIZE 4 @@ -233,6 +244,9 @@ typedef struct PPPoEConnectionStruct { int error; /* Error packet received */ int debug; /* Set to log packets sent and received */ int discoveryTimeout; /* Timeout for discovery packets */ + int seenMaxPayload; + int mtu; /* Stored MTU */ + int mru; /* Stored MRU */ } PPPoEConnection; /* Structure used to determine acceptable PADO or PADS packet */ -- 1.6.6.2 From ae80bf833e48a6202f44a935a68083ae52ad3824 Mon Sep 17 00:00:00 2001 From: Ashok Rao Date: Sat, 11 Sep 2010 22:14:48 +1000 Subject: [PATCH 9/9] chat: Allow TIMEOUT value to come from environment variable This allows the TIMEOUT value to be obtained from the environment using the $ENVVAR syntax. Signed-off-by: Paul Mackerras --- chat/chat.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git ppp-2.4.5-release/chat/chat.c ppp-2.4.5/chat/chat.c index 0b88c27..710dba9 100644 --- ppp-2.4.5-release/chat/chat.c +++ ppp-2.4.5/chat/chat.c @@ -1167,6 +1167,7 @@ register char *s; if (timeout_next) { timeout_next = 0; + s = clean(s, 0); timeout = atoi(s); if (timeout <= 0) -- 1.6.6.2