OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | pppd: Add "replacedefaultroute" and "noreplacedefaultroute" options |
2 | |||
3 | This patch implements two new options, "replacedefaultroute" to replace any |
||
4 | existing system default route when specified and "noreplacedefaultroute" to |
||
5 | disable the "replacedefaultroute" option, which is useful in multi user |
||
6 | environments where the administrator wants to allow users to dial pppd |
||
7 | connections but not allow them to change the system default route. |
||
8 | |||
9 | The patch originated from the Debian project. |
||
10 | |||
11 | Signed-off-by: Jo-Philipp Wich <jo@mein.io> |
||
12 | |||
13 | --- a/pppd/ipcp.c |
||
14 | +++ b/pppd/ipcp.c |
||
15 | @@ -198,6 +198,14 @@ static option_t ipcp_option_list[] = { |
||
16 | "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, |
||
17 | &ipcp_wantoptions[0].default_route }, |
||
18 | |||
19 | + { "replacedefaultroute", o_bool, |
||
20 | + &ipcp_wantoptions[0].replace_default_route, |
||
21 | + "Replace default route", 1 |
||
22 | + }, |
||
23 | + { "noreplacedefaultroute", o_bool, |
||
24 | + &ipcp_allowoptions[0].replace_default_route, |
||
25 | + "Never replace default route", OPT_A2COPY, |
||
26 | + &ipcp_wantoptions[0].replace_default_route }, |
||
27 | { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, |
||
28 | "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, |
||
29 | { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, |
||
30 | @@ -271,7 +279,7 @@ struct protent ipcp_protent = { |
||
31 | ip_active_pkt |
||
32 | }; |
||
33 | |||
34 | -static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); |
||
35 | +static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool)); |
||
36 | static void ipcp_script __P((char *, int)); /* Run an up/down script */ |
||
37 | static void ipcp_script_done __P((void *)); |
||
38 | |||
39 | @@ -1761,7 +1769,8 @@ ip_demand_conf(u) |
||
40 | if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) |
||
41 | return 0; |
||
42 | if (wo->default_route) |
||
43 | - if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) |
||
44 | + if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr, |
||
45 | + wo->replace_default_route)) |
||
46 | default_route_set[u] = 1; |
||
47 | if (wo->proxy_arp) |
||
48 | if (sifproxyarp(u, wo->hisaddr)) |
||
49 | @@ -1849,7 +1858,8 @@ ipcp_up(f) |
||
50 | */ |
||
51 | if (demand) { |
||
52 | if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { |
||
53 | - ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr); |
||
54 | + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, |
||
55 | + wo->replace_default_route); |
||
56 | if (go->ouraddr != wo->ouraddr) { |
||
57 | warn("Local IP address changed to %I", go->ouraddr); |
||
58 | script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); |
||
59 | @@ -1874,7 +1884,8 @@ ipcp_up(f) |
||
60 | |||
61 | /* assign a default route through the interface if required */ |
||
62 | if (ipcp_wantoptions[f->unit].default_route) |
||
63 | - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
||
64 | + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
||
65 | + wo->replace_default_route)) |
||
66 | default_route_set[f->unit] = 1; |
||
67 | |||
68 | /* Make a proxy ARP entry if requested. */ |
||
69 | @@ -1924,7 +1935,8 @@ ipcp_up(f) |
||
70 | |||
71 | /* assign a default route through the interface if required */ |
||
72 | if (ipcp_wantoptions[f->unit].default_route) |
||
73 | - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
||
74 | + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
||
75 | + wo->replace_default_route)) |
||
76 | default_route_set[f->unit] = 1; |
||
77 | |||
78 | /* Make a proxy ARP entry if requested. */ |
||
79 | @@ -2002,7 +2014,7 @@ ipcp_down(f) |
||
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 | @@ -2018,16 +2030,25 @@ ipcp_down(f) |
||
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 | --- a/pppd/ipcp.h |
||
117 | +++ b/pppd/ipcp.h |
||
118 | @@ -70,6 +70,7 @@ typedef struct ipcp_options { |
||
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 | --- a/pppd/pppd.8 |
||
127 | +++ b/pppd/pppd.8 |
||
128 | @@ -127,6 +127,11 @@ is no other default route with the same |
||
129 | value of -1, the route is only added if there is no default route at |
||
130 | all. |
||
131 | .TP |
||
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. |
||
136 | +.TP |
||
137 | .B disconnect \fIscript |
||
138 | Execute the command specified by \fIscript\fR, by passing it to a |
||
139 | shell, after |
||
140 | @@ -740,7 +745,12 @@ disable both forms of hardware flow cont |
||
141 | .TP |
||
142 | .B nodefaultroute |
||
143 | Disable the \fIdefaultroute\fR option. The system administrator who |
||
144 | -wishes to prevent users from creating default routes with pppd |
||
145 | +wishes to prevent users from adding a default route with pppd |
||
146 | +can do so by placing this option in the /etc/ppp/options file. |
||
147 | +.TP |
||
148 | +.B noreplacedefaultroute |
||
149 | +Disable the \fIreplacedefaultroute\fR option. The system administrator who |
||
150 | +wishes to prevent users from replacing a default route with pppd |
||
151 | can do so by placing this option in the /etc/ppp/options file. |
||
152 | .TP |
||
153 | .B nodeflate |
||
154 | --- a/pppd/pppd.h |
||
155 | +++ b/pppd/pppd.h |
||
156 | @@ -681,7 +681,7 @@ int sif6addr __P((int, eui64_t, eui64_t |
||
157 | int cif6addr __P((int, eui64_t, eui64_t)); |
||
158 | /* Remove an IPv6 address from i/f */ |
||
159 | #endif |
||
160 | -int sifdefaultroute __P((int, u_int32_t, u_int32_t)); |
||
161 | +int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt)); |
||
162 | /* Create default route through i/f */ |
||
163 | int cifdefaultroute __P((int, u_int32_t, u_int32_t)); |
||
164 | /* Delete default route through i/f */ |
||
165 | --- a/pppd/sys-linux.c |
||
166 | +++ b/pppd/sys-linux.c |
||
167 | @@ -207,6 +207,8 @@ static unsigned char inbuf[512]; /* buff |
||
168 | static int if_is_up; /* Interface has been marked up */ |
||
169 | static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */ |
||
170 | static int have_default_route; /* Gateway for default route added */ |
||
171 | +static struct rtentry old_def_rt; /* Old default route */ |
||
172 | +static int default_rt_repl_rest; /* replace and restore old default rt */ |
||
173 | static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ |
||
174 | static char proxy_arp_dev[16]; /* Device for proxy arp entry */ |
||
175 | static u_int32_t our_old_addr; /* for detecting address changes */ |
||
176 | @@ -1570,6 +1572,9 @@ static int read_route_table(struct rtent |
||
177 | p = NULL; |
||
178 | } |
||
179 | |||
180 | + SET_SA_FAMILY (rt->rt_dst, AF_INET); |
||
181 | + SET_SA_FAMILY (rt->rt_gateway, AF_INET); |
||
182 | + |
||
183 | SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16); |
||
184 | SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16); |
||
185 | SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16); |
||
186 | @@ -1642,20 +1647,52 @@ int have_route_to(u_int32_t addr) |
||
187 | /******************************************************************** |
||
188 | * |
||
189 | * sifdefaultroute - assign a default route through the address given. |
||
190 | - */ |
||
191 | - |
||
192 | -int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) |
||
193 | -{ |
||
194 | - struct rtentry rt; |
||
195 | - |
||
196 | - if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) { |
||
197 | - if (rt.rt_flags & RTF_GATEWAY) |
||
198 | - error("not replacing existing default route via %I with metric %d", |
||
199 | - SIN_ADDR(rt.rt_gateway), dfl_route_metric); |
||
200 | - else |
||
201 | + * |
||
202 | + * If the global default_rt_repl_rest flag is set, then this function |
||
203 | + * already replaced the original system defaultroute with some other |
||
204 | + * route and it should just replace the current defaultroute with |
||
205 | + * another one, without saving the current route. Use: demand mode, |
||
206 | + * when pppd sets first a defaultroute it it's temporary ppp0 addresses |
||
207 | + * and then changes the temporary addresses to the addresses for the real |
||
208 | + * ppp connection when it has come up. |
||
209 | + */ |
||
210 | + |
||
211 | +int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace) |
||
212 | +{ |
||
213 | + struct rtentry rt, tmp_rt; |
||
214 | + struct rtentry *del_rt = NULL; |
||
215 | + |
||
216 | + if (default_rt_repl_rest) { |
||
217 | + /* We have already reclaced the original defaultroute, if we |
||
218 | + are called again, we will delete the current default route |
||
219 | + and set the new default route in this function. |
||
220 | + - this is normally only the case the doing demand: */ |
||
221 | + if (defaultroute_exists(&tmp_rt, dfl_route_metric)) |
||
222 | + del_rt = &tmp_rt; |
||
223 | + } else if (defaultroute_exists(&old_def_rt, dfl_route_metric) && |
||
224 | + strcmp(old_def_rt.rt_dev, ifname) != 0) { |
||
225 | + /* We did not yet replace an existing default route, let's |
||
226 | + check if we should save and replace a default route: */ |
||
227 | + if (old_def_rt.rt_flags & RTF_GATEWAY) { |
||
228 | + if (!replace) { |
||
229 | + error("not replacing existing default route via %I with metric %d", |
||
230 | + SIN_ADDR(old_def_rt.rt_gateway), dfl_route_metric); |
||
231 | + return 0; |
||
232 | + } else { |
||
233 | + /* we need to copy rt_dev because we need it permanent too: */ |
||
234 | + char *tmp_dev = malloc(strlen(old_def_rt.rt_dev) + 1); |
||
235 | + strcpy(tmp_dev, old_def_rt.rt_dev); |
||
236 | + old_def_rt.rt_dev = tmp_dev; |
||
237 | + |
||
238 | + notice("replacing old default route to %s [%I] with metric %d", |
||
239 | + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway), |
||
240 | + dfl_route_metric); |
||
241 | + default_rt_repl_rest = 1; |
||
242 | + del_rt = &old_def_rt; |
||
243 | + } |
||
244 | + } else |
||
245 | error("not replacing existing default route through %s with metric %d", |
||
246 | - rt.rt_dev, dfl_route_metric); |
||
247 | - return 0; |
||
248 | + old_def_rt.rt_dev, dfl_route_metric); |
||
249 | } |
||
250 | |||
251 | memset (&rt, 0, sizeof (rt)); |
||
252 | @@ -1671,10 +1708,16 @@ int sifdefaultroute (int unit, u_int32_t |
||
253 | |||
254 | rt.rt_flags = RTF_UP; |
||
255 | if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) { |
||
256 | - if ( ! ok_error ( errno )) |
||
257 | + if (!ok_error(errno)) |
||
258 | error("default route ioctl(SIOCADDRT): %m"); |
||
259 | return 0; |
||
260 | } |
||
261 | + if (default_rt_repl_rest && del_rt) |
||
262 | + if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) { |
||
263 | + if (!ok_error(errno)) |
||
264 | + error("del old default route ioctl(SIOCDELRT): %m"); |
||
265 | + return 0; |
||
266 | + } |
||
267 | |||
268 | have_default_route = 1; |
||
269 | return 1; |
||
270 | @@ -1708,11 +1751,21 @@ int cifdefaultroute (int unit, u_int32_t |
||
271 | rt.rt_flags = RTF_UP; |
||
272 | if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) { |
||
273 | if (still_ppp()) { |
||
274 | - if ( ! ok_error ( errno )) |
||
275 | + if (!ok_error(errno)) |
||
276 | error("default route ioctl(SIOCDELRT): %m"); |
||
277 | return 0; |
||
278 | } |
||
279 | } |
||
280 | + if (default_rt_repl_rest) { |
||
281 | + notice("restoring old default route to %s [%I]", |
||
282 | + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway)); |
||
283 | + if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) { |
||
284 | + if (!ok_error(errno)) |
||
285 | + error("restore default route ioctl(SIOCADDRT): %m"); |
||
286 | + return 0; |
||
287 | + } |
||
288 | + default_rt_repl_rest = 0; |
||
289 | + } |
||
290 | |||
291 | return 1; |
||
292 | } |
||
293 | --- a/pppd/sys-solaris.c |
||
294 | +++ b/pppd/sys-solaris.c |
||
295 | @@ -2039,12 +2039,18 @@ cifaddr(u, o, h) |
||
296 | * sifdefaultroute - assign a default route through the address given. |
||
297 | */ |
||
298 | int |
||
299 | -sifdefaultroute(u, l, g) |
||
300 | +sifdefaultroute(u, l, g, replace) |
||
301 | int u; |
||
302 | u_int32_t l, g; |
||
303 | + bool replace; |
||
304 | { |
||
305 | struct rtentry rt; |
||
306 | |||
307 | + if (replace) { |
||
308 | + error("replacedefaultroute not supported on this platform"); |
||
309 | + return 0; |
||
310 | + } |
||
311 | + |
||
312 | #if defined(__USLC__) |
||
313 | g = l; /* use the local address as gateway */ |
||
314 | #endif |