X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipcp.c;h=e9738fe4d894dd9291317412e4a8a93d331db19c;hp=b7da1f780fb3592d5096b5a9ec6c46306d9860ed;hb=6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5;hpb=2e09ef6886bbf00bc5a9a641110f801e372ffde6 diff --git a/pppd/ipcp.c b/pppd/ipcp.c index b7da1f7..e9738fe 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -575,6 +575,14 @@ ipcp_init(unit) f->callbacks = &ipcp_callbacks; fsm_init(&ipcp_fsm[unit]); + /* + * Some 3G modems use repeated IPCP NAKs as a way of stalling + * until they can contact a server on the network, so we increase + * the default number of NAKs we accept before we start treating + * them as rejects. + */ + f->maxnakloops = 100; + memset(wo, 0, sizeof(*wo)); memset(ao, 0, sizeof(*ao)); @@ -723,7 +731,8 @@ ipcp_cilen(f) #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) #define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) -#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) +#define LENCIDNS(neg) LENCIADDR(neg) +#define LENCIWINS(neg) LENCIADDR(neg) /* * First see if we want to change our options to the old @@ -745,7 +754,9 @@ ipcp_cilen(f) LENCIVJ(go->neg_vj, go->old_vj) + LENCIADDR(go->neg_addr) + LENCIDNS(go->req_dns1) + - LENCIDNS(go->req_dns2)) ; + LENCIDNS(go->req_dns2) + + LENCIWINS(go->winsaddr[0]) + + LENCIWINS(go->winsaddr[1])) ; } @@ -819,6 +830,19 @@ ipcp_addci(f, ucp, lenp) neg = 0; \ } +#define ADDCIWINS(opt, addr) \ + if (addr) { \ + if (len >= CILEN_ADDR) { \ + u_int32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + addr = 0; \ + } + ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, go->hisaddr); @@ -831,6 +855,10 @@ ipcp_addci(f, ucp, lenp) ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); + *lenp -= len; } @@ -934,6 +962,21 @@ ipcp_ackci(f, p, len) goto bad; \ } +#define ACKCIWINS(opt, addr) \ + if (addr) { \ + u_int32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } + ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, go->hisaddr); @@ -946,6 +989,10 @@ ipcp_ackci(f, p, len) ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */ @@ -1185,6 +1232,15 @@ ipcp_nakci(f, p, len, treat_as_reject) try.req_dns2 = 1; no.req_dns2 = 1; break; + case CI_MS_WINS1: + case CI_MS_WINS2: + if (cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1) + try.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + break; } p = next; } @@ -1301,6 +1357,21 @@ ipcp_rejci(f, p, len) try.neg = 0; \ } +#define REJCIWINS(opt, addr) \ + if (addr && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u_int32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != addr) \ + goto bad; \ + try.winsaddr[opt == CI_MS_WINS2] = 0; \ + } REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, go->hisaddr); @@ -1314,6 +1385,10 @@ ipcp_rejci(f, p, len) REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */