diff -ru ppp-2.4.4.orig/pppd/ipcp.c ppp-2.4.4/pppd/ipcp.c --- ppp-2.4.4.orig/pppd/ipcp.c 2005-08-26 01:59:34.000000000 +0200 +++ ppp-2.4.4/pppd/ipcp.c 2008-08-17 21:02:36.000000000 +0200 @@ -90,6 +90,7 @@ static int default_route_set[NUM_PPP]; /* Have set up a default route */ static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ static bool usepeerdns; /* Ask peer for DNS addrs */ +static bool usepeerwins; /* Ask peer for WINS addrs */ static int ipcp_is_up; /* have called np_up() */ static int ipcp_is_open; /* haven't called np_finished() */ static bool ask_for_local; /* request our address from peer */ @@ -209,6 +210,9 @@ { "usepeerdns", o_bool, &usepeerdns, "Ask peer for DNS address(es)", 1 }, + { "usepeerwins", o_bool, &usepeerwins, + "Ask peer for WINS address(es)", 1 }, + { "netmask", o_special, (void *)setnetmask, "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, @@ -687,6 +691,8 @@ wo->accept_remote = 1; wo->req_dns1 = usepeerdns; /* Request DNS addresses from the peer */ wo->req_dns2 = usepeerdns; + wo->req_wins1 = usepeerwins; /* Request WINS addresses from the peer */ + wo->req_wins2 = usepeerwins; *go = *wo; if (!ask_for_local) go->ouraddr = 0; @@ -714,8 +720,9 @@ #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 LENCIADDR(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 @@ -737,7 +744,9 @@ 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->req_wins1) + + LENCIWINS(go->req_wins2)); } @@ -810,6 +819,19 @@ } else \ neg = 0; \ } + +#define ADDCIWINS(opt, neg, addr) \ + if (neg) { \ + 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 \ + neg = 0; \ + } ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, go->hisaddr); @@ -823,6 +845,10 @@ ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + ADDCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]); + *lenp -= len; } @@ -926,6 +952,21 @@ goto bad; \ } +#define ACKCIWINS(opt, neg, addr) \ + if (neg) { \ + 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); @@ -938,6 +979,10 @@ ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + ACKCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */ @@ -971,7 +1016,7 @@ u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; u_short cishort; - u_int32_t ciaddr1, ciaddr2, l, cidnsaddr; + u_int32_t ciaddr1, ciaddr2, l, cidnsaddr, ciwinsaddr; ipcp_options no; /* options we've seen Naks for */ ipcp_options try; /* options to request next time */ @@ -1036,6 +1081,19 @@ code \ } +#define NAKCIWINS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciwinsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + /* * Accept the peer's idea of {our,his} address, if different * from our idea, only if the accept_{local,remote} flag is set. @@ -1112,6 +1170,22 @@ } ); + NAKCIWINS(CI_MS_WINS1, req_wins1, + if (treat_as_reject) { + try.req_wins1 = 0; + } else { + try.winsaddr[0] = ciwinsaddr; + } + ); + + NAKCIWINS(CI_MS_WINS2, req_wins2, + if (treat_as_reject) { + try.req_wins2 = 0; + } else { + try.winsaddr[1] = ciwinsaddr; + } + ); + /* * There may be remaining CIs, if the peer is requesting negotiation * on an option that we didn't include in our request packet. @@ -1275,6 +1349,21 @@ try.neg = 0; \ } +#define REJCIWINS(opt, neg, addr) \ + if (go->neg && \ + ((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.neg = 0; \ + } REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, go->hisaddr); @@ -1288,6 +1377,10 @@ REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + REJCIWINS(CI_MS_WINS1, req_wins1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, req_wins2, go->winsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */ @@ -1480,7 +1573,7 @@ /* Microsoft primary or secondary WINS request */ d = citype == CI_MS_WINS2; - /* If we do not have a DNS address then we cannot send it */ + /* If we do not have a WINS address then we cannot send it */ if (ao->winsaddr[d] == 0 || cilen != CILEN_ADDR) { /* Check CI length */ orc = CONFREJ; /* Reject CI */ @@ -1723,6 +1816,13 @@ create_resolv(go->dnsaddr[0], go->dnsaddr[1]); } + if (go->winsaddr[0]) + script_setenv("WINS1", ip_ntoa(go->winsaddr[0]), 0); + if (go->winsaddr[1]) + script_setenv("WINS2", ip_ntoa(go->winsaddr[1]), 0); + if (usepeerwins && (go->winsaddr[0] || go->winsaddr[1])) + script_setenv("USEPEERWINS", "1", 0); + /* * Check that the peer is allowed to use the IP address it wants. */ diff -ru ppp-2.4.4.orig/pppd/ipcp.h ppp-2.4.4/pppd/ipcp.h --- ppp-2.4.4.orig/pppd/ipcp.h 2002-12-05 01:03:32.000000000 +0200 +++ ppp-2.4.4/pppd/ipcp.h 2008-08-17 21:01:55.000000000 +0200 @@ -77,6 +77,8 @@ bool accept_remote; /* accept peer's value for hisaddr */ bool req_dns1; /* Ask peer to send primary DNS address? */ bool req_dns2; /* Ask peer to send secondary DNS address? */ + bool req_wins1; /* Ask peer to send primary WINS address? */ + bool req_wins2; /* Ask peer to send secondary WINS address? */ int vj_protocol; /* protocol value to use in VJ option */ int maxslotindex; /* values for RFC1332 VJ compression neg. */ bool cflag; diff -ru ppp-2.4.4.orig/pppd/pppd.8 ppp-2.4.4/pppd/pppd.8 --- ppp-2.4.4.orig/pppd/pppd.8 2008-08-17 21:01:30.000000000 +0200 +++ ppp-2.4.4/pppd/pppd.8 2008-08-17 21:05:38.000000000 +0200 @@ -1052,6 +1052,16 @@ /etc/ppp/resolv.conf file containing one or two nameserver lines with the address(es) supplied by the peer. .TP +.B usepeerwins +Ask the peer for up to 2 WINS server addresses. The addresses supplied +by the peer (if any) are passed to the /etc/ppp/ip\-up script in the +environment variables WINS1 and WINS2, and the environment variable +USEPEERWINS will be set to 1. +.LP +Please note that some modems (Like the Huawei E220) requires this option in +order to avoid a race condition that results in the incorrect DNS servers +being assigned. +.TP .B user \fIname Sets the name used for authenticating the local system to the peer to \fIname\fR. @@ -1603,6 +1613,15 @@ .B DNS2 If the peer supplies DNS server addresses, this variable is set to the second DNS server address supplied. +.TP +.B WINS1 +If the peer supplies WINS server addresses, this variable is set to the +first WINS server address supplied. +.TP +.B WINS2 +If the peer supplies WINS server addresses, this variable is set to the +second WINS server address supplied. +.P .P Pppd invokes the following scripts, if they exist. It is not an error if they don't exist.