The PPP servers of some UMTS/HSPA modems, including the Huawei E220
and E620, will send WINS server settings and insist that the client
accepts these. If the client does not do so, the modem will sometimes
provide bogus DNS server addresses like 10.11.12.13 and 10.11.12.14.
If we receive ms-wins settings from the server, save and include them
in our ConfReqs.
See also discussions at
http://thread.gmane.org/gmane.linux.ppp/2721
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=445711
[paulus@samba.org: In fact what seems to happen is that the modem naks
IPCP conf-reqs with bogus values until it manages to communicate on the
network. It's not clear that asking for the ms-wins stuff is essential
but it seems that sometimes it helps.]
Signed-off-by: Marcus Better <marcus@better.se>
Signed-off-by: Paul Mackerras <paulus@samba.org>
#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 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
/*
* First see if we want to change our options to the old
LENCIVJ(go->neg_vj, go->old_vj) +
LENCIADDR(go->neg_addr) +
LENCIDNS(go->req_dns1) +
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])) ;
+#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);
ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
go->hisaddr);
ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
+ ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+
+ ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+
try.req_dns2 = 1;
no.req_dns2 = 1;
break;
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;
+#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);
REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
go->ouraddr, go->hisaddr);
REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
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.
*/
/*
* If there are any remaining CIs, then this packet is bad.
*/