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 */
"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 },
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.
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;