diff options
-rw-r--r-- | usr.sbin/ppp/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.c | 135 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.h | 10 | ||||
-rw-r--r-- | usr.sbin/ppp/command.c | 296 | ||||
-rw-r--r-- | usr.sbin/ppp/filter.c | 14 | ||||
-rw-r--r-- | usr.sbin/ppp/iface.c | 431 | ||||
-rw-r--r-- | usr.sbin/ppp/iface.h | 60 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.c | 271 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.h | 5 | ||||
-rw-r--r-- | usr.sbin/ppp/main.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8 | 127 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8.m4 | 127 | ||||
-rw-r--r-- | usr.sbin/ppp/route.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/tun.c | 5 |
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 |