Solve the ``first connection'' problem that occurs on

demand-dial links with dynamic IP numbers where the program
that causes the dial bind()s to an interface address that is
subsequently changed after ppp negotiation.

The problem is defeated by adding negotiated addresses to the
tun interface as additional alias addresses and providing a set
of ``iface'' commands for managing the interface.  Libalias is
also required (and what a name clash!) - it happily IP-aliases
the address so that the source is that of the primary (negotiated)
interface and un-IP-aliases it on the way back.

An ``enable iface-alias'' is done implicitly by the -alias command
line switch.  If -alias isn't given, iface-aliasing is disabled by
default and can't be enabled 'till an ``alias enable yes'' is done.
``alias enable no'' silently disables iface-alias.

So, for dynamic-IP-type-connections, running ``ppp -alias -auto blah''
will work for the first connection, although existing bindings will
not survive a disconnect/connect as the TCP peer will be trying to
send to the old IP address - the packets won't route.

It's now a lot easier to add IPXCP to ppp with minor updates to
the new iface.[ch] (if anyone ever gets 'round to it).

It's also now possible to manually add interface aliases with
something like ``iface add 1.2.3.4/24 5.6.7.8''.  This allows
multi-homed ppp links :-)
This commit is contained in:
Brian Somers 1998-10-22 02:32:50 +00:00
parent 0b10ba9822
commit 8fa6ebe47d
14 changed files with 1080 additions and 415 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)
{
@ -2046,6 +2036,22 @@ OptSet(struct cmdargs const *arg)
return 0;
}
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)
{
@ -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;
}

View File

@ -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);
}

431
usr.sbin/ppp/iface.c Normal file
View File

@ -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;
}

60
usr.sbin/ppp/iface.h Normal file
View File

@ -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 *);

View File

@ -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;
struct in_addr mask, oaddr;
u_int32_t addr;
/* 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;
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);
(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);
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;
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 (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
if (!silent)
log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n",
strerror(errno));
close(s);
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)) {
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);
}
}
if (Enabled(bundle, OPT_PROXY))
arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, 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;

View File

@ -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 */
};

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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