X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipcp.c;h=fea0c7a3e90edd94ca68683b32fa567891ec55f2;hp=b3096c6501e27404cf4742c87c29adbcb8143102;hb=faa01ae951ca6a5809283693548a6176fbde13a3;hpb=bee9bbb1e96af1697d4045e03928f86159538337 diff --git a/pppd/ipcp.c b/pppd/ipcp.c index b3096c6..fea0c7a 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: ipcp.c,v 1.17 1995/04/28 06:24:53 paulus Exp $"; +static char rcsid[] = "$Id: ipcp.c,v 1.23 1996/01/01 22:56:53 paulus Exp $"; #endif /* @@ -28,6 +28,7 @@ static char rcsid[] = "$Id: ipcp.c,v 1.17 1995/04/28 06:24:53 paulus Exp $"; #include #include #include +#include #include #include #include @@ -44,7 +45,9 @@ ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ /* local vars */ -static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ +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 */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -59,6 +62,7 @@ static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ static void ipcp_up __P((fsm *)); /* We're UP */ static void ipcp_down __P((fsm *)); /* We're DOWN */ static void ipcp_script __P((fsm *, char *)); /* Run an up/down script */ +static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ @@ -73,13 +77,20 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ ipcp_up, /* Called when fsm reaches OPENED state */ ipcp_down, /* Called when fsm leaves OPENED state */ NULL, /* Called when we want the lower layer up */ - NULL, /* Called when we want the lower layer down */ + ipcp_finished, /* Called when we want the lower layer down */ NULL, /* Called when Protocol-Reject received */ NULL, /* Retransmission is necessary */ NULL, /* Called to handle protocol-specific codes */ "IPCP" /* String name of protocol */ }; +struct protent ipcp_protent = { + PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej, + ipcp_lowerup, ipcp_lowerdown, ipcp_open, ipcp_close, + ipcp_printpkt, NULL, 1, "IPCP", + ip_check_options, ip_demand_conf, +}; + /* * Lengths of configuration options. */ @@ -130,13 +141,11 @@ ipcp_init(unit) f->callbacks = &ipcp_callbacks; fsm_init(&ipcp_fsm[unit]); - wo->neg_addr = 1; - wo->old_addrs = 0; - wo->ouraddr = 0; - wo->hisaddr = 0; + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + wo->neg_addr = 1; wo->neg_vj = 1; - wo->old_vj = 0; wo->vj_protocol = IPCP_VJ_COMP; wo->maxslotindex = MAX_STATES - 1; /* really max index */ wo->cflag = 1; @@ -149,6 +158,13 @@ ipcp_init(unit) ao->neg_vj = 1; ao->maxslotindex = MAX_STATES - 1; ao->cflag = 1; + + /* + * XXX These control whether the user may use the proxyarp + * and defaultroute options. + */ + ao->proxy_arp = 1; + ao->default_route = 1; } @@ -167,10 +183,11 @@ ipcp_open(unit) * ipcp_close - Take IPCP down. */ void -ipcp_close(unit) +ipcp_close(unit, reason) int unit; + char *reason; { - fsm_close(&ipcp_fsm[unit]); + fsm_close(&ipcp_fsm[unit], reason); } @@ -581,10 +598,9 @@ ipcp_nakci(f, p, len) if (ciaddr1 && go->accept_local) try.ouraddr = ciaddr1; if (try.ouraddr != 0) - no.neg_addr = 1; + try.neg_addr = 1; + no.neg_addr = 1; break; - default: - goto bad; } p = next; } @@ -851,6 +867,46 @@ ipcp_reqci(f, inp, len, reject_if_disagree) ho->neg_addr = 1; ho->hisaddr = ciaddr1; break; + +#ifdef USE_MS_DNS + case CI_MS_DNS1: + /* Microsoft primary DNS request */ + IPCPDEBUG((LOG_INFO, "ipcp: received DNS1 Request ")); + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[0] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[0]) { + DECPTR(sizeof(u_int32_t), p); + tl = ntohl(ao->dnsaddr[0]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_MS_DNS2: + /* Microsoft secondary DNS request */ + IPCPDEBUG((LOG_INFO, "ipcp: received DNS2 Request ")); + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[1] == 0 || /* Yes, this is the first one! */ + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[1]) { /* and this is the 2nd one */ + DECPTR(sizeof(u_int32_t), p); + tl = ntohl(ao->dnsaddr[1]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif case CI_COMPRESSTYPE: IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE ")); @@ -888,7 +944,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) } } ho->maxslotindex = maxslotindex; - ho->cflag = wo->cflag; + ho->cflag = cflag; } else { ho->old_vj = 1; ho->maxslotindex = MAX_STATES - 1; @@ -961,6 +1017,73 @@ endswitch: } +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +void +ip_check_options() +{ + struct hostent *hp; + u_int32_t local; + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Default our local IP address based on our hostname. + * If local IP address already given, don't bother. + */ + if (wo->ouraddr == 0 && !disable_defaultip) { + /* + * Look up our hostname (possibly with domain name appended) + * and take the first IP address as our local IP address. + * If there isn't an IP address for our hostname, too bad. + */ + wo->accept_local = 1; /* don't insist on this default value */ + if ((hp = gethostbyname(hostname)) != NULL) { + local = *(u_int32_t *)hp->h_addr; + if (local != 0 && !bad_ip_adrs(local)) + wo->ouraddr = local; + } + } + + if (demand && wo->hisaddr == 0) { + fprintf(stderr, + "Remote IP address must be specified for demand-dialling\n"); + exit(1); + } +} + + +/* + * ip_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +int +ip_demand_conf(u) + int u; +{ + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) + return 0; + if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) + return 0; + if (!sifup(u)) + return 0; + if (wo->default_route) + if (sifdefaultroute(u, wo->hisaddr)) + default_route_set[u] = 1; + if (wo->proxy_arp) + if (sifproxyarp(u, wo->hisaddr)) + proxy_arp_set[u] = 1; + + syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(wo->ouraddr)); + syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr)); + + return 1; +} + + /* * ipcp_up - IPCP has come UP. * @@ -973,25 +1096,25 @@ ipcp_up(f) u_int32_t mask; ipcp_options *ho = &ipcp_hisoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + np_up(f->unit, PPP_IP); IPCPDEBUG((LOG_INFO, "ipcp: up")); - go->default_route = 0; - go->proxy_arp = 0; /* * We must have a non-zero IP address for both ends of the link. */ if (!ho->neg_addr) - ho->hisaddr = ipcp_wantoptions[f->unit].hisaddr; + ho->hisaddr = wo->hisaddr; if (ho->hisaddr == 0) { syslog(LOG_ERR, "Could not determine remote IP address"); - ipcp_close(f->unit); + ipcp_close(f->unit, "Could not determine remote IP address"); return; } if (go->ouraddr == 0) { syslog(LOG_ERR, "Could not determine local IP address"); - ipcp_close(f->unit); + ipcp_close(f->unit, "Could not determine local IP address"); return; } @@ -1001,42 +1124,59 @@ ipcp_up(f) if (!auth_ip_addr(f->unit, ho->hisaddr)) { syslog(LOG_ERR, "Peer is not authorized to use remote address %s", ip_ntoa(ho->hisaddr)); - ipcp_close(f->unit); + ipcp_close(f->unit, "Unauthorized remote IP address"); return; } - syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr)); - syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr)); + /* set tcp compression */ + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); /* - * Set IP addresses and (if specified) netmask. + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. */ - mask = GetMask(go->ouraddr); - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); - ipcp_close(f->unit); - return; - } + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + syslog(LOG_ERR, "Failed to negotiate desired IP addresses"); + ipcp_close(f->unit, "Wrong IP addresses"); + return; + } + demand_rexmit(PPP_IP); + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + + } else { + + /* + * Set IP addresses and (if specified) netmask. + */ + mask = GetMask(go->ouraddr); + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { + IPCPDEBUG((LOG_WARNING, "sifaddr failed")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } - /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); + /* bring the interface up for IP */ + if (!sifup(f->unit)) { + IPCPDEBUG((LOG_WARNING, "sifup failed")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } - /* bring the interface up for IP */ - if (!sifup(f->unit)) { - IPCPDEBUG((LOG_WARNING, "sifup failed")); - ipcp_close(f->unit); - return; - } + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(f->unit, ho->hisaddr)) + default_route_set[f->unit] = 1; - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(f->unit, ho->hisaddr)) - go->default_route = 1; + /* Make a proxy ARP entry if requested. */ + if (ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(f->unit, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; - /* Make a proxy ARP entry if requested. */ - if (ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(f->unit, ho->hisaddr)) - go->proxy_arp = 1; + syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr)); + syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr)); + } /* * Execute the ip-up script, like this: @@ -1059,22 +1199,47 @@ ipcp_down(f) { u_int32_t ouraddr, hisaddr; + np_down(f->unit, PPP_IP); IPCPDEBUG((LOG_INFO, "ipcp: down")); - ouraddr = ipcp_gotoptions[f->unit].ouraddr; - hisaddr = ipcp_hisoptions[f->unit].hisaddr; - if (ipcp_gotoptions[f->unit].proxy_arp) - cifproxyarp(f->unit, hisaddr); - if (ipcp_gotoptions[f->unit].default_route) - cifdefaultroute(f->unit, hisaddr); - sifdown(f->unit); - cifaddr(f->unit, ouraddr, hisaddr); + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE); + + } else { + ouraddr = ipcp_gotoptions[f->unit].ouraddr; + hisaddr = ipcp_hisoptions[f->unit].hisaddr; + if (proxy_arp_set[f->unit]) { + cifproxyarp(f->unit, hisaddr); + proxy_arp_set[f->unit] = 0; + } + if (default_route_set[f->unit]) { + cifdefaultroute(f->unit, hisaddr); + default_route_set[f->unit] = 0; + } + sifdown(f->unit); + cifaddr(f->unit, ouraddr, hisaddr); + } /* Execute the ip-down script */ ipcp_script(f, _PATH_IPDOWN); } +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void +ipcp_finished(f) + fsm *f; +{ + np_finished(f->unit, PPP_IP); +} + + /* * ipcp_script - Execute a script with arguments * interface-name tty-name speed local-IP remote-IP.