*/
#ifndef lint
-static char rcsid[] = "$Id: ipcp.c,v 1.1 1993/11/11 03:54:25 paulus Exp $";
+static char rcsid[] = "$Id: ipcp.c,v 1.4 1994/04/11 07:19:06 paulus Exp $";
#endif
/*
* TODO:
- * Fix IP address negotiation (wantoptions or hisoptions).
- * Don't set zero IP addresses.
*/
#include <stdio.h>
#include "ppp.h"
#include "fsm.h"
#include "ipcp.h"
-
+#include "pathnames.h"
/* global vars */
ipcp_options ipcp_wantoptions[NPPP]; /* Options that we want to request */
ipcp_options ipcp_allowoptions[NPPP]; /* Options we allow peer to request */
ipcp_options ipcp_hisoptions[NPPP]; /* Options that we ack'd */
+extern char ifname[];
+extern char devname[];
+extern int baud_rate;
+
/* local vars */
static int cis_received[NPPP]; /* # Conf-Reqs received */
static int ipcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv CI */
static void ipcp_up __ARGS((fsm *)); /* We're UP */
static void ipcp_down __ARGS((fsm *)); /* We're DOWN */
-
+static void ipcp_script __ARGS((fsm *, char *)); /* Run an up/down script */
fsm ipcp_fsm[NPPP]; /* IPCP fsm structure */
ipcp_options *wo = &ipcp_wantoptions[f->unit];
wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
+ if (wo->ouraddr == 0)
+ wo->accept_local = 1;
+ if (wo->hisaddr == 0)
+ wo->accept_remote = 1;
ipcp_gotoptions[f->unit] = *wo;
cis_received[f->unit] = 0;
}
}
/*
- * Accept the peer's idea of our address if we don't know it.
- * Accept the peer's idea of his address if he knows it.
+ * Accept the peer's idea of {our,his} address, if different
+ * from our idea, only if the accept_{local,remote} flag is set.
*/
NAKCIADDR(CI_ADDR, neg_addr, go->old_addrs,
- if (!go->ouraddr && ciaddr1) { /* Do we know our address? */
- go->ouraddr = ciaddr1;
+ if (go->accept_local && ciaddr1) { /* Do we know our address? */
+ try.ouraddr = ciaddr1;
IPCPDEBUG((LOG_INFO, "local IP address %s",
ip_ntoa(ciaddr1)));
}
- if (ciaddr2) { /* Does he know his? */
- go->hisaddr = ciaddr2;
+ if (go->accept_remote && ciaddr2) { /* Does he know his? */
+ try.hisaddr = ciaddr2;
IPCPDEBUG((LOG_INFO, "remote IP address %s",
ip_ntoa(ciaddr2)));
}
try.old_addrs = 1;
GETLONG(l, p);
ciaddr1 = htonl(l);
- if (ciaddr1)
+ if (ciaddr1 && go->accept_local)
try.ouraddr = ciaddr1;
GETLONG(l, p);
ciaddr2 = htonl(l);
- if (ciaddr2)
+ if (ciaddr2 && go->accept_remote)
try.hisaddr = ciaddr2;
no.old_addrs = 1;
break;
try.old_addrs = 0;
GETLONG(l, p);
ciaddr1 = htonl(l);
- if (ciaddr1)
+ if (ciaddr1 && go->accept_local)
try.ouraddr = ciaddr1;
no.neg_addr = 1;
break;
GETLONG(tl, p); /* Parse source address (his) */
ciaddr1 = htonl(tl);
IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1)));
- if (wo->hisaddr && ciaddr1 != wo->hisaddr) {
+ if (ciaddr1 != wo->hisaddr
+ && (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof (long), p);
GETLONG(tl, p); /* Parse desination address (ours) */
ciaddr2 = htonl(tl);
IPCPDEBUG((LOG_INFO, "%s)", ip_ntoa(ciaddr2)));
- if (wo->ouraddr && ciaddr2 != wo->ouraddr) {
- orc = CONFNAK;
- if (!reject_if_disagree) {
- DECPTR(sizeof (long), p);
- tl = ntohl(wo->ouraddr);
- PUTLONG(tl, p);
+ if (ciaddr2 != wo->ouraddr) {
+ if (ciaddr2 == 0 || !wo->accept_local) {
+ orc = CONFNAK;
+ if (!reject_if_disagree) {
+ DECPTR(sizeof (long), p);
+ tl = ntohl(wo->ouraddr);
+ PUTLONG(tl, p);
+ }
+ } else {
+ go->ouraddr = ciaddr2; /* accept peer's idea */
}
}
- if (orc == CONFNAK)
- break;
ho->neg_addr = 1;
ho->old_addrs = 1;
GETLONG(tl, p); /* Parse source address (his) */
ciaddr1 = htonl(tl);
IPCPDEBUG((LOG_INFO, "(%s)", ip_ntoa(ciaddr1)));
- if (wo->hisaddr && ciaddr1 != wo->hisaddr) {
+ if (ciaddr1 != wo->hisaddr
+ && (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof (long), p);
}
}
- if (orc == CONFNAK)
- break;
-
ho->neg_addr = 1;
ho->hisaddr = ciaddr1;
break;
PUTCHAR(wo->cflag, p);
}
}
- if (orc == CONFNAK)
- break;
ho->maxslotindex = maxslotindex;
ho->cflag = wo->cflag;
+ } else {
+ ho->old_vj = 1;
+ ho->maxslotindex = MAX_STATES - 1;
+ ho->cflag = 1;
}
break;
/*
* We must have a non-zero IP address for both ends of the link.
*/
- if (ho->hisaddr == 0)
+ if (!ho->neg_addr)
ho->hisaddr = ipcp_wantoptions[f->unit].hisaddr;
if (ho->hisaddr == 0) {
}
/*
- * Check that the peer is allowed to use the IP address he wants.
+ * Check that the peer is allowed to use the IP address it wants.
*/
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
syslog(LOG_ERR, "Peer is not authorized to use remote address %s",
}
/* set tcp compression */
- sifvjcomp(f->unit, ho->neg_vj, ho->cflag);
+ sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
/* bring the interface up for IP */
if (!sifup(f->unit)) {
if (ipcp_wantoptions[f->unit].proxy_arp)
if (sifproxyarp(f->unit, ho->hisaddr))
go->proxy_arp = 1;
+
+ /*
+ * Execute the ip-up script, like this:
+ * /etc/ppp/ip-up interface tty speed local-IP remote-IP
+ */
+ ipcp_script(f, _PATH_IPUP);
+
}
cifdefaultroute(f->unit, hisaddr);
sifdown(f->unit);
cifaddr(f->unit, ouraddr, hisaddr);
+
+ /* Execute the ip-down script */
+ ipcp_script(f, _PATH_IPDOWN);
+}
+
+
+/*
+ * ipcp_script - Execute a script with arguments
+ * interface-name tty-name speed local-IP remote-IP.
+ */
+static void
+ipcp_script(f, script)
+ fsm *f;
+ char *script;
+{
+ char strspeed[32], strlocal[32], strremote[32];
+ char *argv[8];
+
+ sprintf(strspeed, "%d", baud_rate);
+ strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr));
+ strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr));
+
+ argv[0] = script;
+ argv[1] = ifname;
+ argv[2] = devname;
+ argv[3] = strspeed;
+ argv[4] = strlocal;
+ argv[5] = strremote;
+ argv[6] = NULL;
+ run_program(script, argv, 0);
+}
+
+/*
+ * ipcp_printpkt - print the contents of an IPCP packet.
+ */
+char *ipcp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej"
+};
+
+int
+ipcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer)();
+ void *arg;
+{
+ int code, id, len, olen;
+ u_char *pstart, *optend;
+ u_short cishort;
+ u_long cilong;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
+ printer(arg, " %s", ipcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print option list */
+ while (len >= 2) {
+ GETCHAR(code, p);
+ GETCHAR(olen, p);
+ p -= 2;
+ if (olen < 2 || olen > len) {
+ break;
+ }
+ printer(arg, " <");
+ len -= olen;
+ optend = p + olen;
+ switch (code) {
+ case CI_ADDRS:
+ if (olen == CILEN_ADDRS) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "addrs %s", ip_ntoa(cilong));
+ GETLONG(cilong, p);
+ printer(arg, " %s", ip_ntoa(cilong));
+ }
+ break;
+ case CI_COMPRESSTYPE:
+ if (olen >= CILEN_COMPRESS) {
+ p += 2;
+ GETSHORT(cishort, p);
+ printer(arg, "compress ");
+ switch (cishort) {
+ case IPCP_VJ_COMP:
+ printer(arg, "VJ");
+ break;
+ case IPCP_VJ_COMP_OLD:
+ printer(arg, "old-VJ");
+ break;
+ default:
+ printer(arg, "0x%x", cishort);
+ }
+ }
+ break;
+ case CI_ADDR:
+ if (olen == CILEN_ADDR) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "addr %s", ip_ntoa(cilong));
+ }
+ break;
+ }
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+ printer(arg, ">");
+ }
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
}