aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/pppd/ipcp.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1997-08-19 17:52:48 +0000
committerPeter Wemm <peter@FreeBSD.org>1997-08-19 17:52:48 +0000
commitb6633f4571e84ba9a70ad27938ceeeaad08f8d8f (patch)
tree1694e43d8d34f610573fbba567d58a45285f3f34 /usr.sbin/pppd/ipcp.c
parent1dce83d7ed36bfb1399cd82de0c7870dda359e28 (diff)
downloadsrc-b6633f4571e84ba9a70ad27938ceeeaad08f8d8f.tar.gz
src-b6633f4571e84ba9a70ad27938ceeeaad08f8d8f.zip
*gulp* First pass at merging in ppp-2.3.0's pppd. (this has
dial-on-demand, packet filtering, idle timeouts, etc). The IPX support is pretty much there but more work needs to be done in sys-bsd.c for the interface ioctls (Linux has a very different way of configuring IPX interfaces). Along the way some things have temporarily been lost due to very messy conflicts. I will recover them shortly when I can think clearer. The main one is the local:remote address override in pap-secrets and chap-secrets. Some other home-grown features (dns1,dns2) have been implemented differently. Microsoft's chap client auth hacks have been implemented. There are bound to be more rough edges... The changes for connect-max-retries doesn't fit well with the dial-on-demand code.
Notes
Notes: svn path=/head/; revision=28429
Diffstat (limited to 'usr.sbin/pppd/ipcp.c')
-rw-r--r--usr.sbin/pppd/ipcp.c538
1 files changed, 402 insertions, 136 deletions
diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c
index f567992f121d..94dfd8dfc2f3 100644
--- a/usr.sbin/pppd/ipcp.c
+++ b/usr.sbin/pppd/ipcp.c
@@ -28,6 +28,8 @@ static char rcsid[] = "$Id$";
#include <stdio.h>
#include <string.h>
#include <syslog.h>
+#include <netdb.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -44,7 +46,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 +63,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,7 +78,7 @@ 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 */
@@ -81,6 +86,42 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
};
/*
+ * Protocol entry points from main code.
+ */
+static void ipcp_init __P((int));
+static void ipcp_open __P((int));
+static void ipcp_close __P((int, char *));
+static void ipcp_lowerup __P((int));
+static void ipcp_lowerdown __P((int));
+static void ipcp_input __P((int, u_char *, int));
+static void ipcp_protrej __P((int));
+static int ipcp_printpkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+static void ip_check_options __P((void));
+static int ip_demand_conf __P((int));
+static int ip_active_pkt __P((u_char *, int));
+
+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,
+ ip_active_pkt
+};
+
+static void ipcp_clear_addrs __P((int));
+
+/*
* Lengths of configuration options.
*/
#define CILEN_VOID 2
@@ -117,7 +158,7 @@ u_int32_t ipaddr;
/*
* ipcp_init - Initialize IPCP.
*/
-void
+static void
ipcp_init(unit)
int unit;
{
@@ -130,13 +171,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;
@@ -150,7 +189,10 @@ ipcp_init(unit)
ao->maxslotindex = MAX_STATES - 1;
ao->cflag = 1;
- /* allow default route and proxyarp */
+ /*
+ * XXX These control whether the user may use the proxyarp
+ * and defaultroute options.
+ */
ao->proxy_arp = 1;
ao->default_route = 1;
}
@@ -159,7 +201,7 @@ ipcp_init(unit)
/*
* ipcp_open - IPCP is allowed to come up.
*/
-void
+static void
ipcp_open(unit)
int unit;
{
@@ -170,18 +212,19 @@ ipcp_open(unit)
/*
* ipcp_close - Take IPCP down.
*/
-void
-ipcp_close(unit)
+static void
+ipcp_close(unit, reason)
int unit;
+ char *reason;
{
- fsm_close(&ipcp_fsm[unit]);
+ fsm_close(&ipcp_fsm[unit], reason);
}
/*
* ipcp_lowerup - The lower layer is up.
*/
-void
+static void
ipcp_lowerup(unit)
int unit;
{
@@ -192,7 +235,7 @@ ipcp_lowerup(unit)
/*
* ipcp_lowerdown - The lower layer is down.
*/
-void
+static void
ipcp_lowerdown(unit)
int unit;
{
@@ -203,7 +246,7 @@ ipcp_lowerdown(unit)
/*
* ipcp_input - Input IPCP packet.
*/
-void
+static void
ipcp_input(unit, p, len)
int unit;
u_char *p;
@@ -218,7 +261,7 @@ ipcp_input(unit, p, len)
*
* Pretend the lower layer went down, so we shut up.
*/
-void
+static void
ipcp_protrej(unit)
int unit;
{
@@ -253,10 +296,36 @@ ipcp_cilen(f)
fsm *f;
{
ipcp_options *go = &ipcp_gotoptions[f->unit];
+ ipcp_options *wo = &ipcp_wantoptions[f->unit];
+ ipcp_options *ho = &ipcp_hisoptions[f->unit];
#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
+ /*
+ * First see if we want to change our options to the old
+ * forms because we have received old forms from the peer.
+ */
+ if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
+ /* use the old style of address negotiation */
+ go->neg_addr = 1;
+ go->old_addrs = 1;
+ }
+ if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
+ /* try an older style of VJ negotiation */
+ if (cis_received[f->unit] == 0) {
+ /* keep trying the new style until we see some CI from the peer */
+ go->neg_vj = 1;
+ } else {
+ /* use the old style only if the peer did */
+ if (ho->neg_vj && ho->old_vj) {
+ go->neg_vj = 1;
+ go->old_vj = 1;
+ go->vj_protocol = ho->vj_protocol;
+ }
+ }
+ }
+
return (LENCIADDR(go->neg_addr, go->old_addrs) +
LENCIVJ(go->neg_vj, go->old_vj));
}
@@ -271,9 +340,7 @@ ipcp_addci(f, ucp, lenp)
u_char *ucp;
int *lenp;
{
- ipcp_options *wo = &ipcp_wantoptions[f->unit];
ipcp_options *go = &ipcp_gotoptions[f->unit];
- ipcp_options *ho = &ipcp_hisoptions[f->unit];
int len = *lenp;
#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
@@ -310,30 +377,6 @@ ipcp_addci(f, ucp, lenp)
neg = 0; \
}
- /*
- * First see if we want to change our options to the old
- * forms because we have received old forms from the peer.
- */
- if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
- /* use the old style of address negotiation */
- go->neg_addr = 1;
- go->old_addrs = 1;
- }
- if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
- /* try an older style of VJ negotiation */
- if (cis_received[f->unit] == 0) {
- /* keep trying the new style until we see some CI from the peer */
- go->neg_vj = 1;
- } else {
- /* use the old style only if the peer did */
- if (ho->neg_vj && ho->old_vj) {
- go->neg_vj = 1;
- go->old_vj = 1;
- go->vj_protocol = ho->vj_protocol;
- }
- }
- }
-
ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
go->old_addrs, go->ouraddr, go->hisaddr);
@@ -561,7 +604,7 @@ ipcp_nakci(f, p, len)
no.neg_vj = 1;
break;
case CI_ADDRS:
- if (go->neg_addr && go->old_addrs || no.old_addrs
+ if ((go->neg_addr && go->old_addrs) || no.old_addrs
|| cilen != CILEN_ADDRS)
goto bad;
try.neg_addr = 1;
@@ -728,6 +771,9 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
u_char *ucp = inp; /* Pointer to current output char */
int l = *len; /* Length left */
u_char maxslotindex, cflag;
+ int d;
+
+ cis_received[f->unit] = 1;
/*
* Reset all his options.
@@ -756,28 +802,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
next += cilen; /* Step to next CI */
switch (citype) { /* Check CI type */
- case CI_DNS1:
- case CI_DNS2:
- if ( (citype == CI_DNS1 && !dns1) ||
- (citype == CI_DNS2 && !dns2)) {
- orc = CONFREJ; /* Reject DNS */
- break;
- }
- IPCPDEBUG((LOG_INFO, "ipcp: received DNS[12] "));
- GETLONG(tl, p); /* Parse his idea */
- ciaddr1 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1)));
- if ( (citype == CI_DNS1 && ciaddr1 != dns1) ||
- (citype == CI_DNS2 && ciaddr1 != dns2)) {
- orc = CONFNAK;
- if (!reject_if_disagree) {
- DECPTR(sizeof (long), p);
- tl = ntohl(citype == CI_DNS1 ? dns1 : dns2);
- PUTLONG(tl, p);
- }
- }
- break;
-
case CI_ADDRS:
IPCPDEBUG((LOG_INFO, "ipcp: received ADDRS "));
if (!ao->neg_addr ||
@@ -876,6 +900,48 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
ho->neg_addr = 1;
ho->hisaddr = ciaddr1;
break;
+
+ case CI_MS_DNS1:
+ case CI_MS_DNS2:
+ /* Microsoft primary or secondary DNS request */
+ d = citype == CI_MS_DNS2;
+ IPCPDEBUG((LOG_INFO, "ipcp: received DNS%d Request ", d+1));
+
+ /* If we do not have a DNS address then we cannot send it */
+ if (ao->dnsaddr[d] == 0 ||
+ cilen != CILEN_ADDR) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+ GETLONG(tl, p);
+ if (htonl(tl) != ao->dnsaddr[d]) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(ao->dnsaddr[d]);
+ PUTLONG(tl, p);
+ orc = CONFNAK;
+ }
+ break;
+
+ case CI_MS_WINS1:
+ case CI_MS_WINS2:
+ /* Microsoft primary or secondary WINS request */
+ d = citype == CI_MS_WINS2;
+ IPCPDEBUG((LOG_INFO, "ipcp: received WINS%d Request ", d+1));
+
+ /* If we do not have a DNS address then we cannot send it */
+ if (ao->winsaddr[d] == 0 ||
+ cilen != CILEN_ADDR) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+ GETLONG(tl, p);
+ if (htonl(tl) != ao->winsaddr[d]) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(ao->winsaddr[d]);
+ PUTLONG(tl, p);
+ orc = CONFNAK;
+ }
+ break;
case CI_COMPRESSTYPE:
IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE "));
@@ -987,6 +1053,76 @@ endswitch:
/*
+ * ip_check_options - check that any IP-related options are OK,
+ * and assign appropriate defaults.
+ */
+static 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) {
+ option_error("remote IP address required for demand-dialling\n");
+ exit(1);
+ }
+ if (demand && wo->accept_remote) {
+ option_error("ipcp-accept-remote is incompatible with demand\n");
+ exit(1);
+ }
+}
+
+
+/*
+ * ip_demand_conf - configure the interface as though
+ * IPCP were up, for use with dial-on-demand.
+ */
+static 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 (!sifup(u))
+ return 0;
+ if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+ return 0;
+ if (wo->default_route)
+ if (sifdefaultroute(u, wo->ouraddr, 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.
*
* Configure the IP network interface appropriately and bring it up.
@@ -998,25 +1134,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;
}
@@ -1026,42 +1162,93 @@ 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) {
+ if (go->ouraddr != wo->ouraddr)
+ syslog(LOG_WARNING, "Local IP address changed to %s",
+ ip_ntoa(go->ouraddr));
+ if (ho->hisaddr != wo->hisaddr)
+ syslog(LOG_WARNING, "Remote IP address changed to %s",
+ ip_ntoa(ho->hisaddr));
+ ipcp_clear_addrs(f->unit);
+
+ /* Set the interface to the new addresses */
+ 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);
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+ default_route_set[f->unit] = 1;
- /* bring the interface up for IP */
- if (!sifup(f->unit)) {
- IPCPDEBUG((LOG_WARNING, "sifup failed"));
- ipcp_close(f->unit);
- return;
- }
+ /* 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;
- /* 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;
+ }
+ demand_rexmit(PPP_IP);
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ } else {
+ /*
+ * Set IP addresses and (if specified) netmask.
+ */
+ mask = GetMask(go->ouraddr);
+
+#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+ if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+ IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+#endif
+
+ /* bring the interface up for IP */
+ if (!sifup(f->unit)) {
+ IPCPDEBUG((LOG_WARNING, "sifup failed"));
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
- /* Make a proxy ARP entry if requested. */
- if (ipcp_wantoptions[f->unit].proxy_arp)
- if (sifproxyarp(f->unit, ho->hisaddr))
- go->proxy_arp = 1;
+#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+ if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+ IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+#endif
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+ default_route_set[f->unit] = 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;
+
+ 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:
@@ -1082,18 +1269,20 @@ static void
ipcp_down(f)
fsm *f;
{
- u_int32_t ouraddr, hisaddr;
-
IPCPDEBUG((LOG_INFO, "ipcp: down"));
+ np_down(f->unit, PPP_IP);
+ sifvjcomp(f->unit, 0, 0, 0);
- 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 {
+ sifdown(f->unit);
+ ipcp_clear_addrs(f->unit);
+ }
/* Execute the ip-down script */
ipcp_script(f, _PATH_IPDOWN);
@@ -1101,6 +1290,41 @@ ipcp_down(f)
/*
+ * ipcp_clear_addrs() - clear the interface addresses, routes,
+ * proxy arp entries, etc.
+ */
+static void
+ipcp_clear_addrs(unit)
+ int unit;
+{
+ u_int32_t ouraddr, hisaddr;
+
+ ouraddr = ipcp_gotoptions[unit].ouraddr;
+ hisaddr = ipcp_hisoptions[unit].hisaddr;
+ if (proxy_arp_set[unit]) {
+ cifproxyarp(unit, hisaddr);
+ proxy_arp_set[unit] = 0;
+ }
+ if (default_route_set[unit]) {
+ cifdefaultroute(unit, ouraddr, hisaddr);
+ default_route_set[unit] = 0;
+ }
+ cifaddr(unit, ouraddr, hisaddr);
+}
+
+
+/*
+ * 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.
*/
@@ -1130,16 +1354,16 @@ ipcp_script(f, script)
/*
* ipcp_printpkt - print the contents of an IPCP packet.
*/
-char *ipcp_codenames[] = {
+static char *ipcp_codenames[] = {
"ConfReq", "ConfAck", "ConfNak", "ConfRej",
"TermReq", "TermAck", "CodeRej"
};
-int
+static int
ipcp_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
- void (*printer)();
+ void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len, olen;
@@ -1212,33 +1436,17 @@ ipcp_printpkt(p, plen, printer, arg)
printer(arg, "addr %s", ip_ntoa(htonl(cilong)));
}
break;
- case CI_DNS1:
- if (olen == CILEN_ADDR) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "dns1 %s", ip_ntoa(htonl(cilong)));
- }
- break;
- case CI_DNS2:
- if (olen == CILEN_ADDR) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "dns2 %s", ip_ntoa(htonl(cilong)));
- }
- break;
- case CI_NBNS1:
- if (olen == CILEN_ADDR) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "nbns1 %s", ip_ntoa(htonl(cilong)));
- }
+ case CI_MS_DNS1:
+ case CI_MS_DNS2:
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "dns-addr %s", ip_ntoa(htonl(cilong)));
break;
- case CI_NBNS2:
- if (olen == CILEN_ADDR) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "nbns2 %s", ip_ntoa(htonl(cilong)));
- }
+ case CI_MS_WINS1:
+ case CI_MS_WINS2:
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "wins-addr %s", ip_ntoa(htonl(cilong)));
break;
}
while (p < optend) {
@@ -1248,6 +1456,16 @@ ipcp_printpkt(p, plen, printer, arg)
printer(arg, ">");
}
break;
+
+ case TERMACK:
+ case TERMREQ:
+ if (len > 0 && *p >= ' ' && *p < 0x7f) {
+ printer(arg, " ");
+ print_string(p, len, printer, arg);
+ p += len;
+ len = 0;
+ }
+ break;
}
/* print the rest of the bytes in the packet */
@@ -1258,3 +1476,51 @@ ipcp_printpkt(p, plen, printer, arg)
return p - pstart;
}
+
+/*
+ * ip_active_pkt - see if this IP packet is worth bringing the link up for.
+ * We don't bring the link up for IP fragments or for TCP FIN packets
+ * with no data.
+ */
+#define IP_HDRLEN 20 /* bytes */
+#define IP_OFFMASK 0x1fff
+#define IPPROTO_TCP 6
+#define TCP_HDRLEN 20
+#define TH_FIN 0x01
+
+/*
+ * We use these macros because the IP header may be at an odd address,
+ * and some compilers might use word loads to get th_off or ip_hl.
+ */
+
+#define net_short(x) (((x)[0] << 8) + (x)[1])
+#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
+#define get_ipoff(x) net_short((unsigned char *)(x) + 6)
+#define get_ipproto(x) (((unsigned char *)(x))[9])
+#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
+#define get_tcpflags(x) (((unsigned char *)(x))[13])
+
+static int
+ip_active_pkt(pkt, len)
+ u_char *pkt;
+ int len;
+{
+ u_char *tcp;
+ int hlen;
+
+ len -= PPP_HDRLEN;
+ pkt += PPP_HDRLEN;
+ if (len < IP_HDRLEN)
+ return 0;
+ if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
+ return 0;
+ if (get_ipproto(pkt) != IPPROTO_TCP)
+ return 1;
+ hlen = get_iphl(pkt) * 4;
+ if (len < hlen + TCP_HDRLEN)
+ return 0;
+ tcp = pkt + hlen;
+ if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
+ return 0;
+ return 1;
+}