1 --- ppp/pppd/ipcp.c Wed May 31 17:20:41 2000
2 +++ ppp/pppd/ipcp.c Wed May 31 17:27:19 2000
4 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
5 "disable defaultroute option", OPT_A2COPY,
6 &ipcp_wantoptions[0].default_route },
9 + { "replacedefaultroute", o_bool,
10 + &ipcp_wantoptions[0].replace_default_route,
11 + "Replace default route", 1
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 },
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,
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 *));
30 @@ -1344,7 +1354,12 @@
31 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
33 if (wo->default_route)
35 if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
37 + if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
38 + wo->replace_default_route))
40 default_route_set[u] = 1;
42 if (sifproxyarp(u, wo->hisaddr))
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 @@
55 /* assign a default route through the interface if required */
56 if (ipcp_wantoptions[f->unit].default_route)
58 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
60 + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
61 + wo->replace_default_route))
63 default_route_set[f->unit] = 1;
65 /* Make a proxy ARP entry if requested. */
66 @@ -1492,7 +1513,12 @@
68 /* assign a default route through the interface if required */
69 if (ipcp_wantoptions[f->unit].default_route)
71 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
73 + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
74 + wo->replace_default_route))
76 default_route_set[f->unit] = 1;
78 /* Make a proxy ARP entry if requested. */
80 sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
82 ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
83 - ipcp_hisoptions[f->unit].hisaddr);
84 + ipcp_hisoptions[f->unit].hisaddr, 0);
87 /* Execute the ip-down script */
88 @@ -1575,16 +1601,25 @@
89 * proxy arp entries, etc.
92 -ipcp_clear_addrs(unit, ouraddr, hisaddr)
93 +ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
95 u_int32_t ouraddr; /* local address */
96 u_int32_t hisaddr; /* remote address */
97 + bool replacedefaultroute;
99 if (proxy_arp_set[unit]) {
100 cifproxyarp(unit, hisaddr);
101 proxy_arp_set[unit] = 0;
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.
112 + if (!replacedefaultroute && default_route_set[unit]) {
113 cifdefaultroute(unit, ouraddr, hisaddr);
114 default_route_set[unit] = 0;
116 --- ppp/pppd/ipcp.h Wed May 31 17:20:41 2000
117 +++ ppp/pppd/ipcp.h Wed May 31 15:56:17 2000
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.8 Wed May 31 17:20:41 2000
127 +++ ppp/pppd/pppd.8 Wed May 31 15:56:17 2000
129 This entry is removed when the PPP connection is broken. This option
130 is privileged if the \fInodefaultroute\fR option has been specified.
132 +.B replacedefaultroute
133 +This option is a flag to the defaultroute option. If defaultroute is
134 +set and this flag is also set, pppd replaces an existing default route
135 +with the new default route.
139 .B disconnect \fIscript
140 Run the executable or shell command specified by \fIscript\fR after
141 pppd has terminated the link. This script could, for example, issue
145 Disable the \fIdefaultroute\fR option. The system administrator who
146 -wishes to prevent users from creating default routes with pppd
147 +wishes to prevent users from adding a default route with pppd
148 +can do so by placing this option in the /etc/ppp/options file.
150 +.B noreplacedefaultroute
151 +Disable the \fIreplacedefaultroute\fR option. The system administrator who
152 +wishes to prevent users from replacing a default route with pppd
153 can do so by placing this option in the /etc/ppp/options file.
156 --- ppp/pppd/pppd.h Wed May 31 17:20:41 2000
157 +++ ppp/pppd/pppd.h Wed May 31 15:56:17 2000
159 int cif6addr __P((int, eui64_t, eui64_t));
160 /* Remove an IPv6 address from i/f */
163 int sifdefaultroute __P((int, u_int32_t, u_int32_t));
165 +int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
167 /* Create default route through i/f */
168 int cifdefaultroute __P((int, u_int32_t, u_int32_t));
169 /* Delete default route through i/f */
170 --- ppp/pppd/sys-linux.c Wed May 31 17:20:41 2000
171 +++ ppp/pppd/sys-linux.c Wed May 31 17:37:23 2000
174 static int if_is_up; /* Interface has been marked up */
175 static u_int32_t default_route_gateway; /* Gateway for default route added */
176 +static struct rtentry old_def_rt; /* Old default route */
177 +static int default_rt_repl_rest; /* replace and restore old default rt */
178 static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
179 static char proxy_arp_dev[16]; /* Device for proxy arp entry */
180 static u_int32_t our_old_addr; /* for detecting address changes */
181 @@ -1209,6 +1211,9 @@
185 + SET_SA_FAMILY (rt->rt_dst, AF_INET);
186 + SET_SA_FAMILY (rt->rt_gateway, AF_INET);
188 SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
189 SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
190 SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
191 @@ -1278,19 +1283,53 @@
192 /********************************************************************
194 * sifdefaultroute - assign a default route through the address given.
196 + * If the global default_rt_repl_rest flag is set, then this function
197 + * already replaced the original system defaultroute with some other
198 + * route and it should just replace the current defaultroute with
199 + * another one, without saving the current route. Use: demand mode,
200 + * when pppd sets first a defaultroute it it's temporary ppp0 addresses
201 + * and then changes the temporary addresses to the addresses for the real
202 + * ppp connection when it has come up.
205 -int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
206 +int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
210 - if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
211 - u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
212 + struct rtentry rt, tmp_rt;
213 + struct rtentry *del_rt = NULL;
215 - if (old_gateway != gateway)
216 - error("not replacing existing default route to %s [%I]",
217 - rt.rt_dev, old_gateway);
220 + if (default_rt_repl_rest) {
221 + /* We have already reclaced the original defaultroute, if we
222 + * are called again, we will delete the current default route
223 + * and set the new default route in this function.
224 + * - this is normally only the case the doing demand: */
225 + if (defaultroute_exists( &tmp_rt ))
227 + } else if ( defaultroute_exists( &old_def_rt ) &&
228 + strcmp( old_def_rt.rt_dev, ifname ) != 0) {
229 + /* We did not yet replace an existing default route, let's
230 + * check if we should save and replace a default route:
232 + u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
234 + if (old_gateway != gateway) {
236 + error("not replacing default route to %s [%I]",
237 + old_def_rt.rt_dev, old_gateway);
240 + // we need to copy rt_dev because we need it permanent too:
241 + char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1);
242 + strcpy(tmp_dev, old_def_rt.rt_dev);
243 + old_def_rt.rt_dev = tmp_dev;
245 + notice("replacing old default route to %s [%I]",
246 + old_def_rt.rt_dev, old_gateway);
247 + default_rt_repl_rest = 1;
248 + del_rt = &old_def_rt;
253 memset (&rt, '\0', sizeof (rt));
254 @@ -1310,6 +1349,12 @@
255 error("default route ioctl(SIOCADDRT): %m(%d)", errno);
258 + if (default_rt_repl_rest && del_rt)
259 + if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
260 + if ( ! ok_error ( errno ))
261 + error("del old default route ioctl(SIOCDELRT): %m(%d)", errno);
265 default_route_gateway = gateway;
267 @@ -1344,6 +1389,16 @@
268 error("default route ioctl(SIOCDELRT): %m (%d)", errno);
272 + if (default_rt_repl_rest) {
273 + notice("restoring old default route to %s [%I]",
274 + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
275 + if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
276 + if ( ! ok_error ( errno ))
277 + error("restore default route ioctl(SIOCADDRT): %m(%d)", errno);
280 + default_rt_repl_rest = 0;