summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ppp/Makefile4
-rw-r--r--usr.sbin/ppp/bundle.c135
-rw-r--r--usr.sbin/ppp/bundle.h10
-rw-r--r--usr.sbin/ppp/command.c296
-rw-r--r--usr.sbin/ppp/filter.c14
-rw-r--r--usr.sbin/ppp/iface.c431
-rw-r--r--usr.sbin/ppp/iface.h60
-rw-r--r--usr.sbin/ppp/ipcp.c271
-rw-r--r--usr.sbin/ppp/ipcp.h5
-rw-r--r--usr.sbin/ppp/main.c7
-rw-r--r--usr.sbin/ppp/ppp.8127
-rw-r--r--usr.sbin/ppp/ppp.8.m4127
-rw-r--r--usr.sbin/ppp/route.c7
-rw-r--r--usr.sbin/ppp/tun.c5
14 files changed, 1082 insertions, 417 deletions
diff --git a/usr.sbin/ppp/Makefile b/usr.sbin/ppp/Makefile
index 5bfe87d..696479e 100644
--- a/usr.sbin/ppp/Makefile
+++ b/usr.sbin/ppp/Makefile
@@ -1,8 +1,8 @@
-# $Id: Makefile,v 1.47 1998/08/31 12:14:31 brian Exp $
+# $Id: Makefile,v 1.49 1998/10/20 00:19:38 brian Exp $
PROG= ppp
SRCS= arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chat.c command.c \
- datalink.c deflate.c defs.c filter.c fsm.c hdlc.c id.c ip.c \
+ datalink.c deflate.c defs.c filter.c fsm.c hdlc.c id.c iface.c ip.c \
ipcp.c iplist.c lcp.c link.c log.c lqr.c main.c mbuf.c modem.c \
mp.c pap.c physical.c pred.c probe.c prompt.c route.c server.c \
sig.c slcompress.c systems.c throughput.c timer.c tun.c vjcomp.c
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c
index 569d893..28da452 100644
--- a/usr.sbin/ppp/bundle.c
+++ b/usr.sbin/ppp/bundle.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: bundle.c,v 1.34 1998/08/26 17:39:36 brian Exp $
+ * $Id: bundle.c,v 1.35 1998/09/17 00:45:25 brian Exp $
*/
#include <sys/param.h>
@@ -89,6 +89,7 @@
#include "cbcp.h"
#include "datalink.h"
#include "ip.h"
+#include "iface.h"
#define SCATTER_SEGMENTS 4 /* version, datalink, name, physical */
#define SOCKET_OVERHEAD 100 /* additional buffer space for large */
@@ -148,49 +149,6 @@ bundle_NewPhase(struct bundle *bundle, u_int new)
}
}
-static int
-bundle_CleanInterface(const struct bundle *bundle)
-{
- int s;
- struct ifreq ifrq;
- struct ifaliasreq ifra;
-
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- log_Printf(LogERROR, "bundle_CleanInterface: socket(): %s\n",
- strerror(errno));
- return (-1);
- }
- strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1);
- ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
- while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) {
- memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
- strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1);
- ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
- ifra.ifra_addr = ifrq.ifr_addr;
- if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) {
- if (ifra.ifra_addr.sa_family == AF_INET)
- log_Printf(LogERROR, "Can't get dst for %s on %s !\n",
- inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
- bundle->ifp.Name);
- close(s);
- return 0;
- }
- ifra.ifra_broadaddr = ifrq.ifr_dstaddr;
- if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
- if (ifra.ifra_addr.sa_family == AF_INET)
- log_Printf(LogERROR, "Can't delete %s address on %s !\n",
- inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
- bundle->ifp.Name);
- close(s);
- return 0;
- }
- }
- close(s);
-
- return 1;
-}
-
static void
bundle_LayerStart(void *v, struct fsm *fp)
{
@@ -387,14 +345,14 @@ bundle_LayerUp(void *v, struct fsm *fp)
if (bundle->ncp.mp.active) {
struct datalink *dl;
- bundle->ifp.Speed = 0;
+ bundle->ifSpeed = 0;
for (dl = bundle->links; dl; dl = dl->next)
if (dl->state == DATALINK_OPEN)
- bundle->ifp.Speed += modem_Speed(dl->physical);
+ bundle->ifSpeed += modem_Speed(dl->physical);
tun_configure(bundle, bundle->ncp.mp.peer_mrru);
bundle->autoload.running = 1;
} else {
- bundle->ifp.Speed = modem_Speed(p);
+ bundle->ifSpeed = modem_Speed(p);
tun_configure(bundle, fsm2lcp(fp)->his_mru);
}
} else if (fp->proto == PROTO_IPCP) {
@@ -424,15 +382,15 @@ bundle_LayerDown(void *v, struct fsm *fp)
struct datalink *dl;
struct datalink *lost;
- bundle->ifp.Speed = 0;
+ bundle->ifSpeed = 0;
lost = NULL;
for (dl = bundle->links; dl; dl = dl->next)
if (fp == &dl->physical->link.lcp.fsm)
lost = dl;
else if (dl->state == DATALINK_OPEN)
- bundle->ifp.Speed += modem_Speed(dl->physical);
+ bundle->ifSpeed += modem_Speed(dl->physical);
- if (bundle->ifp.Speed)
+ if (bundle->ifSpeed)
/* Don't configure down to a speed of 0 */
tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru);
@@ -769,10 +727,11 @@ struct bundle *
bundle_Create(const char *prefix, int type, const char **argv)
{
int s, enoentcount, err;
+ const char *ifname;
struct ifreq ifrq;
static struct bundle bundle; /* there can be only one */
- if (bundle.ifp.Name != NULL) { /* Already allocated ! */
+ if (bundle.iface != NULL) { /* Already allocated ! */
log_Printf(LogALERT, "bundle_Create: There's only one BUNDLE !\n");
return NULL;
}
@@ -811,24 +770,32 @@ bundle_Create(const char *prefix, int type, const char **argv)
return NULL;
}
- bundle.ifp.Name = strrchr(bundle.dev.Name, '/');
- if (bundle.ifp.Name == NULL)
- bundle.ifp.Name = bundle.dev.Name;
+ ifname = strrchr(bundle.dev.Name, '/');
+ if (ifname == NULL)
+ ifname = bundle.dev.Name;
else
- bundle.ifp.Name++;
+ ifname++;
+
+ bundle.iface = iface_Create(ifname);
+ if (bundle.iface == NULL) {
+ close(s);
+ close(bundle.dev.fd);
+ return NULL;
+ }
/*
* Now, bring up the interface.
*/
memset(&ifrq, '\0', sizeof ifrq);
- strncpy(ifrq.ifr_name, bundle.ifp.Name, sizeof ifrq.ifr_name - 1);
+ strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1);
ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
log_Printf(LogERROR, "bundle_Create: ioctl(SIOCGIFFLAGS): %s\n",
strerror(errno));
close(s);
+ iface_Destroy(bundle.iface);
+ bundle.iface = NULL;
close(bundle.dev.fd);
- bundle.ifp.Name = NULL;
return NULL;
}
ifrq.ifr_flags |= IFF_UP;
@@ -836,22 +803,17 @@ bundle_Create(const char *prefix, int type, const char **argv)
log_Printf(LogERROR, "bundle_Create: ioctl(SIOCSIFFLAGS): %s\n",
strerror(errno));
close(s);
+ iface_Destroy(bundle.iface);
+ bundle.iface = NULL;
close(bundle.dev.fd);
- bundle.ifp.Name = NULL;
return NULL;
}
close(s);
- if ((bundle.ifp.Index = GetIfIndex(bundle.ifp.Name)) < 0) {
- log_Printf(LogERROR, "Can't find interface index.\n");
- close(bundle.dev.fd);
- bundle.ifp.Name = NULL;
- return NULL;
- }
- log_Printf(LogPHASE, "Using interface: %s\n", bundle.ifp.Name);
+ log_Printf(LogPHASE, "Using interface: %s\n", ifname);
- bundle.ifp.Speed = 0;
+ bundle.ifSpeed = 0;
bundle.routing_seq = 0;
bundle.phase = PHASE_DEAD;
@@ -882,8 +844,9 @@ bundle_Create(const char *prefix, int type, const char **argv)
bundle.links = datalink_Create("deflink", &bundle, type);
if (bundle.links == NULL) {
log_Printf(LogALERT, "Cannot create data link: %s\n", strerror(errno));
+ iface_Destroy(bundle.iface);
+ bundle.iface = NULL;
close(bundle.dev.fd);
- bundle.ifp.Name = NULL;
return NULL;
}
@@ -917,7 +880,7 @@ bundle_Create(const char *prefix, int type, const char **argv)
memset(&bundle.choked.timer, '\0', sizeof bundle.choked.timer);
/* Clean out any leftover crud */
- bundle_CleanInterface(&bundle);
+ iface_Clear(bundle.iface, IFACE_CLEAR_ALL);
bundle_LockTun(&bundle);
@@ -939,7 +902,7 @@ bundle_DownInterface(struct bundle *bundle)
}
memset(&ifrq, '\0', sizeof ifrq);
- strncpy(ifrq.ifr_name, bundle->ifp.Name, sizeof ifrq.ifr_name - 1);
+ strncpy(ifrq.ifr_name, bundle->iface->name, sizeof ifrq.ifr_name - 1);
ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
log_Printf(LogERROR, "bundle_DownInterface: ioctl(SIOCGIFFLAGS): %s\n",
@@ -985,7 +948,8 @@ bundle_Destroy(struct bundle *bundle)
/* In case we never made PHASE_NETWORK */
bundle_Notify(bundle, EX_ERRDEAD);
- bundle->ifp.Name = NULL;
+ iface_Destroy(bundle->iface);
+ bundle->iface = NULL;
}
struct rtmsg {
@@ -1032,24 +996,10 @@ bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst,
cp += rtdata.sin_len;
if (cmd == RTM_ADD) {
if (gateway.s_addr == INADDR_ANY) {
- /* Add a route through the interface */
- struct sockaddr_dl dl;
- const char *iname;
- int ilen;
-
- iname = Index2Nam(bundle->ifp.Index);
- ilen = strlen(iname);
- dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen;
- dl.sdl_family = AF_LINK;
- dl.sdl_index = bundle->ifp.Index;
- dl.sdl_type = 0;
- dl.sdl_nlen = ilen;
- dl.sdl_alen = 0;
- dl.sdl_slen = 0;
- strncpy(dl.sdl_data, iname, sizeof dl.sdl_data);
- memcpy(cp, &dl, dl.sdl_len);
- cp += dl.sdl_len;
- rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
+ log_Printf(LogERROR, "bundle_SetRoute: Cannot add a route with"
+ " destination 0.0.0.0\n");
+ close(s);
+ return result;
} else {
rtdata.sin_addr = gateway;
memcpy(cp, &rtdata, rtdata.sin_len);
@@ -1241,7 +1191,7 @@ bundle_ShowStatus(struct cmdargs const *arg)
prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle));
prompt_Printf(arg->prompt, " Device: %s\n", arg->bundle->dev.Name);
prompt_Printf(arg->prompt, " Interface: %s @ %lubps\n",
- arg->bundle->ifp.Name, arg->bundle->ifp.Speed);
+ arg->bundle->iface->name, arg->bundle->ifSpeed);
prompt_Printf(arg->prompt, "\nDefaults:\n");
prompt_Printf(arg->prompt, " Label: %s\n", arg->bundle->cfg.label);
@@ -1294,6 +1244,8 @@ bundle_ShowStatus(struct cmdargs const *arg)
optval(arg->bundle, OPT_THROUGHPUT));
prompt_Printf(arg->prompt, " Utmp Logging: %s\n",
optval(arg->bundle, OPT_UTMP));
+ prompt_Printf(arg->prompt, " Iface-Alias: %s\n",
+ optval(arg->bundle, OPT_IFACEALIAS));
return 0;
}
@@ -1636,11 +1588,6 @@ bundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode)
/* Regenerate phys_type and adjust autoload & idle timers */
bundle_LinksRemoved(bundle);
- if (omode == PHYS_AUTO && !(bundle->phys_type.all & PHYS_AUTO) &&
- bundle->phase != PHASE_NETWORK)
- /* No auto links left */
- ipcp_CleanInterface(&bundle->ncp.ipcp);
-
return 1;
}
diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h
index aee0cc2..2f24b18 100644
--- a/usr.sbin/ppp/bundle.h
+++ b/usr.sbin/ppp/bundle.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: bundle.h,v 1.12 1998/08/07 18:42:47 brian Exp $
+ * $Id: bundle.h,v 1.13 1998/08/25 17:48:42 brian Exp $
*/
#define PHASE_DEAD 0 /* Link is dead */
@@ -40,6 +40,7 @@
#define OPT_SROUTES 0x10
#define OPT_THROUGHPUT 0x20
#define OPT_UTMP 0x40
+#define OPT_IFACEALIAS 0x80
#define MAX_ENDDISC_CLASS 5
@@ -51,6 +52,7 @@ struct physical;
struct link;
struct server;
struct prompt;
+struct iface;
struct bundle {
struct descriptor desc; /* really all our datalinks */
@@ -62,11 +64,15 @@ struct bundle {
int fd; /* The /dev/XXXX descriptor */
} dev;
+#if 0
struct {
- u_long Speed; /* struct tuninfo speed */
int Index; /* The interface index */
char *Name; /* The interface name */
} ifp;
+#endif
+
+ u_long ifSpeed; /* struct tuninfo speed */
+ struct iface *iface; /* Interface information */
int routing_seq; /* The current routing sequence number */
u_int phase; /* Curent phase */
diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c
index 071df09..ced6a8a 100644
--- a/usr.sbin/ppp/command.c
+++ b/usr.sbin/ppp/command.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: command.c,v 1.166 1998/09/17 00:45:26 brian Exp $
+ * $Id: command.c,v 1.167 1998/10/17 12:28:05 brian Exp $
*
*/
#include <sys/types.h>
@@ -83,6 +83,7 @@
#include "chap.h"
#include "cbcp.h"
#include "datalink.h"
+#include "iface.h"
/* ``set'' values */
#define VAR_AUTHKEY 0
@@ -131,7 +132,7 @@
#define NEG_DNS 50
const char Version[] = "2.0";
-const char VersionDate[] = "$Date: 1998/09/17 00:45:26 $";
+const char VersionDate[] = "$Date: 1998/10/17 12:28:05 $";
static int ShowCommand(struct cmdargs const *);
static int TerminalCommand(struct cmdargs const *);
@@ -139,15 +140,17 @@ static int QuitCommand(struct cmdargs const *);
static int OpenCommand(struct cmdargs const *);
static int CloseCommand(struct cmdargs const *);
static int DownCommand(struct cmdargs const *);
-static int AllowCommand(struct cmdargs const *);
static int SetCommand(struct cmdargs const *);
static int LinkCommand(struct cmdargs const *);
static int AddCommand(struct cmdargs const *);
static int DeleteCommand(struct cmdargs const *);
static int NegotiateCommand(struct cmdargs const *);
static int ClearCommand(struct cmdargs const *);
+static int RunListCommand(struct cmdargs const *);
+static int IfaceAddCommand(struct cmdargs const *);
+static int IfaceDeleteCommand(struct cmdargs const *);
+static int IfaceClearCommand(struct cmdargs const *);
#ifndef NOALIAS
-static int AliasCommand(struct cmdargs const *);
static int AliasEnable(struct cmdargs const *);
static int AliasOption(struct cmdargs const *);
#endif
@@ -386,7 +389,7 @@ expand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle)
nargv[arg] = subst(nargv[arg], "HISADDR",
inet_ntoa(bundle->ncp.ipcp.peer_ip));
nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name);
- nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->ifp.Name);
+ nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name);
nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip));
nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname);
nargv[arg] = subst(nargv[arg], "PEER_ENDDISC",
@@ -513,6 +516,69 @@ FgShellCommand(struct cmdargs const *arg)
return ShellCommand(arg, 0);
}
+#ifndef NOALIAS
+static struct cmdtab const AliasCommands[] =
+{
+ {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH,
+ "static address translation", "alias addr [addr_local addr_alias]"},
+ {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
+ "stop incoming connections", "alias deny_incoming [yes|no]",
+ (const void *) PKT_ALIAS_DENY_INCOMING},
+ {"enable", NULL, AliasEnable, LOCAL_AUTH,
+ "enable IP aliasing", "alias enable [yes|no]"},
+ {"log", NULL, AliasOption, LOCAL_AUTH,
+ "log aliasing link creation", "alias log [yes|no]",
+ (const void *) PKT_ALIAS_LOG},
+ {"port", NULL, alias_RedirectPort, LOCAL_AUTH,
+ "port redirection", "alias port [proto addr_local:port_local port_alias]"},
+ {"same_ports", NULL, AliasOption, LOCAL_AUTH,
+ "try to leave port numbers unchanged", "alias same_ports [yes|no]",
+ (const void *) PKT_ALIAS_SAME_PORTS},
+ {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
+ "alias unregistered (private) IP address space only",
+ "alias unregistered_only [yes|no]",
+ (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
+ {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
+ "allocate host sockets", "alias use_sockets [yes|no]",
+ (const void *) PKT_ALIAS_USE_SOCKETS},
+ {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
+ "Display this message", "alias help|? [command]", AliasCommands},
+ {NULL, NULL, NULL},
+};
+#endif
+
+static struct cmdtab const AllowCommands[] = {
+ {"modes", "mode", AllowModes, LOCAL_AUTH,
+ "Only allow certain ppp modes", "allow modes mode..."},
+ {"users", "user", AllowUsers, LOCAL_AUTH,
+ "Only allow ppp access to certain users", "allow users logname..."},
+ {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
+ "Display this message", "allow help|? [command]", AllowCommands},
+ {NULL, NULL, NULL},
+};
+
+static struct cmdtab const IfaceCommands[] =
+{
+ {"add", NULL, IfaceAddCommand, LOCAL_AUTH,
+ "Add iface address", "iface add addr[/bits| mask] peer", NULL},
+ {NULL, "add!", IfaceAddCommand, LOCAL_AUTH,
+ "Add or change an iface address", "iface add! addr[/bits| mask] peer",
+ (void *)1},
+ {"clear", NULL, IfaceClearCommand, LOCAL_AUTH,
+ "Clear iface address(es)", "iface clear"},
+ {"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH,
+ "Delete iface address", "iface delete addr", NULL},
+ {NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH,
+ "Delete iface address", "iface delete addr", (void *)1},
+ {NULL, "delete!", IfaceDeleteCommand, LOCAL_AUTH,
+ "Delete iface address", "iface delete addr", (void *)1},
+ {"show", NULL, iface_Show, LOCAL_AUTH,
+ "Show iface address(es)", "iface show"},
+ {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
+ "Display this message", "alias help|? [command]", IfaceCommands},
+ {NULL, NULL, NULL},
+};
+
static struct cmdtab const Commands[] = {
{"accept", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"accept option request", "accept option .."},
@@ -521,11 +587,11 @@ static struct cmdtab const Commands[] = {
{NULL, "add!", AddCommand, LOCAL_AUTH,
"add or change route", "add! dest mask gateway", (void *)1},
#ifndef NOALIAS
- {"alias", NULL, AliasCommand, LOCAL_AUTH,
- "alias control", "alias option [yes|no]"},
+ {"alias", NULL, RunListCommand, LOCAL_AUTH,
+ "alias control", "alias option [yes|no]", AliasCommands},
#endif
- {"allow", "auth", AllowCommand, LOCAL_AUTH,
- "Allow ppp access", "allow users|modes ...."},
+ {"allow", "auth", RunListCommand, LOCAL_AUTH,
+ "Allow ppp access", "allow users|modes ....", AllowCommands},
{"bg", "!bg", BgShellCommand, LOCAL_AUTH,
"Run a background command", "[!]bg command"},
{"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT,
@@ -548,6 +614,8 @@ static struct cmdtab const Commands[] = {
"Generate a down event", "down"},
{"enable", NULL, NegotiateCommand, LOCAL_AUTH | LOCAL_CX_OPT,
"Enable option", "enable option .."},
+ {"iface", "interface", RunListCommand, LOCAL_AUTH,
+ "interface control", "iface option ...", IfaceCommands},
{"link", "datalink", LinkCommand, LOCAL_AUTH,
"Link specific commands", "link name command ..."},
{"load", NULL, LoadCommand, LOCAL_AUTH | LOCAL_CX_OPT,
@@ -655,6 +723,8 @@ static struct cmdtab const ShowCommands[] = {
"packet filters", "show filter [in|out|dial|alive]"},
{"hdlc", NULL, hdlc_ReportStatus, LOCAL_AUTH | LOCAL_CX,
"HDLC errors", "show hdlc"},
+ {"iface", "interface", iface_Show, LOCAL_AUTH,
+ "Interface status", "show iface"},
{"ipcp", NULL, ipcp_Show, LOCAL_AUTH,
"IPCP status", "show ipcp"},
{"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX,
@@ -1200,13 +1270,12 @@ SetInterfaceAddr(struct cmdargs const *arg)
struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
const char *hisaddr;
- hisaddr = NULL;
- ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
- ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
-
if (arg->argc > arg->argn + 4)
return -1;
+ hisaddr = NULL;
+ ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
+ ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
ipcp->cfg.HaveTriggerAddress = 0;
ipcp->cfg.netmask.s_addr = INADDR_ANY;
iplist_reset(&ipcp->cfg.peer_list);
@@ -1228,20 +1297,13 @@ SetInterfaceAddr(struct cmdargs const *arg)
}
}
- /*
- * For backwards compatibility, 0.0.0.0 means any address.
- */
+ /* 0.0.0.0 means any address (0 bits) */
if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) {
ipcp->cfg.my_range.mask.s_addr = INADDR_ANY;
ipcp->cfg.my_range.width = 0;
}
ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr;
- if (ipcp->cfg.peer_range.ipaddr.s_addr == INADDR_ANY) {
- ipcp->cfg.peer_range.mask.s_addr = INADDR_ANY;
- ipcp->cfg.peer_range.width = 0;
- }
-
if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr,
arg->bundle->phys_type.all & PHYS_AUTO))
return 4;
@@ -1717,7 +1779,6 @@ SetCommand(struct cmdargs const *arg)
return 0;
}
-
static int
AddCommand(struct cmdargs const *arg)
{
@@ -1759,9 +1820,7 @@ AddCommand(struct cmdargs const *arg)
if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) {
gateway = arg->bundle->ncp.ipcp.peer_ip;
addrs |= ROUTE_GWHISADDR;
- } else if (strcasecmp(arg->argv[arg->argn+gw], "INTERFACE") == 0)
- gateway.s_addr = INADDR_ANY;
- else
+ } else
gateway = GetIpAddr(arg->argv[arg->argn+gw]);
if (bundle_SetRoute(arg->bundle, RTM_ADD, dest, gateway, netmask,
@@ -1808,51 +1867,6 @@ DeleteCommand(struct cmdargs const *arg)
}
#ifndef NOALIAS
-static struct cmdtab const AliasCommands[] =
-{
- {"addr", NULL, alias_RedirectAddr, LOCAL_AUTH,
- "static address translation", "alias addr [addr_local addr_alias]"},
- {"deny_incoming", NULL, AliasOption, LOCAL_AUTH,
- "stop incoming connections", "alias deny_incoming [yes|no]",
- (const void *) PKT_ALIAS_DENY_INCOMING},
- {"enable", NULL, AliasEnable, LOCAL_AUTH,
- "enable IP aliasing", "alias enable [yes|no]"},
- {"log", NULL, AliasOption, LOCAL_AUTH,
- "log aliasing link creation", "alias log [yes|no]",
- (const void *) PKT_ALIAS_LOG},
- {"port", NULL, alias_RedirectPort, LOCAL_AUTH,
- "port redirection", "alias port [proto addr_local:port_local port_alias]"},
- {"same_ports", NULL, AliasOption, LOCAL_AUTH,
- "try to leave port numbers unchanged", "alias same_ports [yes|no]",
- (const void *) PKT_ALIAS_SAME_PORTS},
- {"unregistered_only", NULL, AliasOption, LOCAL_AUTH,
- "alias unregistered (private) IP address space only",
- "alias unregistered_only [yes|no]",
- (const void *) PKT_ALIAS_UNREGISTERED_ONLY},
- {"use_sockets", NULL, AliasOption, LOCAL_AUTH,
- "allocate host sockets", "alias use_sockets [yes|no]",
- (const void *) PKT_ALIAS_USE_SOCKETS},
- {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
- "Display this message", "alias help|? [command]", AliasCommands},
- {NULL, NULL, NULL},
-};
-
-
-static int
-AliasCommand(struct cmdargs const *arg)
-{
- if (arg->argc > arg->argn)
- FindExec(arg->bundle, AliasCommands, arg->argc, arg->argn, arg->argv,
- arg->prompt, arg->cx);
- else if (arg->prompt)
- prompt_Printf(arg->prompt, "Use `alias help' to get a list or `alias help"
- " <option>' for syntax help.\n");
- else
- log_Printf(LogWARN, "alias command must have arguments\n");
-
- return 0;
-}
-
static int
AliasEnable(struct cmdargs const *arg)
{
@@ -1862,6 +1876,8 @@ AliasEnable(struct cmdargs const *arg)
return 0;
} else if (strcasecmp(arg->argv[arg->argn], "no") == 0) {
arg->bundle->AliasEnabled = 0;
+ arg->bundle->cfg.opt &= ~OPT_IFACEALIAS;
+ /* Don't iface_Clear() - there may be manually configured addresses */
return 0;
}
}
@@ -1894,32 +1910,6 @@ AliasOption(struct cmdargs const *arg)
}
#endif /* #ifndef NOALIAS */
-static struct cmdtab const AllowCommands[] = {
- {"modes", "mode", AllowModes, LOCAL_AUTH,
- "Only allow certain ppp modes", "allow modes mode..."},
- {"users", "user", AllowUsers, LOCAL_AUTH,
- "Allow users access to ppp", "allow users logname..."},
- {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH,
- "Display this message", "allow help|? [command]", AllowCommands},
- {NULL, NULL, NULL},
-};
-
-static int
-AllowCommand(struct cmdargs const *arg)
-{
- /* arg->bundle may be NULL (see system_IsValid()) ! */
- if (arg->argc > arg->argn)
- FindExec(arg->bundle, AllowCommands, arg->argc, arg->argn, arg->argv,
- arg->prompt, arg->cx);
- else if (arg->prompt)
- prompt_Printf(arg->prompt, "Use `allow ?' to get a list or `allow ? <cmd>'"
- " for syntax help.\n");
- else
- log_Printf(LogWARN, "allow command must have arguments\n");
-
- return 0;
-}
-
static int
LinkCommand(struct cmdargs const *arg)
{
@@ -2047,6 +2037,22 @@ OptSet(struct cmdargs const *arg)
}
static int
+IfaceAliasOptSet(struct cmdargs const *arg)
+{
+ unsigned save = arg->bundle->cfg.opt;
+ int result = OptSet(arg);
+
+ if (result == 0)
+ if (Enabled(arg->bundle, OPT_IFACEALIAS) && !arg->bundle->AliasEnabled) {
+ arg->bundle->cfg.opt = save;
+ log_Printf(LogWARN, "Cannot enable iface-alias without IP aliasing\n");
+ result = 2;
+ }
+
+ return result;
+}
+
+static int
NegotiateSet(struct cmdargs const *arg)
{
long param = (long)arg->cmd->args;
@@ -2138,8 +2144,11 @@ static struct cmdtab const NegotiateCommands[] = {
"disable|enable", (const void *)OPT_THROUGHPUT},
{"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp",
"disable|enable", (const void *)OPT_UTMP},
+ {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH,
+ "maintain interface addresses", "disable|enable",
+ (const void *)OPT_IFACEALIAS},
-#define OPT_MAX 7 /* accept/deny allowed below and not above */
+#define OPT_MAX 8 /* accept/deny allowed below and not above */
{"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
"Address & Control field compression", "accept|deny|disable|enable",
@@ -2258,3 +2267,96 @@ ClearCommand(struct cmdargs const *arg)
throughput_clear(t, clear_type, arg->prompt);
return 0;
}
+
+static int
+RunListCommand(struct cmdargs const *arg)
+{
+ const char *cmd = arg->argc ? arg->argv[arg->argc - 1] : "???";
+
+ if (arg->argc > arg->argn)
+ FindExec(arg->bundle, arg->cmd->args, arg->argc, arg->argn, arg->argv,
+ arg->prompt, arg->cx);
+ else if (arg->prompt)
+ prompt_Printf(arg->prompt, "Use `%s help' to get a list or `%s help"
+ " <option>' for syntax help.\n", cmd, cmd);
+ else
+ log_Printf(LogWARN, "%s command must have arguments\n", cmd);
+
+ return 0;
+}
+
+static int
+IfaceAddCommand(struct cmdargs const *arg)
+{
+ int bits, n, how;
+ struct in_addr ifa, mask, brd;
+
+ if (arg->argc == arg->argn + 2) {
+ if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, &mask, &bits))
+ return -1;
+ n = 1;
+ } else if (arg->argc == arg->argn + 3) {
+ if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL))
+ return -1;
+ if (!ParseAddr(NULL, 1, arg->argv + arg->argn + 1, &mask, NULL, NULL))
+ return -1;
+ n = 2;
+ } else
+ return -1;
+
+ if (!ParseAddr(NULL, 1, arg->argv + arg->argn + n, &brd, NULL, NULL))
+ return -1;
+
+ how = IFACE_ADD_LAST;
+ if (arg->cmd->args)
+ how |= IFACE_FORCE_ADD;
+
+ return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how);
+}
+
+static int
+IfaceDeleteCommand(struct cmdargs const *arg)
+{
+ struct in_addr ifa;
+ int ok;
+
+ if (arg->argc != arg->argn + 1)
+ return -1;
+
+ if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL))
+ return -1;
+
+ if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED &&
+ arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) {
+ log_Printf(LogWARN, "%s: Cannot remove active interface address\n",
+ inet_ntoa(ifa));
+ return 1;
+ }
+
+ ok = iface_inDelete(arg->bundle->iface, ifa);
+ if (!ok) {
+ if (arg->cmd->args)
+ ok = 1;
+ else if (arg->prompt)
+ prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa));
+ else
+ log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa));
+ }
+
+ return !ok;
+}
+
+static int
+IfaceClearCommand(struct cmdargs const *arg)
+{
+ int how;
+
+ if (arg->argc != arg->argn)
+ return -1;
+
+ how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED ?
+ IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL;
+ iface_Clear(arg->bundle->iface, how);
+
+ return 0;
+}
diff --git a/usr.sbin/ppp/filter.c b/usr.sbin/ppp/filter.c
index 3437d11..cd5a644 100644
--- a/usr.sbin/ppp/filter.c
+++ b/usr.sbin/ppp/filter.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: filter.c,v 1.24 1998/06/15 19:06:07 brian Exp $
+ * $Id: filter.c,v 1.25 1998/06/27 12:03:48 brian Exp $
*
* TODO: Shoud send ICMP error message when we discard packets.
*/
@@ -90,9 +90,9 @@ ParseAddr(struct ipcp *ipcp, int argc, char const *const *argv,
cp = pmask || pwidth ? strchr(*argv, '/') : NULL;
len = cp ? cp - *argv : strlen(*argv);
- if (strncasecmp(*argv, "HISADDR", len) == 0)
+ if (ipcp && strncasecmp(*argv, "HISADDR", len) == 0)
*paddr = ipcp->peer_ip;
- else if (strncasecmp(*argv, "MYADDR", len) == 0)
+ else if (ipcp && strncasecmp(*argv, "MYADDR", len) == 0)
*paddr = ipcp->my_ip;
else if (len > 15)
log_Printf(LogWARN, "ParseAddr: %s: Bad address\n", *argv);
@@ -121,8 +121,12 @@ ParseAddr(struct ipcp *ipcp, int argc, char const *const *argv,
if (pwidth)
*pwidth = bits;
- if (pmask)
- pmask->s_addr = htonl(netmasks[bits]);
+ if (pmask) {
+ if (paddr->s_addr == INADDR_ANY)
+ pmask->s_addr = INADDR_ANY;
+ else
+ pmask->s_addr = htonl(netmasks[bits]);
+ }
return (1);
}
diff --git a/usr.sbin/ppp/iface.c b/usr.sbin/ppp/iface.c
new file mode 100644
index 0000000..c217690
--- /dev/null
+++ b/usr.sbin/ppp/iface.c
@@ -0,0 +1,431 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id:$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <sys/un.h>
+
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "defs.h"
+#include "command.h"
+#include "mbuf.h"
+#include "log.h"
+#include "id.h"
+#include "timer.h"
+#include "fsm.h"
+#include "iplist.h"
+#include "lqr.h"
+#include "hdlc.h"
+#include "throughput.h"
+#include "slcompress.h"
+#include "filter.h"
+#include "descriptor.h"
+#include "ipcp.h"
+#include "lcp.h"
+#include "ccp.h"
+#include "link.h"
+#include "mp.h"
+#include "bundle.h"
+#include "prompt.h"
+#include "iface.h"
+
+
+static int
+bitsinmask(struct in_addr mask)
+{
+ u_int32_t bitmask, maskaddr;
+ int bits;
+
+ bitmask = 0xffffffff;
+ maskaddr = ntohl(mask.s_addr);
+ for (bits = 32; bits >= 0; bits--) {
+ if (maskaddr == bitmask)
+ break;
+ bitmask &= ~(1 << (32 - bits));
+ }
+
+ return bits;
+}
+
+struct iface *
+iface_Create(const char *name)
+{
+ int mib[6], i, s;
+ size_t needed;
+ char *buf, *ptr, *end, *cp, *lim;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct sockaddr_dl *dl;
+ struct rt_addrinfo rti;
+ struct iface *iface;
+ struct iface_addr *addr;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ fprintf(stderr, "iface_Create: socket(): %s\n", strerror(errno));
+ return NULL;
+ }
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0;
+
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
+ fprintf(stderr, "clean: sysctl: estimate: %s\n",
+ strerror(errno));
+ close(s);
+ return NULL;
+ }
+
+ if ((buf = (char *)malloc(needed)) == NULL) {
+ close(s);
+ return NULL;
+ }
+
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ free(buf);
+ close(s);
+ return NULL;
+ }
+
+ ptr = buf;
+ end = buf + needed;
+ iface = NULL;
+
+ while (ptr < end && iface == NULL) {
+ ifm = (struct if_msghdr *)ptr; /* On if_msghdr */
+ if (ifm->ifm_type != RTM_IFINFO)
+ break;
+ dl = (struct sockaddr_dl *)(ifm + 1); /* Single _dl at end */
+ if (!strncmp(name, dl->sdl_data, dl->sdl_nlen)) {
+ iface = (struct iface *)malloc(sizeof *iface);
+ if (iface == NULL) {
+ fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
+ return NULL;
+ }
+ iface->name = strdup(name);
+ iface->flags = ifm->ifm_flags;
+ iface->index = ifm->ifm_index;
+ iface->in_addrs = 0;
+ iface->in_addr = NULL;
+ }
+ ptr += ifm->ifm_msglen; /* First ifa_msghdr */
+ for (; ptr < end; ptr += ifam->ifam_msglen) {
+ ifam = (struct ifa_msghdr *)ptr; /* Next if address */
+
+ if (ifam->ifam_type != RTM_NEWADDR) /* finished this if */
+ break;
+
+ if (iface == NULL) /* Keep wading */
+ continue;
+
+ /* Found an address ! */
+
+ if (ifam->ifam_addrs & (1 << RTAX_IFA)) {
+ /* *And* it's configured ! */
+ rti.rti_addrs = ifam->ifam_addrs;
+ lim = (char *)ifam + ifam->ifam_msglen;
+ cp = (char *)(ifam + 1);
+ memset(rti.rti_info, '\0', sizeof(rti.rti_info));
+ for (i = 0; i < RTAX_MAX && cp < lim; i++) {
+ if ((rti.rti_addrs & (1 << i)) == 0)
+ continue;
+ rti.rti_info[i] = (struct sockaddr *)cp;
+#define ROUNDUP(x) \
+ ((x) > 0 ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
+ cp += ROUNDUP(rti.rti_info[i]->sa_len);
+ }
+
+ if (rti.rti_info[RTAX_IFA] &&
+ rti.rti_info[RTAX_IFA]->sa_family == AF_INET) {
+ /* Record the iface address rti */
+
+ addr = (struct iface_addr *)realloc
+ (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
+ if (addr == NULL)
+ break;
+ iface->in_addr = addr;
+
+ addr += iface->in_addrs;
+ iface->in_addrs++;
+
+ addr->ifa.s_addr = ((struct sockaddr_in *)rti.rti_info[RTAX_IFA])->
+ sin_addr.s_addr;
+ addr->brd.s_addr = rti.rti_info[RTAX_BRD] ?
+ ((struct sockaddr_in *)rti.rti_info[RTAX_BRD])->sin_addr.s_addr :
+ INADDR_ANY;
+ addr->mask.s_addr = rti.rti_info[RTAX_NETMASK] ?
+ ((struct sockaddr_in *)rti.rti_info[RTAX_NETMASK])->sin_addr.s_addr:
+ INADDR_ANY;
+
+ addr->bits = bitsinmask(addr->mask);
+ }
+ }
+ }
+ }
+
+ free(buf);
+ close(s);
+
+ return iface;
+}
+
+static void
+iface_addr_Zap(const char *name, struct iface_addr *addr)
+{
+ struct ifaliasreq ifra;
+ struct sockaddr_in *me, *peer;
+ int s;
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ log_Printf(LogERROR, "iface_addr_Zap: socket(): %s\n", strerror(errno));
+ else {
+ memset(&ifra, '\0', sizeof ifra);
+ strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
+ me = (struct sockaddr_in *)&ifra.ifra_addr;
+ peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+ me->sin_family = peer->sin_family = AF_INET;
+ me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
+ me->sin_addr = addr->ifa;
+ peer->sin_addr = addr->brd;
+ if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
+ log_Printf(LogWARN, "iface_addr_Zap: ioctl(SIOCDIFADDR, %s): %s\n",
+ inet_ntoa(addr->ifa), strerror(errno));
+ close(s);
+ }
+}
+
+void
+iface_inClear(struct iface *iface, int how)
+{
+ int n, addrs;
+
+ addrs = n = how == IFACE_CLEAR_ALL ? 0 : 1;
+ for (; n < iface->in_addrs; n++)
+ iface_addr_Zap(iface->name, iface->in_addr + n);
+
+ iface->in_addrs = addrs;
+ /* Don't bother realloc()ing - we have little to gain */
+}
+
+int
+iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask,
+ struct in_addr brd, int how)
+{
+ int slot, s;
+ struct ifaliasreq ifra;
+ struct sockaddr_in *me, *peer, *msk;
+ struct iface_addr *addr;
+
+ for (slot = 0; slot < iface->in_addrs; slot++)
+ if (iface->in_addr[slot].ifa.s_addr == ifa.s_addr) {
+ if (how & IFACE_FORCE_ADD)
+ break;
+ else
+ /* errno = EEXIST; */
+ return 0;
+ }
+
+ addr = (struct iface_addr *)realloc
+ (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
+ if (addr == NULL) {
+ log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
+ return 0;
+ }
+ iface->in_addr = addr;
+
+ s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
+ return 0;
+ }
+
+ memset(&ifra, '\0', sizeof ifra);
+ strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
+
+ me = (struct sockaddr_in *)&ifra.ifra_addr;
+ msk = (struct sockaddr_in *)&ifra.ifra_mask;
+ peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+
+ me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
+ me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
+
+ me->sin_addr = ifa;
+ msk->sin_addr = mask;
+ peer->sin_addr = brd;
+
+ /*
+ * Note: EEXIST is sometimes returned, despite the route actually being
+ * added !
+ */
+ if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) {
+ log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s\n",
+ strerror(errno));
+ close(s);
+ return 0;
+ }
+ close(s);
+
+ if (slot == iface->in_addrs) {
+ /* We're adding a new interface address */
+
+ if (how & IFACE_ADD_FIRST) {
+ /* Stuff it at the start of our list */
+ slot = 0;
+ bcopy(iface->in_addr, iface->in_addr + 1,
+ iface->in_addrs * sizeof iface->in_addr[0]);
+ }
+
+ iface->in_addrs++;
+ } else if (how & IFACE_ADD_FIRST) {
+ /* Shift it up to the first slot */
+ bcopy(iface->in_addr, iface->in_addr + 1, slot * sizeof iface->in_addr[0]);
+ slot = 0;
+ }
+
+ iface->in_addr[slot].ifa = ifa;
+ iface->in_addr[slot].mask = mask;
+ iface->in_addr[slot].brd = brd;
+ iface->in_addr[slot].bits = bitsinmask(iface->in_addr[slot].mask);
+
+ return 1;
+}
+
+int
+iface_inDelete(struct iface *iface, struct in_addr ip)
+{
+ int n;
+
+ for (n = 0; n < iface->in_addrs; n++)
+ if (iface->in_addr[n].ifa.s_addr == ip.s_addr) {
+ iface_addr_Zap(iface->name, iface->in_addr + n);
+ bcopy(iface->in_addr + n + 1, iface->in_addr + n,
+ (iface->in_addrs - n - 1) * sizeof iface->in_addr[0]);
+ iface->in_addrs--;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+iface_Destroy(struct iface *iface)
+{
+ /*
+ * iface_Clear(iface, IFACE_CLEAR_ALL) must be called manually
+ * if that's what the user wants. It's better to leave the interface
+ * allocated so that existing connections can continue to work.
+ */
+
+ if (iface != NULL) {
+ free(iface->name);
+ free(iface->in_addr);
+ free(iface);
+ }
+}
+
+#define if_entry(x) { IFF_##x, #x }
+
+struct {
+ int flag;
+ const char *value;
+} if_flags[] = {
+ if_entry(UP),
+ if_entry(BROADCAST),
+ if_entry(DEBUG),
+ if_entry(LOOPBACK),
+ if_entry(POINTOPOINT),
+ if_entry(RUNNING),
+ if_entry(NOARP),
+ if_entry(PROMISC),
+ if_entry(ALLMULTI),
+ if_entry(OACTIVE),
+ if_entry(SIMPLEX),
+ if_entry(LINK0),
+ if_entry(LINK1),
+ if_entry(LINK2),
+ if_entry(MULTICAST),
+ { 0, "???" }
+};
+
+int
+iface_Show(struct cmdargs const *arg)
+{
+ struct iface *iface = arg->bundle->iface, *current;
+ int f, flags;
+
+ current = iface_Create(iface->name);
+ flags = iface->flags = current->flags;
+ iface_Destroy(current);
+
+ prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
+ for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
+ if ((if_flags[f].flag & flags) || (!if_flags[f].flag && flags)) {
+ prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
+ if_flags[f].value);
+ flags &= ~if_flags[f].flag;
+ }
+ prompt_Printf(arg->prompt, "> has %d address%s:\n", iface->in_addrs,
+ iface->in_addrs == 1 ? "" : "es");
+
+ for (f = 0; f < iface->in_addrs; f++) {
+ prompt_Printf(arg->prompt, " %s", inet_ntoa(iface->in_addr[f].ifa));
+ if (iface->in_addr[f].bits >= 0)
+ prompt_Printf(arg->prompt, "/%d", iface->in_addr[f].bits);
+ if (iface->flags & IFF_POINTOPOINT)
+ prompt_Printf(arg->prompt, " -> %s", inet_ntoa(iface->in_addr[f].brd));
+ else if (iface->flags & IFF_BROADCAST)
+ prompt_Printf(arg->prompt, " broadcast %s",
+ inet_ntoa(iface->in_addr[f].brd));
+ if (iface->in_addr[f].bits < 0)
+ prompt_Printf(arg->prompt, " (mask %s)",
+ inet_ntoa(iface->in_addr[f].mask));
+ prompt_Printf(arg->prompt, "\n");
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/ppp/iface.h b/usr.sbin/ppp/iface.h
new file mode 100644
index 0000000..f3b1dad
--- /dev/null
+++ b/usr.sbin/ppp/iface.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id:$
+ */
+
+struct iface_addr {
+ struct in_addr ifa; /* local address */
+ struct in_addr mask; /* netmask */
+ int bits; /* netmask bits - -1 if not contiguous */
+ struct in_addr brd; /* peer address */
+};
+
+struct iface {
+ char *name; /* Interface name (malloc'd) */
+ int index; /* Interface index */
+ int flags; /* Interface flags (IFF_*) */
+
+ int in_addrs; /* How many in_addr's */
+ struct iface_addr *in_addr; /* Array of addresses (malloc'd) */
+};
+
+#define IFACE_CLEAR_ALL 0 /* Nuke 'em all */
+#define IFACE_CLEAR_ALIASES 1 /* Leave the IPCP address */
+
+#define IFACE_ADD_LAST 0 /* Just another alias */
+#define IFACE_ADD_FIRST 1 /* The IPCP address */
+#define IFACE_FORCE_ADD 2 /* OR'd with IFACE_ADD_{FIRST,LAST} */
+
+#define iface_Clear iface_inClear /* Same for now */
+
+extern struct iface *iface_Create(const char *name);
+extern void iface_inClear(struct iface *, int);
+extern int iface_inAdd(struct iface *, struct in_addr, struct in_addr,
+ struct in_addr, int);
+extern int iface_inDelete(struct iface *, struct in_addr);
+extern int iface_Show(struct cmdargs const *);
+extern void iface_Destroy(struct iface *);
diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c
index 40e1dfa..3d1d3ee 100644
--- a/usr.sbin/ppp/ipcp.c
+++ b/usr.sbin/ppp/ipcp.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ipcp.c,v 1.65 1998/09/04 18:25:59 brian Exp $
+ * $Id: ipcp.c,v 1.66 1998/09/17 00:45:26 brian Exp $
*
* TODO:
* o More RFC1772 backward compatibility
@@ -77,6 +77,7 @@
#include "systems.h"
#include "prompt.h"
#include "route.h"
+#include "iface.h"
#undef REJECTED
#define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
@@ -354,11 +355,8 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
if (gethostname(name, sizeof name) == 0) {
hp = gethostbyname(name);
- if (hp && hp->h_addrtype == AF_INET) {
+ if (hp && hp->h_addrtype == AF_INET)
memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
- ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
- ipcp->cfg.peer_range.width = 32;
- }
}
ipcp->cfg.netmask.s_addr = INADDR_ANY;
memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
@@ -376,9 +374,6 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
memset(&ipcp->vj, '\0', sizeof ipcp->vj);
- ipcp->my_ifip.s_addr = INADDR_ANY;
- ipcp->peer_ifip.s_addr = INADDR_ANY;
-
throughput_init(&ipcp->throughput);
memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
ipcp_Setup(ipcp);
@@ -393,17 +388,26 @@ ipcp_SetLink(struct ipcp *ipcp, struct link *l)
void
ipcp_Setup(struct ipcp *ipcp)
{
- int pos;
+ struct iface *iface = ipcp->fsm.bundle->iface;
+ int pos, n;
ipcp->fsm.open_mode = 0;
ipcp->fsm.maxconfig = 10;
if (iplist_isvalid(&ipcp->cfg.peer_list)) {
- if (ipcp->my_ifip.s_addr != INADDR_ANY &&
- (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1)
- ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos);
- else
+ /* Try to give the peer a previously configured IP address */
+ for (n = 0; n < iface->in_addrs; n++) {
+ pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
+ if (pos != -1) {
+ ipcp->cfg.peer_range.ipaddr =
+ iplist_setcurpos(&ipcp->cfg.peer_list, pos);
+ break;
+ }
+ }
+ if (n == iface->in_addrs)
+ /* Ok, so none of 'em fit.... pick a random one */
ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
+
ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
ipcp->cfg.peer_range.width = 32;
}
@@ -422,17 +426,23 @@ ipcp_Setup(struct ipcp *ipcp)
ipcp->my_ip = ipcp->cfg.TriggerAddress;
log_Printf(LogIPCP, "Using trigger address %s\n",
inet_ntoa(ipcp->cfg.TriggerAddress));
- } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
- (ipcp->cfg.my_range.ipaddr.s_addr &
- ipcp->cfg.my_range.mask.s_addr))
+ } else {
/*
- * Otherwise, if we've been assigned an IP number before, we really
- * want to keep the same IP number so that we can keep any existing
- * connections that are bound to that IP.
+ * Otherwise, if we've used an IP number before and it's still within
+ * the network specified on the ``set ifaddr'' line, we really
+ * want to keep that IP number so that we can keep any existing
+ * connections that are bound to that IP (assuming we're not
+ * ``iface-alias''ing).
*/
- ipcp->my_ip = ipcp->my_ifip;
- else
- ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
+ for (n = 0; n < iface->in_addrs; n++)
+ if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
+ (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
+ ipcp->my_ip = iface->in_addr[n].ifa;
+ break;
+ }
+ if (n == iface->in_addrs)
+ ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
+ }
if (IsEnabled(ipcp->cfg.vj.neg))
ipcp->my_compproto = (PROTO_VJCOMP << 16) +
@@ -450,81 +460,51 @@ static int
ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
struct in_addr hisaddr, int silent)
{
- struct sockaddr_in *sock_in;
- int s;
- u_int32_t mask, addr;
- struct ifaliasreq ifra;
-
- /* If given addresses are alreay set, then ignore this request */
- if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr &&
- bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr)
- return 0;
+ struct in_addr mask, oaddr;
+ u_int32_t addr;
- ipcp_CleanInterface(&bundle->ncp.ipcp);
-
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- log_Printf(LogERROR, "SetIPaddress: socket(): %s\n", strerror(errno));
- return (-1);
- }
-
- memset(&ifra, '\0', sizeof ifra);
- strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1);
- ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
-
- /* Set interface address */
- sock_in = (struct sockaddr_in *)&ifra.ifra_addr;
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr = myaddr;
- sock_in->sin_len = sizeof *sock_in;
-
- /* Set destination address */
- sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr;
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr = hisaddr;
- sock_in->sin_len = sizeof *sock_in;
-
- addr = ntohl(myaddr.s_addr);
+ addr = htonl(myaddr.s_addr);
if (IN_CLASSA(addr))
- mask = IN_CLASSA_NET;
+ mask.s_addr = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(addr))
- mask = IN_CLASSB_NET;
+ mask.s_addr = htonl(IN_CLASSB_NET);
else
- mask = IN_CLASSC_NET;
+ mask.s_addr = htonl(IN_CLASSC_NET);
- /* if subnet mask is given, use it instead of class mask */
if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
- (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask)
- mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr);
-
- sock_in = (struct sockaddr_in *)&ifra.ifra_mask;
- sock_in->sin_family = AF_INET;
- sock_in->sin_addr.s_addr = htonl(mask);
- sock_in->sin_len = sizeof *sock_in;
-
- if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
- if (!silent)
- log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n",
- strerror(errno));
- close(s);
- return (-1);
- }
+ (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask.s_addr) == mask.s_addr)
+ mask.s_addr = htonl(bundle->ncp.ipcp.cfg.netmask.s_addr);
+
+ oaddr.s_addr = bundle->iface->in_addrs ?
+ bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
+ if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
+ IFACE_ADD_FIRST|IFACE_FORCE_ADD))
+ return -1;
+
+ if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
+ && myaddr.s_addr != oaddr.s_addr)
+ /* Nuke the old one */
+ iface_inDelete(bundle->iface, oaddr);
if (Enabled(bundle, OPT_SROUTES))
route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
- bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr;
- bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr;
-
- if (Enabled(bundle, OPT_PROXY))
- arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s);
+ if (Enabled(bundle, OPT_PROXY)) {
+ int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
+ strerror(errno));
+ else {
+ arp_SetProxy(bundle, hisaddr, s);
+ close(s);
+ }
+ }
- close(s);
- return (0);
+ return 0;
}
static struct in_addr
-ChooseHisAddr(struct bundle *bundle, const struct in_addr gw)
+ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
{
struct in_addr try;
u_long f;
@@ -639,40 +619,22 @@ IpcpLayerFinish(struct fsm *fp)
void
ipcp_CleanInterface(struct ipcp *ipcp)
{
- struct ifaliasreq ifra;
- struct sockaddr_in *me, *peer;
- int s;
-
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno));
- return;
- }
+ struct iface *iface = ipcp->fsm.bundle->iface;
route_Clean(ipcp->fsm.bundle, ipcp->route);
- if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
- arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s);
-
- if (ipcp->my_ifip.s_addr != INADDR_ANY ||
- ipcp->peer_ifip.s_addr != INADDR_ANY) {
- memset(&ifra, '\0', sizeof ifra);
- strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name,
- sizeof ifra.ifra_name - 1);
- ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
- me = (struct sockaddr_in *)&ifra.ifra_addr;
- peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
- me->sin_family = peer->sin_family = AF_INET;
- me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
- me->sin_addr = ipcp->my_ifip;
- peer->sin_addr = ipcp->peer_ifip;
- if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
- log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n",
- strerror(errno));
- ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY;
+ if (iface->in_addrs && Enabled(ipcp->fsm.bundle, OPT_PROXY)) {
+ int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
+ strerror(errno));
+ else {
+ arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
+ close(s);
+ }
}
- close(s);
+ iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
}
static void
@@ -682,7 +644,10 @@ IpcpLayerDown(struct fsm *fp)
struct ipcp *ipcp = fsm2ipcp(fp);
const char *s;
- s = inet_ntoa(ipcp->peer_ifip);
+ if (ipcp->fsm.bundle->iface->in_addrs)
+ s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
+ else
+ s = "Interface configuration error !";
log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
/*
@@ -698,9 +663,6 @@ IpcpLayerDown(struct fsm *fp)
system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
}
- if (!(ipcp->fsm.bundle->phys_type.all & PHYS_AUTO))
- ipcp_CleanInterface(ipcp);
-
ipcp_Setup(ipcp);
}
@@ -725,11 +687,12 @@ IpcpLayerUp(struct fsm *fp)
{
/* We're now up */
struct ipcp *ipcp = fsm2ipcp(fp);
- char tbuff[100];
+ char tbuff[16];
log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
- snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip));
- log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip));
+ snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
+ log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
+ tbuff, inet_ntoa(ipcp->peer_ip));
if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
@@ -741,8 +704,7 @@ IpcpLayerUp(struct fsm *fp)
* XXX this stuff should really live in the FSM. Our config should
* associate executable sections in files with events.
*/
- if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE,
- NULL, NULL) < 0) {
+ if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
if (bundle_GetLabel(fp->bundle)) {
if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
LINKUPFILE, NULL, NULL) < 0)
@@ -756,7 +718,7 @@ IpcpLayerUp(struct fsm *fp)
}
static int
-AcceptableAddr(struct in_range *prange, struct in_addr ipaddr)
+AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
{
/* Is the given IP in the given range ? */
return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
@@ -768,13 +730,13 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
struct fsm_decode *dec)
{
/* Deal with incoming PROTO_IPCP */
+ struct iface *iface = fp->bundle->iface;
struct ipcp *ipcp = fsm2ipcp(fp);
- int type, length;
+ int type, length, gotdns, gotdnsnak, n;
u_int32_t compproto;
struct compreq *pcomp;
struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
char tbuff[100], tbuff2[100];
- int gotdns, gotdnsnak;
gotdns = 0;
gotdnsnak = 0;
@@ -810,14 +772,19 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
ipaddr, 1)) {
log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
inet_ntoa(ipaddr));
- if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0)
- /*
- * If we've already got a valid address configured for the peer
- * (in AUTO mode), try NAKing with that so that we don't
- * have to upset things too much.
- */
- ipcp->peer_ip = ipcp->peer_ifip;
- else
+ /*
+ * If we've already had a valid address configured for the peer,
+ * try NAKing with that so that we don't have to upset things
+ * too much.
+ */
+ for (n = 0; n < iface->in_addrs; n++)
+ if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd)
+ >=0) {
+ ipcp->peer_ip = iface->in_addr[n].brd;
+ break;
+ }
+
+ if (n == iface->in_addrs)
/* Just pick an IP number from our list */
ipcp->peer_ip = ChooseHisAddr
(fp->bundle, ipcp->cfg.my_range.ipaddr);
@@ -827,7 +794,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
dec->rejend += length;
} else {
memcpy(dec->nakend, cp, 2);
- memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
+ memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
dec->nakend += length;
}
break;
@@ -838,13 +805,20 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
* want to use.
*/
memcpy(dec->nakend, cp, 2);
- if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) ==
- (ipcp->cfg.peer_range.ipaddr.s_addr &
- ipcp->cfg.peer_range.mask.s_addr))
- /* We prefer the already-configured address */
- memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2);
- else
- memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
+ for (n = 0; n < iface->in_addrs; n++)
+ if ((iface->in_addr[n].brd.s_addr &
+ ipcp->cfg.peer_range.mask.s_addr)
+ == (ipcp->cfg.peer_range.ipaddr.s_addr &
+ ipcp->cfg.peer_range.mask.s_addr)) {
+ /* We prefer the already-configured address */
+ memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr,
+ length - 2);
+ break;
+ }
+
+ if (n == iface->in_addrs)
+ memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
+
dec->nakend += length;
break;
}
@@ -852,6 +826,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
memcpy(dec->ackend, cp, length);
dec->ackend += length;
break;
+
case MODE_NAK:
if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
/* Use address suggested by peer */
@@ -865,11 +840,13 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
fsm_Close(&ipcp->fsm);
}
break;
+
case MODE_REJ:
ipcp->peer_reject |= (1 << type);
break;
}
break;
+
case TY_COMPPROTO:
memcpy(&compproto, cp + 2, 4);
log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
@@ -920,16 +897,19 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
}
}
break;
+
case MODE_NAK:
log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
tbuff, ipcp->my_compproto, compproto);
ipcp->my_compproto = compproto;
break;
+
case MODE_REJ:
ipcp->peer_reject |= (1 << type);
break;
}
break;
+
case TY_IPADDRS: /* RFC1172 */
memcpy(&ipaddr.s_addr, cp + 2, 4);
memcpy(&dstipaddr.s_addr, cp + 6, 4);
@@ -943,6 +923,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
memcpy(dec->ackend, cp, length);
dec->ackend += length;
break;
+
case MODE_NAK:
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
inet_ntoa(ipcp->my_ip));
@@ -950,6 +931,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
ipcp->my_ip = ipaddr;
ipcp->peer_ip = dstipaddr;
break;
+
case MODE_REJ:
ipcp->peer_reject |= (1 << type);
break;
@@ -995,12 +977,14 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
dec->ackend += length;
}
break;
+
case MODE_NAK: /* what does this mean?? */
if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
gotdnsnak = 1;
memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
}
break;
+
case MODE_REJ: /* Can't do much, stop asking */
ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
break;
@@ -1034,9 +1018,11 @@ IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
dec->ackend += length;
}
break;
+
case MODE_NAK:
log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
break;
+
case MODE_REJ:
log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
break;
@@ -1116,11 +1102,8 @@ ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
- ipcp->cfg.peer_range.ipaddr, 0) < 0) {
- ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
- ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
+ ipcp->cfg.peer_range.ipaddr, 0) < 0)
return 0;
- }
} else
return 0;
diff --git a/usr.sbin/ppp/ipcp.h b/usr.sbin/ppp/ipcp.h
index c0a025e..39ea319 100644
--- a/usr.sbin/ppp/ipcp.h
+++ b/usr.sbin/ppp/ipcp.h
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: ipcp.h,v 1.19 1998/05/21 21:45:49 brian Exp $
+ * $Id: ipcp.h,v 1.20 1998/08/26 17:39:37 brian Exp $
*
* TODO:
*/
@@ -87,9 +87,6 @@ struct ipcp {
u_int32_t peer_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
- struct in_addr my_ifip; /* My configured interface address */
- struct in_addr peer_ifip; /* My congigured destination address */
-
struct pppThroughput throughput; /* throughput statistics */
struct mqueue Queue[PRI_FAST + 1]; /* Output packet queues */
};
diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c
index e092574..14aad68 100644
--- a/usr.sbin/ppp/main.c
+++ b/usr.sbin/ppp/main.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: main.c,v 1.142 1998/08/09 09:13:54 brian Exp $
+ * $Id: main.c,v 1.143 1998/09/17 00:45:27 brian Exp $
*
* TODO:
*/
@@ -75,6 +75,7 @@
#include "chap.h"
#include "cbcp.h"
#include "datalink.h"
+#include "iface.h"
#ifndef O_NONBLOCK
#ifdef O_NDELAY
@@ -329,10 +330,12 @@ main(int argc, char **argv)
}
if (prompt) {
prompt->bundle = bundle; /* couldn't do it earlier */
- prompt_Printf(prompt, "Using interface: %s\n", bundle->ifp.Name);
+ prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name);
}
SignalBundle = bundle;
bundle->AliasEnabled = alias;
+ if (alias)
+ bundle->cfg.opt |= OPT_IFACEALIAS;
if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0)
prompt_Printf(prompt, "Warning: No default entry found in config file.\n");
diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8
index 4ed85be..de37467 100644
--- a/usr.sbin/ppp/ppp.8
+++ b/usr.sbin/ppp/ppp.8
@@ -1,4 +1,4 @@
-.\" $Id: ppp.8,v 1.125 1998/09/17 00:45:12 brian Exp $
+.\" $Id: ppp.8,v 1.126 1998/09/18 23:28:10 brian Exp $
.Dd 20 September 1995
.Os FreeBSD
.Dt PPP 8
@@ -408,13 +408,10 @@ PPP ON awfulhak> add default HISADDR
.Pp
The string
.Sq HISADDR
-represents the IP address of the connected peer. It is possible to
-use the keyword
-.Sq INTERFACE
-in place of
-.Sq HISADDR .
-This will create a direct route on the tun interface.
-If it fails due to an existing route, you can overwrite the existing
+represents the IP address of the connected peer.
+If the
+.Dq add
+command fails due to an existing route, you can overwrite the existing
route using
.Bd -literal -offset indent
PPP ON awfulhak> add! default HISADDR
@@ -514,18 +511,15 @@ connection is established. See the provided
.Dq pmdemand
example in
.Pa /etc/ppp/ppp.conf.sample
-which runs a script in the background after the connection is established.
-The literal strings
-.Dv HISADDR ,
-.Dv MYADDR
+which runs a script in the background after the connection is established
+(refer to the
+.Dq shell
and
-.Dv INTERFACE
-may be used, and will be replaced with the relevant IP addresses and interface
-name. Similarly, when a connection is closed, the
-contents of the
+.Dq bg
+commands below for a description of possible substition strings). Similarly,
+when a connection is closed, the contents of the
.Pa /etc/ppp/ppp.linkdown
-file are executed.
-Both of these files have the same format as
+file are executed. Both of these files have the same format as
.Pa /etc/ppp/ppp.conf .
.Pp
In previous versions of
@@ -2134,6 +2128,28 @@ this option will tell
.Nm
not to make any utmp or wtmp entries. This is usually only necessary if
you require the user to both login and authenticate themselves.
+.It iface-alias
+Default: Enabled if
+.Fl alias
+is specified. This option simply tells
+.Nm
+to add new interface addresses to the interface rather than replacing them.
+The option can only be enabled if IP aliasing is enabled
+.Pq Dq alias enable yes .
+.Pp
+With this option enabled,
+.Nm
+will pass traffic for old interface addresses through the IP alias engine
+.Pq see Xr libalias 5 ,
+resulting in the ability (in
+.Fl auto
+mode) to properly connect the process that caused the PPP link to
+come up in the first place.
+.Pp
+Disabling IP aliasing with
+.Dq alias enable off
+will also disable
+.Sq iface-alias .
.El
.Pp
.It add[!] Ar dest[/nn] [mask] gateway
@@ -2162,24 +2178,14 @@ It is possible to use the symbolic names
.Sq MYADDR
or
.Sq HISADDR
-as the destination, and either
+as the destination, and
.Sq HISADDR
-or
-.Sq INTERFACE
as the
.Ar gateway .
.Sq MYADDR
-is replaced with the interface address,
+is replaced with the interface address and
.Sq HISADDR
-is replaced with the interface destination address and
-.Sq INTERFACE
-is replaced with the current interface name. If the interfaces destination
-address has not yet been assigned
-.Pq via Dq set ifaddr ,
-the current
-.Sq INTERFACE
-is used instead of
-.Sq HISADDR .
+is replaced with the interface destination (peer) address.
.Pp
If the
.Ar add!
@@ -2476,6 +2482,52 @@ is specified, only the relevant compression layer(s) are terminated.
Show a list of available commands. If
.Ar command
is specified, show the usage string for that command.
+.It iface Ar command Op args
+This command is used to control the interface used by
+.Nm ppp .
+.Ar Command
+may be one of the following:
+.Bl -tag -width XX
+.It iface add[!] Ar addr[/bits| mask] peer
+Add the given
+.Ar addr mask peer
+combination to the interface. Instead of specifying
+.Ar mask ,
+.Ar /bits
+can be used
+.Pq with no space between \&it and Ar addr .
+If the given address already exists, the command fails unless the
+.Dq \&!
+is used - in which case the previous interface address entry is overwritten
+with the new one, allowing a change of netmask or peer address.
+.It iface clear
+If this command is used while
+.Nm
+is in the OPENED state, all addresses except for the IPCP negotiated
+address are deleted from the interface. If
+.Nm
+is not in the OPENED state, all interface addresses are deleted.
+.Pp
+.It iface delete[!]|rm[!] Ar addr
+This command deletes the given
+.Ar addr
+from the interface. If the
+.Dq \&!
+is used, no error is given if the address isn't currently assigned to
+the interface (and no deletion takes place).
+.It iface show
+Shows the current state and current addresses for the interface. It is
+much the same as running
+.Dq ifconfig INTERFACE .
+.It iface help Op Ar sub-command
+This command, when invoked without
+.Ar sub-command ,
+will show a list of possbile
+.Dq iface
+sub-commands and a brief synopsis for each. When invoked with
+.Ar sub-command ,
+only the synopsis for the given sub-command is shown.
+.El
.It [data]link Ar name[,name...] command Op Ar args
This command may prefix any other command if the user wishes to
specify which link the command should affect. This is only
@@ -3160,6 +3212,16 @@ It is not possible to change a link that is
.Sq direct
or
.Sq dedicated .
+.Pp
+Note: If you issue the command
+.Dq set mode auto ,
+and have IP aliasing enabled, it may be useful to
+.Dq enable iface-alias
+afterwards. This will allow
+.Nm
+to do the necessary address translations to enable the process that
+triggers the connection to connect once the link is up despite the
+peer assigning us a new (dynamic) IP address.
.It set mrru Op Ar value
Setting this option enables Multi-link PPP negotiations, also known as
Multi-link Protocol or MP. There is no default MRRU (Maximum
@@ -3409,6 +3471,9 @@ is not specified, all filters are shown.
Show the current HDLC statistics.
.It show help|?
Give a summary of available show commands.
+.It show iface
+Show the current interface information
+.Pq the same \&as Dq iface show .
.It show ipcp
Show the current IPCP statistics.
.It show lcp
diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4
index 4ed85be..de37467 100644
--- a/usr.sbin/ppp/ppp.8.m4
+++ b/usr.sbin/ppp/ppp.8.m4
@@ -1,4 +1,4 @@
-.\" $Id: ppp.8,v 1.125 1998/09/17 00:45:12 brian Exp $
+.\" $Id: ppp.8,v 1.126 1998/09/18 23:28:10 brian Exp $
.Dd 20 September 1995
.Os FreeBSD
.Dt PPP 8
@@ -408,13 +408,10 @@ PPP ON awfulhak> add default HISADDR
.Pp
The string
.Sq HISADDR
-represents the IP address of the connected peer. It is possible to
-use the keyword
-.Sq INTERFACE
-in place of
-.Sq HISADDR .
-This will create a direct route on the tun interface.
-If it fails due to an existing route, you can overwrite the existing
+represents the IP address of the connected peer.
+If the
+.Dq add
+command fails due to an existing route, you can overwrite the existing
route using
.Bd -literal -offset indent
PPP ON awfulhak> add! default HISADDR
@@ -514,18 +511,15 @@ connection is established. See the provided
.Dq pmdemand
example in
.Pa /etc/ppp/ppp.conf.sample
-which runs a script in the background after the connection is established.
-The literal strings
-.Dv HISADDR ,
-.Dv MYADDR
+which runs a script in the background after the connection is established
+(refer to the
+.Dq shell
and
-.Dv INTERFACE
-may be used, and will be replaced with the relevant IP addresses and interface
-name. Similarly, when a connection is closed, the
-contents of the
+.Dq bg
+commands below for a description of possible substition strings). Similarly,
+when a connection is closed, the contents of the
.Pa /etc/ppp/ppp.linkdown
-file are executed.
-Both of these files have the same format as
+file are executed. Both of these files have the same format as
.Pa /etc/ppp/ppp.conf .
.Pp
In previous versions of
@@ -2134,6 +2128,28 @@ this option will tell
.Nm
not to make any utmp or wtmp entries. This is usually only necessary if
you require the user to both login and authenticate themselves.
+.It iface-alias
+Default: Enabled if
+.Fl alias
+is specified. This option simply tells
+.Nm
+to add new interface addresses to the interface rather than replacing them.
+The option can only be enabled if IP aliasing is enabled
+.Pq Dq alias enable yes .
+.Pp
+With this option enabled,
+.Nm
+will pass traffic for old interface addresses through the IP alias engine
+.Pq see Xr libalias 5 ,
+resulting in the ability (in
+.Fl auto
+mode) to properly connect the process that caused the PPP link to
+come up in the first place.
+.Pp
+Disabling IP aliasing with
+.Dq alias enable off
+will also disable
+.Sq iface-alias .
.El
.Pp
.It add[!] Ar dest[/nn] [mask] gateway
@@ -2162,24 +2178,14 @@ It is possible to use the symbolic names
.Sq MYADDR
or
.Sq HISADDR
-as the destination, and either
+as the destination, and
.Sq HISADDR
-or
-.Sq INTERFACE
as the
.Ar gateway .
.Sq MYADDR
-is replaced with the interface address,
+is replaced with the interface address and
.Sq HISADDR
-is replaced with the interface destination address and
-.Sq INTERFACE
-is replaced with the current interface name. If the interfaces destination
-address has not yet been assigned
-.Pq via Dq set ifaddr ,
-the current
-.Sq INTERFACE
-is used instead of
-.Sq HISADDR .
+is replaced with the interface destination (peer) address.
.Pp
If the
.Ar add!
@@ -2476,6 +2482,52 @@ is specified, only the relevant compression layer(s) are terminated.
Show a list of available commands. If
.Ar command
is specified, show the usage string for that command.
+.It iface Ar command Op args
+This command is used to control the interface used by
+.Nm ppp .
+.Ar Command
+may be one of the following:
+.Bl -tag -width XX
+.It iface add[!] Ar addr[/bits| mask] peer
+Add the given
+.Ar addr mask peer
+combination to the interface. Instead of specifying
+.Ar mask ,
+.Ar /bits
+can be used
+.Pq with no space between \&it and Ar addr .
+If the given address already exists, the command fails unless the
+.Dq \&!
+is used - in which case the previous interface address entry is overwritten
+with the new one, allowing a change of netmask or peer address.
+.It iface clear
+If this command is used while
+.Nm
+is in the OPENED state, all addresses except for the IPCP negotiated
+address are deleted from the interface. If
+.Nm
+is not in the OPENED state, all interface addresses are deleted.
+.Pp
+.It iface delete[!]|rm[!] Ar addr
+This command deletes the given
+.Ar addr
+from the interface. If the
+.Dq \&!
+is used, no error is given if the address isn't currently assigned to
+the interface (and no deletion takes place).
+.It iface show
+Shows the current state and current addresses for the interface. It is
+much the same as running
+.Dq ifconfig INTERFACE .
+.It iface help Op Ar sub-command
+This command, when invoked without
+.Ar sub-command ,
+will show a list of possbile
+.Dq iface
+sub-commands and a brief synopsis for each. When invoked with
+.Ar sub-command ,
+only the synopsis for the given sub-command is shown.
+.El
.It [data]link Ar name[,name...] command Op Ar args
This command may prefix any other command if the user wishes to
specify which link the command should affect. This is only
@@ -3160,6 +3212,16 @@ It is not possible to change a link that is
.Sq direct
or
.Sq dedicated .
+.Pp
+Note: If you issue the command
+.Dq set mode auto ,
+and have IP aliasing enabled, it may be useful to
+.Dq enable iface-alias
+afterwards. This will allow
+.Nm
+to do the necessary address translations to enable the process that
+triggers the connection to connect once the link is up despite the
+peer assigning us a new (dynamic) IP address.
.It set mrru Op Ar value
Setting this option enables Multi-link PPP negotiations, also known as
Multi-link Protocol or MP. There is no default MRRU (Maximum
@@ -3409,6 +3471,9 @@ is not specified, all filters are shown.
Show the current HDLC statistics.
.It show help|?
Give a summary of available show commands.
+.It show iface
+Show the current interface information
+.Pq the same \&as Dq iface show .
.It show ipcp
Show the current IPCP statistics.
.It show lcp
diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c
index a80204d..7f70efb 100644
--- a/usr.sbin/ppp/route.c
+++ b/usr.sbin/ppp/route.c
@@ -17,7 +17,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: route.c,v 1.52 1998/07/28 21:54:54 brian Exp $
+ * $Id: route.c,v 1.53 1998/08/17 06:42:40 brian Exp $
*
*/
@@ -61,6 +61,7 @@
#include "bundle.h"
#include "route.h"
#include "prompt.h"
+#include "iface.h"
static void
p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
@@ -361,7 +362,7 @@ route_IfDelete(struct bundle *bundle, int all)
char *sp, *cp, *ep;
int mib[6];
- log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->ifp.Index);
+ log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->iface->index);
sa_none.s_addr = INADDR_ANY;
mib[0] = CTL_NET;
@@ -407,7 +408,7 @@ route_IfDelete(struct bundle *bundle, int all)
Index2Nam(rtm->rtm_index), rtm->rtm_flags,
inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
- rtm->rtm_index == bundle->ifp.Index &&
+ rtm->rtm_index == bundle->iface->index &&
(all || (rtm->rtm_flags & RTF_GATEWAY))) {
sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
sa = (struct sockaddr *)((char *)sa + sa->sa_len);
diff --git a/usr.sbin/ppp/tun.c b/usr.sbin/ppp/tun.c
index c1d021f..6d97e38 100644
--- a/usr.sbin/ppp/tun.c
+++ b/usr.sbin/ppp/tun.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: tun.c,v 1.8 1998/06/27 14:18:15 brian Exp $
+ * $Id: tun.c,v 1.9 1998/08/09 16:41:01 brian Exp $
*/
#include <sys/types.h>
@@ -65,9 +65,10 @@ tun_configure(struct bundle *bundle, int mtu)
{
struct tuninfo info;
+ memset(&info, '\0', sizeof info);
info.type = IFT_PPP;
info.mtu = mtu;
- info.baudrate = bundle->ifp.Speed;
+ info.baudrate = bundle->ifSpeed;
#ifdef __OpenBSD__
info.flags = IFF_UP|IFF_POINTOPOINT;
#endif
OpenPOWER on IntegriCloud