pppd: add support for defaultroute-metric option

This allows user to specify the 'metric' (or 'prio') for the default
route set by pppd. This is useful in multi-ISP setups where there
might be more than one default gateway.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
This commit is contained in:
Natanael Copa 2014-06-03 08:53:47 +00:00
parent 4043750fca
commit 35e5a569c9
3 changed files with 30 additions and 9 deletions

View File

@ -121,6 +121,7 @@ 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 */
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 */
@ -299,6 +300,10 @@ option_t general_options[] = {
"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 },

View File

@ -121,6 +121,12 @@ the gateway, when IPCP negotiation is successfully completed.
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

View File

@ -232,7 +232,7 @@ static int baud_rate_of (int speed);
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);
@ -242,6 +242,8 @@ static int make_ppp_unit(void);
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.
@ -1439,7 +1441,7 @@ static char *path_to_procfs(const char *tail)
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);
@ -1482,6 +1484,7 @@ 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;
@ -1542,6 +1545,7 @@ static int read_route_table(struct rtentry *rt)
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;
@ -1550,9 +1554,10 @@ static int read_route_table(struct rtentry *rt)
/********************************************************************
*
* 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;
@ -1565,7 +1570,8 @@ static int defaultroute_exists (struct rtentry *rt)
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;
}
@ -1612,13 +1618,13 @@ 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 (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;
}
@ -1626,6 +1632,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
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);
@ -1660,6 +1667,9 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
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;