X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipcp.c;h=0dc251e503d725f4bec5f7f81953fafcc0f04168;hp=24452bff59efd9bec246551b6bae1f9791916a8a;hb=a12ffcd5b0a1cf9a4920064295c9b02b127465b3;hpb=99578f2b8bc6592119868e5fbe6f723cf3640bc2 diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 24452bf..0dc251e 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* * TODO: */ @@ -89,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 */ @@ -217,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 }, @@ -678,14 +686,17 @@ ipcp_resetci(fsm *f) ipcp_options *go = &ipcp_gotoptions[f->unit]; ipcp_options *ao = &ipcp_allowoptions[f->unit]; - wo->req_addr = (wo->neg_addr || wo->old_addrs) && - (ao->neg_addr || ao->old_addrs); + wo->req_addr = ((wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs)) || + (wo->hisaddr && !wo->accept_remote); if (wo->ouraddr == 0) wo->accept_local = 1; if (wo->hisaddr == 0) 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; @@ -737,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)) ; } @@ -809,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); \ @@ -819,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, @@ -834,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; } @@ -938,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; \ @@ -965,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. @@ -999,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 */ @@ -1064,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. @@ -1140,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. @@ -1206,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; @@ -1232,7 +1279,6 @@ bad: return 0; } - /* * ipcp_rejci - Reject some of our CIs. * Callback from fsm_rconfnakrej. @@ -1327,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) { \ @@ -1340,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, @@ -1355,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. @@ -1547,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 */ @@ -1648,7 +1694,8 @@ endswitch: * option safely. */ if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && - wo->req_addr && !reject_if_disagree && !noremoteip) { + wo->req_addr && !reject_if_disagree && + ((wo->hisaddr && !wo->accept_remote) || !noremoteip)) { if (rc == CONFACK) { rc = CONFNAK; ucp = inp; /* reset pointer */ @@ -1760,6 +1807,12 @@ ipcp_up(fsm *f) /* * We must have a non-zero IP address for both ends of the link. */ + + if (wo->hisaddr && !wo->accept_remote && (!(ho->neg_addr || ho->old_addrs) || ho->hisaddr != wo->hisaddr)) { + error("Peer refused to agree to his IP address"); + ipcp_close(f->unit, "Refused his IP address"); + return; + } if (!ho->neg_addr && !ho->old_addrs) ho->hisaddr = wo->hisaddr; @@ -1796,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. */