| 1 |
--- ppp/pppd/ipcp.c Wed May 31 17:20:41 2000 |
| 2 |
+++ ppp/pppd/ipcp.c Wed May 31 17:27:19 2000 |
| 3 |
@@ -145,7 +145,17 @@ |
| 4 |
{ "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, |
| 5 |
"disable defaultroute option", OPT_A2COPY, |
| 6 |
&ipcp_wantoptions[0].default_route }, |
| 7 |
|
| 8 |
+#ifdef __linux__ |
| 9 |
+ { "replacedefaultroute", o_bool, |
| 10 |
+ &ipcp_wantoptions[0].replace_default_route, |
| 11 |
+ "Replace default route", 1 |
| 12 |
+ }, |
| 13 |
+ { "noreplacedefaultroute", o_bool, |
| 14 |
+ &ipcp_allowoptions[0].replace_default_route, |
| 15 |
+ "Never replace default route", OPT_A2COPY, |
| 16 |
+ &ipcp_wantoptions[0].replace_default_route }, |
| 17 |
+#endif |
| 18 |
{ "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, |
| 19 |
"Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, |
| 20 |
{ "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, |
| 21 |
@@ -195,7 +205,7 @@ |
| 22 |
ip_active_pkt |
| 23 |
}; |
| 24 |
|
| 25 |
-static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); |
| 26 |
+static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool)); |
| 27 |
static void ipcp_script __P((char *)); /* Run an up/down script */ |
| 28 |
static void ipcp_script_done __P((void *)); |
| 29 |
|
| 30 |
@@ -1344,7 +1354,12 @@ |
| 31 |
if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) |
| 32 |
return 0; |
| 33 |
if (wo->default_route) |
| 34 |
+#ifndef __linux__ |
| 35 |
if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) |
| 36 |
+#else |
| 37 |
+ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr, |
| 38 |
+ wo->replace_default_route)) |
| 39 |
+#endif |
| 40 |
default_route_set[u] = 1; |
| 41 |
if (wo->proxy_arp) |
| 42 |
if (sifproxyarp(u, wo->hisaddr)) |
| 43 |
@@ -1420,7 +1435,8 @@ |
| 44 |
*/ |
| 45 |
if (demand) { |
| 46 |
if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { |
| 47 |
- ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr); |
| 48 |
+ ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, |
| 49 |
+ wo->replace_default_route); |
| 50 |
if (go->ouraddr != wo->ouraddr) { |
| 51 |
warn("Local IP address changed to %I", go->ouraddr); |
| 52 |
script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr)); |
| 53 |
@@ -1445,7 +1461,12 @@ |
| 54 |
|
| 55 |
/* assign a default route through the interface if required */ |
| 56 |
if (ipcp_wantoptions[f->unit].default_route) |
| 57 |
+#ifndef __linux__ |
| 58 |
if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
| 59 |
+#else |
| 60 |
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
| 61 |
+ wo->replace_default_route)) |
| 62 |
+#endif |
| 63 |
default_route_set[f->unit] = 1; |
| 64 |
|
| 65 |
/* Make a proxy ARP entry if requested. */ |
| 66 |
@@ -1492,7 +1513,12 @@ |
| 67 |
|
| 68 |
/* assign a default route through the interface if required */ |
| 69 |
if (ipcp_wantoptions[f->unit].default_route) |
| 70 |
+#ifndef __linux__ |
| 71 |
if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
| 72 |
+#else |
| 73 |
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
| 74 |
+ wo->replace_default_route)) |
| 75 |
+#endif |
| 76 |
default_route_set[f->unit] = 1; |
| 77 |
|
| 78 |
/* Make a proxy ARP entry if requested. */ |
| 79 |
@@ -1559,7 +1585,7 @@ |
| 80 |
sifnpmode(f->unit, PPP_IP, NPMODE_DROP); |
| 81 |
sifdown(f->unit); |
| 82 |
ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr, |
| 83 |
- ipcp_hisoptions[f->unit].hisaddr); |
| 84 |
+ ipcp_hisoptions[f->unit].hisaddr, 0); |
| 85 |
} |
| 86 |
|
| 87 |
/* Execute the ip-down script */ |
| 88 |
@@ -1575,16 +1601,25 @@ |
| 89 |
* proxy arp entries, etc. |
| 90 |
*/ |
| 91 |
static void |
| 92 |
-ipcp_clear_addrs(unit, ouraddr, hisaddr) |
| 93 |
+ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute) |
| 94 |
int unit; |
| 95 |
u_int32_t ouraddr; /* local address */ |
| 96 |
u_int32_t hisaddr; /* remote address */ |
| 97 |
+ bool replacedefaultroute; |
| 98 |
{ |
| 99 |
if (proxy_arp_set[unit]) { |
| 100 |
cifproxyarp(unit, hisaddr); |
| 101 |
proxy_arp_set[unit] = 0; |
| 102 |
} |
| 103 |
- if (default_route_set[unit]) { |
| 104 |
+ /* If replacedefaultroute, sifdefaultroute will be called soon |
| 105 |
+ * with replacedefaultroute set and that will overwrite the current |
| 106 |
+ * default route. This is the case only when doing demand, otherwise |
| 107 |
+ * during demand, this cifdefaultroute would restore the old default |
| 108 |
+ * route which is not what we want in this case. In the non-demand |
| 109 |
+ * case, we'll delete the default route and restore the old if there |
| 110 |
+ * is one saved by an sifdefaultroute with replacedefaultroute. |
| 111 |
+ */ |
| 112 |
+ if (!replacedefaultroute && default_route_set[unit]) { |
| 113 |
cifdefaultroute(unit, ouraddr, hisaddr); |
| 114 |
default_route_set[unit] = 0; |
| 115 |
} |
| 116 |
--- ppp/pppd/ipcp.h Wed May 31 17:20:41 2000 |
| 117 |
+++ ppp/pppd/ipcp.h Wed May 31 15:56:17 2000 |
| 118 |
@@ -47,6 +47,7 @@ |
| 119 |
bool old_addrs; /* Use old (IP-Addresses) option? */ |
| 120 |
bool req_addr; /* Ask peer to send IP address? */ |
| 121 |
bool default_route; /* Assign default route through interface? */ |
| 122 |
+ bool replace_default_route; /* Replace default route through interface? */ |
| 123 |
bool proxy_arp; /* Make proxy ARP entry for peer? */ |
| 124 |
bool neg_vj; /* Van Jacobson Compression? */ |
| 125 |
bool old_vj; /* use old (short) form of VJ option? */ |
| 126 |
--- ppp/pppd/pppd.h Wed May 31 17:20:41 2000 |
| 127 |
+++ ppp/pppd/pppd.h Wed May 31 15:56:17 2000 |
| 128 |
@@ -416,7 +416,11 @@ |
| 129 |
int cif6addr __P((int, eui64_t, eui64_t)); |
| 130 |
/* Remove an IPv6 address from i/f */ |
| 131 |
#endif |
| 132 |
+#ifndef __linux__ |
| 133 |
int sifdefaultroute __P((int, u_int32_t, u_int32_t)); |
| 134 |
+#else |
| 135 |
+int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt)); |
| 136 |
+#endif |
| 137 |
/* Create default route through i/f */ |
| 138 |
int cifdefaultroute __P((int, u_int32_t, u_int32_t)); |
| 139 |
/* Delete default route through i/f */ |
| 140 |
--- ppp/pppd/sys-linux.c Wed May 31 17:20:41 2000 |
| 141 |
+++ ppp/pppd/sys-linux.c Wed May 31 17:37:23 2000 |
| 142 |
@@ -143,6 +143,8 @@ |
| 143 |
|
| 144 |
static int if_is_up; /* Interface has been marked up */ |
| 145 |
static u_int32_t default_route_gateway; /* Gateway for default route added */ |
| 146 |
+static struct rtentry old_def_rt; /* Old default route */ |
| 147 |
+static int default_rt_repl_rest; /* replace and restore old default rt */ |
| 148 |
static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ |
| 149 |
static char proxy_arp_dev[16]; /* Device for proxy arp entry */ |
| 150 |
static u_int32_t our_old_addr; /* for detecting address changes */ |
| 151 |
@@ -1209,6 +1211,9 @@ |
| 152 |
p = NULL; |
| 153 |
} |
| 154 |
|
| 155 |
+ SET_SA_FAMILY (rt->rt_dst, AF_INET); |
| 156 |
+ SET_SA_FAMILY (rt->rt_gateway, AF_INET); |
| 157 |
+ |
| 158 |
SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16); |
| 159 |
SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16); |
| 160 |
SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16); |
| 161 |
@@ -1278,19 +1283,53 @@ |
| 162 |
/******************************************************************** |
| 163 |
* |
| 164 |
* sifdefaultroute - assign a default route through the address given. |
| 165 |
+ * |
| 166 |
+ * If the global default_rt_repl_rest flag is set, then this function |
| 167 |
+ * already replaced the original system defaultroute with some other |
| 168 |
+ * route and it should just replace the current defaultroute with |
| 169 |
+ * another one, without saving the current route. Use: demand mode, |
| 170 |
+ * when pppd sets first a defaultroute it it's temporary ppp0 addresses |
| 171 |
+ * and then changes the temporary addresses to the addresses for the real |
| 172 |
+ * ppp connection when it has come up. |
| 173 |
*/ |
| 174 |
|
| 175 |
-int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) |
| 176 |
+int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace) |
| 177 |
{ |
| 178 |
- struct rtentry rt; |
| 179 |
- |
| 180 |
- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) { |
| 181 |
- u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway); |
| 182 |
+ struct rtentry rt, tmp_rt; |
| 183 |
+ struct rtentry *del_rt = NULL; |
| 184 |
|
| 185 |
- if (old_gateway != gateway) |
| 186 |
- error("not replacing existing default route to %s [%I]", |
| 187 |
- rt.rt_dev, old_gateway); |
| 188 |
- return 0; |
| 189 |
+ |
| 190 |
+ if (default_rt_repl_rest) { |
| 191 |
+ /* We have already reclaced the original defaultroute, if we |
| 192 |
+ * are called again, we will delete the current default route |
| 193 |
+ * and set the new default route in this function. |
| 194 |
+ * - this is normally only the case the doing demand: */ |
| 195 |
+ if (defaultroute_exists( &tmp_rt )) |
| 196 |
+ del_rt = &tmp_rt; |
| 197 |
+ } else if ( defaultroute_exists( &old_def_rt ) && |
| 198 |
+ strcmp( old_def_rt.rt_dev, ifname ) != 0) { |
| 199 |
+ /* We did not yet replace an existing default route, let's |
| 200 |
+ * check if we should save and replace a default route: |
| 201 |
+ */ |
| 202 |
+ u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway); |
| 203 |
+ |
| 204 |
+ if (old_gateway != gateway) { |
| 205 |
+ if (!replace) { |
| 206 |
+ error("not replacing default route to %s [%I]", |
| 207 |
+ old_def_rt.rt_dev, old_gateway); |
| 208 |
+ return 0; |
| 209 |
+ } else { |
| 210 |
+ // we need to copy rt_dev because we need it permanent too: |
| 211 |
+ char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1); |
| 212 |
+ strcpy(tmp_dev, old_def_rt.rt_dev); |
| 213 |
+ old_def_rt.rt_dev = tmp_dev; |
| 214 |
+ |
| 215 |
+ notice("replacing old default route to %s [%I]", |
| 216 |
+ old_def_rt.rt_dev, old_gateway); |
| 217 |
+ default_rt_repl_rest = 1; |
| 218 |
+ del_rt = &old_def_rt; |
| 219 |
+ } |
| 220 |
+ } |
| 221 |
} |
| 222 |
|
| 223 |
memset (&rt, '\0', sizeof (rt)); |
| 224 |
@@ -1310,6 +1349,12 @@ |
| 225 |
error("default route ioctl(SIOCADDRT): %m(%d)", errno); |
| 226 |
return 0; |
| 227 |
} |
| 228 |
+ if (default_rt_repl_rest && del_rt) |
| 229 |
+ if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) { |
| 230 |
+ if ( ! ok_error ( errno )) |
| 231 |
+ error("del old default route ioctl(SIOCDELRT): %m(%d)", errno); |
| 232 |
+ return 0; |
| 233 |
+ } |
| 234 |
|
| 235 |
default_route_gateway = gateway; |
| 236 |
return 1; |
| 237 |
@@ -1344,6 +1389,16 @@ |
| 238 |
error("default route ioctl(SIOCDELRT): %m (%d)", errno); |
| 239 |
return 0; |
| 240 |
} |
| 241 |
+ } |
| 242 |
+ if (default_rt_repl_rest) { |
| 243 |
+ notice("restoring old default route to %s [%I]", |
| 244 |
+ old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway)); |
| 245 |
+ if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) { |
| 246 |
+ if ( ! ok_error ( errno )) |
| 247 |
+ error("restore default route ioctl(SIOCADDRT): %m(%d)", errno); |
| 248 |
+ return 0; |
| 249 |
+ } |
| 250 |
+ default_rt_repl_rest = 0; |
| 251 |
} |
| 252 |
|
| 253 |
return 1; |