X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fipcp.c;h=d95b69b910f2dd41277e16d7445f841d8b50f3c1;hb=5cb32f1c7e8584994a2c887cb7a3d9823068d2ce;hp=80a18f8c80c6f47b82b632c43f8f2856d8de3929;hpb=2ae35d6c067d198c5e0bb4ac2d480271f3de3540;p=ppp.git diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 80a18f8..d95b69b 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "pppd.h" #include "fsm.h" @@ -195,6 +196,15 @@ static option_t ipcp_option_list[] = { "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, &ipcp_wantoptions[0].default_route }, +#ifdef __linux__ + { "replacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Replace default route", OPT_PRIV | 1 + }, + { "noreplacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Do not replace default route", 0 }, +#endif { "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, @@ -268,7 +278,7 @@ struct protent ipcp_protent = { ip_active_pkt }; -static void ipcp_clear_addrs (int, u_int32_t, u_int32_t); +static void ipcp_clear_addrs (int, u_int32_t, u_int32_t, bool); static void ipcp_script (char *, int); /* Run an up/down script */ static void ipcp_script_done (void *); @@ -984,6 +994,7 @@ bad: static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ipcp_options *wo = &ipcp_wantoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; @@ -1159,7 +1170,7 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) GETLONG(l, p); ciaddr1 = htonl(l); if (ciaddr1 && go->accept_local) - try.ouraddr = ciaddr1; + try.ouraddr = wo->old_addrs ? ciaddr1 : 0; GETLONG(l, p); ciaddr2 = htonl(l); if (ciaddr2 && go->accept_remote) @@ -1174,7 +1185,7 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) ciaddr1 = htonl(l); if (ciaddr1 && go->accept_local) try.ouraddr = ciaddr1; - if (try.ouraddr != 0) + if (try.ouraddr != 0 && wo->neg_addr) try.neg_addr = 1; no.neg_addr = 1; break; @@ -1460,7 +1471,7 @@ ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) if (ciaddr2 != wo->ouraddr) { if (ciaddr2 == 0 || !wo->accept_local) { orc = CONFNAK; - if (!reject_if_disagree) { + if (!reject_if_disagree && wo->old_addrs) { DECPTR(sizeof(u_int32_t), p); tl = ntohl(wo->ouraddr); PUTLONG(tl, p); @@ -1715,7 +1726,8 @@ ip_demand_conf(int 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)) @@ -1741,6 +1753,7 @@ ipcp_up(fsm *f) ipcp_options *ho = &ipcp_hisoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; ipcp_options *wo = &ipcp_wantoptions[f->unit]; + int ifindex; IPCPDEBUG(("ipcp: up")); @@ -1802,7 +1815,8 @@ ipcp_up(fsm *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); @@ -1827,7 +1841,8 @@ ipcp_up(fsm *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. */ @@ -1854,9 +1869,18 @@ ipcp_up(fsm *f) } #endif + ifindex = if_nametoindex(ifname); + /* run the pre-up script, if any, and wait for it to finish */ ipcp_script(_PATH_IPPREUP, 1); + /* check if preup script renamed the interface */ + if (!if_indextoname(ifindex, ifname)) { + error("Interface index %d failed to get renamed by a pre-up script", ifindex); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + /* bring the interface up for IP */ if (!sifup(f->unit)) { if (debug) @@ -1877,7 +1901,8 @@ ipcp_up(fsm *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. */ @@ -1911,7 +1936,7 @@ ipcp_up(fsm *f) */ if (ipcp_script_state == s_down && ipcp_script_pid == 0) { ipcp_script_state = s_up; - ipcp_script(_PATH_IPUP, 0); + ipcp_script(path_ipup, 0); } } @@ -1954,13 +1979,13 @@ ipcp_down(fsm *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 */ if (ipcp_script_state == s_up && ipcp_script_pid == 0) { ipcp_script_state = s_down; - ipcp_script(_PATH_IPDOWN, 0); + ipcp_script(path_ipdown, 0); } } @@ -1970,13 +1995,21 @@ ipcp_down(fsm *f) * proxy arp entries, etc. */ static void -ipcp_clear_addrs(int unit, u_int32_t ouraddr, u_int32_t hisaddr) +ipcp_clear_addrs(int unit, u_int32_t ouraddr, u_int32_t hisaddr, 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; } @@ -2009,13 +2042,13 @@ ipcp_script_done(void *arg) case s_up: if (ipcp_fsm[0].state != OPENED) { ipcp_script_state = s_down; - ipcp_script(_PATH_IPDOWN, 0); + ipcp_script(path_ipdown, 0); } break; case s_down: if (ipcp_fsm[0].state == OPENED) { ipcp_script_state = s_up; - ipcp_script(_PATH_IPUP, 0); + ipcp_script(path_ipup, 0); } break; }