123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- pppd: Add "replacedefaultroute" and "noreplacedefaultroute" options
- This patch implements two new options, "replacedefaultroute" to replace any
- existing system default route when specified and "noreplacedefaultroute" to
- disable the "replacedefaultroute" option, which is useful in multi user
- environments where the administrator wants to allow users to dial pppd
- connections but not allow them to change the system default route.
- The patch originated from the Debian project.
- Signed-off-by: Jo-Philipp Wich <jo@mein.io>
- --- a/pppd/ipcp.c
- +++ b/pppd/ipcp.c
- @@ -198,6 +198,14 @@ static option_t ipcp_option_list[] = {
- "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
- &ipcp_wantoptions[0].default_route },
-
- + { "replacedefaultroute", o_bool,
- + &ipcp_wantoptions[0].replace_default_route,
- + "Replace default route", 1
- + },
- + { "noreplacedefaultroute", o_bool,
- + &ipcp_allowoptions[0].replace_default_route,
- + "Never replace default route", OPT_A2COPY,
- + &ipcp_wantoptions[0].replace_default_route },
- { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
- "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
- { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
- @@ -271,7 +279,7 @@ struct protent ipcp_protent = {
- ip_active_pkt
- };
-
- -static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
- +static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool));
- static void ipcp_script __P((char *, int)); /* Run an up/down script */
- static void ipcp_script_done __P((void *));
-
- @@ -1761,7 +1769,8 @@ ip_demand_conf(u)
- if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
- return 0;
- if (wo->default_route)
- - if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
- + if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
- + wo->replace_default_route))
- default_route_set[u] = 1;
- if (wo->proxy_arp)
- if (sifproxyarp(u, wo->hisaddr))
- @@ -1849,7 +1858,8 @@ ipcp_up(f)
- */
- if (demand) {
- if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
- - ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
- + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
- + wo->replace_default_route);
- if (go->ouraddr != wo->ouraddr) {
- warn("Local IP address changed to %I", go->ouraddr);
- script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
- @@ -1874,7 +1884,8 @@ ipcp_up(f)
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
- - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
- + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
- + wo->replace_default_route))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
- @@ -1924,7 +1935,8 @@ ipcp_up(f)
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
- - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
- + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
- + wo->replace_default_route))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
- @@ -2002,7 +2014,7 @@ ipcp_down(f)
- sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
- sifdown(f->unit);
- ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
- - ipcp_hisoptions[f->unit].hisaddr);
- + ipcp_hisoptions[f->unit].hisaddr, 0);
- }
-
- /* Execute the ip-down script */
- @@ -2018,16 +2030,25 @@ ipcp_down(f)
- * proxy arp entries, etc.
- */
- static void
- -ipcp_clear_addrs(unit, ouraddr, hisaddr)
- +ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
- int unit;
- u_int32_t ouraddr; /* local address */
- u_int32_t hisaddr; /* remote address */
- + bool replacedefaultroute;
- {
- if (proxy_arp_set[unit]) {
- cifproxyarp(unit, hisaddr);
- proxy_arp_set[unit] = 0;
- }
- - if (default_route_set[unit]) {
- + /* If replacedefaultroute, sifdefaultroute will be called soon
- + * with replacedefaultroute set and that will overwrite the current
- + * default route. This is the case only when doing demand, otherwise
- + * during demand, this cifdefaultroute would restore the old default
- + * route which is not what we want in this case. In the non-demand
- + * case, we'll delete the default route and restore the old if there
- + * is one saved by an sifdefaultroute with replacedefaultroute.
- + */
- + if (!replacedefaultroute && default_route_set[unit]) {
- cifdefaultroute(unit, ouraddr, hisaddr);
- default_route_set[unit] = 0;
- }
- --- a/pppd/ipcp.h
- +++ b/pppd/ipcp.h
- @@ -70,6 +70,7 @@ typedef struct ipcp_options {
- bool old_addrs; /* Use old (IP-Addresses) option? */
- bool req_addr; /* Ask peer to send IP address? */
- bool default_route; /* Assign default route through interface? */
- + bool replace_default_route; /* Replace default route through interface? */
- bool proxy_arp; /* Make proxy ARP entry for peer? */
- bool neg_vj; /* Van Jacobson Compression? */
- bool old_vj; /* use old (short) form of VJ option? */
- --- a/pppd/pppd.8
- +++ b/pppd/pppd.8
- @@ -127,6 +127,11 @@ is no other default route with the same
- value of -1, the route is only added if there is no default route at
- all.
- .TP
- +.B replacedefaultroute
- +This option is a flag to the defaultroute option. If defaultroute is
- +set and this flag is also set, pppd replaces an existing default route
- +with the new default route.
- +.TP
- .B disconnect \fIscript
- Execute the command specified by \fIscript\fR, by passing it to a
- shell, after
- @@ -740,7 +745,12 @@ disable both forms of hardware flow cont
- .TP
- .B nodefaultroute
- Disable the \fIdefaultroute\fR option. The system administrator who
- -wishes to prevent users from creating default routes with pppd
- +wishes to prevent users from adding a default route with pppd
- +can do so by placing this option in the /etc/ppp/options file.
- +.TP
- +.B noreplacedefaultroute
- +Disable the \fIreplacedefaultroute\fR option. The system administrator who
- +wishes to prevent users from replacing a default route with pppd
- can do so by placing this option in the /etc/ppp/options file.
- .TP
- .B nodeflate
- --- a/pppd/pppd.h
- +++ b/pppd/pppd.h
- @@ -681,7 +681,7 @@ int sif6addr __P((int, eui64_t, eui64_t
- int cif6addr __P((int, eui64_t, eui64_t));
- /* Remove an IPv6 address from i/f */
- #endif
- -int sifdefaultroute __P((int, u_int32_t, u_int32_t));
- +int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
- /* Create default route through i/f */
- int cifdefaultroute __P((int, u_int32_t, u_int32_t));
- /* Delete default route through i/f */
- --- a/pppd/sys-linux.c
- +++ b/pppd/sys-linux.c
- @@ -207,6 +207,8 @@ static unsigned char inbuf[512]; /* buff
- static int if_is_up; /* Interface has been marked up */
- static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */
- static int have_default_route; /* Gateway for default route added */
- +static struct rtentry old_def_rt; /* Old default route */
- +static int default_rt_repl_rest; /* replace and restore old default rt */
- static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
- static char proxy_arp_dev[16]; /* Device for proxy arp entry */
- static u_int32_t our_old_addr; /* for detecting address changes */
- @@ -1570,6 +1572,9 @@ static int read_route_table(struct rtent
- p = NULL;
- }
-
- + SET_SA_FAMILY (rt->rt_dst, AF_INET);
- + SET_SA_FAMILY (rt->rt_gateway, AF_INET);
- +
- SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
- SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
- SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
- @@ -1642,20 +1647,52 @@ int have_route_to(u_int32_t addr)
- /********************************************************************
- *
- * sifdefaultroute - assign a default route through the address given.
- - */
- -
- -int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
- -{
- - struct rtentry rt;
- -
- - if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) {
- - if (rt.rt_flags & RTF_GATEWAY)
- - error("not replacing existing default route via %I with metric %d",
- - SIN_ADDR(rt.rt_gateway), dfl_route_metric);
- - else
- + *
- + * If the global default_rt_repl_rest flag is set, then this function
- + * already replaced the original system defaultroute with some other
- + * route and it should just replace the current defaultroute with
- + * another one, without saving the current route. Use: demand mode,
- + * when pppd sets first a defaultroute it it's temporary ppp0 addresses
- + * and then changes the temporary addresses to the addresses for the real
- + * ppp connection when it has come up.
- + */
- +
- +int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
- +{
- + struct rtentry rt, tmp_rt;
- + struct rtentry *del_rt = NULL;
- +
- + if (default_rt_repl_rest) {
- + /* We have already reclaced the original defaultroute, if we
- + are called again, we will delete the current default route
- + and set the new default route in this function.
- + - this is normally only the case the doing demand: */
- + if (defaultroute_exists(&tmp_rt, dfl_route_metric))
- + del_rt = &tmp_rt;
- + } else if (defaultroute_exists(&old_def_rt, dfl_route_metric) &&
- + strcmp(old_def_rt.rt_dev, ifname) != 0) {
- + /* We did not yet replace an existing default route, let's
- + check if we should save and replace a default route: */
- + if (old_def_rt.rt_flags & RTF_GATEWAY) {
- + if (!replace) {
- + error("not replacing existing default route via %I with metric %d",
- + SIN_ADDR(old_def_rt.rt_gateway), dfl_route_metric);
- + return 0;
- + } else {
- + /* we need to copy rt_dev because we need it permanent too: */
- + char *tmp_dev = malloc(strlen(old_def_rt.rt_dev) + 1);
- + strcpy(tmp_dev, old_def_rt.rt_dev);
- + old_def_rt.rt_dev = tmp_dev;
- +
- + notice("replacing old default route to %s [%I] with metric %d",
- + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway),
- + dfl_route_metric);
- + default_rt_repl_rest = 1;
- + del_rt = &old_def_rt;
- + }
- + } else
- error("not replacing existing default route through %s with metric %d",
- - rt.rt_dev, dfl_route_metric);
- - return 0;
- + old_def_rt.rt_dev, dfl_route_metric);
- }
-
- memset (&rt, 0, sizeof (rt));
- @@ -1671,10 +1708,16 @@ int sifdefaultroute (int unit, u_int32_t
-
- rt.rt_flags = RTF_UP;
- if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
- - if ( ! ok_error ( errno ))
- + if (!ok_error(errno))
- error("default route ioctl(SIOCADDRT): %m");
- return 0;
- }
- + if (default_rt_repl_rest && del_rt)
- + if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
- + if (!ok_error(errno))
- + error("del old default route ioctl(SIOCDELRT): %m");
- + return 0;
- + }
-
- have_default_route = 1;
- return 1;
- @@ -1708,11 +1751,21 @@ int cifdefaultroute (int unit, u_int32_t
- rt.rt_flags = RTF_UP;
- if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
- if (still_ppp()) {
- - if ( ! ok_error ( errno ))
- + if (!ok_error(errno))
- error("default route ioctl(SIOCDELRT): %m");
- return 0;
- }
- }
- + if (default_rt_repl_rest) {
- + notice("restoring old default route to %s [%I]",
- + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
- + if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
- + if (!ok_error(errno))
- + error("restore default route ioctl(SIOCADDRT): %m");
- + return 0;
- + }
- + default_rt_repl_rest = 0;
- + }
-
- return 1;
- }
- --- a/pppd/sys-solaris.c
- +++ b/pppd/sys-solaris.c
- @@ -2039,12 +2039,18 @@ cifaddr(u, o, h)
- * sifdefaultroute - assign a default route through the address given.
- */
- int
- -sifdefaultroute(u, l, g)
- +sifdefaultroute(u, l, g, replace)
- int u;
- u_int32_t l, g;
- + bool replace;
- {
- struct rtentry rt;
-
- + if (replace) {
- + error("replacedefaultroute not supported on this platform");
- + return 0;
- + }
- +
- #if defined(__USLC__)
- g = l; /* use the local address as gateway */
- #endif
|