X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fipcp.c;h=da5fd739560f22d50f0191651da97cddc4b70ebb;hb=4abe4296f0eddbb2b6ff11dbbd27100156c85f87;hp=1ed4c07796706e3a9e9ce63817e75f2b9600fdb2;hpb=731ef5f88822fdccf7894a28c906bf6bf8fa134c;p=ppp.git diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 1ed4c07..da5fd73 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -40,7 +40,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: ipcp.c,v 1.63 2003/06/29 10:06:14 paulus Exp $" +#define RCSID "$Id: ipcp.c,v 1.69 2004/11/13 12:03:26 paulus Exp $" /* * TODO: @@ -103,7 +103,7 @@ static void ipcp_resetci __P((fsm *)); /* Reset our CI */ static int ipcp_cilen __P((fsm *)); /* Return length of our CI */ static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ -static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ +static int ipcp_nakci __P((fsm *, u_char *, int, int));/* Peer nak'd our CI */ static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ static void ipcp_up __P((fsm *)); /* We're UP */ @@ -696,6 +696,7 @@ ipcp_resetci(f) wo->accept_remote = 0; } } + BZERO(&ipcp_hisoptions[f->unit], sizeof(ipcp_options)); } @@ -720,10 +721,8 @@ ipcp_cilen(f) * First see if we want to change our options to the old * forms because we have received old forms from the peer. */ - if ((wo->neg_addr || wo->old_addrs) && !go->neg_addr && !go->old_addrs) { - /* use the old style of address negotiation */ - go->old_addrs = 1; - } + if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) + go->neg_addr = 0; if (wo->neg_vj && !go->neg_vj && !go->old_vj) { /* try an older style of VJ negotiation */ /* use the old style only if the peer did */ @@ -962,10 +961,11 @@ bad: * 1 - Nak was good. */ static int -ipcp_nakci(f, p, len) +ipcp_nakci(f, p, len, treat_as_reject) fsm *f; u_char *p; int len; + int treat_as_reject; { ipcp_options *go = &ipcp_gotoptions[f->unit]; u_char cimaxslotindex, cicflag; @@ -1041,11 +1041,17 @@ ipcp_nakci(f, p, len) * from our idea, only if the accept_{local,remote} flag is set. */ NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, - if (go->accept_local && ciaddr1) { /* Do we know our address? */ - try.ouraddr = ciaddr1; - } - if (go->accept_remote && ciaddr2) { /* Does he know his? */ - try.hisaddr = ciaddr2; + if (treat_as_reject) { + try.old_addrs = 0; + } else { + if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try.ouraddr = ciaddr1; + } + if (go->accept_remote && ciaddr2) { + /* take his idea of his address */ + try.hisaddr = ciaddr2; + } } ); @@ -1056,7 +1062,9 @@ ipcp_nakci(f, p, len) * the peer wants. */ NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - if (cilen == CILEN_VJ) { + if (treat_as_reject) { + try.neg_vj = 0; + } else if (cilen == CILEN_VJ) { GETCHAR(cimaxslotindex, p); GETCHAR(cicflag, p); if (cishort == IPCP_VJ_COMP) { @@ -1079,18 +1087,30 @@ ipcp_nakci(f, p, len) ); NAKCIADDR(CI_ADDR, neg_addr, - if (go->accept_local && ciaddr1) { /* Do we know our address? */ + if (treat_as_reject) { + try.neg_addr = 0; + try.old_addrs = 0; + } else if (go->accept_local && ciaddr1) { + /* take his idea of our address */ try.ouraddr = ciaddr1; } ); NAKCIDNS(CI_MS_DNS1, req_dns1, - try.dnsaddr[0] = cidnsaddr; - ); + if (treat_as_reject) { + try.req_dns1 = 0; + } else { + try.dnsaddr[0] = cidnsaddr; + } + ); NAKCIDNS(CI_MS_DNS2, req_dns2, - try.dnsaddr[1] = cidnsaddr; - ); + if (treat_as_reject) { + try.req_dns2 = 0; + } else { + try.dnsaddr[1] = cidnsaddr; + } + ); /* * There may be remaining CIs, if the peer is requesting negotiation @@ -1098,10 +1118,10 @@ ipcp_nakci(f, p, len) * If they want to negotiate about IP addresses, we comply. * If they want us to ask for compression, we refuse. */ - while (len > CILEN_VOID) { + while (len >= CILEN_VOID) { GETCHAR(citype, p); GETCHAR(cilen, p); - if( (len -= cilen) < 0 ) + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) goto bad; next = p + cilen - 2; @@ -1674,6 +1694,12 @@ ipcp_up(f) if (!ho->neg_addr && !ho->old_addrs) ho->hisaddr = wo->hisaddr; + if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) + && wo->ouraddr != 0) { + error("Peer refused to agree to our IP address"); + ipcp_close(f->unit, "Refused our IP address"); + return; + } if (go->ouraddr == 0) { error("Could not determine local IP address"); ipcp_close(f->unit, "Could not determine local IP address"); @@ -1687,12 +1713,12 @@ ipcp_up(f) script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); + if (go->dnsaddr[0]) + script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); + if (go->dnsaddr[1]) + script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { script_setenv("USEPEERDNS", "1", 0); - if (go->dnsaddr[0]) - script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); - if (go->dnsaddr[1]) - script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); create_resolv(go->dnsaddr[0], go->dnsaddr[1]); } @@ -1805,6 +1831,8 @@ ipcp_up(f) notice("secondary DNS address %I", go->dnsaddr[1]); } + reset_link_stats(f->unit); + np_up(f->unit, PPP_IP); ipcp_is_up = 1; @@ -1836,6 +1864,8 @@ ipcp_down(f) IPCPDEBUG(("ipcp: down")); /* XXX a bit IPv4-centric here, we only need to get the stats * before the interface is marked down. */ + /* XXX more correct: we must get the stats before running the notifiers, + * at least for the radius plugin */ update_link_stats(f->unit); notify(ip_down_notifier, 0); if (ip_down_hook) @@ -1846,6 +1876,10 @@ ipcp_down(f) } sifvjcomp(f->unit, 0, 0, 0); + print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), + * because print_link_stats() sets link_stats_valid + * to 0 (zero) */ + /* * If we are doing dial-on-demand, set the interface * to queue up outgoing packets (for now).