summaryrefslogtreecommitdiff
path: root/pppd
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2021-10-16 14:01:46 +1100
committerGitHub <noreply@github.com>2021-10-16 14:01:46 +1100
commit92c5612fdb77e83e49c524ae46110c129e13429e (patch)
tree0dbd4d56767b706ef9ed614b2720f3aa2d1e0c1e /pppd
parent4e895b5d9727fbbbf7c50c6ceedea5139da85f5d (diff)
parent61940d9540d27d8a66e12e163da57f7e641a8f2d (diff)
downloadppp-92c5612fdb77e83e49c524ae46110c129e13429e.tar.gz
Merge pull request #297 from mjeveritt/patch-11-test-pr
pppd: Add option to ask peer for WINS address This adds a 'usepeerwins' option, analogous to the usepeerdns option, to ask the peer for WINS server addresses. Nothing is done with the addresses provided other than to pass them to the ip-up script in environment variables. With this, if the peer sends an IPCP Configure-NAK containing WINS addresses, we will request them in the following IPCP Configure-Request. Co-authored-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Michael Everitt <gentoo@veremit.xyz> Signed-off-by: Lars Wendler <polynomial-c@gentoo.org> Signed-off-by: Michael Everitt <michael@2e0cer.net>
Diffstat (limited to 'pppd')
-rw-r--r--pppd/ipcp.c94
-rw-r--r--pppd/ipcp.h2
-rw-r--r--pppd/pppd.819
3 files changed, 92 insertions, 23 deletions
diff --git a/pppd/ipcp.c b/pppd/ipcp.c
index 6bcdf74..0dc251e 100644
--- a/pppd/ipcp.c
+++ b/pppd/ipcp.c
@@ -93,6 +93,7 @@ struct notifier *ip_down_notifier = NULL;
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 */
@@ -221,6 +222,9 @@ static option_t ipcp_option_list[] = {
{ "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 },
@@ -691,6 +695,8 @@ ipcp_resetci(fsm *f)
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;
@@ -742,8 +748,8 @@ ipcp_cilen(fsm *f)
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)) ;
}
@@ -814,8 +820,8 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp)
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); \
@@ -824,7 +830,7 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp)
PUTLONG(l, ucp); \
len -= CILEN_ADDR; \
} else \
- addr = 0; \
+ neg = 0; \
}
ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
@@ -839,9 +845,9 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp)
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;
}
@@ -943,8 +949,8 @@ ipcp_ackci(fsm *f, u_char *p, int len)
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; \
@@ -970,9 +976,9 @@ ipcp_ackci(fsm *f, u_char *p, int len)
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.
@@ -1004,7 +1010,7 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
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 */
@@ -1069,6 +1075,19 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
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.
@@ -1145,6 +1164,22 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
}
);
+ 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.
@@ -1211,13 +1246,20 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
no.req_dns2 = 1;
break;
case CI_MS_WINS1:
+ if (go->req_wins1 || no.req_wins1 || cilen != CILEN_ADDR)
+ goto bad;
+ GETLONG(l, p);
+ try.winsaddr[0] = htonl(l);
+ try.req_wins1 = 1;
+ no.req_wins1 = 1;
+ break;
case CI_MS_WINS2:
- if (cilen != CILEN_ADDR)
+ if (go->req_wins2 || no.req_wins2 || cilen != CILEN_ADDR)
goto bad;
GETLONG(l, p);
- ciaddr1 = htonl(l);
- if (ciaddr1)
- try.winsaddr[citype == CI_MS_WINS2] = ciaddr1;
+ try.winsaddr[1] = htonl(l);
+ try.req_wins2 = 1;
+ no.req_wins2 = 1;
break;
}
p = next;
@@ -1237,7 +1279,6 @@ bad:
return 0;
}
-
/*
* ipcp_rejci - Reject some of our CIs.
* Callback from fsm_rconfnakrej.
@@ -1332,8 +1373,8 @@ ipcp_rejci(fsm *f, u_char *p, int len)
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) { \
@@ -1345,7 +1386,7 @@ ipcp_rejci(fsm *f, u_char *p, int len)
/* 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,
@@ -1360,9 +1401,9 @@ ipcp_rejci(fsm *f, u_char *p, int len)
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.
@@ -1552,7 +1593,7 @@ ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree)
/* 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 */
@@ -1808,6 +1849,13 @@ ipcp_up(fsm *f)
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 --git a/pppd/ipcp.h b/pppd/ipcp.h
index 52d2b22..90336c4 100644
--- a/pppd/ipcp.h
+++ b/pppd/ipcp.h
@@ -77,6 +77,8 @@ typedef struct ipcp_options {
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 --git a/pppd/pppd.8 b/pppd/pppd.8
index b007406..7417a36 100644
--- a/pppd/pppd.8
+++ b/pppd/pppd.8
@@ -1240,6 +1240,16 @@ USEPEERDNS will be set to 1. In addition, pppd will create an
/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.
@@ -1842,6 +1852,15 @@ option was given).
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.