Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | This patch comes from OpenEmbedded. |
| 2 | The original patch is from Debian / SuSE to implement replacedefaultroute |
| 3 | Rebased it to fit ppp-2.4.5. Dongxiao Xu <dongxiao.xu@intel.com> |
| 4 | |
| 5 | Upstream-Status: Inappropriate [debian/suse patches] |
| 6 | |
| 7 | diff -urN ppp-2.4.5-orig/pppd/ipcp.c ppp-2.4.5/pppd/ipcp.c |
| 8 | --- ppp-2.4.5-orig/pppd/ipcp.c 2010-06-30 15:51:12.050166398 +0800 |
| 9 | +++ ppp-2.4.5/pppd/ipcp.c 2010-06-30 16:40:00.478716855 +0800 |
| 10 | @@ -198,6 +198,16 @@ |
| 11 | "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, |
| 12 | &ipcp_wantoptions[0].default_route }, |
| 13 | |
| 14 | +#ifdef __linux__ |
| 15 | + { "replacedefaultroute", o_bool, |
| 16 | + &ipcp_wantoptions[0].replace_default_route, |
| 17 | + "Replace default route", 1 |
| 18 | + }, |
| 19 | + { "noreplacedefaultroute", o_bool, |
| 20 | + &ipcp_allowoptions[0].replace_default_route, |
| 21 | + "Never replace default route", OPT_A2COPY, |
| 22 | + &ipcp_wantoptions[0].replace_default_route }, |
| 23 | +#endif |
| 24 | { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, |
| 25 | "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, |
| 26 | { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, |
| 27 | @@ -271,7 +281,7 @@ |
| 28 | ip_active_pkt |
| 29 | }; |
| 30 | |
| 31 | -static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); |
| 32 | +static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool)); |
| 33 | static void ipcp_script __P((char *, int)); /* Run an up/down script */ |
| 34 | static void ipcp_script_done __P((void *)); |
| 35 | |
| 36 | @@ -1742,7 +1752,12 @@ |
| 37 | if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) |
| 38 | return 0; |
| 39 | if (wo->default_route) |
| 40 | +#ifndef __linux__ |
| 41 | if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) |
| 42 | +#else |
| 43 | + if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr, |
| 44 | + wo->replace_default_route)) |
| 45 | +#endif |
| 46 | default_route_set[u] = 1; |
| 47 | if (wo->proxy_arp) |
| 48 | if (sifproxyarp(u, wo->hisaddr)) |
| 49 | @@ -1830,7 +1845,8 @@ |
| 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 +1871,12 @@ |
| 60 | |
| 61 | /* assign a default route through the interface if required */ |
| 62 | if (ipcp_wantoptions[f->unit].default_route) |
| 63 | +#ifndef __linux__ |
| 64 | if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
| 65 | +#else |
| 66 | + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
| 67 | + wo->replace_default_route)) |
| 68 | +#endif |
| 69 | default_route_set[f->unit] = 1; |
| 70 | |
| 71 | /* Make a proxy ARP entry if requested. */ |
| 72 | @@ -1905,7 +1926,12 @@ |
| 73 | |
| 74 | /* assign a default route through the interface if required */ |
| 75 | if (ipcp_wantoptions[f->unit].default_route) |
| 76 | +#ifndef __linux__ |
| 77 | if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) |
| 78 | +#else |
| 79 | + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr, |
| 80 | + wo->replace_default_route)) |
| 81 | +#endif |
| 82 | default_route_set[f->unit] = 1; |
| 83 | |
| 84 | /* Make a proxy ARP entry if requested. */ |
| 85 | @@ -1983,7 +2009,7 @@ |
| 86 | sifnpmode(f->unit, PPP_IP, NPMODE_DROP); |
| 87 | sifdown(f->unit); |
| 88 | ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr, |
| 89 | - ipcp_hisoptions[f->unit].hisaddr); |
| 90 | + ipcp_hisoptions[f->unit].hisaddr, 0); |
| 91 | } |
| 92 | |
| 93 | /* Execute the ip-down script */ |
| 94 | @@ -1999,12 +2025,21 @@ |
| 95 | * proxy arp entries, etc. |
| 96 | */ |
| 97 | static void |
| 98 | -ipcp_clear_addrs(unit, ouraddr, hisaddr) |
| 99 | +ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute) |
| 100 | int unit; |
| 101 | u_int32_t ouraddr; /* local address */ |
| 102 | u_int32_t hisaddr; /* remote address */ |
| 103 | + bool replacedefaultroute; |
| 104 | { |
| 105 | - if (proxy_arp_set[unit]) { |
| 106 | + /* If replacedefaultroute, sifdefaultroute will be called soon |
| 107 | + * with replacedefaultroute set and that will overwrite the current |
| 108 | + * default route. This is the case only when doing demand, otherwise |
| 109 | + * during demand, this cifdefaultroute would restore the old default |
| 110 | + * route which is not what we want in this case. In the non-demand |
| 111 | + * case, we'll delete the default route and restore the old if there |
| 112 | + * is one saved by an sifdefaultroute with replacedefaultroute. |
| 113 | + */ |
| 114 | + if (!replacedefaultroute && default_route_set[unit]) { |
| 115 | cifproxyarp(unit, hisaddr); |
| 116 | proxy_arp_set[unit] = 0; |
| 117 | } |
| 118 | diff -urN ppp-2.4.5-orig/pppd/ipcp.h ppp-2.4.5/pppd/ipcp.h |
| 119 | --- ppp-2.4.5-orig/pppd/ipcp.h 2010-06-30 15:51:12.043682063 +0800 |
| 120 | +++ ppp-2.4.5/pppd/ipcp.h 2010-06-30 16:40:49.586203129 +0800 |
| 121 | @@ -70,6 +70,7 @@ |
| 122 | bool old_addrs; /* Use old (IP-Addresses) option? */ |
| 123 | bool req_addr; /* Ask peer to send IP address? */ |
| 124 | bool default_route; /* Assign default route through interface? */ |
| 125 | + bool replace_default_route; /* Replace default route through interface? */ |
| 126 | bool proxy_arp; /* Make proxy ARP entry for peer? */ |
| 127 | bool neg_vj; /* Van Jacobson Compression? */ |
| 128 | bool old_vj; /* use old (short) form of VJ option? */ |
| 129 | diff -urN ppp-2.4.5-orig/pppd/pppd.8 ppp-2.4.5/pppd/pppd.8 |
| 130 | --- ppp-2.4.5-orig/pppd/pppd.8 2010-06-30 15:51:12.043682063 +0800 |
| 131 | +++ ppp-2.4.5/pppd/pppd.8 2010-06-30 16:42:47.102413859 +0800 |
| 132 | @@ -121,6 +121,13 @@ |
| 133 | This entry is removed when the PPP connection is broken. This option |
| 134 | is privileged if the \fInodefaultroute\fR option has been specified. |
| 135 | .TP |
| 136 | +.B replacedefaultroute |
| 137 | +This option is a flag to the defaultroute option. If defaultroute is |
| 138 | +set and this flag is also set, pppd replaces an existing default route |
| 139 | +with the new default route. |
| 140 | + |
| 141 | + |
| 142 | +.TP |
| 143 | .B disconnect \fIscript |
| 144 | Execute the command specified by \fIscript\fR, by passing it to a |
| 145 | shell, after |
| 146 | @@ -717,7 +724,12 @@ |
| 147 | .TP |
| 148 | .B nodefaultroute |
| 149 | Disable the \fIdefaultroute\fR option. The system administrator who |
| 150 | -wishes to prevent users from creating default routes with pppd |
| 151 | +wishes to prevent users from adding a default route with pppd |
| 152 | +can do so by placing this option in the /etc/ppp/options file. |
| 153 | +.TP |
| 154 | +.B noreplacedefaultroute |
| 155 | +Disable the \fIreplacedefaultroute\fR option. The system administrator who |
| 156 | +wishes to prevent users from replacing a default route with pppd |
| 157 | can do so by placing this option in the /etc/ppp/options file. |
| 158 | .TP |
| 159 | .B nodeflate |
| 160 | diff -urN ppp-2.4.5-orig/pppd/pppd.h ppp-2.4.5/pppd/pppd.h |
| 161 | --- ppp-2.4.5-orig/pppd/pppd.h 2010-06-30 15:51:12.050166398 +0800 |
| 162 | +++ ppp-2.4.5/pppd/pppd.h 2010-06-30 16:43:36.514148327 +0800 |
| 163 | @@ -643,7 +643,11 @@ |
| 164 | int cif6addr __P((int, eui64_t, eui64_t)); |
| 165 | /* Remove an IPv6 address from i/f */ |
| 166 | #endif |
| 167 | +#ifndef __linux__ |
| 168 | int sifdefaultroute __P((int, u_int32_t, u_int32_t)); |
| 169 | +#else |
| 170 | +int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt)); |
| 171 | +#endif |
| 172 | /* Create default route through i/f */ |
| 173 | int cifdefaultroute __P((int, u_int32_t, u_int32_t)); |
| 174 | /* Delete default route through i/f */ |
| 175 | diff -urN ppp-2.4.5-orig/pppd/sys-linux.c ppp-2.4.5/pppd/sys-linux.c |
| 176 | --- ppp-2.4.5-orig/pppd/sys-linux.c 2010-06-30 15:51:12.050166398 +0800 |
| 177 | +++ ppp-2.4.5/pppd/sys-linux.c 2010-06-30 16:54:00.362716231 +0800 |
| 178 | @@ -206,6 +206,8 @@ |
| 179 | |
| 180 | static int if_is_up; /* Interface has been marked up */ |
| 181 | static int have_default_route; /* Gateway for default route added */ |
| 182 | +static struct rtentry old_def_rt; /* Old default route */ |
| 183 | +static int default_rt_repl_rest; /* replace and restore old default rt */ |
| 184 | static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ |
| 185 | static char proxy_arp_dev[16]; /* Device for proxy arp entry */ |
| 186 | static u_int32_t our_old_addr; /* for detecting address changes */ |
| 187 | @@ -1537,6 +1539,9 @@ |
| 188 | p = NULL; |
| 189 | } |
| 190 | |
| 191 | + SET_SA_FAMILY (rt->rt_dst, AF_INET); |
| 192 | + SET_SA_FAMILY (rt->rt_gateway, AF_INET); |
| 193 | + |
| 194 | SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16); |
| 195 | SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16); |
| 196 | SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16); |
| 197 | @@ -1606,20 +1611,51 @@ |
| 198 | /******************************************************************** |
| 199 | * |
| 200 | * sifdefaultroute - assign a default route through the address given. |
| 201 | - */ |
| 202 | - |
| 203 | -int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) |
| 204 | -{ |
| 205 | - struct rtentry rt; |
| 206 | - |
| 207 | - if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) { |
| 208 | - if (rt.rt_flags & RTF_GATEWAY) |
| 209 | - error("not replacing existing default route via %I", |
| 210 | - SIN_ADDR(rt.rt_gateway)); |
| 211 | - else |
| 212 | - error("not replacing existing default route through %s", |
| 213 | - rt.rt_dev); |
| 214 | - return 0; |
| 215 | + * |
| 216 | + * If the global default_rt_repl_rest flag is set, then this function |
| 217 | + * already replaced the original system defaultroute with some other |
| 218 | + * route and it should just replace the current defaultroute with |
| 219 | + * another one, without saving the current route. Use: demand mode, |
| 220 | + * when pppd sets first a defaultroute it it's temporary ppp0 addresses |
| 221 | + * and then changes the temporary addresses to the addresses for the real |
| 222 | + * ppp connection when it has come up. |
| 223 | + */ |
| 224 | + |
| 225 | +int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace) |
| 226 | +{ |
| 227 | + struct rtentry rt, tmp_rt; |
| 228 | + struct rtentry *del_rt = NULL; |
| 229 | + |
| 230 | + if (default_rt_repl_rest) { |
| 231 | + /* We have already reclaced the original defaultroute, if we |
| 232 | + * are called again, we will delete the current default route |
| 233 | + * and set the new default route in this function. |
| 234 | + * - this is normally only the case the doing demand: */ |
| 235 | + if (defaultroute_exists( &tmp_rt )) |
| 236 | + del_rt = &tmp_rt; |
| 237 | + } else if ( defaultroute_exists( &old_def_rt ) && |
| 238 | + strcmp( old_def_rt.rt_dev, ifname ) != 0) { |
| 239 | + /* We did not yet replace an existing default route, let's |
| 240 | + * check if we should save and replace a default route: |
| 241 | + */ |
| 242 | + u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway); |
| 243 | + if (old_gateway != gateway) { |
| 244 | + if (!replace) { |
| 245 | + error("not replacing default route to %s [%I]", |
| 246 | + old_def_rt.rt_dev, old_gateway); |
| 247 | + return 0; |
| 248 | + } else { |
| 249 | + // we need to copy rt_dev because we need it permanent too: |
| 250 | + char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1); |
| 251 | + strcpy(tmp_dev, old_def_rt.rt_dev); |
| 252 | + old_def_rt.rt_dev = tmp_dev; |
| 253 | + |
| 254 | + notice("replacing old default route to %s [%I]", |
| 255 | + old_def_rt.rt_dev, old_gateway); |
| 256 | + default_rt_repl_rest = 1; |
| 257 | + del_rt = &old_def_rt; |
| 258 | + } |
| 259 | + } |
| 260 | } |
| 261 | |
| 262 | memset (&rt, 0, sizeof (rt)); |
| 263 | @@ -1638,6 +1674,12 @@ |
| 264 | error("default route ioctl(SIOCADDRT): %m"); |
| 265 | return 0; |
| 266 | } |
| 267 | + if (default_rt_repl_rest && del_rt) |
| 268 | + if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) { |
| 269 | + if ( ! ok_error ( errno )) |
| 270 | + error("del old default route ioctl(SIOCDELRT): %m(%d)", errno); |
| 271 | + return 0; |
| 272 | + } |
| 273 | |
| 274 | have_default_route = 1; |
| 275 | return 1; |
| 276 | @@ -1673,6 +1715,16 @@ |
| 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(%d)", errno); |
| 286 | + return 0; |
| 287 | + } |
| 288 | + default_rt_repl_rest = 0; |
| 289 | + } |
| 290 | |
| 291 | return 1; |
| 292 | } |