summaryrefslogtreecommitdiff
path: root/user/ppp/26_all_pppd-usepeerwins.patch
blob: d66fbe0b1c2782acd360d980eb9b2f3145684b10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
--- ppp-2.4.6/pppd/ipcp.c
+++ ppp-2.4.6/pppd/ipcp.c
@@ -91,6 +91,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 */
@@ -210,6 +211,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 },
 
@@ -703,6 +707,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;
@@ -755,8 +761,8 @@
 	    LENCIADDR(go->neg_addr) +
 	    LENCIDNS(go->req_dns1) +
 	    LENCIDNS(go->req_dns2) +
-	    LENCIWINS(go->winsaddr[0]) +
-	    LENCIWINS(go->winsaddr[1])) ;
+	    LENCIWINS(go->req_wins1) +
+	    LENCIWINS(go->req_wins2)) ;
 }
 
 
@@ -830,8 +836,8 @@
 	    neg = 0; \
     }
 
-#define ADDCIWINS(opt, addr) \
-    if (addr) { \
+#define ADDCIWINS(opt, neg, addr) \
+    if (neg) { \
 	if (len >= CILEN_ADDR) { \
 	    u_int32_t l; \
 	    PUTCHAR(opt, ucp); \
@@ -840,7 +846,7 @@
 	    PUTLONG(l, ucp); \
 	    len -= CILEN_ADDR; \
 	} else \
-	    addr = 0; \
+	    neg = 0; \
     }
 
     ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
@@ -855,9 +861,9 @@
 
     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
 
-    ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    ADDCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);
 
-    ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    ADDCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);
     
     *lenp -= len;
 }
@@ -962,8 +968,8 @@
 	    goto bad; \
     }
 
-#define ACKCIWINS(opt, addr) \
-    if (addr) { \
+#define ACKCIWINS(opt, neg, addr) \
+    if (neg) { \
 	u_int32_t l; \
 	if ((len -= CILEN_ADDR) < 0) \
 	    goto bad; \
@@ -989,9 +995,9 @@
 
     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
 
-    ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    ACKCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);
 
-    ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    ACKCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);
 
     /*
      * If there are any remaining CIs, then this packet is bad.
@@ -1026,7 +1032,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 */
 
@@ -1091,6 +1097,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.
@@ -1167,6 +1186,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.
@@ -1259,7 +1294,6 @@
     return 0;
 }
 
-
 /*
  * ipcp_rejci - Reject some of our CIs.
  * Callback from fsm_rconfnakrej.
@@ -1357,8 +1391,8 @@
 	try.neg = 0; \
     }
 
-#define REJCIWINS(opt, addr) \
-    if (addr && \
+#define REJCIWINS(opt, neg, addr) \
+    if (go->neg && \
 	((cilen = p[1]) == CILEN_ADDR) && \
 	len >= cilen && \
 	p[0] == opt) { \
@@ -1370,7 +1404,7 @@
 	/* Check rejected value. */ \
 	if (cilong != addr) \
 	    goto bad; \
-	try.winsaddr[opt == CI_MS_WINS2] = 0; \
+	try.neg = 0; \
     }
 
     REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
@@ -1385,9 +1419,9 @@
 
     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
 
-    REJCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+    REJCIWINS(CI_MS_WINS1, req_wins1, go->winsaddr[0]);
 
-    REJCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    REJCIWINS(CI_MS_WINS2, req_wins2, go->winsaddr[1]);
 
     /*
      * If there are any remaining CIs, then this packet is bad.
@@ -1581,7 +1615,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 */
@@ -1830,6 +1864,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.
      */
--- ppp-2.4.6/pppd/ipcp.h
+++ ppp-2.4.6/pppd/ipcp.h
@@ -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;
--- ppp-2.4.6/pppd/pppd.8
+++ ppp-2.4.6/pppd/pppd.8
@@ -1102,6 +1102,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.
@@ -1650,6 +1660,15 @@
 If the peer supplies DNS server addresses, this variable is set to the
 second DNS server address supplied (whether or not the usepeerdns
 option was given).
+.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.