packages: sort network related packages into package/network/
[openwrt.git] / package / network / services / ppp / patches / 110-debian_defaultroute.patch
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 <jow@openwrt.org>
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 @@ -1742,7 +1750,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 @@ -1830,7 +1839,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 @@ -1855,7 +1865,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 @@ -1905,7 +1916,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 @@ -1983,7 +1995,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 @@ -1999,16 +2011,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 @@ -121,6 +121,11 @@ the gateway, when IPCP negotiation is su
129  This entry is removed when the PPP connection is broken.  This option
130  is privileged if the \fInodefaultroute\fR option has been specified.
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 @@ -717,7 +722,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 @@ -645,7 +645,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 @@ -206,6 +206,8 @@ static unsigned char inbuf[512]; /* buff
168  
169  static int     if_is_up;       /* Interface has been marked up */
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 @@ -1544,6 +1546,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 @@ -1613,20 +1618,51 @@ 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) && strcmp(rt.rt_dev, ifname) != 0) {
197 -       if (rt.rt_flags & RTF_GATEWAY)
198 -           error("not replacing existing default route via %I",
199 -                 SIN_ADDR(rt.rt_gateway));
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))
222 +           del_rt = &tmp_rt;
223 +    } else if (defaultroute_exists(&old_def_rt) &&
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",
230 +                     SIN_ADDR(old_def_rt.rt_gateway));
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]",
239 +                       old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
240 +               default_rt_repl_rest = 1;
241 +               del_rt = &old_def_rt;
242 +           }
243 +       } else
244             error("not replacing existing default route through %s",
245 -                 rt.rt_dev);
246 -       return 0;
247 +                 old_def_rt.rt_dev);
248      }
249  
250      memset (&rt, 0, sizeof (rt));
251 @@ -1641,10 +1677,16 @@ int sifdefaultroute (int unit, u_int32_t
252  
253      rt.rt_flags = RTF_UP;
254      if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
255 -       if ( ! ok_error ( errno ))
256 +       if (!ok_error(errno))
257             error("default route ioctl(SIOCADDRT): %m");
258         return 0;
259      }
260 +    if (default_rt_repl_rest && del_rt)
261 +        if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
262 +           if (!ok_error(errno))
263 +               error("del old default route ioctl(SIOCDELRT): %m");
264 +           return 0;
265 +        }
266  
267      have_default_route = 1;
268      return 1;
269 @@ -1675,11 +1717,21 @@ int cifdefaultroute (int unit, u_int32_t
270      rt.rt_flags = RTF_UP;
271      if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
272         if (still_ppp()) {
273 -           if ( ! ok_error ( errno ))
274 +           if (!ok_error(errno))
275                 error("default route ioctl(SIOCDELRT): %m");
276             return 0;
277         }
278      }
279 +    if (default_rt_repl_rest) {
280 +       notice("restoring old default route to %s [%I]",
281 +               old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
282 +        if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
283 +           if (!ok_error(errno))
284 +               error("restore default route ioctl(SIOCADDRT): %m");
285 +           return 0;
286 +        }
287 +        default_rt_repl_rest = 0;
288 +    }
289  
290      return 1;
291  }
292 --- a/pppd/sys-solaris.c
293 +++ b/pppd/sys-solaris.c
294 @@ -2036,12 +2036,18 @@ cifaddr(u, o, h)
295   * sifdefaultroute - assign a default route through the address given.
296   */
297  int
298 -sifdefaultroute(u, l, g)
299 +sifdefaultroute(u, l, g, replace)
300      int u;
301      u_int32_t l, g;
302 +    bool replace;
303  {
304      struct rtentry rt;
305  
306 +    if (replace) {
307 +       error("replacedefaultroute not supported on this platform");
308 +       return 0;
309 +    }
310 +
311  #if defined(__USLC__)
312      g = l;                     /* use the local address as gateway */
313  #endif