]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/ipcp.c
pppd: Add replacedefaultroute option (#200)
[ppp.git] / pppd / ipcp.c
index f8942a9645592ad7961b2555f8c8fd0393f23c1d..302ca40b4c83cecce9098bfff17dfe75b0bedba0 100644 (file)
@@ -196,6 +196,15 @@ static option_t ipcp_option_list[] = {
       "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
       &ipcp_wantoptions[0].default_route },
 
+#ifdef __linux__
+    { "replacedefaultroute", o_bool,
+                               &ipcp_wantoptions[0].replace_default_route,
+      "Replace default route", OPT_PRIV | 1
+    },
+    { "noreplacedefaultroute", o_bool,
+                               &ipcp_wantoptions[0].replace_default_route,
+      "Do not replace default route", 0 },
+#endif
     { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
       "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
     { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
@@ -269,7 +278,7 @@ struct protent ipcp_protent = {
     ip_active_pkt
 };
 
-static void ipcp_clear_addrs (int, u_int32_t, u_int32_t);
+static void ipcp_clear_addrs (int, u_int32_t, u_int32_t, bool);
 static void ipcp_script (char *, int); /* Run an up/down script */
 static void ipcp_script_done (void *);
 
@@ -1716,7 +1725,8 @@ ip_demand_conf(int u)
     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
        return 0;
     if (wo->default_route)
-       if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
+       if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
+                                           wo->replace_default_route))
            default_route_set[u] = 1;
     if (wo->proxy_arp)
        if (sifproxyarp(u, wo->hisaddr))
@@ -1804,7 +1814,8 @@ ipcp_up(fsm *f)
      */
     if (demand) {
        if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
-           ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
+           ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
+                                     wo->replace_default_route);
            if (go->ouraddr != wo->ouraddr) {
                warn("Local IP address changed to %I", go->ouraddr);
                script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
@@ -1829,7 +1840,8 @@ ipcp_up(fsm *f)
 
            /* assign a default route through the interface if required */
            if (ipcp_wantoptions[f->unit].default_route) 
-               if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+               if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
+                                            wo->replace_default_route))
                    default_route_set[f->unit] = 1;
 
            /* Make a proxy ARP entry if requested. */
@@ -1888,7 +1900,8 @@ ipcp_up(fsm *f)
 
        /* assign a default route through the interface if required */
        if (ipcp_wantoptions[f->unit].default_route) 
-           if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+           if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
+                                        wo->replace_default_route))
                default_route_set[f->unit] = 1;
 
        /* Make a proxy ARP entry if requested. */
@@ -1965,7 +1978,7 @@ ipcp_down(fsm *f)
        sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
        sifdown(f->unit);
        ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
-                        ipcp_hisoptions[f->unit].hisaddr);
+                        ipcp_hisoptions[f->unit].hisaddr, 0);
     }
 
     /* Execute the ip-down script */
@@ -1981,13 +1994,21 @@ ipcp_down(fsm *f)
  * proxy arp entries, etc.
  */
 static void
-ipcp_clear_addrs(int unit, u_int32_t ouraddr, u_int32_t hisaddr)
+ipcp_clear_addrs(int unit, u_int32_t ouraddr, u_int32_t hisaddr, bool replacedefaultroute)
 {
     if (proxy_arp_set[unit]) {
        cifproxyarp(unit, hisaddr);
        proxy_arp_set[unit] = 0;
     }
-    if (default_route_set[unit]) {
+    /* If replacedefaultroute, sifdefaultroute will be called soon
+     * with replacedefaultroute set and that will overwrite the current
+     * default route. This is the case only when doing demand, otherwise
+     * during demand, this cifdefaultroute would restore the old default
+     * route which is not what we want in this case. In the non-demand
+     * case, we'll delete the default route and restore the old if there
+     * is one saved by an sifdefaultroute with replacedefaultroute.
+     */
+    if (!replacedefaultroute && default_route_set[unit]) {
        cifdefaultroute(unit, ouraddr, hisaddr);
        default_route_set[unit] = 0;
     }