diff options
-rw-r--r-- | usr.sbin/ppp/ppp/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/arp.c | 52 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/bundle.c | 177 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/bundle.h | 29 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/cbcp.c | 30 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/chat.c | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/command.c | 453 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/datalink.c | 12 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/filter.c | 14 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/iface.c | 481 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/iface.h | 60 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/ipcp.c | 311 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/ipcp.h | 8 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/lcp.c | 27 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/main.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/mp.c | 19 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/ppp.8 | 193 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/route.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/systems.c | 9 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp/tun.c | 5 |
20 files changed, 1421 insertions, 485 deletions
diff --git a/usr.sbin/ppp/ppp/Makefile b/usr.sbin/ppp/ppp/Makefile index bdbde1fdafb..dee84377e8d 100644 --- a/usr.sbin/ppp/ppp/Makefile +++ b/usr.sbin/ppp/ppp/Makefile @@ -1,11 +1,12 @@ -# $Id: Makefile,v 1.4 1998/09/17 00:47:13 brian Exp $ +# $Id: Makefile,v 1.5 1998/10/29 02:21:44 brian Exp $ PROG= ppp SRCS= arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chap_ms.c chat.c \ command.c datalink.c deflate.c defs.c filter.c fsm.c hdlc.c id.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 + 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 CFLAGS+=-Wall -DHAVE_DES LDADD+= -ldes -lutil -lz DPADD+= ${LIBDES} ${LIBUTIL} ${LIBZ} diff --git a/usr.sbin/ppp/ppp/arp.c b/usr.sbin/ppp/ppp/arp.c index 1e1df64dbd2..19cd1fcbbe7 100644 --- a/usr.sbin/ppp/ppp/arp.c +++ b/usr.sbin/ppp/ppp/arp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: arp.c,v 1.1 1998/08/31 00:22:15 brian Exp $ + * $Id: arp.c,v 1.2 1998/10/29 02:21:44 brian Exp $ * */ @@ -87,10 +87,8 @@ static struct { char extra[128]; } arpmsg; -static int arpmsg_valid; - -int -arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) +static int +arp_ProxySub(struct bundle *bundle, struct in_addr addr, int add, int s) { int routes; @@ -98,9 +96,11 @@ arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) * Get the hardware address of an interface on the same subnet as our local * address. */ + memset(&arpmsg, 0, sizeof arpmsg); if (!get_ether_addr(s, addr, &arpmsg.hwa)) { - log_Printf(LogWARN, "Cannot determine ethernet address for proxy ARP\n"); + log_Printf(LogWARN, "%s: Cannot determine ethernet address for proxy ARP\n", + inet_ntoa(addr)); return 0; } routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET); @@ -109,7 +109,7 @@ arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) strerror(errno)); return 0; } - arpmsg.hdr.rtm_type = RTM_ADD; + arpmsg.hdr.rtm_type = add ? RTM_ADD : RTM_DELETE; arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; arpmsg.hdr.rtm_version = RTM_VERSION; arpmsg.hdr.rtm_seq = ++bundle->routing_seq; @@ -122,44 +122,34 @@ arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg + arpmsg.hwa.sdl_len; - if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { - log_Printf(LogERROR, "Add proxy arp entry: %s\n", strerror(errno)); + + + if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0 && + !(!add && errno == ESRCH)) { + log_Printf(LogERROR, "%s proxy arp entry %s: %s\n", + add ? "Add" : "Delete", inet_ntoa(addr), strerror(errno)); close(routes); return 0; } close(routes); - arpmsg_valid = 1; return 1; } +int +arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) +{ + + return (arp_ProxySub(bundle, addr, 1, s)); +} + /* * arp_ClearProxy - Delete the proxy ARP entry for the peer. */ int arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s) { - int routes; - - if (!arpmsg_valid) - return 0; - arpmsg_valid = 0; - - arpmsg.hdr.rtm_type = RTM_DELETE; - arpmsg.hdr.rtm_seq = ++bundle->routing_seq; - routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET); - if (routes < 0) { - log_Printf(LogERROR, "arp_SetProxy: opening routing socket: %s\n", - strerror(errno)); - return 0; - } - if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { - log_Printf(LogERROR, "Delete proxy arp entry: %s\n", strerror(errno)); - close(routes); - return 0; - } - close(routes); - return 1; + return (arp_ProxySub(bundle, addr, 0, s)); } #else /* RTM_VERSION */ diff --git a/usr.sbin/ppp/ppp/bundle.c b/usr.sbin/ppp/ppp/bundle.c index 09d7d81745e..ee15d50ec41 100644 --- a/usr.sbin/ppp/ppp/bundle.c +++ b/usr.sbin/ppp/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.2 1998/08/31 08:16:34 brian Exp $ + * $Id: bundle.c,v 1.3 1998/10/29 02:21:44 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; } @@ -803,6 +762,8 @@ bundle_Create(const char *prefix, int type, const char **argv) log_SetTun(bundle.unit); bundle.argv = argv; + bundle.argv0 = argv[0]; + bundle.argv1 = argv[1]; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { @@ -811,24 +772,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 +805,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 +846,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 +882,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 +904,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 +950,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 { @@ -1021,6 +987,17 @@ bundle_SetRoute(struct bundle *bundle, int cmd, struct in_addr dst, rtmes.m_rtm.rtm_pid = getpid(); rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; + if (cmd == RTM_ADD || cmd == RTM_CHANGE) { + if (bundle->ncp.ipcp.cfg.sendpipe > 0) { + rtmes.m_rtm.rtm_rmx.rmx_sendpipe = bundle->ncp.ipcp.cfg.sendpipe; + rtmes.m_rtm.rtm_inits |= RTV_SPIPE; + } + if (bundle->ncp.ipcp.cfg.recvpipe > 0) { + rtmes.m_rtm.rtm_rmx.rmx_recvpipe = bundle->ncp.ipcp.cfg.recvpipe; + rtmes.m_rtm.rtm_inits |= RTV_RPIPE; + } + } + memset(&rtdata, '\0', sizeof rtdata); rtdata.sin_len = sizeof rtdata; rtdata.sin_family = AF_INET; @@ -1032,24 +1009,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); @@ -1082,7 +1045,7 @@ failed: (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) { if (!bang) { log_Printf(LogWARN, "Add route failed: %s already exists\n", - inet_ntoa(dst)); + dst.s_addr == 0 ? "default" : inet_ntoa(dst)); result = 0; /* Don't add to our dynamic list */ } else { rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; @@ -1239,9 +1202,10 @@ bundle_ShowStatus(struct cmdargs const *arg) int remaining; prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle)); + prompt_Printf(arg->prompt, " Title: %s\n", arg->bundle->argv[0]); 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); @@ -1280,6 +1244,17 @@ bundle_ShowStatus(struct cmdargs const *arg) else prompt_Printf(arg->prompt, "unspecified\n"); + prompt_Printf(arg->prompt, " sendpipe: "); + if (arg->bundle->ncp.ipcp.cfg.sendpipe > 0) + prompt_Printf(arg->prompt, "%ld\n", arg->bundle->ncp.ipcp.cfg.sendpipe); + else + prompt_Printf(arg->prompt, "unspecified\n"); + prompt_Printf(arg->prompt, " recvpipe: "); + if (arg->bundle->ncp.ipcp.cfg.recvpipe > 0) + prompt_Printf(arg->prompt, "%ld\n", arg->bundle->ncp.ipcp.cfg.recvpipe); + else + prompt_Printf(arg->prompt, "unspecified\n"); + prompt_Printf(arg->prompt, " Sticky Routes: %s\n", optval(arg->bundle, OPT_SROUTES)); prompt_Printf(arg->prompt, " ID check: %s\n", @@ -1290,10 +1265,14 @@ bundle_ShowStatus(struct cmdargs const *arg) optval(arg->bundle, OPT_PASSWDAUTH)); prompt_Printf(arg->prompt, " Proxy: %s\n", optval(arg->bundle, OPT_PROXY)); + prompt_Printf(arg->prompt, " Proxyall: %s\n", + optval(arg->bundle, OPT_PROXYALL)); prompt_Printf(arg->prompt, " Throughput: %s\n", 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 +1615,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; } @@ -1748,3 +1722,16 @@ bundle_setsid(struct bundle *bundle, int holdsession) break; } } + +int +bundle_HighestState(struct bundle *bundle) +{ + struct datalink *dl; + int result = DATALINK_CLOSED; + + for (dl = bundle->links; dl; dl = dl->next) + if (result < dl->state) + result = dl->state; + + return result; +} diff --git a/usr.sbin/ppp/ppp/bundle.h b/usr.sbin/ppp/ppp/bundle.h index 3299f8bad6d..ec72b1850ca 100644 --- a/usr.sbin/ppp/ppp/bundle.h +++ b/usr.sbin/ppp/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.1 1998/08/31 00:22:16 brian Exp $ + * $Id: bundle.h,v 1.2 1998/10/29 02:21:44 brian Exp $ */ #define PHASE_DEAD 0 /* Link is dead */ @@ -33,13 +33,15 @@ #define PHASE_TERMINATE 4 /* Terminating link */ /* cfg.opt bit settings */ -#define OPT_IDCHECK 0x01 -#define OPT_LOOPBACK 0x02 -#define OPT_PASSWDAUTH 0x04 -#define OPT_PROXY 0x08 -#define OPT_SROUTES 0x10 -#define OPT_THROUGHPUT 0x20 -#define OPT_UTMP 0x40 +#define OPT_IDCHECK 0x0001 +#define OPT_IFACEALIAS 0x0002 +#define OPT_LOOPBACK 0x0004 +#define OPT_PASSWDAUTH 0x0008 +#define OPT_PROXY 0x0010 +#define OPT_PROXYALL 0x0020 +#define OPT_SROUTES 0x0040 +#define OPT_THROUGHPUT 0x0080 +#define OPT_UTMP 0x0100 #define MAX_ENDDISC_CLASS 5 @@ -51,22 +53,22 @@ struct physical; struct link; struct server; struct prompt; +struct iface; struct bundle { struct descriptor desc; /* really all our datalinks */ int unit; /* The device/interface unit number */ const char **argv; /* From main() */ + const char *argv0; /* Original */ + const char *argv1; /* Original */ struct { char Name[20]; /* The /dev/XXXX name */ int fd; /* The /dev/XXXX descriptor */ } dev; - struct { - u_long Speed; /* struct tuninfo speed */ - int Index; /* The interface index */ - char *Name; /* The interface name */ - } ifp; + u_long ifSpeed; /* struct tuninfo speed */ + struct iface *iface; /* Interface information */ int routing_seq; /* The current routing sequence number */ u_int phase; /* Curent phase */ @@ -181,3 +183,4 @@ extern int bundle_RenameDatalink(struct bundle *, struct datalink *, const char *); extern void bundle_setsid(struct bundle *, int); extern void bundle_LockTun(struct bundle *); +extern int bundle_HighestState(struct bundle *); diff --git a/usr.sbin/ppp/ppp/cbcp.c b/usr.sbin/ppp/ppp/cbcp.c index 265e75f0696..6b9350599e4 100644 --- a/usr.sbin/ppp/ppp/cbcp.c +++ b/usr.sbin/ppp/ppp/cbcp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cbcp.c,v 1.1 1998/08/31 00:22:16 brian Exp $ + * $Id: cbcp.c,v 1.2 1998/10/29 02:21:44 brian Exp $ */ #include <sys/types.h> @@ -293,7 +293,7 @@ cbcp_SendReq(struct cbcp *cbcp) break; default: - data.length = 2; + data.length = (char *)&data.delay - (char *)&data; break; } @@ -471,7 +471,9 @@ cbcp_SendResponse(struct cbcp *cbcp) data.type = cbcp->fsm.type; data.delay = cbcp->fsm.delay; addr = (struct cbcp_addr *)data.addr_start; - if (*cbcp->fsm.phone) { + if (data.type == CBCP_NONUM) + data.length = (char *)&data.delay - (char *)&data; + else if (*cbcp->fsm.phone) { addr->type = CBCP_ADDR_PSTN; strcpy(addr->addr, cbcp->fsm.phone); data.length = (addr->addr + strlen(addr->addr) + 1) - (char *)&data; @@ -548,6 +550,13 @@ cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data) log_Printf(LogPHASE, "Internal CBCP error - agreed on %d ??!?\n", (int)cbcp->fsm.type); return CBCP_ACTION_DOWN; + } else if (data->type == CBCP_NONUM && cbcp->fsm.type == CBCP_CLIENTNUM) { + /* + * Client doesn't want CBCP after all.... + * We only allow this when ``set cbcp *'' has been specified. + */ + cbcp->fsm.type = CBCP_NONUM; + return CBCP_ACTION_ACK; } log_Printf(LogCBCP, "Invalid peer RESPONSE\n"); return CBCP_ACTION_REQ; @@ -557,6 +566,7 @@ static void cbcp_SendAck(struct cbcp *cbcp) { struct cbcp_data data; + char *end; /* Only callees send ACKs */ @@ -565,7 +575,8 @@ cbcp_SendAck(struct cbcp *cbcp) data.type = cbcp->fsm.type; data.delay = cbcp->fsm.delay; - data.length = data.addr_start - (char *)&data; + end = data.type == CBCP_NONUM ? (char *)&data.delay : data.addr_start; + data.length = end - (char *)&data; cbcp_data_Show(&data); cbcp_Output(cbcp, CBCP_ACK, &data); @@ -610,6 +621,7 @@ cbcp_Input(struct physical *p, struct mbuf *bp) timer_Stop(&cbcp->fsm.timer); if (cbcp_AdjustResponse(cbcp, data)) { cbcp->fsm.restart = DEF_REQs; + cbcp->fsm.id = head->id; cbcp_SendResponse(cbcp); } else datalink_CBCPFailed(cbcp->p->dl); @@ -621,6 +633,11 @@ cbcp_Input(struct physical *p, struct mbuf *bp) log_Printf(LogCBCP, "%s: RecvResponse(%d) state = %s\n", p->dl->name, head->id, cbcpstate(cbcp->fsm.state)); cbcp_data_Show(data); + if (cbcp->fsm.id != head->id) { + log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n", + cbcp->fsm.id, head->id); + cbcp->fsm.id = head->id; + } if (cbcp->fsm.state == CBCP_REQSENT || cbcp->fsm.state == CBCP_ACKSENT) { timer_Stop(&cbcp->fsm.timer); switch (cbcp_CheckResponse(cbcp, data)) { @@ -653,6 +670,11 @@ cbcp_Input(struct physical *p, struct mbuf *bp) log_Printf(LogCBCP, "%s: RecvAck(%d) state = %s\n", p->dl->name, head->id, cbcpstate(cbcp->fsm.state)); cbcp_data_Show(data); + if (cbcp->fsm.id != head->id) { + log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n", + cbcp->fsm.id, head->id); + cbcp->fsm.id = head->id; + } if (cbcp->fsm.state == CBCP_RESPSENT) { timer_Stop(&cbcp->fsm.timer); datalink_CBCPComplete(cbcp->p->dl); diff --git a/usr.sbin/ppp/ppp/chat.c b/usr.sbin/ppp/ppp/chat.c index eb8f36c58c9..3cb19aa8824 100644 --- a/usr.sbin/ppp/ppp/chat.c +++ b/usr.sbin/ppp/ppp/chat.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: chat.c,v 1.1 1998/08/31 00:22:18 brian Exp $ + * $Id: chat.c,v 1.2 1998/10/29 02:21:44 brian Exp $ */ #include <sys/types.h> @@ -429,6 +429,7 @@ chat_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) if (begin >= ebegin && begin < eend && !strncmp(begin, c->argptr, c->arglen)) { /* Got it ! */ + timer_Stop(&c->timeout); if (memchr(begin + c->arglen - 1, '\n', c->bufend - begin - c->arglen + 1) == NULL) { /* force it into the log */ diff --git a/usr.sbin/ppp/ppp/command.c b/usr.sbin/ppp/ppp/command.c index 013cdaf65c1..32047b97522 100644 --- a/usr.sbin/ppp/ppp/command.c +++ b/usr.sbin/ppp/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.2 1998/08/31 08:16:36 brian Exp $ + * $Id: command.c,v 1.3 1998/10/29 02:21:44 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 @@ -112,6 +113,8 @@ #define VAR_CALLBACK 24 #define VAR_CBCP 25 #define VAR_CHOKED 26 +#define VAR_SENDPIPE 27 +#define VAR_RECVPIPE 28 /* ``accept|deny|disable|enable'' masks */ #define NEG_HISMASK (1) @@ -131,7 +134,7 @@ #define NEG_DNS 50 const char Version[] = "2.0"; -const char VersionDate[] = "$Date: 1998/08/31 08:16:36 $"; +const char VersionDate[] = "$Date: 1998/10/29 02:21:44 $"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); @@ -139,15 +142,18 @@ 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 *); +static int SetProcTitle(struct cmdargs const *); #ifndef NOALIAS -static int AliasCommand(struct cmdargs const *); static int AliasEnable(struct cmdargs const *); static int AliasOption(struct cmdargs const *); #endif @@ -203,7 +209,9 @@ HelpCommand(struct cmdargs const *arg) if (cmd->name && (cmd->lauth & arg->prompt->auth)) { cx = showcx(cmd); cxlen = cmax - strlen(cmd->name); - prompt_Printf(arg->prompt, " %s%-*.*s: %-*.*s", + if (n % cols != 0) + prompt_Printf(arg->prompt, " "); + prompt_Printf(arg->prompt, "%s%-*.*s: %-*.*s", cmd->name, cxlen, cxlen, cx, dmax, dmax, cmd->helpmes); if (++n % cols == 0) prompt_Printf(arg->prompt, "\n"); @@ -377,14 +385,16 @@ static void expand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle) { int arg; + char pid[12]; nargv[0] = strdup(oargv[0]); + snprintf(pid, sizeof pid, "%d", getpid()); for (arg = 1; arg < argc; arg++) { nargv[arg] = strdup(oargv[arg]); 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", @@ -395,6 +405,7 @@ expand(char **nargv, int argc, char const *const *oargv, struct bundle *bundle) mp_Enddisc(bundle->ncp.mp.cfg.enddisc.class, bundle->ncp.mp.cfg.enddisc.address, bundle->ncp.mp.cfg.enddisc.len)); + nargv[arg] = subst(nargv[arg], "PROCESSID", pid); nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); } nargv[arg] = NULL; @@ -479,8 +490,9 @@ ShellCommand(struct cmdargs const *arg, int bg) execl(shell, shell, NULL); } - log_Printf(LogWARN, "exec() of %s failed\n", - arg->argc > arg->argn ? arg->argv[arg->argn] : shell); + log_Printf(LogWARN, "exec() of %s failed: %s\n", + arg->argc > arg->argn ? arg->argv[arg->argn] : shell, + strerror(errno)); exit(255); } @@ -511,6 +523,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 .."}, @@ -519,11 +594,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, @@ -546,6 +621,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, @@ -653,6 +730,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, @@ -1198,13 +1277,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); @@ -1226,20 +1304,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; @@ -1275,24 +1346,32 @@ SetVariable(struct cmdargs const *arg) switch (param) { case VAR_AUTHKEY: - if (bundle_Phase(arg->bundle) == PHASE_DEAD) { - strncpy(arg->bundle->cfg.auth.key, argp, - sizeof arg->bundle->cfg.auth.key - 1); - arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; - } else { - err = "set authkey: Only available at phase DEAD\n"; - log_Printf(LogWARN, err); + switch (bundle_Phase(arg->bundle)) { + case PHASE_DEAD: + case PHASE_ESTABLISH: + strncpy(arg->bundle->cfg.auth.key, argp, + sizeof arg->bundle->cfg.auth.key - 1); + arg->bundle->cfg.auth.key[sizeof arg->bundle->cfg.auth.key - 1] = '\0'; + break; + default: + err = "set authkey: Only available at phase DEAD/ESTABLISH\n"; + log_Printf(LogWARN, err); + break; } break; case VAR_AUTHNAME: - if (bundle_Phase(arg->bundle) == PHASE_DEAD) { - strncpy(arg->bundle->cfg.auth.name, argp, - sizeof arg->bundle->cfg.auth.name - 1); - arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name - 1] = '\0'; - } else { - err = "set authname: Only available at phase DEAD\n"; - log_Printf(LogWARN, err); + switch (bundle_Phase(arg->bundle)) { + case PHASE_DEAD: + case PHASE_ESTABLISH: + strncpy(arg->bundle->cfg.auth.name, argp, + sizeof arg->bundle->cfg.auth.name - 1); + arg->bundle->cfg.auth.name[sizeof arg->bundle->cfg.auth.name-1] = '\0'; + break; + default: + err = "set authname: Only available at phase DEAD/ESTABLISH\n"; + log_Printf(LogWARN, err); + break; } break; @@ -1375,9 +1454,19 @@ SetVariable(struct cmdargs const *arg) break; case VAR_MRRU: - if (bundle_Phase(arg->bundle) != PHASE_DEAD) { - log_Printf(LogWARN, "mrru: Only changable at phase DEAD\n"); - return 1; + switch (bundle_Phase(arg->bundle)) { + case PHASE_DEAD: + break; + case PHASE_ESTABLISH: + /* Make sure none of our links are DATALINK_LCP or greater */ + if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { + log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); + return 1; + } + break; + default: + log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); + return 1; } long_val = atol(argp); if (long_val && long_val < MIN_MRU) { @@ -1583,7 +1672,16 @@ SetVariable(struct cmdargs const *arg) if (arg->bundle->cfg.choked.timeout <= 0) arg->bundle->cfg.choked.timeout = CHOKED_TIMEOUT; break; - + + case VAR_SENDPIPE: + long_val = atol(argp); + arg->bundle->ncp.ipcp.cfg.sendpipe = long_val; + break; + + case VAR_RECVPIPE: + long_val = atol(argp); + arg->bundle->ncp.ipcp.cfg.recvpipe = long_val; + break; } return err ? 1 : 0; @@ -1679,10 +1777,16 @@ static struct cmdtab const SetCommands[] = { "modem parity", "set parity [odd|even|none]"}, {"phone", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "telephone number(s)", "set phone phone1[:phone2[...]]", (const void *)VAR_PHONE}, + {"proctitle", "title", SetProcTitle, LOCAL_AUTH, + "Process title", "set proctitle [value]"}, {"reconnect", NULL, datalink_SetReconnect, LOCAL_AUTH | LOCAL_CX, "Reconnect timeout", "set reconnect value ntries"}, + {"recvpipe", NULL, SetVariable, LOCAL_AUTH, + "RECVPIPE value", "set recvpipe value", (const void *)VAR_RECVPIPE}, {"redial", NULL, datalink_SetRedial, LOCAL_AUTH | LOCAL_CX, "Redial timeout", "set redial value|random[.value|random] [attempts]"}, + {"sendpipe", NULL, SetVariable, LOCAL_AUTH, + "SENDPIPE value", "set sendpipe value", (const void *)VAR_SENDPIPE}, {"server", "socket", SetServer, LOCAL_AUTH, "server port", "set server|socket TcpPort|LocalName|none password [mask]"}, {"speed", NULL, SetModemSpeed, LOCAL_AUTH | LOCAL_CX, @@ -1715,7 +1819,6 @@ SetCommand(struct cmdargs const *arg) return 0; } - static int AddCommand(struct cmdargs const *arg) { @@ -1757,9 +1860,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, @@ -1806,51 +1907,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) { @@ -1860,6 +1916,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; } } @@ -1892,32 +1950,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) { @@ -2045,6 +2077,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; @@ -2105,12 +2153,24 @@ NegotiateSet(struct cmdargs const *arg) cx->physical->link.lcp.cfg.protocomp |= add; break; case NEG_SHORTSEQ: - if (bundle_Phase(arg->bundle) != PHASE_DEAD) - log_Printf(LogWARN, "shortseq: Only changable at phase DEAD\n"); - else { - arg->bundle->ncp.mp.cfg.shortseq &= keep; - arg->bundle->ncp.mp.cfg.shortseq |= add; + switch (bundle_Phase(arg->bundle)) { + case PHASE_DEAD: + break; + case PHASE_ESTABLISH: + /* Make sure none of our links are DATALINK_LCP or greater */ + if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { + log_Printf(LogWARN, "shortseq: Only changable before" + " LCP negotiations\n"); + return 1; + } + break; + default: + log_Printf(LogWARN, "shortseq: Only changable at phase" + " DEAD/ESTABLISH\n"); + return 1; } + arg->bundle->ncp.mp.cfg.shortseq &= keep; + arg->bundle->ncp.mp.cfg.shortseq |= add; break; case NEG_VJCOMP: arg->bundle->ncp.ipcp.cfg.vj.neg &= keep; @@ -2124,12 +2184,17 @@ NegotiateSet(struct cmdargs const *arg) static struct cmdtab const NegotiateCommands[] = { {"idcheck", NULL, OptSet, LOCAL_AUTH, "Check FSM reply ids", "disable|enable", (const void *)OPT_IDCHECK}, + {"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH, + "retain interface addresses", "disable|enable", + (const void *)OPT_IFACEALIAS}, {"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface", "disable|enable", (const void *)OPT_LOOPBACK}, {"passwdauth", NULL, OptSet, LOCAL_AUTH, "Use passwd file", "disable|enable", (const void *)OPT_PASSWDAUTH}, - {"proxy", NULL, OptSet, LOCAL_AUTH, "Create proxy ARP entry", + {"proxy", NULL, OptSet, LOCAL_AUTH, "Create a proxy ARP entry", "disable|enable", (const void *)OPT_PROXY}, + {"proxyall", NULL, OptSet, LOCAL_AUTH, "Proxy ARP for all remote hosts", + "disable|enable", (const void *)OPT_PROXYALL}, {"sroutes", NULL, OptSet, LOCAL_AUTH, "Use sticky routes", "disable|enable", (const void *)OPT_SROUTES}, {"throughput", NULL, OptSet, LOCAL_AUTH, "Rolling throughput", @@ -2137,7 +2202,7 @@ static struct cmdtab const NegotiateCommands[] = { {"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp", "disable|enable", (const void *)OPT_UTMP}, -#define OPT_MAX 7 /* accept/deny allowed below and not above */ +#define OPT_MAX 9 /* accept/deny allowed below and not above */ {"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX, "Address & Control field compression", "accept|deny|disable|enable", @@ -2256,3 +2321,143 @@ 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 + 1) { + if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) + return -1; + mask.s_addr = brd.s_addr = INADDR_BROADCAST; + } else { + 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; +} + +static int +SetProcTitle(struct cmdargs const *arg) +{ + static char title[LINE_LEN]; + char *argv[MAXARGS], *ptr; + int len, remaining, f, argc = arg->argc - arg->argn; + + if (arg->argc == arg->argn) { + arg->bundle->argv[0] = arg->bundle->argv0; + arg->bundle->argv[1] = arg->bundle->argv1; + return 0; + } + + if (argc >= sizeof argv / sizeof argv[0]) { + argc = sizeof argv / sizeof argv[0] - 1; + log_Printf(LogWARN, "Truncating proc title to %d args\n", argc); + } + expand(argv, argc, arg->argv + arg->argn, arg->bundle); + + ptr = title; + remaining = sizeof title - 1; + for (f = 0; f < argc && remaining; f++) { + if (f) { + *ptr++ = ' '; + remaining--; + } + len = strlen(argv[f]); + if (len > remaining) + len = remaining; + memcpy(ptr, argv[f], len); + remaining -= len; + ptr += len; + } + *ptr = '\0'; + + arg->bundle->argv[0] = title; + arg->bundle->argv[1] = NULL; + + return 0; +} diff --git a/usr.sbin/ppp/ppp/datalink.c b/usr.sbin/ppp/ppp/datalink.c index d8a1bf24aea..2c8a4c61dbc 100644 --- a/usr.sbin/ppp/ppp/datalink.c +++ b/usr.sbin/ppp/ppp/datalink.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.c,v 1.1 1998/08/31 00:22:19 brian Exp $ + * $Id: datalink.c,v 1.2 1998/10/29 02:21:44 brian Exp $ */ #include <sys/types.h> @@ -984,8 +984,14 @@ datalink_Show(struct cmdargs const *arg) prompt_Printf(arg->prompt, "%scbcp\n", comma ? ", " : ""); prompt_Printf(arg->prompt, " CBCP: delay: %ds\n", arg->cx->cfg.cbcp.delay); - prompt_Printf(arg->prompt, " phone: %s\n", - arg->cx->cfg.cbcp.phone); + prompt_Printf(arg->prompt, " phone: "); + if (!strcmp(arg->cx->cfg.cbcp.phone, "*")) { + if (arg->cx->physical->type & PHYS_DIRECT) + prompt_Printf(arg->prompt, "Caller decides\n"); + else + prompt_Printf(arg->prompt, "Dialback server decides\n"); + } else + prompt_Printf(arg->prompt, "%s\n", arg->cx->cfg.cbcp.phone); prompt_Printf(arg->prompt, " timeout: %lds\n", arg->cx->cfg.cbcp.fsmretry); } else diff --git a/usr.sbin/ppp/ppp/filter.c b/usr.sbin/ppp/ppp/filter.c index 29591fac11d..5e82924437c 100644 --- a/usr.sbin/ppp/ppp/filter.c +++ b/usr.sbin/ppp/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.1 1998/08/31 00:22:20 brian Exp $ + * $Id: filter.c,v 1.2 1998/10/29 02:21:45 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/ppp/iface.c b/usr.sbin/ppp/ppp/iface.c new file mode 100644 index 00000000000..09141a96d1e --- /dev/null +++ b/usr.sbin/ppp/ppp/iface.c @@ -0,0 +1,481 @@ +/*- + * 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: iface.c,v 1.1 1998/10/29 02:21:45 brian Exp $ + */ + +#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; + log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(addr->ifa)); + 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, chg; + 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; + } + + /* + * We've gotta be careful here. If we try to add an address with the + * same destination as an existing interface, nothing will work. + * Instead, we tweak all previous address entries that match the + * to-be-added destination to 255.255.255.255 (w/ a similar netmask). + * There *may* be more than one - if the user has ``iface add''ed + * stuff previously. + */ + for (chg = 0; chg < iface->in_addrs; chg++) { + if ((iface->in_addr[chg].brd.s_addr == brd.s_addr && + brd.s_addr != INADDR_BROADCAST) || chg == slot) { + 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 = iface->in_addr[chg].ifa; + msk->sin_addr = iface->in_addr[chg].mask; + peer->sin_addr = iface->in_addr[chg].brd; + log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(me->sin_addr)); + ID0ioctl(s, SIOCDIFADDR, &ifra); /* Don't care if it fails... */ + if (chg != slot) { + peer->sin_addr.s_addr = iface->in_addr[chg].brd.s_addr = + msk->sin_addr.s_addr = iface->in_addr[chg].mask.s_addr = + INADDR_BROADCAST; + iface->in_addr[chg].bits = 32; + log_Printf(LogDEBUG, "Add %s -> 255.255.255.255\n", + inet_ntoa(me->sin_addr)); + if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) { + /* Oops - that's bad(ish) news ! We've lost an alias ! */ + log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n", + inet_ntoa(me->sin_addr), strerror(errno)); + iface->in_addrs--; + bcopy(iface->in_addr + chg + 1, iface->in_addr + chg, + (iface->in_addrs - chg) * sizeof iface->in_addr[0]); + if (slot > chg) + slot--; + chg--; + } + } + } + } + + 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; + + if (log_IsKept(LogDEBUG)) { + char buf[16]; + + strncpy(buf, inet_ntoa(brd), sizeof buf-1); + buf[sizeof buf - 1] = '\0'; + log_Printf(LogDEBUG, "Add %s -> %s\n", inet_ntoa(ifa), buf); + } + + /* An EEXIST failure w/ brd == INADDR_BROADCAST is ok (and works!) */ + if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && + (brd.s_addr != INADDR_BROADCAST || errno != EEXIST)) { + log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n", + inet_ntoa(ifa), strerror(errno)); + ID0ioctl(s, SIOCDIFADDR, &ifra); /* EEXIST ? */ + 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/ppp/iface.h b/usr.sbin/ppp/ppp/iface.h new file mode 100644 index 00000000000..c9c5cafc61b --- /dev/null +++ b/usr.sbin/ppp/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: iface.h,v 1.1 1998/10/29 02:21:45 brian Exp $ + */ + +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/ppp/ipcp.c b/usr.sbin/ppp/ppp/ipcp.c index 6bc15118327..6113885c1a0 100644 --- a/usr.sbin/ppp/ppp/ipcp.c +++ b/usr.sbin/ppp/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.4 1998/09/04 18:42:08 brian Exp $ + * $Id: ipcp.c,v 1.5 1998/10/29 02:21:45 brian Exp $ * * TODO: * o More RFC1772 backward compatibility @@ -28,10 +28,12 @@ #include <netinet/ip.h> #include <arpa/inet.h> #include <sys/socket.h> +#include <net/route.h> #include <netdb.h> #include <net/if.h> #include <sys/sockio.h> #include <sys/un.h> +#include <arpa/nameser.h> #include <fcntl.h> #include <resolv.h> @@ -77,6 +79,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 +357,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 +376,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 +390,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 +428,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) + @@ -447,84 +459,90 @@ ipcp_Setup(struct ipcp *ipcp) } static int -ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, - struct in_addr hisaddr, int silent) +ipcp_doproxyall(struct bundle *bundle, + int (*proxyfun)(struct bundle *, struct in_addr, int), int s) { - 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; - - 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); + int n, ret; + struct sticky_route *rp; + struct in_addr addr; + struct ipcp *ipcp; + + ipcp = &bundle->ncp.ipcp; + for (rp = ipcp->route; rp != NULL; rp = rp->next) { + if (ntohl(rp->mask.s_addr) == INADDR_BROADCAST) + continue; + n = INADDR_BROADCAST - ntohl(rp->mask.s_addr) - 1; + if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { + addr = rp->dst; + while (n--) { + addr.s_addr = htonl(ntohl(addr.s_addr) + 1); + log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); + ret = (*proxyfun)(bundle, addr, s); + if (!ret) + return ret; + } + } } - 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; + return 0; +} - /* 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; +static int +ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, + struct in_addr hisaddr, int silent) +{ + static struct in_addr none = { INADDR_ANY }; + struct in_addr mask, oaddr; + u_int32_t addr; - 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 (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) + bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 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) || Enabled(bundle, OPT_PROXYALL)) { + int s = ID0socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", + strerror(errno)); + else { + if (Enabled(bundle, OPT_PROXYALL)) + ipcp_doproxyall(bundle, arp_SetProxy, s); + else if (Enabled(bundle, OPT_PROXY)) + 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 +657,26 @@ 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) || + Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { + int s = ID0socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", + strerror(errno)); + else { + if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) + ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); + else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) + 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 +686,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 +705,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 +729,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 +746,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 +760,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 +772,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 +814,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 +836,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 +847,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 +868,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 +882,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 +939,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 +965,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 +973,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 +1019,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 +1060,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 +1144,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/ppp/ipcp.h b/usr.sbin/ppp/ppp/ipcp.h index 0f293080468..e52459001f8 100644 --- a/usr.sbin/ppp/ppp/ipcp.h +++ b/usr.sbin/ppp/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.1 1998/08/31 00:22:22 brian Exp $ + * $Id: ipcp.h,v 1.2 1998/10/29 02:21:45 brian Exp $ * * TODO: */ @@ -57,6 +57,9 @@ struct ipcp { struct in_range peer_range; /* HISADDR spec */ struct iplist peer_list; /* Ranges of HISADDR values */ + u_long sendpipe; /* route sendpipe size */ + u_long recvpipe; /* route recvpipe size */ + struct in_addr TriggerAddress; /* Address to suggest in REQ */ unsigned HaveTriggerAddress : 1; /* Trigger address specified */ @@ -87,9 +90,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/ppp/lcp.c b/usr.sbin/ppp/ppp/lcp.c index 598c0e41c7c..a551caa60b0 100644 --- a/usr.sbin/ppp/ppp/lcp.c +++ b/usr.sbin/ppp/ppp/lcp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lcp.c,v 1.3 1998/09/09 00:07:10 brian Exp $ + * $Id: lcp.c,v 1.4 1998/10/29 02:21:45 brian Exp $ * * TODO: * o Limit data field length by MRU @@ -663,13 +663,24 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, #ifdef HAVE_DES link2physical(fp->link)->dl->chap.using_MSChap = cp[4] == 0x80; #endif - } else if (IsAccepted(lcp->cfg.pap)) { - *dec->nakend++ = *cp; - *dec->nakend++ = 4; - *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8); - *dec->nakend++ = (unsigned char) PROTO_PAP; - } else - goto reqreject; + } else { + if (IsAccepted(lcp->cfg.chap)) { +#ifndef HAVE_DES + if (cp[4] == 0x80) + log_Printf(LogWARN, "Chap 0x80 not available without DES\n"); + else +#endif + log_Printf(LogWARN, "Chap 0x%02x not supported\n", + (unsigned)cp[4]); + } + if (IsAccepted(lcp->cfg.pap)) { + *dec->nakend++ = *cp; + *dec->nakend++ = 4; + *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8); + *dec->nakend++ = (unsigned char) PROTO_PAP; + } else + goto reqreject; + } break; default: diff --git a/usr.sbin/ppp/ppp/main.c b/usr.sbin/ppp/ppp/main.c index 48c36c7e317..059f365da92 100644 --- a/usr.sbin/ppp/ppp/main.c +++ b/usr.sbin/ppp/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.2 1998/08/31 08:16:41 brian Exp $ + * $Id: main.c,v 1.3 1998/10/29 02:21:45 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/mp.c b/usr.sbin/ppp/ppp/mp.c index 7a47f993e0c..97e74f16791 100644 --- a/usr.sbin/ppp/ppp/mp.c +++ b/usr.sbin/ppp/ppp/mp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp.c,v 1.2 1998/09/04 18:27:47 brian Exp $ + * $Id: mp.c,v 1.3 1998/10/29 02:21:46 brian Exp $ */ #include <sys/types.h> @@ -774,9 +774,20 @@ mp_SetEnddisc(struct cmdargs const *arg) struct mp *mp = &arg->bundle->ncp.mp; struct in_addr addr; - if (bundle_Phase(arg->bundle) != PHASE_DEAD) { - log_Printf(LogWARN, "set enddisc: Only available at phase DEAD\n"); - return 1; + switch (bundle_Phase(arg->bundle)) { + case PHASE_DEAD: + break; + case PHASE_ESTABLISH: + /* Make sure none of our links are DATALINK_LCP or greater */ + if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { + log_Printf(LogWARN, "enddisc: Only changable before" + " LCP negotiations\n"); + return 1; + } + break; + default: + log_Printf(LogWARN, "enddisc: Only changable at phase DEAD/ESTABLISH\n"); + return 1; } if (arg->argc == arg->argn) { diff --git a/usr.sbin/ppp/ppp/ppp.8 b/usr.sbin/ppp/ppp/ppp.8 index 59202b7580c..1410cb1baae 100644 --- a/usr.sbin/ppp/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.3 1998/09/18 23:28:47 brian Exp $ +.\" $Id: ppp.8,v 1.4 1998/10/29 02:21:46 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 @@ -2090,6 +2084,11 @@ as the client password in Default: Disabled. Enabling this option will tell .Nm to proxy ARP for the peer. +.It proxyall +Default: Disabled. Enabling this will tell +.Nm +to add proxy arp entries for every IP address in all class C or +smaller subnets routed via the tun interface. .It sroutes Default: Enabled. When the .Dq add @@ -2134,6 +2133,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 +2183,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! @@ -2370,12 +2381,18 @@ file. This is replaced with the IP number assigned to the local interface. .It Li PEER_ENDDISC This is replaced with the value of the peers endpoint discriminator. +.It Li PROCESSID +This is replaced with the current process id. .It Li USER This is replaced with the username that has been authenticated with PAP or CHAP. Normally, this variable is assigned only in -direct mode. This value is available irrespective of whether utmp logging is enabled. .El .Pp +These substitutions are also done by the +.Dq set proctitle +command. +.Pp If you wish to pause .Nm while the command executes, use the @@ -2476,6 +2493,66 @@ 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. +.Pp +If only +.Ar addr +is specified, +.Ar bits +defaults to +.Dq 32 +and +.Ar peer +defaults to +.Dq 255.255.255.255 . +This address (the broadcast address) is the only duplicate peer address that +.Nm +allows. +.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 @@ -2659,12 +2736,20 @@ links will stay active until the bundle idle timer expires. If no arguments are given, callback is disabled, otherwise, .Nm will request (or in -.Ar direct -mode, will accept) one of the given protocols. If a request is NAK'd +.Fl direct +mode, will accept) one of the given protocols. In client mode, if a +request is NAK'd .Nm will request another, until no options remain at which point .Nm -will terminate negotiations. +will terminate negotiations. In server mode, +.Nm +will accept any of the given protocols - but the client +.Em must +request one of them. If you wish callback to be optional, you must include +.Ar none +as an option. +.Pp The options are as follows (in this order of preference): .Pp .Bl -tag @@ -2702,7 +2787,7 @@ themselves. If the peer does not wish to do callback at all, .Nm will accept the fact and continue without callback rather than terminating -the connection. +the connection. This is required if you wish callback to be optional. .El .Pp .It set cbcp Op *|number[,number]... Op delay Op retry @@ -3160,6 +3245,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 @@ -3228,6 +3323,17 @@ the maximum number of times specified by below. In .Fl background mode, each number is attempted at most once. +.It set [proc]title Op Ar value +The current process title as displayed by +.Xr ps 1 +is changed according to +.Ar value . +If +.Ar value +is not specified, the original process title is restored. All the +word replacements done by the shell commands (see the +.Dq bg +command above) are done here too. .It set reconnect Ar timeout ntries Should the line drop unexpectedly (due to loss of CD or LQR failure), a connection will be re-established after the given @@ -3241,6 +3347,11 @@ defaults to zero. A value of for .Ar timeout will result in a variable pause, somewhere between 0 and 30 seconds. +.It set recvpipe Op Ar value +This sets the routing table RECVPIPE value. The optimum value is +just over twice the MTU value. If +.Ar value +is unspecified or zero, the default kernel controlled value is used. .It set redial Ar seconds[.nseconds] [attempts] .Nm Ppp can be instructed to attempt to redial @@ -3269,6 +3380,11 @@ should immediately follow the keyword. See the .Dq open description above for further details. +.It set sendpipe Op Ar value +This sets the routing table SENDPIPE value. The optimum value is +just over twice the MTU value. If +.Ar value +is unspecified or zero, the default kernel controlled value is used. .It set server|socket Ar TcpPort|LocalName|none password Op Ar mask This command tells .Nm @@ -3409,6 +3525,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 @@ -3453,11 +3572,11 @@ Read the example configuration files. They are a good source of information. .It Use .Dq help , -.Dq show ? , .Dq alias ? , +.Dq enable ? , .Dq set ? and -.Dq set ? <var> +.Dq show ? to get online information about what's available. .It The following urls contain useful information: diff --git a/usr.sbin/ppp/ppp/route.c b/usr.sbin/ppp/ppp/route.c index 5328f3a4ab8..d5243f2adf3 100644 --- a/usr.sbin/ppp/ppp/route.c +++ b/usr.sbin/ppp/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.1 1998/08/31 00:22:27 brian Exp $ + * $Id: route.c,v 1.2 1998/10/29 02:21:46 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/ppp/systems.c b/usr.sbin/ppp/ppp/systems.c index 22dd1546da7..b16731d4cd3 100644 --- a/usr.sbin/ppp/ppp/systems.c +++ b/usr.sbin/ppp/ppp/systems.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: systems.c,v 1.1 1998/08/31 00:22:28 brian Exp $ + * $Id: systems.c,v 1.2 1998/10/29 02:21:46 brian Exp $ * * TODO: */ @@ -315,8 +315,13 @@ ReadSystem(struct bundle *bundle, const char *name, const char *file, if (*cp == '\0') /* empty / comment */ continue; - if (!indent) /* start of next section */ + if (!indent) { /* start of next section */ + wp = strchr(cp, ':'); + if (doexec && (wp == NULL || wp[1] != '\0')) + log_Printf(LogWARN, "Unindented command (%s line %d) - ignored\n", + filename, linenum); break; + } len = strlen(cp); argc = command_Interpret(cp, len, argv); diff --git a/usr.sbin/ppp/ppp/tun.c b/usr.sbin/ppp/ppp/tun.c index 2043f61925c..353cb0043e3 100644 --- a/usr.sbin/ppp/ppp/tun.c +++ b/usr.sbin/ppp/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.1 1998/08/31 00:22:30 brian Exp $ + * $Id: tun.c,v 1.2 1998/10/29 02:21:46 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 |