ccp_options *go = &ccp_gotoptions[f->unit];
return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
- + (go->deflate? CILEN_DEFLATE: 0)
+ + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0)
+ + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0)
+ (go->predictor_1? CILEN_PREDICTOR_1: 0)
+ (go->predictor_2? CILEN_PREDICTOR_2: 0)
+ (go->mppe? CILEN_MPPE: 0);
bool predictor_2; /* do Predictor-2? */
bool deflate_correct; /* use correct code for deflate? */
bool deflate_draft; /* use draft RFC code for deflate? */
- bool mppe; /* do MPPE? */
+ u_char mppe; /* MPPE bitfield */
u_short bsd_bits; /* # bits/code for BSD Compress */
u_short deflate_size; /* lg(window size) for Deflate */
short method; /* code for chosen compression method */
case IPX_ROUTER_NAME:
if (cilen >= CILEN_NAME) {
int name_size = cilen - CILEN_NAME;
- if (name_size > sizeof (ho->name))
+ if (name_size >= sizeof (ho->name))
name_size = sizeof (ho->name) - 1;
memset (ho->name, 0, sizeof (ho->name));
memcpy (ho->name, p, name_size);
static const char rcsid[] = RCSID;
/* interface vars */
-char ifname[32]; /* Interface name */
+char ifname[MAXIFNAMELEN]; /* Interface name */
int ifunit; /* Interface unit number */
struct channel *the_channel;
NULL
};
-/*
- * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
- */
-#if !defined(PPP_DRV_NAME)
-#define PPP_DRV_NAME "ppp"
-#endif /* !defined(PPP_DRV_NAME) */
-
int
main(argc, argv)
int argc;
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 (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);
if (iskey) {
create_pidfile(getpid()); /* write pid to file */
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 req_ifname[MAXIFNAMELEN]; /* requested interface name */
bool multilink = 0; /* Enable multilink operation */
char *bundle_name = NULL; /* bundle name for multilink */
bool dump_options; /* print out option values */
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 */
+int dfl_route_metric = -1; /* metric of the default route to set over the PPP link */
#ifdef MAXOCTETS
unsigned int maxoctets = 0; /* default - no limit */
"PPP interface unit number to use if possible",
OPT_PRIO | OPT_LLIMIT, 0, 0 },
+ { "ifname", o_string, req_ifname,
+ "Set PPP interface name",
+ OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXIFNAMELEN },
+
{ "dump", o_bool, &dump_options,
"Print out option values after parsing all options", 1 },
{ "dryrun", o_bool, &dryrun,
"Unset user environment variable",
OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint },
+ { "defaultroute-metric", o_int, &dfl_route_metric,
+ "Metric to use for the default route (Linux only; -1 for default behavior)",
+ OPT_PRIV|OPT_LLIMIT|OPT_INITONLY, NULL, 0, -1 },
+
#ifdef HAVE_MULTILINK
{ "multilink", o_bool, &multilink,
"Enable multilink operation", OPT_PRIO | 1 },
endif
all: $(PLUGINS)
- for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all; done
+ for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all || exit $$?; done
%.so: %.c
$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^
install: $(PLUGINS)
$(INSTALL) -d $(LIBDIR)
$(INSTALL) $? $(LIBDIR)
- for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install; done
+ for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install || exit $$?; done
clean:
rm -f *.o *.so *.a
- for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean; done
+ for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean || exit $$?; done
depend:
$(CPP) -M $(CFLAGS) *.c >.depend
- for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend; done
+ for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend || exit $$?; done
memcpy(sp.sa_addr.pppoe.dev, conn->ifName, IFNAMSIZ);
memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN);
if (connect(conn->sessionSocket, (struct sockaddr *) &sp,
- sizeof(struct sockaddr_pppox)) < 0)
+ sizeof(struct sockaddr_pppox)) < 0 && errno != EALREADY)
error("Failed to disconnect PPPoE socket: %d %m", errno);
close(conn->sessionSocket);
- /* don't send PADT?? */
- if (conn->discoverySocket >= 0)
+ if (conn->discoverySocket >= 0) {
+ sendPADT(conn, NULL);
close(conn->discoverySocket);
+ }
}
static void
#include <sys/socket.h>
#endif
+/* This has to be included before Linux 4.8's linux/in.h
+ * gets dragged in. */
+#include <netinet/in.h>
+
/* Ugly header files on some Linux boxes... */
#if defined(HAVE_LINUX_IF_H)
#include <linux/if.h>
#include <linux/if_ether.h>
#endif
-#include <netinet/in.h>
-
#ifdef HAVE_NETINET_IF_ETHER_H
#include <sys/types.h>
#endif
-
/* Ethernet frame types according to RFC 2516 */
#define ETH_PPPOE_DISCOVERY 0x8863
#define ETH_PPPOE_SESSION 0x8864
This entry is removed when the PPP connection is broken. This option
is privileged if the \fInodefaultroute\fR option has been specified.
.TP
+.B defaultroute-metric
+Define the metric of the \fIdefaultroute\fR and only add it if there
+is no other default route with the same metric. With the default
+value of -1, the route is only added if there is no default route at
+all.
+.TP
.B disconnect \fIscript
Execute the command specified by \fIscript\fR, by passing it to a
shell, after
.TP
.B unit \fInum
Sets the ppp unit number (for a ppp0 or ppp1 etc interface name) for outbound
-connections.
+connections. If the unit is already in use a dynamically allocated number will
+be used.
+.TP
+.B ifname \fIstring
+Set the ppp interface name for outbound connections. If the interface name is
+already in use, or if the name cannot be used for any other reason, pppd will
+terminate.
.TP
.B unset \fIname
Remove a variable from the environment variable for scripts that are
#define MAXARGS 1 /* max # args to a command */
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
#define MAXSECRETLEN 256 /* max length of password or secret */
+#define MAXIFNAMELEN 32 /* max length of interface name; or use IFNAMSIZ, can we
+ always include net/if.h? */
+
+/*
+ * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
+ * Where should PPP_DRV_NAME come from? Do we include it here?
+ */
+#if !defined(PPP_DRV_NAME)
+#define PPP_DRV_NAME "ppp"
+#endif /* !defined(PPP_DRV_NAME) */
/*
* Option descriptor structure.
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 req_ifname[MAXIFNAMELEN]; /* interface name to use */
extern bool multilink; /* enable multilink operation */
extern bool noendpoint; /* don't send or accept endpt. discrim. */
extern char *bundle_name; /* bundle name for multilink */
static void close_route_table (void);
static int open_route_table (void);
static int read_route_table (struct rtentry *rt);
-static int defaultroute_exists (struct rtentry *rt);
+static int defaultroute_exists (struct rtentry *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);
extern u_char inpacket_buf[]; /* borrowed from main.c */
+extern int dfl_route_metric;
+
/*
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
* if it exists.
}
if (x < 0)
error("Couldn't create new ppp unit: %m");
+
+ if (x == 0 && req_ifname[0] != '\0') {
+ struct ifreq ifr;
+ 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);
+ x = ioctl(sock_fd, SIOCSIFNAME, &ifr);
+ if (x < 0)
+ error("Couldn't rename interface %s to %s: %m", t, req_ifname);
+ else
+ info("Renamed interface %s to %s", t, req_ifname);
+ }
+
return x;
}
FILE *route_fd = (FILE *) 0;
static char route_buffer[512];
static int route_dev_col, route_dest_col, route_gw_col;
-static int route_flags_col, route_mask_col;
+static int route_flags_col, route_metric_col, route_mask_col;
static int route_num_cols;
static int open_route_table (void);
route_dest_col = 1;
route_gw_col = 2;
route_flags_col = 3;
+ route_metric_col = 6;
route_mask_col = 7;
route_num_cols = 8;
SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
+ rt->rt_metric = (short) strtoul(cols[route_metric_col], NULL, 10);
rt->rt_dev = cols[route_dev_col];
return 1;
/********************************************************************
*
* defaultroute_exists - determine if there is a default route
+ * with the given metric (or negative for any)
*/
-static int defaultroute_exists (struct rtentry *rt)
+static int defaultroute_exists (struct rtentry *rt, int metric)
{
int result = 0;
if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
continue;
- if (SIN_ADDR(rt->rt_dst) == 0L) {
+ if (SIN_ADDR(rt->rt_dst) == 0L && (metric < 0
+ || rt->rt_metric == metric)) {
result = 1;
break;
}
{
struct rtentry rt;
- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
+ if (defaultroute_exists(&rt, dfl_route_metric) && 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));
+ error("not replacing existing default route via %I with metric %d",
+ SIN_ADDR(rt.rt_gateway), dfl_route_metric);
else
- error("not replacing existing default route through %s",
- rt.rt_dev);
+ error("not replacing existing default route through %s with metric %d",
+ rt.rt_dev, dfl_route_metric);
return 0;
}
SET_SA_FAMILY (rt.rt_dst, AF_INET);
rt.rt_dev = ifname;
+ rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
if (kernel_version > KVERSION(2,1,0)) {
SET_SA_FAMILY (rt.rt_genmask, AF_INET);
rt.rt_dev = ifname;
+ rt.rt_dev = ifname;
+ rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
+
if (kernel_version > KVERSION(2,1,0)) {
SET_SA_FAMILY (rt.rt_genmask, AF_INET);
SIN_ADDR(rt.rt_genmask) = 0L;
printer(arg, "\\t");
break;
default:
- printer(arg, "\\%.3o", c);
+ printer(arg, "\\%.3o", (unsigned char) c);
}
}
}
int dflag; /* print data rates, not bytes */
int interval, count;
int infinite;
-int unit;
int s; /* socket or /dev/ppp file descriptor */
int signalled; /* set if alarm goes off "early" */
char *progname;
{
int c;
#ifdef STREAMS
+ int unit;
char *dev;
#endif
if (argc > 0)
interface = argv[0];
- if (sscanf(interface, PPP_DRV_NAME "%d", &unit) != 1) {
- fprintf(stderr, "%s: invalid interface '%s' specified\n",
- progname, interface);
- }
-
#ifndef STREAMS
{
struct ifreq ifr;
}
#else /* STREAMS */
+ if (sscanf(interface, PPP_DRV_NAME "%d", &unit) != 1) {
+ fprintf(stderr, "%s: invalid interface '%s' specified\n",
+ progname, interface);
+ }
+
#ifdef __osf__
dev = "/dev/streams/ppp";
#else
if [ -s /var/log/ppp.log ]; then
exec tail "$@" /var/log/ppp.log
else
- exec tail "$@" /var/log/syslog | grep ' \(pppd\|chat\)\['
+ exec grep ' \(pppd\|chat\)\[' /var/log/syslog | tail "$@"
fi
fi
# There is an argument, so kill the pppd started on that provider.
-PID=`ps axw | grep "[ /]pppd call $1" | awk '{print $1}'`
+PID=`ps axw | grep "[ /]pppd call $1" | grep -w "$1" | awk '{print $1}'`
if test -n "$PID" ; then
$KILL -$SIG $PID || {
echo "$0: $KILL failed. None ${DONE}."