]> git.ozlabs.org Git - ppp.git/commitdiff
pppd: add support for defaultroute-metric option
authorNatanael Copa <ncopa@alpinelinux.org>
Tue, 3 Jun 2014 08:53:47 +0000 (08:53 +0000)
committerNatanael Copa <ncopa@alpinelinux.org>
Fri, 15 Aug 2014 07:26:16 +0000 (07:26 +0000)
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>
pppd/options.c
pppd/pppd.8
pppd/sys-linux.c

index 45fa742cd9ce9d095490ebc68fa199023f8da8cc..ca3f8750c8bb4547895c5057ed3ae937224f0452 100644 (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 */
 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 */
 
 #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 },
 
       "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 },
 #ifdef HAVE_MULTILINK
     { "multilink", o_bool, &multilink,
       "Enable multilink operation", OPT_PRIO | 1 },
index e2768b135273d1772e1241a322fe1116aa1587b8..c508d277df3aa5539dd3c0d94787d97f71709956 100644 (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
 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
 .B disconnect \fIscript
 Execute the command specified by \fIscript\fR, by passing it to a
 shell, after
index 72a7727c403f79762a93bf1342e3b02aa869c27a..37bdda4d78184bc85ce0c29715f05226e8b0a0bc 100644 (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 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);
 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 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.
 /*
  * 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;
 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);
 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_dest_col = 1;
     route_gw_col = 2;
     route_flags_col = 3;
+    route_metric_col = 6;
     route_mask_col = 7;
     route_num_cols = 8;
 
     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);
     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;
     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
 /********************************************************************
  *
  * 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;
 
 {
     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 (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;
        }
            result = 1;
            break;
        }
@@ -1612,13 +1618,13 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
 {
     struct rtentry rt;
 
 {
     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)
        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
        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;
     }
 
        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;
     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);
 
     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_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;
     if (kernel_version > KVERSION(2,1,0)) {
        SET_SA_FAMILY (rt.rt_genmask, AF_INET);
        SIN_ADDR(rt.rt_genmask) = 0L;