authenticating itself to you, of course.)
-What's new in ppp-2.4.7.
+What's new in ppp-2.4.8.
************************
+* New pppd options have been added:
+ - ifname, to set the name for the PPP interface device
+ - defaultroute-metric, to set the metric for the default route
+ - defaultroute6, to add an IPv6 default route (with nodefaultroute6
+ to prevent adding an IPv6 default route)
+ - up_sdnotify, to have pppd notify systemd when the link is up.
+
+* The rp-pppoe plugin has new options:
+ - host-uniq, to set the Host-Uniq value to send
+ - pppoe-padi-timeout, to set the timeout for discovery packets
+ - pppoe-padi-attempts, to set the number of discovery attempts.
+
+* Added the CLASS attribute in radius packets.
+
+* Sundry bug fixes.
+
+* Fixed warnings and issues found by static analysis.
+
+* Added Submitting-patches.md.
+
+
+What was new in ppp-2.4.7.
+**************************
+
* Fixed a potential security issue in parsing option files (CVE-2014-3158).
* There is a new "stop-bits" option, which takes an argument of 1 or 2,
endif
ifdef MPPE
CFLAGS += -DMPPE=1
+HEADERS += mppe.h
endif
endif
#LIBS += -lshadow $(LIBS)
endif
-ifneq ($(wildcard /usr/include/crypt.h),)
+ifneq ($(wildcard $(shell $(CC) --print-sysroot)/usr/include/crypt.h),)
CFLAGS += -DHAVE_CRYPT_H=1
LIBS += -lcrypt
endif
ifdef NEEDDES
ifndef USE_CRYPT
-CFLAGS += -I/usr/include/openssl
+CFLAGS += -I$(shell $(CC) --print-sysroot)/usr/include/openssl
LIBS += -lcrypto
else
CFLAGS += -DUSE_CRYPT=1
#include "pathnames.h"
#include "session.h"
-static const char rcsid[] = RCSID;
/* Bits in scan_authfile return value */
#define NONWILD_SERVER 1
#include "fsm.h"
#include "lcp.h"
-static const char rcsid[] = RCSID;
/*
* Options.
#include "lcp.h" /* lcp_close(), lcp_fsm */
#endif
-static const char rcsid[] = RCSID;
/*
* Unfortunately there is a bug in zlib which means that using a
#include "pppcrypt.h"
#include "magic.h"
-static const char rcsid[] = RCSID;
static void ascii2unicode __P((char[], int, u_char[]));
#include "ipcp.h"
#include "lcp.h"
-static const char rcsid[] = RCSID;
char *frame;
int framelen;
#define SHA_DIGESTSIZE 20
#endif
-static const char rcsid[] = RCSID;
eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
#ifdef USE_SRP
int fd;
#endif /* USE_SRP */
+ /*
+ * Ignore requests if we're not open
+ */
+ if (esp->es_client.ea_state <= eapClosed)
+ return;
+
/*
* Note: we update es_client.ea_id *only if* a Response
* message is being generated. Otherwise, we leave it the
}
/* Not so likely to happen. */
- if (vallen >= len + sizeof (rhostname)) {
+ if (len - vallen >= sizeof (rhostname)) {
dbglog("EAP: trimming really long peer name down");
BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
rhostname[sizeof (rhostname) - 1] = '\0';
u_char dig[SHA_DIGESTSIZE];
#endif /* USE_SRP */
+ /*
+ * Ignore responses if we're not open
+ */
+ if (esp->es_server.ea_state <= eapClosed)
+ return;
+
if (esp->es_server.ea_id != id) {
dbglog("EAP: discarding Response %d; expected ID %d", id,
esp->es_server.ea_id);
}
/* Not so likely to happen. */
- if (vallen >= len + sizeof (rhostname)) {
+ if (len - vallen >= sizeof (rhostname)) {
dbglog("EAP: trimming really long peer name down");
BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
rhostname[sizeof (rhostname) - 1] = '\0';
int id;
int len;
{
+ /*
+ * Ignore failure messages if we're not open
+ */
+ if (esp->es_client.ea_state <= eapClosed)
+ return;
+
if (!eap_client_active(esp)) {
dbglog("EAP unexpected failure message in state %s (%d)",
eap_state_name(esp->es_client.ea_state),
#define RCSID "$Id: ecp.c,v 1.4 2004/11/04 10:02:26 paulus Exp $"
-static const char rcsid[] = RCSID;
#include <string.h>
#include "pppd.h"
-static const char rcsid[] = RCSID;
/*
* eui64_ntoa - Make an ascii representation of an interface identifier
#include "pppd.h"
#include "fsm.h"
-static const char rcsid[] = RCSID;
static void fsm_timeout __P((void *));
static void fsm_rconfreq __P((fsm *, int, u_char *, int));
#include "ipcp.h"
#include "pathnames.h"
-static const char rcsid[] = RCSID;
/* global vars */
ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
#include "magic.h"
#include "pathnames.h"
-static const char rcsid[] = RCSID;
/* global vars */
ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */
int no_ifaceid_neg = 0;
/* local vars */
+static int default_route_set[NUM_PPP]; /* Have set up a default route */
static int ipv6cp_is_up;
/* Hook for a plugin to know when IPv6 protocol has come up */
{ "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local,
"Accept peer's interface identifier for us", 1 },
+ { "defaultroute6", o_bool, &ipv6cp_wantoptions[0].default_route,
+ "Add default IPv6 route", OPT_ENABLE|1, &ipv6cp_allowoptions[0].default_route },
+ { "nodefaultroute6", o_bool, &ipv6cp_allowoptions[0].default_route,
+ "disable defaultroute6 option", OPT_A2CLR,
+ &ipv6cp_wantoptions[0].default_route },
+ { "-defaultroute6", o_bool, &ipv6cp_allowoptions[0].default_route,
+ "disable defaultroute6 option", OPT_ALIAS | OPT_A2CLR,
+ &ipv6cp_wantoptions[0].default_route },
+
{ "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip,
"Use (default) IPv4 address as interface identifier", 1 },
wo->vj_protocol = IPV6CP_COMP;
#endif
+ /*
+ * XXX This controls whether the user may use the defaultroute option.
+ */
+ ao->default_route = 1;
}
#endif
if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
return 0;
+ if (wo->default_route)
+ if (sif6defaultroute(u, wo->ourid, wo->hisid))
+ default_route_set[u] = 1;
notice("ipv6_demand_conf");
notice("local LL address %s", llv6_ntoa(wo->ourid));
return;
}
+ /* assign a default route through the interface if required */
+ if (ipv6cp_wantoptions[f->unit].default_route)
+ if (sif6defaultroute(f->unit, go->ourid, ho->hisid))
+ default_route_set[f->unit] = 1;
}
demand_rexmit(PPP_IPV6);
sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
}
sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
+ /* assign a default route through the interface if required */
+ if (ipv6cp_wantoptions[f->unit].default_route)
+ if (sif6defaultroute(f->unit, go->ourid, ho->hisid))
+ default_route_set[f->unit] = 1;
+
notice("local LL address %s", llv6_ntoa(go->ourid));
notice("remote LL address %s", llv6_ntoa(ho->hisid));
}
typedef struct ipv6cp_options {
int neg_ifaceid; /* Negotiate interface identifier? */
int req_ifaceid; /* Ask peer to send interface identifier? */
+ int default_route; /* Assign default route through interface? */
int accept_local; /* accept peer's value for iface id? */
int opt_local; /* ourtoken set by option */
int opt_remote; /* histoken set by option */
#include "pathnames.h"
#include "magic.h"
-static const char rcsid[] = RCSID;
/* global vars */
ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
#include "chap-new.h"
#include "magic.h"
-static const char rcsid[] = RCSID;
/*
* When the link comes up we want to be able to wait for a short while,
#include "pppd.h"
#include "magic.h"
-static const char rcsid[] = RCSID;
-extern long mrand48 __P((void));
-extern void srand48 __P((long));
+extern long mrand48 (void);
+extern void srand48 (long);
/*
* magic_init - Initialize the magic number generator.
* and current time, currently.
*/
void
-magic_init()
+magic_init(void)
{
long seed;
struct timeval t;
* magic - Returns the next magic number.
*/
u_int32_t
-magic()
+magic(void)
{
return (u_int32_t) mrand48();
}
*/
double
-drand48()
+drand48(void)
{
return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
}
long
-mrand48()
+mrand48(void)
{
return random();
}
void
-srand48(seedval)
-long seedval;
+srand48(long seedval)
{
srandom((int)seedval);
}
* $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $
*/
-void magic_init __P((void)); /* Initialize the magic number generator */
-u_int32_t magic __P((void)); /* Returns the next magic number */
+void magic_init (void); /* Initialize the magic number generator */
+u_int32_t magic (void); /* Returns the next magic number */
/* Fill buffer with random bytes */
-void random_bytes __P((unsigned char *buf, int len));
+void random_bytes (unsigned char *buf, int len);
#include <netdb.h>
#include <utmp.h>
#include <pwd.h>
-#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "atcp.h"
#endif
-static const char rcsid[] = RCSID;
/* interface vars */
char ifname[MAXIFNAMELEN]; /* Interface name */
static sigset_t signals_handled;
static int waiting;
-static sigjmp_buf sigjmp;
+static int sigpipe[2];
char **script_env; /* Env. variable values for scripts */
int s_env_nalloc; /* # words avail at script_env */
handle_events()
{
struct timeval timo;
+ unsigned char buf[16];
kill_link = open_ccp_flag = 0;
- if (sigsetjmp(sigjmp, 1) == 0) {
- sigprocmask(SIG_BLOCK, &signals_handled, NULL);
- if (got_sighup || got_sigterm || got_sigusr2 || got_sigchld) {
- sigprocmask(SIG_UNBLOCK, &signals_handled, NULL);
- } else {
- waiting = 1;
- sigprocmask(SIG_UNBLOCK, &signals_handled, NULL);
- wait_input(timeleft(&timo));
- }
- }
+
+ /* alert via signal pipe */
+ waiting = 1;
+ /* flush signal pipe */
+ for (; read(sigpipe[0], buf, sizeof(buf)) > 0; );
+ add_fd(sigpipe[0]);
+ /* wait if necessary */
+ if (!(got_sighup || got_sigterm || got_sigusr2 || got_sigchld))
+ wait_input(timeleft(&timo));
waiting = 0;
+ remove_fd(sigpipe[0]);
+
calltimeout();
if (got_sighup) {
info("Hangup (SIGHUP)");
{
struct sigaction sa;
+ /* create pipe to wake up event handler from signal handler */
+ if (pipe(sigpipe) < 0)
+ fatal("Couldn't create signal pipe: %m");
+ fcntl(sigpipe[0], F_SETFD, fcntl(sigpipe[0], F_GETFD) | FD_CLOEXEC);
+ fcntl(sigpipe[1], F_SETFD, fcntl(sigpipe[1], F_GETFD) | FD_CLOEXEC);
+ fcntl(sigpipe[0], F_SETFL, fcntl(sigpipe[0], F_GETFL) | O_NONBLOCK);
+ fcntl(sigpipe[1], F_SETFL, fcntl(sigpipe[1], F_GETFL) | O_NONBLOCK);
+
/*
* Compute mask of all interesting signals and install signal handlers
* for each. Only one signal handler may be active at a time. Therefore,
set_ifunit(iskey)
int iskey;
{
+ char ifkey[32];
+
if (req_ifname[0] != '\0')
slprintf(ifname, sizeof(ifname), "%s", req_ifname);
else
slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
info("Using interface %s", ifname);
script_setenv("IFNAME", ifname, iskey);
+ slprintf(ifkey, sizeof(ifkey), "%d", ifunit);
+ script_setenv("UNIT", ifkey, iskey);
if (iskey) {
create_pidfile(getpid()); /* write pid to file */
create_linkpidfile(getpid());
kill_my_pg(sig);
notify(sigreceived, sig);
if (waiting)
- siglongjmp(sigjmp, 1);
+ write(sigpipe[1], &sig, sizeof(sig));
}
kill_my_pg(sig);
notify(sigreceived, sig);
if (waiting)
- siglongjmp(sigjmp, 1);
+ write(sigpipe[1], &sig, sizeof(sig));
}
{
got_sigchld = 1;
if (waiting)
- siglongjmp(sigjmp, 1);
+ write(sigpipe[1], &sig, sizeof(sig));
}
{
got_sigusr2 = 1;
if (waiting)
- siglongjmp(sigjmp, 1);
+ write(sigpipe[1], &sig, sizeof(sig));
}
/* Executing in the child */
sys_close();
#ifdef USE_TDB
- tdb_close(pppdb);
+ if (pppdb != NULL)
+ tdb_close(pppdb);
#endif
/* make sure infd, outfd and errfd won't get tromped on below */
/* make sure the string is null-terminated */
rec.dptr[rec.dsize-1] = 0;
/* parse the interface number */
- parse_num(rec.dptr, "IFNAME=ppp", &unit);
+ parse_num(rec.dptr, "UNIT=", &unit);
/* check the pid value */
if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid)
|| !process_exists(pppd_pid)
TDB_DATA kd, vd;
int ret = 0;
- slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit);
+ slprintf(ifkey, sizeof(ifkey), "UNIT=%d", unit);
kd.dptr = ifkey;
kd.dsize = strlen(ifkey);
vd = tdb_fetch(pppdb, kd);
if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) {
ep->class = EPD_MAC;
ep->length = 6;
- free(p);
return 1;
}
- if (p)
- free(p);
-
/* see if our hostname corresponds to a reasonable IP address */
hp = gethostbyname(hostname);
if (hp != NULL) {
ep->length = l;
return 1;
}
-
char *strdup __P((char *));
#endif
-static const char rcsid[] = RCSID;
struct option_value {
struct option_value *next;
free(*optptr);
*optptr = sv;
}
+ /* obfuscate original argument for things like password */
+ if (opt->flags & OPT_HIDE) {
+ memset(*argv, '?', strlen(*argv));
+ *argv = "********";
+ }
break;
case o_special_noarg:
char **argv;
{
if (phase == PHASE_INITIALIZE) {
- fprintf(stderr, "pppd version %s\n", VERSION);
+ fprintf(stdout, "pppd version %s\n", VERSION);
exit(0);
}
return 0;
c = getc(f);
}
+ word[MAXWORDLEN-1] = 0; /* make sure word is null-terminated */
/*
* End of the word: check for errors.
-#define VERSION "2.4.7"
-#define DATE "9 August 2014"
+#define VERSION "2.4.8"
+#define DATE "31 December 2019"
}
else
{
- sprintf (buffer, "%ld", pair->lvalue);
+ sprintf (buffer, "%d", pair->lvalue);
strncpy(value, buffer, (size_t) lv);
}
break;
if (*name != '/')
strcpy(ttyname, "/dev/");
- strncat(ttyname, name, sizeof(ttyname));
+ strncat(ttyname, name, sizeof(ttyname) - strlen(ttyname) -1);
for(p = map2id_list; p; p = p->next)
if (!strcmp(ttyname, p->name)) return p->id;
option = find_option(optname, OT_STR);
if (option == NULL)
- fatal("rc_conf_str: unkown config option requested: %s", optname);
+ fatal("rc_conf_str: unknown config option requested: %s", optname);
return (char *)option->val;
}
option = find_option(optname, OT_INT|OT_AUO);
if (option == NULL)
- fatal("rc_conf_int: unkown config option requested: %s", optname);
+ fatal("rc_conf_int: unknown config option requested: %s", optname);
return *((int *)option->val);
}
option = find_option(optname, OT_SRV);
if (option == NULL)
- fatal("rc_conf_srv: unkown config option requested: %s", optname);
+ fatal("rc_conf_srv: unknown config option requested: %s", optname);
return (SERVER *)option->val;
}
if ((h = strtok (buffer, " \t\n")) == NULL) /* first hostname */
continue;
- memset (hostnm, '\0', AUTH_ID_LEN);
- len = strlen (h);
- if (len > AUTH_ID_LEN)
- {
- len = AUTH_ID_LEN;
- }
- strncpy (hostnm, h, (size_t) len);
- hostnm[AUTH_ID_LEN] = '\0';
+ memset (hostnm, '\0', AUTH_ID_LEN + 1);
+ strlcpy (hostnm, h, AUTH_ID_LEN + 1);
if ((s = strtok (NULL, " \t\n")) == NULL) /* and secret field */
continue;
- memset (secret, '\0', MAX_SECRET_LENGTH);
- len = strlen (s);
- if (len > MAX_SECRET_LENGTH)
- {
- len = MAX_SECRET_LENGTH;
- }
- strncpy (secret, s, (size_t) len);
- secret[MAX_SECRET_LENGTH] = '\0';
+ memset (secret, '\0', MAX_SECRET_LENGTH + 1);
+ strlcpy (secret, s, MAX_SECRET_LENGTH + 1);
if (!strchr (hostnm, '/')) /* If single name form */
{
char *
rc_mksid (void)
{
- static char buf[15];
+ static char buf[32];
static unsigned short int cnt = 0;
- sprintf (buf, "%08lX%04X%02hX",
+ slprintf(buf, sizeof(buf), "%08lX%04X%02hX",
(unsigned long int) time (NULL),
(unsigned int) getpid (),
cnt & 0xFF);
/* Step through the tags */
curTag = packet->payload;
- while(curTag - packet->payload < len) {
+ while (curTag - packet->payload + TAG_HDR_SIZE <= len) {
/* Alignment is not guaranteed, so do this by hand... */
tagType = (curTag[0] << 8) + curTag[1];
tagLen = (curTag[2] << 8) + curTag[3];
/* Define if you have the <netpacket/packet.h> header file. */
#define HAVE_NETPACKET_PACKET_H 1
-/* Define if you have the <sys/cdefs.h> header file. */
-#define HAVE_SYS_CDEFS_H 1
-
/* Define if you have the <sys/dlpi.h> header file. */
/* #undef HAVE_SYS_DLPI_H */
static void
PPPOEDeviceOptions(void)
{
- char buf[256];
- snprintf(buf, 256, _PATH_ETHOPT "%s", devnam);
+ char buf[MAXPATHLEN];
+
+ strlcpy(buf, _PATH_ETHOPT, MAXPATHLEN);
+ strlcat(buf, devnam, MAXPATHLEN);
if (!options_from_file(buf, 0, 0, 1))
exit(EXIT_OPTION_ERROR);
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <time.h>
#include "pppoe.h"
#error Unknown method for accessing raw Ethernet frames
#endif
-#ifdef HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
value of -1, the route is only added if there is no default route at
all.
.TP
+.B defaultroute6
+Add a default IPv6 route to the system routing tables, using the peer as
+the gateway, when IPv6CP negotiation is successfully completed.
+This entry is removed when the PPP connection is broken. This option
+is privileged if the \fInodefaultroute6\fR option has been specified.
+.TP
.B disconnect \fIscript
Execute the command specified by \fIscript\fR, by passing it to a
shell, after
wishes to prevent users from creating default routes with pppd
can do so by placing this option in the /etc/ppp/options file.
.TP
+.B nodefaultroute6
+Disable the \fIdefaultroute6\fR option. The system administrator who
+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 nodeflate
Disables Deflate compression; pppd will not request or agree to
compress packets using the Deflate scheme.
.I PPP in HDLC-like Framing.
July 1994.
.TP
+.B RFC1990
+Sklower, K.; et al.,
+.I The PPP Multilink Protocol (MP).
+August 1996.
+.TP
.B RFC2284
Blunk, L.; Vollbrecht, J.,
.I PPP Extensible Authentication Protocol (EAP).
#define __PPPD_H__
#include <stdio.h> /* for FILE */
+#include <stdlib.h> /* for encrypt */
+#include <unistd.h> /* for setkey */
#include <limits.h> /* for NGROUPS_MAX */
#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
#include <sys/types.h> /* for u_int32_t, if defined */
/* Create default route through i/f */
int cifdefaultroute __P((int, u_int32_t, u_int32_t));
/* Delete default route through i/f */
+#ifdef INET6
+int sif6defaultroute __P((int, eui64_t, eui64_t));
+ /* Create default IPv6 route through i/f */
+int cif6defaultroute __P((int, eui64_t, eui64_t));
+ /* Delete default IPv6 route through i/f */
+#endif
int sifproxyarp __P((int, u_int32_t));
/* Add proxy ARP entry for peer */
int cifproxyarp __P((int, u_int32_t));
memset((void *)&ll, 0, sizeof(ll));
(void)time(&tnow);
ll.ll_time = tnow;
- (void)strncpy(ll.ll_line, ttyName, sizeof(ll.ll_line));
- (void)strncpy(ll.ll_host, ifname, sizeof(ll.ll_host));
+ strlcpy(ll.ll_line, ttyName, sizeof(ll.ll_line));
+ strlcpy(ll.ll_host, ifname, sizeof(ll.ll_host));
(void)write(fd, (char *)&ll, sizeof(ll));
(void)close(fd);
}
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#include <string.h>
+#include <time.h>
#include <netinet/in.h> /* htonl() */
#include <net/ppp_defs.h>
#include "sha1.h"
#define MAX_ADDR_LEN 7
#endif
-#if __GLIBC__ >= 2
+#if !defined(__GLIBC__) || __GLIBC__ >= 2
#include <asm/types.h> /* glibc 2 conflicts with linux/types.h */
#include <net/if.h>
#include <net/if_arp.h>
eui64_copy(eui64, sin6.s6_addr32[2]); \
} while (0)
+static const eui64_t nulleui64;
#endif /* INET6 */
/* We can get an EIO error on an ioctl if the modem has hung up */
static int if_is_up; /* Interface has been marked up */
static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */
static int have_default_route; /* Gateway for default route added */
+static int have_default_route6; /* Gateway for default IPv6 route added */
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 */
static int open_route_table (void);
static int read_route_table (struct rtentry *rt);
static int defaultroute_exists (struct rtentry *rt, int metric);
+static int defaultroute6_exists (struct in6_rtmsg *rt, int metric);
static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
char *name, int namelen);
static void decode_version (char *buf, int *version, int *mod, int *patch);
*/
if (have_default_route)
cifdefaultroute(0, 0, 0);
+#ifdef INET6
+ if (have_default_route6)
+ cif6defaultroute(0, nulleui64, nulleui64);
+#endif
if (has_proxy_arp)
cifproxyarp(0, proxy_arp_addr);
char t[MAXIFNAMELEN];
memset(&ifr, 0, sizeof(struct ifreq));
slprintf(t, sizeof(t), "%s%d", PPP_DRV_NAME, ifunit);
- strncpy(ifr.ifr_name, t, IF_NAMESIZE);
- strncpy(ifr.ifr_newname, req_ifname, IF_NAMESIZE);
+ strlcpy(ifr.ifr_name, t, IF_NAMESIZE);
+ strlcpy(ifr.ifr_newname, req_ifname, IF_NAMESIZE);
x = ioctl(sock_fd, SIOCSIFNAME, &ifr);
if (x < 0)
error("Couldn't rename interface %s to %s: %m", t, req_ifname);
return 1;
}
+#ifdef INET6
+/*
+ * /proc/net/ipv6_route parsing stuff.
+ */
+static int route_dest_plen_col;
+static int open_route6_table (void);
+static int read_route6_table (struct in6_rtmsg *rt);
+
+/********************************************************************
+ *
+ * open_route6_table - open the interface to the route table
+ */
+static int open_route6_table (void)
+{
+ char *path;
+
+ close_route_table();
+
+ path = path_to_procfs("/net/ipv6_route");
+ route_fd = fopen (path, "r");
+ if (route_fd == NULL) {
+ error("can't open routing table %s: %m", path);
+ return 0;
+ }
+
+ /* default to usual columns */
+ route_dest_col = 0;
+ route_dest_plen_col = 1;
+ route_gw_col = 4;
+ route_metric_col = 5;
+ route_flags_col = 8;
+ route_dev_col = 9;
+ route_num_cols = 10;
+
+ return 1;
+}
+
+/********************************************************************
+ *
+ * read_route6_table - read the next entry from the route table
+ */
+
+static void hex_to_in6_addr(struct in6_addr *addr, const char *s)
+{
+ char hex8[9];
+ unsigned i;
+ uint32_t v;
+
+ hex8[8] = 0;
+ for (i = 0; i < 4; i++) {
+ memcpy(hex8, s + 8*i, 8);
+ v = strtoul(hex8, NULL, 16);
+ addr->s6_addr32[i] = v;
+ }
+}
+
+static int read_route6_table(struct in6_rtmsg *rt)
+{
+ char *cols[ROUTE_MAX_COLS], *p;
+ int col;
+
+ memset (rt, '\0', sizeof (struct in6_rtmsg));
+
+ if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
+ return 0;
+
+ p = route_buffer;
+ for (col = 0; col < route_num_cols; ++col) {
+ cols[col] = strtok(p, route_delims);
+ if (cols[col] == NULL)
+ return 0; /* didn't get enough columns */
+ p = NULL;
+ }
+
+ hex_to_in6_addr(&rt->rtmsg_dst, cols[route_dest_col]);
+ rt->rtmsg_dst_len = strtoul(cols[route_dest_plen_col], NULL, 16);
+ hex_to_in6_addr(&rt->rtmsg_gateway, cols[route_gw_col]);
+
+ rt->rtmsg_metric = strtoul(cols[route_metric_col], NULL, 16);
+ rt->rtmsg_flags = strtoul(cols[route_flags_col], NULL, 16);
+ rt->rtmsg_ifindex = if_nametoindex(cols[route_dev_col]);
+
+ return 1;
+}
+
+/********************************************************************
+ *
+ * defaultroute6_exists - determine if there is a default route
+ */
+
+static int defaultroute6_exists (struct in6_rtmsg *rt, int metric)
+{
+ int result = 0;
+
+ if (!open_route6_table())
+ return 0;
+
+ while (read_route6_table(rt) != 0) {
+ if ((rt->rtmsg_flags & RTF_UP) == 0)
+ continue;
+
+ if (rt->rtmsg_dst_len != 0)
+ continue;
+ if (rt->rtmsg_dst.s6_addr32[0] == 0L
+ && rt->rtmsg_dst.s6_addr32[1] == 0L
+ && rt->rtmsg_dst.s6_addr32[2] == 0L
+ && rt->rtmsg_dst.s6_addr32[3] == 0L
+ && (metric < 0 || rt->rtmsg_metric == metric)) {
+ result = 1;
+ break;
+ }
+ }
+
+ close_route_table();
+ return result;
+}
+
+/********************************************************************
+ *
+ * sif6defaultroute - assign a default route through the address given.
+ *
+ * If the global default_rt_repl_rest flag is set, then this function
+ * already replaced the original system defaultroute with some other
+ * route and it should just replace the current defaultroute with
+ * another one, without saving the current route. Use: demand mode,
+ * when pppd sets first a defaultroute it it's temporary ppp0 addresses
+ * and then changes the temporary addresses to the addresses for the real
+ * ppp connection when it has come up.
+ */
+
+int sif6defaultroute (int unit, eui64_t ouraddr, eui64_t gateway)
+{
+ struct in6_rtmsg rt;
+ char buf[IF_NAMESIZE];
+
+ if (defaultroute6_exists(&rt, dfl_route_metric) &&
+ rt.rtmsg_ifindex != if_nametoindex(ifname)) {
+ if (rt.rtmsg_flags & RTF_GATEWAY)
+ error("not replacing existing default route via gateway");
+ else
+ error("not replacing existing default route through %s",
+ if_indextoname(rt.rtmsg_ifindex, buf));
+ return 0;
+ }
+
+ memset (&rt, 0, sizeof (rt));
+
+ rt.rtmsg_ifindex = if_nametoindex(ifname);
+ rt.rtmsg_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
+ rt.rtmsg_dst_len = 0;
+
+ rt.rtmsg_flags = RTF_UP;
+ if (ioctl(sock6_fd, SIOCADDRT, &rt) < 0) {
+ if ( ! ok_error ( errno ))
+ error("default route ioctl(SIOCADDRT): %m");
+ return 0;
+ }
+
+ have_default_route6 = 1;
+ return 1;
+}
+
+/********************************************************************
+ *
+ * cif6defaultroute - delete a default route through the address given.
+ */
+
+int cif6defaultroute (int unit, eui64_t ouraddr, eui64_t gateway)
+{
+ struct in6_rtmsg rt;
+
+ have_default_route6 = 0;
+
+ memset (&rt, '\0', sizeof (rt));
+
+ rt.rtmsg_ifindex = if_nametoindex(ifname);
+ rt.rtmsg_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
+ rt.rtmsg_dst_len = 0;
+
+ rt.rtmsg_flags = RTF_UP;
+ if (ioctl(sock6_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
+ if (still_ppp()) {
+ if ( ! ok_error ( errno ))
+ error("default route ioctl(SIOCDELRT): %m");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif /* INET6 */
+
/********************************************************************
*
* sifproxyarp - Make a proxy ARP entry for the peer.
#define UDP6_DEV_NAME "/dev/udp6"
#endif /* !defined(UDP6_DEV_NAME) && defined(SOL2) */
-static const char rcsid[] = RCSID;
#if defined(SOL2)
/*
static int ip6muxid = -1; /* Multiplexer file descriptor */
static int if6_is_up = 0; /* IPv6 interface has been marked up */
+#define IN6_SOCKADDR_FROM_EUI64(s, eui64) do { \
+ (s)->sin6_family = AF_INET6; \
+ (s)->sin6_addr.s6_addr32[0] = htonl(0xfe800000); \
+ eui64_copy(eui64, (s)->sin6_addr.s6_addr32[2]); \
+ } while(0)
+
#define _IN6_LLX_FROM_EUI64(l, s, eui64, as) do { \
s->sin6_addr.s6_addr32[0] = htonl(as); \
eui64_copy(eui64, s->sin6_addr.s6_addr32[2]); \
l.lifr_addr = laddr; \
} while (0)
+#define _IN6A_LLX_FROM_EUI64(s, eui64, as) do { \
+ s->s6_addr32[0] = htonl(as); \
+ eui64_copy(eui64, s->s6_addr32[2]); \
+ } while (0)
+
#define IN6_LLADDR_FROM_EUI64(l, s, eui64) \
_IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000)
#define IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \
_IN6_LLX_FROM_EUI64(l, s, eui64, 0)
+#define IN6A_LLADDR_FROM_EUI64(s, eui64) \
+ _IN6A_LLX_FROM_EUI64(s, eui64, 0xfe800000)
+
#endif /* defined(INET6) && defined(SOL2) */
#if defined(INET6) && defined(SOL2)
static int if_is_up; /* Interface has been marked up */
static u_int32_t remote_addr; /* IP address of peer */
static u_int32_t default_route_gateway; /* Gateway for default route added */
+static eui64_t default_route_gateway6; /* Gateway for default IPv6 route added */
static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
/* Prototypes for procedures local to this file. */
sifdown(0);
if (default_route_gateway)
cifdefaultroute(0, default_route_gateway, default_route_gateway);
+ if (default_route_gateway6.e32[0] != 0 || default_route_gateway6.e32[1] != 0)
+ cif6defaultroute(0, default_route_gateway6, default_route_gateway6);
if (proxy_arp_addr)
cifproxyarp(0, proxy_arp_addr);
#if defined(SOL2)
return 1;
}
+/*
+ * sif6defaultroute - assign a default route through the address given.
+ */
+int
+sif6defaultroute(u, l, g)
+ int u;
+ eui64_t l, g;
+{
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_in6 dst;
+ struct sockaddr_in6 gw;
+ } rmsg;
+ static int seq;
+ int rtsock;
+
+#if defined(__USLC__)
+ g = l; /* use the local address as gateway */
+#endif
+ memset(&rmsg, 0, sizeof(rmsg));
+
+ rmsg.rtm.rtm_msglen = sizeof (rmsg);
+ rmsg.rtm.rtm_version = RTM_VERSION;
+ rmsg.rtm.rtm_type = RTM_ADD;
+ rmsg.rtm.rtm_flags = RTF_GATEWAY;
+ rmsg.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
+ rmsg.rtm.rtm_pid = getpid();
+ rmsg.rtm.rtm_seq = seq++;
+
+ rmsg.dst.sin6_family = AF_INET6;
+
+ rmsg.gw.sin6_family = AF_INET6;
+ IN6_SOCKADDR_FROM_EUI64(&rmsg.gw, g);
+
+ rtsock = socket(PF_ROUTE, SOCK_RAW, 0);
+
+ if (rtsock < 0) {
+ error("Can't add default route: %m");
+ return 0;
+ }
+
+ if (write(rtsock, &rmsg, sizeof(rmsg)) < 0)
+ error("Can't add default route: %m");
+
+ close(rtsock);
+
+ default_route_gateway6 = g;
+ return 1;
+}
+
+/*
+ * cif6defaultroute - delete a default route through the address given.
+ */
+int
+cif6defaultroute(u, l, g)
+ int u;
+ eui64_t l, g;
+{
+ /* No need to do this on Solaris; the kernel deletes the
+ route when the interface goes down. */
+ memset(&default_route_gateway6, 0, sizeof(default_route_gateway6));
+ return 1;
+}
+
#endif /* defined(SOL2) && defined(INET6) */
#include <netdb.h>
#include <utmp.h>
#include <pwd.h>
-#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "pppd.h"
#include "upap.h"
-static const char rcsid[] = RCSID;
static bool hide_password = 1;
#include "fsm.h"
#include "lcp.h"
-static const char rcsid[] = RCSID;
#if defined(SUNOS4)
extern char *strerror();
u_int32_t ip;
static char hexchars[] = "0123456789abcdef";
struct buffer_info bufinfo;
+ int termch;
buf0 = buf;
--buflen;
p = (unsigned char *)"<NULL>";
if (fillch == '0' && prec >= 0) {
n = prec;
+ termch = -1; /* matches no unsigned char value */
} else {
- n = strlen((char *)p);
- if (prec >= 0 && n > prec)
+ n = buflen;
+ if (prec != -1 && n > prec)
n = prec;
+ termch = 0; /* stop on null byte */
}
while (n > 0 && buflen > 0) {
c = *p++;
+ if (c == termch)
+ break;
--n;
if (!quoted && c >= 0x80) {
OUTCHAR('M');
}
len = num + sizeof(num) - 1 - str;
} else {
- len = strlen(str);
- if (prec >= 0 && len > prec)
- len = prec;
+ for (len = 0; len < buflen && (prec == -1 || len < prec); ++len)
+ if (str[len] == 0)
+ break;
}
if (width > 0) {
if (width > buflen)
++r;
++r;
if (endp - r > mru)
- printf(" ERROR: length (%d) > MRU (%d)\n",
+ printf(" ERROR: length (%zd) > MRU (%d)\n",
endp - r, mru);
if (decompress && fcs == PPP_GOODFCS) {
/* See if this is a CCP or compressed packet */