diff --git a/.gitignore b/.gitignore index a8237d3..3d1a93b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ nshdoas/*.o nshdoas/compile.c nshdoas/nshdoas nshdoas/parse.c +.depend diff --git a/Makefile b/Makefile index fea4dad..433869b 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,6 @@ # PROG= nsh -SUBDIR += bgpnsh nshdoas - .PHONY: release dist .include "nsh-version.mk" @@ -19,27 +17,79 @@ MANDIR?=${PREFIX}/man/man .endif # For use with flashrd: -#CFLAGS=-O -DDHCPLEASES=\"/flash/dhcpd.leases\" -Wmissing-prototypes -Wformat -Wall -Wpointer-arith -Wbad-function-cast #-W +CFLAGS=-O -DDHCPLEASES=\"/flash/dhcpd.leases\" -Wmissing-prototypes -Wformat -Wall -Wpointer-arith -Wbad-function-cast #-W CFLAGS?=-O -CFLAGS+=-Wmissing-prototypes -Wformat -Wall -Wbad-function-cast -I/usr/local/include #-W -Wpointer-arith +CFLAGS+=-Wmissing-prototypes -Wformat -Wall -Wbad-function-cast -I/usr/local/include -Wno-error -Wno-unused-variable -Wno-implicit-function-declaration -Wno-pointer-sign -Wbad-function-cast -o ${.TARGET} #-W -Wpointer-arith CPPFLAGS+=-DNSH_VERSION=${NSH_VERSION} -SRCS=arp.c compile.c main.c genget.c commands.c bgpcommands.c stats.c kroute.c -SRCS+=ctl.c show.c if.c version.c route.c conf.c complete.c ieee80211.c -SRCS+=bridge.c tunnel.c media.c sysctl.c passwd.c pfsync.c carp.c -SRCS+=trunk.c who.c more.c stringlist.c utils.c sqlite3.c ppp.c prompt.c -SRCS+=nopt.c pflow.c wg.c nameserver.c ndp.c umb.c utf8.c cmdargs.c ctlargs.c -SRCS+=helpcommands.c makeargv.c hashtable.c mantab.c -CLEANFILES+=compile.c mantab.c +OSNAME != uname +.if $(OSNAME) == "OpenBSD" +# bgpnsh and nshdoas needs some porting work, eg: sudo? +# unveil() also is OpenBSD specific +SUBDIR += openbsd/bgpnsh openbsd/nshdoas + +SRCS=openbsd/arp.c openbsd/compile.c openbsd/main.c openbsd/genget.c openbsd/commands.c openbsd/bgpcommands.c openbsd/stats.c openbsd/kroute.c +SRCS+=openbsd/ctl.c openbsd/show.c openbsd/if.c openbsd/version.c openbsd/route.c openbsd/conf.c openbsd/complete.c openbsd/ieee80211.c +SRCS+=openbsd/bridge.c openbsd/tunnel.c openbsd/media.c openbsd/sysctl.c openbsd/passwd.c openbsd/pfsync.c openbsd/carp.c +SRCS+=openbsd/trunk.c openbsd/who.c openbsd/more.c openbsd/stringlist.c openbsd/utils.c openbsd/sqlite3.c openbsd/ppp.c openbsd/prompt.c +SRCS+=openbsd/nopt.c openbsd/pflow.c openbsd/wg.c openbsd/nameserver.c openbsd/ndp.c openbsd/umb.c openbsd/utf8.c openbsd/cmdargs.c openbsd/ctlargs.c +SRCS+=openbsd/helpcommands.c openbsd/makeargv.c openbsd/hashtable.c openbsd/mantab.c +CLEANFILES+=openbsd/compile.c openbsd/mantab.c LDADD=-lutil -ledit -ltermcap -lsqlite3 -L/usr/local/lib #-static -MAN=nsh.8 +openbsd/compile.c: openbsd/compile.sh *.c *.h + cd openbsd; sh ${.CURDIR}/openbsd/compile.sh + +openbsd/mantab.c: openbsd/mantab.sh nsh.8 + cd openbsd; sh ${.CURDIR}/openbsd/mantab.sh ${.CURDIR}/nsh.8 > mantab.c +.endif + +.if $(OSNAME) == "NetBSD" +SRCS=netbsd/ctl.c netbsd/compile.c netbsd/main.c netbsd/genget.c netbsd/commands.c netbsd/more.c netbsd/complete.c netbsd/passwd.c +SRCS+=netbsd/conf.c netbsd/sqlite3.c netbsd/who.c netbsd/version.c +CLEANFILES+=netbsd/compile.c +LDADD=-ledit -ltermcap -lsqlite3 -L/usr/local/lib -static + +NOMAN=1 + +netbsd/compile.c: netbsd/compile.sh + cd netbsd; sh ${.CURDIR}/netbsd/compile.sh +.endif -compile.c: compile.sh *.c *.h - sh ${.CURDIR}/compile.sh +# For Darwin, brew install bmake and run `bmake` +.if $(OSNAME) == "Darwin" +SRCS=darwin/ctl.c darwin/compile.c darwin/main.c darwin/genget.c darwin/commands.c darwin/more.c darwin/complete.c darwin/passwd.c +SRCS+=darwin/conf.c darwin/sqlite3.c darwin/who.c darwin/version.c +CLEANFILES+=darwin/compile.c +LDADD=-ledit -ltermcap -lsqlite3 -L/usr/local/lib -mantab.c: mantab.sh nsh.8 - sh ${.CURDIR}/mantab.sh ${.CURDIR}/nsh.8 > mantab.c +darwin/compile.c: darwin/compile.sh + cd darwin; sh ${.CURDIR}/darwin/compile.sh +.endif + +# For Linux, install bmake and run `bmake` +.if $(OSNAME) == "Linux" +SRCS=linux/ctl.c linux/compile.c linux/main.c linux/genget.c linux/commands.c linux/more.c linux/complete.c linux/passwd.c +SRCS+=linux/conf.c linux/sqlite3.c linux/version.c linux/who.c +CLEANFILES+=linux/compile.c +LDADD=-lbsd -ledit -ltermcap -lsqlite3 -L/usr/local/lib + +linux/compile.c: linux/compile.sh + cd linux; sh ${.CURDIR}/linux/compile.sh +.endif + +.if $(OSNAME) == "FreeBSD" +SRCS=freebsd/ctl.c freebsd/utils.c freebsd/compile.c freebsd/who.c freebsd/main.c freebsd/genget.c freebsd/more.c freebsd/complete.c freebsd/passwd.c +SRCS+=freebsd/conf.c freebsd/version.c freebsd/sqlite3.c +SRCS+=freebsd/commands.c +CLEANFILES+=freebsd/compile.c +LDADD=-ledit -lutil -lpthread -lmemstat -lelf -lkvm -lxo -lm -ltermcap -lsqlite3 -L/usr/lib -L/usr/local/lib + +freebsd/compile.c: freebsd/compile.sh + cd freebsd; sh ${.CURDIR}/freebsd/compile.sh +.endif + +MAN=nsh.8 release: clean sed -i -e "s/_RELEASE=No/_RELEASE=Yes/" ${.CURDIR}/nsh-version.mk diff --git a/darwin/commands.c b/darwin/commands.c new file mode 100644 index 0000000..d3454f1 --- /dev/null +++ b/darwin/commands.c @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2002-2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" +#include "sysctl.h" + +char prompt[128]; + +char line[1024]; +char saveline[1024]; +int margc; +char hname[HSIZE]; +static char hbuf[MAXHOSTNAMELEN]; /* host name */ +static char ifname[IFNAMSIZ]; /* interface name */ +struct intlist *whichlist; + +#define RT_TABLEID_MAX 255 +#define NARGS sizeof(line)/2 /* max arguments in char line[] */ +char *margv[NARGS]; /* argv storage */ +size_t cursor_argc; /* location of cursor in margv */ +size_t cursor_argo; /* offset of cursor margv[cursor_argc] */ + +pid_t child; + +static int quit(void); +static int disable(void); +static int doverbose(int, char**); +static int doediting(int, char**); +static int hostname(int, char **); +static int help(int, char**); +static int shell(int, char*[]); +static int ping(int, char*[]); +static int ping6(int, char*[]); +static int ssh(int, char*[]); +static int telnet(int, char*[]); +static int traceroute(int, char*[]); +static int traceroute6(int, char*[]); +static Command *getcmd(char *); +static void sigalarm(int); +static int show_hostname(int, char **); +static int pr_conf(int, char **); +static int pr_s_conf(int, char **); +static int show_help(int, char **); +static int wr_startup(void); +static int wr_conf(char *); +static int el_burrito(EditLine *, int, char **); + void p_argv(int, char **); +static int flush_history(void); +static int flush_line(char *); +static int flush_help(void); +static int notvalid(void); + +#include "commands.h" + +void sigalarm(int blahfart) +{ + if (child != -1) { + kill(child, SIGKILL); + } +} + +/* + * Quit command + */ + +int +quit(void) +{ + printf("%% Session terminated.\n"); + exit(0); + return 0; +} + +/* + * Data structures and routines for the "show" command. + */ + +Menu showlist[] = { + { "hostname", "Router hostname", CMPL0 0, 0, 0, 0, show_hostname }, + { "version", "Software information", CMPL0 0, 0, 0, 0, version }, + { "users", "System users", CMPL0 0, 0, 0, 0, who }, + { "running-config", "Operating configuration", CMPL0 0, 0, 0, 0, pr_conf }, + { "startup-config", "Startup configuration", CMPL0 0, 0, 0, 0, pr_s_conf }, + { "?", "Options", CMPL0 0, 0, 0, 0, show_help }, + { "help", 0, CMPL0 0, 0, 0, 0, show_help }, + { 0, 0, 0, 0, 0 } +}; + +/* + * Data structures and routines for the "flush" command. + */ + +Menu flushlist[] = { + { "line", "Active user", CMPL0 0, 0, 1, 1, flush_line }, + { "history", "Command history", CMPL0 0, 0, 0, 0, flush_history }, + { "?", "Options", CMPL0 0, 0, 0, 0, flush_help }, + { "help", 0, CMPL0 0, 0, 0, 0, flush_help }, + { 0, 0, 0, 0, 0 } +}; + +static int +flush_line(char *line) +{ + char *argv[] = { PKILL, "-9", "-t", line, NULL }; + cmdargs(PKILL, argv); + return (1); +} + +static int +flush_help(void) +{ + Menu *f; + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'flush' commands are:\n\n"); + + for (f = flushlist; f->name; f++) { + if (strlen(f->name) > z) + z = strlen(f->name); + } + + for (f = flushlist; f->name; f++) { + if (f->help) + printf(" %-*s %s\n", z, f->name, f->help); + } + return 0; +} + +static int +showcmd(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + int success = 0; + + if (argc < 2) { + show_help(argc, argv); + return 0; + } + + /* + * Validate show argument + */ + s = (Menu *) genget(argv[1], (char **) showlist, sizeof(Menu)); + if (s == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(s)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + if (((s->minarg + 2) > argc) || ((s->maxarg + 2) < argc)) { + printf("%% Wrong number of argument%s to 'show %s' command" + " (min %i, max %i)\n", argc <= 2 ? "" : "s", s->name, + s->minarg, s->maxarg); + return 0; + } + if (s->handler) /* As if there was something else we do ? */ + success = (*s->handler)(argc, argv); + + return(success); +} + +static int +show_help(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'show' commands are:\n\n"); + + for (s = showlist; s->name; s++) { + if (strlen(s->name) > z) + z = strlen(s->name); + } + + for (s = showlist; s->name; s++) { + if (s->help) + printf(" %-*s %s\n", z, s->name, s->help); + } + return 0; +} + +/* + * Data structures and routines for the main CLI + */ + +static char + hostnamehelp[] = "Set system hostname", + interfacehelp[] = "Modify interface parameters", + rtablehelp[] = "Routing table switch", + grouphelp[] = "Modify group attributes", + arphelp[] = "Static ARP set", +#ifdef notyet + parphelp[] = "Proxy ARP set", +#endif + pfhelp[] = "Packet filter control", + ospfhelp[] = "OSPF control", + ospf6help[] = "OSPF6 control", + eigrphelp[] = "EIGRP control", + bgphelp[] = "BGP control", + riphelp[] = "RIP control", + ldphelp[] = "LDP control", + relayhelp[] = "Relay control", + ipsechelp[] = "IPsec IKEv1 control", + ikehelp[] = "IPsec IKEv2 control", + rtadvhelp[] = "Router advertisement control", + dvmrphelp[] = "DVMRP control", + sasynchelp[] = "SA synchronization control", + dhcphelp[] = "DHCP server control", + snmphelp[] = "SNMP server control", + smtphelp[] = "SMTP server control", + ldaphelp[] = "LDAP server control", + sshdhelp[] = "SSH server control", + ntphelp[] = "NTP synchronization control", + nppphelp[] = "PPP server control", + ifstatehelp[] = "ifstate server control", + ftpproxyhelp[] ="ftp-proxy server control", + tftpproxyhelp[] ="tftp-proxy server control", + tftphelp[] = "TFTP server control", + dnshelp[] = "DNS rule control", + motdhelp[] = "Message of-the-day", + inethelp[] = "Inet super-server control", + bridgehelp[] = "Modify bridge parameters", + showhelp[] = "Show system information", + iphelp[] = "Set IP networking parameters", + ip6help[] = "Set IPv6 networking parameters", + mplshelp[] = "Set MPLS network parameters", + ddbhelp[] = "Set DDB parameters", + pipexhelp[] = "Set PIPEX parameters", + flushhelp[] = "Flush system tables", + enablehelp[] = "Enable privileged mode", + disablehelp[] = "Disable privileged mode", + pinghelp[] = "Send IPv4 ICMP echo request", + ping6help[] = "Send IPv6 ICMP echo request", + tracerthelp[] = "Print the route to IPv4 host", + tracert6help[] ="Print the route to IPv6 host", + sshhelp[] = "SSH connection to remote host", + telnethelp[] = "Telnet connection to remote host", + quithelp[] = "Close current connection", + verbosehelp[] = "Set verbose diagnostics", + editinghelp[] = "Set command line editing", + whohelp[] = "Display system users", + shellhelp[] = "Invoke a subshell", + savehelp[] = "Save the current configuration", + nreboothelp[] = "Reboot the system", + halthelp[] = "Halt the system", + helphelp[] = "Print help information"; + +/* + * Primary commands, will be included in help output + */ + +#define ssctl sizeof(struct ctl) +Command cmdtab[] = { + { "hostname", hostnamehelp, CMPL0 0, 0, hostname, 1, 0, 0 }, + { "show", showhelp, CMPL(ta) (char **)showlist, sizeof(Menu), showcmd, 0, 0, 0 }, + { "enable", enablehelp, CMPL0 0, 0, enable, 0, 0, 0 }, + { "disable", disablehelp, CMPL0 0, 0, disable, 1, 0, 0 }, + { "ping", pinghelp, CMPL0 0, 0, ping, 0, 0, 0 }, + { "ping6", ping6help, CMPL0 0, 0, ping6, 0, 0, 0 }, + { "traceroute", tracerthelp, CMPL0 0, 0, traceroute, 0, 0, 0 }, + { "traceroute6", tracert6help, CMPL0 0, 0, traceroute6, 0, 0, 0 }, + { "ssh", sshhelp, CMPL0 0, 0, ssh, 0, 0, 0 }, + { "telnet", telnethelp, CMPL0 0, 0, telnet, 0, 0, 0 }, + { "write-config", savehelp, CMPL0 0, 0, wr_startup, 1, 0, 0 }, + { "verbose", verbosehelp, CMPL0 0, 0, doverbose, 0, 1, 0 }, + { "editing", editinghelp, CMPL0 0, 0, doediting, 0, 1, 0 }, + { "who", whohelp, CMPL0 0, 0, who, 0, 0, 0 }, + { "!", shellhelp, CMPL0 0, 0, shell, 1, 0, 0 }, + { "?", helphelp, CMPL(C) 0, 0, help, 0, 0, 0 }, + { "quit", quithelp, CMPL0 0, 0, quit, 0, 0, 0 }, + { "help", 0, CMPL(C) 0, 0, help, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +/* + * These commands escape ambiguous check and help listings + */ + +static Command cmdtab2[] = { + { "config", 0, CMPL0 0, 0, notvalid, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +Command * +getcmd(char *name) +{ + Command *cm; + + if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + +void +makeargv() +{ + char *cp, *cp2, *base, c; + char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + /* save for shell command */ + strlcpy(saveline, line, sizeof(saveline)); + + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while ((c = *cp)) { + int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + cursor_argc = margc += 1; + base = cp; + for (cursor_argo = 0, cp2 = cp; c != '\0'; + cursor_argo = (cp + 1) - base, c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) { + cursor_argo = 0; + break; + } + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') { + cursor_argc--; + break; + } + cp++; + } + *argp++ = 0; + if (cursor_pos == line) { + cursor_argc = 0; + cursor_argo = 0; + } +} + +void +command() +{ + Command *c; + u_int num; + + if (editing) { + inithist(); + initedit(); + } + + for (;;) { + if (!editing) { + printf("%s", cprompt()); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + printf("\n"); + (void) quit(); + /* NOTREACHED */ + } + break; + } + } else { + const char *buf; + cursor_pos = NULL; + + if ((buf = el_gets(elc, &num)) == NULL || num == 0) + break; + + if (buf[--num] == '\n') { + if (num == 0) + break; + } + if (num >= sizeof(line)) { + printf("%% Input exceeds permitted length\n"); + break; + } + memcpy(line, buf, (size_t)num); + line[num] = '\0'; + history(histc, &ev, H_ENTER, buf); + } + + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + if (NO_ARG(margv[0])) + c = getcmd(margv[1]); + else + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("%% Ambiguous command\n"); + continue; + } + if (c == 0) { + int val = 1; + + if (editing) + val = el_burrito(elc, margc, margv); + if (val) + printf("%% Invalid command\n"); + continue; + } + if (NO_ARG(margv[0]) && ! c->nocmd) { + printf("%% Invalid command: %s %s\n", margv[0], + margv[1]); + continue; + } + if (c->needpriv != 0 && priv != 1) { + printf("%% Privilege required\n"); + continue; + } + if (c->modh) + strlcpy(hname, c->name, HSIZE); + if ((*c->handler) (margc, margv, 0)) { + break; + } + } +} + +/* + * Help command. + */ +static int +help(int argc, char **argv) +{ + Command *c; + + if (argc == 1) { + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% Commands are:\n\n"); + + for (c = cmdtab; c->name; c++) + if (((c->needpriv && priv) || !c->needpriv) + && strlen(c->name) > z) + z = strlen(c->name); + for (c = cmdtab; c->name; c++) { + if (c->help && ((c->needpriv && priv) || + !c->needpriv)) + printf(" %-*s %s\n", z, c->name, c->help); + } + return 0; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("%% Ambiguous help command %s\n", arg); + else if (c == (Command *)0) + printf("%% Invalid help command %s\n", arg); + else + printf("%% %s: %s\n", arg, c->help); + } + return 0; +} + +/* + * Hostname command. + */ +int +hostname(int argc, char **argv) +{ + argv++; + argc--; + + if (argc > 1) { + printf("%% Invalid arguments\n"); + return 1; + } + + if (argc == 1) { + if (sethostname(*argv, strlen(*argv))) + printf("%% sethostname: %s\n", strerror(errno)); + } else + show_hostname(0, NULL); + return 0; +} + +int show_hostname(int argc, char **argv) +{ + if (gethostname(hbuf, sizeof(hbuf))) + printf("%% gethostname: %s\n", strerror(errno)); + else + printf("%s\n", hbuf); + + return 0; +} + +/* + * Shell command. + */ +int +shell(int argc, char **argv) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + /* + * Fire up the shell in the child. + */ + char *shellp; + char *shellname = shellp = "/bin/sh"; + + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], + (char *)NULL); + else + execl(shellp, shellname, (char *)NULL); + printf("%% execl failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for shell to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * ping command. + */ +int +ping(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING, argv); + } + return 0; +} + +int +ping6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING6, argv); + } + return 0; +} + +/* + * telnet command. + */ +int +telnet(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TELNET, argv); + } + return 0; +} + +/* + * ssh command. + */ +int +ssh(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(SSH, argv); + } + return 0; +} + +/* + * traceroute command. + */ +int +traceroute(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT, argv); + } + return 0; +} + +int +traceroute6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT6, argv); + } + return 0; +} + +int +argvtostring(int argc, char **argv, char *string, int strlen) +{ + int i, j; + + for (i = 0, j = 0; argc && i < (strlen - 1); i++) { + if (argv[0][j] == '\0') { + argc--, argv++; + string[i] = ' '; + j = 0; + continue; + } + string[i] = argv[0][j]; + j++; + } + if (i > 0) + i--; + string[i] = '\0'; + + return i; +} + +/* + * cmd, multiple args + */ +int +cmdargs(char *cmd, char *arg[]) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + char *shellp = cmd; + + execv(shellp, arg); + printf("%% execv failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for cmd to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * disable privileged mode + */ +int +disable(void) +{ + priv = 0; + return 0; +} + +int +notvalid(void) +{ + printf("%% The command you entered is not necessary with this" + " software.\n"); + + return(0); +} + +/* + * verbose diagnostics + */ +int +doverbose(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + verbose = 0; + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + verbose = 1; + } + + printf("%% Diagnostic mode %s\n", verbose ? "enabled" : "disabled"); + + return 0; +} + +int +doediting(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + endedit(); + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + initedit(); + } + + printf("%% Command line editing %s\n", + editing ? "enabled" : "disabled"); + + return 0; +} + +int +flush_history(void) +{ + if (!editing) { + printf("%% Command line editing not enabled\n"); + return(1); + } + + /* + * Editing mode needs to be reinitialized if the histi/histc + * pointers are going to change..... + */ + endedit(); + endhist(); + inithist(); + initedit(); + + return(0); +} + +void +gen_help(char **x, char *cmdprefix, char *descrsuffix, int szstruct) +{ + /* only for structures starting with char *name; char *help; !! */ + char **y = x; + struct ghs *ghs; + int z = 0; + + printf("%% Arguments may be abbreviated\n\n"); + + while (*y != 0) { + if (strlen(*y) > z) + z = strlen(*y); + y = (char **)((char *)y + szstruct); + } + + while (*x != 0) { + ghs = (struct ghs *)x; + if (ghs->help) + printf(" %s %-*s %s %s\n", cmdprefix, z, *x, + ghs->help, descrsuffix); + x = (char **)((char *)x + szstruct); + } + return; +} + +/* + * read a text file and execute commands + * take into account that we may have mode handlers int cmdtab that + * execute indented commands from the rc file + */ +int +cmdrc(char rcname[FILENAME_MAX]) +{ + Command *c = NULL, *savec = NULL; + FILE *rcfile; + char modhvar[128]; /* required variable in mode handler cmd */ + unsigned int lnum; /* line number */ + u_int z = 0; /* max length of cmdtab argument */ + + if ((rcfile = fopen(rcname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", rcname, strerror(errno)); + return 1; + } + + for (c = cmdtab; c->name; c++) + if (strlen(c->name) > z) + z = strlen(c->name); + c = NULL; + + for (lnum = 1; ; lnum++) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (line[0] == '!') + continue; + /* + * Don't ignore indented comments with pound sign, otherwise + * comments won't be saved into daemon/ctl config files. + */ + if (line[0] == ' ' && line[1] == '!' && savec && savec->modh == 2) + continue; + if (line[0] == ' ') + strlcpy(saveline, line, sizeof(line)); + makeargv(); + if (margv[0] == 0) + continue; + if (line[0] == ' ' && (!savec || savec->modh < 1)) { + printf("%% No mode handler specified before" + " indented command? (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (line[0] != ' ' || (line[0] == ' ' && line[1] != ' ' + && savec && savec->modh == 2)) { + /* + * command was not indented, or indented for a mode 2 + * handler. process normally. + */ + if (NO_ARG(margv[0])) { + c = getcmd(margv[1]); + if (line[0] != ' ') + savec = c; + if (savec && (savec->nocmd == 0)) { + printf("%% Invalid rc command (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } else { + c = getcmd(margv[0]); + if (line[0] != ' ') + savec = c; + if(savec && savec->modh) { + /* + * any mode handler should have + * one value stored, passed on + */ + if (margv[1]) { + strlcpy(hname, c->name, + HSIZE); + strlcpy(modhvar, margv[1], + sizeof(modhvar)); + } else { + printf("%% No argument after" + " mode handler (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } + } + } + if (Ambiguous(c)) { + printf("%% Ambiguous rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (c == 0) { + printf("%% Invalid rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (verbose) { + printf("%% %4s: %*s%10s (line %u) margv ", + savec && savec->modh ? "mode" : "cmd", z, + savec && savec->name ? savec->name : "", + c != savec ? "(sub-cmd)" : "", lnum); + p_argv(margc, margv); + printf("\n"); + } + if (c->modh == 1) + (*c->handler) (margc, margv, modhvar); + else + (*c->handler) (margc, margv, 0); + } + fclose(rcfile); + return 0; +} + +void +p_argv(int argc, char **argv) +{ + int z; + + for (z = 0; z < argc; z++) + printf("%s%s", z ? " " : "[", argv[z]); + printf("]"); + return; +} + +/* + * for the purpose of interface handler routines, 1 here is failure and + * 0 is success + */ +int +el_burrito(EditLine *el, int argc, char **argv) +{ + char *colon; + int val; + + if (!editing) /* Nothing to parse, fail */ + return(1); + + /* + * el_parse will always return a non-error status if someone specifies + * argv[0] with a colon. The idea of the colon is to allow host- + * specific commands, which is really only useful in .editrc, so + * it is invalid here. + */ + colon = strchr(argv[0], ':'); + if (colon) + return(1); + + val = el_parse(el, argc, (const char **)argv); + + if (val == 0) + return(0); + else + return(1); +} + +char * +cprompt(void) +{ + int pr; + char tmp[4]; + + if (cli_rtable) + snprintf(tmp, sizeof(tmp), "%d", cli_rtable); + + gethostname(hbuf, sizeof(hbuf)); + pr = priv | cli_rtable; + snprintf(prompt, sizeof(prompt), "%s%s%s%s%s%s%s%s", hbuf, pr ? "(" : "", + priv ? "p" : "", priv && cli_rtable ? "-" : "", + cli_rtable ? "rtable " : "", cli_rtable ? tmp : "", + pr ?")" : "> ", pr ? "# " : ""); + + return(prompt); +} + +char * +iprompt(void) +{ + gethostname(hbuf, sizeof(hbuf)); + snprintf(prompt, sizeof(prompt), "%s(%s-%s)>", hbuf, + bridge ? "bridge" : "interface", ifname); + + return(prompt); +} + +int +wr_startup(void) +{ + char *argv[] = { SAVESCRIPT, NSHRC_TEMP, '\0' }; + + if (wr_conf(NSHRC_TEMP)) + printf("%% Saving configuration\n"); + else + printf("%% Unable to save configuration: %s\n", + strerror(errno)); + + cmdargs(SAVESCRIPT, argv); + + return(1); +} + +/* + * Save configuration + */ +int +wr_conf(char *fname) +{ + FILE *rchandle; + int error = 1; + + if ((rchandle = fopen(fname, "w")) == NULL) + error = 0; + else { + conf(rchandle); + fclose(rchandle); + } + + return (error); +} + +/* + * Show wrappers + */ +int +pr_conf(int argc, char **argv) +{ + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + if (!wr_conf(NSHRC_TEMP)) { + printf("%% Couldn't generate configuration\n"); + return(0); + } + + more(NSHRC_TEMP); + + return(1); +} + +/* + * Show startup config + */ +int +pr_s_conf(int argc, char **argv) +{ + int ret; + + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + ret = more(NSHRC); + + return(ret); +} + + +char ** +step_optreq(char **xargs, char **args, int argc, char **argv, int skip) +{ + int i; + int fill = 0; /* total fillable arguments */ + int flc = 0; /* number of filled arguments */ + + /* count fillable arguments */ + for (i = 0; i < NOPTFILL - 1; i++) { + if (xargs[i] == OPT || xargs[i] == REQ) + fill++; + if (xargs[i] == NULL) + break; + } + + if (argc - skip > fill) { + printf("%% Superfluous argument: %s\n", argv[skip + fill]); + return NULL; + } + + /* copy xargs to args, replace OPT/REQ args with argv past skip */ + for (i = 0; i < NOPTFILL - 2; i++) { + if (xargs[i] == NULL) { + args[i] = '\0'; + if (i > 1) + /* + * all **args passed must have at least two arguments + * and a terminating NULL. the point of this check + * is to allow the first two arguments to be NULL but + * still fill in fillargs[x] with corresponding NULL + */ + break; + } + if (xargs[i] == OPT || xargs[i] == REQ) { + /* copy from argv to args */ + if (argc - skip - flc > 0) { + args[i] = argv[skip + flc]; + flc++; + } else if (xargs[i] == REQ) { + printf("%% Missing required argument\n"); + return NULL; + } else { + args[i] = '\0'; + break; + } + } else { + /* copy from xargs to args */ + args[i] = xargs[i]; + } + } + + return(args); +} diff --git a/darwin/commands.h b/darwin/commands.h new file mode 100644 index 0000000..ae2476e --- /dev/null +++ b/darwin/commands.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static struct fpf { + char *name; + char *help; + char *cmd; + char *arg; +} fpfs[] = { + { "all", "all PF elements", PFCTL, "-Fall" }, + { "nat", "NAT rules", PFCTL, "-Fnat" }, + { "queue", "queue rules", PFCTL, "-Fqueue" }, + { "filter", "filter rules", PFCTL, "-Frules" }, + { "states", "NAT/filter states", PFCTL, "-Fstate" }, + { "stats", "PF statistics", PFCTL, "-Finfo" }, + { "tables", "PF address tables", PFCTL, "-FTables" }, + { 0, 0, 0, 0 } +}; + +static struct stt { + char *name; + char *help; + void (*handler) (); +} stts[] = { + { 0, 0, 0 } +}; + +struct prot1 { + char *name; + char *help; + char *args[32]; +}; + +struct prot { + char *name; + struct prot1 *table; +}; + +struct prot1 bgcs[] = { + { "announced", "All announced networks", + { BGPCTL, "network", "show", OPT, NULL } }, + { "interfaces", "Interface states", + { BGPCTL, "show", "interfaces", NULL } }, + { "nexthop", "BGP nexthop routes", + { BGPCTL, "show", "nexthop", NULL } }, + { "summary", "Neighbor session states and counters", + { BGPCTL, "show", "summary", OPT, NULL } }, + { "rib", "Routing Information Base", + { BGPCTL, "show", "rib", OPT, OPT, OPT, NULL } }, + { "neighbor", "Detailed peer", + { BGPCTL, "show", "neighbor", REQ, OPT, NULL } }, + { "ip", "IP BGP", + { BGPCTL, "show", "ip", "bgp", OPT, OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 oscs[] = { + { "fib", "Forward Information Base", + { OSPFCTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPFCTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPFCTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPFCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPFCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPFCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 os6cs[] = { + { "fib", "Forward Information Base", + { OSPF6CTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPF6CTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPF6CTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPF6CTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPF6CTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPF6CTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 eics[] = { + { "interfaces", "Interface", + { EIGRPCTL, "show", "interfaces", OPT, OPT, NULL } }, + { "neighbor", "Neighbor", + { EIGRPCTL, "show", "neighbor", OPT, OPT, NULL } }, + { "topology", "Topology", + { EIGRPCTL, "show", "topology", OPT, OPT, NULL } }, + { "traffic", "Traffic", + { EIGRPCTL, "show", "traffic", OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rics[] = { + { "fib", "Forward Information Base", + { RIPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { RIPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbor", + { RIPCTL, "show", "neighbor", NULL } }, + { "rib", "Routing Information Base", + { RIPCTL, "show", "rib", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 lics[] = { + { "fib", "Forward Information Base", + { LDPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { LDPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbors", + { LDPCTL, "show", "neighbor", NULL } }, + { "lib", "Label Information Base", + { LDPCTL, "show", "lib", NULL } }, + { "discovery", "Adjacencies", + { LDPCTL, "show", "discovery", NULL } }, + { "l2vpn", "Pseudowire", + { LDPCTL, "show", "l2vpn", OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 iscs[] = { + { "flows", "Display IPsec flows", + { IPSECCTL, "-sf", NULL } }, + { "sadb", "Display SADB", + { IPSECCTL, "-ss", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 ikcs[] = { + { "monitor", "Monitor internal iked messages", + { IKECTL, "monitor", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dvcs[] = { + { "igmp", "Internet Group Message Protocol", + { DVMRPCTL, "show", "igmp", NULL } }, + { "interfaces", "Interfaces", + { DVMRPCTL, "show", "interfaces", OPT, NULL } }, + { "mfc", "Multicast Forwarding Cache", + { DVMRPCTL, "show", "mfc", OPT, NULL } }, + { "neighbor", "Neighbor", + { DVMRPCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { DVMRPCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { DVMRPCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rlcs[] = { + { "hosts", "hosts", + { RELAYCTL, "show", "hosts", NULL } }, + { "redirects", "redirects", + { RELAYCTL, "show", "redirects", NULL } }, + { "status", "status", + { RELAYCTL, "show", "relays", NULL } }, + { "sessions", "sessions", + { RELAYCTL, "show", "sessions", NULL } }, + { "summary", "summary", + { RELAYCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 smcs[] = { + { "queue", "envelopes in queue", + { SMTPCTL, "show", "queue", NULL } }, + { "runqueue", "envelopes scheduled for delivery", + { SMTPCTL, "show", "runqueue", NULL } }, + { "stats", "runtime statistics", + { SMTPCTL, "show", "stats", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dhcs[] = { + { "leases", "leases", { 0 } }, + { 0, 0, { 0 } } +}; + +struct prot1 ldcs[] = { + { "stats", "statistics counters", + { LDAPCTL, "stats", NULL } }, + { 0, 0, { 0 } } +}; + +/* show yyy zzz */ +struct prot prots[] = { + { "bgp", bgcs }, + { "ospf", oscs }, + { "ospf6", os6cs }, + { "rip", rics }, + { "ike", ikcs }, + { "ipsec", iscs }, + { "ldp", lics }, + { "dvmrp", dvcs }, + { "relay", rlcs }, + { "smtp", smcs }, + { "ldap", ldcs }, + { 0, 0 } +}; diff --git a/compile.sh b/darwin/compile.sh similarity index 100% rename from compile.sh rename to darwin/compile.sh diff --git a/darwin/complete.c b/darwin/complete.c new file mode 100644 index 0000000..51fcbdd --- /dev/null +++ b/darwin/complete.c @@ -0,0 +1,500 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/complete.c,v 1.19 2006/06/23 20:35:25 steven Exp $ */ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +#define ttyout stdout +#define ttyin stdin + +unsigned char complete(EditLine *, int, char **, size_t, char *); + +static int comparstr(const void *, const void *); +static unsigned char complete_ambiguous(char *, int, StringList *, EditLine *); +static unsigned char complete_command(char *, int, EditLine *, char **, int); +static unsigned char complete_subcommand(char *, int, EditLine *, char **, int); +static unsigned char complete_local(char *, int, EditLine *); +static unsigned char complete_ifname(char *, int, EditLine *); +static unsigned char complete_args(struct ghs *, char *, int, EditLine *, + char **, int, int); +static void list_vertical(StringList *); + +unsigned char complt_c(EditLine *, int); +unsigned char complt_i(EditLine *, int); +unsigned char exit_i(EditLine *, int); + +static int +comparstr(const void *a, const void *b) +{ + return (strcmp(*(char **)a, *(char **)b)); +} + +/* + * Determine if complete is ambiguous. If unique, insert. + * If no choices, error. If unambiguous prefix, insert that. + * Otherwise, list choices. words is assumed to be filtered + * to only contain possible choices. + * Args: + * word word which started the match + * list list by default + * words stringlist containing possible matches + */ +static unsigned char +complete_ambiguous(char *word, int list, StringList *words, EditLine *el) +{ + char insertstr[MAXPATHLEN]; + char *lastmatch; + int i, j; + size_t matchlen, wordlen; + + wordlen = strlen(word); + if (words->sl_cur == 0) + return (CC_ERROR); /* no choices available */ + + if (words->sl_cur == 1) { /* only once choice available */ + (void)strlcpy(insertstr, words->sl_str[0], sizeof insertstr); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + + if (!list) { + matchlen = 0; + if ((lastmatch = words->sl_str[0])) + matchlen = strlen(lastmatch); + for (i = 1 ; i < words->sl_cur ; i++) { + for (j = wordlen ; j < strlen(words->sl_str[i]); j++) + if (lastmatch[j] != words->sl_str[i][j]) + break; + if (j < matchlen) + matchlen = j; + } + if (matchlen > wordlen) { + (void)strlcpy(insertstr, lastmatch, matchlen+1); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + /* + * XXX: really want CC_REFRESH_BEEP + */ + return (CC_REFRESH); + } + } + + putc('\n', ttyout); + qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); + list_vertical(words); + return (CC_REDISPLAY); +} + +/* + * Complete a command + */ +static unsigned char +complete_command(char *word, int list, EditLine *el, char **table, int stlen) +{ + char **c; + struct ghs *ghs; + StringList *words; + size_t wordlen; + unsigned char rv; + + if (table == NULL) + return(CC_ERROR); + + words = sl_init(); + wordlen = strlen(word); + + for (c = table; *c != NULL; c = (char **)((char *)c + stlen)) { + ghs = (struct ghs *)c; + if (wordlen > strlen(ghs->name)) + continue; + if (strncmp(word, ghs->name, wordlen) == 0) + sl_add(words, ghs->name); + } + + rv = complete_ambiguous(word, list, words, el); + sl_free(words, 0); + return (rv); +} + +/* + * Complete a (sub)command + */ +static unsigned char +complete_subcommand(char *word, int list, EditLine *el, char **table, int stlen) +{ + struct ghs *ghs = NULL; + + if (table == NULL) + return(CC_ERROR); + + ghs = (struct ghs *)genget(margv[cursor_argc-1], table, stlen); + if (ghs == 0 || Ambiguous(ghs)) + return(CC_ERROR); + + /* + * XXX completion lists that hit subcommand tables don't get more than + * the first CMPL arg tested in complete_args as long as the level + * 0 is passed to complete_args + */ + return(complete_args(ghs, word, list, el, table, stlen, 0)); +} + +/* + * Complete a local file + */ +static unsigned char +complete_local(char *word, int list, EditLine *el) +{ + StringList *words; + char dir[MAXPATHLEN]; + char *file; + DIR *dd; + struct dirent *dp; + unsigned char rv; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '.'; + dir[1] = '\0'; + file = word; + } else { + if (file == word) { + dir[0] = '/'; + dir[1] = '\0'; + } else { + (void)strlcpy(dir, word, (size_t)(file - word) + 1); + } + file++; + } + + if ((dd = opendir(dir)) == NULL) + return (CC_ERROR); + + words = sl_init(); + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(file) > dp->d_namlen) + continue; + if (strncmp(file, dp->d_name, strlen(file)) == 0) { + char *tcp; + + tcp = strdup(dp->d_name); + if (tcp == NULL) + errx(1, "Can't allocate memory for local dir"); + sl_add(words, tcp); + } + } + closedir(dd); + + rv = complete_ambiguous(file, list, words, el); + sl_free(words, 1); + return (rv); +} + +unsigned char +exit_i(EditLine *el, int ch) +{ + printf("\n"); + return CC_EOF; +} + +unsigned char +complt_i(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)whichlist, sizeof(struct intlist), + NULL)); +} + +unsigned char +complt_c(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)cmdtab, sizeof(struct cmd), NULL)); +} + +unsigned char +complete_ifname(char *word, int list, EditLine *el) +{ + StringList *words; + size_t wordlen; + unsigned char rv; + + words = sl_init(); + wordlen = strlen(word); + + struct if_nameindex *ifn_list, *ifnp; + + if ((ifn_list = if_nameindex()) == NULL) + return 0; + + for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { + if (wordlen > strlen(ifnp->if_name)) + continue; + if (strncmp(word, ifnp->if_name, wordlen) == 0) + sl_add(words, ifnp->if_name); + } + + rv = complete_ambiguous(word, list, words, el); + if_freenameindex(ifn_list); + sl_free(words, 0); + return (rv); +} + +/* + * Generic complete routine + */ +unsigned char +complete(EditLine *el, int ch, char **table, size_t stlen, char *arg) +{ + static char word[256]; + static int lastc_argc, lastc_argo; + struct ghs *c; + const LineInfo *lf; + int celems, dolist; + size_t len; + + (void)ch; /* not used */ + lf = el_line(el); + len = lf->lastchar - lf->buffer; + if (len >= sizeof(line)) + return (CC_ERROR); + (void)memcpy(line, lf->buffer, len); + line[len] = '\0'; + cursor_pos = line + (lf->cursor - lf->buffer); + lastc_argc = cursor_argc; /* remember last cursor pos */ + lastc_argo = cursor_argo; + makeargv(); /* build argc/argv of current line */ + + if (margc == 0 || cursor_argo >= sizeof(word)) + return (CC_ERROR); + + dolist = 0; + + /* if cursor and word is same, list alternatives */ + if (lastc_argc == cursor_argc && lastc_argo == cursor_argo + && strncmp(word, margv[cursor_argc], cursor_argo) == 0) + dolist = 1; + else if (cursor_argo) + memcpy(word, margv[cursor_argc], cursor_argo); + word[cursor_argo] = '\0'; + + if (cursor_argc == 0) + return (complete_command(word, dolist, el, table, stlen)); + + if (arg == NULL) + arg = margv[0]; + c = (struct ghs *) genget(arg, table, stlen); + if (c == (struct ghs *)-1 || c == 0 || Ambiguous(c)) + return (CC_ERROR); + celems = strlen(c->complete); + + /* check for 'continuation' completes (which are uppercase) */ + if ((cursor_argc > celems) && (celems > 0) + && isupper((unsigned char)c->complete[celems-1])) + cursor_argc = celems; + + if (cursor_argc > celems) + return (CC_ERROR); + + return(complete_args(c, word, dolist, el, table, stlen, + cursor_argc - 1)); +} + +unsigned char +complete_args(struct ghs *c, char *word, int dolist, EditLine *el, char **table, + int stlen, int level) +{ +#ifdef CMPLDEBUG + printf("[%s]",&c->complete[level]); +#endif + switch (c->complete[level]) { + case 'l': /* local complete */ + case 'L': + return (complete_local(word, dolist, el)); + case 'c': /* command complete */ + case 'C': + return (complete_command(word, dolist, el, table, stlen)); + case 'i': + case 'I': + return (complete_ifname(word, dolist, el)); + case 't': /* points to a table */ + case 'T': + if (c->table == NULL) + return(CC_ERROR); + return (complete_command(word, dolist, el, c->table, c->stlen)); + case 'a': + case 'A': + if (c->table == NULL) + return(CC_ERROR); + return (complete_subcommand(word, dolist, el, c->table, c->stlen)); + case 'n': /* no complete */ + return (CC_ERROR); + } + + return (CC_ERROR); +} + +/* + * List words in stringlist, vertically arranged + */ +void +list_vertical(StringList *sl) +{ + int i, j, w; + int columns, width, lines; + char *p; + + width = 0; + + for (i = 0 ; i < sl->sl_cur ; i++) { + w = strlen(sl->sl_str[i]); + if (w > width) + width = w; + } + width = (width + 8) &~ 7; + + columns = 1; + if (columns == 0) + columns = 1; + lines = (sl->sl_cur + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + p = sl->sl_str[j * lines + i]; + if (p) + fputs(p, ttyout); + if (j * lines + i + lines >= sl->sl_cur) { + putc('\n', ttyout); + break; + } + if (p) + w = strlen(p); + else + w = 0; + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } + } + } +} + +/* + * this needs to be called before initedit() + */ +void +inithist() +{ + if (!histc) { + histc = history_init(); /* init the builtin history */ + history(histc, &ev, H_SETSIZE, 100); /* remember 100 events */ + } + if (!histi) { + histi = history_init(); + history(histi, &ev, H_SETSIZE, 100); + } +} + +void +endhist() +{ + if (histc) { + history_end(histc); /* deallocate */ + histc = NULL; + } + if (histi) { + history_end(histi); + histi = NULL; + } +} + +void +initedit() +{ + editing = 1; + + if (!elc) { + elc = el_init(__progname, stdin, stdout, stderr); + if (histc) + el_set(elc, EL_HIST, history, histc); /* use history */ + el_set(elc, EL_EDITOR, "emacs"); /* default type */ + el_set(elc, EL_PROMPT, cprompt); /* set the prompt + * function */ + el_set(elc, EL_ADDFN, "complt_c", "Command completion", + complt_c); + el_set(elc, EL_BIND, "\t", "complt_c", NULL); + el_source(elc, NULL); /* read ~/.editrc */ + el_set(elc, EL_SIGNAL, 1); + } + if (!eli) { + eli = el_init(__progname, stdin, stdout, stderr); + if (histi) + el_set(eli, EL_HIST, history, histi); + el_set(eli, EL_EDITOR, "emacs"); + el_set(eli, EL_PROMPT, iprompt); + el_set(eli, EL_ADDFN, "complt_i", "Command completion", + complt_i); + el_set(eli, EL_BIND, "\t", "complt_i", NULL); + el_set(eli, EL_ADDFN, "exit_i", "Exit", exit_i); + el_set(eli, EL_BIND, "^X", "exit_i", NULL); + el_set(eli, EL_BIND, "^D", "exit_i", NULL); + el_source(eli, NULL); + el_set(eli, EL_SIGNAL, 1); + } +} + +void +endedit() +{ + editing = 0; + + if (elc) { + el_end(elc); + elc = NULL; + } + if (eli) { + el_end(eli); + eli = NULL; + } +} diff --git a/darwin/conf.c b/darwin/conf.c new file mode 100644 index 0000000..30df557 --- /dev/null +++ b/darwin/conf.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2002-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +void conf_db_single(FILE *, char *, char *, char *); +void conf_ctl(FILE *, char *, char *, int); +int scantext(char *, char *); + +#define TMPSIZ 1024 /* size of temp strings */ + +int +conf(FILE *output) +{ + char cpass[_PASSWORD_LEN+1]; + char hostbuf[MAXHOSTNAMELEN]; + + fprintf(output, "!\n"); + + gethostname (hostbuf, sizeof(hostbuf)); + fprintf(output, "hostname %s\n", hostbuf); + if (read_pass(cpass, sizeof(cpass))) { + fprintf(output, "enable secret blowfish %s\n", cpass); + } else { + if (errno != ENOENT) + printf("%% Unable to read run-time crypt repository:" + " %s\n", strerror(errno)); + } + fprintf(output, "!\n"); + conf_ctl(output, "", "motd", 0); + + fprintf(output, "!\n"); + + conf_ctl(output, "", "sshd", 0); + + fprintf(output, "!\n"); + + return(0); +} + +void conf_ctl(FILE *output, char *delim, char *name, int rtableid) +{ + FILE *conf; + struct daemons *x; + struct ctl *ctl; + char tmp_str[TMPSIZ], tmpfile[64]; + char *fenablenm = NULL, *fothernm = NULL, *flocalnm = NULL; + int defenable = 0, pntdrules = 0, pntdflag = 0, dbflag; + + x = (struct daemons *)genget(name, (char **)ctl_daemons, + sizeof(struct daemons)); + if (x == 0 || Ambiguous(x)) { + printf("%% conf_ctl: %s: genget internal failure\n", name); + return; + } + + /* print rules if they exist */ + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", x->tmpfile, rtableid); + if ((conf = fopen(tmpfile, "r")) != NULL) { + fprintf(output, "%s%s rules\n", delim, name); + for (;;) { + if(fgets(tmp_str, TMPSIZ, conf) == NULL) + break; + if(tmp_str[0] == 0) + break; + fprintf(output, "%s %s", delim, tmp_str); + } + fclose(conf); + fprintf(output, "%s!\n", delim); + pntdrules = 1; + } else if (errno != ENOENT || (errno == ENOENT && verbose)) + printf("%% conf_ctl: %s: %s\n", tmpfile, strerror(errno)); + + /* fill in argument names from table */ + for (ctl = x->table; ctl != NULL && ctl->name != NULL; ctl++) { + switch(ctl->flag_x) { + case DB_X_ENABLE_DEFAULT: + defenable = 1; + /* FALLTHROUGH */ + case DB_X_ENABLE: + fenablenm = ctl->name; + break; + case DB_X_LOCAL: + flocalnm = ctl->name; + break; + case DB_X_OTHER: + fothernm = ctl->name; + break; + case DB_X_DISABLE: + case DB_X_REMOVE: + case DB_X_DISABLE_ALWAYS: + case 0: + break; + default: + printf("%% conf_ctl: flag_x %d unknown\n", ctl->flag_x); + return; + } + } +} + + +/* find string in file */ +int scantext(char *fname, char *string) +{ + FILE *file; + char line[128]; + int found = 0; + + if ((file = fopen(fname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", fname, strerror(errno)); + return(0); + } + + for (;;) { + if (fgets(line, sizeof(line), file) == NULL) + break; + if (strcmp(line, string) == 0) { + found = 1; + break; + } + } + + fclose(file); + return(found); +} + +void +conf_db_single(FILE *output, char *dbname, char *lookup, char *ifname) +{ + StringList *dbreturn; + dbreturn = sl_init(); + + if (db_select_flag_x_ctl(dbreturn, dbname, ifname) < 0) { + printf("%% conf_db_single %s database select failed\n", dbname); + } + if (dbreturn->sl_cur > 0) { + if (lookup == NULL) + fprintf(output, " %s\n", dbname); + else if (strcmp(dbreturn->sl_str[0], lookup) != 0) + fprintf(output, " %s %s\n", dbname, dbreturn->sl_str[0]); + } + sl_free(dbreturn, 1); +} diff --git a/darwin/ctl.c b/darwin/ctl.c new file mode 100644 index 0000000..ef80ea5 --- /dev/null +++ b/darwin/ctl.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +/* service daemons */ +#define SSHD "/usr/sbin/sshd" + +/* table variable (for pkill usage) */ +static char table[16]; + +/* service routines */ +void call_editor(char *, char **, char *); +void ctl_symlink(char *, char *, char *); +int rule_writeline(char *, mode_t, char *); +int fill_tmpfile(char **, char *, char **); +int acq_lock(char *); +void rls_lock(int); + +/* master daemon list */ +struct daemons ctl_daemons[] = { +{ "sshd", "SSH", ctl_sshd, SSHDCONF_TEMP, 0600, 0, 255 }, +{ 0, 0, 0, 0, 0, 0 } +}; + +/* per-daemon commands, and their C or executable functions */ + +/* MOTD */ +struct ctl ctl_motd[] = { + { "edit", "edit message-of-the-day", + { "motd", NULL, NULL }, call_editor, 0, T_HANDLER }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +/* sshd */ +char *ctl_sshd_test[] = { SSHD, "-tf", REQTEMP, NULL }; +struct ctl ctl_sshd[] = { + { "enable", "enable service", + { SSHD, "-f", REQTEMP, NULL }, NULL, DB_X_ENABLE, T_EXEC }, + { "disable", "disable service", + { PKILL, table, "-f", SSHD, "-f", REQTEMP, NULL }, NULL, + DB_X_DISABLE, T_EXEC }, + { "edit", "edit configuration", + { "sshd", (char *)ctl_sshd_test, NULL }, call_editor, 0, + T_HANDLER_FILL1 }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +void +ctl_symlink(char *temp, char *real, char *z) +{ + rmtemp(temp); + symlink(real, temp); +} + +/* flag to other nsh sessions or nsh conf() that actions have been taken */ +void +flag_x(char *name, char *daemon, int dbflag, char *data) +{ + if (db_delete_flag_x_ctl(name, daemon) < 0) { + printf("%% database delete failure ctl ctl\n"); + return; + } + if (dbflag == DB_X_REMOVE) + return; + if (db_insert_flag_x(name, daemon, cli_rtable, dbflag, data) < 0) { + printf("%% database insert failure ctl ctl\n"); + } +} + +/* the main entry point into ctl.c from CLI */ +int +ctlhandler(int argc, char **argv, char *modhvar) +{ + struct daemons *daemons; + struct ctl *x; + char tmpfile[PATH_MAX]; + char *step_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char *tmp_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char **fillargs; + + /* loop daemon list to find table pointer */ + daemons = (struct daemons *) genget(hname, (char **)ctl_daemons, + sizeof(struct daemons)); + if (daemons == 0) { + printf("%% Internal error - Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(daemons)) { + printf("%% Internal error - Ambiguous argument %s\n", argv[1]); + return 0; + } + + if (cli_rtable > daemons->rtablemax) { + printf("%% Command %s not available via rtable %d\n", + daemons->name, cli_rtable); + return 0; + } + + snprintf(table, sizeof(table), "-T%d", cli_rtable); + if (daemons->tmpfile) + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + if (modhvar) { + /* action specified or indented command specified */ + if (argc == 2 && isprefix(argv[1], "rules")) { + /* skip 'X rules' line */ + return(0); + } + if (isprefix(modhvar, "rules")) { + if (!daemons->tmpfile) { + printf("%% writeline without tmpfile\n"); + return 0; + } + /* write indented line to tmp config file */ + rule_writeline(tmpfile, daemons->mode, saveline); + return 0; + } + } + if (argc < 2 || argv[1][0] == '?') { + gen_help((char **)daemons->table, "", "", sizeof(struct ctl)); + return 0; + } + + x = (struct ctl *) genget(argv[1], (char **)daemons->table, + sizeof(struct ctl)); + if (x == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(x)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + + fillargs = step_optreq(x->args, step_args, argc, argv, 2); + if (fillargs == NULL) + return 0; + + switch(x->type) { + /* fill_tmpfile will return 0 if tmpfile or args are NULL */ + case T_HANDLER: + /* pointer to handler routine, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) { + (*x->handler)(tmp_args[0], tmp_args[1], tmp_args[2]); + } else { + (*x->handler)(fillargs[0], fillargs[1], fillargs[2]); + } + break; + case T_HANDLER_FILL1: + /* pointer to handler routine, fill args @ args[1] pointer */ + if (fill_tmpfile((char **)fillargs[1], tmpfile, tmp_args)) + (*x->handler)(fillargs[0], tmp_args, fillargs[2]); + else + (*x->handler)(fillargs[0], (char **)fillargs[1], fillargs[2]); + break; + case T_EXEC: + /* command to execute via execv syscall, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) + cmdargs(tmp_args[0], tmp_args); + else + cmdargs(fillargs[0], fillargs); + break; + } + + if (x->flag_x != 0) { + flag_x("ctl", daemons->name, x->flag_x, NULL); + } + + return 1; +} + +int +fill_tmpfile(char **fillargs, char *tmpfile, char **tmp_args) +{ + int i; + + if (fillargs == NULL || tmpfile == NULL) + return 0; + + for (i = 0; i < NOPTFILL - 1; i++) { + if(fillargs[i] == NULL) { + break; + } + if(fillargs[i] == REQTEMP) { + tmp_args[i] = tmpfile; + } else { + tmp_args[i] = fillargs[i]; + } + } + return 1; +} + +void +call_editor(char *name, char **args, char *z) +{ + int fd, found = 0; + char *editor, tmpfile[64]; + struct daemons *daemons; + + for (daemons = ctl_daemons; daemons->name != 0; daemons++) + if (strncmp(daemons->name, name, strlen(name)) == 0) { + found = 1; + break; + } + + if (!found) { + printf("%% call_editor internal error\n"); + return; + } + + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + /* acq lock, call editor, test config with cmd and args, release lock */ + if ((editor = getenv("EDITOR")) == NULL) + editor = DEFAULT_EDITOR; + if ((fd = acq_lock(tmpfile)) > 0) { + char *argv[] = { editor, tmpfile, NULL }; + cmdargs(editor, argv); + chmod(tmpfile, daemons->mode); + if (args != NULL) + cmdargs(args[0], args); + rls_lock(fd); + } else + printf ("%% %s configuration is locked for editing\n", + daemons->propername); +} + +int +rule_writeline(char *fname, mode_t mode, char *writeline) +{ + FILE *rulefile; + + rulefile = fopen(fname, "a"); + if (rulefile == NULL) { + printf("%% Rule write failed: %s\n", strerror(errno)); + return(1); + } + if (writeline[0] == ' ') + writeline++; + fprintf(rulefile, "%s", writeline); + fclose(rulefile); + chmod(fname, mode); + return(0); +} + +int +acq_lock(char *fname) +{ + int fd; + char lockf[SIZE_CONF_TEMP + sizeof(".lock")]; + + /* + * some text editors lock (vi), some don't (mg) + * + * here we lock a separate, do-nothing file so we don't interfere + * with the editors that do... (lock multiple concurrent nsh users) + */ + snprintf(lockf, sizeof(lockf), "%s.lock", fname); + if ((fd = open(lockf, O_RDWR | O_CREAT, 0600)) == -1) + return(-1); + if (flock(fd, LOCK_EX | LOCK_NB) == 0) + return(fd); + else { + close(fd); + return(-1); + } +} + +void +rls_lock(int fd) +{ + /* best-effort, who cares */ + flock(fd, LOCK_UN); + close(fd); + return; +} + +void +rmtemp(char *file) +{ + if (unlink(file) != 0) + if (errno != ENOENT) + printf("%% Unable to remove temporary file %s: %s\n", + file, strerror(errno)); +} diff --git a/darwin/editing.h b/darwin/editing.h new file mode 100644 index 0000000..e9bc288 --- /dev/null +++ b/darwin/editing.h @@ -0,0 +1,9 @@ +#include + +extern EditLine *elc; /* editline(3) status structure */ +extern EditLine *eli; /* another one */ +extern History *histc; /* command() editline(3) history structure */ +extern History *histi; /* interface() editline(3) status structure */ +extern char *cursor_pos; /* cursor position we're looking for */ +extern size_t cursor_argc; /* location of cursor in margv */ +extern size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ diff --git a/darwin/externs.h b/darwin/externs.h new file mode 100644 index 0000000..b7fbffe --- /dev/null +++ b/darwin/externs.h @@ -0,0 +1,561 @@ +/* + * nsh externs, prototypes and macros + */ + +#define NO_ARG(x) (strcasecmp(x, "no") == 0) /* absolute "no" */ + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) /* sys/param.h */ + +struct rtdump { + char *buf; /* start of routing table */ + char *lim; /* end of routing table */ +}; + +extern char *__progname; /* duh */ +extern char *vers; /* the version of nsh */ +extern char saveline[1024]; /* command line */ +extern char line[1024]; /* command line for makeargv() */ +extern int margc; /* makeargv() arg count */ +extern char *margv[]; /* makeargv() args */ +extern int verbose; /* is verbose mode on? */ +extern int editing; /* is command line editing mode on? */ +extern int bridge; /* are we in bridge mode (or interface mode?) */ +extern int priv; /* privileged mode or not? */ +//extern pid_t pid; /* process id of nsh */ +extern int cli_rtable; /* environment rtable */ + +#define HSIZE 64 +extern char hname[HSIZE]; /* prefix name to mode handler */ + +#ifdef _HISTEDIT_H_ +extern HistEvent ev; /* ev */ +#endif + +/* defaults */ +#define DEFAULT_MTU 1500 /* net.inet.ip.defmtu */ +#define DEFAULT_TTL 64 /* net.inet.ip.defttl */ +#define DEFAULT_MTTL 255 /* net.mpls.ttl */ +#define ESP_UDPENCAP_PORT 4500 /* net.inet.esp.udpencap_port */ + +/* nopt.c */ +#define no_arg 1 +#define req_arg 2 +struct nopts { + char *name; + int type; + int arg; +}; +extern int noptind; +extern char *nopterr; +int nopt(int, char **, struct nopts *); + +/* ppp.c */ +int intsppp(char *, int, int, char **); +int intpppoe(char *, int, int, char **); +void conf_pppoe(FILE *, int, char *); +void conf_sppp(FILE *, int, char *); + +/* conf.c */ +#define LEASEPREFIX "/var/db/dhclient.leases" +int conf(FILE *); +long default_mtu(char *); +int conf_routes(FILE *, char *, int, int, int); +int conf_dhcrelay(char *, char *, int); + +/* show.c */ +void p_rttables(int, int, int); +#ifdef _NETINET_IN_H_ +char *routename4(in_addr_t); +char *netname4(in_addr_t, struct sockaddr_in *); +#endif +#ifdef _NETINET6_IN6_H_ +char *routename6(struct sockaddr_in6 *); +char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); +void in6_fillscopeid(struct sockaddr_in6 *); +void in6_clearscopeid(struct sockaddr_in6 *); +#endif +#ifdef _SYS_SOCKET_H_ +char *routename(struct sockaddr *); +char *netname(struct sockaddr *, struct sockaddr *); +char *any_ntoa(const struct sockaddr *); +#endif + +/* alignment constraint for routing socket */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +/* routesys.c */ +#ifdef _NET_ROUTE_H_ +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; +#endif +#ifdef _WANT_SO_ +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + struct sockaddr_inarp sinarp; +}; +extern union sockunion so_dst, so_mask, so_gate, so_ifp; +#endif +#ifdef _NETINET6_IN6_H_ +int prefixlen(int, struct sockaddr_in6 *); +#endif +extern int rtm_addrs; +extern long rtm_inits; +#define FLUSH 0 +struct rtdump *getrtdump(int, int, int); +void freertdump(struct rtdump *); +int monitor(int, char **); +int rtmsg(int, int, int, int, int); +void flushroutes(int, int); +void bprintf(FILE *, int, char *); +#ifdef _NET_IF_DL_H_ +char *mylink_ntoa(const struct sockaddr_dl *); +#endif +extern char ifnetflags[]; +extern char routeflags[]; +extern char addrnames[]; +extern char metricnames[]; + +/* ctl.c */ +/* tmp config locations */ +#define PFCONF_TEMP "/var/run/pf.conf" +#define OSPFCONF_TEMP "/var/run/ospfd.conf" +#define OSPF6CONF_TEMP "/var/run/ospf6d.conf" +#define EIGRPCONF_TEMP "/var/run/eigrpd.conf" +#define BGPCONF_TEMP "/var/run/bgpd.conf" +#define RIPCONF_TEMP "/var/run/ripd.conf" +#define LDPCONF_TEMP "/var/run/ldpd.conf" +#define IPSECCONF_TEMP "/var/run/ipsec.conf" +#define IKECONF_TEMP "/var/run/iked.conf" +#define DVMRPCONF_TEMP "/var/run/dvmrpd.conf" +#define RTADVCONF_TEMP "/var/run/rtadvd.conf" +#define RELAYCONF_TEMP "/var/run/relayd.conf" +#define SASYNCCONF_TEMP "/var/run/sasyncd.conf" +#define DHCPCONF_TEMP "/var/run/dhcpd.conf" +#define SNMPCONF_TEMP "/var/run/snmpd.conf" +#define NTPCONF_TEMP "/var/run/ntpd.conf" +#define IFSTATE_TEMP "/var/run/ifstated.conf" +#define NPPPCONF_TEMP "/var/run/npppd.conf" +#define FTPPROXY_TEMP "/var/run/ftp-proxy" +#define TFTPPROXY_TEMP "/var/run/tftp-proxy" +#define TFTP_TEMP "/var/run/tftpd" +#define RESOLVCONF_TEMP "/var/run/resolv.conf" +#define RESOLVCONF_SYM "/var/run/resolv.conf.symlink" +#define RESOLVCONF_DHCP "/var/run/resolv.conf.dhcp" +#define INETCONF_TEMP "/var/run/inetd.conf" +#define SSHDCONF_TEMP "/var/run/sshd.conf" +#define SMTPCONF_TEMP "/var/run/smtpd.conf" +#define LDAPCONF_TEMP "/var/run/ldapd.conf" +#define IFSTATECONF_TEMP "/var/run/ifstated.conf" +#define MOTD_TEMP "/var/run/motd" + +/* argument list replacement */ +#define OPT (void *)1 +#define REQ (void *)2 +#define IFNAME (void *)3 +#define REQTEMP (void *)4 +#define SIZE_CONF_TEMP 64 +int ctlhandler(int, char **, char *); +void rmtemp(char *); +/* control programs */ +#define PFCTL "/sbin/pfctl" +#define OSPFCTL "/usr/sbin/ospfctl" +#define OSPF6CTL "/usr/sbin/ospf6ctl" +#define EIGRPCTL "/usr/sbin/eigrpctl" +#define BGPCTL "/usr/sbin/bgpctl" +#define RIPCTL "/usr/sbin/ripctl" +#define LDPCTL "/usr/sbin/ldpctl" +#define IPSECCTL "/sbin/ipsecctl" +#define IKECTL "/usr/sbin/ikectl" +#define DVMRPCTL "/usr/sbin/dvmrpctl" +#define RELAYCTL "/usr/sbin/relayctl" +#define SNMPCTL "/usr/sbin/snmpctl" +#define SMTPCTL "/usr/sbin/smtpctl" +#define LDAPCTL "/usr/sbin/ldapctl" +struct ctl { + char *name; + char *help; + char *args[32]; + void (*handler)(); + int flag_x; + int type; +}; +#define T_HANDLER 1 +#define T_HANDLER_FILL1 2 +#define T_EXEC 3 +struct daemons { + char *name; + char *propername; + struct ctl *table; + char *tmpfile; + mode_t mode; + int doreload; + int rtablemax; +}; +extern struct daemons ctl_daemons[]; +extern struct ctl ctl_pf[]; +extern struct ctl ctl_ospf[]; +extern struct ctl ctl_ospf6[]; +extern struct ctl ctl_eigrp[]; +extern struct ctl ctl_relay[]; +extern struct ctl ctl_bgp[]; +extern struct ctl ctl_rip[]; +extern struct ctl ctl_ldp[]; +extern struct ctl ctl_ipsec[]; +extern struct ctl ctl_nppp[]; +extern struct ctl ctl_ifstate[]; +extern struct ctl ctl_ike[]; +extern struct ctl ctl_dvmrp[]; +extern struct ctl ctl_rtadv[]; +extern struct ctl ctl_sasync[]; +extern struct ctl ctl_dhcp[]; +extern struct ctl ctl_snmp[]; +extern struct ctl ctl_smtp[]; +extern struct ctl ctl_sshd[]; +extern struct ctl ctl_ntp[]; +extern struct ctl ctl_ftpproxy[]; +extern struct ctl ctl_tftpproxy[]; +extern struct ctl ctl_tftp[]; +extern struct ctl ctl_dns[]; +extern struct ctl ctl_inet[]; +extern struct ctl ctl_ldap[]; +extern struct ctl ctl_motd[]; +void flag_x(char *, char *, int, char *); + +/* commands.c */ +#define NOPTFILL 7 +#define DEFAULT_EDITOR "/usr/bin/vi" +#define NSHRC_TEMP "/var/run/nshrc" +#define NSHRC "/etc/nshrc" +#define PING "/sbin/ping" +#define PING6 "/sbin/ping6" +#define TRACERT "/usr/sbin/traceroute" +#define TRACERT6 "/usr/sbin/traceroute6" +#define TELNET "/usr/bin/telnet" +#define SSH "/usr/bin/ssh" +#define PKILL "/usr/bin/pkill" +#define SAVESCRIPT "/usr/local/bin/save.sh" +#ifndef DHCPLEASES +#define DHCPLEASES "/var/db/dhcpd.leases" +#endif +void command(void); +char **step_optreq(char **, char **, int, char **, int); +int argvtostring(int, char **, char *, int); +int cmdrc(char rcname[FILENAME_MAX]); +int cmdargs(char *, char **); +char *iprompt(void); +char *cprompt(void); +char *pprompt(void); +int group (int, char **); +void gen_help(char **, char *, char *, int); +void makeargv(void); +extern size_t cursor_argc; +extern size_t cursor_argo; + +typedef struct cmd { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler) (); /* routine which executes command */ + int needpriv; /* Do we need privilege to execute? */ + int nocmd; /* Can we specify 'no ...command...'? */ + int modh; /* Is it a mode handler for cmdrc()? */ +} Command; + +typedef struct menu { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int minarg; /* Minimum number of arguments */ + int maxarg; /* Maximum number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ +} Menu; + +struct intlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler)(); /* Routine to perform (for special ops) */ + int bridge; /* 0 == Interface, 1 == Bridge, 2 == Both */ +}; + +/* generic help /complt struct */ +struct ghs { + char *name; + char *help; + char *complete; + char **table; + int stlen; +}; + +extern Command cmdtab[]; +extern struct intlist Intlist[]; +extern struct intlist Bridgelist[]; +extern struct intlist *whichlist; + +/* ieee80211.c */ +#define NWID 0 +#define NWKEY 1 +#define POWERSAVE 2 +#define TXPOWER 3 +#define BSSID 4 +#define DEFAULT_POWERSAVE 100 /* 100 ms */ +const char *get_string(const char *, const char *, __int8_t *, int *); +void make_string(char *str, int, const __int8_t *buf, int); +int get_nwinfo(char *, char *, int, int); +int get_nwpowersave(int, char *); +int intnwkey(char *, int, int, char **); +int inttxpower(char *, int, int, char **); +int intbssid(char *, int, int, char **); + +/* stats.c */ +void rt_stats(void); +void tcp_stats(void); +void udp_stats(void); +void ip_stats(void); +void icmp_stats(void); +void igmp_stats(void); +void ah_stats(void); +void esp_stats(void); +void ipip_stats(void); +void carp_stats(void); +void pfsync_stats(void); +void ipcomp_stats(void); + +/* mbuf.c */ +void mbpr(void); + +/* kread.c */ +char *plural(int); +char *plurales(int); + +/* genget.c */ +int isprefix(char *, char*); +char **genget(char *, char **, int); +int Ambiguous(void *); + +/* sysctl.c */ +int sysctl_int(int[], int, int); +int ipsysctl(int, char *, char *, int); +void conf_sysctls(FILE *); + +/* route.c */ +#define NO_NETMASK 0 +#define ASSUME_NETMASK 1 +int route(int, char**); +void show_route(char *, int); +int is_ip_addr(char *); +#ifdef _IP_T_ +void parse_ip_pfx(char *, int, ip_t *); +int ip_route(ip_t *, ip_t *, u_short, int, int, struct rt_metrics, int inits); +#endif +#ifdef _NETINET6_IN6_H_ +int parse_ipv6(char *, struct in6_addr *); +#endif + +/* if.c */ +#define DHCLIENT "/sbin/dhclient" +#define DHCRELAY "/usr/sbin/dhcrelay" +#define RTADVD "/usr/sbin/rtadvd" +#define IFDATA_MTU 1 /* request for if_data.ifi_mtu */ +#define IFDATA_BAUDRATE 2 /* request for if_data.ifi_baudrate */ +#define MBPS(bps) (bps / 1000 / 1000) +#define ROUNDMBPS(bps) ((float)bps == ((bps / 1000 / 1000) * 1000 * 1000)) +#define ROUNDKBPS(bps) ((float)bps == ((bps / 1000) * 1000)) +#define ROUNDKBYTES(bytes) ((float)bytes == ((bytes / 1024) * 1024)) +void imr_init(char *); +int is_valid_ifname(char *); +int show_int(int, char **); +int get_rdomain(int, char *); +int get_ifdata(char *, int); +int get_ifflags(char *, int); +int set_ifflags(char *, int, int); +int get_ifxflags(char *, int); +int set_ifxflags(char *, int, int); +int intip(char *, int, int, char **); +int intmtu(char *, int, int, char **); +int intkeepalive(char *, int, int, char **); +int intmpelabel(char *, int, int, char **); +int intrdomain(char *, int, int, char **); +int intdhcrelay(char *, int, int, char **); +int intmetric(char *, int, int, char **); +int intrtd(char *, int, int, char **); +int intvlan(char *, int, int, char **); +int intflags(char *, int, int, char **); +int intxflags(char *, int, int, char **); +int intaf(char *, int, int, char **); +int intlink(char *, int, int, char **); +int intnwid(char *, int, int, char **); +int intpowersave(char *, int, int, char **); +int intdesc(char *, int, int, char **); +int intpflow(char *, int, int, char **); +int intlladdr(char *, int, int, char **); +int intgroup(char *, int, int, char **); +int intrtlabel(char *, int, int, char **); +int intparent(char *, int, int, char **); +int intpatch(char *, int, int, char **); +int intmpw(char *, int, int, char **); +int addaf(char *, int, int); +int removeaf(char *, int, int); +char *get_hwdaddr(char *); + +/* main.c */ +void intr(void); + +/* version.c */ +int version(int, char **); + +/* compile.c */ +extern char compiled[], compiledby[], compiledon[], compilehost[]; + +/* bridge.c */ +long bridge_cfg(int, char *, int); +int bridge_confaddrs(int, char *, char *, FILE *); +int bridge_rules(int, char *, char *, char *, FILE *); +int bridge_list(int, char *, char *, char *, int, int); +int bridge_addrs(int, char *, char *, char *); +int set_ifflag(int, char *, short); +int clr_ifflag(int, char *, short); +int is_bridge(int, char *); +int brport(char *, int, int, char **); +int brval(char *, int, int, char **); +int brrule(char *, int, int, char **); +int brstatic(char *, int, int, char **); +int brpri(char *, int, int, char **); +int flush_bridgedyn(char *); +int flush_bridgeall(char *); +int flush_bridgerule(char *, char*); + +/* tunnel.c */ +int inttunnel(char *, int, int, char **); +int intvnetid(char *, int, int, char **); +int get_physrtable(int, char *); +int get_physttl(int, char *); +int get_vnetid(int, char *); + +/* media.c */ +#define DEFAULT_MEDIA_TYPE "autoselect" +void media_status(int, char *, char *); +void media_supported(int, char *, char *, char *); +int phys_status(int, char *, char *, char *, int, int); +int intmedia(char *, int, int, char **); +int intmediaopt(char *, int, int, char **); +int conf_media_status(FILE *, int, char *); + +/* passwd.c */ +#define NSHPASSWD_TEMP "/var/run/nshpasswd" +int read_pass(char *, size_t); +int gen_salt(char *, size_t); +int enable(int, char **); + +/* pfsync.c */ +#define PFSYNC_MAXUPDATES 128 +int intsyncdev(char *, int, int, char **); +int intsyncpeer(char *, int, int, char **); +int intmaxupd(char *, int, int, char **); +int conf_pfsync(FILE *, int, char *); + +/* carp.c */ +#define CARP_ADVSKEW 0 +#define CARP_ADVBASE 1 +#define CARP_VHID 2 +#define CARP_PEER 3 +#define CARP_BALANCING 4 +int intcarp(char *, int, int, char **); +int intcpass(char *, int, int, char **); +int intcnode(char *, int, int, char **); +int conf_carp(FILE *, int, char *); +int carp_state(int, char *); +int intcdev(char *, int, int, char **); + +/* trunk.c */ +int inttrunkport(char *, int, int, char **); +int inttrunkproto(char *, int, int, char **); +int conf_trunk(FILE *output, int ifs, char *ifname); +void show_trunk(int ifs, char *ifname); + +/* who.c */ +int who(int, char **); + +/* arp.c */ +int arpget(const char *); +int arpset(int, char **); +void arpdump(void); +void conf_arp(FILE *, char *); +//char *sec2str(time_t); + +/* more.c */ +int more(char *); +int nsh_cbreak(void); +void nsh_nocbreak(void); +void setwinsize(int); +#ifdef _SYS_TTYCOM_H_ +extern struct winsize winsize; +#endif + +/* complete.c */ +#define CMPL(x) __STRING(x), +#define CMPL0 "", +void inithist(void); +void endhist(void); +void initedit(void); +void endedit(void); + +/* utils.c */ +int string_index(char *, char **); +//char *format_time(time_t); +char *format_k(__uint64_t amt); + +/* sqlite3.c */ +/* sqlite3.c */ +#define SQ3DBFILE "/var/run/nsh.db" +#define DB_X_ENABLE 1 /* enable command */ +#define DB_X_DISABLE 2 /* disable command */ +#define DB_X_LOCAL 3 /* local control command */ +#define DB_X_OTHER 4 /* other command */ +#define DB_X_REMOVE 5 /* remove command */ +#define DB_X_ENABLE_DEFAULT 6 /* enable command, always prints enable until disabled */ +#define DB_X_DISABLE_ALWAYS 7 /* disable command, always prints if disabled */ +int db_create_table_rtables(void); +int db_create_table_flag_x(char *); +int db_create_table_nameservers(void); +int db_insert_flag_x(char *, char *, int, int, char *); +int db_insert_rtables(int, char *); +int db_insert_nameserver(char *); +int db_delete_rtables_rtable(int); +int db_delete_flag_x_ctl(char *, char *); +int db_delete_flag_x_ctl_data(char *, char *, char *); +int db_delete_nameservers(void); +#ifdef _STRINGLIST_H +int db_select_flag_x_ctl_data(StringList *, char *, char *, char *); +int db_select_flag_x_ctl(StringList *, char *, char *); +int db_select_rtable_rtables(StringList *); +int db_select_rtables_rtable(StringList *, int); +int db_select_rtables_ctl(StringList *, char *); +int db_select_name_rtable(StringList *, int); +int db_select_flag_x_ctl_rtable(StringList *, char *, int); +int db_select_flag_x_data_ctl_rtable(StringList *, char *, char *, int); +int db_select_nameservers(StringList *); +#endif +int db_select_flag_x_dbflag_rtable(char *, char *, int); + +/* pflow.c */ +#define PFLOW_SENDER 0 +#define PFLOW_RECEIVER 1 +#define PFLOW_VERSION 2 +#ifdef _SYS_SOCKET_H_ +int pflow_addr(const char *, struct sockaddr_storage *); +#endif +int pflow_status(int, int, char *, char *); diff --git a/darwin/genget.c b/darwin/genget.c new file mode 100644 index 0000000..549e785 --- /dev/null +++ b/darwin/genget.c @@ -0,0 +1,99 @@ +/* From: $OpenBSD: genget.c,v 1.5 2001/05/25 10:23:06 hin Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include "externs.h" + +int isprefix(char *, char*); + +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ +int +isprefix(char *s1, char *s2) +{ + char *os1; + char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (tolower((unsigned char)c1) == tolower((unsigned char)c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + +char ** +genget(char *name, char **table, int stlen) + /* name to match */ + /* name entry in table */ + +{ + char **c, **found; + int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ +int +Ambiguous(void *s) +{ + return((char **)s == &ambiguous); +} diff --git a/darwin/main.c b/darwin/main.c new file mode 100644 index 0000000..7fd6984 --- /dev/null +++ b/darwin/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002-2013 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +void usage(void); + +jmp_buf toplevel; + +char *vers = "1.0"; +int bridge = 0; /* bridge mode for interface() */ +int verbose = 0; /* verbose mode */ +int priv = 0, cli_rtable = 0; +int editing = 1; +pid_t pid; + +History *histi = NULL; +History *histc = NULL; +HistEvent ev; +EditLine *elc = NULL; +EditLine *eli = NULL; +char *cursor_pos = NULL; + +void intr(void); + +int +main(int argc, char *argv[]) +{ + int top, ch, iflag = 0, cflag = 0; + char rc[PATH_MAX]; + + if(getuid() != 0) + printf("%% Functionality limited without root privilege.\n"); + + pid = getpid(); + + while ((ch = getopt(argc, argv, "c:i:v")) != -1) + switch (ch) { + case 'c': + cflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'i': + iflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'v': + verbose = 1; + break; + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (cflag && iflag) + usage(); + if (argc > 0) + usage(); + if (iflag) + rmtemp(SQ3DBFILE); + + printf("%% NSH v%s\n", vers); + + if (iflag) { + /* + * Interpret config file and exit + */ + priv = 1; + + /* + * Set carp group carpdemote to 128 during initialization + */ + + cmdrc(rc); + + /* + * Initialization over + */ + + exit(0); + } + if (cflag) { + /* + * Interpret command file and exit + */ + priv = 1; + + cmdrc(rc); + + exit(0); + } + + top = setjmp(toplevel) == 0; + if (top) { + (void)signal(SIGWINCH, setwinsize); + (void)signal(SIGINT, (sig_t)intr); + (void)setwinsize(0); + } else + putchar('\n'); + + for (;;) { + command(); + top = 1; + } + + /* NOTREACHED */ + return 0; +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-v] [-i rcfile | -c rcfile]\n", __progname); + fprintf(stderr, " -v indicates verbose operation\n"); + fprintf(stderr, " -i rcfile loads initial system" \ + " configuration from rcfile\n"); + fprintf(stderr, " -c rcfile loads commands from rcfile\n"); + exit(1); +} + +void +intr(void) +{ + longjmp(toplevel, 1); +} diff --git a/darwin/more.c b/darwin/more.c new file mode 100644 index 0000000..4e037df --- /dev/null +++ b/darwin/more.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +#define PAGERPROMPT " --More-- " +#define BACKOVERPROMPT "\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b" + +int nsh_cbreak(void); +void nsh_nocbreak(void); + +static struct termios oldtty; + +struct winsize winsize; + +/* + * Display file + */ +int +more(char *fname) +{ + FILE *f; + char *input, c; + size_t s; + int i, nopager = 0; + + if ((f = fopen(fname, "r")) == NULL) { + if (errno == ENOENT) + printf ("%% File %s not found\n", fname); + else + printf ("%% more: fopen(%s): %s\n", fname, + strerror(errno)); + return(0); + } + + if (nsh_cbreak() < 0) + nopager = 1; + + for (i = 0; (input = fgetln(f, &s)) != NULL; i++) { + + if (!nopager && i == (winsize.ws_row - 1)) { + printf(PAGERPROMPT); + fflush(0); + c = getchar(); + printf(BACKOVERPROMPT); + if (c == 'q') + break; /* stop */ + if (c == '\r' || c == '\n') + i--; /* skip one line */ + else + i = 0; /* skip one page */ + } + + /* + * We replace newline (or whatever was at the end of + * the line) with NUL termination + */ + input[s-1] = '\0'; + printf("%s\n", input); + } + + if (!nopager) + nsh_nocbreak(); + + fclose(f); + return(1); +} + +int +nsh_cbreak(void) +{ + struct termios newtty; + + if (tcgetattr(fileno(stdout), &oldtty) < 0) + return(-1); + + (void)memcpy(&newtty, &oldtty, sizeof(newtty)); + + newtty.c_lflag &= ~(ECHO | ICANON); /* no echo, canonical */ + newtty.c_cc[VMIN] = 1; /* one char at a time */ + newtty.c_cc[VTIME] = 0; /* no timeout */ + + if (tcsetattr(fileno(stdout), TCSAFLUSH, &newtty) < 0) + return(-1); + return(0); +} + +void +nsh_nocbreak(void) +{ + tcsetattr(0, TCSAFLUSH, &oldtty); +} + +void +setwinsize(int signo) +{ + int save_errno = errno; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) { + winsize.ws_col = winsize.ws_col ? winsize.ws_col : 80; + winsize.ws_row = winsize.ws_row ? winsize.ws_row : 24; + } else { + winsize.ws_col = 80; + winsize.ws_row = 24; + } + + errno = save_errno; +} diff --git a/darwin/passwd.c b/darwin/passwd.c new file mode 100644 index 0000000..9700a20 --- /dev/null +++ b/darwin/passwd.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2004 + * Christian Gut. 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 ``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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int read_pass(char *, size_t); +int write_pass(char *); +int gen_salt(char *, size_t); + +/* read_pass reads the (blowfish crypted) password from a file */ +int +read_pass(char *pass, size_t size) +{ + FILE *pwdhandle; + + pwdhandle = fopen(NSHPASSWD_TEMP, "r"); + if (pwdhandle == NULL) + return (0); + fgets(pass, size, pwdhandle); + fclose(pwdhandle); + + return (1); +} + +/* write the crypted password to the passwd-temp file */ +int +write_pass(char *cpass) +{ + FILE *pwdhandle; + + umask(S_IWGRP | S_IRWXO); + /* maybe we should flock here? */ + pwdhandle = fopen(NSHPASSWD_TEMP, "w"); + if (pwdhandle == NULL) { + printf("%% Unable to write run-time crypt repository: %s\n", + strerror(errno)); + return (0); + } + fprintf(pwdhandle, "%s", cpass); + fclose(pwdhandle); + + return (1); +} + +int +gen_salt(char *salt, size_t saltlen) +{ + /* 6 is a rounds value like from localcipher option of login.conf */ + strlcpy(salt, "1234567", saltlen); + return 1; +} + +/* + * enable privileged mode + */ +int +enable(int argc, char **argv) +{ + char *p, *cpass; + char salt[_PASSWORD_LEN]; + char pass[_PASSWORD_LEN + 1]; + + switch (argc) { + + case 1: + if (priv == 1) + return 0; + + /* try to read pass */ + if (!(read_pass(pass, sizeof(pass)))) { + if (errno == ENOENT) { + /* no password file, so enable */ + priv = 1; + return 1; + } else { + /* cant read password file */ + printf("%% Unable to read password: %s\n", + strerror(errno)); + return 0; + } + } + p = getpass("Password:"); + if (p == NULL || *p == '\0') + return 0; + + if (strcmp(pass, pass) == 0) { + priv = 1; + return 1; + } else { + printf("%% Password incorrect\n"); + return 0; + } + + case 2: + if (argv[1][0] == '?') { + /* print help */ + printf("%% enable\t\t\t\tenable privileged mode\n"); + printf("%% enable ?\t\t\t\tShow Options\n"); + printf("%% enable secret \t\tSet password" + "(plaintext)\n"); + printf("%% enable secret \t\tSet" + " password(ciphertext)\n"); + return 1; + } else { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + case 3: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* crypt plaintext and save as pass */ + strlcpy(pass, argv[2], sizeof(pass)); + return(write_pass(pass)); + + case 4: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[2]); + return 0; + } + + if (!isprefix(argv[2], "blowfish")) { + printf("%% Invalid cipher: %s\n", argv[3]); + return 0; + } + + /* privileged? */ + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* set crypted pass */ + strlcpy(pass, argv[3], sizeof(pass)); + return (write_pass(pass)); + + default: + printf("%% Too many arguments\n"); + return 0; + } + +} diff --git a/darwin/sqlite3.c b/darwin/sqlite3.c new file mode 100644 index 0000000..e92f479 --- /dev/null +++ b/darwin/sqlite3.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +int sq3simple(char *, StringList *); + +#define QSZ 1024 /* maximum query text size */ + +int +db_create_table_rtables(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS rtables (rtable INTEGER PRIMARY KEY, name TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_nameservers(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS nameservers (nameserver TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_flag_x(char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "CREATE TABLE IF NOT EXISTS %s (ctl TEXT, rtable INTEGER, flag INTEGER," + "data TEXT)", name); + return(sq3simple(query, NULL)); +} + +int +db_insert_flag_x(char *name, char *ctl, int rtableid, int flag, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO '%s' VALUES('%s', %d, %d, '%s')", + name, ctl, rtableid, flag, data); + return(sq3simple(query, NULL)); +} + +int +db_insert_rtables(int rtableid, char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO 'rtables' VALUES(%d, '%s')", rtableid, name); + return(sq3simple(query, NULL)); +} + +int +db_delete_rtables_rtable(int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'rtables' WHERE rtable=%d", rtableid); + return(sq3simple(query, NULL)); +} + +int +db_insert_nameserver(char *nameserver) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT OR REPLACE INTO 'nameservers' VALUES('%s')", + nameserver); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl(char *name, char *ctl) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND rtable=%d", name, ctl, cli_rtable); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl_data(char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, NULL)); +} + +int +db_delete_nameservers(void) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'nameservers'"); + return(sq3simple(query, NULL)); +} + +int +db_select_flag_x_ctl_data(StringList *words, char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_ctl(StringList *words, char *name, char *ctl) +{ + char query [QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s'", name, ctl); + return(sq3simple(query, words)); +} + +int +db_select_rtable_rtables(StringList *words) +{ + char query[]="SELECT rtable FROM rtables"; + return(sq3simple(query, words)); +} + +int +db_select_rtables_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable=%d", rtableid); + return(sq3simple(query,words)); +} + +int +db_select_flag_x_ctl_rtable(StringList *words, char *name, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT ctl FROM %s WHERE rtable=%d", name, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_data_ctl_rtable(StringList *words, char *name, char *ctl, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_nameservers(StringList *words) +{ + char query[]="SELECT nameserver FROM nameservers"; + return(sq3simple(query, words)); +} + +int +db_select_name_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable='%d'", rtableid); + return(sq3simple(query, words)); +} + +/* simple query execution, dump results straight into words */ +int +sq3simple(char *sql, StringList *words) +{ + sqlite3 *db; + sqlite3_stmt *stmt; + char *result, *new = NULL; + int rv, len, tlen = 0; + + if (sqlite3_open(SQ3DBFILE, &db)) { + printf("%% database file open failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) + != SQLITE_OK) { + printf("%% sqlite3_prepare_v2 failed: %s (%s)\n", + sqlite3_errmsg(db), sql); + return -1; + } + + while ((rv = sqlite3_step(stmt)) == SQLITE_ROW) { + result = (char *)sqlite3_column_text(stmt, 0); + len = strlen(result) + 1; + if ((new = malloc(len)) == NULL) { + printf("%% sq3simple: malloc failed\n"); + break; + } + tlen += len; + strlcpy(new, result, len); + sl_add(words, new); + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + if (rv != SQLITE_DONE) { + printf("%% sq3simple: error: %s\n", sqlite3_errmsg(db)); + return -1; + } + return tlen; +} diff --git a/darwin/stringlist.h b/darwin/stringlist.h new file mode 100644 index 0000000..442657b --- /dev/null +++ b/darwin/stringlist.h @@ -0,0 +1,51 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/stringlist.h,v 1.2 2002/02/16 21:27:46 millert Exp $ */ + +/* + * Copyright (c) 1994 Christos Zoulas + * 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 ``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 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. + */ + +#ifndef _STRINGLIST_H +#define _STRINGLIST_H + +#include +#include + +/* + * Simple string list + */ +typedef struct _stringlist { + char **sl_str; + size_t sl_max; + size_t sl_cur; +} StringList; + +__BEGIN_DECLS +StringList *sl_init(void); +void sl_add(StringList *, char *); +void sl_free(StringList *, int); +char *sl_find(StringList *, char *); +__END_DECLS + +#endif /* _STRINGLIST_H */ diff --git a/sysctl.h b/darwin/sysctl.h similarity index 100% rename from sysctl.h rename to darwin/sysctl.h diff --git a/darwin/version.c b/darwin/version.c new file mode 100644 index 0000000..93edac3 --- /dev/null +++ b/darwin/version.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int +version(int argc, char **argv) +{ + char cpubuf[1024]; + char kernver[1024]; + struct timeval tv, boottime; + struct utsname un; + size_t len; + time_t c; + uint64_t physmem; + int mib[5], pntd, weeks, days, hours, mins; + + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + len = sizeof(physmem); + if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) { + printf("%% HW_PHYSMEM: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + len = sizeof(cpubuf); + if (sysctl(mib, 2, &cpubuf, &len, NULL, 0) == -1) { + printf("%% HW_MODEL: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + len = sizeof(boottime); + if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1) { + printf("%% KERN_BOOTTIME: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + len = sizeof(kernver); + if (sysctl(mib, 2, &kernver, &len, NULL, 0) == -1) { + printf("%% KERN_VERSION: %s\n", strerror(errno)); + return(1); + } + if (uname(&un)) { + printf("%% uname: %s\n", strerror(errno)); + return(1); + } + gettimeofday(&tv, (struct timezone *)0); + c = difftime(tv.tv_sec, boottime.tv_sec); + + printf("%% NSH v%s\n", vers); + printf("Compiled %s by %s@%s\n", compiled, compiledby, compilehost); + printf("uptime: "); + pntd = 0; + weeks = c / (7 * 24 * 60 * 60); + c %= (7 * 24 * 60 * 60); + days = c / (24 * 60 * 60); + c %= (24 * 60 * 60); + hours = c / (60 * 60); + c %= (60 * 60); + mins = c / 60; + c %= 60; + if (weeks) { + printf("%d week%s", weeks, weeks == 1 ? "" : "s"); + pntd = 1; + } + if (days) { + printf("%s%d day%s", pntd ? ", " : "", days, + days == 1 ? "" : "s"); + pntd = 1; + } + if (hours) { + printf("%s%d hour%s", pntd ? ", " : "", hours, + hours == 1 ? "" : "s"); + pntd = 1; + } + if (mins) { + printf("%s%d minute%s", pntd ? ", " : "", mins, + mins == 1 ? "" : "s"); + pntd = 1; + } + if (!pntd) + printf("%d second%s", (int)c, c == 1 ? "" : "s"); + printf("\n"); + printf("system: %s/%s version %s\n", un.sysname, un.machine, + un.release); + printf("cpu: %s\n", cpubuf); + printf("memory: %ldB\n", (physmem / 1024)); + printf("kernel: %s", kernver); + return(0); +} + diff --git a/darwin/who.c b/darwin/who.c new file mode 100644 index 0000000..16b9aac --- /dev/null +++ b/darwin/who.c @@ -0,0 +1,449 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2002 Tim J. Robbins. + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void heading(void); +static void process_utmp(void); +static void quick(void); +static void row(const struct utmpx *); +static int ttywidth(void); +static void usage(void); +static void whoami(void); + +static int Hflag; /* Write column headings */ +static int aflag; /* Print all entries */ +static int bflag; /* Show date of the last reboot */ +#ifdef __APPLE__ +static int lflag; /* waiting to login */ +#endif +static int mflag; /* Show info about current terminal */ +#ifdef __APPLE__ +static int pflag; /* Processes active & spawned by init */ +#endif +#ifdef __APPLE__ +static int dflag; /* dead processes */ +#endif +static int qflag; /* "Quick" mode */ +#ifdef __APPLE__ +static int rflag; /* run-level of the init process */ +#endif +static int sflag; /* Show name, line, time */ +#ifdef __APPLE__ +static int tflag; /* time of change to system clock */ +#endif +static int Tflag; /* Show terminal state */ +static int uflag; /* Show idle time */ +#ifdef __APPLE__ +#include +static int unix2003_std; +#endif + +int +who(int argc, char *argv[]) +{ + int ch; + + setlocale(LC_TIME, ""); + +#ifdef __APPLE__ + unix2003_std = COMPAT_MODE("bin/who", "unix2003"); +#endif + +#ifndef __APPLE__ + while ((ch = getopt(argc, argv, "HTabmqsu")) != -1) { +#else + while ((ch = getopt(argc, argv, "abdHlmpqrstTu")) != -1) { +#endif + switch (ch) { + case 'H': /* Write column headings */ + Hflag = 1; + break; + case 'T': /* Show terminal state */ + Tflag = 1; + break; + case 'a': /* Same as -bdlprtTu */ + aflag = bflag = Tflag = uflag = 1; +#ifdef __APPLE__ + dflag = lflag = pflag = rflag = sflag = tflag = 1; +#endif + break; + case 'b': /* Show date of the last reboot */ + bflag = 1; + break; +#ifdef __APPLE__ + case 'd': /* dead processes */ + dflag = 1; + break; + case 'l': /* waiting to login */ + lflag = 1; + break; +#endif + case 'm': /* Show info about current terminal */ + mflag = 1; + break; +#ifdef __APPLE__ + case 'p': /* Processes active & spawned by init */ + pflag = 1; + break; +#endif + case 'q': /* "Quick" mode */ + qflag = 1; + break; +#ifdef __APPLE__ + case 'r': /* run-level of the init process */ + rflag = 1; + break; +#endif + case 's': /* Show name, line, time */ + sflag = 1; + break; +#ifdef __APPLE__ + case 't': /* time of change to system clock */ + tflag = 1; + break; +#endif + case 'u': /* Show idle time */ + uflag = 1; + break; + default: + usage(); + /*NOTREACHED*/ + } + } + argc -= optind; + argv += optind; + + if (argc >= 2 && strcmp(argv[0], "am") == 0 && + (strcmp(argv[1], "i") == 0 || strcmp(argv[1], "I") == 0)) { + /* "who am i" or "who am I", equivalent to -m */ + mflag = 1; + argc -= 2; + argv += 2; + } + if (argc > 1) + usage(); + + if (*argv != NULL) { +#ifndef __APPLE__ + if (setutxdb(UTXDB_ACTIVE, *argv) != 0) + err(1, "%s", *argv); +#else + if (!utmpxname(*argv) || !wtmpxname(*argv)) + usage(); +#endif + } + + if (qflag) + quick(); + else { + if (sflag) + Tflag = uflag = 0; + if (Hflag) + heading(); + if (mflag) + whoami(); + else + process_utmp(); + } + + endutxent(); + +#ifdef __APPLE__ + if (ferror(stdout) != 0 || fflush(stdout) != 0) + err(1, "stdout"); +#endif +} + +static void +heading(void) +{ + + printf("%-16s ", "NAME"); + if (Tflag) + printf("S "); + printf("%-12s %-12s ", "LINE", "TIME"); + if (uflag) + printf("IDLE "); +#ifdef __APPLE__ + if (unix2003_std && uflag && !Tflag) + printf(" PID "); +#endif + printf("%-16s\n", "FROM"); +} + +static void +row(const struct utmpx *ut) +{ +#ifndef __APPLE__ + char buf[80], tty[PATH_MAX]; +#else + char buf[80], tty[sizeof(_PATH_DEV) + _UTX_LINESIZE]; +#endif + struct stat sb; + time_t idle, t; + static int d_first = -1; + struct tm *tm; + char state; +#ifdef __APPLE__ + char login_pidstr[20]; +#endif + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + + state = '?'; + idle = 0; + if (Tflag || uflag) { + snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, ut->ut_line); + if (stat(tty, &sb) == 0) { + state = sb.st_mode & (S_IWOTH|S_IWGRP) ? + '+' : '-'; + idle = time(NULL) - sb.st_mtime; + } +#ifdef __APPLE__ + if (unix2003_std && !Tflag) { + if (ut->ut_pid) { + snprintf(login_pidstr,sizeof(login_pidstr), + "%8d",ut->ut_pid); + } else { + strcpy(login_pidstr," ?"); + } + } +#endif + } + +#ifdef __APPLE__ + if (ut->ut_type == BOOT_TIME) { + printf(" "); + } else { + printf("%-16s ", ut->ut_user); + } +#else + printf("%-16s ", ut->ut_user); +#endif /* __APPLE__ */ + if (Tflag) + printf("%c ", state); + if (ut->ut_type == BOOT_TIME) + printf("%-12s ", "system boot"); +#ifdef __APPLE__ + else if (ut->ut_type == LOGIN_PROCESS) + printf("%-12s ", "LOGIN"); +#endif + else + printf("%-12s ", ut->ut_line); + t = ut->ut_tv.tv_sec; + tm = localtime(&t); + strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm); + printf("%-*s ", 12, buf); + if (uflag) { + if (idle < 60) + printf(" . "); + else if (idle < 24 * 60 * 60) + printf("%02d:%02d ", (int)(idle / 60 / 60), + (int)(idle / 60 % 60)); + else + printf(" old "); +#ifdef __APPLE__ + if (unix2003_std && !Tflag) { + printf("%s ", login_pidstr); + } +#endif + } + if (*ut->ut_host != '\0') + printf("(%s)", ut->ut_host); +#ifdef __APPLE__ + if (dflag && ut->ut_type == DEAD_PROCESS) { + printf("\tterm=%d exit=%d", 0, 0); + } +#endif + putchar('\n'); +} + +static int +ttystat(char *line) +{ + struct stat sb; + char ttybuf[MAXPATHLEN]; + + (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line); + if (stat(ttybuf, &sb) == 0) { + return (0); + } else + return (-1); +} + +static void +process_utmp(void) +{ + struct utmpx *utx; + + while ((utx = getutxent()) != NULL) { +#ifdef __APPLE__ + if (aflag) { + row(utx); + } + else if (!bflag && utx->ut_type == USER_PROCESS) { + if (ttystat(utx->ut_line) == 0) { + if (!rflag && !lflag && !dflag) { + row(utx); + } + } + } + else if (bflag && utx->ut_type == BOOT_TIME) { +#ifndef __APPLE__ + if (ttystat(utx->ut_line) == 0) { +#endif /* __APPLE__ */ + row(utx); +#ifndef __APPLE__ + } +#endif /* __APPLE__ */ + } + else if (dflag && utx->ut_type == DEAD_PROCESS) { + row(utx); + } + else if (lflag && utx->ut_type == LOGIN_PROCESS) { + row(utx); + } +#else + if (((aflag || !bflag) && utx->ut_type == USER_PROCESS) || + (bflag && utx->ut_type == BOOT_TIME)) + if (ttystat(utx->ut_line) == 0) + row(utx); +#endif + } +#ifdef __APPLE__ + if (rflag) { + printf(" . run-level 3\n"); + } +#endif +} + + +static void +quick(void) +{ + struct utmpx *utx; + int col, ncols, num; + + ncols = ttywidth(); + col = num = 0; + while ((utx = getutxent()) != NULL) { +#ifndef __APPLE__ + if (utx->ut_type != USER_PROCESS) +#else + if (*utx->ut_user == '\0' || utx->ut_type != USER_PROCESS) +#endif + continue; + printf("%-16s", utx->ut_user); + if (++col < ncols / (16 + 1)) + putchar(' '); + else { + col = 0; + putchar('\n'); + } + num++; + } + if (col != 0) + putchar('\n'); + + printf("# users = %d\n", num); +} + +static void +whoami(void) +{ + struct utmpx ut, *utx; + struct passwd *pwd; + const char *name, *tty; + + if ((tty = ttyname(STDIN_FILENO)) == NULL) + tty = "tty??"; + else if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) + tty += sizeof _PATH_DEV - 1; + strlcpy(ut.ut_line, tty, sizeof ut.ut_line); + + /* Search utmp for our tty, dump first matching record. */ + if ((utx = getutxline(&ut)) != NULL && utx->ut_type == USER_PROCESS) { + row(utx); + return; + } + + /* Not found; fill the utmp structure with the information we have. */ + memset(&ut, 0, sizeof(ut)); + if ((pwd = getpwuid(getuid())) != NULL) + name = pwd->pw_name; + else + name = "?"; + strlcpy(ut.ut_user, name, sizeof ut.ut_user); + gettimeofday(&ut.ut_tv, NULL); + row(&ut); +} + +static int +ttywidth(void) +{ + struct winsize ws; + long width; + char *cols, *ep; + + if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') { + errno = 0; + width = strtol(cols, &ep, 10); + if (errno || width <= 0 || width > INT_MAX || ep == cols || + *ep != '\0') + warnx("invalid COLUMNS environment variable ignored"); + else + return (width); + } + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) + return (ws.ws_col); + + return (80); +} diff --git a/freebsd/commands.c b/freebsd/commands.c new file mode 100644 index 0000000..bbc98a3 --- /dev/null +++ b/freebsd/commands.c @@ -0,0 +1,1249 @@ +/* + * Copyright (c) 2002-2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" +#include "sysctl.h" + +char prompt[128]; + +char line[1024]; +char saveline[1024]; +int margc; +char hname[HSIZE]; +static char hbuf[MAXHOSTNAMELEN]; /* host name */ +static char ifname[IFNAMSIZ]; /* interface name */ +struct intlist *whichlist; + +#define RT_TABLEID_MAX 255 +#define NARGS sizeof(line)/2 /* max arguments in char line[] */ +char *margv[NARGS]; /* argv storage */ +size_t cursor_argc; /* location of cursor in margv */ +size_t cursor_argo; /* offset of cursor margv[cursor_argc] */ + +pid_t child; + +static int quit(void); +static int disable(void); +static int doverbose(int, char**); +static int doediting(int, char**); +static int hostname(int, char **); +static int help(int, char**); +static int shell(int, char*[]); +static int ping(int, char*[]); +static int ping6(int, char*[]); +static int ssh(int, char*[]); +static int telnet(int, char*[]); +static int traceroute(int, char*[]); +static int traceroute6(int, char*[]); +static Command *getcmd(char *); +static void sigalarm(int); +static int show_hostname(int, char **); +static int pr_conf(int, char **); +static int pr_kernel(int, char **); +static int pr_s_conf(int, char **); +static int show_help(int, char **); +static int wr_startup(void); +static int wr_conf(char *); +static int el_burrito(EditLine *, int, char **); + void p_argv(int, char **); +static int flush_history(void); +static int flush_line(char *); +static int flush_help(void); +static int notvalid(void); +static void pf_stats(void); + +#include "commands.h" + +void sigalarm(int blahfart) +{ + if (child != -1) { + kill(child, SIGKILL); + } +} + +/* + * Quit command + */ + +int +quit(void) +{ + printf("%% Session terminated.\n"); + exit(0); + return 0; +} + +/* + * Data structures and routines for the "show" command. + */ + +Menu showlist[] = { + { "hostname", "Router hostname", CMPL0 0, 0, 0, 0, show_hostname }, + { "kernel", "Kernel statistics", CMPL(ta) (char **)stts, sizeof(struct stt), 0, 1, pr_kernel }, + { "version", "Software information", CMPL0 0, 0, 0, 0, version }, + { "users", "System users", CMPL0 0, 0, 0, 0, who }, + { "running-config", "Operating configuration", CMPL0 0, 0, 0, 0, pr_conf }, + { "startup-config", "Startup configuration", CMPL0 0, 0, 0, 0, pr_s_conf }, + { "?", "Options", CMPL0 0, 0, 0, 0, show_help }, + { "help", 0, CMPL0 0, 0, 0, 0, show_help }, + { 0, 0, 0, 0, 0 } +}; + +/* + * Data structures and routines for the "flush" command. + */ + +Menu flushlist[] = { + { "line", "Active user", CMPL0 0, 0, 1, 1, flush_line }, + { "history", "Command history", CMPL0 0, 0, 0, 0, flush_history }, + { "?", "Options", CMPL0 0, 0, 0, 0, flush_help }, + { "help", 0, CMPL0 0, 0, 0, 0, flush_help }, + { 0, 0, 0, 0, 0 } +}; + +static int +flush_line(char *line) +{ + char *argv[] = { PKILL, "-9", "-t", line, NULL }; + cmdargs(PKILL, argv); + return (1); +} + +static int +flush_help(void) +{ + Menu *f; + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'flush' commands are:\n\n"); + + for (f = flushlist; f->name; f++) { + if (strlen(f->name) > z) + z = strlen(f->name); + } + + for (f = flushlist; f->name; f++) { + if (f->help) + printf(" %-*s %s\n", z, f->name, f->help); + } + return 0; +} + +static int +showcmd(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + int success = 0; + + if (argc < 2) { + show_help(argc, argv); + return 0; + } + + /* + * Validate show argument + */ + s = (Menu *) genget(argv[1], (char **) showlist, sizeof(Menu)); + if (s == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(s)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + if (((s->minarg + 2) > argc) || ((s->maxarg + 2) < argc)) { + printf("%% Wrong number of argument%s to 'show %s' command" + " (min %i, max %i)\n", argc <= 2 ? "" : "s", s->name, + s->minarg, s->maxarg); + return 0; + } + if (s->handler) /* As if there was something else we do ? */ + success = (*s->handler)(argc, argv); + + return(success); +} + +static int +show_help(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'show' commands are:\n\n"); + + for (s = showlist; s->name; s++) { + if (strlen(s->name) > z) + z = strlen(s->name); + } + + for (s = showlist; s->name; s++) { + if (s->help) + printf(" %-*s %s\n", z, s->name, s->help); + } + return 0; +} + +/* + * Data structures and routines for the main CLI + */ + +static char + hostnamehelp[] = "Set system hostname", + interfacehelp[] = "Modify interface parameters", + rtablehelp[] = "Routing table switch", + grouphelp[] = "Modify group attributes", + arphelp[] = "Static ARP set", +#ifdef notyet + parphelp[] = "Proxy ARP set", +#endif + pfhelp[] = "Packet filter control", + ospfhelp[] = "OSPF control", + ospf6help[] = "OSPF6 control", + eigrphelp[] = "EIGRP control", + bgphelp[] = "BGP control", + riphelp[] = "RIP control", + ldphelp[] = "LDP control", + relayhelp[] = "Relay control", + ipsechelp[] = "IPsec IKEv1 control", + ikehelp[] = "IPsec IKEv2 control", + rtadvhelp[] = "Router advertisement control", + dvmrphelp[] = "DVMRP control", + sasynchelp[] = "SA synchronization control", + dhcphelp[] = "DHCP server control", + snmphelp[] = "SNMP server control", + smtphelp[] = "SMTP server control", + ldaphelp[] = "LDAP server control", + sshdhelp[] = "SSH server control", + ntphelp[] = "NTP synchronization control", + nppphelp[] = "PPP server control", + ifstatehelp[] = "ifstate server control", + ftpproxyhelp[] ="ftp-proxy server control", + tftpproxyhelp[] ="tftp-proxy server control", + tftphelp[] = "TFTP server control", + dnshelp[] = "DNS rule control", + motdhelp[] = "Message of-the-day", + inethelp[] = "Inet super-server control", + bridgehelp[] = "Modify bridge parameters", + showhelp[] = "Show system information", + iphelp[] = "Set IP networking parameters", + ip6help[] = "Set IPv6 networking parameters", + mplshelp[] = "Set MPLS network parameters", + ddbhelp[] = "Set DDB parameters", + pipexhelp[] = "Set PIPEX parameters", + flushhelp[] = "Flush system tables", + enablehelp[] = "Enable privileged mode", + disablehelp[] = "Disable privileged mode", + pinghelp[] = "Send IPv4 ICMP echo request", + ping6help[] = "Send IPv6 ICMP echo request", + tracerthelp[] = "Print the route to IPv4 host", + tracert6help[] ="Print the route to IPv6 host", + sshhelp[] = "SSH connection to remote host", + telnethelp[] = "Telnet connection to remote host", + quithelp[] = "Close current connection", + verbosehelp[] = "Set verbose diagnostics", + editinghelp[] = "Set command line editing", + whohelp[] = "Display system users", + shellhelp[] = "Invoke a subshell", + savehelp[] = "Save the current configuration", + nreboothelp[] = "Reboot the system", + halthelp[] = "Halt the system", + helphelp[] = "Print help information"; + +/* + * Primary commands, will be included in help output + */ + +#define ssctl sizeof(struct ctl) +Command cmdtab[] = { + { "hostname", hostnamehelp, CMPL0 0, 0, hostname, 1, 0, 0 }, + { "show", showhelp, CMPL(ta) (char **)showlist, sizeof(Menu), showcmd, 0, 0, 0 }, + { "enable", enablehelp, CMPL0 0, 0, enable, 0, 0, 0 }, + { "disable", disablehelp, CMPL0 0, 0, disable, 1, 0, 0 }, + { "ping", pinghelp, CMPL0 0, 0, ping, 0, 0, 0 }, + { "ping6", ping6help, CMPL0 0, 0, ping6, 0, 0, 0 }, + { "traceroute", tracerthelp, CMPL0 0, 0, traceroute, 0, 0, 0 }, + { "traceroute6", tracert6help, CMPL0 0, 0, traceroute6, 0, 0, 0 }, + { "ssh", sshhelp, CMPL0 0, 0, ssh, 0, 0, 0 }, + { "telnet", telnethelp, CMPL0 0, 0, telnet, 0, 0, 0 }, + { "write-config", savehelp, CMPL0 0, 0, wr_startup, 1, 0, 0 }, + { "verbose", verbosehelp, CMPL0 0, 0, doverbose, 0, 1, 0 }, + { "editing", editinghelp, CMPL0 0, 0, doediting, 0, 1, 0 }, + { "who", whohelp, CMPL0 0, 0, who, 0, 0, 0 }, + { "!", shellhelp, CMPL0 0, 0, shell, 1, 0, 0 }, + { "?", helphelp, CMPL(C) 0, 0, help, 0, 0, 0 }, + { "quit", quithelp, CMPL0 0, 0, quit, 0, 0, 0 }, + { "help", 0, CMPL(C) 0, 0, help, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +/* + * These commands escape ambiguous check and help listings + */ + +static Command cmdtab2[] = { + { "config", 0, CMPL0 0, 0, notvalid, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +Command * +getcmd(char *name) +{ + Command *cm; + + if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + +void +makeargv() +{ + char *cp, *cp2, *base, c; + char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + /* save for shell command */ + strlcpy(saveline, line, sizeof(saveline)); + + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while ((c = *cp)) { + int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + cursor_argc = margc += 1; + base = cp; + for (cursor_argo = 0, cp2 = cp; c != '\0'; + cursor_argo = (cp + 1) - base, c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) { + cursor_argo = 0; + break; + } + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') { + cursor_argc--; + break; + } + cp++; + } + *argp++ = 0; + if (cursor_pos == line) { + cursor_argc = 0; + cursor_argo = 0; + } +} + +void +command() +{ + Command *c; + u_int num; + + if (editing) { + inithist(); + initedit(); + } + + for (;;) { + if (!editing) { + printf("%s", cprompt()); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + printf("\n"); + (void) quit(); + /* NOTREACHED */ + } + break; + } + } else { + const char *buf; + cursor_pos = NULL; + + if ((buf = el_gets(elc, &num)) == NULL || num == 0) + break; + + if (buf[--num] == '\n') { + if (num == 0) + break; + } + if (num >= sizeof(line)) { + printf("%% Input exceeds permitted length\n"); + break; + } + memcpy(line, buf, (size_t)num); + line[num] = '\0'; + history(histc, &ev, H_ENTER, buf); + } + + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + if (NO_ARG(margv[0])) + c = getcmd(margv[1]); + else + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("%% Ambiguous command\n"); + continue; + } + if (c == 0) { + int val = 1; + + if (editing) + val = el_burrito(elc, margc, margv); + if (val) + printf("%% Invalid command\n"); + continue; + } + if (NO_ARG(margv[0]) && ! c->nocmd) { + printf("%% Invalid command: %s %s\n", margv[0], + margv[1]); + continue; + } + if (c->needpriv != 0 && priv != 1) { + printf("%% Privilege required\n"); + continue; + } + if (c->modh) + strlcpy(hname, c->name, HSIZE); + if ((*c->handler) (margc, margv, 0)) { + break; + } + } +} + +/* + * Help command. + */ +static int +help(int argc, char **argv) +{ + Command *c; + + if (argc == 1) { + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% Commands are:\n\n"); + + for (c = cmdtab; c->name; c++) + if (((c->needpriv && priv) || !c->needpriv) + && strlen(c->name) > z) + z = strlen(c->name); + for (c = cmdtab; c->name; c++) { + if (c->help && ((c->needpriv && priv) || + !c->needpriv)) + printf(" %-*s %s\n", z, c->name, c->help); + } + return 0; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("%% Ambiguous help command %s\n", arg); + else if (c == (Command *)0) + printf("%% Invalid help command %s\n", arg); + else + printf("%% %s: %s\n", arg, c->help); + } + return 0; +} + +/* + * Hostname command. + */ +int +hostname(int argc, char **argv) +{ + argv++; + argc--; + + if (argc > 1) { + printf("%% Invalid arguments\n"); + return 1; + } + + if (argc == 1) { + if (sethostname(*argv, strlen(*argv))) + printf("%% sethostname: %s\n", strerror(errno)); + } else + show_hostname(0, NULL); + return 0; +} + +int show_hostname(int argc, char **argv) +{ + if (gethostname(hbuf, sizeof(hbuf))) + printf("%% gethostname: %s\n", strerror(errno)); + else + printf("%s\n", hbuf); + + return 0; +} + +/* + * Shell command. + */ +int +shell(int argc, char **argv) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + /* + * Fire up the shell in the child. + */ + char *shellp; + char *shellname = shellp = "/bin/sh"; + + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], + (char *)NULL); + else + execl(shellp, shellname, (char *)NULL); + printf("%% execl failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for shell to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * ping command. + */ +int +ping(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING, argv); + } + return 0; +} + +int +ping6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING6, argv); + } + return 0; +} + +/* + * telnet command. + */ +int +telnet(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TELNET, argv); + } + return 0; +} + +/* + * ssh command. + */ +int +ssh(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(SSH, argv); + } + return 0; +} + +/* + * traceroute command. + */ +int +traceroute(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT, argv); + } + return 0; +} + +int +traceroute6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT6, argv); + } + return 0; +} + +int +argvtostring(int argc, char **argv, char *string, int strlen) +{ + int i, j; + + for (i = 0, j = 0; argc && i < (strlen - 1); i++) { + if (argv[0][j] == '\0') { + argc--, argv++; + string[i] = ' '; + j = 0; + continue; + } + string[i] = argv[0][j]; + j++; + } + if (i > 0) + i--; + string[i] = '\0'; + + return i; +} + +/* + * cmd, multiple args + */ +int +cmdargs(char *cmd, char *arg[]) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + char *shellp = cmd; + + execv(shellp, arg); + printf("%% execv failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for cmd to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * disable privileged mode + */ +int +disable(void) +{ + priv = 0; + return 0; +} + +int +notvalid(void) +{ + printf("%% The command you entered is not necessary with this" + " software.\n"); + + return(0); +} + +/* + * verbose diagnostics + */ +int +doverbose(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + verbose = 0; + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + verbose = 1; + } + + printf("%% Diagnostic mode %s\n", verbose ? "enabled" : "disabled"); + + return 0; +} + +int +doediting(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + endedit(); + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + initedit(); + } + + printf("%% Command line editing %s\n", + editing ? "enabled" : "disabled"); + + return 0; +} + +int +flush_history(void) +{ + if (!editing) { + printf("%% Command line editing not enabled\n"); + return(1); + } + + /* + * Editing mode needs to be reinitialized if the histi/histc + * pointers are going to change..... + */ + endedit(); + endhist(); + inithist(); + initedit(); + + return(0); +} + +void +gen_help(char **x, char *cmdprefix, char *descrsuffix, int szstruct) +{ + /* only for structures starting with char *name; char *help; !! */ + char **y = x; + struct ghs *ghs; + int z = 0; + + printf("%% Arguments may be abbreviated\n\n"); + + while (*y != 0) { + if (strlen(*y) > z) + z = strlen(*y); + y = (char **)((char *)y + szstruct); + } + + while (*x != 0) { + ghs = (struct ghs *)x; + if (ghs->help) + printf(" %s %-*s %s %s\n", cmdprefix, z, *x, + ghs->help, descrsuffix); + x = (char **)((char *)x + szstruct); + } + return; +} + +/* + * read a text file and execute commands + * take into account that we may have mode handlers int cmdtab that + * execute indented commands from the rc file + */ +int +cmdrc(char rcname[FILENAME_MAX]) +{ + Command *c = NULL, *savec = NULL; + FILE *rcfile; + char modhvar[128]; /* required variable in mode handler cmd */ + unsigned int lnum; /* line number */ + u_int z = 0; /* max length of cmdtab argument */ + + if ((rcfile = fopen(rcname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", rcname, strerror(errno)); + return 1; + } + + for (c = cmdtab; c->name; c++) + if (strlen(c->name) > z) + z = strlen(c->name); + c = NULL; + + for (lnum = 1; ; lnum++) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (line[0] == '!') + continue; + /* + * Don't ignore indented comments with pound sign, otherwise + * comments won't be saved into daemon/ctl config files. + */ + if (line[0] == ' ' && line[1] == '!' && savec && savec->modh == 2) + continue; + if (line[0] == ' ') + strlcpy(saveline, line, sizeof(line)); + makeargv(); + if (margv[0] == 0) + continue; + if (line[0] == ' ' && (!savec || savec->modh < 1)) { + printf("%% No mode handler specified before" + " indented command? (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (line[0] != ' ' || (line[0] == ' ' && line[1] != ' ' + && savec && savec->modh == 2)) { + /* + * command was not indented, or indented for a mode 2 + * handler. process normally. + */ + if (NO_ARG(margv[0])) { + c = getcmd(margv[1]); + if (line[0] != ' ') + savec = c; + if (savec && (savec->nocmd == 0)) { + printf("%% Invalid rc command (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } else { + c = getcmd(margv[0]); + if (line[0] != ' ') + savec = c; + if(savec && savec->modh) { + /* + * any mode handler should have + * one value stored, passed on + */ + if (margv[1]) { + strlcpy(hname, c->name, + HSIZE); + strlcpy(modhvar, margv[1], + sizeof(modhvar)); + } else { + printf("%% No argument after" + " mode handler (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } + } + } + if (Ambiguous(c)) { + printf("%% Ambiguous rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (c == 0) { + printf("%% Invalid rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (verbose) { + printf("%% %4s: %*s%10s (line %u) margv ", + savec && savec->modh ? "mode" : "cmd", z, + savec && savec->name ? savec->name : "", + c != savec ? "(sub-cmd)" : "", lnum); + p_argv(margc, margv); + printf("\n"); + } + if (c->modh == 1) + (*c->handler) (margc, margv, modhvar); + else + (*c->handler) (margc, margv, 0); + } + fclose(rcfile); + return 0; +} + +void +p_argv(int argc, char **argv) +{ + int z; + + for (z = 0; z < argc; z++) + printf("%s%s", z ? " " : "[", argv[z]); + printf("]"); + return; +} + +/* + * for the purpose of interface handler routines, 1 here is failure and + * 0 is success + */ +int +el_burrito(EditLine *el, int argc, char **argv) +{ + char *colon; + int val; + + if (!editing) /* Nothing to parse, fail */ + return(1); + + /* + * el_parse will always return a non-error status if someone specifies + * argv[0] with a colon. The idea of the colon is to allow host- + * specific commands, which is really only useful in .editrc, so + * it is invalid here. + */ + colon = strchr(argv[0], ':'); + if (colon) + return(1); + + val = el_parse(el, argc, (const char **)argv); + + if (val == 0) + return(0); + else + return(1); +} + +char * +cprompt(void) +{ + int pr; + char tmp[4]; + + if (cli_rtable) + snprintf(tmp, sizeof(tmp), "%d", cli_rtable); + + gethostname(hbuf, sizeof(hbuf)); + pr = priv | cli_rtable; + snprintf(prompt, sizeof(prompt), "%s%s%s%s%s%s%s%s", hbuf, pr ? "(" : "", + priv ? "p" : "", priv && cli_rtable ? "-" : "", + cli_rtable ? "rtable " : "", cli_rtable ? tmp : "", + pr ?")" : "> ", pr ? "# " : ""); + + return(prompt); +} + +char * +iprompt(void) +{ + gethostname(hbuf, sizeof(hbuf)); + snprintf(prompt, sizeof(prompt), "%s(%s-%s)>", hbuf, + bridge ? "bridge" : "interface", ifname); + + return(prompt); +} + +int +wr_startup(void) +{ + char *argv[] = { SAVESCRIPT, NSHRC_TEMP, '\0' }; + + if (wr_conf(NSHRC_TEMP)) + printf("%% Saving configuration\n"); + else + printf("%% Unable to save configuration: %s\n", + strerror(errno)); + + cmdargs(SAVESCRIPT, argv); + + return(1); +} + +/* + * Save configuration + */ +int +wr_conf(char *fname) +{ + FILE *rchandle; + int error = 1; + + if ((rchandle = fopen(fname, "w")) == NULL) + error = 0; + else { + conf(rchandle); + fclose(rchandle); + } + + return (error); +} + +/* + * Show wrappers + */ +int +pr_conf(int argc, char **argv) +{ + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + if (!wr_conf(NSHRC_TEMP)) { + printf("%% Couldn't generate configuration\n"); + return(0); + } + + more(NSHRC_TEMP); + + return(1); +} + +/* + * Show startup config + */ +int +pr_s_conf(int argc, char **argv) +{ + int ret; + + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + ret = more(NSHRC); + + return(ret); +} + + +char ** +step_optreq(char **xargs, char **args, int argc, char **argv, int skip) +{ + int i; + int fill = 0; /* total fillable arguments */ + int flc = 0; /* number of filled arguments */ + + /* count fillable arguments */ + for (i = 0; i < NOPTFILL - 1; i++) { + if (xargs[i] == OPT || xargs[i] == REQ) + fill++; + if (xargs[i] == NULL) + break; + } + + if (argc - skip > fill) { + printf("%% Superfluous argument: %s\n", argv[skip + fill]); + return NULL; + } + + /* copy xargs to args, replace OPT/REQ args with argv past skip */ + for (i = 0; i < NOPTFILL - 2; i++) { + if (xargs[i] == NULL) { + args[i] = '\0'; + if (i > 1) + /* + * all **args passed must have at least two arguments + * and a terminating NULL. the point of this check + * is to allow the first two arguments to be NULL but + * still fill in fillargs[x] with corresponding NULL + */ + break; + } + if (xargs[i] == OPT || xargs[i] == REQ) { + /* copy from argv to args */ + if (argc - skip - flc > 0) { + args[i] = argv[skip + flc]; + flc++; + } else if (xargs[i] == REQ) { + printf("%% Missing required argument\n"); + return NULL; + } else { + args[i] = '\0'; + break; + } + } else { + /* copy from xargs to args */ + args[i] = xargs[i]; + } + } + + return(args); +} + +int +pr_kernel(int argc, char **argv) +{ + struct stt *x; + + /* int i; + for (i = 0; i < sizeof(argv); i++) { + printf("ARGV%d: %s\n", i, argv[i]); + + } */ + + if (argc < 3 || argv[2][0] == '?') { + gen_help((char **)stts, "show kernel", "statistics", + sizeof(struct stt)); + return 0; + } + x = (struct stt *) genget(argv[2], (char **)stts, sizeof(struct stt)); + if (x == 0) { + printf("%% Invalid argument %s\n", argv[2]); + return 0; + } else if (Ambiguous(x)) { + printf("%% Ambiguous argument %s\n", argv[2]); + return 0; + } + if (x->handler) /* not likely to be false */ + (*x->handler)(); + + return(0); +} + +void +pf_stats(void) +{ + char *argv[] = { PFCTL, "-sinfo", NULL }; + + printf("%% pf statistics:\n"); + + cmdargs(PFCTL, argv); + return; +} diff --git a/freebsd/commands.h b/freebsd/commands.h new file mode 100644 index 0000000..4109ad8 --- /dev/null +++ b/freebsd/commands.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2008-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static struct fpf { + char *name; + char *help; + char *cmd; + char *arg; +} fpfs[] = { + { "all", "all PF elements", PFCTL, "-Fall" }, + { "nat", "NAT rules", PFCTL, "-Fnat" }, + { "queue", "queue rules", PFCTL, "-Fqueue" }, + { "filter", "filter rules", PFCTL, "-Frules" }, + { "states", "NAT/filter states", PFCTL, "-Fstate" }, + { "stats", "PF statistics", PFCTL, "-Finfo" }, + { "tables", "PF address tables", PFCTL, "-FTables" }, + { 0, 0, 0, 0 } +}; + +static struct stt { + char *name; + char *help; + void (*handler) (); +} stts[] = { + //{ "ip", "Internet Protocol", ip_stats }, + //{ "ah", "Authentication Header", ah_stats }, + //{ "esp", "Encapsulated Security Payload", esp_stats }, + //{ "udp", "Unreliable Datagram Protocol", udp_stats }, + //{ "icmp", "Internet Control Message Protocol", icmp_stats }, + //{ "igmp", "Internet Group Management Protocol", igmp_stats }, + //{ "ipcomp", "IP Compression", ipcomp_stats }, + //{ "route", "Routing", rt_stats }, + //{ "carp", "Common Address Redundancy Protocol", carp_stats }, + //{ "mbuf", "Packet memory buffer", mbpr }, + //{ "pf", "Packet Filter", pf_stats }, + { 0, 0, 0 } +}; + +struct prot1 { + char *name; + char *help; + char *args[32]; +}; + +struct prot { + char *name; + struct prot1 *table; +}; + +struct prot1 bgcs[] = { + { "announced", "All announced networks", + { BGPCTL, "network", "show", OPT, NULL } }, + { "interfaces", "Interface states", + { BGPCTL, "show", "interfaces", NULL } }, + { "nexthop", "BGP nexthop routes", + { BGPCTL, "show", "nexthop", NULL } }, + { "summary", "Neighbor session states and counters", + { BGPCTL, "show", "summary", OPT, NULL } }, + { "rib", "Routing Information Base", + { BGPCTL, "show", "rib", OPT, OPT, OPT, NULL } }, + { "neighbor", "Detailed peer", + { BGPCTL, "show", "neighbor", REQ, OPT, NULL } }, + { "ip", "IP BGP", + { BGPCTL, "show", "ip", "bgp", OPT, OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 oscs[] = { + { "fib", "Forward Information Base", + { OSPFCTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPFCTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPFCTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPFCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPFCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPFCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 os6cs[] = { + { "fib", "Forward Information Base", + { OSPF6CTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPF6CTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPF6CTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPF6CTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPF6CTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPF6CTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 eics[] = { + { "interfaces", "Interface", + { EIGRPCTL, "show", "interfaces", OPT, OPT, NULL } }, + { "neighbor", "Neighbor", + { EIGRPCTL, "show", "neighbor", OPT, OPT, NULL } }, + { "topology", "Topology", + { EIGRPCTL, "show", "topology", OPT, OPT, NULL } }, + { "traffic", "Traffic", + { EIGRPCTL, "show", "traffic", OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rics[] = { + { "fib", "Forward Information Base", + { RIPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { RIPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbor", + { RIPCTL, "show", "neighbor", NULL } }, + { "rib", "Routing Information Base", + { RIPCTL, "show", "rib", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 lics[] = { + { "fib", "Forward Information Base", + { LDPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { LDPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbors", + { LDPCTL, "show", "neighbor", NULL } }, + { "lib", "Label Information Base", + { LDPCTL, "show", "lib", NULL } }, + { "discovery", "Adjacencies", + { LDPCTL, "show", "discovery", NULL } }, + { "l2vpn", "Pseudowire", + { LDPCTL, "show", "l2vpn", OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 iscs[] = { + { "flows", "Display IPsec flows", + { IPSECCTL, "-sf", NULL } }, + { "sadb", "Display SADB", + { IPSECCTL, "-ss", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 ikcs[] = { + { "monitor", "Monitor internal iked messages", + { IKECTL, "monitor", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dvcs[] = { + { "igmp", "Internet Group Message Protocol", + { DVMRPCTL, "show", "igmp", NULL } }, + { "interfaces", "Interfaces", + { DVMRPCTL, "show", "interfaces", OPT, NULL } }, + { "mfc", "Multicast Forwarding Cache", + { DVMRPCTL, "show", "mfc", OPT, NULL } }, + { "neighbor", "Neighbor", + { DVMRPCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { DVMRPCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { DVMRPCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rlcs[] = { + { "hosts", "hosts", + { RELAYCTL, "show", "hosts", NULL } }, + { "redirects", "redirects", + { RELAYCTL, "show", "redirects", NULL } }, + { "status", "status", + { RELAYCTL, "show", "relays", NULL } }, + { "sessions", "sessions", + { RELAYCTL, "show", "sessions", NULL } }, + { "summary", "summary", + { RELAYCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 smcs[] = { + { "queue", "envelopes in queue", + { SMTPCTL, "show", "queue", NULL } }, + { "runqueue", "envelopes scheduled for delivery", + { SMTPCTL, "show", "runqueue", NULL } }, + { "stats", "runtime statistics", + { SMTPCTL, "show", "stats", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dhcs[] = { + { "leases", "leases", { 0 } }, + { 0, 0, { 0 } } +}; + +struct prot1 ldcs[] = { + { "stats", "statistics counters", + { LDAPCTL, "stats", NULL } }, + { 0, 0, { 0 } } +}; + +/* show yyy zzz */ +struct prot prots[] = { + { "bgp", bgcs }, + { "ospf", oscs }, + { "ospf6", os6cs }, + { "rip", rics }, + { "ike", ikcs }, + { "ipsec", iscs }, + { "ldp", lics }, + { "dvmrp", dvcs }, + { "relay", rlcs }, + { "smtp", smcs }, + { "ldap", ldcs }, + { 0, 0 } +}; diff --git a/freebsd/compile.sh b/freebsd/compile.sh new file mode 100644 index 0000000..3af29ec --- /dev/null +++ b/freebsd/compile.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +cat >compile.c <<__END +char compiled[] = "`/bin/date +"%d-%b-%y %H:%M"`"; +char compiledby[] = "`/usr/bin/whoami`"; +char compilehost[] = "`uname -n`"; +__END diff --git a/freebsd/complete.c b/freebsd/complete.c new file mode 100644 index 0000000..51fcbdd --- /dev/null +++ b/freebsd/complete.c @@ -0,0 +1,500 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/complete.c,v 1.19 2006/06/23 20:35:25 steven Exp $ */ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +#define ttyout stdout +#define ttyin stdin + +unsigned char complete(EditLine *, int, char **, size_t, char *); + +static int comparstr(const void *, const void *); +static unsigned char complete_ambiguous(char *, int, StringList *, EditLine *); +static unsigned char complete_command(char *, int, EditLine *, char **, int); +static unsigned char complete_subcommand(char *, int, EditLine *, char **, int); +static unsigned char complete_local(char *, int, EditLine *); +static unsigned char complete_ifname(char *, int, EditLine *); +static unsigned char complete_args(struct ghs *, char *, int, EditLine *, + char **, int, int); +static void list_vertical(StringList *); + +unsigned char complt_c(EditLine *, int); +unsigned char complt_i(EditLine *, int); +unsigned char exit_i(EditLine *, int); + +static int +comparstr(const void *a, const void *b) +{ + return (strcmp(*(char **)a, *(char **)b)); +} + +/* + * Determine if complete is ambiguous. If unique, insert. + * If no choices, error. If unambiguous prefix, insert that. + * Otherwise, list choices. words is assumed to be filtered + * to only contain possible choices. + * Args: + * word word which started the match + * list list by default + * words stringlist containing possible matches + */ +static unsigned char +complete_ambiguous(char *word, int list, StringList *words, EditLine *el) +{ + char insertstr[MAXPATHLEN]; + char *lastmatch; + int i, j; + size_t matchlen, wordlen; + + wordlen = strlen(word); + if (words->sl_cur == 0) + return (CC_ERROR); /* no choices available */ + + if (words->sl_cur == 1) { /* only once choice available */ + (void)strlcpy(insertstr, words->sl_str[0], sizeof insertstr); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + + if (!list) { + matchlen = 0; + if ((lastmatch = words->sl_str[0])) + matchlen = strlen(lastmatch); + for (i = 1 ; i < words->sl_cur ; i++) { + for (j = wordlen ; j < strlen(words->sl_str[i]); j++) + if (lastmatch[j] != words->sl_str[i][j]) + break; + if (j < matchlen) + matchlen = j; + } + if (matchlen > wordlen) { + (void)strlcpy(insertstr, lastmatch, matchlen+1); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + /* + * XXX: really want CC_REFRESH_BEEP + */ + return (CC_REFRESH); + } + } + + putc('\n', ttyout); + qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); + list_vertical(words); + return (CC_REDISPLAY); +} + +/* + * Complete a command + */ +static unsigned char +complete_command(char *word, int list, EditLine *el, char **table, int stlen) +{ + char **c; + struct ghs *ghs; + StringList *words; + size_t wordlen; + unsigned char rv; + + if (table == NULL) + return(CC_ERROR); + + words = sl_init(); + wordlen = strlen(word); + + for (c = table; *c != NULL; c = (char **)((char *)c + stlen)) { + ghs = (struct ghs *)c; + if (wordlen > strlen(ghs->name)) + continue; + if (strncmp(word, ghs->name, wordlen) == 0) + sl_add(words, ghs->name); + } + + rv = complete_ambiguous(word, list, words, el); + sl_free(words, 0); + return (rv); +} + +/* + * Complete a (sub)command + */ +static unsigned char +complete_subcommand(char *word, int list, EditLine *el, char **table, int stlen) +{ + struct ghs *ghs = NULL; + + if (table == NULL) + return(CC_ERROR); + + ghs = (struct ghs *)genget(margv[cursor_argc-1], table, stlen); + if (ghs == 0 || Ambiguous(ghs)) + return(CC_ERROR); + + /* + * XXX completion lists that hit subcommand tables don't get more than + * the first CMPL arg tested in complete_args as long as the level + * 0 is passed to complete_args + */ + return(complete_args(ghs, word, list, el, table, stlen, 0)); +} + +/* + * Complete a local file + */ +static unsigned char +complete_local(char *word, int list, EditLine *el) +{ + StringList *words; + char dir[MAXPATHLEN]; + char *file; + DIR *dd; + struct dirent *dp; + unsigned char rv; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '.'; + dir[1] = '\0'; + file = word; + } else { + if (file == word) { + dir[0] = '/'; + dir[1] = '\0'; + } else { + (void)strlcpy(dir, word, (size_t)(file - word) + 1); + } + file++; + } + + if ((dd = opendir(dir)) == NULL) + return (CC_ERROR); + + words = sl_init(); + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(file) > dp->d_namlen) + continue; + if (strncmp(file, dp->d_name, strlen(file)) == 0) { + char *tcp; + + tcp = strdup(dp->d_name); + if (tcp == NULL) + errx(1, "Can't allocate memory for local dir"); + sl_add(words, tcp); + } + } + closedir(dd); + + rv = complete_ambiguous(file, list, words, el); + sl_free(words, 1); + return (rv); +} + +unsigned char +exit_i(EditLine *el, int ch) +{ + printf("\n"); + return CC_EOF; +} + +unsigned char +complt_i(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)whichlist, sizeof(struct intlist), + NULL)); +} + +unsigned char +complt_c(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)cmdtab, sizeof(struct cmd), NULL)); +} + +unsigned char +complete_ifname(char *word, int list, EditLine *el) +{ + StringList *words; + size_t wordlen; + unsigned char rv; + + words = sl_init(); + wordlen = strlen(word); + + struct if_nameindex *ifn_list, *ifnp; + + if ((ifn_list = if_nameindex()) == NULL) + return 0; + + for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { + if (wordlen > strlen(ifnp->if_name)) + continue; + if (strncmp(word, ifnp->if_name, wordlen) == 0) + sl_add(words, ifnp->if_name); + } + + rv = complete_ambiguous(word, list, words, el); + if_freenameindex(ifn_list); + sl_free(words, 0); + return (rv); +} + +/* + * Generic complete routine + */ +unsigned char +complete(EditLine *el, int ch, char **table, size_t stlen, char *arg) +{ + static char word[256]; + static int lastc_argc, lastc_argo; + struct ghs *c; + const LineInfo *lf; + int celems, dolist; + size_t len; + + (void)ch; /* not used */ + lf = el_line(el); + len = lf->lastchar - lf->buffer; + if (len >= sizeof(line)) + return (CC_ERROR); + (void)memcpy(line, lf->buffer, len); + line[len] = '\0'; + cursor_pos = line + (lf->cursor - lf->buffer); + lastc_argc = cursor_argc; /* remember last cursor pos */ + lastc_argo = cursor_argo; + makeargv(); /* build argc/argv of current line */ + + if (margc == 0 || cursor_argo >= sizeof(word)) + return (CC_ERROR); + + dolist = 0; + + /* if cursor and word is same, list alternatives */ + if (lastc_argc == cursor_argc && lastc_argo == cursor_argo + && strncmp(word, margv[cursor_argc], cursor_argo) == 0) + dolist = 1; + else if (cursor_argo) + memcpy(word, margv[cursor_argc], cursor_argo); + word[cursor_argo] = '\0'; + + if (cursor_argc == 0) + return (complete_command(word, dolist, el, table, stlen)); + + if (arg == NULL) + arg = margv[0]; + c = (struct ghs *) genget(arg, table, stlen); + if (c == (struct ghs *)-1 || c == 0 || Ambiguous(c)) + return (CC_ERROR); + celems = strlen(c->complete); + + /* check for 'continuation' completes (which are uppercase) */ + if ((cursor_argc > celems) && (celems > 0) + && isupper((unsigned char)c->complete[celems-1])) + cursor_argc = celems; + + if (cursor_argc > celems) + return (CC_ERROR); + + return(complete_args(c, word, dolist, el, table, stlen, + cursor_argc - 1)); +} + +unsigned char +complete_args(struct ghs *c, char *word, int dolist, EditLine *el, char **table, + int stlen, int level) +{ +#ifdef CMPLDEBUG + printf("[%s]",&c->complete[level]); +#endif + switch (c->complete[level]) { + case 'l': /* local complete */ + case 'L': + return (complete_local(word, dolist, el)); + case 'c': /* command complete */ + case 'C': + return (complete_command(word, dolist, el, table, stlen)); + case 'i': + case 'I': + return (complete_ifname(word, dolist, el)); + case 't': /* points to a table */ + case 'T': + if (c->table == NULL) + return(CC_ERROR); + return (complete_command(word, dolist, el, c->table, c->stlen)); + case 'a': + case 'A': + if (c->table == NULL) + return(CC_ERROR); + return (complete_subcommand(word, dolist, el, c->table, c->stlen)); + case 'n': /* no complete */ + return (CC_ERROR); + } + + return (CC_ERROR); +} + +/* + * List words in stringlist, vertically arranged + */ +void +list_vertical(StringList *sl) +{ + int i, j, w; + int columns, width, lines; + char *p; + + width = 0; + + for (i = 0 ; i < sl->sl_cur ; i++) { + w = strlen(sl->sl_str[i]); + if (w > width) + width = w; + } + width = (width + 8) &~ 7; + + columns = 1; + if (columns == 0) + columns = 1; + lines = (sl->sl_cur + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + p = sl->sl_str[j * lines + i]; + if (p) + fputs(p, ttyout); + if (j * lines + i + lines >= sl->sl_cur) { + putc('\n', ttyout); + break; + } + if (p) + w = strlen(p); + else + w = 0; + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } + } + } +} + +/* + * this needs to be called before initedit() + */ +void +inithist() +{ + if (!histc) { + histc = history_init(); /* init the builtin history */ + history(histc, &ev, H_SETSIZE, 100); /* remember 100 events */ + } + if (!histi) { + histi = history_init(); + history(histi, &ev, H_SETSIZE, 100); + } +} + +void +endhist() +{ + if (histc) { + history_end(histc); /* deallocate */ + histc = NULL; + } + if (histi) { + history_end(histi); + histi = NULL; + } +} + +void +initedit() +{ + editing = 1; + + if (!elc) { + elc = el_init(__progname, stdin, stdout, stderr); + if (histc) + el_set(elc, EL_HIST, history, histc); /* use history */ + el_set(elc, EL_EDITOR, "emacs"); /* default type */ + el_set(elc, EL_PROMPT, cprompt); /* set the prompt + * function */ + el_set(elc, EL_ADDFN, "complt_c", "Command completion", + complt_c); + el_set(elc, EL_BIND, "\t", "complt_c", NULL); + el_source(elc, NULL); /* read ~/.editrc */ + el_set(elc, EL_SIGNAL, 1); + } + if (!eli) { + eli = el_init(__progname, stdin, stdout, stderr); + if (histi) + el_set(eli, EL_HIST, history, histi); + el_set(eli, EL_EDITOR, "emacs"); + el_set(eli, EL_PROMPT, iprompt); + el_set(eli, EL_ADDFN, "complt_i", "Command completion", + complt_i); + el_set(eli, EL_BIND, "\t", "complt_i", NULL); + el_set(eli, EL_ADDFN, "exit_i", "Exit", exit_i); + el_set(eli, EL_BIND, "^X", "exit_i", NULL); + el_set(eli, EL_BIND, "^D", "exit_i", NULL); + el_source(eli, NULL); + el_set(eli, EL_SIGNAL, 1); + } +} + +void +endedit() +{ + editing = 0; + + if (elc) { + el_end(elc); + elc = NULL; + } + if (eli) { + el_end(eli); + eli = NULL; + } +} diff --git a/freebsd/conf.c b/freebsd/conf.c new file mode 100644 index 0000000..47a258c --- /dev/null +++ b/freebsd/conf.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2002-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +void conf_db_single(FILE *, char *, char *, char *); +void conf_ctl(FILE *, char *, char *, int); +int scantext(char *, char *); + +#define TMPSIZ 1024 /* size of temp strings */ + +int +conf(FILE *output) +{ + char cpass[_PASSWORD_LEN+1]; + char hostbuf[MAXHOSTNAMELEN]; + + fprintf(output, "!\n"); + + gethostname (hostbuf, sizeof(hostbuf)); + fprintf(output, "hostname %s\n", hostbuf); + if (read_pass(cpass, sizeof(cpass))) { + fprintf(output, "enable secret blowfish %s\n", cpass); + } else { + if (errno != ENOENT) + printf("%% Unable to read run-time crypt repository:" + " %s\n", strerror(errno)); + } + fprintf(output, "!\n"); + conf_ctl(output, "", "motd", 0); + + fprintf(output, "!\n"); + + conf_ctl(output, "", "sshd", 0); + + fprintf(output, "!\n"); + + return(0); +} + +void conf_ctl(FILE *output, char *delim, char *name, int rtableid) +{ + FILE *conf; + struct daemons *x; + struct ctl *ctl; + char tmp_str[TMPSIZ], tmpfile[64]; + char *fenablenm = NULL, *fothernm = NULL, *flocalnm = NULL; + int defenable = 0, pntdrules = 0, pntdflag = 0, dbflag; + + x = (struct daemons *)genget(name, (char **)ctl_daemons, + sizeof(struct daemons)); + if (x == 0 || Ambiguous(x)) { + printf("%% conf_ctl: %s: genget internal failure\n", name); + return; + } + + /* print rules if they exist */ + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", x->tmpfile, rtableid); + if ((conf = fopen(tmpfile, "r")) != NULL) { + fprintf(output, "%s%s rules\n", delim, name); + for (;;) { + if(fgets(tmp_str, TMPSIZ, conf) == NULL) + break; + if(tmp_str[0] == 0) + break; + fprintf(output, "%s %s", delim, tmp_str); + } + fclose(conf); + fprintf(output, "%s!\n", delim); + pntdrules = 1; + } else if (errno != ENOENT || (errno == ENOENT && verbose)) + printf("%% conf_ctl: %s: %s\n", tmpfile, strerror(errno)); + + /* fill in argument names from table */ + for (ctl = x->table; ctl != NULL && ctl->name != NULL; ctl++) { + switch(ctl->flag_x) { + case DB_X_ENABLE_DEFAULT: + defenable = 1; + /* FALLTHROUGH */ + case DB_X_ENABLE: + fenablenm = ctl->name; + break; + case DB_X_LOCAL: + flocalnm = ctl->name; + break; + case DB_X_OTHER: + fothernm = ctl->name; + break; + case DB_X_DISABLE: + case DB_X_REMOVE: + case DB_X_DISABLE_ALWAYS: + case 0: + break; + default: + printf("%% conf_ctl: flag_x %d unknown\n", ctl->flag_x); + return; + } + } + + /* print rules as currently enabled in running time database */ + if ((dbflag = db_select_flag_x_dbflag_rtable("ctl", x->name, rtableid)) + < 0) { + printf("%% database ctl select failure (%s, %d)\n", x->name, rtableid); + return; + } + switch(dbflag) { + case DB_X_ENABLE: + fprintf(output, "%s%s %s\n", delim, x->name, fenablenm ? + fenablenm : "enable"); + pntdflag = 1; + break; + case DB_X_LOCAL: + fprintf(output, "%s%s %s\n", delim, x->name, flocalnm ? + flocalnm : "local"); + pntdflag = 1; + break; + case DB_X_OTHER: + fprintf(output, "%s%s %s\n", delim, x->name, fothernm ? + fothernm : "other"); + pntdflag = 1; + break; + case DB_X_DISABLE_ALWAYS: + fprintf(output, "%s%s disable\n", delim, x->name); + pntdflag = 1; + /* FALLTHROUGH */ + case DB_X_DISABLE: + defenable = 0; + break; + case DB_X_REMOVE: + case DB_X_ENABLE_DEFAULT: + case 0: + break; + default: + printf("%% conf_ctl: dbflag %d unknown\n", dbflag); + } + if (defenable) { + fprintf(output, "%s%s %s\n", delim, x->name, fenablenm ? + fenablenm : "enable"); + pntdflag = 1; + } + if (pntdrules && x->doreload) { + fprintf(output, "%s%s reload\n", delim, x->name); + pntdflag = 1; + } + if (pntdflag) + fprintf(output, "%s!\n", delim); +} + + +/* find string in file */ +int scantext(char *fname, char *string) +{ + FILE *file; + char line[128]; + int found = 0; + + if ((file = fopen(fname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", fname, strerror(errno)); + return(0); + } + + for (;;) { + if (fgets(line, sizeof(line), file) == NULL) + break; + if (strcmp(line, string) == 0) { + found = 1; + break; + } + } + + fclose(file); + return(found); +} + +void +conf_db_single(FILE *output, char *dbname, char *lookup, char *ifname) +{ + StringList *dbreturn; + dbreturn = sl_init(); + + if (db_select_flag_x_ctl(dbreturn, dbname, ifname) < 0) { + printf("%% conf_db_single %s database select failed\n", dbname); + } + if (dbreturn->sl_cur > 0) { + if (lookup == NULL) + fprintf(output, " %s\n", dbname); + else if (strcmp(dbreturn->sl_str[0], lookup) != 0) + fprintf(output, " %s %s\n", dbname, dbreturn->sl_str[0]); + } + sl_free(dbreturn, 1); +} diff --git a/freebsd/ctl.c b/freebsd/ctl.c new file mode 100644 index 0000000..ef80ea5 --- /dev/null +++ b/freebsd/ctl.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +/* service daemons */ +#define SSHD "/usr/sbin/sshd" + +/* table variable (for pkill usage) */ +static char table[16]; + +/* service routines */ +void call_editor(char *, char **, char *); +void ctl_symlink(char *, char *, char *); +int rule_writeline(char *, mode_t, char *); +int fill_tmpfile(char **, char *, char **); +int acq_lock(char *); +void rls_lock(int); + +/* master daemon list */ +struct daemons ctl_daemons[] = { +{ "sshd", "SSH", ctl_sshd, SSHDCONF_TEMP, 0600, 0, 255 }, +{ 0, 0, 0, 0, 0, 0 } +}; + +/* per-daemon commands, and their C or executable functions */ + +/* MOTD */ +struct ctl ctl_motd[] = { + { "edit", "edit message-of-the-day", + { "motd", NULL, NULL }, call_editor, 0, T_HANDLER }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +/* sshd */ +char *ctl_sshd_test[] = { SSHD, "-tf", REQTEMP, NULL }; +struct ctl ctl_sshd[] = { + { "enable", "enable service", + { SSHD, "-f", REQTEMP, NULL }, NULL, DB_X_ENABLE, T_EXEC }, + { "disable", "disable service", + { PKILL, table, "-f", SSHD, "-f", REQTEMP, NULL }, NULL, + DB_X_DISABLE, T_EXEC }, + { "edit", "edit configuration", + { "sshd", (char *)ctl_sshd_test, NULL }, call_editor, 0, + T_HANDLER_FILL1 }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +void +ctl_symlink(char *temp, char *real, char *z) +{ + rmtemp(temp); + symlink(real, temp); +} + +/* flag to other nsh sessions or nsh conf() that actions have been taken */ +void +flag_x(char *name, char *daemon, int dbflag, char *data) +{ + if (db_delete_flag_x_ctl(name, daemon) < 0) { + printf("%% database delete failure ctl ctl\n"); + return; + } + if (dbflag == DB_X_REMOVE) + return; + if (db_insert_flag_x(name, daemon, cli_rtable, dbflag, data) < 0) { + printf("%% database insert failure ctl ctl\n"); + } +} + +/* the main entry point into ctl.c from CLI */ +int +ctlhandler(int argc, char **argv, char *modhvar) +{ + struct daemons *daemons; + struct ctl *x; + char tmpfile[PATH_MAX]; + char *step_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char *tmp_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char **fillargs; + + /* loop daemon list to find table pointer */ + daemons = (struct daemons *) genget(hname, (char **)ctl_daemons, + sizeof(struct daemons)); + if (daemons == 0) { + printf("%% Internal error - Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(daemons)) { + printf("%% Internal error - Ambiguous argument %s\n", argv[1]); + return 0; + } + + if (cli_rtable > daemons->rtablemax) { + printf("%% Command %s not available via rtable %d\n", + daemons->name, cli_rtable); + return 0; + } + + snprintf(table, sizeof(table), "-T%d", cli_rtable); + if (daemons->tmpfile) + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + if (modhvar) { + /* action specified or indented command specified */ + if (argc == 2 && isprefix(argv[1], "rules")) { + /* skip 'X rules' line */ + return(0); + } + if (isprefix(modhvar, "rules")) { + if (!daemons->tmpfile) { + printf("%% writeline without tmpfile\n"); + return 0; + } + /* write indented line to tmp config file */ + rule_writeline(tmpfile, daemons->mode, saveline); + return 0; + } + } + if (argc < 2 || argv[1][0] == '?') { + gen_help((char **)daemons->table, "", "", sizeof(struct ctl)); + return 0; + } + + x = (struct ctl *) genget(argv[1], (char **)daemons->table, + sizeof(struct ctl)); + if (x == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(x)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + + fillargs = step_optreq(x->args, step_args, argc, argv, 2); + if (fillargs == NULL) + return 0; + + switch(x->type) { + /* fill_tmpfile will return 0 if tmpfile or args are NULL */ + case T_HANDLER: + /* pointer to handler routine, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) { + (*x->handler)(tmp_args[0], tmp_args[1], tmp_args[2]); + } else { + (*x->handler)(fillargs[0], fillargs[1], fillargs[2]); + } + break; + case T_HANDLER_FILL1: + /* pointer to handler routine, fill args @ args[1] pointer */ + if (fill_tmpfile((char **)fillargs[1], tmpfile, tmp_args)) + (*x->handler)(fillargs[0], tmp_args, fillargs[2]); + else + (*x->handler)(fillargs[0], (char **)fillargs[1], fillargs[2]); + break; + case T_EXEC: + /* command to execute via execv syscall, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) + cmdargs(tmp_args[0], tmp_args); + else + cmdargs(fillargs[0], fillargs); + break; + } + + if (x->flag_x != 0) { + flag_x("ctl", daemons->name, x->flag_x, NULL); + } + + return 1; +} + +int +fill_tmpfile(char **fillargs, char *tmpfile, char **tmp_args) +{ + int i; + + if (fillargs == NULL || tmpfile == NULL) + return 0; + + for (i = 0; i < NOPTFILL - 1; i++) { + if(fillargs[i] == NULL) { + break; + } + if(fillargs[i] == REQTEMP) { + tmp_args[i] = tmpfile; + } else { + tmp_args[i] = fillargs[i]; + } + } + return 1; +} + +void +call_editor(char *name, char **args, char *z) +{ + int fd, found = 0; + char *editor, tmpfile[64]; + struct daemons *daemons; + + for (daemons = ctl_daemons; daemons->name != 0; daemons++) + if (strncmp(daemons->name, name, strlen(name)) == 0) { + found = 1; + break; + } + + if (!found) { + printf("%% call_editor internal error\n"); + return; + } + + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + /* acq lock, call editor, test config with cmd and args, release lock */ + if ((editor = getenv("EDITOR")) == NULL) + editor = DEFAULT_EDITOR; + if ((fd = acq_lock(tmpfile)) > 0) { + char *argv[] = { editor, tmpfile, NULL }; + cmdargs(editor, argv); + chmod(tmpfile, daemons->mode); + if (args != NULL) + cmdargs(args[0], args); + rls_lock(fd); + } else + printf ("%% %s configuration is locked for editing\n", + daemons->propername); +} + +int +rule_writeline(char *fname, mode_t mode, char *writeline) +{ + FILE *rulefile; + + rulefile = fopen(fname, "a"); + if (rulefile == NULL) { + printf("%% Rule write failed: %s\n", strerror(errno)); + return(1); + } + if (writeline[0] == ' ') + writeline++; + fprintf(rulefile, "%s", writeline); + fclose(rulefile); + chmod(fname, mode); + return(0); +} + +int +acq_lock(char *fname) +{ + int fd; + char lockf[SIZE_CONF_TEMP + sizeof(".lock")]; + + /* + * some text editors lock (vi), some don't (mg) + * + * here we lock a separate, do-nothing file so we don't interfere + * with the editors that do... (lock multiple concurrent nsh users) + */ + snprintf(lockf, sizeof(lockf), "%s.lock", fname); + if ((fd = open(lockf, O_RDWR | O_CREAT, 0600)) == -1) + return(-1); + if (flock(fd, LOCK_EX | LOCK_NB) == 0) + return(fd); + else { + close(fd); + return(-1); + } +} + +void +rls_lock(int fd) +{ + /* best-effort, who cares */ + flock(fd, LOCK_UN); + close(fd); + return; +} + +void +rmtemp(char *file) +{ + if (unlink(file) != 0) + if (errno != ENOENT) + printf("%% Unable to remove temporary file %s: %s\n", + file, strerror(errno)); +} diff --git a/freebsd/editing.h b/freebsd/editing.h new file mode 100644 index 0000000..e9bc288 --- /dev/null +++ b/freebsd/editing.h @@ -0,0 +1,9 @@ +#include + +extern EditLine *elc; /* editline(3) status structure */ +extern EditLine *eli; /* another one */ +extern History *histc; /* command() editline(3) history structure */ +extern History *histi; /* interface() editline(3) status structure */ +extern char *cursor_pos; /* cursor position we're looking for */ +extern size_t cursor_argc; /* location of cursor in margv */ +extern size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ diff --git a/freebsd/externs.h b/freebsd/externs.h new file mode 100644 index 0000000..21a40eb --- /dev/null +++ b/freebsd/externs.h @@ -0,0 +1,562 @@ +/* + * nsh externs, prototypes and macros + */ + +#define NO_ARG(x) (strcasecmp(x, "no") == 0) /* absolute "no" */ + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) /* sys/param.h */ + +struct rtdump { + char *buf; /* start of routing table */ + char *lim; /* end of routing table */ +}; + +extern char *__progname; /* duh */ +extern char *vers; /* the version of nsh */ +extern char saveline[1024]; /* command line */ +extern char line[1024]; /* command line for makeargv() */ +extern int margc; /* makeargv() arg count */ +extern char *margv[]; /* makeargv() args */ +extern int verbose; /* is verbose mode on? */ +extern int editing; /* is command line editing mode on? */ +extern int bridge; /* are we in bridge mode (or interface mode?) */ +extern int priv; /* privileged mode or not? */ +//extern pid_t pid; /* process id of nsh */ +extern int cli_rtable; /* environment rtable */ + +#define HSIZE 64 +extern char hname[HSIZE]; /* prefix name to mode handler */ + +#ifdef _HISTEDIT_H_ +extern HistEvent ev; /* ev */ +#endif + +/* defaults */ +#define DEFAULT_MTU 1500 /* net.inet.ip.defmtu */ +#define DEFAULT_TTL 64 /* net.inet.ip.defttl */ +#define DEFAULT_MTTL 255 /* net.mpls.ttl */ +#define ESP_UDPENCAP_PORT 4500 /* net.inet.esp.udpencap_port */ + +/* nopt.c */ +#define no_arg 1 +#define req_arg 2 +struct nopts { + char *name; + int type; + int arg; +}; +extern int noptind; +extern char *nopterr; +int nopt(int, char **, struct nopts *); + +/* ppp.c */ +int intsppp(char *, int, int, char **); +int intpppoe(char *, int, int, char **); +void conf_pppoe(FILE *, int, char *); +void conf_sppp(FILE *, int, char *); + +/* conf.c */ +#define LEASEPREFIX "/var/db/dhclient.leases" +int conf(FILE *); +long default_mtu(char *); +int conf_routes(FILE *, char *, int, int, int); +int conf_dhcrelay(char *, char *, int); + +/* show.c */ +void p_rttables(int, int, int); +#ifdef _NETINET_IN_H_ +char *routename4(in_addr_t); +char *netname4(in_addr_t, struct sockaddr_in *); +#endif +#ifdef _NETINET6_IN6_H_ +char *routename6(struct sockaddr_in6 *); +char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); +void in6_fillscopeid(struct sockaddr_in6 *); +void in6_clearscopeid(struct sockaddr_in6 *); +#endif +#ifdef _SYS_SOCKET_H_ +char *routename(struct sockaddr *); +char *netname(struct sockaddr *, struct sockaddr *); +char *any_ntoa(const struct sockaddr *); +#endif + +/* alignment constraint for routing socket */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +/* routesys.c */ +#ifdef _NET_ROUTE_H_ +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; +#endif +#ifdef _WANT_SO_ +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + struct sockaddr_inarp sinarp; +}; +extern union sockunion so_dst, so_mask, so_gate, so_ifp; +#endif +#ifdef _NETINET6_IN6_H_ +int prefixlen(int, struct sockaddr_in6 *); +#endif +extern int rtm_addrs; +extern long rtm_inits; +#define FLUSH 0 +struct rtdump *getrtdump(int, int, int); +void freertdump(struct rtdump *); +int monitor(int, char **); +int rtmsg(int, int, int, int, int); +void flushroutes(int, int); +void bprintf(FILE *, int, char *); +#ifdef _NET_IF_DL_H_ +char *mylink_ntoa(const struct sockaddr_dl *); +#endif +extern char ifnetflags[]; +extern char routeflags[]; +extern char addrnames[]; +extern char metricnames[]; + +/* ctl.c */ +/* tmp config locations */ +#define PFCONF_TEMP "/var/run/pf.conf" +#define OSPFCONF_TEMP "/var/run/ospfd.conf" +#define OSPF6CONF_TEMP "/var/run/ospf6d.conf" +#define EIGRPCONF_TEMP "/var/run/eigrpd.conf" +#define BGPCONF_TEMP "/var/run/bgpd.conf" +#define RIPCONF_TEMP "/var/run/ripd.conf" +#define LDPCONF_TEMP "/var/run/ldpd.conf" +#define IPSECCONF_TEMP "/var/run/ipsec.conf" +#define IKECONF_TEMP "/var/run/iked.conf" +#define DVMRPCONF_TEMP "/var/run/dvmrpd.conf" +#define RTADVCONF_TEMP "/var/run/rtadvd.conf" +#define RELAYCONF_TEMP "/var/run/relayd.conf" +#define SASYNCCONF_TEMP "/var/run/sasyncd.conf" +#define DHCPCONF_TEMP "/var/run/dhcpd.conf" +#define SNMPCONF_TEMP "/var/run/snmpd.conf" +#define NTPCONF_TEMP "/var/run/ntpd.conf" +#define IFSTATE_TEMP "/var/run/ifstated.conf" +#define NPPPCONF_TEMP "/var/run/npppd.conf" +#define FTPPROXY_TEMP "/var/run/ftp-proxy" +#define TFTPPROXY_TEMP "/var/run/tftp-proxy" +#define TFTP_TEMP "/var/run/tftpd" +#define RESOLVCONF_TEMP "/var/run/resolv.conf" +#define RESOLVCONF_SYM "/var/run/resolv.conf.symlink" +#define RESOLVCONF_DHCP "/var/run/resolv.conf.dhcp" +#define INETCONF_TEMP "/var/run/inetd.conf" +#define SSHDCONF_TEMP "/var/run/sshd.conf" +#define SMTPCONF_TEMP "/var/run/smtpd.conf" +#define LDAPCONF_TEMP "/var/run/ldapd.conf" +#define IFSTATECONF_TEMP "/var/run/ifstated.conf" +#define MOTD_TEMP "/var/run/motd" + +/* argument list replacement */ +#define OPT (void *)1 +#define REQ (void *)2 +#define IFNAME (void *)3 +#define REQTEMP (void *)4 +#define SIZE_CONF_TEMP 64 +int ctlhandler(int, char **, char *); +void rmtemp(char *); +/* control programs */ +#define PFCTL "/sbin/pfctl" +#define OSPFCTL "/usr/sbin/ospfctl" +#define OSPF6CTL "/usr/sbin/ospf6ctl" +#define EIGRPCTL "/usr/sbin/eigrpctl" +#define BGPCTL "/usr/sbin/bgpctl" +#define RIPCTL "/usr/sbin/ripctl" +#define LDPCTL "/usr/sbin/ldpctl" +#define IPSECCTL "/sbin/ipsecctl" +#define IKECTL "/usr/sbin/ikectl" +#define DVMRPCTL "/usr/sbin/dvmrpctl" +#define RELAYCTL "/usr/sbin/relayctl" +#define SNMPCTL "/usr/sbin/snmpctl" +#define SMTPCTL "/usr/sbin/smtpctl" +#define LDAPCTL "/usr/sbin/ldapctl" +struct ctl { + char *name; + char *help; + char *args[32]; + void (*handler)(); + int flag_x; + int type; +}; +#define T_HANDLER 1 +#define T_HANDLER_FILL1 2 +#define T_EXEC 3 +struct daemons { + char *name; + char *propername; + struct ctl *table; + char *tmpfile; + mode_t mode; + int doreload; + int rtablemax; +}; +extern struct daemons ctl_daemons[]; +extern struct ctl ctl_pf[]; +extern struct ctl ctl_ospf[]; +extern struct ctl ctl_ospf6[]; +extern struct ctl ctl_eigrp[]; +extern struct ctl ctl_relay[]; +extern struct ctl ctl_bgp[]; +extern struct ctl ctl_rip[]; +extern struct ctl ctl_ldp[]; +extern struct ctl ctl_ipsec[]; +extern struct ctl ctl_nppp[]; +extern struct ctl ctl_ifstate[]; +extern struct ctl ctl_ike[]; +extern struct ctl ctl_dvmrp[]; +extern struct ctl ctl_rtadv[]; +extern struct ctl ctl_sasync[]; +extern struct ctl ctl_dhcp[]; +extern struct ctl ctl_snmp[]; +extern struct ctl ctl_smtp[]; +extern struct ctl ctl_sshd[]; +extern struct ctl ctl_ntp[]; +extern struct ctl ctl_ftpproxy[]; +extern struct ctl ctl_tftpproxy[]; +extern struct ctl ctl_tftp[]; +extern struct ctl ctl_dns[]; +extern struct ctl ctl_inet[]; +extern struct ctl ctl_ldap[]; +extern struct ctl ctl_motd[]; +void flag_x(char *, char *, int, char *); + +/* commands.c */ +#define NOPTFILL 7 +#define DEFAULT_EDITOR "/usr/bin/vi" +#define NSHRC_TEMP "/var/run/nshrc" +#define NSHRC "/etc/nshrc" +#define PING "/sbin/ping" +#define PING6 "/sbin/ping6" +#define TRACERT "/usr/sbin/traceroute" +#define TRACERT6 "/usr/sbin/traceroute6" +#define TELNET "/usr/bin/telnet" +#define SSH "/usr/bin/ssh" +#define PKILL "/usr/bin/pkill" +#define SAVESCRIPT "/usr/local/bin/save.sh" +#ifndef DHCPLEASES +#define DHCPLEASES "/var/db/dhcpd.leases" +#endif +void command(void); +char **step_optreq(char **, char **, int, char **, int); +int argvtostring(int, char **, char *, int); +int cmdrc(char rcname[FILENAME_MAX]); +int cmdargs(char *, char **); +char *iprompt(void); +char *cprompt(void); +char *pprompt(void); +int group (int, char **); +void gen_help(char **, char *, char *, int); +void makeargv(void); +extern size_t cursor_argc; +extern size_t cursor_argo; + +typedef struct cmd { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler) (); /* routine which executes command */ + int needpriv; /* Do we need privilege to execute? */ + int nocmd; /* Can we specify 'no ...command...'? */ + int modh; /* Is it a mode handler for cmdrc()? */ +} Command; + +typedef struct menu { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int minarg; /* Minimum number of arguments */ + int maxarg; /* Maximum number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ +} Menu; + +struct intlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler)(); /* Routine to perform (for special ops) */ + int bridge; /* 0 == Interface, 1 == Bridge, 2 == Both */ +}; + +/* generic help /complt struct */ +struct ghs { + char *name; + char *help; + char *complete; + char **table; + int stlen; +}; + +extern Command cmdtab[]; +extern struct intlist Intlist[]; +extern struct intlist Bridgelist[]; +extern struct intlist *whichlist; + +/* ieee80211.c */ +#define NWID 0 +#define NWKEY 1 +#define POWERSAVE 2 +#define TXPOWER 3 +#define BSSID 4 +#define DEFAULT_POWERSAVE 100 /* 100 ms */ +const char *get_string(const char *, const char *, __int8_t *, int *); +void make_string(char *str, int, const __int8_t *buf, int); +int get_nwinfo(char *, char *, int, int); +int get_nwpowersave(int, char *); +int intnwkey(char *, int, int, char **); +int inttxpower(char *, int, int, char **); +int intbssid(char *, int, int, char **); + +/* stats.c */ +void rt_stats(void); +void tcp_stats(void); +void udp_stats(void); +//void ip_stats(void); +void stats(void); +void icmp_stats(void); +void igmp_stats(void); +void ah_stats(void); +void esp_stats(void); +void ipip_stats(void); +void carp_stats(void); +void pfsync_stats(void); +void ipcomp_stats(void); + +/* mbuf.c */ +void mbpr(void); + +/* kread.c */ +char *plural(int); +char *plurales(int); + +/* genget.c */ +int isprefix(char *, char*); +char **genget(char *, char **, int); +int Ambiguous(void *); + +/* sysctl.c */ +int sysctl_int(int[], int, int); +int ipsysctl(int, char *, char *, int); +void conf_sysctls(FILE *); + +/* route.c */ +#define NO_NETMASK 0 +#define ASSUME_NETMASK 1 +int route(int, char**); +void show_route(char *, int); +int is_ip_addr(char *); +#ifdef _IP_T_ +void parse_ip_pfx(char *, int, ip_t *); +int ip_route(ip_t *, ip_t *, u_short, int, int, struct rt_metrics, int inits); +#endif +#ifdef _NETINET6_IN6_H_ +int parse_ipv6(char *, struct in6_addr *); +#endif + +/* if.c */ +#define DHCLIENT "/sbin/dhclient" +#define DHCRELAY "/usr/sbin/dhcrelay" +#define RTADVD "/usr/sbin/rtadvd" +#define IFDATA_MTU 1 /* request for if_data.ifi_mtu */ +#define IFDATA_BAUDRATE 2 /* request for if_data.ifi_baudrate */ +#define MBPS(bps) (bps / 1000 / 1000) +#define ROUNDMBPS(bps) ((float)bps == ((bps / 1000 / 1000) * 1000 * 1000)) +#define ROUNDKBPS(bps) ((float)bps == ((bps / 1000) * 1000)) +#define ROUNDKBYTES(bytes) ((float)bytes == ((bytes / 1024) * 1024)) +void imr_init(char *); +int is_valid_ifname(char *); +int show_int(int, char **); +int get_rdomain(int, char *); +int get_ifdata(char *, int); +int get_ifflags(char *, int); +int set_ifflags(char *, int, int); +int get_ifxflags(char *, int); +int set_ifxflags(char *, int, int); +int intip(char *, int, int, char **); +int intmtu(char *, int, int, char **); +int intkeepalive(char *, int, int, char **); +int intmpelabel(char *, int, int, char **); +int intrdomain(char *, int, int, char **); +int intdhcrelay(char *, int, int, char **); +int intmetric(char *, int, int, char **); +int intrtd(char *, int, int, char **); +int intvlan(char *, int, int, char **); +int intflags(char *, int, int, char **); +int intxflags(char *, int, int, char **); +int intaf(char *, int, int, char **); +int intlink(char *, int, int, char **); +int intnwid(char *, int, int, char **); +int intpowersave(char *, int, int, char **); +int intdesc(char *, int, int, char **); +int intpflow(char *, int, int, char **); +int intlladdr(char *, int, int, char **); +int intgroup(char *, int, int, char **); +int intrtlabel(char *, int, int, char **); +int intparent(char *, int, int, char **); +int intpatch(char *, int, int, char **); +int intmpw(char *, int, int, char **); +int addaf(char *, int, int); +int removeaf(char *, int, int); +char *get_hwdaddr(char *); + +/* main.c */ +void intr(void); + +/* version.c */ +int version(int, char **); + +/* compile.c */ +extern char compiled[], compiledby[], compiledon[], compilehost[]; + +/* bridge.c */ +long bridge_cfg(int, char *, int); +int bridge_confaddrs(int, char *, char *, FILE *); +int bridge_rules(int, char *, char *, char *, FILE *); +int bridge_list(int, char *, char *, char *, int, int); +int bridge_addrs(int, char *, char *, char *); +int set_ifflag(int, char *, short); +int clr_ifflag(int, char *, short); +int is_bridge(int, char *); +int brport(char *, int, int, char **); +int brval(char *, int, int, char **); +int brrule(char *, int, int, char **); +int brstatic(char *, int, int, char **); +int brpri(char *, int, int, char **); +int flush_bridgedyn(char *); +int flush_bridgeall(char *); +int flush_bridgerule(char *, char*); + +/* tunnel.c */ +int inttunnel(char *, int, int, char **); +int intvnetid(char *, int, int, char **); +int get_physrtable(int, char *); +int get_physttl(int, char *); +int get_vnetid(int, char *); + +/* media.c */ +#define DEFAULT_MEDIA_TYPE "autoselect" +void media_status(int, char *, char *); +void media_supported(int, char *, char *, char *); +int phys_status(int, char *, char *, char *, int, int); +int intmedia(char *, int, int, char **); +int intmediaopt(char *, int, int, char **); +int conf_media_status(FILE *, int, char *); + +/* passwd.c */ +#define NSHPASSWD_TEMP "/var/run/nshpasswd" +int read_pass(char *, size_t); +int gen_salt(char *, size_t); +int enable(int, char **); + +/* pfsync.c */ +#define PFSYNC_MAXUPDATES 128 +int intsyncdev(char *, int, int, char **); +int intsyncpeer(char *, int, int, char **); +int intmaxupd(char *, int, int, char **); +int conf_pfsync(FILE *, int, char *); + +/* carp.c */ +#define CARP_ADVSKEW 0 +#define CARP_ADVBASE 1 +#define CARP_VHID 2 +#define CARP_PEER 3 +#define CARP_BALANCING 4 +int intcarp(char *, int, int, char **); +int intcpass(char *, int, int, char **); +int intcnode(char *, int, int, char **); +int conf_carp(FILE *, int, char *); +int carp_state(int, char *); +int intcdev(char *, int, int, char **); + +/* trunk.c */ +int inttrunkport(char *, int, int, char **); +int inttrunkproto(char *, int, int, char **); +int conf_trunk(FILE *output, int ifs, char *ifname); +void show_trunk(int ifs, char *ifname); + +/* who.c */ +int who(int, char **); + +/* arp.c */ +int arpget(const char *); +int arpset(int, char **); +void arpdump(void); +void conf_arp(FILE *, char *); +//char *sec2str(time_t); + +/* more.c */ +int more(char *); +int nsh_cbreak(void); +void nsh_nocbreak(void); +void setwinsize(int); +#ifdef _SYS_TTYCOM_H_ +extern struct winsize winsize; +#endif + +/* complete.c */ +#define CMPL(x) __STRING(x), +#define CMPL0 "", +void inithist(void); +void endhist(void); +void initedit(void); +void endedit(void); + +/* utils.c */ +int string_index(char *, char **); +//char *format_time(time_t); +char *format_k(__uint64_t amt); + +/* sqlite3.c */ +/* sqlite3.c */ +#define SQ3DBFILE "/var/run/nsh.db" +#define DB_X_ENABLE 1 /* enable command */ +#define DB_X_DISABLE 2 /* disable command */ +#define DB_X_LOCAL 3 /* local control command */ +#define DB_X_OTHER 4 /* other command */ +#define DB_X_REMOVE 5 /* remove command */ +#define DB_X_ENABLE_DEFAULT 6 /* enable command, always prints enable until disabled */ +#define DB_X_DISABLE_ALWAYS 7 /* disable command, always prints if disabled */ +int db_create_table_rtables(void); +int db_create_table_flag_x(char *); +int db_create_table_nameservers(void); +int db_insert_flag_x(char *, char *, int, int, char *); +int db_insert_rtables(int, char *); +int db_insert_nameserver(char *); +int db_delete_rtables_rtable(int); +int db_delete_flag_x_ctl(char *, char *); +int db_delete_flag_x_ctl_data(char *, char *, char *); +int db_delete_nameservers(void); +#ifdef _STRINGLIST_H +int db_select_flag_x_ctl_data(StringList *, char *, char *, char *); +int db_select_flag_x_ctl(StringList *, char *, char *); +int db_select_rtable_rtables(StringList *); +int db_select_rtables_rtable(StringList *, int); +int db_select_rtables_ctl(StringList *, char *); +int db_select_name_rtable(StringList *, int); +int db_select_flag_x_ctl_rtable(StringList *, char *, int); +int db_select_flag_x_data_ctl_rtable(StringList *, char *, char *, int); +int db_select_nameservers(StringList *); +#endif +int db_select_flag_x_dbflag_rtable(char *, char *, int); + +/* pflow.c */ +#define PFLOW_SENDER 0 +#define PFLOW_RECEIVER 1 +#define PFLOW_VERSION 2 +#ifdef _SYS_SOCKET_H_ +int pflow_addr(const char *, struct sockaddr_storage *); +#endif +int pflow_status(int, int, char *, char *); diff --git a/freebsd/genget.c b/freebsd/genget.c new file mode 100644 index 0000000..e7b48f6 --- /dev/null +++ b/freebsd/genget.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include + +__FBSDID("$FreeBSD$"); + +#ifndef lint +#if 0 +static const char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95"; +#endif +#endif /* not lint */ + + +#include + +#include "misc-proto.h" + +#define LOWER(x) (isupper(x) ? tolower(x) : (x)) +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ +int +isprefix(char *s1, const char *s2) +{ + char *os1; + char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (LOWER(c1) == LOWER(c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + +char ** +genget(char *name, char **table, int stlen) +{ + char **c, **found; + int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ +int +Ambiguous(char **s) +{ + return(s == &ambiguous); +} diff --git a/freebsd/main.c b/freebsd/main.c new file mode 100644 index 0000000..7fd6984 --- /dev/null +++ b/freebsd/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002-2013 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +void usage(void); + +jmp_buf toplevel; + +char *vers = "1.0"; +int bridge = 0; /* bridge mode for interface() */ +int verbose = 0; /* verbose mode */ +int priv = 0, cli_rtable = 0; +int editing = 1; +pid_t pid; + +History *histi = NULL; +History *histc = NULL; +HistEvent ev; +EditLine *elc = NULL; +EditLine *eli = NULL; +char *cursor_pos = NULL; + +void intr(void); + +int +main(int argc, char *argv[]) +{ + int top, ch, iflag = 0, cflag = 0; + char rc[PATH_MAX]; + + if(getuid() != 0) + printf("%% Functionality limited without root privilege.\n"); + + pid = getpid(); + + while ((ch = getopt(argc, argv, "c:i:v")) != -1) + switch (ch) { + case 'c': + cflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'i': + iflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'v': + verbose = 1; + break; + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (cflag && iflag) + usage(); + if (argc > 0) + usage(); + if (iflag) + rmtemp(SQ3DBFILE); + + printf("%% NSH v%s\n", vers); + + if (iflag) { + /* + * Interpret config file and exit + */ + priv = 1; + + /* + * Set carp group carpdemote to 128 during initialization + */ + + cmdrc(rc); + + /* + * Initialization over + */ + + exit(0); + } + if (cflag) { + /* + * Interpret command file and exit + */ + priv = 1; + + cmdrc(rc); + + exit(0); + } + + top = setjmp(toplevel) == 0; + if (top) { + (void)signal(SIGWINCH, setwinsize); + (void)signal(SIGINT, (sig_t)intr); + (void)setwinsize(0); + } else + putchar('\n'); + + for (;;) { + command(); + top = 1; + } + + /* NOTREACHED */ + return 0; +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-v] [-i rcfile | -c rcfile]\n", __progname); + fprintf(stderr, " -v indicates verbose operation\n"); + fprintf(stderr, " -i rcfile loads initial system" \ + " configuration from rcfile\n"); + fprintf(stderr, " -c rcfile loads commands from rcfile\n"); + exit(1); +} + +void +intr(void) +{ + longjmp(toplevel, 1); +} diff --git a/freebsd/misc-proto.h b/freebsd/misc-proto.h new file mode 100644 index 0000000..e5559ab --- /dev/null +++ b/freebsd/misc-proto.h @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)misc-proto.h 8.1 (Berkeley) 6/4/93 + * $FreeBSD$ + */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __MISC_PROTO__ +#define __MISC_PROTO__ + +void auth_encrypt_init(char *, char *, const char *, int); +void auth_encrypt_connect(int); +void printd(const unsigned char *, int); + +int isprefix(char *, const char *); +char **genget(char *, char **, int); +int Ambiguous(char **); + +int getent(char *, const char *); +char *Getstr(const char *, char **); + +/* + * These functions are imported from the application + */ +int net_write(unsigned char *, int); +void net_encrypt(void); +int telnet_spin(void); +char *telnet_getenv(char *); +char *telnet_gets(const char *, char *, int, int); +void printsub(char, unsigned char *, int); +#endif diff --git a/freebsd/more.c b/freebsd/more.c new file mode 100644 index 0000000..4e037df --- /dev/null +++ b/freebsd/more.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +#define PAGERPROMPT " --More-- " +#define BACKOVERPROMPT "\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b" + +int nsh_cbreak(void); +void nsh_nocbreak(void); + +static struct termios oldtty; + +struct winsize winsize; + +/* + * Display file + */ +int +more(char *fname) +{ + FILE *f; + char *input, c; + size_t s; + int i, nopager = 0; + + if ((f = fopen(fname, "r")) == NULL) { + if (errno == ENOENT) + printf ("%% File %s not found\n", fname); + else + printf ("%% more: fopen(%s): %s\n", fname, + strerror(errno)); + return(0); + } + + if (nsh_cbreak() < 0) + nopager = 1; + + for (i = 0; (input = fgetln(f, &s)) != NULL; i++) { + + if (!nopager && i == (winsize.ws_row - 1)) { + printf(PAGERPROMPT); + fflush(0); + c = getchar(); + printf(BACKOVERPROMPT); + if (c == 'q') + break; /* stop */ + if (c == '\r' || c == '\n') + i--; /* skip one line */ + else + i = 0; /* skip one page */ + } + + /* + * We replace newline (or whatever was at the end of + * the line) with NUL termination + */ + input[s-1] = '\0'; + printf("%s\n", input); + } + + if (!nopager) + nsh_nocbreak(); + + fclose(f); + return(1); +} + +int +nsh_cbreak(void) +{ + struct termios newtty; + + if (tcgetattr(fileno(stdout), &oldtty) < 0) + return(-1); + + (void)memcpy(&newtty, &oldtty, sizeof(newtty)); + + newtty.c_lflag &= ~(ECHO | ICANON); /* no echo, canonical */ + newtty.c_cc[VMIN] = 1; /* one char at a time */ + newtty.c_cc[VTIME] = 0; /* no timeout */ + + if (tcsetattr(fileno(stdout), TCSAFLUSH, &newtty) < 0) + return(-1); + return(0); +} + +void +nsh_nocbreak(void) +{ + tcsetattr(0, TCSAFLUSH, &oldtty); +} + +void +setwinsize(int signo) +{ + int save_errno = errno; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) { + winsize.ws_col = winsize.ws_col ? winsize.ws_col : 80; + winsize.ws_row = winsize.ws_row ? winsize.ws_row : 24; + } else { + winsize.ws_col = 80; + winsize.ws_row = 24; + } + + errno = save_errno; +} diff --git a/freebsd/nlist_symbols b/freebsd/nlist_symbols new file mode 100644 index 0000000..1c09d81 --- /dev/null +++ b/freebsd/nlist_symbols @@ -0,0 +1,54 @@ +# $FreeBSD$ +# +# module_name symbol_name +all _ahstat +all _arpstat +all _carpstats +all _divcbinfo +all _espstat +all _icmp6stat +all _icmpstat +all _igmpstat +all _ip6stat +all _ipcompstat +all _ipsec4stat +all _ipsec6stat +all _ipstat +all _mf6ctable +all _mfchashtbl +all _mfctablesize +all _mif6table +all _mrt6stat +all _mrtstat +all _netisr_bindthreads +all _netisr_defaultqlimit +all _netisr_dispatch_policy +all _netisr_maxprot +all _netisr_maxqlimit +all _netisr_maxthreads +all _netisr_proto +all _ngsocklist +all _nws +all _nws_array +all _nws_count +all _pfkeystat +all _pfsyncstats +all _pim6stat +all _pimstat +all _rip6stat +all _ripcbinfo +all _rtree +all _rtstat +all _sctpstat +all _sfstat +all _tcbinfo +all _tcpstat +all _tcps_states +all _udbinfo +all _udpstat +all _unp_count +all _unp_dhead +all _unp_gencnt +all _unp_shead +all _unp_sphead +all _viftable diff --git a/freebsd/nsh.8 b/freebsd/nsh.8 new file mode 100644 index 0000000..655bc23 --- /dev/null +++ b/freebsd/nsh.8 @@ -0,0 +1,4334 @@ +.\" $OpenBSD: nsh.8,v 1.1 2023/03/15 23:22:00 UTC chrisc Exp $ +.\" +.\" Copyright (c) 2002-2023 Chris Cappuccio. 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. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. +.\" +.Dd $Mdocdate: March 15 2023 $ +.Dt NSH 8 +.Os +.Sh NAME +.Nm nsh +.Nd network configuration shell +.Sh SYNOPSIS +.Nm nsh +.Op Fl v +.Op Fl i Ar rcfile +.Op Fl c Ar config-script-file +.Sh DESCRIPTION +.Nm +is a command interpreter intended for both interactive and shell script use. +.Nm +is an alternative to: +.Xr ifconfig 8 , +.Xr sysctl 8 , +.Xr route 8 , +and encapsulates configuration for other daemons into one place. +.Nm +provides an alternative to: +.Xr netstart 8 +and parts of +.Xr rc 8 . +.Nm +has its own command language similar to the configuration language used by +many network appliance vendors. +.Pp +.Nm +encapsulates the many available networking services and daemons that are +included in +.Ox +base, see the +.Sx SEE ALSO +section for a complete list. +.Pp +.Nm +is a shell to configure +.Ox +kernel's networking functions such as routing +of packets, firewalling, network address translation, rate limiting, +bandwidth queueing, LAN bridging, IP tunnelling, and encryption. +.Nm +provides simple wrappers around these functions to aid setting up a network. +The goals of this software are: +.Bl -dash +.It +Make the command syntax uniform +.It +Bring all configuration together in a single configuration file +.It +Provide a wrapper for any +.Ox +ctl utility such as +.Xr ospfctl 8 , +.Xr ipsecctl 8 , +and +.Xr bgpctl 8 . +.El +.Pp +.Nm +encapsulates those configuration files, so that their native configuration +files are encapsulated within the +.Nm +configuration framework. +.Nm +does not in any way obfuscate the configuration syntax that is utilised or +provided by these ctl.c based programs. +.Nm +allows the administrator to view and edit all configuration in one place. +.Ss COMMAND LINE ARGUMENTS +When +.Nm +is run without arguments it loads an interactive shell. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl v +.Nm +produce verbose output +.It Fl c Ar config-script-file +.Nm +execute the command(s) in the +.Ar config-script-file . +This is typically used to implement scripted changes to configuration. +.It Fl i Ar rcfile +load the initial system configuration from the command(s) in the +.Ar rcfile . +This is typically used to clear the configuration and load a full +.Nm +configuration script from rcfile . +.El +.Ss INTERACTIVE FEATURES +When run without any command line arguments, +.Nm +presents an unprivileged shell to the user. +All +.Nm +interactive command line modes allow basic command line editing features from +.Xr editline 7 +library. +The command history of the current session is available through the up / down +arrow keys. +.Pp +It is possible to repeat the commands from the command history. +.Pp +Any command can be abbreviated as long as the abbreviation is not ambiguous. +e.g. 'show running-config' can be abbreviated to 'sho run'. +.Pp +If the user enters a command that is ambiguous +.Nm +warns the user with 'Ambiguous argument' message, +e.g. ambiguous command entry. +.Bd -literal -offset indent +nsh/show i +% Ambiguous argument i +.Ed +.Ss Command line completion +.Nm +has double command line completion for user convenience if the command +is not ambiguous double completes the command. +If what is typed is ambiguous double tab presents the administrator +with the available command line options that match what has been typed thus +far. +.Bl -dash +.It +E.g. command line completion display +.Bd -literal -offset indent +nsh(p)/i +ifstate inet ip ipsec +ike interface ip6 +.Ed +.El +.Ss Command History +Use the up arrow on most keyboards to review the previous commands entered in +the current session. +The command being currently viewed can be repeated by hitting enter. +.Ss Reversing Commands +.Nm +commands can be reversed in the following ways: +.Bl -dash +.It +Any affirmative commands that do not contain +.Ic enable +keyword can be reversed +with the +.Ic no +keyword in front of the affirmative version of the command. +e.g. reverse allowing IP packet forwarding. +.Bd -literal -offset indent +nsh(p)/ip forwarding +nsh(p)/no ip forwarding +.Ed +.It +Any affirmative commands that contain +.Ic enable +keyword can be reversed +with +.Ic disable +keyword. +E.g reverse enabling packet filter firewall command. +.Bd -literal -offset indent +nsh(p)/pf enable +%pf enabled +nsh(p)/pf disable +%pf disabled +.Ed +.El +.Ss Standard Prompt vs Privileged Prompt +.Nm +shell starts as an unprivileged prompt which displays as the text of the FQDN +(fully qualified domain name) of the machine followed by a forward slash. +.Bl -dash +.It +e.g. standard prompt of the device firewall.machine.com +.Bd -literal -offset indent +firewall.machinename.com/ +.Ed +.El +The privileged shell is accessed using the enable command. +The privileged shell has the FQDN of the machine followed by (p) to indicate +privileged and followed by a / +.Bl -dash +.It +e.g. privileged shell prompt of the device firewall.machine.com +.Bd -literal -offset indent +firewall.machinename.com(p)/ +.Ed +.El +.Pp +For the purposes of this manual, any examples the machine is called +.Nm +. +.Bl -dash +.It +e.g. standard prompt appearing in examples in this manual +.Bd -literal -offset indent +nsh/ +.Ed +.It +e.g. privileged prompt appearing in examples in this manual +.Bd -literal -offset indent +nsh(p)/ +.Ed +.El +.Sh INTERACTIVE COMMANDS +.Tg help +.Ic ? | help +.Op nsh-command +.Pp +Display available commands and options that can used in the current +.Nm +mode. +The help or ? can be followed by a +.Nm +command, +.Nm +displays the purpose of the specified command. +.Bl -dash +.It +E.g. display help on the rtable command +.Bd -literal -offset indent +nsh(p)/? rtable +% rtable: Routing table switch +.Ed +.It +E.g. display help for all available commands. +.Bd -literal -offset indent +nsh(p)/help +% Commands may be abbreviated. +% Commands are: + + hostname Set system hostname + interface Modify interface parameters + rtable Routing table switch + group Modify group attributes + arp Static ARP set + ndp Static NDP set + nameserver set or remove static DNS nameservers + bridge Modify bridge parameters + show Show system information + ip Set IP networking parameters + ip6 Set IPv6 networking parameters + mpls Set MPLS network parameters + ddb Set DDB parameters + pipex Set PIPEX parameters + flush Flush system tables + enable Enable privileged mode + disable Disable privileged mode + route Add a host or network route + pf Packet filter control + ospf OSPF control + ospf6 OSPF6 control + eigrp EIGRP control + bgp BGP control + rip RIP control + ldp LDP control + relay Relay control + ipsec IPsec IKEv1 control + ike IPsec IKEv2 control + dvmrp DVMRP control + rad Router advertisement control + sasync SA synchronization control + dhcp DHCP server control + snmp SNMP server control + ldap LDAP server control + smtp SMTP server control + sshd SSH server control + ntp NTP synchronization control + nppp PPP server control + ifstate ifstate server control + ftp-proxy ftp-proxy server control + tftp-proxy tftp-proxy server control + tftp TFTP server control + resolv Resolver configuration control + motd Message of-the-day + inet Inet super-server control + ping Send IPv4 ICMP echo request + ping6 Send IPv6 ICMP echo request + traceroute Print the route to IPv4 host + traceroute6 Print the route to IPv6 host + ssh SSH connection to remote host + telnet Telnet connection to remote host + reboot Reboot the system + halt Halt the system + write-config Save the current configuration + verbose Set verbose diagnostics + editing Set command line editing + who Display system users + ! Invoke a subshell + ? Print help information + quit Close current connection +nsh(p)/ +.Ed +.El +.Tg hostname +.Ic hostname +.Op Ar hostname +.Pp +hostname without arguments displays the current configured hostname +of the system. +hostname with an argument will set hostname to the argument's value. +.Bl -dash +.It +e.g. set hostname to the myfirewallname.com . +.Bd -literal -offset indent +nsh(p)/hostname myfirewallname.com +myfirewallname.com(p)/ +.Ed +.El +.Tg enable +.Ic enable +Start a privileged shell to allow the user run privleged configuration +commands. +i.e. enable privileged command shell mode. +If an enable secret or password is set, the user shall be prompted to enter +the password to access the privileged shell. +.Pp +.Op no +.Ic enable Ar secret +.Pp +Set or the password that an administrator would enter to access the privileged +shell. +.Bl -dash +.It +e.g. Set a password manually to yourpassword +.Bd -literal -offset indent +nsh(p)/enable secret yourpassword +.Ed +.It +e.g. Set a password using a previously set encrypted password +.Bd -literal -offset indent +nsh(p)/enable secret blowfish $2b$10$kKSJFDd....NqIUaTCZ0= +.Ed +.El +.Pp +.Tg disable +.Ic disable +.Pp +Exit privileged mode. +Useful if you have completed configuration but still want the ability to run +diagnostics in an unprivileged +.Nm +shell. +.Pp +.Tg rtable +.Tg rdomain +.Op no +.Ic rtable +.Op Ar table-id +.Op Ar name +.Pp +rtable when used with a specified table-id can execute services, diagnostic +commands (ping, traceroute) and set routes under alternate routing tables. +The default +.Ox +kernel can accommodate 256 rtables. +They have a 1:1 relationship with routing domains, except that routing domain 0 +can contain multiple routing tables. +In addition, routing tables initialized prior to their corresponding +routing domain +.Xr rdomain 4 +, shall be initialised with a routing domain of 0. +.Bl -dash +.It +e.g. Create a new routing table rdomain 3 create a loopback for rdomain 3. +.Bd -literal -offset indent +nsh(p)/interface lo3 +nsh(interface-lo3)/rt +nsh(interface-lo3)/rdomain 3 +nsh(interface-lo3)/ip 127.0.0.1/8 +.Ed +.It +configure a physical interface +.Bd -literal -offset indent +nsh(p)/interface em0 +nsh(interface-em0)/rdomain 3 +nsh(interface-em0)/ip 10.255.0.10/24 +.Ed +.It +Once the rdomain has been initialized (by creating a loopback inside the + rdomain) the administrator can add routes to the rtable. +.Bd -literal -offset indent +nsh(p)/rtable 3 customer label network3 +nsh(p-rtable 3)/route 0.0.0.0/0 10.255.0.1 +.Ed +.It +One can configure any service or daemon inside that routing domain e.g. +to setup ssh in rdomain 3 +.Bd -literal -offset indent +nsh(p-rtable 3)/sshd edit +nsh(p-rtable 3)/sshd enable +.Ed +.It +The rtable command also supports unprivileged mode usage to execute +diagnostic commands in the respective route domain / VRF. +.Bd -literal -offset indent +nsh(p)/disable +nsh/rtable 3 +nsh(rtable 3)/ping 10.255.0.10 +%PING 10.255.0.10 (10.255.0.10): 56 data bytes +%64 bytes from 10.255.0.10: icmp_seq=0 ttl=255 time=0.090 ms +.Ed +.It +To leave the rtable menu the user can type rtable 0 to return to the main +routing table. +.Bd -literal -offset indent +nsh(p-rtable 3)/rtable 0 +nsh(p)/ +.Ed +.El +.Pp +.Tg group +.Op no +.Ic group +.Op Ar group-name +.Op Cm carpdemote +.Op demotion-counter +.Pp +Modify group attributes for the group-name named group. +TBC +.Pp +.Tg arp +.Op no +.Ic arp +.Op Ar IPv4-Address +.Op Ar MAC-Address +.Pp +Set or remove a static IP address and MAC address binding for Address +Resolution Protocol. +TBC +.Pp +.Tg ndp +.Op no +.Ic ndp +.Op Ar IPv6-Address +.Op Ar MAC-Address +.Op Cm temp +.Op Cm proxy +.Pp +Set or remove a static IPv6 address and MAC address binding for the +IPv6 Neighbour Discovery Protocol (NDP). +The entry will be permanent unless the word +.Cm temp +is given in the command. +If the word +.Cm proxy +is given, this system will act as an ND Proxy server, +responding to requests for +.Ar IPv6-Address +even though the MAC address is not its own. +.Pp +.Tg bridge +.Tg tpmr +.Tg veb +.Tg switch +.Tg layer2 +.Op no +.Ic bridge +.Op Ar bridge-name +.Pp +Modify bridge configuration on the named bridge or layer 2 +forwarding interfaces such as, +.Xr bridge 4 , +.Xr veb 4 , +.Xr tpmr 4 . +See also +.Ox +manual pages for +.Xr bridge 4 , +.Xr veb 4 , +.Xr tpmr 4 +and +.Xr ifconfig 8 +(accessible via the following nsh +commands): +.Bd -literal -offset indent +!man bridge +!man ifconfig +.Ed +.Bl -dash +.It +e.g. configure bridge settings on bridge1. and display bridge configuration +help. +.El +E.g show available bridge configuration commands. +.Bd -literal -offset indent +nsh(p)/bridge bridge1 +nsh(bridge-bridge1)/? +% Commands may be abbreviated. +% Type 'exit' at a prompt to leave bridge configuration mode. +% Bridge configuration commands are: + + description Bridge description + member Bridge member(s) + span Bridge spanning port(s) + blocknonip Block non-IP traffic forwarding on member(s) + discover Mark member(s) as discovery port(s) + learning Mark member(s) as learning port(s) + stp Enable 802.1D spanning tree protocol on member(s) + maxaddr Maximum address cache size + timeout Address cache timeout + maxage Time for 802.1D configuration to remain valid + fwddelay Time before bridge begins forwarding packets + hellotime 802.1D configuration packet broadcast interval + priority Spanning priority for all members on an 802.1D bridge + rule Bridge layer 2 filtering rules + static Static bridge address entry + ifpriority Spanning priority of a member on an 802.1D bridge + ifcost Spanning tree path cost of a member on 802.1D bridge + link Link level options + txprio Priority in tunnel protocol headers + rxprio Source used for packet priority + vnetid Virtual interface network identifier + parent Parent interface + tunneldomain Tunnel parameters + protect Configure protected bridge domains + shutdown Shutdown bridge + ? Options +.Ed +.eg. configure a standard +.Xr bridge 4 +device called bridge101 and add vlan 101 and vether101 as member ports. +.Bd -literal -offset indent +nsh(p)/bridge bridge101 +nsh(bridge-bridge101)/member vether101 +nsh(bridge-bridge101)/member vlan101 +nsh(bridge-bridge101)/exit +.Ed +E.g. configure a virtual ethernet bridge +.Xr veb 4 +device called veb101 and add vlan 101 and vether101 as member ports. +.Bd -literal -offset indent +nsh(p)/bridge veb101 +nsh(bridge-veb101)/member vether101 +nsh(bridge-veb101)/member vlan101 +nsh(bridge-veb101)/exit +.Ed +.eg. configure a virtual ethernet bridge +.Xr veb 4 +device called veb101 and add vlan 101 and vether101 as member ports. +.Bd -literal -offset indent +nsh(p)/bridge tpmr101 +nsh(bridge-tpmr101)/member vether101 +nsh(bridge-tpmr101)/member vlan101 +nsh(bridge-tpmr101)/exit +.Ed +Note +.Xr tpmr 4 +is a layer 2 mac relay and it does not have layer2 to physical +interface mac learning capabilities it is simply a relay, its +purpose is to minimise processing when forwarding packets +transparently between two and only two interfaces on a machine. +Consequentially not all bridge configuration commands will be accepted by +the system. +If an unsupported command is issued to a tpmr interface the system will +display the following when rejecting the configuration command +.Bd -literal -offset indent +% Inappropriate ioctl for device +.Ed +.Tg ip6 +.Op no +.Ic ip6 +.Op Cm \&? | forwarding | mforwarding | multipath | maxifprefixes | maxifdefrouters | maxdynroutes +.Pp +Configure IPv6 networking parameters, +such as forwarding, multicast forwarding, multipath routing, etc. +.Bl -dash +.It +e.g. list available IPv6 configuration options +.Bd -literal -offset indent +nsh(p)/ip6 +% Commands may be abbreviated. +% 'ip6' commands are: + forwarding Enable IPv6 Forwarding + mforwarding Enable IPv6 Multicast Forwarding + multipath Multipath routing + maxdynroutes Max IPv6 Dyn Routes + ? Help +.Ed +.El +.Pp +.Op no +.Ic ip6 forwarding +.Pp +Enable or disable forwarding (routing /NAT) of IPv6 packets through the +kernel. +.Bd -literal -offset indent +nsh(p)/ip6 forwarding +.Ed +.Pp +.Op no +.Ic ip6 forwarding +.Pp +Enable or disable forwarding of IPv6 multicast packets through the +kernel. +.Bd -literal -offset indent +nsh(p)/ip6 mforwarding +.Ed +.Pp +.Op no +.Ic ip6 multipath +.Pp +Enable or disable multipath routing for IPv6 addresses. +If multipath is disabled, only the first selected route is used for a +given destination regardless of how many routes exist in the routing table. +.Bd -literal -offset indent +nsh(p)/ip6 multipath +.Ed +.Pp +.Op no +.Ic ip6 maxdynroutes +.Op Ar max-route-value +.Pp +Set or disable the limit on maximum number of IPv6 routes created as a result +of incomming ICMPv6 redirects. +The max-route-value can be set to any value 0-20480 or -1. +A value of 0 prevents any routes being created as a result of incoming ICMPv6 +redirects. +Set to -1 to disable the limit. +The default value for maxdynroutes is 4096. +.Bd -literal -offset indent +nsh(p)/ip6 maxdynroutes 8192 +.Ed +.Tg mpls +.Op no +.Ic mpls +.Op Cm \&? | ttl | mapttl-ip | mapttl-ip6 +Configure MPLS (Multi Protocol Label Switching) network parameters in the +kernel. +.Bd -literal -offset indent +nsh(p)/mpls ? +% Commands may be abbreviated. +% 'mpls' commands are: + + ttl MPLS ttl + mapttl-ip MPLS mapttl IPv4 + mapttl-ip6 MPLS mapttl IPv6 + ? Help +.Ed +.Pp +.Op no +.Ic mpls ttl +.Op Ar 0-255 +.Pp +Configure the default MPLS (Multi Protocol Label Switching) TTL (time to live) +in the kernel for MPLS shim headers of generated (not forwarded) MPLS packets. +The default value is 255. +.Bd -literal -offset indent +nsh(p)/mpls ttl 64 +.Ed +.Pp +.Op no +.Ic mpls mapttl-ip +.Op Ar 0-1 +.Pp +Set or unset whether the kernel decrements the TTL of the IP packet +header that is encapsulated in mpls packet, when the packet is mpls label +switched (forwarded via MPLS). +This is useful when diagnosing failures in the forwarding path of an +MPLS tunnel. +If set to 0, the encapsulated payload IP header TTL is not modified while +passing through MPLS and the MPLS label stack. +The default value is 1. +.Bd -literal -offset indent +nsh(p)/mpls mapttl-ip 1 +.Ed +.Pp +.Op no +.Ic mpls mapttl-ip6 +.Op Ar 0-1 +.Pp +Set or unset whether or not the kernel decrements the TTL of the IPv6 +packet header that is encapsulated in mpls packet, when the packet is mpls +label switched (forwarded via MPLS). +This feature is useful when diagnosing failures in the forwarding path of an +MPLS tunnel. +If set to 0, the encapsulated payload IPv6 header TTL field is not modified +while passing through MPLS and the MPLS label stack. +The default value is 0. +.Bd -literal -offset indent +nsh(p)/mpls mapttl-ip6 1 +.Ed +.Pp +.Tg ddb +.Op no +.Ic ddb +.Op Cm \&? | panic | console | log +.Pp +Configure or remove kernel debug (DDB) options. +.Bd -literal -offset indent +nsh(p)/ddb ? +% Commands may be abbreviated. +% 'ddb' commands are: + + panic DDB panic + console DDB console + log DDB log + ? Help + +.Ed +.Pp +.Op no +.Ic ddb panic +.Pp +Enable or disable dropping the system to the kernel debugger in the event of a +system panic. +By default, dropping to the ddb debugger in a system panic is enabled. +.Bd -literal -offset indent +nsh(p)/ddb panic +.Ed +.Pp +.Op no +.Ic ddb console +.Pp +Enable access to the kernel debugger from the console using an +architecture-dependent magic key sequence on the console or a debugger button. +When running +.Ox +with a +.Xr securelevel 7 +greater than 0, this feature cannot be enabled. +By default accessing the ddb debugger from the console is disabled. +.Bd -literal -offset indent +nsh(p)/ddb console +.Ed +.Pp +.Op no +.Ic ddb log +.Pp +Enable or disable logging the output of the kernel debugger in the kernel +message buffer. +By default ddb debugger output logging to the kernel message buffer is +enabled. +.Bd -literal -offset indent +nsh(p)/ddb log +.Ed +.Pp +.Tg pipex +.Op no +.Ic pipex +.Op Cm \&? | enable +.Pp +Enable or disable +.Xr pipex 4 +processing on +.Xr pppac 4 +and +.Xr pppx 4 +interfaces. +.Xr pipex 4 +handles PPP frames and forwards IP packets in-kernel. +It accelerates the performance of packet forwarding, because it reduces +copying of packets between kernel and userland. +By default pipex is disabled. +.Bd -literal -offset indent +nsh(p)/pipex enable +.Ed +.Tg packetfilter +.Tg firewall +.Tg pf +.Ic pf +.Op Cm \&? | enable | disable | edit | reload +.Pp +Control the configuration and operation of the pf (Packet Filter) firewall. +.Bd -literal -offset indent +nsh(p)/pf ? +% Arguments may be abbreviated + + enable enable service + disable disable service + edit edit configuration + reload reload service +.Ed +.Pp +.Ic pf edit +.Pp +Open the default system editor and edit the firewall configuration. +The edited ruleset is automatically validated on saving and exiting the editor. +Note! firewall configuration changes DO NOT take effect until the "pf reload" +command is entered. +The editor used by nsh can be customised to your preferred editor using the +EDITOR and VISUAL environment variables. +For packet filter configuration syntax, refer to +.Xr pf.conf 5 . +.Bd -literal -offset indent +nsh(p)/!man pf.conf +nsh(p)/pf edit +.Ed +.Pp +.Ic pf reload +Once the pf ruleset has been edited and validated the modified pf +configuration can be applied with this command. +.Bd -literal -offset indent +nsh(p)/pf reload +.Ed +.Tg ospf +.Ic ospf +.Op Cm \&? | enable | disable | edit | reload | fib | log +Enable, disable or configure +.Xr ospfd 8 , +the OSPF (Open Shortest Path First) daemon. +.Bd -literal -offset indent +nsh(p)/ospf enable +.Ed +.Pp +.Ic ospf edit +Edit the configuration of the OSPF daemon. +The edited ruleset is automatically validated on saving and exiting the +editor. +Note ospfd configuration changes DO NOT take effect until the "ospf reload" +command is entered. +The editor used by nsh can be customised to your preferred editor using the +EDITOR and VISUAL environment variables. +For OSPF configuration syntax, refer to +.Xr ospfd.conf 5 . +.Bd -literal -offset indent +nsh(p)/!man ospfd.conf +nsh(p)/ospf edit +.Ed +.Pp +.Ic ospf reload +Reread and apply the OSPF configuration. +.Bd -literal -offset indent +nsh(p)/ospf reload +.Ed +.Pp +.Ic ospf fib +.Op Cm \&? | couple | decouple | reload +.Pp +Configure whether or not +.Xr ospfd 8 +updates the forwarding information base (the active kernel routing tables). +this is an active control not a persistent configuration setting. +.\" TODO rewording attempted +See "fib-update" in +.Xr ospfd.conf 5 +for more information. +The decouple feature is useful for monitoring OSPF networks without affecting +the routing table of the system. +OSPF decouple should only be done where there is only one link between the +system and the rest of the OSPF network. +The ospf fib reload command re fetches and relearns the routes in the FIB and +passes them to the ospfd daemon for processing. +.Bd -literal -offset indent +nsh(p)/ospf fib decouple +.Ed +.Pp +.Ic ospf log +.Op Cm \&? | verbose | brief +.Pp +Configure the detail level of +.Xr ospfd 8 +logging messages. +Set ospf log verbose to enable detailed debug log output from ospfd. +set ospf log brief to disable detailed debug log output from ospfd. +.Bd -literal -offset indent +nsh(p)/ospf log verbose +.Ed +.Pp +.Tg eigrpd +.Tg eigrp +.Ic eigrp +.Op Cm \&? | enable | disable | edit +.Op Cm options +.Pp +Enable or disable or configure the +.Xr eigrpd 8 +Enhanced Interior Gateway Routing Protocol daemon. +The configuration of +.Ic eigrp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic eigrp +daemon is documented in +.Xr eigrpd.conf 5 +manual page. +Thre are a number of +.Cm options +that can be used to control the operation of +.Xr eigrpd 8 +daemon, these options are documented in the +.Xr eigrpctl 8 +manual page. +.Pp +.Tg bgpd +.Tg bgp +.Tg bgpctl +.Tg bgp +.Ic bgp +.Op Cm \&? | enable | disable | edit +.Op Cm options +.Pp +Enable or disable or configure +.Xr bgpd 8 , +the Border Gateway Protocol daemon. +Configuration of the +.Ic bgp +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr bgpd.conf 5 . +Thre are a number of +.Cm options +that can be used to control the operation of +.Xr bgpd 8 , +documented in +.Xr bgpctl 8 . +.Pp +.Tg ripd +.Tg rip +.Ic rip +.Op Cm \&? | enable | disable | edit +.Op Cm options +.Pp +Enable or disable or configure the +.Xr ripd 8 +Routing Information Protocol daemon. +The configuration of +.Ic rip +daemon can be edited with +.Cm edit +command, the configuration syntax is documented in +.Xr ripd.conf 5 . +Thre are a number of +.Cm options +that can be used to control the operation of +.Xr ripd 8 +daemon, these options are documented in +.Xr ripctl 8 . +.Pp +.Tg ldpd +.Tg ldp +.Ic ldp +.Op Cm \&? | enable | disable | edit +.Op Cm options +.Pp +Enable or disable or configure the +.Xr ldpd 8 +Label Distribution Protocol daemon. +The configuration of +.Ic ldp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic ldp +daemon is documented in +.Xr ldpd.conf 5 . +Thre are a number of +.Cm options +that can be used to control the operation of +.Xr ldpd 8 +daemon, these options are documented in +.Xr ldpctl 8 . +.Pp +.Tg relayd +.Tg relay +.Ic relay +.Op Cm \&? | enable | disable | edit +.Op Cm options +.Pp +Enable or disable or configure the +.Xr relayd 8 , +a load balancer and TLS termination daemon. +The configuration of +.Ic relay +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr relayd.conf 5 . +There are a number of +.Cm options +that can be used to control the operation of +.Xr relayd 8 +daemon, these options are documented in +.Xr relayctl 8 . +.Pp +.Tg isakmpd +.Tg ipsec +.Ic ipsec +.Op Cm \&? | enable | disable | edit | reload +.Pp +Enable or disable or configure the +.Xr isakmpd 8 +Internet Key Exchange version 1 IKEv1 ISAKMP / Oakley daemon. +The configuration of +.Ic ipsec +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic ipsec +daemon is documented in +.Xr isakmpd.conf 5 +and +.Xr ipsec.conf 5 . +.Pp +.Tg iked +.Tg ike +.Ic ike +.Op Cm \&? | enable | disable | edit +.Op Ar options +.Pp +Enable or disable or configure the +.Xr iked 8 +Internet Key Exchange version 2 IKEv2 daemon. +The configuration of +.Ic ike +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic ike +daemon is documented in +.Xr iked.conf 5 . +.Ar options +to control the +.Xr iked 8 +daemon in a similar manner to +.Xr ikectl 8 +i.e to force ike daemon to run in active mode or passive mode, or reload the +the daemon configuration. +These features are documented in +.Xr ikectl 8 . +.Pp +.Tg dvmrpd +.Tg dvmrp +.Ic dvmrp +.Op Cm \&? | enable | disable | edit +.Pp +Enable or disable or configure the +.Xr dvmrpd 8 +Distance Vector Multicast Routing Protocol daemon. +The configuration of +.Ic dvmrp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic dvmrp +daemon is documented in +.Xr dvmrpd.conf 5 +manual page. +.Pp +.Tg rad +.Ic rad +.Op Cm \&? | enable | disable | edit +.Pp +Enable or disable or configure the +.Xr rad 8 +Router Advertisement daemon for IPv6. +The configuration of +.Ic rad +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr rad.conf 5 . +.Pp +.Tg sasyncd +.Tg sasync +.Ic sasync +.Op Cm \&? | enable | disable | edit +.Pp +Enable or disable or configure the +.Xr sasyncd 8 +IPSec Security Association synchronisation daemon for failover gateways. +The configuration of +.Ic sasync +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic sasync +daemon is documented in +.Xr sasyncd.conf 5 . +.Pp +.Tg dhcpd +.Tg dhcp +.Ic dhcp +.Op Cm \&? | enable | disable | edit +.Pp +Enable or disable or configure the +.Xr dhcpd 8 +Dynamic Host Configuration Protocol daemon. +The configuration of +.Ic dhcp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic dhcp +daemon is documented in +.Xr dhcpd.conf 5 . +.Pp +.Tg snmpd +.Tg snmp +.Ic snmp +.Op Cm \&? | enable | disable | edit | trap +.Op Ar options +.Pp +Enable or disable or configure the +.Xr snmpd 8 +Lightweight Directory Access Protocol daemon. +The configuration of +.Ic snmp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic snmp +daemon is documented in +.Xr snmpd.conf 5 . +.Pp +.Tg ldapd +.Tg ldap +.Ic ldap +.Op Cm \&? | enable | disable | edit +.Op Ar options +.Pp +Enable or disable or configure the +.Xr ldapd 8 +Lightweight Directory Access Protocol daemon. +The configuration of +.Ic ldap +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic ldap +daemon is documented in +.Xr ldapd.conf 5 . +.Ar options +to control the +.Xr ldapd 8 +daemon in a similar manner to +.Xr ldapctl 8 +e.g. to set log verbose vs brief or to compact / re-index the LDAP database +are documented in +.Xr ldapctl 8 . +.Pp +.Tg smtpd +.Tg smtp +.Ic smtp +.Op Cm \&? | enable | disable | edit +.Op options +.Pp +Enable or disable or configure the +.Xr smtpd 8 +OpenSMTPD Simple Mail Transfer Protocol daemon. +The configuration of +.Ic smtp +daemon can be edited with +.Cm edit +command, the configuration syntax of +.Ic smtp +daemon is documented in +.Xr smtpd.conf 5 +manual page. +.Pp +.Ar options +to control +.Xr smtpd 8 +in a similar manner to +.Xr smtpctl 8 +i.e pausing / resuming mta (mail transfer agents) / mda (mail delivery +agents) are documented in +.Xr smtpctl 8 . +.Pp +.Tg sshd +.Ic sshd +.Op Cm \&? | enable | disable | edit +.Pp +Enable or disable or configure the +.Xr sshd 8 +OpenSSH secure shell daemon. +The configuration of +.Ic sshd +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr sshd_config 5 . +.Pp +.Tg ntpd +.Tg ntp +.Ic ntp +.Op Cm enable | disable | edit +.Pp +Enable or disable or configure the +.Xr ntpd 8 +Open network time protocol daemon. +The configuration of +.Ic ntp +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr ntpd.conf 5 . +.Pp +.Tg npppd +.Tg nppp +.Ic nppp +.Op Cm \&? | enable | disable | session | monitor | edit +.Op Cm clear Ar \&? | all | ppp-id | address | interface | protocol | realm | \ +username +.Op Cm session Ar \&? |all | brief | packets +.Op Cm monitor Ar \&? | all | ppp-id | address | interface | protocol | realm | \ +username +.Pp +Enable or disable or configure the +.Xr npppd 8 +new Point-to-Point Protocol daemon. +The +.Ic nppp +daemon supports termination of PPPoE, PPTP and L2TP PPP tunnels. +.Xr npppd 8 +works with +.Xr pipex 4 +for improved throughput through the ppp tunnels. +.Pp +The configuration of +.Ic nppp +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr npppd.conf 5 . +.Pp +.Tg ifstated +.Tg ifstate +.Ic ifstate +.Op Cm enable | disable | edit +.Pp +Enable or disable or configure the +.Xr ifstated 8 +interface state daemon. +The configuration of +.Ic ifstate +daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr ifstated.conf 5 . +.Pp +.Tg ftp-proxy +.Ic ftp-proxy +.Op Cm enable | disable +Activate or deactivate the local ftp proxy on the system. +ftp-proxy in order to function properly requires pf to be enabled on the +system. +.Nm +starts ftp-proxy on 127.0.0.1 (rdomain 0) by default. +Redirect rules in pf must be used to direct outside traffic from any rdomain +to the local tftp daemon. +.Bl -dash +.It +e.g. enable ftp-proxy +.Bd -literal -offset indent +nsh(p)/ftp-proxy enable +.Ed +.El +.Pp +.Tg tftp-proxy +.Ic tftp-proxy +.Op Cm enable | disable +.Pp +Activate or deactivate the local tftp proxy on the system. +tftp-proxy in order to function properly requires pf to be enabled on the +system. +.Nm +starts tftp-proxy on 127.0.0.1 (domain 0), port 6969 by default. +Redirect rules in pf must be used to direct outside traffic from any rdomain +to the local tftp proxy. +.Bl -dash +.It +e.g. enable tftp-proxy and redirects needed to use it. +.Bd -literal -offset indent +nsh(p)/tftp-proxy enable +.Ed +.It +Add firewall rule in pf to divert tftp requests to tftp proxy +.Bd -literal -offset indent +nsh(p)/pf edit + +pass in quick on $int_if inet proto udp from $lan to port tftp +divert-to 127.0.0.1 port 6969 +pass out quick on $ext_if inet proto udp from $lan to port tftp +group proxy divert-reply +.Ed +.El +.Pp +.Tg tftp +.Ic tftp +.Op Cm enable | disable +.Pp +Enable or disable the tftp daemon. +.Nm +starts tftpd on 127.0.0.1, port 69 by default. +.Pp +.Tg resolv +.Ic resolv +.Op Cm enable | disable +.Pp +Enable or disable +.Xr resolvd 8 . +.Xr resolvd 8 +is enabled by default and is required to learn DNS information over +DHCP and IPv6 RA. +If +.Xr resolvd 8 +is disabled then the +.Xr resolv.conf 5 +file must be maintained manually. +.Pp +.Tg nameserver +.Tg resolv.conf +.Op no +.Ic nameserver +.Ar IP-address1 +.Op Ar IP-address2 ... IP-address5 +.Pp +Configure static DNS name resolution servers used by the system. +Up to 5 IPv4 and/or IPv6. +.Ar IP-address +arguments can be specified, which will then be added to +.Xr resolv.conf 5 +via +.Xr resolvd 8 . +.Pp +The +.Cm no nameserver +command removes any previously configured static DNS servers. +.Pp +The +.Cm nameserver +command requires +.Xr resolvd 8 +to be enabled. +DNS servers learned via DHCP or IPv6 RA are not affected by the +.Cm nameserver +command. +.Pp +.Tg inetd +.Tg inet +.Ic inet +.Op Cm enable | disable | edit +.Pp +Enable or disable or configure the +.Xr inetd 8 +inet superserver daemon. +The configuration of inet daemon can be edited with +.Cm edit +command, the syntax is documented in +.Xr inetd.conf 8 . +.Pp +.Tg ping +.Ic ping +.Op options +.Ar host +.Pp +Send ICMP ECHO_REQUEST packets to an IPv4 network +.Ar host , +specified by name or IPv4 address. +The +.Ar options +are documented in the +.Xr ping 8 . +.Pp +.Tg ping6 +.Ic ping6 +.Op options +.Ar host +.Pp +Send ICMP ECHO_REQUEST packets to an IPv6 network +.Ar host , +specified by name or IPv6 address. +The +.Ar options +are documented in the +.Xr ping6 8 +manual page. +.Pp +.Tg traceroute +.Ic traceroute +.Op options +.Ar host +.Pp +Trace and print the route packets take to an IPv4 network +.Ar host , +specified by name or IP address. +The +.Ar options +are documented in +.Xr traceroute 8 . +.Pp +.Tg traceroute6 +.Ic traceroute6 +.Op options +.Ar host +.Pp +Trace and print the route packets take to an IPv6 network +.Ar host , +specified by name or IP address. +The +.Ar options +are documented in +.Xr traceroute6 8 . +.Pp +.Tg ssh +.Ic ssh +.Op Ar options +.Op Ic -p Ar port +.Ar host +.Pp +Open a OpenSSH +.Xr ssh 1 +session to the remote system +.Ar host , +specified by name or IP address. +The +.Ar port +is the TCP port on the remote host which you wish to connect. +The +.Ar options +are documented in +.Xr ssh 1 . +.Pp +.Tg telnet +.Ic telnet +.Op Ar options +.Op Ar host +.Op port +.Pp +Open a +.Xr telnet 1 +session to the given TCP +.Ar port +on the remote server +.Ar host , +specified by name or IP address. +If the port is not specified the IANA assigned port 23 for telnet will be +used. +The +.Ar options +are documented in +.Xr telnet 1 . +.Pp +.Tg reboot +.Ic reboot +.Pp +Restart the system. +Warning no confirmation prompt is issued, configuration changes are +NOT automatically saved! +User must save configuration manually BEFORE using reboot. +Requires privileged access. +.Bl -dash +.It +E.g. restart the system +.Bd -literal -offset indent +nsh(p)/reboot +% Reboot initiated +.Ed +.El +.Tg halt +.Ic halt +shut down the system. +Warning no confirmation prompt is issued, configuration changes are +NOT automatically saved! +User must save configuration manually BEFORE using halt. +Requires privileged mode. +.Bl -dash +.It +e.g. shutdown the system +.Bd -literal -offset indent +nsh(p)/halt +% Shutdown initiated +.Ed +.El +.Tg write-config +.Ic write-config +.Pp +Save the running configuration to the permanent configuration space. +On the next startup of the system, this saved configuration is used. +.Bl -dash +.It +e.g. save the configuration on the system +.Bd -literal -offset indent +nsh(p)/write-config +% Configuration saved +.Ed +.El +.Pp +.Tg verbose +.Op no +.Ic verbose +.Pp +Verbose mode sets nsh to display extra information on entered commands. +It is useful during a diagnostic and troubleshooting session. +.Bl -dash +.It +E.g. enable verbose output +.Bd -literal -offset indent +nsh/verbose +% Diagnostic mode enabled +.Ed +.It +If you do not wish to have the extra information displayed, you may +disable verbose mode. +.Bd -literal -offset indent +nsh/no verbose +% Diagnostic mode disabled +.Ed +.El +.Tg show +.Ic show +.Op hostname | interface | autoconf | route | route6 | sadb | arp | ndp | vlan\ + | kernel | bgp | ospf | ospf6 | eigrp | rip | ldp | ike | ipsec | dvmrp\ + | relay | dhcp | smtp | ldap | monitor | version | users | running-config\ + | startup-config |\&? | help +.Pp +The main diagnostic and informational command is 'show'. +show without arguments displays the available diagnostic show sub commands. +.Bl -dash +.It +E.g using show and its built in help +.Bd -literal -offset indent +nsh(p)/show +% Commands may be abbreviated. +% 'show' commands are: + + hostname Router hostname + interface Interface config + autoconf IPv4/IPv6 autoconf state + route IPv4 route table or route lookup + route6 IPv6 route table or route lookup + sadb Security Association Database + arp ARP table + ndp NDP table + vlan 802.1Q/802.1ad VLANs + bridge Ethernet bridges + kernel Kernel statistics + bgp BGP information + ospf OSPF information + ospf6 OSPF6 information + eigrp EIGRP information + rip RIP information + ldp LDP information + ike IKE information + ipsec IPsec information + dvmrp DVMRP information + relay Relay server + dhcp DHCP server + smtp SMTP server + ldap LDAP server + monitor Monitor routing/arp table changes + version Software information + users System users + running-config Operating configuration + startup-config Startup configuration + ? Options +nsh(p)/ +.Ed +.El +.Pp +.Ic show hostname +.Pp +Display the system's currently assigned hostname. +.Bl -dash +.It +e.g. display the name of the device +.Bd -literal -offset indent +nsh(p)/show hostname +% devicename.com +.Ed +.El +.Pp +.Tg interface +.Ic show interface +.Op Ar interface-name +.Op Cm status +.Pp +Display essential information about the system network interfaces including +any network bridges / switches. +show interface without any arguments displays information about all +interfaces available on the system. +The +.Cm status +keyword shows a useful summary (including the Name, Admin Status, Link +state, and Media type) of each hardware and other +configured network interfaces on the system. +.Pp +show interface +.Ar interface-name +Display information about a specific interface. +.Bl -dash +.It +e.g. display information about the loopback interface. +.Bd -literal -offset indent +nsh/show interface lo0 +% lo0 + Interface is up (last change 22:07:02), protocol is up + Interface type Loopback + Internet address ::1/128, fe80::1%lo0/64, 127.0.0.1/8 + rdomain 0, MTU 32768 bytes + 4 packets input, 160 bytes, 0 errors, 0 drops + 4 packets output, 160 bytes, 0 errors, 0 unsupported +.Ed +.It +"Interface is up" means that the interface is turned on in software. +"Protocol is up" means that the interface is configured and ready to run. +The "Interface type" explains what the interface is used for on +the system. +Some interfaces are not intended to pass traffic for network users, and instead +handle internal functions on the system. +See +.Xr ifconfig 8 +for more information on interface types supported by +.Ox . +.It +"Internet address" shows the IPv4 and IPv6 addresses configured for the +interface, if any. +IPv6 addresses with a % sign are "link-local" and not valid outside of the +context of the interface name specified. +MTU describes the Maximum Transmission Unit, the largest size of a packet which +the kernel can transmit on this interface. +.It +The statistics show the number of packets, bytes, errors, and dropped packets +in both incoming and outgoing directions. +The average input/output sizes describe the median size of packets going in +and out the interface. +Note that the total bytes in and/or out may not be accurate. +.Ox +uses an unsigned long type to hold the byte count. +When the byte count exceeds the storage limit of an unsigned long +(4,294,967,295 on a 32 bit architecture or 18,446,744,073,709,551,615 +on a 64-bit architecture), the counter will overflow, causing it to roll over +to 0. +The average packet size is inaccurate when the total byte count rolls +over, because the total number of packets reflects bytes that are no +longer counted. +.It +With verbose mode enabled, 'show interface' displays the raw kernel flags +for an interface. +See +.Xr ifmedia 4 +for an explanation of these flags. +.Bd -literal -offset indent + +nsh(p)/show interface lo0 +% lo0 + Interface is up (last change 22:13:28), protocol is up + Interface type Loopback + Internet address ::1/128, fe80::1%lo0/64, 127.0.0.1/8 + rdomain 0, MTU 32768 bytes + 4 packets input, 160 bytes, 0 errors, 0 drops + 4 packets output, 160 bytes, 0 errors, 0 unsupported + Flags: + + Hardware features: + +.Ed +.It +With a bridge, verbose mode displays spanning tree member states and bridge +members. +.Bd -literal -offset indent +nsh/show int bridge0 +% bridge0 + Bridge is up (last change 00:00:21), protocol is up + Interface type Ethernet Bridge + 0 packets input, 0 bytes, 0 errors, 0 drops + 0 packets output, 0 bytes, 0 errors, 0 unsupported + Flags: + + STP member state: + sis0: listening + +.Ed +.It +With an IEEE 802.11 wireless interface, verbose mode displays the network ID, +network key, and power-saving mode (if enabled). +.Bd -literal -offset indent +nsh/show int athn0 +% athn0 + BLah blah + IEEE 802.11 + network id blah + network key blah + powersaving (111 ms) + +.Ed +.It +With an interface that supports media commands, including Ethernet and +IEEE 802.11 wireless interfaces, verbose mode displays which media types are +available. +.Bd -literal -offset indent +nsh/show int sis0 +% sis0 + Supported media types: + media none + media 10baseT + media 10baseT, mediaopt full-duplex + media 100baseTX + media 100baseTX, mediaopt full-duplex + media autoselect + +.Ed +.El +e.g. briefly list the status of all interfaces on the system. +.Bd -literal -offset indent +nsh(p)/show interface status +% Name Status Link Media + lo0 up - + em0 up active Ethernet 1000baseT full-duplex + enc0 down active + pflog0 up - + tpmr1 up active + vether1 up active Ethernet + vether2 up active Ethernet + vether10 up active Ethernet + vether11 up active Ethernet + bridge101 up - + vether20 up active Ethernet + vether21 up active Ethernet + veb201 up - +nsh(p)/ +.Ed +.Pp +.Tg autoconf +.Ic show autoconf +.Pp +Display the interfaces on the system that are dynamically configured and the +current state and configured settings such as IP addresses, routes +nameservers and the server that the system recieved the autoconf settings from +. +.Pp +e.g. list current autoconfiguration state of the system. +.Bd -literal -offset indent +nsh(p)/show autoconf +em0 [Bound] + inet 10.0.2.15 netmask 255.255.255.0 + default gateway 10.0.2.2 + nameservers 10.0.0.1 192.168.0.1 + lease 17 hours + dhcp server 10.0.2.2 +.Ed +.Pp +.Tg route +.Ic show route +.Pp +Display a dump of the kernel's IPv4 routing table, including ARP entries. +.Pp +e.g. display contents of the IPv4 routing table. +.Bd -literal -offset indent +nsh/show route +Flags: U - up, G - gateway, H - host, L - link layer, R - reject (unreachable), + D - dynamic, S - static + +% IPv4 routing table: + +Destination Gateway Flags Refs Packets Mtu Interface +0.0.0.0/0 172.20.1.1 UGS 3 57502 - sis0 +127.0.0.0/8 127.0.0.1 UGRS 0 0 33224 lo0 +127.0.0.1 127.0.0.1 UH 2 12 33224 lo0 +172.20.1.0/24 link#1 U 0 0 - sis0 +172.20.1.1 8:0:20:71:22:e7 UHL 1 0 - sis0 +172.20.1.2 127.0.0.1 UGHS 0 0 33224 lo0 +172.20.1.23 link#1 UHL 1 1764 - sis0 +172.20.1.255 link#1 UHL 2 1555 - sis0 +224.0.0.0/4 127.0.0.1 URS 0 0 33224 lo0 +.Ed +.Bl -dash +.It +The destination column is simply the destination network which the route +describes. +The gateway is the next hop for this route to pass through. +Gateways which are described as 'link#' are local area networks or members of +local area networks. +.It +The flags are useful to determine if the kernel is using a particular +route or not. +.It +U - up + This route is active +G - gateway + The destination of this route is behind a gateway (next hop). +H - host + This route describes a host on the local network. +L - link layer + The destination has been or needs to be discovered through a layer 2 protocol +R - reject + This route is unreachable, and therefore marked unusable in the kernel +D - dynamic + This is a dynamic route which has is managed through routing software on + the local system (such as ripd, ospfd or bgpd) +S - static + This is a static route set by a user +.El +.Pp +.Tg route6 +.Ic show route6 +.Pp +Display a dump of the kernel's IPv6 routing table, including neighbour entries. +.Pp +e.g. display contents of the IPv6 routing table. +.Bd -literal -offset indent +nsh(p)/show route6 +Flags: U - up, G - gateway, H - host, L - link layer, R - reject (unreachable), + D - dynamic, S - static, T - MPLS, c - CLONED, l - LOCAL + +% IPv6: +Destination Gateway Flags Refs Use Mtu Interface +::/96 ::1 UGRS 0 0 32768 lo0 +::1 ::1 UH 10 20 32768 lo0 +::ffff:0.0.0.0/96 ::1 UGRS 0 0 32768 lo0 +2002::/24 ::1 UGRS 0 0 32768 lo0 +2002:7f00::/24 ::1 UGRS 0 0 32768 lo0 +2002:e000::/20 ::1 UGRS 0 0 32768 lo0 +2002:ff00::/24 ::1 UGRS 0 0 32768 lo0 +fe80::/10 ::1 UGRS 0 0 32768 lo0 +fec0::/10 ::1 UGRS 0 0 32768 lo0 +fe80::1%lo0 fe80::1%lo0 UH 0 0 32768 lo0 +ff01::/16 ::1 UGRS 0 0 32768 lo0 +ff01::%lo0/32 fe80::1%lo0 U 0 1 32768 lo0 +ff02::/16 ::1 UGRS 0 0 32768 lo0 +ff02::%lo0/32 fe80::1%lo0 U 0 1 32768 lo0 +nsh(p)/ +.Ed +.Pp +.Tg sadb +.Tg ipsec +.Ic show sadb +.Pp +Display the IPSEC security association database of the system. +.Pp +.Tg arp +.Ic show arp +.Pp +Display Address Resolution Protocol table of the system, listing +IPv4 to layer2 mac-address entries, the interfaces they were learned on and the +expiry of each interfaces. +Locally configured IPv4 addresses appear as permanent arp entries. +.Pp +e.g. display contents of the arp table. +.Bd -literal -offset indent +nsh(p)/show arp +Host Ethernet Address Netif Expire Flags +10.0.2.2 52:54:00:12:35:02 em0 2m14s +10.0.2.15 08:00:27:bd:cb:77 em0 permanent l +nsh(p)/ +.Ed +.Pp +.Tg ndp +.Ic show ndp +.Pp +Display Neighbour Discovery Protocol NDP table. +Neighbour Discovery Protocol database of the system, listing +IPv6 to layer2 mac-address entries, the interfaces they were learned on and the +expiry of each interfaces. +Locally configured IPv6 addresses appear as permanent ndp entries. +.Pp +e.g. display contents of the ndp table. +.Bd -literal -offset indent +nsh(p)/show ndp +Neighbor Linklayer Address Netif Expire S Flags +fe80::a00:27ff:febd:cb77%em0 08:00:27:bd:cb:77 em0 permanent R l +fe80::cafe:babe:beef:face%em0 52:54:00:12:35:02 em0 17m03s +nsh(p)/ +.Ed +.Pp +.Tg vlan +.Ic show vlan +.Op vlan-id +.Pp +Display all virtual local area network interfaces configured on the system. +Lists the vlans parent interfaces, any layer2 forwarding device the interface +is a member of and the vlan interface description. +expiry of each interfaces. +.Pp +e.g. display all vlan interfaces on the system +.Bd -literal -offset indent +nsh(p)/show vlan +% Interface Tag Status Type Parent Bridge Description + vlan100 100 up 802.1Q em0 bridge100 Stefans-LAN + vlan200 200 up 802.1Q vether200 veb200 Chris-C-LAN +nsh(p)/ +.Ed +e.g. display information on all vlans with vnetid/tag of 200. +.Bd -literal -offset indent +nsh(p)/show vlan 200 +% Interface Tag Status Type Parent Bridge Description + vlan200 200 up 802.1Q vether200 veb200 Chris-C-LAN +nsh(p)/ +.Ed +.Pp +.Tg bridge +.Tg veb +.Tg tpmr +.Ic show bridge +.Op bridge-interface | veb-interace | tpmr-interface +.Pp +Without specifying an argument, it displays all layer2 forwarding +devices configured on the system, and all members of each layer2 +forwarding device, and any description of the layer2 forwarding +device. +Layer 2 forwarding devices supported by this command include +.Xr bridge 4 +standard bridge, +.Xr veb 4 +virtual ethernet bridge +and the +.Xr tpmr 4 +two port mac relay device. +.Pp +e.g. Display all layer2 forwarding devices and their member ports +.Bd -literal -offset indent +nsh(p)/show bridge +% Bridge Status Member Interfaces + bridge1 down + Description: - + bridge100 up vlan100 + Description: Tom-Smyths-Bridge + veb200 up vlan200 + Description: Chris-Cappuccios-Bridge + tpmr102 up vether1102 vether2102 + Description: dlg-bridge +nsh(p)/ +.Ed +e.g. Display the information the tpmr102 layer2 forwarding device +.Bd -literal -offset indent +nsh(p)/show bridge tpmr102 +% Bridge Status Member Interfaces + tpmr102 up vether1102 vether2102 + Description: 2PortMacRelay-bridge-102 +.Ed +.Pp +.Tg kernel +.Tg ip +.Tg ah +.Tg esp +.Tg tcp +.Tg icmp +.Tg igmp +.Tg ipcomp +.Tg route +.Tg carp +.Tg mbuf +.Tg pf +.Ic show kernel +.Op Ar ip | ah | esp | tcp | icmp | igmp | ipcomp | route | carp | mbuf | pf +.Pp +Display kernel statistics available for query. +Display kernel statistics as selected by the argument. +Executing show kernel without an argument lists all available statistics +.Pp +e.g. show available kernel statistics. +.Bd -literal -offset indent +nsh(p)/show kernel +% Arguments may be abbreviated + + show kernel ip Internet Protocol statistics + show kernel ah Authentication Header statistics + show kernel esp Encapsulated Security Payload statistics + show kernel tcp Transmission Control Protocol statistics + show kernel udp Unreliable Datagram Protocol statistics + show kernel icmp Internet Control Message Protocol statistics + show kernel igmp Internet Group Management Protocol statistics + show kernel ipcomp IP Compression statistics + show kernel route Routing statistics + show kernel carp Common Address Redundancy Protocol statistics + show kernel mbuf Packet memory buffer statistics + show kernel pf Packet Filter statistics +nsh(p)/ +.Ed +.Pp +e.g. show packet filter kernel statistics +.Bd -literal -offset indent +nsh(p)/show kernel pf +% pf statistics: +Status: Enabled for 0 days 23:58:32 Debug: err + +State Table Total Rate + current entries 7 + half-open tcp 0 + searches 284973 3.3/s + inserts 836 0.0/s + removals 829 0.0/s +Counters + match 841 0.0/s + bad-offset 0 0.0/s + fragment 0 0.0/s + short 0 0.0/s + normalize 0 0.0/s + memory 0 0.0/s + bad-timestamp 0 0.0/s + congestion 0 0.0/s + ip-option 1 0.0/s + proto-cksum 0 0.0/s + state-mismatch 0 0.0/s + state-insert 0 0.0/s + state-limit 0 0.0/s + src-limit 0 0.0/s + synproxy 0 0.0/s + translate 0 0.0/s + no-route 0 0.0/s +nsh(p)/ +.Ed +.Pp +.Tg ip +.Tg route +.Tg bgp +.Ic show bgp +.Op Ar announced | interfaces | nexthop | summary | rib | neighbor | ip +.Pp +Display status for +.Xr bgpd 8 +Border Gateway Protocol BGPv4 dynamic routing on this system. +e.g. show bgp +.Bd -literal -offset indent +nsh(p)/show bgp +% Arguments may be abbreviated + + show bgp announced All announced networks information + show bgp interfaces Interface states information + show bgp nexthop BGP nexthop routes information + show bgp summary Neighbor session states and counters information + show bgp rib Routing Information Base information + show bgp neighbor Detailed peer information + show bgp ip IP BGP information +nsh(p)/ +.Ed +.Pp +.Tg ip +.Tg ospf +.Tg route +.Ic show ospf +.Op Ar fib | database | interfaces | neighbor | rib | summary +.Pp +Display the state of +.Xr ospfd 8 +Open Shortest Path First OSPF dynamic links state routing +protocol for IPv4 on this system. +.Bd -literal -offset indent +nsh(p)/show ospf +% Arguments may be abbreviated + + show ospf fib Forward Information Base information + show ospf database Link State Database information + show ospf interfaces Interface information + show ospf neighbor Neighbor information + show ospf rib Routing Information Base information + show ospf summary Summary information +nsh(p)/ +.Ed +.Pp +.Tg ospf6 +.Tg ospfv3 +.Tg route6 +.Ic show ospf6 +.Op Ar fib | database | interfaces | neighbor | rib | summary +.Pp +Display the state of +.Xr ospf6d 8 +Open Shortest Path First OSPFv3 daemon for dynamic links state +routing protocol for IPv6 on this system. +.Bd -literal -offset indent +nsh(p)/show ospf6 +% Arguments may be abbreviated + + show ospf6 fib Forward Information Base information + show ospf6 database Link State Database information + show ospf6 interfaces Interface information + show ospf6 neighbor Neighbor information + show ospf6 rib Routing Information Base information + show ospf6 summary Summary information +nsh(p)/ +.Ed +.Pp +.Tg rip +.Ic show rip +.Op Ar fib | interfaces | neighbor | rib +.Pp +Display the status of +.Xr ripd 8 +Routing Information Protocol RIP daemon for dynamic +distance vector routing protocol on this system. +.Bd -literal -offset indent +nsh(p)/show rip +% Arguments may be abbreviated + + show rip fib Forward Information Base information + show rip interfaces Interfaces information + show rip neighbor Neighbor information + show rip rib Routing Information Base information +nsh(p)/ +.Ed +.Pp +.Tg mpls +.Tg ldp +.Tg label +.Tg l2vpn +.Ic show ldp +.Op Ar fib | interfaces | neighbor | lib | discovery | l2vpn +.Pp +Display information on the status of +.Xr ldpd 8 +Label Distribution protocol LDP routing daemon for MPLS Multi +Protocol label Switching on this system. +.Bd -literal -offset indent +nsh(p)/show ldp +% Arguments may be abbreviated + + show ldp fib Forward Information Base information + show ldp interfaces Interfaces information + show ldp neighbor Neighbors information + show ldp lib Label Information Base information + show ldp discovery Adjacencies information + show ldp l2vpn Pseudowire information +nsh(p)/ +.Ed +.Pp +.Tg ipsec +.Tg ike +.Tg ikev2 +.Tg flow +.Tg sa +.Tg sadb +.Ic show ike +.Op Ar monitor +.Pp +Display Information on the Internet Key Exchange IKEv2 daemon on +this system. +.Pp +.Ic show ipsec +.Op Ar flows | sadb +.Pp +Display IPSECurity information related to either IPSEC flows or the +Security Association Database on the system. +.Pp +.Tg dvmrp +.Tg multicast +.Tg igmp +.Ic show dvmrp +.Op Ar igmp | interfaces | mfc | neighbor | rib | summary +.Pp +Display status information from +.Xr dvmrpd 8 +the Distance Vector Multicast Routing Protocol (DVMRP) daemon. +.Bd -literal -offset indent +nsh(p)/show dvmrp +% Arguments may be abbreviated + + show dvmrp igmp Internet Group Message Protocol information + show dvmrp interfaces Interfaces information + show dvmrp mfc Multicast Forwarding Cache information + show dvmrp neighbor Neighbor information + show dvmrp rib Routing Information Base information + show dvmrp summary Summary information +nsh(p)/ +.Ed +.Tg relay +.Tg relayd +.Ic relay +.Op Ar hosts | redirects | status | sessions | summary +.Pp +Display status information from +.Xr relayd 8 +daemon for loadbalancing, TLS termination and content switching. +.Bd -literal -offset indent +nsh(p)/show relay +% Arguments may be abbreviated + + show relay hosts hosts information + show relay redirects redirects information + show relay status status information + show relay sessions sessions information + show relay summary summary information +nsh(p)/ +.Ed +.Pp +.Tg dhcp +.Tg ip +.Tg lease +.Ic show dhcp +.Op Ar leases +Display leases recored in the lease database as handed out by +.Xr dhcpd 8 +Dynamic Host Configuration Protocol (DHCP) daemon. +.Pp +.Tg ldap +.Tg auth +.Ic show ldap +.Op Ar stats +Display statistics from +.Xr ldapd 8 +Lightweight Directory Access Protocol (LDAP) daemon. +.Pp +.Ic show monitor +.Pp +Start an interactive console monitor mode for the system's routing socket. +The monitor displays raw descriptions of the data passing into the kernel's +routing socket and dumps of the kernel's routing messages to the machine. +Press enter or control-C to exit this mode. +.Pp +.Ic show version +.Pp +Display basic version information about the host and about NSH, including, + the system's uptime and kernel version. +It also shows both the kernel that NSH was compiled under, and the +current kernel that NSH is running under. +.Nm +should always be running on a kernel that is of a similar version to the +version of the kernel/header files that NSH was compiled under. +This ensures that +.Nm +can interact with the kernel properly (and vice versa). +.Bd -literal -offset indent +nsh/show version +% NSH v1.0 +Compiled 03-Apr-22 06:03 by _pbuild@amd64-1.ports.openbsd.org +uptime: 1 day, 2 hours, 17 minutes +system: OpenBSD/amd64 version 7.1 +cpu: Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz +memory: 8175MB +kernel: OpenBSD 7.1 (GENERIC.MP) #459: Mon Apr 4 18:16:13 MDT 2022 + deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP +.Ed +.Pp +.Ic show running-config +.Pp +Display the current running configuration on the system, including +interface and bridge configurations, routes, the system hostname, firewall +rules, and other information compiled by nsh. +.Pp +.Ic show startup-config +.Pp +Display the startup configuration on the system, read from nshrc, +including interface and bridge configuration, routes, the system hostname, +firewall rules, and other information compiled by +.Nm +. +TBC +.Tg flush +.Ic flush +.Op routes | arp | ndp | line | bridge-dyn | bridge-all | bridge-rule | pf | history |\&? | help +.Pp +Clear various system tables. +.Pp +.Ic flush routes +.Pp +Clear the system routing table. +.Pp +.Ic flush arp +.Pp +Clear the system arp cache and static arp table. +.Pp +.Ic flush ndp +.Pp +Clear the system NDP cache and static NDP table. +.Pp +.Ic flush bridge-dyn +.Ar bridge-name +.Pp +Clear dynamically learned members from the named bridge. +.Bd -literal -offset indent +nsh/flush bridge-dyn bridge0 +.Ed +.Pp +Delete all dynamically learned members from bridge0. +Note! any members set manually (static members) are not removed by this +command. +.Pp +.Ic flush bridge-all +.Ar bridge-name +.Pp +Clear dynamically and statically learned members from the named bridge. +.Bd -literal -offset indent +nsh/flush bridge-all bridge0 +.Ed +.Pp +.Ic flush bridge-rule +.Ar bridge-name +.Ar interface-name +.Pp +Clear all rules on the named bridge on the named interface. +.Bd -literal -offset indent +nsh/flush bridge-rule bridge0 vether0 +.Ed +.Pp +.Ic flush history +.Pp +Clear the command history +.Pp +.Tg route +.Op no +.Ic route +.Op destination +.Op Ar /prefixlen | netmask +.Ar gateway +.Op flags +.Pp +Add or remove static routes. +IPv4 addresses can be configured with prefix length in CIDR or dotted decimal +IP netmasks (e.g. 255.255.255.0) to describe the route. +The IPv6 address may only be configured with a prefix length. +This command only runs in privileged mode. +.Bl -dash +.It +e.g. setup routes on the system +.Bd -literal -offset indent +nsh(p)/route 192.168.0.0/16 1.2.3.4 +.Ed +.It +is equivalent to: +.Bd -literal -offset indent +nsh(p)/route 192.168.0.0/255.255.0.0 1.2.3.4 +.Ed +.It +Use the +.Ic no +keyword to remove the specific route (if present) in the routing table. +.Bd -literal -offset indent +nsh(p)/no route 192.168.0.0/16 1.2.3.4 +.Ed +.It +If you do not specify a mask, +.Nm +assumes you are routing a host address (/32 in ipv4). +.Bd -literal -offset indent +nsh(p)/route 10.6.6.4 1.2.3.4 +.Ed +.It +Routing flags may be defined after a route. +.Bd -literal -offset indent +nsh(p)/route 127.0.0.0/8 127.0.0.1 reject +.Ed +.It +or +.Bd -literal -offset indent +nsh(p)/route ::/96 ::1 reject +.Ed +.El +.Ss Route Flags +Flags: +.Ic blackhole | cloning | iface | llinfo | nmpath\ + | nostatic | proto1 | proto2 | reject +.Op mtu Ar mtu-bytes +.Op expire Ar seconds +.Bd -literal +blackhole RTF_BLACKHOLE discard packets for this route +cloning RTF_CLONING generate a new route on use +iface !RTF_GATEWAY destination is directly reachable +llinfo RTF_LLINFO translates proto addr(l3) to link addr(l2) +nompath !RTF_MPATH do not allow multiple gateways for this route +nostatic !RTF_STATIC do not save this in the static routing table +proto1 RTF_PROTO1 protocol specific flag #1 +proto2 RTF_PROTO2 protocol specific flag #2 +reject RTF_REJECT reject packets with ICMP unreachable +.Ed +.Tg quit +.Ic quit +.Pp +exit +.Nm +. +.Pp +.Tg verbose +.Op no +.Ic verbose +.Pp +Sets verbose mode on / off. +(By default verbose mode is off). +Use the +.Ic no +keyword turn verbose mode off. +.Bd -literal -offset indent +nsh(p)/verbose +% Diagnostic mode enabled + +nsh(p)/no verbose +% Diagnostic mode disabled + +.Ed +.Pp +.Tg editing +.Op no +.Ic editing +.Pp +Set command line editing on / off. +(If defaults to on). +Use the +.Ic no +keyword to turn command editing mode off. +.Bd -literal -offset indent +nsh(p)/editing +% Command line editing enabled + +nsh(p)/no editing +% Command line editing disabled +.Ed +.Pp +.Tg shell +.Tg ksh +.Tg sh +.Tg csh +.Ic nsh(p)/! +.Op Cm shell-command +.Ar argument-1 +.Op Ar argument-n +.Pp +Invoke a shell or run an entered shell-command with arguments if required. +(requires privileged mode). +The active users login shell is the shell that is invoked by this feature. +This feature disabled to enhance security. +.Pp +E.g. list files in /root +.Bd -literal -offset indent +nsh(p)/!ls /root + +helloworld.c +helloworld2.c + +nsh(p)/! + +OpenBSDshell# +.Ed +.Pp +.Tg ip +.Op no +.Ic ip +.Op Cm arptimeout | arpdown | carp | carp-log | carp-preempt | forwarding |\ + mforwarding | mtu-path-disc | mtu-disc-timeout | ipip | gre | wccp | etherip\ + | ipcomp | esp | esp-udpencap | esp-udpencap-port | ah | sourceroute | encdebug\ + | send-redirects | ifq-maxlen | directed-broadcast | multipath | default-ttl\ + |\&? +.Pp +Modify system kernel ip processing parameters or features. +(requires privileged mode). +.Pp +All commands in this category allow the 'no' modifier to disable the option. +.Bd -literal -offset indent +nsh(p)/ip ? +% Commands may be abbreviated. +% 'ip' commands are: + + arptimeout Seconds for ARP entries to remain in cache + arpdown Seconds before resending unanswered ARP requests + carp Allow CARP + carp-log CARP Logging Priority + carp-preempt CARP Virtual Host Preemption + forwarding Enable IPv4 Forwarding + mforwarding Enable IPv4 Multicast Forwarding + mtu-path-disc Enable IPv4 MTU Path Discovery + mtu-disc-timeout Seconds that MTU entries remain in Path MTU discovery cache + ipip Allow IP-in-IP Encapsulation + gre Allow Generic Route Encapsulation + wccp Allow Web Cache Control Protocol + etherip Allow Ether-IP Encapsulation + ipcomp Allow IP Compression + esp Allow Encapsulated Security Payload + esp-udpencap Allow ESP encapsulation within UDP + esp-udpencap-port UDP port number for encapsulation + ah Allow Authentication Header + sourceroute Process Loose/Strict Source Route Options + encdebug Enable if_enc debugging + send-redirects Send ICMP redirects + ifq-maxlen IPv4 ifqueue max length + directed-broadcast Allow directed broadcasts + multipath Multipath routing + default-ttl Default IP packet TTL + ? Options + +.Ed +.Ic ip arptimeout +.Ar seconds +.Pp +Sets the timeout (seconds) for ARP entries to remain in cache on this system. +.Pp +When the system stops receiving ARP packets from the host and, the +.Ic arptimout +seconds pass, the arp entries are removed from the ARP cache. +If a service or user requests to communicate with the IP address of the +removed cache entry the system requests via broadcast an ARP request. +Lower +.Ic arptimeout +values increase the broadcast traffic on the underlying network. +While higher +.Ic arptimeout +values increase the time it takes to resolve a host. +This setting should be the same or lower on a router than the bridge MAC table +timeout on an intermediate bridge. +.Bd -literal -offset indent +nsh(p)/ip arptimeout 300 +.Ed +.Pp +.Op no +.Ic ip arpdown +.Ar seconds +.Pp +Set or remove configured timeout (seconds) the system waits before resending an +unanswered ARP request. +.Pp +If the ARP system fails to resolve a MAC address, the system waits for +.Ic ip arpdown +number of seconds before retrying. +.Pp +Lower settings increases the broadcast traffic on the underlying network +while higher settings increases the time it takes to resolve a host +(after the host boots up) and on a network that is experiencing packet loss. +.Bd -literal -offset indent +nsh(p)/ip arpdown 20 +.Ed +.Pp +.Op no +.Ic ip carp +.Pp +Enable or disable +.Xr carp 4 +functionality in the system kernel. +Carp is a BSD licensed technology for router redundancy utilising a virtual ip +that floats between 2 or more routers on a LAN segment, it is similar to VRRP +or HSRP. +.Bd -literal -offset indent +nsh(p)/ip carp +.Ed +.Pp +.Op no +.Ic ip carp-log +.Ar 0-7 +.Pp +Enable or disable logging of carp state change, bad packets and other errors +in the system kernel. +carp-log may be set to a value between 0 and 7 corresponding with standard +syslog(3) priorities. +The default value is 2, which limits logging to changes in CARP state. +.Bd -literal -offset indent +nsh(p)/ip carp-log 7 +.Ed +.Pp +.Op no +.Ic ip carp-preempt +.Pp +Enable or disable the device taking master role from an existing master carp +router +.Bd -literal -offset indent +nsh(p)/ip carp-preempt +.Ed +.Pp +.Op no +.Ic ip forwarding +.Pp +Enable or disable IP packet forwarding in the system kernel. +This must be set in order to use routing, NAT, IPsec or packet filter features. +.Bd -literal -offset indent +nsh(p)/ip forwarding +.Ed +.Pp +.Op no +.Ic ip ipip +.Pp +Enable or disable IP-in-IP encapsulation in the system kernel. +.Bd -literal -offset indent +nsh(p)/ip ipip +.Ed +.Pp +.Op no +.Ic ip gre +.Pp +Enable or disable Generic Route Encapsulation in the system kernel. +Must be used to enable +.Xr gre 4 +interfaces. +.Bd -literal -offset indent +nsh(p)/ip gre +.Ed +.Pp +.Op no +.Ic ip wccp +.Pp +Enable or disable GRE-based Web Cache Control Protocol packets to manage +caching device. +Must be used to enable WCCP on +.Xr gre 4 +interfaces. +.Bd -literal -offset indent +nsh(p)/ip wccp +.Ed +.Pp +.Op no +.Ic ip etherip +.Pp +Enable or disable GRE-based Ether-IP encapsulation in the system kernel. +.Bd -literal -offset indent +nsh(p)/ip etherip +.Ed +.Pp +.Op no +.Ic ip ipcomp +.Pp +Enable or disable IPComp internet protocol compression in the system kernel. +.Bd -literal -offset indent +nsh(p)/ip ipcomp +.Ed +.Pp +.Op no +.Ic ip esp +.Pp +Enable or disable IPsec Encapsulated Security Payload procesing in the system +kernel. +(Enabled by default.) +.Bd -literal -offset indent +nsh(p)/ip esp +.Ed +.Pp +.Op no +.Ic ip esp-udpencap +Enable or Disable processing of UDP encapsulated ESP packets in the system +kernel. +(Enabled by default.) +.Bd -literal -offset indent +nsh(p)/ip esp-udpencap +.Ed +.Pp +.Op no +.Ic ip esp-udpencap-port +.Ar 0-65535 +Sets the value of the UDP port that triggers decapsulation for incoming +UDP encapsulated ESP packets. +(The default port is 4500) udp encapsulated esp packets are useful for +traversing NAT routers. +.Bd -literal -offset indent +nsh(p)/ip esp-udpencap-port 4600 +.Ed +.Pp +.Op no +.Ic ip ah +.Pp +Enable or disable IPsec Authentication Header processing in the system kernel. +(Enabled by default.) +.Bd -literal -offset indent +nsh (p)/ip ah +.Ed +.Pp +.Op no +.Ic ip sourceroute +.Pp +Enable or disable processing loose or strict source routing options on IP +packet headers. +Do not enable this option on systems connected to the public internet. +.Bd -literal -offset indent +nsh(p)/ip sourceroute +.Ed +.Pp +.Op no +.Ic ip encdebug +.Pp +Enable or disable printing debug messages for the +.Xr enc 4 +interface to the +kernel output. +Note! Requires a kernel compiled with ENCDEBUG option. +.Bd -literal -offset indent +nsh(p)/ip encdebug +.Ed +.Pp +.Op no +.Ic ip send-redirects +.Pp +Controls whether or not the system sends ICMP redirects to local hosts. +(Enabled by default). +.Pp +When there is a direct path on the local network from one host to another, but +one of those hosts chooses to talk through the router instead, the system +sends an ICMP redirect to the originating host. +This redirect tells the host the direct path on the network to send further +packets. +.Bd -literal -offset indent +nsh(p)/ip send-redirects +.Ed +.Pp +.Op no +.Ic ip directed-broadcast +.Pp +Enable or disable kernel forwarding of IP traffic to the broadcast address +of any interface on the system. +This setting is useful for limiting certain types of DoS attacks. +.Pp +.Op no +.Ic ip multipath +.Pp +Enable or disable ip multicast forwarding in the system kernel. +(Disabled by default.) +.Bd -literal -offset indent +nsh(p)/ip mforwarding +.Ed +.Pp +.Op no +.Ic ip default-ttl +.Ar ttl +.Pp +Sets the default ttl used on IP packets originating from this system. +Valid ttl value is in the range 1-255. +.Pp +The TTL, or time-to-live, is decremented by one each time the packet passes +through another router on the internet. +The default TTL that the system uses is 64, therefore it allows for the +packet to pass through up to 64 routers (also called hops) before reaching +its destination. +The main purpose of the TTL is to avoid routing loops in the network. +.Bd -literal -offset indent +nsh(p)/ip default-ttl 128 +.Ed +.Pp +.Ic ip \&? +.Pp +Displays the help menu and available ip command options. +.Bd -literal -offset indent +nsh(p)/ip ? +.Ed +.Tg interface +.Op no +.Ic interface +.Op ip | alias | description | group | rdomain | rtlabel | priority\ + | llpriority | mtu | metric | link | arp | lladdr | nwid | nwkey\ + | powersave | txpower | bssid | media | mediaopt | auth | peer\ + | pppoe | tunnel | tunneldomain | txprio | rxprio | vnetid\ + | vnetflowid | parent | patch | keepalive | mplslabel | pwe\ + | syncdev | syncpeer | maxupd | vhid | advbase | advskew | carppass\ + | carpdev | carpnode | carppeer | balancing | pflow | debug\ + | dhcrelay | wol | mpls | inet6 | autoconf6\ + | autoconfprivacy | temporary | monitor | wgpeer | wgport\ + | wgkey | wgrtable | trunkport | trunkproto | shutdown |\&? +interface mode commands, are commands that can be applied to a specific +named interface. +.Bd -literal -offset indent +nsh(interface-em0)/? +% Commands may be abbreviated. +% Type 'exit' at a prompt to leave interface configuration mode. +% Interface configuration commands are: + + ip IP address and other parameters + alias Additional IP addresses and other parameters + description Interface description + group Interface group + rdomain Interface routing domain + rtlabel Interface route labels + priority Data packet priority + llpriority Link Level packet priority + mtu Maximum Transmission Unit + metric Routing metric + link Link level options + arp Address Resolution Protocol + staticarp Always use static ARP to find other hosts + lladdr Link Level (MAC) Address + nwid 802.11 network ID + nwkey 802.11 network key + powersave 802.11 powersaving mode + txpower 802.11 transmit power + bssid 802.11 bss id + media Media type + mediaopt Media options + auth PPP authentication + peer PPP peer authentication + pppoe PPPoE settings + tunnel Tunnel parameters + tunneldomain Tunnel routing domain for transit + txprio Priority in tunnel protocol headers + rxprio Source used for packet priority + vnetid Virtual interface network identifier + vnetflowid Use part of vnetid as flowid + parent Parent interface + patch Pair interface + keepalive GRE tunnel keepalive + mplslabel MPLS local label + pwe MPLS PWE3 + syncdev PFsync control message interface + syncpeer PFsync peer address + maxupd PFsync max updates, defer first packet + vhid CARP virtual host ID + advbase CARP advertisement interval + advskew CARP advertisement skew + carppass CARP passphrase + carpdev CARP device + carpnode CARP additional vhid/advskew + carppeer CARP peer + balancing CARP balancing mode + pflow pflow data export + debug Driver dependent debugging + dhcrelay DHCP Relay Agent + wol Wake On LAN + mpls MPLS + inet6 IPv6 + autoconf6 IPv6 Autoconfigurable address + autoconfprivacy Privacy addresses for IPv6 autoconf + temporary Temporary addresses for IPv6 autoconf + monitor Monitor mode for incoming traffic + wgpeer Wireguard peer config + wgport Wireguard UDP port + wgkey Wireguard private key + wgrtable Wireguard routing table + trunkport Add child interface(s) to trunk + trunkproto Define trunkproto + shutdown Shutdown interface + ? Options +.Ed +.Pp +.Op no +.Ic ip +.Op dhcp +.Ar | address/prefix-length | address/netmask +.Pp +Adds or removes the main IP address and other related parameters on the +interface. +IPv4 addresses can be configured with CIDR bitlength, or classic netmask. +The IPv6 address may only be configured with a bitlength. +.Bd -literal -offset indent +nsh(interface-lo0)/ip ::1/128 +.Ed +or +.Bd -literal -offset indent +nsh(interface-fxp0)/ip 192.168.100.1/24 +.Ed +or +.Bd -literal -offset indent +nsh(interface-fxp0)/ip 192.168.100.1/255.255.255.0 +.Ed +.Pp +.Op no +.Ic alias +.Ar address/prefix-length | address/netmask +.Pp +Deprecated, adds or removes additional IP address and other related +parameters on the interface. +IPv4 addresses can be configured with CIDR bitlength, or classic netmask. +The IP address may only be configured with a bitlength. +.Pp +.Op no +.Ic ip dhcp +.Pp +Enables or disables dhclient on a given (broadcast and layer2 capable) +interface. +.Pp +DHCP client notes: +DHCP client mode takes control of default gateway route. +There is currently no way to control default gateway if DHCP client is used +on multiple interfaces. +The first DHCP client interface to succeed in obtaining a lease sets the +default gateway. +.Pp +If /var/db is kept across reboots, (such as in a configuration where +.Nm +is used on a hard disk) /var/db/dhclient.leasees.$if files may exist where +not desired. +The presence of /var/db/dhclient.leases.$if (where $if is the interface name) +triggers DHCP mode to be turned on in saved +.Nm +configurations (write) and in displayed +.Nm +configurations (show running-config). +If you are using +.Nm +on a system where /var is kept persistently, look at the running +configuration and execute 'no ip dhcp' for insterfaces on which you do not +intend to use DHCP. +.Bd -literal -offset indent +nsh(interface-fxp0)/ip dhcp +.Ed +.Pp +.Op no +.Ic description +.Ar text +.Pp +Adds or removes a descriptive label to the interface. +.Bd -literal -offset indent +nsh(interface-em0)/description Chris-WAN01-Link +.Ed +.Pp +.Op no +.Ic group +.Ar group-name +.Op another-group-name...groupname-N +.Pp +Adds or removes a group label to the interface. +The group can then be referred to in other configuration such as the +firewall pf configuration. +This is useful for grouping similar interfaces together and, can reduce the +size of your firewall rule set. +An interface can be a member of multiple groups. +.Bd -literal -offset indent +nsh(interface-em0)/group WAN +.Ed +.Pp +.Tg rdomain +.Op no +.Ic rdomain +.Ar routing-domain-number +.Pp +Set the +.Xr rdomain 4 +or routing domain of an interface. +Note that this command clears all existing ip configuration on the interface. +Therefore, you should run this command before any configuring any other +setting on the interface. +.Pp +.Op no +.Ic rtlabel +.Op Ar rtable-id +.Pp +Set or remove the +.Xr rtable 4 +id on an interface. +Each +.Xr rdomain 4 +can contain multiple +.Xr rtable 4 +this feature allows for policy routing within each rdomain. +.Pp +.Op no +.Ic priority +.Ar 0-15 +.Pp +Set the interface routing priority to a value in the range of 0 to 15 with +smaller numbers being better. +The default priority of an interface is 0, except for IEEE 802.11 wireless +interfaces (priority 4), umb(4) interfaces (priority 6), and carp(4) +interfaces (priority 15). +The default priority of newly connected routes (routes created by +configuring an IP address on an interface) is calculated by adding 4 +(RTP_CONNECTED) to the interface priority. +The default priority of new static routes added to the kernel is calculated +by adding 8 (RTP_STATIC) to the interface priority. +.Pp +.Op no +.Ic llpriority +.Ar 0-7 +Sets or remove the priority for link layer communications on the interface +to a value between 0-7 +.Xr arp 8 +.Xr ndp 8 +.Xr bpf 4 +.Xr pppoe 4 +.Bd -literal -offset indent +nsh(interface-em0)/llpriority 7 +.Ed +.Pp +.Op no +.Ic mtu +.Ar mtu-bytes +.Pp +Add or remove a configured Maximum Transmission Unit (MTU) on the interface. +This is the maximum packet size that the operating system is permitted to +transmit. +Use the +.Ic no +keyword to set +.Ic mtu +to reset the interface MTU to the default value for that interface type. +.Pp +The output of 'show interface' displays a 'hardmtu' value which is the +maximum mtu value supported by the hardware and driver currently installed. +The mtu command fails gracefully if the specified mtu exceeds the hardmtu +value of the interface. +.Pp +A larger MTU is particularly useful for underlay interfaces which +encapsulated tunneled traffic traverses or for features which stack tags, +such as +.Xr pppoe 4 , +.Xr vxlan 4 , +.Xr etherip 4 , +.Xr eoip 4 , +.Xr gre 4 , +.Xr vlan 4 , +QinQ, svlan or tagging or QinQ (svlan) tagging and MPLS devices such as +.Xr mpe 4 , +.Xr mpip 4 , +and +.Xr mpw 4 . +.Pp +nsh(interface-vr0)/mtu 1600 +.Pp +.Op no +.Ic metric +.Ar 0-2147483647 +.Pp +Set routing metric for the interface. +Using +.Ic no +keyword +before metric sets the interface metric to the default value of zero. +.Bd -literal -offset indent +nsh(interface-fxp0)/metric 2 +.Ed +.Pp +.Op no +.Ic link <0|1|2> +.Pp +Set any of the link flags on the interface. +Using +.Ic no +keyword before +.Ic link XYZ +removes the specified link flags 'XYZ'. +Using +.Ic no +keyword before +.Ic link +removes all link flags from the interface. +.Bd -literal -offset indent +nsh(interface-gre0)/no link 0 +.Ed +Each different interface type uses link flags for different purposes. +.Pp +.Tg arp +.Op no +.Ic arp +.Pp +Enable or disable +.Xr arp 8 +Address Resolution Protocol ARP on the interface. +(Enabled by default.) +.Bd -literal -offset indent +nsh(interface-fxp0)/arp +nsh(interface-fxp0)/no arp +.Ed +.Pp +.Op no +.Ic staticarp +.Pp +Always use static ARP entries to find other hosts reachable via the interface. +(Disabled by default.) +.Bd -literal -offset indent +nsh(interface-fxp0)/staticarp +nsh(interface-fxp0)/no staticarp +.Ed +.Pp +Only hosts with entries in the static ARP table will be reachable via +the interface. +Static ARP entries can be configured using the +.Cm arp +command in the global context (not the +.Cm arp +command in the interface context). +.Pp +When +.Cm staticarp +is enabled no ARP requests will be sent out on the interface, while +responses to incoming ARP requests for the interface's own addresses +will still be sent. +If ARP was previously disabled on the interface with the +.Cm no arp +command then ARP will be automatically re-enabled to allow outgoing +ARP responses. +.Pp +.Tg macaddress +.Tg lladdr +.Op no +.Ic lladdr +.Ar mac-address | random +.Pp +Set or remove the mac address on the interface. +The administrator can specific a macadress in colon notation e.g. +00:11:22:33:44:55 or random to request a random mac address assignment +for the interface. +.Bd -literal -offset indent +nsh(interface-vether3)/lladdr random +nsh(interface-vether3)/lladdr 00:11:22:33:44:55 +.Ed +.Pp +.Op no +.Ic nwid +.Ar network-id +.Pp +Set or remove the configured network ID for an 802.11 capable interface. +Use the +.Ic no +keyword before the +.Ic nwid +to reset to the default value of a blank network ID. +.Pp +.Op no +.Ic nwkey +.Ar key +.Pp +Set the WEP network key for an 802.11 capable interface. +Use the +.Ic no +keyword before nwkey to turn off WEP. +.Pp +.Op no +.Ic powersave +.Ar time +.Pp +Set the 802.11 powersaving mode to X ms of time. +Use the +.Ic no +keyword before powersave to set the powersave mode to the default powersave +time. +.Pp +.Op no +.Ic txpower +.Ar dBm +.Pp +Set the transmit power on an 802.11 radio network interface manually. +Power units are in dBm. +Use the +.Ic no +keyword before +.Ic txpower +to set the radio transmit power to automatic. +.Pp +E.g to set the tx power of iwn0 to 10dBm simply enter the command below: +.Bd -literal -offset indent +nsh(interface-iwn0)/txpower 10 +.Ed +.Pp +.Op no +.Ic bssid +.Ar mac-address +.Pp +Set or remove the configured BSSID of a radio interface to a specific +MAC address, the mac-address should be entered in semi colon format +e.g. 12:34:56:78:9a:bc. +.Pp +E.g. set the bssid of radio interface iwn0 +.Bd -literal -offset indent +nsh(interface-iwn0)/bssid 12:34:56:78:90:12 +.Ed +.Pp +.Op no +.Ic media +.Op type +.Op instance +.Pp +Set the media type of the interface. +Entering media without an argument diplays help for the media settings +available for the interface. +.Pp +E.g. show media settings supported by an intel pro 1000 em(4) interface +.Pp +nsh(interface-em0)media +.Pp +%autoselect | 10baseT | 100baseTx | 1000baseT. +.Pp +E.g to set the speed of the network interface speed to 1000mb/s +.Bd -literal -offset indent +nsh(interface-em0)/media 1000baseT +.Ed +Note! Enabling verbose mode and running show interface +displays all media settings supported by the network interface. +.Bd -literal -offset indent +nsh(p)/verbose +% Diagnostic mode enabled + +nsh(p)/sho int vr0 +% vr0 + Interface is up (last change 37d 12:16:02), protocol is up + Interface type Ethernet (Broadcast), hardware address 00:0d:b9:29:6b:50 + Media type autoselect (100baseTX full-duplex), status active + Internet address 100.64.0.1/24, fe80::20d:b9ff:fe29:6b50%vr0/64 + Routing Domain 0, MTU 1500 bytes (hardmtu 1740), Line Rate 100 Mbps + 187081496 packets input, 232860544316 bytes, 19 errors, 0 drops + 102231197 packets output, 21564487790 bytes, 0 errors, 3267264 unsupported + 1244 input, 210 output (average bytes/packet) + 0 collisions + Flags: + + Hardware features: + + Supported media types on vr0: + media none + media 10baseT + media 10baseT, mediaopt full-duplex + media 100baseTX + media 100baseTX, mediaopt full-duplex + media autoselect + +.Ed +To force the interface to use a particular media type, +.Bd -literal -offset indent +nsh(interface-vr0)/media 10baseT +.Ed +.Pp +.Op no +.Ic mediaopt +.Ar option +.Pp +Set or remove media options such as full-duplex / half-duplex. +.Pp +e.g to set vr0 interface to full-duplex mode: +.Bd -literal -offset indent +nsh(interface-vr0)/mediaopt full-duplex + +nsh(interface-vr0)/no mediaopt full-duplex +.Ed +.Pp +.Op no +.Ic auth +.Cm proto +.Ar pap | chap +.Cm name Ar name-text +.Cm key Ar key-text +.Pp +Set or remove the PPP authentication parameters for the interface. +.Pp +.Op no +.Ic peer +.Cm proto Ar pap | chap +.Cm name Ar name-text +.Cm key Ar key-text +.Op Cm flag Ar callin | norechalange +.Pp +Set or remove configured peer PPP authentication parameters for the interface. +.Pp +.Op no +.Ic tunnel +.Ar source-ip destination-ip +.Op Cm ttl Ar 0-255 +.Op df +.Op ecn +.Pp +Set or remove tunnel assignments with this command. +Note that tunnel assignments are only valid on gif and gre interfaces at +this time. +TODO +.Bd -literal -offset indent +nsh(interface-gre0)/tunnel 12.3.3.3 12.6.6.6 +.Ed +.Pp +.Op no +.Ic tunneldomain +.Op rdomain-id +.Pp +Set or remove tunnel routing domain over which tunnel encapsulated packets +are to be exchanged between tunnel ip endpoints. +.Pp +.Op no +.Cm txprio Op Ar 0-7 | packet | payload +.Pp +Set or remove configured transmit priority of the headers of a tunnel interface. +Valid options are standard traffic priority values (0-7) or set the headers +according to encapsulated packet or payload priority. +.Pp +E.g. to set the priority of headers of the tunnel gre1 to match that of the +payload. +.Bd -literal -offset indent +nsh(interface-gre1)/txprio payload +.Ed +.Pp +.Op no +.Cm rxprio Op Ar 0-7 | packet | payload +.Pp +Set or remove configured receive priority of the headers of a tunnel +interfaces are standard traffic priority values (0-7) or set the headers +according to encapsulated packet / payload priority). +.Pp +E.g. to set the priority of headers of tunnel gre1 manually to 7 regardless +of payload: +.Bd -literal -offset indent +nsh(interface-gre1)/rxprio 7 +.Ed +.Pp +.Tg vxlan +.Tg vlan +.Tg vnetid +.Tg vni +.Op no +.Cm vnetid Op 0-16777215 | 1-4094 +.Pp +On a +.Xr vxlan 4 +interface, set or remove the 24 bit virtual network identifier VNI tag. +Virtual network identifier tags are typically used in large multi +tenant VXLAN multiple routing domain environments and have an +acceptable range of 0-16777215. +.Pp +On a +.Xr vlan 4 +interface, set or remove the VLAN ID in IEEE 802.1Q vlan tag +If vnetid invoked inside a vlan interface the acceptable range is the +standard 12-bit vlan id 1-4094. +.Pp +E.g. set vxlan100 vnetid to 8192. +.Bd -literal -offset indent +nsh(interface-vxlan100)/vnetid 8192 +.Ed +.Pp +.Op no +.Cm vnetflowid +.Pp +Allow or disallow the interface to use a portion of the virtual network +identifier space as a flow identifier. +This allows loadbalancing of the encapsulated traffic over multiple links. +.Pp +E.g. enable vnetflowid load balancing for gre1. +.Bd -literal -offset indent +nsh(interface-gre1)/vnetflowid +.Ed +.Pp +.Op no +.Ic parent +.Ar parent-interface +.Pp +Set or remove the parent interface for a +.Xr vlan 4 +interface. +.Pp +E.g. set the parent interface of vlan1024 to em0. +.Bd -literal -offset indent +nsh(interface-vlan1024)/parent em0 +.Ed +.Pp +.Tg pair +.Tg patch +.Op no +.Ic patch +.Ar pair-interface-name +.Pp +Set or remove patch (layer1+ connection) between current interface and another +.Xr pair 4 +interface. +A patch is a CPU efficient way of forwarding packets between two +.Xr pair 4 +interfaces, the forwarding mechanisim is layer1 like a cable what is sent +by one +.Xr pair 4 +interface is recived by the other +.Xr pair 4 +interface and vice versa. +Patch can only connect two +.Xr pair 4 +interfaces, no other interface types are supported. +.Pp +E.g. To connect pair1 and pair2 interfaces with a virtual patch cable. +.Bd -literal -offset indent -compact +nsh(p)/interface pair1 + +nsh(interface-pair1)/patch pair2 +.Ed +.Pp +.Op no +.Ic keepalive +.Op Ar period Ar count +.Pp +Enable or disable gre / gre based interfaces sending keepalive packets sent +every period seconds. +A second timer is run with a timeout of count * period. +If no keepalive response is received during that time, the link is considered +down. +The minimal usable count is 2 since the round-trip time of keepalive packets + needs to be taken into account. +.Pp +E.g. enable keepalives on interface gre1 at 1 second interval and down +count of 3. +.Bd -literal -offset indent +nsh(interface-gre1)/keepalive 1 3 +.Ed +.Pp +.Tg mpls +.Tg vpls +.Tg label +.Op no +.Ic mplslabel +.Op Ar 16-1024575 +.Pp +Set or remove the local MPLS label to the specified mplslabel this label on +the local system shall de-encapsulated for input. +(MPLS labels 0-15 inclusive are reserved labels and cannot be used). +MPLS labels are supported for +.Xr mpe 4 , +.Xr mpip 4 +and +.Xr mpw 4 +interfaces. +.Pp +E.g. set the mpls label to 10240 on interface mpe1. +.Bd -literal -offset indent +nsh(interface-mpe1)/mplslabel 10240 +.Ed +.Pp +.Op no +.Ic pwe neighbor +.Op Ar neighbor-label Ar neighbor-ip +.Pp +Set or remove the configuration of the PWE3 neighbor, configured with an MPLS +neighbor label and a neighbor ip. +neighbor-label can be any value 16-1024575. +neighbour-ip should be set to the ip address of the PWE3 neighbor. +.Pp +.Op no +.Ic pwe +.Op Ar cw +.Pp +Enable or disable the use of PWE3 Control Word. +The control word is used to facilitate fragmentation across mpls packets. +This option supported on the +.Xr mpip 4 +and +.Xr mpw 4 +interfaces. +.Pp +E.g. enable control word on an mpls pseudo wire interface mpw1. +.Bd -literal -offset indent +nsh(interface-mpw1)/pw cw +.Ed +.Pp +.Op no +.Ic pwe +.Op Ar fat +.Pp +Enables or disables the use of PWE flow-aware transport FAT flow label. +This option supported on the +.Xr mpip 4 +and +.Xr mpw 4 +interfaces. +.Pp +E.g. Enable flow-aware transport flow label on mpls ip interface mpip1 +.Bd -literal -offset indent +interface-mpip1)/pw fat +.Ed +.Pp +.Tg pfsync +.Tg sync +.Tg syncdev +.Op no +.Ic syncdev +.Ar syncdev-name +.Pp +Configures or removes the data interface through which pfsync update messages +are sent. +Note that the pfsync protocol currently includes no authentication method. +It is advisable to layer authentication, signing and (possibly encrypted +tunnels for the underlay interfaces. +For simplicity on co-located pfsynced firewalls a secure way to use pfsync, +is through a a direct (layer1 (i.e. no switches)) cable connecting directly +between two pfsync capable devices (i.e. a conenction made with an ethernet +patch cable). +This command is valid only for +.Xr pfsync 4 +interfaces. +.Pp +E.g. Set the physical interface em1 as the pfsync0 syncdev +.Bd -literal -offset indent +nsh(interface-pfsync0)/syncdev em1 +.Ed +.Pp +.Op no +.Ic syncpeer +.Op Ar ipv4-peer-pfsync-address +.Pp +Set or remove a manually entered ip address of the pfsync interface of a +peer pf sync firewall. +By default, state change messages are sent out on the synchronisation +interface using IP multicast packets to the 224.0.0.240 group address. +When syncpeer ip address is set the sync messages are sent via unicast +to the specified ipv4-peer-pfsync-address. +This command is valid only for +.Xr pfsync 4 +interfaces. +.Pp +E.g. set sync messages to use unicast peer ip address 192.0.0.10 which +is reachable via syncdev interface. +.Bd -literal -offset indent +nsh(interface-pfsync0)/syncpeer 192.0.0.10 +.Ed +.Pp +.Op no +.Ic maxupd +.Ar 0-255 +.Op defer +.Pp +Configures or removes the maximum number of updates which are collapsible into +one for a single state. +The default value is 128. +The transmission a pfsync update packet shall be delayed by a maximum of 1 +second. +The defer flag defers the first packet of each connection from being +delivered until the state is active on pfsync peer. +This command is valid only for +.Xr pfsync 4 +interfaces. +.Pp +E.g. set the pfsync to aggregate the maximum number of state changes before +sending a pfsync update message (reduce pfsync traffic updates) +.Pp +nsh(interface-pfsync0)/maxupd 255 +.Pp +E.g. set pfsync to aggregate a max of 32 state changes in one packet and delay +fowarding of new connection packets until peers pfstate is synchronised use: +.Bd -literal -offset indent +nsh(interface-pfsync0)/maxupd 32 defer +.Ed +.Pp +.Tg carp +.Tg hsrp +.Tg vrrp +.Op no +.Ic vhid +.Op Ar 1-255 +.Pp +Configure or remove the virtual host ID for the Common Address Redundancy +CARP protocol. +vhid is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. set virtual router host id on carp0 interface to 12. +.Bd -literal -offset indent +nsh(interface-carp0)/vhid 12 +.Ed +.Pp +.Op no +.Ic advbase +.Op Ar 0-254 +.Pp +Configure or remove the advertisement interval in seconds for the master host +to advertise itself. +advbase is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. set the advertisement interval to 10 seconds on carp0 interface. +.Bd -literal -offset indent +nshpromot(interface-carp0)/advbase 10 +.Ed +.Pp +.Op no +.Ic advskew +.Ar skew +.Pp +Configure or remove the carp advertisement skew on the active carp interface. +The formula is advbase + (advskew / 255). +If the master does not advertise within three times this interval, this host +assumes master role and starts advertising as master. +The device with the highest advskew value is least likely to become master, +a device with a high advskew only becomes master if all other devices are +offline. advskew is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. set the advskew to 20 on carp0 interface. +.Bd -literal -offset indent +nsh(interface-carp0)/advskew 20 +.Ed +.Pp +.Op no +.Ic carppass +.Ar passphrase +.Pp +Configure or remove the CARP passphrase of the active interface. +The passphrase can be up to 19 characters long and can contain special +characters. +There is no passphrase by default. +carpass is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. Set carp0 carp passphrase to 19CharPassphrase!!! including exclamation +marks. +.Bd -literal -offset indent +nsh(interface-carp0)/carppass 19CharPassphrase!!! +.Ed +.Pp +.Op no +.Ic carpdev +.Op Ar interface-name +.Pp +Set or remove the interface on which the selected carp interface's carp +advertisements are sent and received. +The carpdev is the "real interface" over which the carp virtual IP is +accessible. +carpdev is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g set carp0 to use vlan10 as its carpdev. +.Bd -literal -offset indent +nsh(interface-carp0)/carpdev vlan10 +.Ed +.Pp +.Op no +.Ic carpnode +.Op Ar vhid +.Op advskew +.Op state +.Pp +Set or remove carpnode parameter on a carp interface. +carpnode facilitates loadbalancing across carp nodes. +Each carpdevice that you wish to loadbalance should have a carpnode and +advskew entry on each carp device. +carpnode is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. For a 3 node carp cluster, one can setup carpnode loadbalanced entries as +follows. +.Pp +on carp router 1 +.Bd -literal -offset indent +nsh(interface-carp0)/carpnode 1 10 +.Ed +on caro router 2 +.Bd -literal -offset indent +nsh(interface-carp0)/carpnode 1 20 +.Ed +on carp router 3 +.Bd -literal -offset indent +nsh(interface-carp0)/carpnode 1 30 +.Ed +.Pp +.Op no +.Ic carppeer +.Op Ar peer-ip-address +.Pp +Set or remove the carppeer ip address of a carp peer on the active carp +interface. +carppeer is valid for +.Xr carp 4 +interfaces only. +.Pp +E.g. set carppeer to 10.2.3.4 on carp0 interface. +.Bd -literal -offset indent +nsh(interface-carp0)/carppeer 10.2.3.4 +.Ed +.Pp +.Op no +.Cm balancing Op Ar none | ip | ip-stealth | ip-unicast +.Pp +Set or remove the balancing mode on the active carp interface. +Valid balancing modes are as follows: +.Bl -bullet -compact +.It +none no load-balancing. +.It +ip IP load balancing on top of Layer 2 multicast MAC + (requires multicast mac support on the network switch) +.It +ip-stealth carp wont send packets with its own virtual MAC + address as the source. + Stealth mode prevents a switch from learning the + virtual MAC address, therefore the switch would + unicast flood traffic to all switch ports + (unless there is some swithc acls to prevent flooding + unnecessarily. +.It +ip-unicast Used in conjunction with a HUB or a switch that + can replicate packets (monitoring or mirror) or + other non-standard switch forwarding mechanism. +.El +Note: IP balancing is being used on a firewall, it is recommended to +configure the carpnodes in a symmetrical manner. +This is achieved by simply using the same carpnodes list on all sides of the +firewall. +This ensures that packets of one connection pass in and out on the same host +and are not routed asymmetrically. +.Pp +balancing is valid when used in +.Xr carp 4 +interfaces. +.Pp +E.g. enable standard IP balancing over layer2 multicast mac on carp0 interface +.Pp +nsh(interface-carp0)/balancing ip +.Pp +.Op no +.Ic pflow +.Op Cm sender Ar sender-ip Cm receiver Ar receiver-ip:port +.Op Cm version Ar 5 | 9 | 10 +.Pp +Set or remove pflow export to a +.Xr pflow 4 +interface. +plfow without arguments displays command help. +To set a up a pflow export the sender-ip and receiver-ip:port must be specified. +The specified pflow sender-ip address must exist on an interface on the +system already. +The receiver-ip:port is the address of the flow collector in your network. +version specifies the export flow prtocol i.e. netflow version (5 or 9) or +the standardised IPFIX (10). +.Pp +The pflow interface attempts aggregate multiple pflow records in one +export UDP packet. +The aggregation algoritim record for longer than 30 seconds. +The packet size and thus the maximum number of flows is controlled by the +mtu of the inteface the flows are exported via. +.Pp +There is a one-to-one correspondence between packets seen by bpf(4) on +the pflow interface and packets sent out to the flow receiver. +I.e. if a packet with 30 flows on pflow, then the same 30 flows were sent out +to the receiver. +.Pp +pflow command is valid only on a +.Xr pflow 4 +interface. +.Pp +E.g. to setup a pflow export from 10.1.1.1 to an IPFIX flow collector +listening on another server on 10.1.1.2 port 4739. +.Bd -literal -offset indent +nsh(p)/interface pflow0 + +nsh(interface-pflow0)/pflow sender 10.1.1.1 receiver 10.1.1.2:4379 version 10 +.Ed +.Pp +.Op no +.Ic debug +.Pp +Set or remove the driver-dependant debugging flag for an interface. +Useful for troubleshooting. +.Pp +E.g to set debugging on a carp0 interface. +.Bd -literal -offset indent +nsh(interface-carp0)/debug +.Ed +.Pp +.Tg relay +.Tg dhcp +.Tg dhcprelay +.Tg dhcrelay +.Op no +.Ic dhcrelay +.Op Ar dhcp-server-ip +.Pp +Set or remove dhcp relay agent on the selected interface. +The +.Xr dhcrelay 8 +service listens on the selected interface for broadcast +dhcp requests and then wrap the recieved broadcast request in a unicast ip +packet and send it to a DHCP server specified by dhcp-server-ip. +.Pp +E.g. set up dhcprelay on em0 and send requests to DHCP server 10.1.1.2 +.Bd -literal -offset indent +nsh(interface-em0)/dhcrelay 10.1.1.2 +.Ed +.Pp +.Tg wake +.Tg wol +.Op no +.Ic wol +.Pp +Enable or disable WOL (wake on lan) functionality on the selected interface. +The interface and device bios or firmware must support WOL functionality. +.Pp +E.g. to enable wake on lan on interface em0. +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/wol +.Ed +.Pp +.Tg mpls +.Tg vpls +.Tg label +.Op no +.Ic mpls +.Pp +Set or remove the MPLS flag on the selected interface,if mpls is set on the +interface, the interface can send and receive mpls traffic. +.Pp +E.g enable mpls on em0 +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/mpls +.Ed +.Pp +.Op no +.Ic inet6 +.Pp +Enables or disables ipv6 (inet6) link local address on the selected interface. +.Pp +E.g. to enable ipv6 link local address on em0 +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/rad +.Ed +.Pp +.Op no +.Ic autoconf6 +.Pp +Enable or disable IPv6 auto configuration of Ipv6 address on the inteface. +If autoconf6 is used alone (without temporary or autoconfprivacy being set +on the interface then the autoconfigured address assigned is repeatable based +on the MAC address of the interface (EUI64). +.Pp +E.g. enable ipv6 autoconf address on the interface em0. +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/autoconf6 +.Ed +.Pp +.Op no +.Ic temporary +.Pp +Configure or remove temporary address extension for stateless ipv6 +autoconfiguaration. +Temporary address assignments prevents a repeatable IPv6 address being assigned +to the device to reduce the possibility of longterm external tracking of +device (users) activity. +.Pp +E.g. enable ipv6 autoconf with a temporary address on the interface em0. +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/autoconf6 + +nsh(interface-em0)/temporary +.Ed +.Pp +.Op no +.Ic autoconfprivacy +.Pp +deprecated. alias for Cm temporary above. +Randomised addresses used to be called autoconfprivacy extensions for IPv6. +Temporary addressing is a better description as privacy is not necessarily +guaranteed by random IP addressing of a device. +.Pp +E.g. enable ipv6 autoconf with "privacy" random temp address on the +interface em0. +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/autoconf6 + +nsh(interface-em0)/autoconfprivacy +.Ed +.Pp +.Tg sensor +.Tg monitor +.Tg sniff +.Tg span +.Op no +.Ic monitor +.Pp +Configure or remove the monitor flag on the selected interface. +Prevents the packets being processed in the network stack. +Useful for intrusion detection sniffing and other diagnostics. +.Pp +E.g. to enable ipv6 autoconf with "privacy" random temp address on the +interface em0 +.Bd -literal -offset indent +nsh(p)/interface em0 + +nsh(interface-em0)/monitor +.Ed +.Pp +.Tg wireguard +.Tg wg +.Op no +.Cm wgpeer Op Ar public-key +.Op Cm endpoint Ar endpoint-ip:port | Cm aip Ar allowed-ip/prefix | Cm psk Ar pre-shared-key | Cm pka Ar interval-sec +.Pp +Configure or remove a wireguard peer with the peers publickey. +The public-key is 32 bytes and base64-encoded. +.Pp +.Ic pka Ar interval-sec +The persistent keep alive (pka) option sets the interval of keepalive packets +in seconds. +By default pka is is disabled i.e. the interval is 0. +pka can help maintain connectivity to a peer that would otherwise be denied +unsolicited traffic by an intermediate firewall or NAT device. +Empirically, an interval of 25 seconds should suffice for most firewall +configurations. +.Pp +.Ic psk Ar pre-shared-key +The psk and preshared-key is optional but recommended as it supplements the +public key cryptography with symmetric key cryptography. +.Pp +.Ic aip Ar allowed-ip/prefix +Set the peer's allowed IPv4 or IPv6 addresses or prefixes for tunnelled traffic. +The option be repeated to set multiple allowed ip/ranges. +No addresses are allowed by default. +.Bl -dash +.It +E.g set the a peer with the following requirements: +.Bl -bullet +.It +public key EJqeFntM71Dfvn/LDu88gLOWw8aeOHoxrshOEHFd6lQ= +.It +from an ip of 10.1.2.3/32 +.It +with a keep alive packet interval of 25 seconds +.El +.El +.Bd -literal -offset indent +nsh(p)/interface wg0 + +nsh(interface-wg0)/wgpeer EJqeFntM71Dfvn/LDu88gLOWw8aeOHoxrshOEHFd6lQ= +aip 10.1.2.3/32 endpoint 10.1.2.3:5252 +psk oJo0kNhoF3TElGUXDg4b0H6IJvOiVCAc/tuaJa1nmVU= +.Ed +.Ic wgkey +.Op Ar privatekey +Set the private key of the current +.Xr wg 4 +wireguard interface. +When +.Ic wgkey +is run without an argument a new wireguard key is generated for the interface. +The privatekey is 32 bytes and base64-encoded. +.Pp +E.g. set the private key of +.Xr wg 4 +wireguard interface wg0 to a specific key. +.Bd -literal -offset indent +nsh(p)/interface wg0 + +nsh(interface-wg0)/wgkey QComa+ca+mWih+Vl/5G/p+UwhYy17hw5vdwysZpIAn0= +.Ed +.Pp +.Op no +.Ic wgport Ar 0-65535 +.Pp +Set or remove the configuration for the local UDP port to be used by the +current wireguard interface when exchanging traffic with its wireguard peers. +The interface binds to INADDR_ANY and IN6ADDR_ANY_INIT. +If +.Ic wgport +is entered without an argument wireguard selects its own port automatically. +.Pp +E.g. set wireguard interface wg0 to listen on 18443 UDP. +.Bd -literal -offset indent +nsh(p)/interface wg0 + +nsh(interface-wg0)/wgport 18443 +.Ed +.Pp +.Op no +.Ic wgrtable +.Op Ar rtable-id +.Pp +Set or remove the configuration of which routing table the Exchange traffic +with peers under. +The routing table choice is made using rtable-id which would be a value +between 0 and 255 on a default +.Ox +kernel. +The routing domain of the wgrtable does not need be in the same routing domain +to which the interface is attached. +wgrtable configures which +.Xr rdomain 4 +the interface's tunnelled traffic appears. +.Pp +E.g. set wireguard interface wg0 routing table to routing domain 5. +.Bd -literal -offset indent +nsh(p)/interface wg0 + +nsh(interface-wg0)/wgrtable 5 +.Ed +.Pp +.Op no +.Ic shutdown +.Pp +Administratively turn off or on the current interface. +.Pp +Using this command to shutdown and then turn up an interface resets the +interface. +.Bd -literal -offset indent +nsh(interface-de0)/shutdown +nsh(interface-de0)/no shutdown +.Ed +.Sh Section 5 > Bridge mode commands +see the following man pages for information +.Pp +!man bridge +.Pp +!man ifconfig +.Sh Section 6 > PF mode commands +see the following man pages for information +.Pp +!man pfctl +!man pf.conf +.Sh Section 7 > Adding system users to +.Nm +. +.Pp +.Ox +has facilities for a user to be able to login directly to nsh without +having access to a typical bourne or C shell. +.Pp +Configure the user so they can run /bin/nsh from sudo. +You must do this in /etc/sudoers, like this: +.Bd -literal -offset indent +nshuser ALL=NOPASSWD:/bin/nsh +.Ed +(replace 'nshuser' with the actual user name) +.Pp +Another way to configure sudoers is to allow all users that are members +of a certain group to run NSH through sudo, like this: +.Bd -literal -offset indent +%nshgroup ALL=NOPASSWD:/bin/nsh +.Ed +(replace 'nshgroup' with the actual group name) +.Pp +Compile nwrapper (in the nsh distribution): +.Bd -literal -offset indent +cc -static -o nwrapper nwrapper.c +.Ed +Move nwrapper to a permanent location: +.Bd -literal -offset indent +mv nwrapper /bin/nwrapper +.Ed +Change the user's shell to nwrapper: +.Bd -literal -offset indent +usermod -s /bin/nwrapper nshuser +.Ed +(replace 'nshuser' with the actual user name) +.Pp +Do NOT add nwrapper (or nsh) to /etc/shells. +They should not be entered here. +.Sh Common interface types +Packet Filter Logging: This interface is used to pass traffic logged by +the firewall to software which can record it. +These interface names start with 'pflog'. +.Pp +IPsec Loopback: This interface is used internally in the system to +pass decapsulated IPsec traffic. +All traffic from this interface has already been authenticated and +unencrypted from the IPsec subsystem. +This is useful when writing firewall rules. +These interface names start with 'enc'. +.Pp +Generic Tunnel: This interface is used to configure a network tunnel to +another host or router. +It follows the RFC1933 tunnelling standard. +These interface names start with 'gif'. +.Pp +Ethernet Bridge: This interface is used to configure layer 2 bridging +between physical and virtual network ports on a system. +These interface names start with 'bridge'. +.Pp +Ethernet: This is a physical Ethernet interface, running at 10, 100, or +1000 megabits per second. +These interface names are based on the name of the driver, and vary with +different Ethernet chip types. +.Pp +IEEE 802.1Q Virtual: This is a virtual Ethernet, Token Ring, or FDDI +interface. +It uses the IEEE 802.1Q protocol to segment real Ethernet interfaces into +multiple layer 2 networks. +These interface names start with 'vlan'. +.Pp +Virtual: This is a virtual interface of any type. +Often several different interfaces use this type. +Several versions of +.Ox +use this type to denote virtual IEEE 802.1Q interfaces, described above. +.Pp +PPP: This interface implements the Point to Point Protocol (PPP). +PPP, described in RFC 1661, creates a network over serial communication lines. +It is used over modem connections, direct serial links, leased lines, and +over virtual IP based connections such as in SSH sessions. +These interface names start with 'ppp' when referring to a version which +supports serial and modem connections. +Other interface types may also implement the Point to Point Protocol. +.Pp +IEEE 802.11 Wireless: This interface implements the IEEE 802.11 wireless +LAN protocol. +Many implementations of this network have little or no security unless used +with proper encryption such as IPsec. +These interface names are based on the name of the driver, and vary with +different wireless chip types. +.Sh Interface flags +.Bl -bullet -compact +.It +.Ic UP +.Pp + Interface is up +.Pp +.It +.Ic BROADCAST +.Pp + broadcast address valid +.Pp +.It +.Ic DEBUG +.Pp + debugging enabed (only some network drivers use this) +.Pp +.It +.Ic LOOPBACK +.Pp + Interface is a loopback network (internal to the machine) +.Pp +.It +.Ic POINTOPOINT +.Pp + Interface is point-to-point link +.Pp +.It +.Ic NOARP +.Pp + Address Resolution Protocol is disabled on this interface +.Pp +.It +.Ic PROMISC +.Pp + Interface is in promiscuous mode, the system's software to + receive all packets visible to the network card, + even if they are not destined for this host +.Pp +.It +.Ic ALLMULTI +.Pp + This causes the interface to receive all multicast traffic, + even for multicast networks that it was not signed up for +.Pp +.It +.Ic OACTIVE +.Pp + Transmission in progress. + An interface that displays this flag continuously may be + stuck. + You may be able to reset an interface that is in this state + by using and then reversing the 'shutdown' command from the + interface menu. +.Pp + E.g. reset an interface. +.Bd -literal -offset indent + nsh(p)interface vr0 + nsh(interface-vr0)/shutdown + nsh(interface-vr0)/no shutdown +.Ed +.It +.Ic SIMPLEX +.Pp + Can't hear own transmissions +.Pp +.It +.Ic LINK0 +.Pp + This flag has different meanings with different interface\ + types +.Pp +.It +.Ic LINK1 +.Pp + This flag has different meanings with different interface\ + types +.Pp +.It +.Ic LINK2 +.Pp + This flag has different meanings with different interface\ + types +.Pp +.It +.Ic MULTICAST + This interface supports multicast +.El +.Sh ALTQ notes +TODO +.Sh Interface-specific notes +There are several special interfaces. +.Ss gre +The gre interface allows for tunnel construction using the Cisco GRE +encapsulation protocol. + You can use the tunnel command under interface mode to create a tunnel. +.Bd -literal -offset indent +nsh(interface-gre0)/tunnel 1.2.3.4 5.5.5.5 +.Ed +enc (IPsec Loopback) +.Pp +enc (specifically, enc0) is the encapsulating interface. +It is a software loopback mechanism used to control non-encapsulated IPsec +traffic using the pf firewall ruleset. +It allows an administrator to see outgoing packets before they have been +processed by IPsec, or incoming packets after they have been processed. +.Pp +All traffic out of enc0 is already decrypted and authenticated via IPsec. +Thus, it is helpful when writing firewall rulesets. +.Ss ppp (Point to Point Protocol) +The serial line Point-to-Point protocol uses this interface. +.Ss sl (Serial Line Interface Protocol) +The Serial Line Internet Protocol uses this interface. +.Pp +tun (Tunnel Interface) +.Pp +This is another software loopback mechanism. +It allows user processes to create their own virtual network interfaces. +It is used by the PPPoE implementation. +.Ss gif +This interface is used for RFC 1933 IPv[46] to IPv[46] tunnels. +.Bd -literal -offset indent +nsh(interface-gif0)/tunnel 1.2.3.4 5.5.5.5 +.Ed +tunnels can be used between rdomains. +.Bd -literal -offset indent +nsh(interface-gif0)/tunnel 1.2.3.4 5.5.5.5 rdomain 5 +.Ed +.Ss pflog +Packets logged from the packet filter are visible on this interface +.Ss vlan +This interface type allows virtual LANs to be setup over an Ethernet +port using the 802.1Q protocol. +E.g. setup a virtual interface with the 192.168.44.1 IP address, +with 802.1Q trunking on the fxp3 physical interface, and a vlan ID of 4. +.Bd -literal -offset indent +nsh(interface-vlan0)/vnetid 4 + +nsh(interface-vlan0)/parent fxp3 + +nsh(interface-vlan0)/ip 192.168.44.1/24 +.Ed +.Ss Svlan +This interface type allows virtual LANs to be setup over an Ethernet +port using 802.1AD provider bridge. +.Pp +This product includes software developed by the University of California, +Berkeley and its contributors. +.Pp +This product includes software developed by Jason L. Wright +.Pp +This product includes software developed by the +.Nx +Foundation Incorporated and its contributors. +.Pp +.Ev EDITOR +was used to specify the name of an (old-style) line editor, such as +.Xr ed 1 , +and +.Ev VISUAL +was used to specify a (new-style) screen editor, such as +.Xr vi 1 . +Hence if +.Ev VISUAL +is set, it overrides +.Ev EDITOR . +TODO +.Sh FILES +.Bl -tag -width /etc/suid_profile -compact +.It Pa /etc/nshrc +global configuration file +.It Pa ~/.profile +user's login profile +.It Pa /etc/shells +shell database +.It Pa /etc/suid_profile +privileged shell profile +.El +.Sh SEE ALSO +.Bd -ragged -offset indent +.Xr ed 1 , +.Xr mg 1 , +.Xr stty 1 , +.Xr vi 1 , +.Xr pf 4 , +.Xr bgpd.conf 5 , +.Xr dhcpd.conf 5 , +.Xr ospf6d.conf 5 , +.Xr ospfd.conf 5 , +.Xr pf.conf 5 , +.Xr relayd.conf 5 , +.Xr resolv.conf 5 , +.Xr shells 5 , +.Xr environ 7 , +.Xr script 7 , +.Xr bgpd 8 , +.Xr dhcpd 8 , +.Xr dhcpleased 8 , +.Xr dvmrpd 8 , +.Xr eigrpd 8 , +.Xr ftpd 8 , +.Xr ftp-proxy 8 , +.Xr ifstated 8 , +.Xr iked 8 , +.Xr inetd 8 , +.Xr ipsecctl 8 , +.Xr ldapd 8 +.Xr ldpd 8 , +.Xr npppd 8 , +.Xr ntpd 8 , +.Xr ospf6d 8 , +.Xr ospfd 8 , +.Xr pfctl 8 , +.Xr relayd 8 , +.Xr resolvd 8 , +.Xr ripd 8 , +.Xr rad 8 , +.Xr sasyncd 8 , +.Xr slaacd 8 , +.Xr smtpd 8 , +.Xr snmpd 8 , +.Xr sshd 8 , +.Xr tftp-proxy 8 , +.Xr tftpd 8 , +.Ed +.Pp +.Rs +.%A Chris Cappuccio +.%T http://www.nmedia.net/nsh/ +.%D 2014 +.Re +.Rs +.%A Chris Cappuccio +.%T https://github.com/yellowman/nsh +.%D 2022 +.\" The second edition of the above book (1995) is about ksh93, +.\" but the OpenBSD ksh is a descendant from ksh88 via pdksh. +.Re +.Rs +.%A Stephen G. Kochan +.%A Patrick H. Wood +.%B UNIX Shell Programming, 3rd Edition +.%D 2003 +.%I Sams +.%O ISBN 0672324903 +.Re +.Sh AUTHORS +.An -nosplit +This shell was originally designed and written by +.An Chris Cappuccio Aq Mt chris@nmedia.net , +and is now co-maintained by +.An Stefan Sperling Aq Mt stsp@openbsd.org +and +.An Tom Smyth Aq Mt tom.smyth@wirelessconnect.eu . +.Sh BUGS diff --git a/freebsd/passwd.c b/freebsd/passwd.c new file mode 100644 index 0000000..9700a20 --- /dev/null +++ b/freebsd/passwd.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2004 + * Christian Gut. 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 ``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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int read_pass(char *, size_t); +int write_pass(char *); +int gen_salt(char *, size_t); + +/* read_pass reads the (blowfish crypted) password from a file */ +int +read_pass(char *pass, size_t size) +{ + FILE *pwdhandle; + + pwdhandle = fopen(NSHPASSWD_TEMP, "r"); + if (pwdhandle == NULL) + return (0); + fgets(pass, size, pwdhandle); + fclose(pwdhandle); + + return (1); +} + +/* write the crypted password to the passwd-temp file */ +int +write_pass(char *cpass) +{ + FILE *pwdhandle; + + umask(S_IWGRP | S_IRWXO); + /* maybe we should flock here? */ + pwdhandle = fopen(NSHPASSWD_TEMP, "w"); + if (pwdhandle == NULL) { + printf("%% Unable to write run-time crypt repository: %s\n", + strerror(errno)); + return (0); + } + fprintf(pwdhandle, "%s", cpass); + fclose(pwdhandle); + + return (1); +} + +int +gen_salt(char *salt, size_t saltlen) +{ + /* 6 is a rounds value like from localcipher option of login.conf */ + strlcpy(salt, "1234567", saltlen); + return 1; +} + +/* + * enable privileged mode + */ +int +enable(int argc, char **argv) +{ + char *p, *cpass; + char salt[_PASSWORD_LEN]; + char pass[_PASSWORD_LEN + 1]; + + switch (argc) { + + case 1: + if (priv == 1) + return 0; + + /* try to read pass */ + if (!(read_pass(pass, sizeof(pass)))) { + if (errno == ENOENT) { + /* no password file, so enable */ + priv = 1; + return 1; + } else { + /* cant read password file */ + printf("%% Unable to read password: %s\n", + strerror(errno)); + return 0; + } + } + p = getpass("Password:"); + if (p == NULL || *p == '\0') + return 0; + + if (strcmp(pass, pass) == 0) { + priv = 1; + return 1; + } else { + printf("%% Password incorrect\n"); + return 0; + } + + case 2: + if (argv[1][0] == '?') { + /* print help */ + printf("%% enable\t\t\t\tenable privileged mode\n"); + printf("%% enable ?\t\t\t\tShow Options\n"); + printf("%% enable secret \t\tSet password" + "(plaintext)\n"); + printf("%% enable secret \t\tSet" + " password(ciphertext)\n"); + return 1; + } else { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + case 3: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* crypt plaintext and save as pass */ + strlcpy(pass, argv[2], sizeof(pass)); + return(write_pass(pass)); + + case 4: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[2]); + return 0; + } + + if (!isprefix(argv[2], "blowfish")) { + printf("%% Invalid cipher: %s\n", argv[3]); + return 0; + } + + /* privileged? */ + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* set crypted pass */ + strlcpy(pass, argv[3], sizeof(pass)); + return (write_pass(pass)); + + default: + printf("%% Too many arguments\n"); + return 0; + } + +} diff --git a/freebsd/sqlite3.c b/freebsd/sqlite3.c new file mode 100644 index 0000000..bf02668 --- /dev/null +++ b/freebsd/sqlite3.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +int sq3simple(char *, StringList *); + +#define QSZ 1024 /* maximum query text size */ + +int +db_create_table_rtables(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS rtables (rtable INTEGER PRIMARY KEY, name TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_nameservers(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS nameservers (nameserver TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_flag_x(char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "CREATE TABLE IF NOT EXISTS %s (ctl TEXT, rtable INTEGER, flag INTEGER," + "data TEXT)", name); + return(sq3simple(query, NULL)); +} + +int +db_insert_flag_x(char *name, char *ctl, int rtableid, int flag, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO '%s' VALUES('%s', %d, %d, '%s')", + name, ctl, rtableid, flag, data); + return(sq3simple(query, NULL)); +} + +int +db_insert_rtables(int rtableid, char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO 'rtables' VALUES(%d, '%s')", rtableid, name); + return(sq3simple(query, NULL)); +} + +int +db_delete_rtables_rtable(int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'rtables' WHERE rtable=%d", rtableid); + return(sq3simple(query, NULL)); +} + +int +db_insert_nameserver(char *nameserver) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT OR REPLACE INTO 'nameservers' VALUES('%s')", + nameserver); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl(char *name, char *ctl) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND rtable=%d", name, ctl, cli_rtable); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl_data(char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, NULL)); +} + +int +db_delete_nameservers(void) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'nameservers'"); + return(sq3simple(query, NULL)); +} + +int +db_select_flag_x_ctl_data(StringList *words, char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_ctl(StringList *words, char *name, char *ctl) +{ + char query [QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s'", name, ctl); + return(sq3simple(query, words)); +} + +int +db_select_rtable_rtables(StringList *words) +{ + char query[]="SELECT rtable FROM rtables"; + return(sq3simple(query, words)); +} + +int +db_select_rtables_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable=%d", rtableid); + return(sq3simple(query,words)); +} + +int +db_select_flag_x_ctl_rtable(StringList *words, char *name, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT ctl FROM %s WHERE rtable=%d", name, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_data_ctl_rtable(StringList *words, char *name, char *ctl, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_dbflag_rtable(char *name, char *ctl, int rtableid) +{ + StringList *words; + char query[QSZ]; + int rv; + const char *errmsg = NULL; + + snprintf(query, QSZ, "SELECT flag FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + words = sl_init(); + if((rv = sq3simple(query, words)) > 0) { + rv = strtonum(words->sl_str[0], INT_MIN, INT_MAX, &errmsg); + if (errmsg) { + printf("%% db_select_flag_x_dbflag_rtable %s: %s\n", + words->sl_str[0], errmsg); + rv = -1; + } + } + + sl_free(words, 1); + + return rv; +} + +int +db_select_nameservers(StringList *words) +{ + char query[]="SELECT nameserver FROM nameservers"; + return(sq3simple(query, words)); +} + +int +db_select_name_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable='%d'", rtableid); + return(sq3simple(query, words)); +} + +/* simple query execution, dump results straight into words */ +int +sq3simple(char *sql, StringList *words) +{ + sqlite3 *db; + sqlite3_stmt *stmt; + char *result, *new = NULL; + int rv, len, tlen = 0; + + if (sqlite3_open(SQ3DBFILE, &db)) { + printf("%% database file open failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) + != SQLITE_OK) { + printf("%% sqlite3_prepare_v2 failed: %s (%s)\n", + sqlite3_errmsg(db), sql); + return -1; + } + + while ((rv = sqlite3_step(stmt)) == SQLITE_ROW) { + result = (char *)sqlite3_column_text(stmt, 0); + len = strlen(result) + 1; + if ((new = malloc(len)) == NULL) { + printf("%% sq3simple: malloc failed\n"); + break; + } + tlen += len; + strlcpy(new, result, len); + sl_add(words, new); + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + if (rv != SQLITE_DONE) { + printf("%% sq3simple: error: %s\n", sqlite3_errmsg(db)); + return -1; + } + return tlen; +} diff --git a/freebsd/stringlist.h b/freebsd/stringlist.h new file mode 100644 index 0000000..442657b --- /dev/null +++ b/freebsd/stringlist.h @@ -0,0 +1,51 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/stringlist.h,v 1.2 2002/02/16 21:27:46 millert Exp $ */ + +/* + * Copyright (c) 1994 Christos Zoulas + * 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 ``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 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. + */ + +#ifndef _STRINGLIST_H +#define _STRINGLIST_H + +#include +#include + +/* + * Simple string list + */ +typedef struct _stringlist { + char **sl_str; + size_t sl_max; + size_t sl_cur; +} StringList; + +__BEGIN_DECLS +StringList *sl_init(void); +void sl_add(StringList *, char *); +void sl_free(StringList *, int); +char *sl_find(StringList *, char *); +__END_DECLS + +#endif /* _STRINGLIST_H */ diff --git a/freebsd/sysctl.h b/freebsd/sysctl.h new file mode 100644 index 0000000..430c54a --- /dev/null +++ b/freebsd/sysctl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct ipsysctl { + char *name; + int mib[6]; + int32_t def_larg; /* default value, or 0 for on/off + * sysctls */ + int enable; /* if on/off sysctl, 0 default is enabled, 1 + * default is disabled, 2 always show ena ble + * or disable */ +}; + +struct sysctltab { + char *name; + int pf; + Menu *table; + struct ipsysctl *sysctl; +}; + +extern struct sysctltab sysctls[]; +extern struct ipsysctl ipsysctls[]; +extern struct ipsysctl ip6sysctls[]; +extern struct ipsysctl mplssysctls[]; +extern struct ipsysctl ddbsysctls[]; +extern struct ipsysctl pipexsysctls[]; +extern Menu iptab[]; +extern Menu ip6tab[]; +extern Menu mplstab[]; +extern Menu ddbtab[]; +extern Menu pipextab[]; + +#define DEFAULT_MAXDYNROUTES 4096 /* net.inet6.ip6.maxdynroutes */ +#define DEFAULT_NEIGHBORGCTHRESH 2048 /* net.inet6.ip6.neighborgcthresh */ diff --git a/freebsd/utils.c b/freebsd/utils.c new file mode 100644 index 0000000..e34c246 --- /dev/null +++ b/freebsd/utils.c @@ -0,0 +1,144 @@ +/* + * Steal some useful routines from top + * + * Copyright (c) 1984, 1989, William LeFebvre, Rice University + * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University + * + * 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 ``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 HIS EMPLOYER 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +/* + * string_index(string, array) - find string in array and return index + */ +int +string_index(char *string, char **array) +{ + int i = 0; + + while (*array != NULL) { + if (strncmp(string, *array, strlen(string)) == 0) + return (i); + array++; + i++; + } + return (-1); +} + +/* + * format_time(seconds) - format number of seconds into a suitable display + * that will fit within 6 characters. Note that this routine builds its + * string in a static area. If it needs to be called more than once without + * overwriting previous data, then we will need to adopt a technique similar + * to the one used for format_k. + */ + +/* + * Explanation: We want to keep the output within 6 characters. For low + * values we use the format mm:ss. For values that exceed 999:59, we switch + * to a format that displays hours and fractions: hhh.tH. For values that + * exceed 999.9, we use hhhh.t and drop the "H" designator. For values that + * exceed 9999.9, we use "???". + */ + +char * +format_time(time_t seconds) +{ + static char result[10]; + + /* sanity protection */ + if (seconds < 0 || seconds > (99999l * 360l)) { + strlcpy(result, " ???", sizeof result); + } else if (seconds >= (1000l * 60l)) { + /* alternate (slow) method displaying hours and tenths */ + snprintf(result, sizeof(result), "%5.1fH", + (double) seconds / (double) (60l * 60l)); + + /* + * It is possible that the snprintf took more than 6 + * characters. If so, then the "H" appears as result[6]. If + * not, then there is a \0 in result[6]. Either way, it is + * safe to step on. + */ + result[6] = '\0'; + } else { + /* standard method produces MMM:SS */ + /* we avoid printf as must as possible to make this quick */ + snprintf(result, sizeof(result), "%3d:%02d", (int)seconds / 60, + (int)seconds % 60); + } + return (result); +} + +/* + * format_k(amt) - format a kilobyte memory value, returning a string + * suitable for display. Returns a pointer to a static + * area that changes each call. "amt" is converted to a + * string with a trailing "K". If "amt" is 10000 or greater, + * then it is formatted as megabytes (rounded) with a + * trailing "M". + */ + +/* + * Compromise time. We need to return a string, but we don't want the + * caller to have to worry about freeing a dynamically allocated string. + * Unfortunately, we can't just return a pointer to a static area as one + * of the common uses of this function is in a large call to snprintf where + * it might get invoked several times. Our compromise is to maintain an + * array of strings and cycle thru them with each invocation. We make the + * array large enough to handle the above mentioned case. The constant + * NUM_STRINGS defines the number of strings in this array: we can tolerate + * up to NUM_STRINGS calls before we start overwriting old information. + * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer + * to convert the modulo operation into something quicker. What a hack! + */ + +#define NUM_STRINGS 8 + +char * +format_k(uint64_t amt) +{ + static char retarray[NUM_STRINGS][16]; + static int idx = 0; + char *ret, tag = 'K'; + + ret = retarray[idx]; + idx = (idx + 1) % NUM_STRINGS; + + if (amt >= 10000) { + amt /= 1024; + tag = 'M'; + if (amt >= 10000) { + amt /= 1024; + tag = 'G'; + } + } + snprintf(ret, sizeof(retarray[0]), "%llu%c", amt, tag); + return (ret); +} diff --git a/freebsd/version.c b/freebsd/version.c new file mode 100644 index 0000000..4e31afe --- /dev/null +++ b/freebsd/version.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int +version(int argc, char **argv) +{ + char cpubuf[1024]; + char kernver[1024]; + struct timeval tv, boottime; + struct utsname un; + size_t len; + time_t c; + uint64_t physmem; + int mib[5], pntd, weeks, days, hours, mins; + + mib[0] = CTL_HW; + mib[1] = HW_PHYSMEM; + len = sizeof(physmem); + if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) { + printf("%% HW_PHYSMEM: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + len = sizeof(cpubuf); + if (sysctl(mib, 2, &cpubuf, &len, NULL, 0) == -1) { + printf("%% HW_MODEL: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + len = sizeof(boottime); + if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1) { + printf("%% KERN_BOOTTIME: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + len = sizeof(kernver); + if (sysctl(mib, 2, &kernver, &len, NULL, 0) == -1) { + printf("%% KERN_VERSION: %s\n", strerror(errno)); + return(1); + } + if (uname(&un)) { + printf("%% uname: %s\n", strerror(errno)); + return(1); + } + gettimeofday(&tv, (struct timezone *)0); + c = difftime(tv.tv_sec, boottime.tv_sec); + + printf("%% NSH v%s\n", vers); + printf("Compiled %s by %s@%s\n", compiled, compiledby, compilehost); + printf("uptime: "); + pntd = 0; + weeks = c / (7 * 24 * 60 * 60); + c %= (7 * 24 * 60 * 60); + days = c / (24 * 60 * 60); + c %= (24 * 60 * 60); + hours = c / (60 * 60); + c %= (60 * 60); + mins = c / 60; + c %= 60; + if (weeks) { + printf("%d week%s", weeks, weeks == 1 ? "" : "s"); + pntd = 1; + } + if (days) { + printf("%s%d day%s", pntd ? ", " : "", days, + days == 1 ? "" : "s"); + pntd = 1; + } + if (hours) { + printf("%s%d hour%s", pntd ? ", " : "", hours, + hours == 1 ? "" : "s"); + pntd = 1; + } + if (mins) { + printf("%s%d minute%s", pntd ? ", " : "", mins, + mins == 1 ? "" : "s"); + pntd = 1; + } + if (!pntd) + printf("%d second%s", (int)c, c == 1 ? "" : "s"); + printf("\n"); + printf("system: %s/%s version %s\n", un.sysname, un.machine, + un.release); + printf("cpu: %s\n", cpubuf); + printf("memory: %sB\n", format_k(physmem / 1024)); + printf("kernel: %s", kernver); + return(0); +} + diff --git a/freebsd/who.c b/freebsd/who.c new file mode 100644 index 0000000..8d98c76 --- /dev/null +++ b/freebsd/who.c @@ -0,0 +1,282 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2002 Tim J. Robbins. + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void heading(void); +static void process_utmp(void); +static void quick(void); +static void row(const struct utmpx *); +static int ttywidth(void); +static void whoami(void); + +static int Hflag; /* Write column headings */ +static int aflag; /* Print all entries */ +static int bflag; /* Show date of the last reboot */ +static int mflag; /* Show info about current terminal */ +static int qflag; /* "Quick" mode */ +static int sflag; /* Show name, line, time */ +static int Tflag; /* Show terminal state */ +static int uflag; /* Show idle time */ + +int +who(int argc, char *argv[]) +{ + int ch; + + setlocale(LC_TIME, ""); + + // header and idle time flags + Hflag = 1; + uflag = 1; + + argc -= optind; + argv += optind; + + if (argc >= 2 && strcmp(argv[0], "am") == 0 && + (strcmp(argv[1], "i") == 0 || strcmp(argv[1], "I") == 0)) { + /* "who am i" or "who am I", equivalent to -m */ + mflag = 1; + argc -= 2; + argv += 2; + } + + if (*argv != NULL) { + if (setutxdb(UTXDB_ACTIVE, *argv) != 0) + err(1, "%s", *argv); + } + + if (qflag) + quick(); + else { + if (sflag) + Tflag = uflag = 0; + if (Hflag) + heading(); + if (mflag) + whoami(); + else + process_utmp(); + } + + endutxent(); + + return(0); +} + +static void +heading(void) +{ + + printf("%-16s ", "User"); + if (Tflag) + printf("S "); + printf("%-12s %-12s ", "Line", "When"); + if (uflag) + printf("Idle "); + printf("%-16s\n", "From"); +} + +static void +row(const struct utmpx *ut) +{ + char buf[80], tty[PATH_MAX]; + struct stat sb; + time_t idle, t; + static int d_first = -1; + struct tm *tm; + char state; + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + + state = '?'; + idle = 0; + if (Tflag || uflag) { + snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, ut->ut_line); + if (stat(tty, &sb) == 0) { + state = sb.st_mode & (S_IWOTH|S_IWGRP) ? + '+' : '-'; + idle = time(NULL) - sb.st_mtime; + } + } + + printf("%-16s ", ut->ut_user); + if (Tflag) + printf("%c ", state); + if (ut->ut_type == BOOT_TIME) + printf("%-12s ", "system boot"); + else + printf("%-12s ", ut->ut_line); + t = ut->ut_tv.tv_sec; + tm = localtime(&t); + strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm); + printf("%-*s ", 12, buf); + if (uflag) { + if (idle < 60) + printf(" . "); + else if (idle < 24 * 60 * 60) + printf("%02d:%02d ", (int)(idle / 60 / 60), + (int)(idle / 60 % 60)); + else + printf(" old "); + } + if (*ut->ut_host != '\0') + printf("(%s)", ut->ut_host); + putchar('\n'); +} + +static int +ttystat(char *line) +{ + struct stat sb; + char ttybuf[MAXPATHLEN]; + + (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line); + if (stat(ttybuf, &sb) == 0) { + return (0); + } else + return (-1); +} + +static void +process_utmp(void) +{ + struct utmpx *utx; + int num = 0; + + while ((utx = getutxent()) != NULL) { + if (((aflag || !bflag) && utx->ut_type == USER_PROCESS) || + (bflag && utx->ut_type == BOOT_TIME)) + if (ttystat(utx->ut_line) == 0) { + row(utx); + num++; + } + } + + printf("%% users = %d\n", num); +} + +static void +quick(void) +{ + struct utmpx *utx; + int col, ncols, num; + + ncols = ttywidth(); + col = num = 0; + while ((utx = getutxent()) != NULL) { + if (utx->ut_type != USER_PROCESS) + continue; + printf("%-16s", utx->ut_user); + if (++col < ncols / (16 + 1)) + putchar(' '); + else { + col = 0; + putchar('\n'); + } + num++; + } + if (col != 0) + putchar('\n'); + + printf("# users = %d\n", num); +} + +static void +whoami(void) +{ + struct utmpx ut, *utx; + struct passwd *pwd; + const char *name, *tty; + + if ((tty = ttyname(STDIN_FILENO)) == NULL) + tty = "tty??"; + else if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) + tty += sizeof _PATH_DEV - 1; + strlcpy(ut.ut_line, tty, sizeof ut.ut_line); + + /* Search utmp for our tty, dump first matching record. */ + if ((utx = getutxline(&ut)) != NULL && utx->ut_type == USER_PROCESS) { + row(utx); + return; + } + + /* Not found; fill the utmp structure with the information we have. */ + memset(&ut, 0, sizeof(ut)); + if ((pwd = getpwuid(getuid())) != NULL) + name = pwd->pw_name; + else + name = "?"; + strlcpy(ut.ut_user, name, sizeof ut.ut_user); + gettimeofday(&ut.ut_tv, NULL); + row(&ut); +} + +static int +ttywidth(void) +{ + struct winsize ws; + long width; + char *cols, *ep; + + if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') { + errno = 0; + width = strtol(cols, &ep, 10); + if (errno || width <= 0 || width > INT_MAX || ep == cols || + *ep != '\0') + warnx("invalid COLUMNS environment variable ignored"); + else + return (width); + } + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) + return (ws.ws_col); + + return (80); +} diff --git a/linux/commands.c b/linux/commands.c new file mode 100644 index 0000000..9825290 --- /dev/null +++ b/linux/commands.c @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2002-2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" +#include "sysctl.h" + +char prompt[128]; + +char line[1024]; +char saveline[1024]; +int margc; +char hname[HSIZE]; +static char hbuf[MAXHOSTNAMELEN]; /* host name */ +static char ifname[IFNAMSIZ]; /* interface name */ +struct intlist *whichlist; + +#define RT_TABLEID_MAX 255 +#define NARGS sizeof(line)/2 /* max arguments in char line[] */ +char *margv[NARGS]; /* argv storage */ +size_t cursor_argc; /* location of cursor in margv */ +size_t cursor_argo; /* offset of cursor margv[cursor_argc] */ + +pid_t child; + +static int quit(void); +static int disable(void); +static int doverbose(int, char**); +static int doediting(int, char**); +static int hostname(int, char **); +static int help(int, char**); +static int shell(int, char*[]); +static int ping(int, char*[]); +static int ping6(int, char*[]); +static int ssh(int, char*[]); +static int telnet(int, char*[]); +static int traceroute(int, char*[]); +static int traceroute6(int, char*[]); +static Command *getcmd(char *); +static void sigalarm(int); +static int show_hostname(int, char **); +static int pr_conf(int, char **); +static int pr_s_conf(int, char **); +static int show_help(int, char **); +static int wr_startup(void); +static int wr_conf(char *); +static int el_burrito(EditLine *, int, char **); + void p_argv(int, char **); +static int flush_history(void); +static int flush_line(char *); +static int flush_help(void); +static int notvalid(void); + +#include "commands.h" + +void sigalarm(int blahfart) +{ + if (child != -1) { + kill(child, SIGKILL); + } +} + +/* + * Quit command + */ + +int +quit(void) +{ + printf("%% Session terminated.\n"); + exit(0); + return 0; +} + +/* + * Data structures and routines for the "show" command. + */ + +Menu showlist[] = { + { "hostname", "Router hostname", CMPL0 0, 0, 0, 0, show_hostname }, + { "version", "Software information", CMPL0 0, 0, 0, 0, version }, + { "users", "System users", CMPL0 0, 0, 0, 0, who }, + { "running-config", "Operating configuration", CMPL0 0, 0, 0, 0, pr_conf }, + { "startup-config", "Startup configuration", CMPL0 0, 0, 0, 0, pr_s_conf }, + { "?", "Options", CMPL0 0, 0, 0, 0, show_help }, + { "help", 0, CMPL0 0, 0, 0, 0, show_help }, + { 0, 0, 0, 0, 0 } +}; + +/* + * Data structures and routines for the "flush" command. + */ + +Menu flushlist[] = { + { "line", "Active user", CMPL0 0, 0, 1, 1, flush_line }, + { "history", "Command history", CMPL0 0, 0, 0, 0, flush_history }, + { "?", "Options", CMPL0 0, 0, 0, 0, flush_help }, + { "help", 0, CMPL0 0, 0, 0, 0, flush_help }, + { 0, 0, 0, 0, 0 } +}; + +static int +flush_line(char *line) +{ + char *argv[] = { PKILL, "-9", "-t", line, NULL }; + cmdargs(PKILL, argv); + return (1); +} + +static int +flush_help(void) +{ + Menu *f; + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'flush' commands are:\n\n"); + + for (f = flushlist; f->name; f++) { + if (strlen(f->name) > z) + z = strlen(f->name); + } + + for (f = flushlist; f->name; f++) { + if (f->help) + printf(" %-*s %s\n", z, f->name, f->help); + } + return 0; +} + +static int +showcmd(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + int success = 0; + + if (argc < 2) { + show_help(argc, argv); + return 0; + } + + /* + * Validate show argument + */ + s = (Menu *) genget(argv[1], (char **) showlist, sizeof(Menu)); + if (s == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(s)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + if (((s->minarg + 2) > argc) || ((s->maxarg + 2) < argc)) { + printf("%% Wrong number of argument%s to 'show %s' command" + " (min %i, max %i)\n", argc <= 2 ? "" : "s", s->name, + s->minarg, s->maxarg); + return 0; + } + if (s->handler) /* As if there was something else we do ? */ + success = (*s->handler)(argc, argv); + + return(success); +} + +static int +show_help(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'show' commands are:\n\n"); + + for (s = showlist; s->name; s++) { + if (strlen(s->name) > z) + z = strlen(s->name); + } + + for (s = showlist; s->name; s++) { + if (s->help) + printf(" %-*s %s\n", z, s->name, s->help); + } + return 0; +} + +/* + * Data structures and routines for the main CLI + */ + +static char + hostnamehelp[] = "Set system hostname", + interfacehelp[] = "Modify interface parameters", + rtablehelp[] = "Routing table switch", + grouphelp[] = "Modify group attributes", + arphelp[] = "Static ARP set", +#ifdef notyet + parphelp[] = "Proxy ARP set", +#endif + pfhelp[] = "Packet filter control", + ospfhelp[] = "OSPF control", + ospf6help[] = "OSPF6 control", + eigrphelp[] = "EIGRP control", + bgphelp[] = "BGP control", + riphelp[] = "RIP control", + ldphelp[] = "LDP control", + relayhelp[] = "Relay control", + ipsechelp[] = "IPsec IKEv1 control", + ikehelp[] = "IPsec IKEv2 control", + rtadvhelp[] = "Router advertisement control", + dvmrphelp[] = "DVMRP control", + sasynchelp[] = "SA synchronization control", + dhcphelp[] = "DHCP server control", + snmphelp[] = "SNMP server control", + smtphelp[] = "SMTP server control", + ldaphelp[] = "LDAP server control", + sshdhelp[] = "SSH server control", + ntphelp[] = "NTP synchronization control", + nppphelp[] = "PPP server control", + ifstatehelp[] = "ifstate server control", + ftpproxyhelp[] ="ftp-proxy server control", + tftpproxyhelp[] ="tftp-proxy server control", + tftphelp[] = "TFTP server control", + dnshelp[] = "DNS rule control", + motdhelp[] = "Message of-the-day", + inethelp[] = "Inet super-server control", + bridgehelp[] = "Modify bridge parameters", + showhelp[] = "Show system information", + iphelp[] = "Set IP networking parameters", + ip6help[] = "Set IPv6 networking parameters", + mplshelp[] = "Set MPLS network parameters", + ddbhelp[] = "Set DDB parameters", + pipexhelp[] = "Set PIPEX parameters", + flushhelp[] = "Flush system tables", + enablehelp[] = "Enable privileged mode", + disablehelp[] = "Disable privileged mode", + pinghelp[] = "Send IPv4 ICMP echo request", + ping6help[] = "Send IPv6 ICMP echo request", + tracerthelp[] = "Print the route to IPv4 host", + tracert6help[] ="Print the route to IPv6 host", + sshhelp[] = "SSH connection to remote host", + telnethelp[] = "Telnet connection to remote host", + quithelp[] = "Close current connection", + verbosehelp[] = "Set verbose diagnostics", + editinghelp[] = "Set command line editing", + whohelp[] = "Display system users", + shellhelp[] = "Invoke a subshell", + savehelp[] = "Save the current configuration", + nreboothelp[] = "Reboot the system", + halthelp[] = "Halt the system", + helphelp[] = "Print help information"; + +/* + * Primary commands, will be included in help output + */ + +#define ssctl sizeof(struct ctl) +Command cmdtab[] = { + { "hostname", hostnamehelp, CMPL0 0, 0, hostname, 1, 0, 0 }, + { "show", showhelp, CMPL(ta) (char **)showlist, sizeof(Menu), showcmd, 0, 0, 0 }, + { "enable", enablehelp, CMPL0 0, 0, enable, 0, 0, 0 }, + { "disable", disablehelp, CMPL0 0, 0, disable, 1, 0, 0 }, + { "ping", pinghelp, CMPL0 0, 0, ping, 0, 0, 0 }, + { "ping6", ping6help, CMPL0 0, 0, ping6, 0, 0, 0 }, + { "traceroute", tracerthelp, CMPL0 0, 0, traceroute, 0, 0, 0 }, + { "traceroute6", tracert6help, CMPL0 0, 0, traceroute6, 0, 0, 0 }, + { "ssh", sshhelp, CMPL0 0, 0, ssh, 0, 0, 0 }, + { "telnet", telnethelp, CMPL0 0, 0, telnet, 0, 0, 0 }, + { "write-config", savehelp, CMPL0 0, 0, wr_startup, 1, 0, 0 }, + { "verbose", verbosehelp, CMPL0 0, 0, doverbose, 0, 1, 0 }, + { "editing", editinghelp, CMPL0 0, 0, doediting, 0, 1, 0 }, + { "who", whohelp, CMPL0 0, 0, who, 0, 0, 0 }, + { "!", shellhelp, CMPL0 0, 0, shell, 1, 0, 0 }, + { "?", helphelp, CMPL(C) 0, 0, help, 0, 0, 0 }, + { "quit", quithelp, CMPL0 0, 0, quit, 0, 0, 0 }, + { "help", 0, CMPL(C) 0, 0, help, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +/* + * These commands escape ambiguous check and help listings + */ + +static Command cmdtab2[] = { + { "config", 0, CMPL0 0, 0, notvalid, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +Command * +getcmd(char *name) +{ + Command *cm; + + if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + +void +makeargv() +{ + char *cp, *cp2, *base, c; + char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + /* save for shell command */ + strlcpy(saveline, line, sizeof(saveline)); + + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while ((c = *cp)) { + int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + cursor_argc = margc += 1; + base = cp; + for (cursor_argo = 0, cp2 = cp; c != '\0'; + cursor_argo = (cp + 1) - base, c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) { + cursor_argo = 0; + break; + } + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') { + cursor_argc--; + break; + } + cp++; + } + *argp++ = 0; + if (cursor_pos == line) { + cursor_argc = 0; + cursor_argo = 0; + } +} + +void +command() +{ + Command *c; + u_int num; + + if (editing) { + inithist(); + initedit(); + } + + for (;;) { + if (!editing) { + printf("%s", cprompt()); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + printf("\n"); + (void) quit(); + /* NOTREACHED */ + } + break; + } + } else { + const char *buf; + cursor_pos = NULL; + + if ((buf = el_gets(elc, &num)) == NULL || num == 0) + break; + + if (buf[--num] == '\n') { + if (num == 0) + break; + } + if (num >= sizeof(line)) { + printf("%% Input exceeds permitted length\n"); + break; + } + memcpy(line, buf, (size_t)num); + line[num] = '\0'; + history(histc, &ev, H_ENTER, buf); + } + + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + if (NO_ARG(margv[0])) + c = getcmd(margv[1]); + else + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("%% Ambiguous command\n"); + continue; + } + if (c == 0) { + int val = 1; + + if (editing) + val = el_burrito(elc, margc, margv); + if (val) + printf("%% Invalid command\n"); + continue; + } + if (NO_ARG(margv[0]) && ! c->nocmd) { + printf("%% Invalid command: %s %s\n", margv[0], + margv[1]); + continue; + } + if (c->needpriv != 0 && priv != 1) { + printf("%% Privilege required\n"); + continue; + } + if (c->modh) + strlcpy(hname, c->name, HSIZE); + if ((*c->handler) (margc, margv, 0)) { + break; + } + } +} + +/* + * Help command. + */ +static int +help(int argc, char **argv) +{ + Command *c; + + if (argc == 1) { + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% Commands are:\n\n"); + + for (c = cmdtab; c->name; c++) + if (((c->needpriv && priv) || !c->needpriv) + && strlen(c->name) > z) + z = strlen(c->name); + for (c = cmdtab; c->name; c++) { + if (c->help && ((c->needpriv && priv) || + !c->needpriv)) + printf(" %-*s %s\n", z, c->name, c->help); + } + return 0; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("%% Ambiguous help command %s\n", arg); + else if (c == (Command *)0) + printf("%% Invalid help command %s\n", arg); + else + printf("%% %s: %s\n", arg, c->help); + } + return 0; +} + +/* + * Hostname command. + */ +int +hostname(int argc, char **argv) +{ + argv++; + argc--; + + if (argc > 1) { + printf("%% Invalid arguments\n"); + return 1; + } + + if (argc == 1) { + if (sethostname(*argv, strlen(*argv))) + printf("%% sethostname: %s\n", strerror(errno)); + } else + show_hostname(0, NULL); + return 0; +} + +int show_hostname(int argc, char **argv) +{ + if (gethostname(hbuf, sizeof(hbuf))) + printf("%% gethostname: %s\n", strerror(errno)); + else + printf("%s\n", hbuf); + + return 0; +} + +/* + * Shell command. + */ +int +shell(int argc, char **argv) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + /* + * Fire up the shell in the child. + */ + char *shellp; + char *shellname = shellp = "/bin/sh"; + + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], + (char *)NULL); + else + execl(shellp, shellname, (char *)NULL); + printf("%% execl failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for shell to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * ping command. + */ +int +ping(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING, argv); + } + return 0; +} + +int +ping6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING6, argv); + } + return 0; +} + +/* + * telnet command. + */ +int +telnet(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TELNET, argv); + } + return 0; +} + +/* + * ssh command. + */ +int +ssh(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(SSH, argv); + } + return 0; +} + +/* + * traceroute command. + */ +int +traceroute(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT, argv); + } + return 0; +} + +int +traceroute6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT6, argv); + } + return 0; +} + +int +argvtostring(int argc, char **argv, char *string, int strlen) +{ + int i, j; + + for (i = 0, j = 0; argc && i < (strlen - 1); i++) { + if (argv[0][j] == '\0') { + argc--, argv++; + string[i] = ' '; + j = 0; + continue; + } + string[i] = argv[0][j]; + j++; + } + if (i > 0) + i--; + string[i] = '\0'; + + return i; +} + +/* + * cmd, multiple args + */ +int +cmdargs(char *cmd, char *arg[]) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + char *shellp = cmd; + + execv(shellp, arg); + printf("%% execv failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for cmd to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * disable privileged mode + */ +int +disable(void) +{ + priv = 0; + return 0; +} + +int +notvalid(void) +{ + printf("%% The command you entered is not necessary with this" + " software.\n"); + + return(0); +} + +/* + * verbose diagnostics + */ +int +doverbose(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + verbose = 0; + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + verbose = 1; + } + + printf("%% Diagnostic mode %s\n", verbose ? "enabled" : "disabled"); + + return 0; +} + +int +doediting(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + endedit(); + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + initedit(); + } + + printf("%% Command line editing %s\n", + editing ? "enabled" : "disabled"); + + return 0; +} + +int +flush_history(void) +{ + if (!editing) { + printf("%% Command line editing not enabled\n"); + return(1); + } + + /* + * Editing mode needs to be reinitialized if the histi/histc + * pointers are going to change..... + */ + endedit(); + endhist(); + inithist(); + initedit(); + + return(0); +} + +void +gen_help(char **x, char *cmdprefix, char *descrsuffix, int szstruct) +{ + /* only for structures starting with char *name; char *help; !! */ + char **y = x; + struct ghs *ghs; + int z = 0; + + printf("%% Arguments may be abbreviated\n\n"); + + while (*y != 0) { + if (strlen(*y) > z) + z = strlen(*y); + y = (char **)((char *)y + szstruct); + } + + while (*x != 0) { + ghs = (struct ghs *)x; + if (ghs->help) + printf(" %s %-*s %s %s\n", cmdprefix, z, *x, + ghs->help, descrsuffix); + x = (char **)((char *)x + szstruct); + } + return; +} + +/* + * read a text file and execute commands + * take into account that we may have mode handlers int cmdtab that + * execute indented commands from the rc file + */ +int +cmdrc(char rcname[FILENAME_MAX]) +{ + Command *c = NULL, *savec = NULL; + FILE *rcfile; + char modhvar[128]; /* required variable in mode handler cmd */ + unsigned int lnum; /* line number */ + u_int z = 0; /* max length of cmdtab argument */ + + if ((rcfile = fopen(rcname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", rcname, strerror(errno)); + return 1; + } + + for (c = cmdtab; c->name; c++) + if (strlen(c->name) > z) + z = strlen(c->name); + c = NULL; + + for (lnum = 1; ; lnum++) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (line[0] == '!') + continue; + /* + * Don't ignore indented comments with pound sign, otherwise + * comments won't be saved into daemon/ctl config files. + */ + if (line[0] == ' ' && line[1] == '!' && savec && savec->modh == 2) + continue; + if (line[0] == ' ') + strlcpy(saveline, line, sizeof(line)); + makeargv(); + if (margv[0] == 0) + continue; + if (line[0] == ' ' && (!savec || savec->modh < 1)) { + printf("%% No mode handler specified before" + " indented command? (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (line[0] != ' ' || (line[0] == ' ' && line[1] != ' ' + && savec && savec->modh == 2)) { + /* + * command was not indented, or indented for a mode 2 + * handler. process normally. + */ + if (NO_ARG(margv[0])) { + c = getcmd(margv[1]); + if (line[0] != ' ') + savec = c; + if (savec && (savec->nocmd == 0)) { + printf("%% Invalid rc command (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } else { + c = getcmd(margv[0]); + if (line[0] != ' ') + savec = c; + if(savec && savec->modh) { + /* + * any mode handler should have + * one value stored, passed on + */ + if (margv[1]) { + strlcpy(hname, c->name, + HSIZE); + strlcpy(modhvar, margv[1], + sizeof(modhvar)); + } else { + printf("%% No argument after" + " mode handler (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } + } + } + if (Ambiguous(c)) { + printf("%% Ambiguous rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (c == 0) { + printf("%% Invalid rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (verbose) { + printf("%% %4s: %*s%10s (line %u) margv ", + savec && savec->modh ? "mode" : "cmd", z, + savec && savec->name ? savec->name : "", + c != savec ? "(sub-cmd)" : "", lnum); + p_argv(margc, margv); + printf("\n"); + } + if (c->modh == 1) + (*c->handler) (margc, margv, modhvar); + else + (*c->handler) (margc, margv, 0); + } + fclose(rcfile); + return 0; +} + +void +p_argv(int argc, char **argv) +{ + int z; + + for (z = 0; z < argc; z++) + printf("%s%s", z ? " " : "[", argv[z]); + printf("]"); + return; +} + +/* + * for the purpose of interface handler routines, 1 here is failure and + * 0 is success + */ +int +el_burrito(EditLine *el, int argc, char **argv) +{ + char *colon; + int val; + + if (!editing) /* Nothing to parse, fail */ + return(1); + + /* + * el_parse will always return a non-error status if someone specifies + * argv[0] with a colon. The idea of the colon is to allow host- + * specific commands, which is really only useful in .editrc, so + * it is invalid here. + */ + colon = strchr(argv[0], ':'); + if (colon) + return(1); + + val = el_parse(el, argc, (const char **)argv); + + if (val == 0) + return(0); + else + return(1); +} + +char * +cprompt(void) +{ + int pr; + char tmp[4]; + + if (cli_rtable) + snprintf(tmp, sizeof(tmp), "%d", cli_rtable); + + gethostname(hbuf, sizeof(hbuf)); + pr = priv | cli_rtable; + snprintf(prompt, sizeof(prompt), "%s%s%s%s%s%s%s%s", hbuf, pr ? "(" : "", + priv ? "p" : "", priv && cli_rtable ? "-" : "", + cli_rtable ? "rtable " : "", cli_rtable ? tmp : "", + pr ?")" : "> ", pr ? "# " : ""); + + return(prompt); +} + +char * +iprompt(void) +{ + gethostname(hbuf, sizeof(hbuf)); + snprintf(prompt, sizeof(prompt), "%s(%s-%s)>", hbuf, + bridge ? "bridge" : "interface", ifname); + + return(prompt); +} + +int +wr_startup(void) +{ + char *argv[] = { SAVESCRIPT, NSHRC_TEMP, '\0' }; + + if (wr_conf(NSHRC_TEMP)) + printf("%% Saving configuration\n"); + else + printf("%% Unable to save configuration: %s\n", + strerror(errno)); + + cmdargs(SAVESCRIPT, argv); + + return(1); +} + +/* + * Save configuration + */ +int +wr_conf(char *fname) +{ + FILE *rchandle; + int error = 1; + + if ((rchandle = fopen(fname, "w")) == NULL) + error = 0; + else { + conf(rchandle); + fclose(rchandle); + } + + return (error); +} + +/* + * Show wrappers + */ +int +pr_conf(int argc, char **argv) +{ + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + if (!wr_conf(NSHRC_TEMP)) { + printf("%% Couldn't generate configuration\n"); + return(0); + } + + more(NSHRC_TEMP); + + return(1); +} + +/* + * Show startup config + */ +int +pr_s_conf(int argc, char **argv) +{ + int ret; + + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + ret = more(NSHRC); + + return(ret); +} + + +char ** +step_optreq(char **xargs, char **args, int argc, char **argv, int skip) +{ + int i; + int fill = 0; /* total fillable arguments */ + int flc = 0; /* number of filled arguments */ + + /* count fillable arguments */ + for (i = 0; i < NOPTFILL - 1; i++) { + if (xargs[i] == OPT || xargs[i] == REQ) + fill++; + if (xargs[i] == NULL) + break; + } + + if (argc - skip > fill) { + printf("%% Superfluous argument: %s\n", argv[skip + fill]); + return NULL; + } + + /* copy xargs to args, replace OPT/REQ args with argv past skip */ + for (i = 0; i < NOPTFILL - 2; i++) { + if (xargs[i] == NULL) { + args[i] = '\0'; + if (i > 1) + /* + * all **args passed must have at least two arguments + * and a terminating NULL. the point of this check + * is to allow the first two arguments to be NULL but + * still fill in fillargs[x] with corresponding NULL + */ + break; + } + if (xargs[i] == OPT || xargs[i] == REQ) { + /* copy from argv to args */ + if (argc - skip - flc > 0) { + args[i] = argv[skip + flc]; + flc++; + } else if (xargs[i] == REQ) { + printf("%% Missing required argument\n"); + return NULL; + } else { + args[i] = '\0'; + break; + } + } else { + /* copy from xargs to args */ + args[i] = xargs[i]; + } + } + + return(args); +} diff --git a/linux/commands.h b/linux/commands.h new file mode 100644 index 0000000..ae2476e --- /dev/null +++ b/linux/commands.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static struct fpf { + char *name; + char *help; + char *cmd; + char *arg; +} fpfs[] = { + { "all", "all PF elements", PFCTL, "-Fall" }, + { "nat", "NAT rules", PFCTL, "-Fnat" }, + { "queue", "queue rules", PFCTL, "-Fqueue" }, + { "filter", "filter rules", PFCTL, "-Frules" }, + { "states", "NAT/filter states", PFCTL, "-Fstate" }, + { "stats", "PF statistics", PFCTL, "-Finfo" }, + { "tables", "PF address tables", PFCTL, "-FTables" }, + { 0, 0, 0, 0 } +}; + +static struct stt { + char *name; + char *help; + void (*handler) (); +} stts[] = { + { 0, 0, 0 } +}; + +struct prot1 { + char *name; + char *help; + char *args[32]; +}; + +struct prot { + char *name; + struct prot1 *table; +}; + +struct prot1 bgcs[] = { + { "announced", "All announced networks", + { BGPCTL, "network", "show", OPT, NULL } }, + { "interfaces", "Interface states", + { BGPCTL, "show", "interfaces", NULL } }, + { "nexthop", "BGP nexthop routes", + { BGPCTL, "show", "nexthop", NULL } }, + { "summary", "Neighbor session states and counters", + { BGPCTL, "show", "summary", OPT, NULL } }, + { "rib", "Routing Information Base", + { BGPCTL, "show", "rib", OPT, OPT, OPT, NULL } }, + { "neighbor", "Detailed peer", + { BGPCTL, "show", "neighbor", REQ, OPT, NULL } }, + { "ip", "IP BGP", + { BGPCTL, "show", "ip", "bgp", OPT, OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 oscs[] = { + { "fib", "Forward Information Base", + { OSPFCTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPFCTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPFCTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPFCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPFCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPFCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 os6cs[] = { + { "fib", "Forward Information Base", + { OSPF6CTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPF6CTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPF6CTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPF6CTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPF6CTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPF6CTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 eics[] = { + { "interfaces", "Interface", + { EIGRPCTL, "show", "interfaces", OPT, OPT, NULL } }, + { "neighbor", "Neighbor", + { EIGRPCTL, "show", "neighbor", OPT, OPT, NULL } }, + { "topology", "Topology", + { EIGRPCTL, "show", "topology", OPT, OPT, NULL } }, + { "traffic", "Traffic", + { EIGRPCTL, "show", "traffic", OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rics[] = { + { "fib", "Forward Information Base", + { RIPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { RIPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbor", + { RIPCTL, "show", "neighbor", NULL } }, + { "rib", "Routing Information Base", + { RIPCTL, "show", "rib", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 lics[] = { + { "fib", "Forward Information Base", + { LDPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { LDPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbors", + { LDPCTL, "show", "neighbor", NULL } }, + { "lib", "Label Information Base", + { LDPCTL, "show", "lib", NULL } }, + { "discovery", "Adjacencies", + { LDPCTL, "show", "discovery", NULL } }, + { "l2vpn", "Pseudowire", + { LDPCTL, "show", "l2vpn", OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 iscs[] = { + { "flows", "Display IPsec flows", + { IPSECCTL, "-sf", NULL } }, + { "sadb", "Display SADB", + { IPSECCTL, "-ss", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 ikcs[] = { + { "monitor", "Monitor internal iked messages", + { IKECTL, "monitor", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dvcs[] = { + { "igmp", "Internet Group Message Protocol", + { DVMRPCTL, "show", "igmp", NULL } }, + { "interfaces", "Interfaces", + { DVMRPCTL, "show", "interfaces", OPT, NULL } }, + { "mfc", "Multicast Forwarding Cache", + { DVMRPCTL, "show", "mfc", OPT, NULL } }, + { "neighbor", "Neighbor", + { DVMRPCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { DVMRPCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { DVMRPCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rlcs[] = { + { "hosts", "hosts", + { RELAYCTL, "show", "hosts", NULL } }, + { "redirects", "redirects", + { RELAYCTL, "show", "redirects", NULL } }, + { "status", "status", + { RELAYCTL, "show", "relays", NULL } }, + { "sessions", "sessions", + { RELAYCTL, "show", "sessions", NULL } }, + { "summary", "summary", + { RELAYCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 smcs[] = { + { "queue", "envelopes in queue", + { SMTPCTL, "show", "queue", NULL } }, + { "runqueue", "envelopes scheduled for delivery", + { SMTPCTL, "show", "runqueue", NULL } }, + { "stats", "runtime statistics", + { SMTPCTL, "show", "stats", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dhcs[] = { + { "leases", "leases", { 0 } }, + { 0, 0, { 0 } } +}; + +struct prot1 ldcs[] = { + { "stats", "statistics counters", + { LDAPCTL, "stats", NULL } }, + { 0, 0, { 0 } } +}; + +/* show yyy zzz */ +struct prot prots[] = { + { "bgp", bgcs }, + { "ospf", oscs }, + { "ospf6", os6cs }, + { "rip", rics }, + { "ike", ikcs }, + { "ipsec", iscs }, + { "ldp", lics }, + { "dvmrp", dvcs }, + { "relay", rlcs }, + { "smtp", smcs }, + { "ldap", ldcs }, + { 0, 0 } +}; diff --git a/linux/compile.sh b/linux/compile.sh new file mode 100644 index 0000000..3af29ec --- /dev/null +++ b/linux/compile.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +cat >compile.c <<__END +char compiled[] = "`/bin/date +"%d-%b-%y %H:%M"`"; +char compiledby[] = "`/usr/bin/whoami`"; +char compilehost[] = "`uname -n`"; +__END diff --git a/linux/complete.c b/linux/complete.c new file mode 100644 index 0000000..9e3c6c8 --- /dev/null +++ b/linux/complete.c @@ -0,0 +1,498 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/complete.c,v 1.19 2006/06/23 20:35:25 steven Exp $ */ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "externs.h" +#include "stringlist.h" + +#define ttyout stdout +#define ttyin stdin + +unsigned char complete(EditLine *, int, char **, size_t, char *); + +static int comparstr(const void *, const void *); +static unsigned char complete_ambiguous(char *, int, StringList *, EditLine *); +static unsigned char complete_command(char *, int, EditLine *, char **, int); +static unsigned char complete_subcommand(char *, int, EditLine *, char **, int); +static unsigned char complete_local(char *, int, EditLine *); +static unsigned char complete_ifname(char *, int, EditLine *); +static unsigned char complete_args(struct ghs *, char *, int, EditLine *, + char **, int, int); +static void list_vertical(StringList *); + +unsigned char complt_c(EditLine *, int); +unsigned char complt_i(EditLine *, int); +unsigned char exit_i(EditLine *, int); + +static int +comparstr(const void *a, const void *b) +{ + return (strcmp(*(char **)a, *(char **)b)); +} + +/* + * Determine if complete is ambiguous. If unique, insert. + * If no choices, error. If unambiguous prefix, insert that. + * Otherwise, list choices. words is assumed to be filtered + * to only contain possible choices. + * Args: + * word word which started the match + * list list by default + * words stringlist containing possible matches + */ +static unsigned char +complete_ambiguous(char *word, int list, StringList *words, EditLine *el) +{ + char insertstr[MAXPATHLEN]; + char *lastmatch; + int i, j; + size_t matchlen, wordlen; + + wordlen = strlen(word); + if (words->sl_cur == 0) + return (CC_ERROR); /* no choices available */ + + if (words->sl_cur == 1) { /* only once choice available */ + (void)strlcpy(insertstr, words->sl_str[0], sizeof insertstr); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + + if (!list) { + matchlen = 0; + if ((lastmatch = words->sl_str[0])) + matchlen = strlen(lastmatch); + for (i = 1 ; i < words->sl_cur ; i++) { + for (j = wordlen ; j < strlen(words->sl_str[i]); j++) + if (lastmatch[j] != words->sl_str[i][j]) + break; + if (j < matchlen) + matchlen = j; + } + if (matchlen > wordlen) { + (void)strlcpy(insertstr, lastmatch, matchlen+1); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + /* + * XXX: really want CC_REFRESH_BEEP + */ + return (CC_REFRESH); + } + } + + putc('\n', ttyout); + qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); + list_vertical(words); + return (CC_REDISPLAY); +} + +/* + * Complete a command + */ +static unsigned char +complete_command(char *word, int list, EditLine *el, char **table, int stlen) +{ + char **c; + struct ghs *ghs; + StringList *words; + size_t wordlen; + unsigned char rv; + + if (table == NULL) + return(CC_ERROR); + + words = sl_init(); + wordlen = strlen(word); + + for (c = table; *c != NULL; c = (char **)((char *)c + stlen)) { + ghs = (struct ghs *)c; + if (wordlen > strlen(ghs->name)) + continue; + if (strncmp(word, ghs->name, wordlen) == 0) + sl_add(words, ghs->name); + } + + rv = complete_ambiguous(word, list, words, el); + sl_free(words, 0); + return (rv); +} + +/* + * Complete a (sub)command + */ +static unsigned char +complete_subcommand(char *word, int list, EditLine *el, char **table, int stlen) +{ + struct ghs *ghs = NULL; + + if (table == NULL) + return(CC_ERROR); + + ghs = (struct ghs *)genget(margv[cursor_argc-1], table, stlen); + if (ghs == 0 || Ambiguous(ghs)) + return(CC_ERROR); + + /* + * XXX completion lists that hit subcommand tables don't get more than + * the first CMPL arg tested in complete_args as long as the level + * 0 is passed to complete_args + */ + return(complete_args(ghs, word, list, el, table, stlen, 0)); +} + +/* + * Complete a local file + */ +static unsigned char +complete_local(char *word, int list, EditLine *el) +{ + StringList *words; + char dir[MAXPATHLEN]; + char *file; + DIR *dd; + struct dirent *dp; + unsigned char rv; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '.'; + dir[1] = '\0'; + file = word; + } else { + if (file == word) { + dir[0] = '/'; + dir[1] = '\0'; + } else { + (void)strlcpy(dir, word, (size_t)(file - word) + 1); + } + file++; + } + + if ((dd = opendir(dir)) == NULL) + return (CC_ERROR); + + words = sl_init(); + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(file) > strlen(dp->d_name)) + continue; + if (strncmp(file, dp->d_name, strlen(file)) == 0) { + char *tcp; + + tcp = strdup(dp->d_name); + if (tcp == NULL) + errx(1, "Can't allocate memory for local dir"); + sl_add(words, tcp); + } + } + closedir(dd); + + rv = complete_ambiguous(file, list, words, el); + sl_free(words, 1); + return (rv); +} + +unsigned char +exit_i(EditLine *el, int ch) +{ + printf("\n"); + return CC_EOF; +} + +unsigned char +complt_i(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)whichlist, sizeof(struct intlist), + NULL)); +} + +unsigned char +complt_c(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)cmdtab, sizeof(struct cmd), NULL)); +} + +unsigned char +complete_ifname(char *word, int list, EditLine *el) +{ + StringList *words; + size_t wordlen; + unsigned char rv; + + words = sl_init(); + wordlen = strlen(word); + + struct if_nameindex *ifn_list, *ifnp; + + if ((ifn_list = if_nameindex()) == NULL) + return 0; + + for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { + if (wordlen > strlen(ifnp->if_name)) + continue; + if (strncmp(word, ifnp->if_name, wordlen) == 0) + sl_add(words, ifnp->if_name); + } + + rv = complete_ambiguous(word, list, words, el); + if_freenameindex(ifn_list); + sl_free(words, 0); + return (rv); +} + +/* + * Generic complete routine + */ +unsigned char +complete(EditLine *el, int ch, char **table, size_t stlen, char *arg) +{ + static char word[256]; + static int lastc_argc, lastc_argo; + struct ghs *c; + const LineInfo *lf; + int celems, dolist; + size_t len; + + (void)ch; /* not used */ + lf = el_line(el); + len = lf->lastchar - lf->buffer; + if (len >= sizeof(line)) + return (CC_ERROR); + (void)memcpy(line, lf->buffer, len); + line[len] = '\0'; + cursor_pos = line + (lf->cursor - lf->buffer); + lastc_argc = cursor_argc; /* remember last cursor pos */ + lastc_argo = cursor_argo; + makeargv(); /* build argc/argv of current line */ + + if (margc == 0 || cursor_argo >= sizeof(word)) + return (CC_ERROR); + + dolist = 0; + + /* if cursor and word is same, list alternatives */ + if (lastc_argc == cursor_argc && lastc_argo == cursor_argo + && strncmp(word, margv[cursor_argc], cursor_argo) == 0) + dolist = 1; + else if (cursor_argo) + memcpy(word, margv[cursor_argc], cursor_argo); + word[cursor_argo] = '\0'; + + if (cursor_argc == 0) + return (complete_command(word, dolist, el, table, stlen)); + + if (arg == NULL) + arg = margv[0]; + c = (struct ghs *) genget(arg, table, stlen); + if (c == (struct ghs *)-1 || c == 0 || Ambiguous(c)) + return (CC_ERROR); + celems = strlen(c->complete); + + /* check for 'continuation' completes (which are uppercase) */ + if ((cursor_argc > celems) && (celems > 0) + && isupper((unsigned char)c->complete[celems-1])) + cursor_argc = celems; + + if (cursor_argc > celems) + return (CC_ERROR); + + return(complete_args(c, word, dolist, el, table, stlen, + cursor_argc - 1)); +} + +unsigned char +complete_args(struct ghs *c, char *word, int dolist, EditLine *el, char **table, + int stlen, int level) +{ +#ifdef CMPLDEBUG + printf("[%s]",&c->complete[level]); +#endif + switch (c->complete[level]) { + case 'l': /* local complete */ + case 'L': + return (complete_local(word, dolist, el)); + case 'c': /* command complete */ + case 'C': + return (complete_command(word, dolist, el, table, stlen)); + case 'i': + case 'I': + return (complete_ifname(word, dolist, el)); + case 't': /* points to a table */ + case 'T': + if (c->table == NULL) + return(CC_ERROR); + return (complete_command(word, dolist, el, c->table, c->stlen)); + case 'a': + case 'A': + if (c->table == NULL) + return(CC_ERROR); + return (complete_subcommand(word, dolist, el, c->table, c->stlen)); + case 'n': /* no complete */ + return (CC_ERROR); + } + + return (CC_ERROR); +} + +/* + * List words in stringlist, vertically arranged + */ +void +list_vertical(StringList *sl) +{ + int i, j, w; + int columns, width, lines; + char *p; + + width = 0; + + for (i = 0 ; i < sl->sl_cur ; i++) { + w = strlen(sl->sl_str[i]); + if (w > width) + width = w; + } + width = (width + 8) &~ 7; + + columns = 1; + if (columns == 0) + columns = 1; + lines = (sl->sl_cur + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + p = sl->sl_str[j * lines + i]; + if (p) + fputs(p, ttyout); + if (j * lines + i + lines >= sl->sl_cur) { + putc('\n', ttyout); + break; + } + if (p) + w = strlen(p); + else + w = 0; + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } + } + } +} + +/* + * this needs to be called before initedit() + */ +void +inithist() +{ + if (!histc) { + histc = history_init(); /* init the builtin history */ + history(histc, &ev, H_SETSIZE, 100); /* remember 100 events */ + } + if (!histi) { + histi = history_init(); + history(histi, &ev, H_SETSIZE, 100); + } +} + +void +endhist() +{ + if (histc) { + history_end(histc); /* deallocate */ + histc = NULL; + } + if (histi) { + history_end(histi); + histi = NULL; + } +} + +void +initedit() +{ + editing = 1; + + if (!elc) { + elc = el_init(__progname, stdin, stdout, stderr); + if (histc) + el_set(elc, EL_HIST, history, histc); /* use history */ + el_set(elc, EL_EDITOR, "emacs"); /* default type */ + el_set(elc, EL_PROMPT, cprompt); /* set the prompt + * function */ + el_set(elc, EL_ADDFN, "complt_c", "Command completion", + complt_c); + el_set(elc, EL_BIND, "\t", "complt_c", NULL); + el_source(elc, NULL); /* read ~/.editrc */ + el_set(elc, EL_SIGNAL, 1); + } + if (!eli) { + eli = el_init(__progname, stdin, stdout, stderr); + if (histi) + el_set(eli, EL_HIST, history, histi); + el_set(eli, EL_EDITOR, "emacs"); + el_set(eli, EL_PROMPT, iprompt); + el_set(eli, EL_ADDFN, "complt_i", "Command completion", + complt_i); + el_set(eli, EL_BIND, "\t", "complt_i", NULL); + el_set(eli, EL_ADDFN, "exit_i", "Exit", exit_i); + el_set(eli, EL_BIND, "^X", "exit_i", NULL); + el_set(eli, EL_BIND, "^D", "exit_i", NULL); + el_source(eli, NULL); + el_set(eli, EL_SIGNAL, 1); + } +} + +void +endedit() +{ + editing = 0; + + if (elc) { + el_end(elc); + elc = NULL; + } + if (eli) { + el_end(eli); + eli = NULL; + } +} diff --git a/linux/conf.c b/linux/conf.c new file mode 100644 index 0000000..2fee7fe --- /dev/null +++ b/linux/conf.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2002-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +#define _PASSWORD_LEN 60 + +void conf_db_single(FILE *, char *, char *, char *); +void conf_ctl(FILE *, char *, char *, int); +int scantext(char *, char *); + +#define TMPSIZ 1024 /* size of temp strings */ + +int +conf(FILE *output) +{ + char cpass[_PASSWORD_LEN+1]; + char hostbuf[MAXHOSTNAMELEN]; + + fprintf(output, "!\n"); + + gethostname (hostbuf, sizeof(hostbuf)); + fprintf(output, "hostname %s\n", hostbuf); + if (read_pass(cpass, sizeof(cpass))) { + fprintf(output, "enable secret blowfish %s\n", cpass); + } else { + if (errno != ENOENT) + printf("%% Unable to read run-time crypt repository:" + " %s\n", strerror(errno)); + } + fprintf(output, "!\n"); + conf_ctl(output, "", "motd", 0); + + fprintf(output, "!\n"); + + conf_ctl(output, "", "sshd", 0); + + fprintf(output, "!\n"); + + return(0); +} + +void conf_ctl(FILE *output, char *delim, char *name, int rtableid) +{ + FILE *conf; + struct daemons *x; + struct ctl *ctl; + char tmp_str[TMPSIZ], tmpfile[64]; + char *fenablenm = NULL, *fothernm = NULL, *flocalnm = NULL; + int defenable = 0, pntdrules = 0, pntdflag = 0, dbflag; + + x = (struct daemons *)genget(name, (char **)ctl_daemons, + sizeof(struct daemons)); + if (x == 0 || Ambiguous(x)) { + printf("%% conf_ctl: %s: genget internal failure\n", name); + return; + } + + /* print rules if they exist */ + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", x->tmpfile, rtableid); + if ((conf = fopen(tmpfile, "r")) != NULL) { + fprintf(output, "%s%s rules\n", delim, name); + for (;;) { + if(fgets(tmp_str, TMPSIZ, conf) == NULL) + break; + if(tmp_str[0] == 0) + break; + fprintf(output, "%s %s", delim, tmp_str); + } + fclose(conf); + fprintf(output, "%s!\n", delim); + pntdrules = 1; + } else if (errno != ENOENT || (errno == ENOENT && verbose)) + printf("%% conf_ctl: %s: %s\n", tmpfile, strerror(errno)); + + /* fill in argument names from table */ + for (ctl = x->table; ctl != NULL && ctl->name != NULL; ctl++) { + switch(ctl->flag_x) { + case DB_X_ENABLE_DEFAULT: + defenable = 1; + /* FALLTHROUGH */ + case DB_X_ENABLE: + fenablenm = ctl->name; + break; + case DB_X_LOCAL: + flocalnm = ctl->name; + break; + case DB_X_OTHER: + fothernm = ctl->name; + break; + case DB_X_DISABLE: + case DB_X_REMOVE: + case DB_X_DISABLE_ALWAYS: + case 0: + break; + default: + printf("%% conf_ctl: flag_x %d unknown\n", ctl->flag_x); + return; + } + } +} + + +/* find string in file */ +int scantext(char *fname, char *string) +{ + FILE *file; + char line[128]; + int found = 0; + + if ((file = fopen(fname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", fname, strerror(errno)); + return(0); + } + + for (;;) { + if (fgets(line, sizeof(line), file) == NULL) + break; + if (strcmp(line, string) == 0) { + found = 1; + break; + } + } + + fclose(file); + return(found); +} + +void +conf_db_single(FILE *output, char *dbname, char *lookup, char *ifname) +{ + StringList *dbreturn; + dbreturn = sl_init(); + + if (db_select_flag_x_ctl(dbreturn, dbname, ifname) < 0) { + printf("%% conf_db_single %s database select failed\n", dbname); + } + if (dbreturn->sl_cur > 0) { + if (lookup == NULL) + fprintf(output, " %s\n", dbname); + else if (strcmp(dbreturn->sl_str[0], lookup) != 0) + fprintf(output, " %s %s\n", dbname, dbreturn->sl_str[0]); + } + sl_free(dbreturn, 1); +} diff --git a/linux/ctl.c b/linux/ctl.c new file mode 100644 index 0000000..5da011a --- /dev/null +++ b/linux/ctl.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +/* service daemons */ +#define SSHD "/usr/sbin/sshd" + +/* table variable (for pkill usage) */ +static char table[16]; + +/* service routines */ +void call_editor(char *, char **, char *); +void ctl_symlink(char *, char *, char *); +int rule_writeline(char *, mode_t, char *); +int fill_tmpfile(char **, char *, char **); +int acq_lock(char *); +void rls_lock(int); + +/* master daemon list */ +struct daemons ctl_daemons[] = { +{ "sshd", "SSH", ctl_sshd, SSHDCONF_TEMP, 0600, 0, 255 }, +{ 0, 0, 0, 0, 0, 0 } +}; + +/* per-daemon commands, and their C or executable functions */ + +/* MOTD */ +struct ctl ctl_motd[] = { + { "edit", "edit message-of-the-day", + { "motd", NULL, NULL }, call_editor, 0, T_HANDLER }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +/* sshd */ +char *ctl_sshd_test[] = { SSHD, "-tf", REQTEMP, NULL }; +struct ctl ctl_sshd[] = { + { "enable", "enable service", + { SSHD, "-f", REQTEMP, NULL }, NULL, DB_X_ENABLE, T_EXEC }, + { "disable", "disable service", + { PKILL, table, "-f", SSHD, "-f", REQTEMP, NULL }, NULL, + DB_X_DISABLE, T_EXEC }, + { "edit", "edit configuration", + { "sshd", (char *)ctl_sshd_test, NULL }, call_editor, 0, + T_HANDLER_FILL1 }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +void +ctl_symlink(char *temp, char *real, char *z) +{ + rmtemp(temp); + symlink(real, temp); +} + +/* flag to other nsh sessions or nsh conf() that actions have been taken */ +void +flag_x(char *name, char *daemon, int dbflag, char *data) +{ + if (db_delete_flag_x_ctl(name, daemon) < 0) { + printf("%% database delete failure ctl ctl\n"); + return; + } + if (dbflag == DB_X_REMOVE) + return; + if (db_insert_flag_x(name, daemon, cli_rtable, dbflag, data) < 0) { + printf("%% database insert failure ctl ctl\n"); + } +} + +/* the main entry point into ctl.c from CLI */ +int +ctlhandler(int argc, char **argv, char *modhvar) +{ + struct daemons *daemons; + struct ctl *x; + char tmpfile[PATH_MAX]; + char *step_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char *tmp_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char **fillargs; + + /* loop daemon list to find table pointer */ + daemons = (struct daemons *) genget(hname, (char **)ctl_daemons, + sizeof(struct daemons)); + if (daemons == 0) { + printf("%% Internal error - Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(daemons)) { + printf("%% Internal error - Ambiguous argument %s\n", argv[1]); + return 0; + } + + if (cli_rtable > daemons->rtablemax) { + printf("%% Command %s not available via rtable %d\n", + daemons->name, cli_rtable); + return 0; + } + + snprintf(table, sizeof(table), "-T%d", cli_rtable); + if (daemons->tmpfile) + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + if (modhvar) { + /* action specified or indented command specified */ + if (argc == 2 && isprefix(argv[1], "rules")) { + /* skip 'X rules' line */ + return(0); + } + if (isprefix(modhvar, "rules")) { + if (!daemons->tmpfile) { + printf("%% writeline without tmpfile\n"); + return 0; + } + /* write indented line to tmp config file */ + rule_writeline(tmpfile, daemons->mode, saveline); + return 0; + } + } + if (argc < 2 || argv[1][0] == '?') { + gen_help((char **)daemons->table, "", "", sizeof(struct ctl)); + return 0; + } + + x = (struct ctl *) genget(argv[1], (char **)daemons->table, + sizeof(struct ctl)); + if (x == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(x)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + + fillargs = step_optreq(x->args, step_args, argc, argv, 2); + if (fillargs == NULL) + return 0; + + switch(x->type) { + /* fill_tmpfile will return 0 if tmpfile or args are NULL */ + case T_HANDLER: + /* pointer to handler routine, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) { + (*x->handler)(tmp_args[0], tmp_args[1], tmp_args[2]); + } else { + (*x->handler)(fillargs[0], fillargs[1], fillargs[2]); + } + break; + case T_HANDLER_FILL1: + /* pointer to handler routine, fill args @ args[1] pointer */ + if (fill_tmpfile((char **)fillargs[1], tmpfile, tmp_args)) + (*x->handler)(fillargs[0], tmp_args, fillargs[2]); + else + (*x->handler)(fillargs[0], (char **)fillargs[1], fillargs[2]); + break; + case T_EXEC: + /* command to execute via execv syscall, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) + cmdargs(tmp_args[0], tmp_args); + else + cmdargs(fillargs[0], fillargs); + break; + } + + if (x->flag_x != 0) { + flag_x("ctl", daemons->name, x->flag_x, NULL); + } + + return 1; +} + +int +fill_tmpfile(char **fillargs, char *tmpfile, char **tmp_args) +{ + int i; + + if (fillargs == NULL || tmpfile == NULL) + return 0; + + for (i = 0; i < NOPTFILL - 1; i++) { + if(fillargs[i] == NULL) { + break; + } + if(fillargs[i] == REQTEMP) { + tmp_args[i] = tmpfile; + } else { + tmp_args[i] = fillargs[i]; + } + } + return 1; +} + +void +call_editor(char *name, char **args, char *z) +{ + int fd, found = 0; + char *editor, tmpfile[64]; + struct daemons *daemons; + + for (daemons = ctl_daemons; daemons->name != 0; daemons++) + if (strncmp(daemons->name, name, strlen(name)) == 0) { + found = 1; + break; + } + + if (!found) { + printf("%% call_editor internal error\n"); + return; + } + + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + /* acq lock, call editor, test config with cmd and args, release lock */ + if ((editor = getenv("EDITOR")) == NULL) + editor = DEFAULT_EDITOR; + if ((fd = acq_lock(tmpfile)) > 0) { + char *argv[] = { editor, tmpfile, NULL }; + cmdargs(editor, argv); + chmod(tmpfile, daemons->mode); + if (args != NULL) + cmdargs(args[0], args); + rls_lock(fd); + } else + printf ("%% %s configuration is locked for editing\n", + daemons->propername); +} + +int +rule_writeline(char *fname, mode_t mode, char *writeline) +{ + FILE *rulefile; + + rulefile = fopen(fname, "a"); + if (rulefile == NULL) { + printf("%% Rule write failed: %s\n", strerror(errno)); + return(1); + } + if (writeline[0] == ' ') + writeline++; + fprintf(rulefile, "%s", writeline); + fclose(rulefile); + chmod(fname, mode); + return(0); +} + +int +acq_lock(char *fname) +{ + int fd; + char lockf[SIZE_CONF_TEMP + sizeof(".lock")]; + + /* + * some text editors lock (vi), some don't (mg) + * + * here we lock a separate, do-nothing file so we don't interfere + * with the editors that do... (lock multiple concurrent nsh users) + */ + snprintf(lockf, sizeof(lockf), "%s.lock", fname); + if ((fd = open(lockf, O_RDWR | O_CREAT, 0600)) == -1) + return(-1); + if (flock(fd, LOCK_EX | LOCK_NB) == 0) + return(fd); + else { + close(fd); + return(-1); + } +} + +void +rls_lock(int fd) +{ + /* best-effort, who cares */ + flock(fd, LOCK_UN); + close(fd); + return; +} + +void +rmtemp(char *file) +{ + if (unlink(file) != 0) + if (errno != ENOENT) + printf("%% Unable to remove temporary file %s: %s\n", + file, strerror(errno)); +} diff --git a/linux/editing.h b/linux/editing.h new file mode 100644 index 0000000..e9bc288 --- /dev/null +++ b/linux/editing.h @@ -0,0 +1,9 @@ +#include + +extern EditLine *elc; /* editline(3) status structure */ +extern EditLine *eli; /* another one */ +extern History *histc; /* command() editline(3) history structure */ +extern History *histi; /* interface() editline(3) status structure */ +extern char *cursor_pos; /* cursor position we're looking for */ +extern size_t cursor_argc; /* location of cursor in margv */ +extern size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ diff --git a/linux/externs.h b/linux/externs.h new file mode 100644 index 0000000..bc35fc8 --- /dev/null +++ b/linux/externs.h @@ -0,0 +1,561 @@ +/* + * nsh externs, prototypes and macros + */ + +#define NO_ARG(x) (strcasecmp(x, "no") == 0) /* absolute "no" */ + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) /* sys/param.h */ + +struct rtdump { + char *buf; /* start of routing table */ + char *lim; /* end of routing table */ +}; + +extern char *__progname; /* duh */ +extern char *vers; /* the version of nsh */ +extern char saveline[1024]; /* command line */ +extern char line[1024]; /* command line for makeargv() */ +extern int margc; /* makeargv() arg count */ +extern char *margv[]; /* makeargv() args */ +extern int verbose; /* is verbose mode on? */ +extern int editing; /* is command line editing mode on? */ +extern int bridge; /* are we in bridge mode (or interface mode?) */ +extern int priv; /* privileged mode or not? */ +//extern pid_t pid; /* process id of nsh */ +extern int cli_rtable; /* environment rtable */ + +#define HSIZE 64 +extern char hname[HSIZE]; /* prefix name to mode handler */ + +#ifdef _HISTEDIT_H_ +extern HistEvent ev; /* ev */ +#endif + +/* defaults */ +#define DEFAULT_MTU 1500 /* net.inet.ip.defmtu */ +#define DEFAULT_TTL 64 /* net.inet.ip.defttl */ +#define DEFAULT_MTTL 255 /* net.mpls.ttl */ +#define ESP_UDPENCAP_PORT 4500 /* net.inet.esp.udpencap_port */ + +/* nopt.c */ +#define no_arg 1 +#define req_arg 2 +struct nopts { + char *name; + int type; + int arg; +}; +extern int noptind; +extern char *nopterr; +int nopt(int, char **, struct nopts *); + +/* ppp.c */ +int intsppp(char *, int, int, char **); +int intpppoe(char *, int, int, char **); +void conf_pppoe(FILE *, int, char *); +void conf_sppp(FILE *, int, char *); + +/* conf.c */ +#define LEASEPREFIX "/var/db/dhclient.leases" +int conf(FILE *); +long default_mtu(char *); +int conf_routes(FILE *, char *, int, int, int); +int conf_dhcrelay(char *, char *, int); + +/* show.c */ +void p_rttables(int, int, int); +#ifdef _NETINET_IN_H_ +char *routename4(in_addr_t); +char *netname4(in_addr_t, struct sockaddr_in *); +#endif +#ifdef _NETINET6_IN6_H_ +char *routename6(struct sockaddr_in6 *); +char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); +void in6_fillscopeid(struct sockaddr_in6 *); +void in6_clearscopeid(struct sockaddr_in6 *); +#endif +#ifdef _SYS_SOCKET_H_ +char *routename(struct sockaddr *); +char *netname(struct sockaddr *, struct sockaddr *); +char *any_ntoa(const struct sockaddr *); +#endif + +/* alignment constraint for routing socket */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +/* routesys.c */ +#ifdef _NET_ROUTE_H_ +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; +#endif +#ifdef _WANT_SO_ +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + struct sockaddr_inarp sinarp; +}; +extern union sockunion so_dst, so_mask, so_gate, so_ifp; +#endif +#ifdef _NETINET6_IN6_H_ +int prefixlen(int, struct sockaddr_in6 *); +#endif +extern int rtm_addrs; +extern long rtm_inits; +#define FLUSH 0 +struct rtdump *getrtdump(int, int, int); +void freertdump(struct rtdump *); +int monitor(int, char **); +int rtmsg(int, int, int, int, int); +void flushroutes(int, int); +void bprintf(FILE *, int, char *); +#ifdef _NET_IF_DL_H_ +char *mylink_ntoa(const struct sockaddr_dl *); +#endif +extern char ifnetflags[]; +extern char routeflags[]; +extern char addrnames[]; +extern char metricnames[]; + +/* ctl.c */ +/* tmp config locations */ +#define PFCONF_TEMP "/var/run/pf.conf" +#define OSPFCONF_TEMP "/var/run/ospfd.conf" +#define OSPF6CONF_TEMP "/var/run/ospf6d.conf" +#define EIGRPCONF_TEMP "/var/run/eigrpd.conf" +#define BGPCONF_TEMP "/var/run/bgpd.conf" +#define RIPCONF_TEMP "/var/run/ripd.conf" +#define LDPCONF_TEMP "/var/run/ldpd.conf" +#define IPSECCONF_TEMP "/var/run/ipsec.conf" +#define IKECONF_TEMP "/var/run/iked.conf" +#define DVMRPCONF_TEMP "/var/run/dvmrpd.conf" +#define RTADVCONF_TEMP "/var/run/rtadvd.conf" +#define RELAYCONF_TEMP "/var/run/relayd.conf" +#define SASYNCCONF_TEMP "/var/run/sasyncd.conf" +#define DHCPCONF_TEMP "/var/run/dhcpd.conf" +#define SNMPCONF_TEMP "/var/run/snmpd.conf" +#define NTPCONF_TEMP "/var/run/ntpd.conf" +#define IFSTATE_TEMP "/var/run/ifstated.conf" +#define NPPPCONF_TEMP "/var/run/npppd.conf" +#define FTPPROXY_TEMP "/var/run/ftp-proxy" +#define TFTPPROXY_TEMP "/var/run/tftp-proxy" +#define TFTP_TEMP "/var/run/tftpd" +#define RESOLVCONF_TEMP "/var/run/resolv.conf" +#define RESOLVCONF_SYM "/var/run/resolv.conf.symlink" +#define RESOLVCONF_DHCP "/var/run/resolv.conf.dhcp" +#define INETCONF_TEMP "/var/run/inetd.conf" +#define SSHDCONF_TEMP "/var/run/sshd.conf" +#define SMTPCONF_TEMP "/var/run/smtpd.conf" +#define LDAPCONF_TEMP "/var/run/ldapd.conf" +#define IFSTATECONF_TEMP "/var/run/ifstated.conf" +#define MOTD_TEMP "/var/run/motd" + +/* argument list replacement */ +#define OPT (void *)1 +#define REQ (void *)2 +#define IFNAME (void *)3 +#define REQTEMP (void *)4 +#define SIZE_CONF_TEMP 64 +int ctlhandler(int, char **, char *); +void rmtemp(char *); +/* control programs */ +#define PFCTL "/sbin/pfctl" +#define OSPFCTL "/usr/sbin/ospfctl" +#define OSPF6CTL "/usr/sbin/ospf6ctl" +#define EIGRPCTL "/usr/sbin/eigrpctl" +#define BGPCTL "/usr/sbin/bgpctl" +#define RIPCTL "/usr/sbin/ripctl" +#define LDPCTL "/usr/sbin/ldpctl" +#define IPSECCTL "/sbin/ipsecctl" +#define IKECTL "/usr/sbin/ikectl" +#define DVMRPCTL "/usr/sbin/dvmrpctl" +#define RELAYCTL "/usr/sbin/relayctl" +#define SNMPCTL "/usr/sbin/snmpctl" +#define SMTPCTL "/usr/sbin/smtpctl" +#define LDAPCTL "/usr/sbin/ldapctl" +struct ctl { + char *name; + char *help; + char *args[32]; + void (*handler)(); + int flag_x; + int type; +}; +#define T_HANDLER 1 +#define T_HANDLER_FILL1 2 +#define T_EXEC 3 +struct daemons { + char *name; + char *propername; + struct ctl *table; + char *tmpfile; + mode_t mode; + int doreload; + int rtablemax; +}; +extern struct daemons ctl_daemons[]; +extern struct ctl ctl_pf[]; +extern struct ctl ctl_ospf[]; +extern struct ctl ctl_ospf6[]; +extern struct ctl ctl_eigrp[]; +extern struct ctl ctl_relay[]; +extern struct ctl ctl_bgp[]; +extern struct ctl ctl_rip[]; +extern struct ctl ctl_ldp[]; +extern struct ctl ctl_ipsec[]; +extern struct ctl ctl_nppp[]; +extern struct ctl ctl_ifstate[]; +extern struct ctl ctl_ike[]; +extern struct ctl ctl_dvmrp[]; +extern struct ctl ctl_rtadv[]; +extern struct ctl ctl_sasync[]; +extern struct ctl ctl_dhcp[]; +extern struct ctl ctl_snmp[]; +extern struct ctl ctl_smtp[]; +extern struct ctl ctl_sshd[]; +extern struct ctl ctl_ntp[]; +extern struct ctl ctl_ftpproxy[]; +extern struct ctl ctl_tftpproxy[]; +extern struct ctl ctl_tftp[]; +extern struct ctl ctl_dns[]; +extern struct ctl ctl_inet[]; +extern struct ctl ctl_ldap[]; +extern struct ctl ctl_motd[]; +void flag_x(char *, char *, int, char *); + +/* commands.c */ +#define NOPTFILL 7 +#define DEFAULT_EDITOR "/usr/bin/vi" +#define NSHRC_TEMP "/var/run/nshrc" +#define NSHRC "/etc/nshrc" +#define PING "/usr/bin/ping" +#define PING6 "/usr/bin/ping6" +#define TRACERT "/usr/bin/traceroute" +#define TRACERT6 "/usr/bin/traceroute6" +#define TELNET "/usr/bin/telnet" +#define SSH "/usr/bin/ssh" +#define PKILL "/usr/bin/pkill" +#define SAVESCRIPT "/usr/local/bin/save.sh" +#ifndef DHCPLEASES +#define DHCPLEASES "/var/db/dhcpd.leases" +#endif +void command(void); +char **step_optreq(char **, char **, int, char **, int); +int argvtostring(int, char **, char *, int); +int cmdrc(char rcname[FILENAME_MAX]); +int cmdargs(char *, char **); +char *iprompt(void); +char *cprompt(void); +char *pprompt(void); +int group (int, char **); +void gen_help(char **, char *, char *, int); +void makeargv(void); +extern size_t cursor_argc; +extern size_t cursor_argo; + +typedef struct cmd { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler) (); /* routine which executes command */ + int needpriv; /* Do we need privilege to execute? */ + int nocmd; /* Can we specify 'no ...command...'? */ + int modh; /* Is it a mode handler for cmdrc()? */ +} Command; + +typedef struct menu { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int minarg; /* Minimum number of arguments */ + int maxarg; /* Maximum number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ +} Menu; + +struct intlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler)(); /* Routine to perform (for special ops) */ + int bridge; /* 0 == Interface, 1 == Bridge, 2 == Both */ +}; + +/* generic help /complt struct */ +struct ghs { + char *name; + char *help; + char *complete; + char **table; + int stlen; +}; + +extern Command cmdtab[]; +extern struct intlist Intlist[]; +extern struct intlist Bridgelist[]; +extern struct intlist *whichlist; + +/* ieee80211.c */ +#define NWID 0 +#define NWKEY 1 +#define POWERSAVE 2 +#define TXPOWER 3 +#define BSSID 4 +#define DEFAULT_POWERSAVE 100 /* 100 ms */ +const char *get_string(const char *, const char *, __int8_t *, int *); +void make_string(char *str, int, const __int8_t *buf, int); +int get_nwinfo(char *, char *, int, int); +int get_nwpowersave(int, char *); +int intnwkey(char *, int, int, char **); +int inttxpower(char *, int, int, char **); +int intbssid(char *, int, int, char **); + +/* stats.c */ +void rt_stats(void); +void tcp_stats(void); +void udp_stats(void); +void ip_stats(void); +void icmp_stats(void); +void igmp_stats(void); +void ah_stats(void); +void esp_stats(void); +void ipip_stats(void); +void carp_stats(void); +void pfsync_stats(void); +void ipcomp_stats(void); + +/* mbuf.c */ +void mbpr(void); + +/* kread.c */ +char *plural(int); +char *plurales(int); + +/* genget.c */ +int isprefix(char *, char*); +char **genget(char *, char **, int); +int Ambiguous(void *); + +/* sysctl.c */ +int sysctl_int(int[], int, int); +int ipsysctl(int, char *, char *, int); +void conf_sysctls(FILE *); + +/* route.c */ +#define NO_NETMASK 0 +#define ASSUME_NETMASK 1 +int route(int, char**); +void show_route(char *, int); +int is_ip_addr(char *); +#ifdef _IP_T_ +void parse_ip_pfx(char *, int, ip_t *); +int ip_route(ip_t *, ip_t *, u_short, int, int, struct rt_metrics, int inits); +#endif +#ifdef _NETINET6_IN6_H_ +int parse_ipv6(char *, struct in6_addr *); +#endif + +/* if.c */ +#define DHCLIENT "/sbin/dhclient" +#define DHCRELAY "/usr/sbin/dhcrelay" +#define RTADVD "/usr/sbin/rtadvd" +#define IFDATA_MTU 1 /* request for if_data.ifi_mtu */ +#define IFDATA_BAUDRATE 2 /* request for if_data.ifi_baudrate */ +#define MBPS(bps) (bps / 1000 / 1000) +#define ROUNDMBPS(bps) ((float)bps == ((bps / 1000 / 1000) * 1000 * 1000)) +#define ROUNDKBPS(bps) ((float)bps == ((bps / 1000) * 1000)) +#define ROUNDKBYTES(bytes) ((float)bytes == ((bytes / 1024) * 1024)) +void imr_init(char *); +int is_valid_ifname(char *); +int show_int(int, char **); +int get_rdomain(int, char *); +int get_ifdata(char *, int); +int get_ifflags(char *, int); +int set_ifflags(char *, int, int); +int get_ifxflags(char *, int); +int set_ifxflags(char *, int, int); +int intip(char *, int, int, char **); +int intmtu(char *, int, int, char **); +int intkeepalive(char *, int, int, char **); +int intmpelabel(char *, int, int, char **); +int intrdomain(char *, int, int, char **); +int intdhcrelay(char *, int, int, char **); +int intmetric(char *, int, int, char **); +int intrtd(char *, int, int, char **); +int intvlan(char *, int, int, char **); +int intflags(char *, int, int, char **); +int intxflags(char *, int, int, char **); +int intaf(char *, int, int, char **); +int intlink(char *, int, int, char **); +int intnwid(char *, int, int, char **); +int intpowersave(char *, int, int, char **); +int intdesc(char *, int, int, char **); +int intpflow(char *, int, int, char **); +int intlladdr(char *, int, int, char **); +int intgroup(char *, int, int, char **); +int intrtlabel(char *, int, int, char **); +int intparent(char *, int, int, char **); +int intpatch(char *, int, int, char **); +int intmpw(char *, int, int, char **); +int addaf(char *, int, int); +int removeaf(char *, int, int); +char *get_hwdaddr(char *); + +/* main.c */ +void intr(void); + +/* version.c */ +int version(int, char **); + +/* compile.c */ +extern char compiled[], compiledby[], compiledon[], compilehost[]; + +/* bridge.c */ +long bridge_cfg(int, char *, int); +int bridge_confaddrs(int, char *, char *, FILE *); +int bridge_rules(int, char *, char *, char *, FILE *); +int bridge_list(int, char *, char *, char *, int, int); +int bridge_addrs(int, char *, char *, char *); +int set_ifflag(int, char *, short); +int clr_ifflag(int, char *, short); +int is_bridge(int, char *); +int brport(char *, int, int, char **); +int brval(char *, int, int, char **); +int brrule(char *, int, int, char **); +int brstatic(char *, int, int, char **); +int brpri(char *, int, int, char **); +int flush_bridgedyn(char *); +int flush_bridgeall(char *); +int flush_bridgerule(char *, char*); + +/* tunnel.c */ +int inttunnel(char *, int, int, char **); +int intvnetid(char *, int, int, char **); +int get_physrtable(int, char *); +int get_physttl(int, char *); +int get_vnetid(int, char *); + +/* media.c */ +#define DEFAULT_MEDIA_TYPE "autoselect" +void media_status(int, char *, char *); +void media_supported(int, char *, char *, char *); +int phys_status(int, char *, char *, char *, int, int); +int intmedia(char *, int, int, char **); +int intmediaopt(char *, int, int, char **); +int conf_media_status(FILE *, int, char *); + +/* passwd.c */ +#define NSHPASSWD_TEMP "/var/run/nshpasswd" +int read_pass(char *, size_t); +int gen_salt(char *, size_t); +int enable(int, char **); + +/* pfsync.c */ +#define PFSYNC_MAXUPDATES 128 +int intsyncdev(char *, int, int, char **); +int intsyncpeer(char *, int, int, char **); +int intmaxupd(char *, int, int, char **); +int conf_pfsync(FILE *, int, char *); + +/* carp.c */ +#define CARP_ADVSKEW 0 +#define CARP_ADVBASE 1 +#define CARP_VHID 2 +#define CARP_PEER 3 +#define CARP_BALANCING 4 +int intcarp(char *, int, int, char **); +int intcpass(char *, int, int, char **); +int intcnode(char *, int, int, char **); +int conf_carp(FILE *, int, char *); +int carp_state(int, char *); +int intcdev(char *, int, int, char **); + +/* trunk.c */ +int inttrunkport(char *, int, int, char **); +int inttrunkproto(char *, int, int, char **); +int conf_trunk(FILE *output, int ifs, char *ifname); +void show_trunk(int ifs, char *ifname); + +/* who.c */ +int who(int, char **); + +/* arp.c */ +int arpget(const char *); +int arpset(int, char **); +void arpdump(void); +void conf_arp(FILE *, char *); +//char *sec2str(time_t); + +/* more.c */ +int more(char *); +int nsh_cbreak(void); +void nsh_nocbreak(void); +void setwinsize(int); +#ifdef _SYS_TTYCOM_H_ +extern struct winsize winsize; +#endif + +/* complete.c */ +#define CMPL(x) __STRING(x), +#define CMPL0 "", +void inithist(void); +void endhist(void); +void initedit(void); +void endedit(void); + +/* utils.c */ +int string_index(char *, char **); +//char *format_time(time_t); +char *format_k(__uint64_t amt); + +/* sqlite3.c */ +/* sqlite3.c */ +#define SQ3DBFILE "/var/run/nsh.db" +#define DB_X_ENABLE 1 /* enable command */ +#define DB_X_DISABLE 2 /* disable command */ +#define DB_X_LOCAL 3 /* local control command */ +#define DB_X_OTHER 4 /* other command */ +#define DB_X_REMOVE 5 /* remove command */ +#define DB_X_ENABLE_DEFAULT 6 /* enable command, always prints enable until disabled */ +#define DB_X_DISABLE_ALWAYS 7 /* disable command, always prints if disabled */ +int db_create_table_rtables(void); +int db_create_table_flag_x(char *); +int db_create_table_nameservers(void); +int db_insert_flag_x(char *, char *, int, int, char *); +int db_insert_rtables(int, char *); +int db_insert_nameserver(char *); +int db_delete_rtables_rtable(int); +int db_delete_flag_x_ctl(char *, char *); +int db_delete_flag_x_ctl_data(char *, char *, char *); +int db_delete_nameservers(void); +#ifdef _STRINGLIST_H +int db_select_flag_x_ctl_data(StringList *, char *, char *, char *); +int db_select_flag_x_ctl(StringList *, char *, char *); +int db_select_rtable_rtables(StringList *); +int db_select_rtables_rtable(StringList *, int); +int db_select_rtables_ctl(StringList *, char *); +int db_select_name_rtable(StringList *, int); +int db_select_flag_x_ctl_rtable(StringList *, char *, int); +int db_select_flag_x_data_ctl_rtable(StringList *, char *, char *, int); +int db_select_nameservers(StringList *); +#endif +int db_select_flag_x_dbflag_rtable(char *, char *, int); + +/* pflow.c */ +#define PFLOW_SENDER 0 +#define PFLOW_RECEIVER 1 +#define PFLOW_VERSION 2 +#ifdef _SYS_SOCKET_H_ +int pflow_addr(const char *, struct sockaddr_storage *); +#endif +int pflow_status(int, int, char *, char *); diff --git a/linux/genget.c b/linux/genget.c new file mode 100644 index 0000000..549e785 --- /dev/null +++ b/linux/genget.c @@ -0,0 +1,99 @@ +/* From: $OpenBSD: genget.c,v 1.5 2001/05/25 10:23:06 hin Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include "externs.h" + +int isprefix(char *, char*); + +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ +int +isprefix(char *s1, char *s2) +{ + char *os1; + char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (tolower((unsigned char)c1) == tolower((unsigned char)c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + +char ** +genget(char *name, char **table, int stlen) + /* name to match */ + /* name entry in table */ + +{ + char **c, **found; + int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ +int +Ambiguous(void *s) +{ + return((char **)s == &ambiguous); +} diff --git a/linux/main.c b/linux/main.c new file mode 100644 index 0000000..283974d --- /dev/null +++ b/linux/main.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2002-2013 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +void usage(void); + +jmp_buf toplevel; + +char *vers = "1.0"; +int bridge = 0; /* bridge mode for interface() */ +int verbose = 0; /* verbose mode */ +int priv = 0, cli_rtable = 0; +int editing = 1; +pid_t pid; + +History *histi = NULL; +History *histc = NULL; +HistEvent ev; +EditLine *elc = NULL; +EditLine *eli = NULL; +char *cursor_pos = NULL; + +void intr(void); + +int +main(int argc, char *argv[]) +{ + int top, ch, iflag = 0, cflag = 0; + char rc[PATH_MAX]; + + if(getuid() != 0) + printf("%% Functionality limited without root privilege.\n"); + + pid = getpid(); + + while ((ch = getopt(argc, argv, "c:i:v")) != -1) + switch (ch) { + case 'c': + cflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'i': + iflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'v': + verbose = 1; + break; + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (cflag && iflag) + usage(); + if (argc > 0) + usage(); + if (iflag) + rmtemp(SQ3DBFILE); + + printf("%% NSH v%s\n", vers); + + if (iflag) { + /* + * Interpret config file and exit + */ + priv = 1; + + /* + * Set carp group carpdemote to 128 during initialization + */ + + cmdrc(rc); + + /* + * Initialization over + */ + + exit(0); + } + if (cflag) { + /* + * Interpret command file and exit + */ + priv = 1; + + cmdrc(rc); + + exit(0); + } + + top = setjmp(toplevel) == 0; + if (top) { + (void)signal(SIGWINCH, setwinsize); + (void)signal(SIGINT, (sig_t)intr); + (void)setwinsize(0); + } else + putchar('\n'); + + for (;;) { + command(); + top = 1; + } + + /* NOTREACHED */ + return 0; +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-v] [-i rcfile | -c rcfile]\n", __progname); + fprintf(stderr, " -v indicates verbose operation\n"); + fprintf(stderr, " -i rcfile loads initial system" \ + " configuration from rcfile\n"); + fprintf(stderr, " -c rcfile loads commands from rcfile\n"); + exit(1); +} + +void +intr(void) +{ + longjmp(toplevel, 1); +} diff --git a/linux/more.c b/linux/more.c new file mode 100644 index 0000000..69793d8 --- /dev/null +++ b/linux/more.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +#define PAGERPROMPT " --More-- " +#define BACKOVERPROMPT "\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b" + +int nsh_cbreak(void); +void nsh_nocbreak(void); + +static struct termios oldtty; + +struct winsize winsize; + +/* + * Display file + */ +int +more(char *fname) +{ + FILE *f; + char *input, c; + size_t s; + int i, nopager = 0; + + if ((f = fopen(fname, "r")) == NULL) { + if (errno == ENOENT) + printf ("%% File %s not found\n", fname); + else + printf ("%% more: fopen(%s): %s\n", fname, + strerror(errno)); + return(0); + } + + if (nsh_cbreak() < 0) + nopager = 1; + + for (i = 0; (input = getline(c, f, &s)) != NULL; i++) { + + if (!nopager && i == (winsize.ws_row - 1)) { + printf(PAGERPROMPT); + fflush(0); + c = getchar(); + printf(BACKOVERPROMPT); + if (c == 'q') + break; /* stop */ + if (c == '\r' || c == '\n') + i--; /* skip one line */ + else + i = 0; /* skip one page */ + } + + /* + * We replace newline (or whatever was at the end of + * the line) with NUL termination + */ + input[s-1] = '\0'; + printf("%s\n", input); + } + + if (!nopager) + nsh_nocbreak(); + + fclose(f); + return(1); +} + +int +nsh_cbreak(void) +{ + struct termios newtty; + + if (tcgetattr(fileno(stdout), &oldtty) < 0) + return(-1); + + (void)memcpy(&newtty, &oldtty, sizeof(newtty)); + + newtty.c_lflag &= ~(ECHO | ICANON); /* no echo, canonical */ + newtty.c_cc[VMIN] = 1; /* one char at a time */ + newtty.c_cc[VTIME] = 0; /* no timeout */ + + if (tcsetattr(fileno(stdout), TCSAFLUSH, &newtty) < 0) + return(-1); + return(0); +} + +void +nsh_nocbreak(void) +{ + tcsetattr(0, TCSAFLUSH, &oldtty); +} + +void +setwinsize(int signo) +{ + int save_errno = errno; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) { + winsize.ws_col = winsize.ws_col ? winsize.ws_col : 80; + winsize.ws_row = winsize.ws_row ? winsize.ws_row : 24; + } else { + winsize.ws_col = 80; + winsize.ws_row = 24; + } + + errno = save_errno; +} diff --git a/linux/passwd.c b/linux/passwd.c new file mode 100644 index 0000000..5978c29 --- /dev/null +++ b/linux/passwd.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2004 + * Christian Gut. 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 ``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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +#define _PASSWORD_LEN 60 + +int read_pass(char *, size_t); +int write_pass(char *); +int gen_salt(char *, size_t); + +/* read_pass reads the (blowfish crypted) password from a file */ +int +read_pass(char *pass, size_t size) +{ + FILE *pwdhandle; + + pwdhandle = fopen(NSHPASSWD_TEMP, "r"); + if (pwdhandle == NULL) + return (0); + fgets(pass, size, pwdhandle); + fclose(pwdhandle); + + return (1); +} + +/* write the crypted password to the passwd-temp file */ +int +write_pass(char *cpass) +{ + FILE *pwdhandle; + + umask(S_IWGRP | S_IRWXO); + /* maybe we should flock here? */ + pwdhandle = fopen(NSHPASSWD_TEMP, "w"); + if (pwdhandle == NULL) { + printf("%% Unable to write run-time crypt repository: %s\n", + strerror(errno)); + return (0); + } + fprintf(pwdhandle, "%s", cpass); + fclose(pwdhandle); + + return (1); +} + +int +gen_salt(char *salt, size_t saltlen) +{ + /* 6 is a rounds value like from localcipher option of login.conf */ + strlcpy(salt, "1234567", saltlen); + return 1; +} + +/* + * enable privileged mode + */ +int +enable(int argc, char **argv) +{ + char *p, *cpass; + char salt[_PASSWORD_LEN]; + char pass[_PASSWORD_LEN + 1]; + + switch (argc) { + + case 1: + if (priv == 1) + return 0; + + /* try to read pass */ + if (!(read_pass(pass, sizeof(pass)))) { + if (errno == ENOENT) { + /* no password file, so enable */ + priv = 1; + return 1; + } else { + /* cant read password file */ + printf("%% Unable to read password: %s\n", + strerror(errno)); + return 0; + } + } + p = getpass("Password:"); + if (p == NULL || *p == '\0') + return 0; + + if (strcmp(pass, pass) == 0) { + priv = 1; + return 1; + } else { + printf("%% Password incorrect\n"); + return 0; + } + + case 2: + if (argv[1][0] == '?') { + /* print help */ + printf("%% enable\t\t\t\tenable privileged mode\n"); + printf("%% enable ?\t\t\t\tShow Options\n"); + printf("%% enable secret \t\tSet password" + "(plaintext)\n"); + printf("%% enable secret \t\tSet" + " password(ciphertext)\n"); + return 1; + } else { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + case 3: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* crypt plaintext and save as pass */ + strlcpy(pass, argv[2], sizeof(pass)); + return(write_pass(pass)); + + case 4: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[2]); + return 0; + } + + if (!isprefix(argv[2], "blowfish")) { + printf("%% Invalid cipher: %s\n", argv[3]); + return 0; + } + + /* privileged? */ + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* set crypted pass */ + strlcpy(pass, argv[3], sizeof(pass)); + return (write_pass(pass)); + + default: + printf("%% Too many arguments\n"); + return 0; + } + +} diff --git a/linux/sqlite3.c b/linux/sqlite3.c new file mode 100644 index 0000000..e92f479 --- /dev/null +++ b/linux/sqlite3.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +int sq3simple(char *, StringList *); + +#define QSZ 1024 /* maximum query text size */ + +int +db_create_table_rtables(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS rtables (rtable INTEGER PRIMARY KEY, name TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_nameservers(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS nameservers (nameserver TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_flag_x(char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "CREATE TABLE IF NOT EXISTS %s (ctl TEXT, rtable INTEGER, flag INTEGER," + "data TEXT)", name); + return(sq3simple(query, NULL)); +} + +int +db_insert_flag_x(char *name, char *ctl, int rtableid, int flag, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO '%s' VALUES('%s', %d, %d, '%s')", + name, ctl, rtableid, flag, data); + return(sq3simple(query, NULL)); +} + +int +db_insert_rtables(int rtableid, char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO 'rtables' VALUES(%d, '%s')", rtableid, name); + return(sq3simple(query, NULL)); +} + +int +db_delete_rtables_rtable(int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'rtables' WHERE rtable=%d", rtableid); + return(sq3simple(query, NULL)); +} + +int +db_insert_nameserver(char *nameserver) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT OR REPLACE INTO 'nameservers' VALUES('%s')", + nameserver); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl(char *name, char *ctl) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND rtable=%d", name, ctl, cli_rtable); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl_data(char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, NULL)); +} + +int +db_delete_nameservers(void) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'nameservers'"); + return(sq3simple(query, NULL)); +} + +int +db_select_flag_x_ctl_data(StringList *words, char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_ctl(StringList *words, char *name, char *ctl) +{ + char query [QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s'", name, ctl); + return(sq3simple(query, words)); +} + +int +db_select_rtable_rtables(StringList *words) +{ + char query[]="SELECT rtable FROM rtables"; + return(sq3simple(query, words)); +} + +int +db_select_rtables_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable=%d", rtableid); + return(sq3simple(query,words)); +} + +int +db_select_flag_x_ctl_rtable(StringList *words, char *name, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT ctl FROM %s WHERE rtable=%d", name, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_data_ctl_rtable(StringList *words, char *name, char *ctl, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_nameservers(StringList *words) +{ + char query[]="SELECT nameserver FROM nameservers"; + return(sq3simple(query, words)); +} + +int +db_select_name_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable='%d'", rtableid); + return(sq3simple(query, words)); +} + +/* simple query execution, dump results straight into words */ +int +sq3simple(char *sql, StringList *words) +{ + sqlite3 *db; + sqlite3_stmt *stmt; + char *result, *new = NULL; + int rv, len, tlen = 0; + + if (sqlite3_open(SQ3DBFILE, &db)) { + printf("%% database file open failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) + != SQLITE_OK) { + printf("%% sqlite3_prepare_v2 failed: %s (%s)\n", + sqlite3_errmsg(db), sql); + return -1; + } + + while ((rv = sqlite3_step(stmt)) == SQLITE_ROW) { + result = (char *)sqlite3_column_text(stmt, 0); + len = strlen(result) + 1; + if ((new = malloc(len)) == NULL) { + printf("%% sq3simple: malloc failed\n"); + break; + } + tlen += len; + strlcpy(new, result, len); + sl_add(words, new); + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + if (rv != SQLITE_DONE) { + printf("%% sq3simple: error: %s\n", sqlite3_errmsg(db)); + return -1; + } + return tlen; +} diff --git a/linux/stringlist.h b/linux/stringlist.h new file mode 100644 index 0000000..442657b --- /dev/null +++ b/linux/stringlist.h @@ -0,0 +1,51 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/stringlist.h,v 1.2 2002/02/16 21:27:46 millert Exp $ */ + +/* + * Copyright (c) 1994 Christos Zoulas + * 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 ``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 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. + */ + +#ifndef _STRINGLIST_H +#define _STRINGLIST_H + +#include +#include + +/* + * Simple string list + */ +typedef struct _stringlist { + char **sl_str; + size_t sl_max; + size_t sl_cur; +} StringList; + +__BEGIN_DECLS +StringList *sl_init(void); +void sl_add(StringList *, char *); +void sl_free(StringList *, int); +char *sl_find(StringList *, char *); +__END_DECLS + +#endif /* _STRINGLIST_H */ diff --git a/linux/sysctl.h b/linux/sysctl.h new file mode 100644 index 0000000..430c54a --- /dev/null +++ b/linux/sysctl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct ipsysctl { + char *name; + int mib[6]; + int32_t def_larg; /* default value, or 0 for on/off + * sysctls */ + int enable; /* if on/off sysctl, 0 default is enabled, 1 + * default is disabled, 2 always show ena ble + * or disable */ +}; + +struct sysctltab { + char *name; + int pf; + Menu *table; + struct ipsysctl *sysctl; +}; + +extern struct sysctltab sysctls[]; +extern struct ipsysctl ipsysctls[]; +extern struct ipsysctl ip6sysctls[]; +extern struct ipsysctl mplssysctls[]; +extern struct ipsysctl ddbsysctls[]; +extern struct ipsysctl pipexsysctls[]; +extern Menu iptab[]; +extern Menu ip6tab[]; +extern Menu mplstab[]; +extern Menu ddbtab[]; +extern Menu pipextab[]; + +#define DEFAULT_MAXDYNROUTES 4096 /* net.inet6.ip6.maxdynroutes */ +#define DEFAULT_NEIGHBORGCTHRESH 2048 /* net.inet6.ip6.neighborgcthresh */ diff --git a/linux/version.c b/linux/version.c new file mode 100644 index 0000000..a8afe8f --- /dev/null +++ b/linux/version.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include "externs.h" + +int +version(int argc, char **argv) +{ + char cpubuf[1024]; + char kernver[1024]; + struct timeval tv, boottime; + struct utsname un; + size_t len; + time_t c; + uint64_t physmem; + int mib[5], pntd, weeks, days, hours, mins; + + // depends on sysctl.h which was deprecated + /* + mib[0] = CTL_HW; + mib[1] = HW_PHYSMEM64; + len = sizeof(physmem); + if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) { + printf("%% HW_PHYSMEM: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + len = sizeof(cpubuf); + if (sysctl(mib, 2, &cpubuf, &len, NULL, 0) == -1) { + printf("%% HW_MODEL: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + len = sizeof(boottime); + if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1) { + printf("%% KERN_BOOTTIME: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + len = sizeof(kernver); + if (sysctl(mib, 2, &kernver, &len, NULL, 0) == -1) { + printf("%% KERN_VERSION: %s\n", strerror(errno)); + return(1); + } */ + if (uname(&un)) { + printf("%% uname: %s\n", strerror(errno)); + return(1); + } + gettimeofday(&tv, (struct timezone *)0); + c = difftime(tv.tv_sec, boottime.tv_sec); + + printf("%% NSH v%s\n", vers); + printf("Compiled %s by %s@%s\n", compiled, compiledby, compilehost); + printf("uptime: "); + pntd = 0; + weeks = c / (7 * 24 * 60 * 60); + c %= (7 * 24 * 60 * 60); + days = c / (24 * 60 * 60); + c %= (24 * 60 * 60); + hours = c / (60 * 60); + c %= (60 * 60); + mins = c / 60; + c %= 60; + if (weeks) { + printf("%d week%s", weeks, weeks == 1 ? "" : "s"); + pntd = 1; + } + if (days) { + printf("%s%d day%s", pntd ? ", " : "", days, + days == 1 ? "" : "s"); + pntd = 1; + } + if (hours) { + printf("%s%d hour%s", pntd ? ", " : "", hours, + hours == 1 ? "" : "s"); + pntd = 1; + } + if (mins) { + printf("%s%d minute%s", pntd ? ", " : "", mins, + mins == 1 ? "" : "s"); + pntd = 1; + } + if (!pntd) + printf("%d second%s", (int)c, c == 1 ? "" : "s"); + printf("\n"); + printf("system: %s/%s version %s\n", un.sysname, un.machine, + un.release); + //printf("cpu: %s\n", cpubuf); + //printf("memory: %ldB\n", (physmem / 1024)); + //printf("kernel: %s", kernver); + return(0); +} + diff --git a/linux/who.c b/linux/who.c new file mode 100644 index 0000000..47d5ec5 --- /dev/null +++ b/linux/who.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +void output(struct utmp *); +void output_labels(void); + +int +who(int argc, char **argv) +{ + FILE *utmp; + struct utmp who; + int count = 0; + + if ((utmp = fopen(_PATH_UTMP, "r")) == NULL) { + printf("%% who: fopen %s: %s\n",_PATH_UTMP,strerror(errno)); + return(0); + } + +#define HOST_WIDTH 40 +#define NAME_WIDTH 8 + + output_labels(); + + while (fread((char *)&who, sizeof(who), 1, utmp) == 1) { + if (*who.ut_name && *who.ut_line) { + output(&who); + count++; + } + } + (void) printf ("%% users=%d\n", count); + + return(0); +} + +void +output_labels(void) +{ + (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, "User"); + + (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, "Line"); + (void)printf("When "); + + (void)printf("Idle %.*s", HOST_WIDTH, "From"); + + (void)putchar('\n'); +} + +void +output(struct utmp *up) +{ + char line[sizeof(_PATH_DEV) + sizeof (up->ut_line)]; + static time_t now = 0; + time_t idle = 0; + + if (now == 0) + time(&now); + + memset(line, 0, sizeof line); + strlcpy(line, _PATH_DEV, sizeof line); + strlcat(line, up->ut_line, sizeof line); + + (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, up->ut_name); + + (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line); + (void)printf("%.12s ", ctime(&up->ut_time) + 4); + + if (idle < 60) + (void)printf("00:00 "); + else if (idle < (24 * 60 * 60)) + (void)printf("%02d:%02d ", + ((int)idle / (60 * 60)), + ((int)idle % (60 * 60)) / 60); + else + (void)printf(" old "); + + if (*up->ut_host) + printf(" %.*s", HOST_WIDTH, up->ut_host); + (void)putchar('\n'); +} diff --git a/netbsd/commands.c b/netbsd/commands.c new file mode 100644 index 0000000..d3454f1 --- /dev/null +++ b/netbsd/commands.c @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2002-2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" +#include "sysctl.h" + +char prompt[128]; + +char line[1024]; +char saveline[1024]; +int margc; +char hname[HSIZE]; +static char hbuf[MAXHOSTNAMELEN]; /* host name */ +static char ifname[IFNAMSIZ]; /* interface name */ +struct intlist *whichlist; + +#define RT_TABLEID_MAX 255 +#define NARGS sizeof(line)/2 /* max arguments in char line[] */ +char *margv[NARGS]; /* argv storage */ +size_t cursor_argc; /* location of cursor in margv */ +size_t cursor_argo; /* offset of cursor margv[cursor_argc] */ + +pid_t child; + +static int quit(void); +static int disable(void); +static int doverbose(int, char**); +static int doediting(int, char**); +static int hostname(int, char **); +static int help(int, char**); +static int shell(int, char*[]); +static int ping(int, char*[]); +static int ping6(int, char*[]); +static int ssh(int, char*[]); +static int telnet(int, char*[]); +static int traceroute(int, char*[]); +static int traceroute6(int, char*[]); +static Command *getcmd(char *); +static void sigalarm(int); +static int show_hostname(int, char **); +static int pr_conf(int, char **); +static int pr_s_conf(int, char **); +static int show_help(int, char **); +static int wr_startup(void); +static int wr_conf(char *); +static int el_burrito(EditLine *, int, char **); + void p_argv(int, char **); +static int flush_history(void); +static int flush_line(char *); +static int flush_help(void); +static int notvalid(void); + +#include "commands.h" + +void sigalarm(int blahfart) +{ + if (child != -1) { + kill(child, SIGKILL); + } +} + +/* + * Quit command + */ + +int +quit(void) +{ + printf("%% Session terminated.\n"); + exit(0); + return 0; +} + +/* + * Data structures and routines for the "show" command. + */ + +Menu showlist[] = { + { "hostname", "Router hostname", CMPL0 0, 0, 0, 0, show_hostname }, + { "version", "Software information", CMPL0 0, 0, 0, 0, version }, + { "users", "System users", CMPL0 0, 0, 0, 0, who }, + { "running-config", "Operating configuration", CMPL0 0, 0, 0, 0, pr_conf }, + { "startup-config", "Startup configuration", CMPL0 0, 0, 0, 0, pr_s_conf }, + { "?", "Options", CMPL0 0, 0, 0, 0, show_help }, + { "help", 0, CMPL0 0, 0, 0, 0, show_help }, + { 0, 0, 0, 0, 0 } +}; + +/* + * Data structures and routines for the "flush" command. + */ + +Menu flushlist[] = { + { "line", "Active user", CMPL0 0, 0, 1, 1, flush_line }, + { "history", "Command history", CMPL0 0, 0, 0, 0, flush_history }, + { "?", "Options", CMPL0 0, 0, 0, 0, flush_help }, + { "help", 0, CMPL0 0, 0, 0, 0, flush_help }, + { 0, 0, 0, 0, 0 } +}; + +static int +flush_line(char *line) +{ + char *argv[] = { PKILL, "-9", "-t", line, NULL }; + cmdargs(PKILL, argv); + return (1); +} + +static int +flush_help(void) +{ + Menu *f; + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'flush' commands are:\n\n"); + + for (f = flushlist; f->name; f++) { + if (strlen(f->name) > z) + z = strlen(f->name); + } + + for (f = flushlist; f->name; f++) { + if (f->help) + printf(" %-*s %s\n", z, f->name, f->help); + } + return 0; +} + +static int +showcmd(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + int success = 0; + + if (argc < 2) { + show_help(argc, argv); + return 0; + } + + /* + * Validate show argument + */ + s = (Menu *) genget(argv[1], (char **) showlist, sizeof(Menu)); + if (s == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(s)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + if (((s->minarg + 2) > argc) || ((s->maxarg + 2) < argc)) { + printf("%% Wrong number of argument%s to 'show %s' command" + " (min %i, max %i)\n", argc <= 2 ? "" : "s", s->name, + s->minarg, s->maxarg); + return 0; + } + if (s->handler) /* As if there was something else we do ? */ + success = (*s->handler)(argc, argv); + + return(success); +} + +static int +show_help(int argc, char **argv) +{ + Menu *s; /* pointer to current command */ + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% 'show' commands are:\n\n"); + + for (s = showlist; s->name; s++) { + if (strlen(s->name) > z) + z = strlen(s->name); + } + + for (s = showlist; s->name; s++) { + if (s->help) + printf(" %-*s %s\n", z, s->name, s->help); + } + return 0; +} + +/* + * Data structures and routines for the main CLI + */ + +static char + hostnamehelp[] = "Set system hostname", + interfacehelp[] = "Modify interface parameters", + rtablehelp[] = "Routing table switch", + grouphelp[] = "Modify group attributes", + arphelp[] = "Static ARP set", +#ifdef notyet + parphelp[] = "Proxy ARP set", +#endif + pfhelp[] = "Packet filter control", + ospfhelp[] = "OSPF control", + ospf6help[] = "OSPF6 control", + eigrphelp[] = "EIGRP control", + bgphelp[] = "BGP control", + riphelp[] = "RIP control", + ldphelp[] = "LDP control", + relayhelp[] = "Relay control", + ipsechelp[] = "IPsec IKEv1 control", + ikehelp[] = "IPsec IKEv2 control", + rtadvhelp[] = "Router advertisement control", + dvmrphelp[] = "DVMRP control", + sasynchelp[] = "SA synchronization control", + dhcphelp[] = "DHCP server control", + snmphelp[] = "SNMP server control", + smtphelp[] = "SMTP server control", + ldaphelp[] = "LDAP server control", + sshdhelp[] = "SSH server control", + ntphelp[] = "NTP synchronization control", + nppphelp[] = "PPP server control", + ifstatehelp[] = "ifstate server control", + ftpproxyhelp[] ="ftp-proxy server control", + tftpproxyhelp[] ="tftp-proxy server control", + tftphelp[] = "TFTP server control", + dnshelp[] = "DNS rule control", + motdhelp[] = "Message of-the-day", + inethelp[] = "Inet super-server control", + bridgehelp[] = "Modify bridge parameters", + showhelp[] = "Show system information", + iphelp[] = "Set IP networking parameters", + ip6help[] = "Set IPv6 networking parameters", + mplshelp[] = "Set MPLS network parameters", + ddbhelp[] = "Set DDB parameters", + pipexhelp[] = "Set PIPEX parameters", + flushhelp[] = "Flush system tables", + enablehelp[] = "Enable privileged mode", + disablehelp[] = "Disable privileged mode", + pinghelp[] = "Send IPv4 ICMP echo request", + ping6help[] = "Send IPv6 ICMP echo request", + tracerthelp[] = "Print the route to IPv4 host", + tracert6help[] ="Print the route to IPv6 host", + sshhelp[] = "SSH connection to remote host", + telnethelp[] = "Telnet connection to remote host", + quithelp[] = "Close current connection", + verbosehelp[] = "Set verbose diagnostics", + editinghelp[] = "Set command line editing", + whohelp[] = "Display system users", + shellhelp[] = "Invoke a subshell", + savehelp[] = "Save the current configuration", + nreboothelp[] = "Reboot the system", + halthelp[] = "Halt the system", + helphelp[] = "Print help information"; + +/* + * Primary commands, will be included in help output + */ + +#define ssctl sizeof(struct ctl) +Command cmdtab[] = { + { "hostname", hostnamehelp, CMPL0 0, 0, hostname, 1, 0, 0 }, + { "show", showhelp, CMPL(ta) (char **)showlist, sizeof(Menu), showcmd, 0, 0, 0 }, + { "enable", enablehelp, CMPL0 0, 0, enable, 0, 0, 0 }, + { "disable", disablehelp, CMPL0 0, 0, disable, 1, 0, 0 }, + { "ping", pinghelp, CMPL0 0, 0, ping, 0, 0, 0 }, + { "ping6", ping6help, CMPL0 0, 0, ping6, 0, 0, 0 }, + { "traceroute", tracerthelp, CMPL0 0, 0, traceroute, 0, 0, 0 }, + { "traceroute6", tracert6help, CMPL0 0, 0, traceroute6, 0, 0, 0 }, + { "ssh", sshhelp, CMPL0 0, 0, ssh, 0, 0, 0 }, + { "telnet", telnethelp, CMPL0 0, 0, telnet, 0, 0, 0 }, + { "write-config", savehelp, CMPL0 0, 0, wr_startup, 1, 0, 0 }, + { "verbose", verbosehelp, CMPL0 0, 0, doverbose, 0, 1, 0 }, + { "editing", editinghelp, CMPL0 0, 0, doediting, 0, 1, 0 }, + { "who", whohelp, CMPL0 0, 0, who, 0, 0, 0 }, + { "!", shellhelp, CMPL0 0, 0, shell, 1, 0, 0 }, + { "?", helphelp, CMPL(C) 0, 0, help, 0, 0, 0 }, + { "quit", quithelp, CMPL0 0, 0, quit, 0, 0, 0 }, + { "help", 0, CMPL(C) 0, 0, help, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +/* + * These commands escape ambiguous check and help listings + */ + +static Command cmdtab2[] = { + { "config", 0, CMPL0 0, 0, notvalid, 0, 0, 0 }, + { 0, 0, CMPL0 0, 0, 0, 0, 0, 0 } +}; + +Command * +getcmd(char *name) +{ + Command *cm; + + if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + +void +makeargv() +{ + char *cp, *cp2, *base, c; + char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + /* save for shell command */ + strlcpy(saveline, line, sizeof(saveline)); + + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while ((c = *cp)) { + int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + cursor_argc = margc += 1; + base = cp; + for (cursor_argo = 0, cp2 = cp; c != '\0'; + cursor_argo = (cp + 1) - base, c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) { + cursor_argo = 0; + break; + } + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') { + cursor_argc--; + break; + } + cp++; + } + *argp++ = 0; + if (cursor_pos == line) { + cursor_argc = 0; + cursor_argo = 0; + } +} + +void +command() +{ + Command *c; + u_int num; + + if (editing) { + inithist(); + initedit(); + } + + for (;;) { + if (!editing) { + printf("%s", cprompt()); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + printf("\n"); + (void) quit(); + /* NOTREACHED */ + } + break; + } + } else { + const char *buf; + cursor_pos = NULL; + + if ((buf = el_gets(elc, &num)) == NULL || num == 0) + break; + + if (buf[--num] == '\n') { + if (num == 0) + break; + } + if (num >= sizeof(line)) { + printf("%% Input exceeds permitted length\n"); + break; + } + memcpy(line, buf, (size_t)num); + line[num] = '\0'; + history(histc, &ev, H_ENTER, buf); + } + + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + if (NO_ARG(margv[0])) + c = getcmd(margv[1]); + else + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("%% Ambiguous command\n"); + continue; + } + if (c == 0) { + int val = 1; + + if (editing) + val = el_burrito(elc, margc, margv); + if (val) + printf("%% Invalid command\n"); + continue; + } + if (NO_ARG(margv[0]) && ! c->nocmd) { + printf("%% Invalid command: %s %s\n", margv[0], + margv[1]); + continue; + } + if (c->needpriv != 0 && priv != 1) { + printf("%% Privilege required\n"); + continue; + } + if (c->modh) + strlcpy(hname, c->name, HSIZE); + if ((*c->handler) (margc, margv, 0)) { + break; + } + } +} + +/* + * Help command. + */ +static int +help(int argc, char **argv) +{ + Command *c; + + if (argc == 1) { + u_int z = 0; + + printf("%% Commands may be abbreviated.\n"); + printf("%% Commands are:\n\n"); + + for (c = cmdtab; c->name; c++) + if (((c->needpriv && priv) || !c->needpriv) + && strlen(c->name) > z) + z = strlen(c->name); + for (c = cmdtab; c->name; c++) { + if (c->help && ((c->needpriv && priv) || + !c->needpriv)) + printf(" %-*s %s\n", z, c->name, c->help); + } + return 0; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("%% Ambiguous help command %s\n", arg); + else if (c == (Command *)0) + printf("%% Invalid help command %s\n", arg); + else + printf("%% %s: %s\n", arg, c->help); + } + return 0; +} + +/* + * Hostname command. + */ +int +hostname(int argc, char **argv) +{ + argv++; + argc--; + + if (argc > 1) { + printf("%% Invalid arguments\n"); + return 1; + } + + if (argc == 1) { + if (sethostname(*argv, strlen(*argv))) + printf("%% sethostname: %s\n", strerror(errno)); + } else + show_hostname(0, NULL); + return 0; +} + +int show_hostname(int argc, char **argv) +{ + if (gethostname(hbuf, sizeof(hbuf))) + printf("%% gethostname: %s\n", strerror(errno)); + else + printf("%s\n", hbuf); + + return 0; +} + +/* + * Shell command. + */ +int +shell(int argc, char **argv) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + /* + * Fire up the shell in the child. + */ + char *shellp; + char *shellname = shellp = "/bin/sh"; + + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], + (char *)NULL); + else + execl(shellp, shellname, (char *)NULL); + printf("%% execl failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for shell to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * ping command. + */ +int +ping(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING, argv); + } + return 0; +} + +int +ping6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(PING6, argv); + } + return 0; +} + +/* + * telnet command. + */ +int +telnet(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TELNET, argv); + } + return 0; +} + +/* + * ssh command. + */ +int +ssh(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(SSH, argv); + } + return 0; +} + +/* + * traceroute command. + */ +int +traceroute(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT, argv); + } + return 0; +} + +int +traceroute6(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%% Invalid arguments\n"); + return 1; + } else { + cmdargs(TRACERT6, argv); + } + return 0; +} + +int +argvtostring(int argc, char **argv, char *string, int strlen) +{ + int i, j; + + for (i = 0, j = 0; argc && i < (strlen - 1); i++) { + if (argv[0][j] == '\0') { + argc--, argv++; + string[i] = ' '; + j = 0; + continue; + } + string[i] = argv[0][j]; + j++; + } + if (i > 0) + i--; + string[i] = '\0'; + + return i; +} + +/* + * cmd, multiple args + */ +int +cmdargs(char *cmd, char *arg[]) +{ + sig_t sigint, sigquit, sigchld; + + sigint = signal(SIGINT, SIG_IGN); + sigquit = signal(SIGQUIT, SIG_IGN); + sigchld = signal(SIGCHLD, SIG_DFL); + + switch(child = fork()) { + case -1: + printf("%% fork failed: %s\n", strerror(errno)); + break; + + case 0: + { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + char *shellp = cmd; + + execv(shellp, arg); + printf("%% execv failed: %s\n", strerror(errno)); + _exit(0); + } + break; + default: + signal(SIGALRM, sigalarm); + wait(0); /* Wait for cmd to complete */ + break; + } + + signal(SIGINT, sigint); + signal(SIGQUIT, sigquit); + signal(SIGCHLD, sigchld); + signal(SIGALRM, SIG_DFL); + child = -1; + + return 1; +} + +/* + * disable privileged mode + */ +int +disable(void) +{ + priv = 0; + return 0; +} + +int +notvalid(void) +{ + printf("%% The command you entered is not necessary with this" + " software.\n"); + + return(0); +} + +/* + * verbose diagnostics + */ +int +doverbose(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + verbose = 0; + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + verbose = 1; + } + + printf("%% Diagnostic mode %s\n", verbose ? "enabled" : "disabled"); + + return 0; +} + +int +doediting(int argc, char **argv) +{ + if (argc > 1) { + if (NO_ARG(argv[0])) { + endedit(); + } else { + printf ("%% Invalid argument\n"); + return 1; + } + } else { + initedit(); + } + + printf("%% Command line editing %s\n", + editing ? "enabled" : "disabled"); + + return 0; +} + +int +flush_history(void) +{ + if (!editing) { + printf("%% Command line editing not enabled\n"); + return(1); + } + + /* + * Editing mode needs to be reinitialized if the histi/histc + * pointers are going to change..... + */ + endedit(); + endhist(); + inithist(); + initedit(); + + return(0); +} + +void +gen_help(char **x, char *cmdprefix, char *descrsuffix, int szstruct) +{ + /* only for structures starting with char *name; char *help; !! */ + char **y = x; + struct ghs *ghs; + int z = 0; + + printf("%% Arguments may be abbreviated\n\n"); + + while (*y != 0) { + if (strlen(*y) > z) + z = strlen(*y); + y = (char **)((char *)y + szstruct); + } + + while (*x != 0) { + ghs = (struct ghs *)x; + if (ghs->help) + printf(" %s %-*s %s %s\n", cmdprefix, z, *x, + ghs->help, descrsuffix); + x = (char **)((char *)x + szstruct); + } + return; +} + +/* + * read a text file and execute commands + * take into account that we may have mode handlers int cmdtab that + * execute indented commands from the rc file + */ +int +cmdrc(char rcname[FILENAME_MAX]) +{ + Command *c = NULL, *savec = NULL; + FILE *rcfile; + char modhvar[128]; /* required variable in mode handler cmd */ + unsigned int lnum; /* line number */ + u_int z = 0; /* max length of cmdtab argument */ + + if ((rcfile = fopen(rcname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", rcname, strerror(errno)); + return 1; + } + + for (c = cmdtab; c->name; c++) + if (strlen(c->name) > z) + z = strlen(c->name); + c = NULL; + + for (lnum = 1; ; lnum++) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (line[0] == '!') + continue; + /* + * Don't ignore indented comments with pound sign, otherwise + * comments won't be saved into daemon/ctl config files. + */ + if (line[0] == ' ' && line[1] == '!' && savec && savec->modh == 2) + continue; + if (line[0] == ' ') + strlcpy(saveline, line, sizeof(line)); + makeargv(); + if (margv[0] == 0) + continue; + if (line[0] == ' ' && (!savec || savec->modh < 1)) { + printf("%% No mode handler specified before" + " indented command? (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (line[0] != ' ' || (line[0] == ' ' && line[1] != ' ' + && savec && savec->modh == 2)) { + /* + * command was not indented, or indented for a mode 2 + * handler. process normally. + */ + if (NO_ARG(margv[0])) { + c = getcmd(margv[1]); + if (line[0] != ' ') + savec = c; + if (savec && (savec->nocmd == 0)) { + printf("%% Invalid rc command (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } else { + c = getcmd(margv[0]); + if (line[0] != ' ') + savec = c; + if(savec && savec->modh) { + /* + * any mode handler should have + * one value stored, passed on + */ + if (margv[1]) { + strlcpy(hname, c->name, + HSIZE); + strlcpy(modhvar, margv[1], + sizeof(modhvar)); + } else { + printf("%% No argument after" + " mode handler (line %u) ", + lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + } + } + } + if (Ambiguous(c)) { + printf("%% Ambiguous rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (c == 0) { + printf("%% Invalid rc command (line %u) ", lnum); + p_argv(margc, margv); + printf("\n"); + continue; + } + if (verbose) { + printf("%% %4s: %*s%10s (line %u) margv ", + savec && savec->modh ? "mode" : "cmd", z, + savec && savec->name ? savec->name : "", + c != savec ? "(sub-cmd)" : "", lnum); + p_argv(margc, margv); + printf("\n"); + } + if (c->modh == 1) + (*c->handler) (margc, margv, modhvar); + else + (*c->handler) (margc, margv, 0); + } + fclose(rcfile); + return 0; +} + +void +p_argv(int argc, char **argv) +{ + int z; + + for (z = 0; z < argc; z++) + printf("%s%s", z ? " " : "[", argv[z]); + printf("]"); + return; +} + +/* + * for the purpose of interface handler routines, 1 here is failure and + * 0 is success + */ +int +el_burrito(EditLine *el, int argc, char **argv) +{ + char *colon; + int val; + + if (!editing) /* Nothing to parse, fail */ + return(1); + + /* + * el_parse will always return a non-error status if someone specifies + * argv[0] with a colon. The idea of the colon is to allow host- + * specific commands, which is really only useful in .editrc, so + * it is invalid here. + */ + colon = strchr(argv[0], ':'); + if (colon) + return(1); + + val = el_parse(el, argc, (const char **)argv); + + if (val == 0) + return(0); + else + return(1); +} + +char * +cprompt(void) +{ + int pr; + char tmp[4]; + + if (cli_rtable) + snprintf(tmp, sizeof(tmp), "%d", cli_rtable); + + gethostname(hbuf, sizeof(hbuf)); + pr = priv | cli_rtable; + snprintf(prompt, sizeof(prompt), "%s%s%s%s%s%s%s%s", hbuf, pr ? "(" : "", + priv ? "p" : "", priv && cli_rtable ? "-" : "", + cli_rtable ? "rtable " : "", cli_rtable ? tmp : "", + pr ?")" : "> ", pr ? "# " : ""); + + return(prompt); +} + +char * +iprompt(void) +{ + gethostname(hbuf, sizeof(hbuf)); + snprintf(prompt, sizeof(prompt), "%s(%s-%s)>", hbuf, + bridge ? "bridge" : "interface", ifname); + + return(prompt); +} + +int +wr_startup(void) +{ + char *argv[] = { SAVESCRIPT, NSHRC_TEMP, '\0' }; + + if (wr_conf(NSHRC_TEMP)) + printf("%% Saving configuration\n"); + else + printf("%% Unable to save configuration: %s\n", + strerror(errno)); + + cmdargs(SAVESCRIPT, argv); + + return(1); +} + +/* + * Save configuration + */ +int +wr_conf(char *fname) +{ + FILE *rchandle; + int error = 1; + + if ((rchandle = fopen(fname, "w")) == NULL) + error = 0; + else { + conf(rchandle); + fclose(rchandle); + } + + return (error); +} + +/* + * Show wrappers + */ +int +pr_conf(int argc, char **argv) +{ + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + if (!wr_conf(NSHRC_TEMP)) { + printf("%% Couldn't generate configuration\n"); + return(0); + } + + more(NSHRC_TEMP); + + return(1); +} + +/* + * Show startup config + */ +int +pr_s_conf(int argc, char **argv) +{ + int ret; + + if (priv != 1) { + printf ("%% Privilege required\n"); + return(0); + } + + ret = more(NSHRC); + + return(ret); +} + + +char ** +step_optreq(char **xargs, char **args, int argc, char **argv, int skip) +{ + int i; + int fill = 0; /* total fillable arguments */ + int flc = 0; /* number of filled arguments */ + + /* count fillable arguments */ + for (i = 0; i < NOPTFILL - 1; i++) { + if (xargs[i] == OPT || xargs[i] == REQ) + fill++; + if (xargs[i] == NULL) + break; + } + + if (argc - skip > fill) { + printf("%% Superfluous argument: %s\n", argv[skip + fill]); + return NULL; + } + + /* copy xargs to args, replace OPT/REQ args with argv past skip */ + for (i = 0; i < NOPTFILL - 2; i++) { + if (xargs[i] == NULL) { + args[i] = '\0'; + if (i > 1) + /* + * all **args passed must have at least two arguments + * and a terminating NULL. the point of this check + * is to allow the first two arguments to be NULL but + * still fill in fillargs[x] with corresponding NULL + */ + break; + } + if (xargs[i] == OPT || xargs[i] == REQ) { + /* copy from argv to args */ + if (argc - skip - flc > 0) { + args[i] = argv[skip + flc]; + flc++; + } else if (xargs[i] == REQ) { + printf("%% Missing required argument\n"); + return NULL; + } else { + args[i] = '\0'; + break; + } + } else { + /* copy from xargs to args */ + args[i] = xargs[i]; + } + } + + return(args); +} diff --git a/netbsd/commands.h b/netbsd/commands.h new file mode 100644 index 0000000..ae2476e --- /dev/null +++ b/netbsd/commands.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static struct fpf { + char *name; + char *help; + char *cmd; + char *arg; +} fpfs[] = { + { "all", "all PF elements", PFCTL, "-Fall" }, + { "nat", "NAT rules", PFCTL, "-Fnat" }, + { "queue", "queue rules", PFCTL, "-Fqueue" }, + { "filter", "filter rules", PFCTL, "-Frules" }, + { "states", "NAT/filter states", PFCTL, "-Fstate" }, + { "stats", "PF statistics", PFCTL, "-Finfo" }, + { "tables", "PF address tables", PFCTL, "-FTables" }, + { 0, 0, 0, 0 } +}; + +static struct stt { + char *name; + char *help; + void (*handler) (); +} stts[] = { + { 0, 0, 0 } +}; + +struct prot1 { + char *name; + char *help; + char *args[32]; +}; + +struct prot { + char *name; + struct prot1 *table; +}; + +struct prot1 bgcs[] = { + { "announced", "All announced networks", + { BGPCTL, "network", "show", OPT, NULL } }, + { "interfaces", "Interface states", + { BGPCTL, "show", "interfaces", NULL } }, + { "nexthop", "BGP nexthop routes", + { BGPCTL, "show", "nexthop", NULL } }, + { "summary", "Neighbor session states and counters", + { BGPCTL, "show", "summary", OPT, NULL } }, + { "rib", "Routing Information Base", + { BGPCTL, "show", "rib", OPT, OPT, OPT, NULL } }, + { "neighbor", "Detailed peer", + { BGPCTL, "show", "neighbor", REQ, OPT, NULL } }, + { "ip", "IP BGP", + { BGPCTL, "show", "ip", "bgp", OPT, OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 oscs[] = { + { "fib", "Forward Information Base", + { OSPFCTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPFCTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPFCTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPFCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPFCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPFCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 os6cs[] = { + { "fib", "Forward Information Base", + { OSPF6CTL, "show", "fib", OPT, OPT, NULL } }, + { "database", "Link State Database", + { OSPF6CTL, "show", "database", OPT, OPT, NULL } }, + { "interfaces", "Interface", + { OSPF6CTL, "show", "interfaces", OPT, NULL } }, + { "neighbor", "Neighbor", + { OSPF6CTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { OSPF6CTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { OSPF6CTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 eics[] = { + { "interfaces", "Interface", + { EIGRPCTL, "show", "interfaces", OPT, OPT, NULL } }, + { "neighbor", "Neighbor", + { EIGRPCTL, "show", "neighbor", OPT, OPT, NULL } }, + { "topology", "Topology", + { EIGRPCTL, "show", "topology", OPT, OPT, NULL } }, + { "traffic", "Traffic", + { EIGRPCTL, "show", "traffic", OPT, OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rics[] = { + { "fib", "Forward Information Base", + { RIPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { RIPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbor", + { RIPCTL, "show", "neighbor", NULL } }, + { "rib", "Routing Information Base", + { RIPCTL, "show", "rib", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 lics[] = { + { "fib", "Forward Information Base", + { LDPCTL, "show", "fib", OPT, NULL } }, + { "interfaces", "Interfaces", + { LDPCTL, "show", "interfaces", NULL } }, + { "neighbor", "Neighbors", + { LDPCTL, "show", "neighbor", NULL } }, + { "lib", "Label Information Base", + { LDPCTL, "show", "lib", NULL } }, + { "discovery", "Adjacencies", + { LDPCTL, "show", "discovery", NULL } }, + { "l2vpn", "Pseudowire", + { LDPCTL, "show", "l2vpn", OPT, NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 iscs[] = { + { "flows", "Display IPsec flows", + { IPSECCTL, "-sf", NULL } }, + { "sadb", "Display SADB", + { IPSECCTL, "-ss", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 ikcs[] = { + { "monitor", "Monitor internal iked messages", + { IKECTL, "monitor", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dvcs[] = { + { "igmp", "Internet Group Message Protocol", + { DVMRPCTL, "show", "igmp", NULL } }, + { "interfaces", "Interfaces", + { DVMRPCTL, "show", "interfaces", OPT, NULL } }, + { "mfc", "Multicast Forwarding Cache", + { DVMRPCTL, "show", "mfc", OPT, NULL } }, + { "neighbor", "Neighbor", + { DVMRPCTL, "show", "neighbor", OPT, NULL } }, + { "rib", "Routing Information Base", + { DVMRPCTL, "show", "rib", OPT, NULL } }, + { "summary", "Summary", + { DVMRPCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 rlcs[] = { + { "hosts", "hosts", + { RELAYCTL, "show", "hosts", NULL } }, + { "redirects", "redirects", + { RELAYCTL, "show", "redirects", NULL } }, + { "status", "status", + { RELAYCTL, "show", "relays", NULL } }, + { "sessions", "sessions", + { RELAYCTL, "show", "sessions", NULL } }, + { "summary", "summary", + { RELAYCTL, "show", "summary", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 smcs[] = { + { "queue", "envelopes in queue", + { SMTPCTL, "show", "queue", NULL } }, + { "runqueue", "envelopes scheduled for delivery", + { SMTPCTL, "show", "runqueue", NULL } }, + { "stats", "runtime statistics", + { SMTPCTL, "show", "stats", NULL } }, + { 0, 0, { 0 } } +}; + +struct prot1 dhcs[] = { + { "leases", "leases", { 0 } }, + { 0, 0, { 0 } } +}; + +struct prot1 ldcs[] = { + { "stats", "statistics counters", + { LDAPCTL, "stats", NULL } }, + { 0, 0, { 0 } } +}; + +/* show yyy zzz */ +struct prot prots[] = { + { "bgp", bgcs }, + { "ospf", oscs }, + { "ospf6", os6cs }, + { "rip", rics }, + { "ike", ikcs }, + { "ipsec", iscs }, + { "ldp", lics }, + { "dvmrp", dvcs }, + { "relay", rlcs }, + { "smtp", smcs }, + { "ldap", ldcs }, + { 0, 0 } +}; diff --git a/netbsd/compile.sh b/netbsd/compile.sh new file mode 100644 index 0000000..3af29ec --- /dev/null +++ b/netbsd/compile.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +cat >compile.c <<__END +char compiled[] = "`/bin/date +"%d-%b-%y %H:%M"`"; +char compiledby[] = "`/usr/bin/whoami`"; +char compilehost[] = "`uname -n`"; +__END diff --git a/netbsd/complete.c b/netbsd/complete.c new file mode 100644 index 0000000..51fcbdd --- /dev/null +++ b/netbsd/complete.c @@ -0,0 +1,500 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/complete.c,v 1.19 2006/06/23 20:35:25 steven Exp $ */ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +#define ttyout stdout +#define ttyin stdin + +unsigned char complete(EditLine *, int, char **, size_t, char *); + +static int comparstr(const void *, const void *); +static unsigned char complete_ambiguous(char *, int, StringList *, EditLine *); +static unsigned char complete_command(char *, int, EditLine *, char **, int); +static unsigned char complete_subcommand(char *, int, EditLine *, char **, int); +static unsigned char complete_local(char *, int, EditLine *); +static unsigned char complete_ifname(char *, int, EditLine *); +static unsigned char complete_args(struct ghs *, char *, int, EditLine *, + char **, int, int); +static void list_vertical(StringList *); + +unsigned char complt_c(EditLine *, int); +unsigned char complt_i(EditLine *, int); +unsigned char exit_i(EditLine *, int); + +static int +comparstr(const void *a, const void *b) +{ + return (strcmp(*(char **)a, *(char **)b)); +} + +/* + * Determine if complete is ambiguous. If unique, insert. + * If no choices, error. If unambiguous prefix, insert that. + * Otherwise, list choices. words is assumed to be filtered + * to only contain possible choices. + * Args: + * word word which started the match + * list list by default + * words stringlist containing possible matches + */ +static unsigned char +complete_ambiguous(char *word, int list, StringList *words, EditLine *el) +{ + char insertstr[MAXPATHLEN]; + char *lastmatch; + int i, j; + size_t matchlen, wordlen; + + wordlen = strlen(word); + if (words->sl_cur == 0) + return (CC_ERROR); /* no choices available */ + + if (words->sl_cur == 1) { /* only once choice available */ + (void)strlcpy(insertstr, words->sl_str[0], sizeof insertstr); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + + if (!list) { + matchlen = 0; + if ((lastmatch = words->sl_str[0])) + matchlen = strlen(lastmatch); + for (i = 1 ; i < words->sl_cur ; i++) { + for (j = wordlen ; j < strlen(words->sl_str[i]); j++) + if (lastmatch[j] != words->sl_str[i][j]) + break; + if (j < matchlen) + matchlen = j; + } + if (matchlen > wordlen) { + (void)strlcpy(insertstr, lastmatch, matchlen+1); + if (el_insertstr(el, insertstr + wordlen) == -1) + return (CC_ERROR); + else + /* + * XXX: really want CC_REFRESH_BEEP + */ + return (CC_REFRESH); + } + } + + putc('\n', ttyout); + qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); + list_vertical(words); + return (CC_REDISPLAY); +} + +/* + * Complete a command + */ +static unsigned char +complete_command(char *word, int list, EditLine *el, char **table, int stlen) +{ + char **c; + struct ghs *ghs; + StringList *words; + size_t wordlen; + unsigned char rv; + + if (table == NULL) + return(CC_ERROR); + + words = sl_init(); + wordlen = strlen(word); + + for (c = table; *c != NULL; c = (char **)((char *)c + stlen)) { + ghs = (struct ghs *)c; + if (wordlen > strlen(ghs->name)) + continue; + if (strncmp(word, ghs->name, wordlen) == 0) + sl_add(words, ghs->name); + } + + rv = complete_ambiguous(word, list, words, el); + sl_free(words, 0); + return (rv); +} + +/* + * Complete a (sub)command + */ +static unsigned char +complete_subcommand(char *word, int list, EditLine *el, char **table, int stlen) +{ + struct ghs *ghs = NULL; + + if (table == NULL) + return(CC_ERROR); + + ghs = (struct ghs *)genget(margv[cursor_argc-1], table, stlen); + if (ghs == 0 || Ambiguous(ghs)) + return(CC_ERROR); + + /* + * XXX completion lists that hit subcommand tables don't get more than + * the first CMPL arg tested in complete_args as long as the level + * 0 is passed to complete_args + */ + return(complete_args(ghs, word, list, el, table, stlen, 0)); +} + +/* + * Complete a local file + */ +static unsigned char +complete_local(char *word, int list, EditLine *el) +{ + StringList *words; + char dir[MAXPATHLEN]; + char *file; + DIR *dd; + struct dirent *dp; + unsigned char rv; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '.'; + dir[1] = '\0'; + file = word; + } else { + if (file == word) { + dir[0] = '/'; + dir[1] = '\0'; + } else { + (void)strlcpy(dir, word, (size_t)(file - word) + 1); + } + file++; + } + + if ((dd = opendir(dir)) == NULL) + return (CC_ERROR); + + words = sl_init(); + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(file) > dp->d_namlen) + continue; + if (strncmp(file, dp->d_name, strlen(file)) == 0) { + char *tcp; + + tcp = strdup(dp->d_name); + if (tcp == NULL) + errx(1, "Can't allocate memory for local dir"); + sl_add(words, tcp); + } + } + closedir(dd); + + rv = complete_ambiguous(file, list, words, el); + sl_free(words, 1); + return (rv); +} + +unsigned char +exit_i(EditLine *el, int ch) +{ + printf("\n"); + return CC_EOF; +} + +unsigned char +complt_i(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)whichlist, sizeof(struct intlist), + NULL)); +} + +unsigned char +complt_c(EditLine *el, int ch) +{ + return(complete(el, ch, (char **)cmdtab, sizeof(struct cmd), NULL)); +} + +unsigned char +complete_ifname(char *word, int list, EditLine *el) +{ + StringList *words; + size_t wordlen; + unsigned char rv; + + words = sl_init(); + wordlen = strlen(word); + + struct if_nameindex *ifn_list, *ifnp; + + if ((ifn_list = if_nameindex()) == NULL) + return 0; + + for (ifnp = ifn_list; ifnp->if_name != NULL; ifnp++) { + if (wordlen > strlen(ifnp->if_name)) + continue; + if (strncmp(word, ifnp->if_name, wordlen) == 0) + sl_add(words, ifnp->if_name); + } + + rv = complete_ambiguous(word, list, words, el); + if_freenameindex(ifn_list); + sl_free(words, 0); + return (rv); +} + +/* + * Generic complete routine + */ +unsigned char +complete(EditLine *el, int ch, char **table, size_t stlen, char *arg) +{ + static char word[256]; + static int lastc_argc, lastc_argo; + struct ghs *c; + const LineInfo *lf; + int celems, dolist; + size_t len; + + (void)ch; /* not used */ + lf = el_line(el); + len = lf->lastchar - lf->buffer; + if (len >= sizeof(line)) + return (CC_ERROR); + (void)memcpy(line, lf->buffer, len); + line[len] = '\0'; + cursor_pos = line + (lf->cursor - lf->buffer); + lastc_argc = cursor_argc; /* remember last cursor pos */ + lastc_argo = cursor_argo; + makeargv(); /* build argc/argv of current line */ + + if (margc == 0 || cursor_argo >= sizeof(word)) + return (CC_ERROR); + + dolist = 0; + + /* if cursor and word is same, list alternatives */ + if (lastc_argc == cursor_argc && lastc_argo == cursor_argo + && strncmp(word, margv[cursor_argc], cursor_argo) == 0) + dolist = 1; + else if (cursor_argo) + memcpy(word, margv[cursor_argc], cursor_argo); + word[cursor_argo] = '\0'; + + if (cursor_argc == 0) + return (complete_command(word, dolist, el, table, stlen)); + + if (arg == NULL) + arg = margv[0]; + c = (struct ghs *) genget(arg, table, stlen); + if (c == (struct ghs *)-1 || c == 0 || Ambiguous(c)) + return (CC_ERROR); + celems = strlen(c->complete); + + /* check for 'continuation' completes (which are uppercase) */ + if ((cursor_argc > celems) && (celems > 0) + && isupper((unsigned char)c->complete[celems-1])) + cursor_argc = celems; + + if (cursor_argc > celems) + return (CC_ERROR); + + return(complete_args(c, word, dolist, el, table, stlen, + cursor_argc - 1)); +} + +unsigned char +complete_args(struct ghs *c, char *word, int dolist, EditLine *el, char **table, + int stlen, int level) +{ +#ifdef CMPLDEBUG + printf("[%s]",&c->complete[level]); +#endif + switch (c->complete[level]) { + case 'l': /* local complete */ + case 'L': + return (complete_local(word, dolist, el)); + case 'c': /* command complete */ + case 'C': + return (complete_command(word, dolist, el, table, stlen)); + case 'i': + case 'I': + return (complete_ifname(word, dolist, el)); + case 't': /* points to a table */ + case 'T': + if (c->table == NULL) + return(CC_ERROR); + return (complete_command(word, dolist, el, c->table, c->stlen)); + case 'a': + case 'A': + if (c->table == NULL) + return(CC_ERROR); + return (complete_subcommand(word, dolist, el, c->table, c->stlen)); + case 'n': /* no complete */ + return (CC_ERROR); + } + + return (CC_ERROR); +} + +/* + * List words in stringlist, vertically arranged + */ +void +list_vertical(StringList *sl) +{ + int i, j, w; + int columns, width, lines; + char *p; + + width = 0; + + for (i = 0 ; i < sl->sl_cur ; i++) { + w = strlen(sl->sl_str[i]); + if (w > width) + width = w; + } + width = (width + 8) &~ 7; + + columns = 1; + if (columns == 0) + columns = 1; + lines = (sl->sl_cur + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + p = sl->sl_str[j * lines + i]; + if (p) + fputs(p, ttyout); + if (j * lines + i + lines >= sl->sl_cur) { + putc('\n', ttyout); + break; + } + if (p) + w = strlen(p); + else + w = 0; + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } + } + } +} + +/* + * this needs to be called before initedit() + */ +void +inithist() +{ + if (!histc) { + histc = history_init(); /* init the builtin history */ + history(histc, &ev, H_SETSIZE, 100); /* remember 100 events */ + } + if (!histi) { + histi = history_init(); + history(histi, &ev, H_SETSIZE, 100); + } +} + +void +endhist() +{ + if (histc) { + history_end(histc); /* deallocate */ + histc = NULL; + } + if (histi) { + history_end(histi); + histi = NULL; + } +} + +void +initedit() +{ + editing = 1; + + if (!elc) { + elc = el_init(__progname, stdin, stdout, stderr); + if (histc) + el_set(elc, EL_HIST, history, histc); /* use history */ + el_set(elc, EL_EDITOR, "emacs"); /* default type */ + el_set(elc, EL_PROMPT, cprompt); /* set the prompt + * function */ + el_set(elc, EL_ADDFN, "complt_c", "Command completion", + complt_c); + el_set(elc, EL_BIND, "\t", "complt_c", NULL); + el_source(elc, NULL); /* read ~/.editrc */ + el_set(elc, EL_SIGNAL, 1); + } + if (!eli) { + eli = el_init(__progname, stdin, stdout, stderr); + if (histi) + el_set(eli, EL_HIST, history, histi); + el_set(eli, EL_EDITOR, "emacs"); + el_set(eli, EL_PROMPT, iprompt); + el_set(eli, EL_ADDFN, "complt_i", "Command completion", + complt_i); + el_set(eli, EL_BIND, "\t", "complt_i", NULL); + el_set(eli, EL_ADDFN, "exit_i", "Exit", exit_i); + el_set(eli, EL_BIND, "^X", "exit_i", NULL); + el_set(eli, EL_BIND, "^D", "exit_i", NULL); + el_source(eli, NULL); + el_set(eli, EL_SIGNAL, 1); + } +} + +void +endedit() +{ + editing = 0; + + if (elc) { + el_end(elc); + elc = NULL; + } + if (eli) { + el_end(eli); + eli = NULL; + } +} diff --git a/netbsd/conf.c b/netbsd/conf.c new file mode 100644 index 0000000..47a258c --- /dev/null +++ b/netbsd/conf.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2002-2009 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +void conf_db_single(FILE *, char *, char *, char *); +void conf_ctl(FILE *, char *, char *, int); +int scantext(char *, char *); + +#define TMPSIZ 1024 /* size of temp strings */ + +int +conf(FILE *output) +{ + char cpass[_PASSWORD_LEN+1]; + char hostbuf[MAXHOSTNAMELEN]; + + fprintf(output, "!\n"); + + gethostname (hostbuf, sizeof(hostbuf)); + fprintf(output, "hostname %s\n", hostbuf); + if (read_pass(cpass, sizeof(cpass))) { + fprintf(output, "enable secret blowfish %s\n", cpass); + } else { + if (errno != ENOENT) + printf("%% Unable to read run-time crypt repository:" + " %s\n", strerror(errno)); + } + fprintf(output, "!\n"); + conf_ctl(output, "", "motd", 0); + + fprintf(output, "!\n"); + + conf_ctl(output, "", "sshd", 0); + + fprintf(output, "!\n"); + + return(0); +} + +void conf_ctl(FILE *output, char *delim, char *name, int rtableid) +{ + FILE *conf; + struct daemons *x; + struct ctl *ctl; + char tmp_str[TMPSIZ], tmpfile[64]; + char *fenablenm = NULL, *fothernm = NULL, *flocalnm = NULL; + int defenable = 0, pntdrules = 0, pntdflag = 0, dbflag; + + x = (struct daemons *)genget(name, (char **)ctl_daemons, + sizeof(struct daemons)); + if (x == 0 || Ambiguous(x)) { + printf("%% conf_ctl: %s: genget internal failure\n", name); + return; + } + + /* print rules if they exist */ + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", x->tmpfile, rtableid); + if ((conf = fopen(tmpfile, "r")) != NULL) { + fprintf(output, "%s%s rules\n", delim, name); + for (;;) { + if(fgets(tmp_str, TMPSIZ, conf) == NULL) + break; + if(tmp_str[0] == 0) + break; + fprintf(output, "%s %s", delim, tmp_str); + } + fclose(conf); + fprintf(output, "%s!\n", delim); + pntdrules = 1; + } else if (errno != ENOENT || (errno == ENOENT && verbose)) + printf("%% conf_ctl: %s: %s\n", tmpfile, strerror(errno)); + + /* fill in argument names from table */ + for (ctl = x->table; ctl != NULL && ctl->name != NULL; ctl++) { + switch(ctl->flag_x) { + case DB_X_ENABLE_DEFAULT: + defenable = 1; + /* FALLTHROUGH */ + case DB_X_ENABLE: + fenablenm = ctl->name; + break; + case DB_X_LOCAL: + flocalnm = ctl->name; + break; + case DB_X_OTHER: + fothernm = ctl->name; + break; + case DB_X_DISABLE: + case DB_X_REMOVE: + case DB_X_DISABLE_ALWAYS: + case 0: + break; + default: + printf("%% conf_ctl: flag_x %d unknown\n", ctl->flag_x); + return; + } + } + + /* print rules as currently enabled in running time database */ + if ((dbflag = db_select_flag_x_dbflag_rtable("ctl", x->name, rtableid)) + < 0) { + printf("%% database ctl select failure (%s, %d)\n", x->name, rtableid); + return; + } + switch(dbflag) { + case DB_X_ENABLE: + fprintf(output, "%s%s %s\n", delim, x->name, fenablenm ? + fenablenm : "enable"); + pntdflag = 1; + break; + case DB_X_LOCAL: + fprintf(output, "%s%s %s\n", delim, x->name, flocalnm ? + flocalnm : "local"); + pntdflag = 1; + break; + case DB_X_OTHER: + fprintf(output, "%s%s %s\n", delim, x->name, fothernm ? + fothernm : "other"); + pntdflag = 1; + break; + case DB_X_DISABLE_ALWAYS: + fprintf(output, "%s%s disable\n", delim, x->name); + pntdflag = 1; + /* FALLTHROUGH */ + case DB_X_DISABLE: + defenable = 0; + break; + case DB_X_REMOVE: + case DB_X_ENABLE_DEFAULT: + case 0: + break; + default: + printf("%% conf_ctl: dbflag %d unknown\n", dbflag); + } + if (defenable) { + fprintf(output, "%s%s %s\n", delim, x->name, fenablenm ? + fenablenm : "enable"); + pntdflag = 1; + } + if (pntdrules && x->doreload) { + fprintf(output, "%s%s reload\n", delim, x->name); + pntdflag = 1; + } + if (pntdflag) + fprintf(output, "%s!\n", delim); +} + + +/* find string in file */ +int scantext(char *fname, char *string) +{ + FILE *file; + char line[128]; + int found = 0; + + if ((file = fopen(fname, "r")) == 0) { + printf("%% Unable to open %s: %s\n", fname, strerror(errno)); + return(0); + } + + for (;;) { + if (fgets(line, sizeof(line), file) == NULL) + break; + if (strcmp(line, string) == 0) { + found = 1; + break; + } + } + + fclose(file); + return(found); +} + +void +conf_db_single(FILE *output, char *dbname, char *lookup, char *ifname) +{ + StringList *dbreturn; + dbreturn = sl_init(); + + if (db_select_flag_x_ctl(dbreturn, dbname, ifname) < 0) { + printf("%% conf_db_single %s database select failed\n", dbname); + } + if (dbreturn->sl_cur > 0) { + if (lookup == NULL) + fprintf(output, " %s\n", dbname); + else if (strcmp(dbreturn->sl_str[0], lookup) != 0) + fprintf(output, " %s %s\n", dbname, dbreturn->sl_str[0]); + } + sl_free(dbreturn, 1); +} diff --git a/netbsd/ctl.c b/netbsd/ctl.c new file mode 100644 index 0000000..ef80ea5 --- /dev/null +++ b/netbsd/ctl.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +/* service daemons */ +#define SSHD "/usr/sbin/sshd" + +/* table variable (for pkill usage) */ +static char table[16]; + +/* service routines */ +void call_editor(char *, char **, char *); +void ctl_symlink(char *, char *, char *); +int rule_writeline(char *, mode_t, char *); +int fill_tmpfile(char **, char *, char **); +int acq_lock(char *); +void rls_lock(int); + +/* master daemon list */ +struct daemons ctl_daemons[] = { +{ "sshd", "SSH", ctl_sshd, SSHDCONF_TEMP, 0600, 0, 255 }, +{ 0, 0, 0, 0, 0, 0 } +}; + +/* per-daemon commands, and their C or executable functions */ + +/* MOTD */ +struct ctl ctl_motd[] = { + { "edit", "edit message-of-the-day", + { "motd", NULL, NULL }, call_editor, 0, T_HANDLER }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +/* sshd */ +char *ctl_sshd_test[] = { SSHD, "-tf", REQTEMP, NULL }; +struct ctl ctl_sshd[] = { + { "enable", "enable service", + { SSHD, "-f", REQTEMP, NULL }, NULL, DB_X_ENABLE, T_EXEC }, + { "disable", "disable service", + { PKILL, table, "-f", SSHD, "-f", REQTEMP, NULL }, NULL, + DB_X_DISABLE, T_EXEC }, + { "edit", "edit configuration", + { "sshd", (char *)ctl_sshd_test, NULL }, call_editor, 0, + T_HANDLER_FILL1 }, + { 0, 0, { 0 }, 0, 0, 0 } +}; + +void +ctl_symlink(char *temp, char *real, char *z) +{ + rmtemp(temp); + symlink(real, temp); +} + +/* flag to other nsh sessions or nsh conf() that actions have been taken */ +void +flag_x(char *name, char *daemon, int dbflag, char *data) +{ + if (db_delete_flag_x_ctl(name, daemon) < 0) { + printf("%% database delete failure ctl ctl\n"); + return; + } + if (dbflag == DB_X_REMOVE) + return; + if (db_insert_flag_x(name, daemon, cli_rtable, dbflag, data) < 0) { + printf("%% database insert failure ctl ctl\n"); + } +} + +/* the main entry point into ctl.c from CLI */ +int +ctlhandler(int argc, char **argv, char *modhvar) +{ + struct daemons *daemons; + struct ctl *x; + char tmpfile[PATH_MAX]; + char *step_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char *tmp_args[NOPTFILL] = { NULL, NULL, NULL, NULL, NULL, NULL }; + char **fillargs; + + /* loop daemon list to find table pointer */ + daemons = (struct daemons *) genget(hname, (char **)ctl_daemons, + sizeof(struct daemons)); + if (daemons == 0) { + printf("%% Internal error - Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(daemons)) { + printf("%% Internal error - Ambiguous argument %s\n", argv[1]); + return 0; + } + + if (cli_rtable > daemons->rtablemax) { + printf("%% Command %s not available via rtable %d\n", + daemons->name, cli_rtable); + return 0; + } + + snprintf(table, sizeof(table), "-T%d", cli_rtable); + if (daemons->tmpfile) + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + if (modhvar) { + /* action specified or indented command specified */ + if (argc == 2 && isprefix(argv[1], "rules")) { + /* skip 'X rules' line */ + return(0); + } + if (isprefix(modhvar, "rules")) { + if (!daemons->tmpfile) { + printf("%% writeline without tmpfile\n"); + return 0; + } + /* write indented line to tmp config file */ + rule_writeline(tmpfile, daemons->mode, saveline); + return 0; + } + } + if (argc < 2 || argv[1][0] == '?') { + gen_help((char **)daemons->table, "", "", sizeof(struct ctl)); + return 0; + } + + x = (struct ctl *) genget(argv[1], (char **)daemons->table, + sizeof(struct ctl)); + if (x == 0) { + printf("%% Invalid argument %s\n", argv[1]); + return 0; + } else if (Ambiguous(x)) { + printf("%% Ambiguous argument %s\n", argv[1]); + return 0; + } + + fillargs = step_optreq(x->args, step_args, argc, argv, 2); + if (fillargs == NULL) + return 0; + + switch(x->type) { + /* fill_tmpfile will return 0 if tmpfile or args are NULL */ + case T_HANDLER: + /* pointer to handler routine, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) { + (*x->handler)(tmp_args[0], tmp_args[1], tmp_args[2]); + } else { + (*x->handler)(fillargs[0], fillargs[1], fillargs[2]); + } + break; + case T_HANDLER_FILL1: + /* pointer to handler routine, fill args @ args[1] pointer */ + if (fill_tmpfile((char **)fillargs[1], tmpfile, tmp_args)) + (*x->handler)(fillargs[0], tmp_args, fillargs[2]); + else + (*x->handler)(fillargs[0], (char **)fillargs[1], fillargs[2]); + break; + case T_EXEC: + /* command to execute via execv syscall, fill main args */ + if (fill_tmpfile(fillargs, tmpfile, tmp_args)) + cmdargs(tmp_args[0], tmp_args); + else + cmdargs(fillargs[0], fillargs); + break; + } + + if (x->flag_x != 0) { + flag_x("ctl", daemons->name, x->flag_x, NULL); + } + + return 1; +} + +int +fill_tmpfile(char **fillargs, char *tmpfile, char **tmp_args) +{ + int i; + + if (fillargs == NULL || tmpfile == NULL) + return 0; + + for (i = 0; i < NOPTFILL - 1; i++) { + if(fillargs[i] == NULL) { + break; + } + if(fillargs[i] == REQTEMP) { + tmp_args[i] = tmpfile; + } else { + tmp_args[i] = fillargs[i]; + } + } + return 1; +} + +void +call_editor(char *name, char **args, char *z) +{ + int fd, found = 0; + char *editor, tmpfile[64]; + struct daemons *daemons; + + for (daemons = ctl_daemons; daemons->name != 0; daemons++) + if (strncmp(daemons->name, name, strlen(name)) == 0) { + found = 1; + break; + } + + if (!found) { + printf("%% call_editor internal error\n"); + return; + } + + snprintf(tmpfile, sizeof(tmpfile), "%s.%d", daemons->tmpfile, + cli_rtable); + + /* acq lock, call editor, test config with cmd and args, release lock */ + if ((editor = getenv("EDITOR")) == NULL) + editor = DEFAULT_EDITOR; + if ((fd = acq_lock(tmpfile)) > 0) { + char *argv[] = { editor, tmpfile, NULL }; + cmdargs(editor, argv); + chmod(tmpfile, daemons->mode); + if (args != NULL) + cmdargs(args[0], args); + rls_lock(fd); + } else + printf ("%% %s configuration is locked for editing\n", + daemons->propername); +} + +int +rule_writeline(char *fname, mode_t mode, char *writeline) +{ + FILE *rulefile; + + rulefile = fopen(fname, "a"); + if (rulefile == NULL) { + printf("%% Rule write failed: %s\n", strerror(errno)); + return(1); + } + if (writeline[0] == ' ') + writeline++; + fprintf(rulefile, "%s", writeline); + fclose(rulefile); + chmod(fname, mode); + return(0); +} + +int +acq_lock(char *fname) +{ + int fd; + char lockf[SIZE_CONF_TEMP + sizeof(".lock")]; + + /* + * some text editors lock (vi), some don't (mg) + * + * here we lock a separate, do-nothing file so we don't interfere + * with the editors that do... (lock multiple concurrent nsh users) + */ + snprintf(lockf, sizeof(lockf), "%s.lock", fname); + if ((fd = open(lockf, O_RDWR | O_CREAT, 0600)) == -1) + return(-1); + if (flock(fd, LOCK_EX | LOCK_NB) == 0) + return(fd); + else { + close(fd); + return(-1); + } +} + +void +rls_lock(int fd) +{ + /* best-effort, who cares */ + flock(fd, LOCK_UN); + close(fd); + return; +} + +void +rmtemp(char *file) +{ + if (unlink(file) != 0) + if (errno != ENOENT) + printf("%% Unable to remove temporary file %s: %s\n", + file, strerror(errno)); +} diff --git a/netbsd/editing.h b/netbsd/editing.h new file mode 100644 index 0000000..e9bc288 --- /dev/null +++ b/netbsd/editing.h @@ -0,0 +1,9 @@ +#include + +extern EditLine *elc; /* editline(3) status structure */ +extern EditLine *eli; /* another one */ +extern History *histc; /* command() editline(3) history structure */ +extern History *histi; /* interface() editline(3) status structure */ +extern char *cursor_pos; /* cursor position we're looking for */ +extern size_t cursor_argc; /* location of cursor in margv */ +extern size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ diff --git a/netbsd/externs.h b/netbsd/externs.h new file mode 100644 index 0000000..b7fbffe --- /dev/null +++ b/netbsd/externs.h @@ -0,0 +1,561 @@ +/* + * nsh externs, prototypes and macros + */ + +#define NO_ARG(x) (strcasecmp(x, "no") == 0) /* absolute "no" */ + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) /* sys/param.h */ + +struct rtdump { + char *buf; /* start of routing table */ + char *lim; /* end of routing table */ +}; + +extern char *__progname; /* duh */ +extern char *vers; /* the version of nsh */ +extern char saveline[1024]; /* command line */ +extern char line[1024]; /* command line for makeargv() */ +extern int margc; /* makeargv() arg count */ +extern char *margv[]; /* makeargv() args */ +extern int verbose; /* is verbose mode on? */ +extern int editing; /* is command line editing mode on? */ +extern int bridge; /* are we in bridge mode (or interface mode?) */ +extern int priv; /* privileged mode or not? */ +//extern pid_t pid; /* process id of nsh */ +extern int cli_rtable; /* environment rtable */ + +#define HSIZE 64 +extern char hname[HSIZE]; /* prefix name to mode handler */ + +#ifdef _HISTEDIT_H_ +extern HistEvent ev; /* ev */ +#endif + +/* defaults */ +#define DEFAULT_MTU 1500 /* net.inet.ip.defmtu */ +#define DEFAULT_TTL 64 /* net.inet.ip.defttl */ +#define DEFAULT_MTTL 255 /* net.mpls.ttl */ +#define ESP_UDPENCAP_PORT 4500 /* net.inet.esp.udpencap_port */ + +/* nopt.c */ +#define no_arg 1 +#define req_arg 2 +struct nopts { + char *name; + int type; + int arg; +}; +extern int noptind; +extern char *nopterr; +int nopt(int, char **, struct nopts *); + +/* ppp.c */ +int intsppp(char *, int, int, char **); +int intpppoe(char *, int, int, char **); +void conf_pppoe(FILE *, int, char *); +void conf_sppp(FILE *, int, char *); + +/* conf.c */ +#define LEASEPREFIX "/var/db/dhclient.leases" +int conf(FILE *); +long default_mtu(char *); +int conf_routes(FILE *, char *, int, int, int); +int conf_dhcrelay(char *, char *, int); + +/* show.c */ +void p_rttables(int, int, int); +#ifdef _NETINET_IN_H_ +char *routename4(in_addr_t); +char *netname4(in_addr_t, struct sockaddr_in *); +#endif +#ifdef _NETINET6_IN6_H_ +char *routename6(struct sockaddr_in6 *); +char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); +void in6_fillscopeid(struct sockaddr_in6 *); +void in6_clearscopeid(struct sockaddr_in6 *); +#endif +#ifdef _SYS_SOCKET_H_ +char *routename(struct sockaddr *); +char *netname(struct sockaddr *, struct sockaddr *); +char *any_ntoa(const struct sockaddr *); +#endif + +/* alignment constraint for routing socket */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +/* routesys.c */ +#ifdef _NET_ROUTE_H_ +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; +#endif +#ifdef _WANT_SO_ +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + struct sockaddr_inarp sinarp; +}; +extern union sockunion so_dst, so_mask, so_gate, so_ifp; +#endif +#ifdef _NETINET6_IN6_H_ +int prefixlen(int, struct sockaddr_in6 *); +#endif +extern int rtm_addrs; +extern long rtm_inits; +#define FLUSH 0 +struct rtdump *getrtdump(int, int, int); +void freertdump(struct rtdump *); +int monitor(int, char **); +int rtmsg(int, int, int, int, int); +void flushroutes(int, int); +void bprintf(FILE *, int, char *); +#ifdef _NET_IF_DL_H_ +char *mylink_ntoa(const struct sockaddr_dl *); +#endif +extern char ifnetflags[]; +extern char routeflags[]; +extern char addrnames[]; +extern char metricnames[]; + +/* ctl.c */ +/* tmp config locations */ +#define PFCONF_TEMP "/var/run/pf.conf" +#define OSPFCONF_TEMP "/var/run/ospfd.conf" +#define OSPF6CONF_TEMP "/var/run/ospf6d.conf" +#define EIGRPCONF_TEMP "/var/run/eigrpd.conf" +#define BGPCONF_TEMP "/var/run/bgpd.conf" +#define RIPCONF_TEMP "/var/run/ripd.conf" +#define LDPCONF_TEMP "/var/run/ldpd.conf" +#define IPSECCONF_TEMP "/var/run/ipsec.conf" +#define IKECONF_TEMP "/var/run/iked.conf" +#define DVMRPCONF_TEMP "/var/run/dvmrpd.conf" +#define RTADVCONF_TEMP "/var/run/rtadvd.conf" +#define RELAYCONF_TEMP "/var/run/relayd.conf" +#define SASYNCCONF_TEMP "/var/run/sasyncd.conf" +#define DHCPCONF_TEMP "/var/run/dhcpd.conf" +#define SNMPCONF_TEMP "/var/run/snmpd.conf" +#define NTPCONF_TEMP "/var/run/ntpd.conf" +#define IFSTATE_TEMP "/var/run/ifstated.conf" +#define NPPPCONF_TEMP "/var/run/npppd.conf" +#define FTPPROXY_TEMP "/var/run/ftp-proxy" +#define TFTPPROXY_TEMP "/var/run/tftp-proxy" +#define TFTP_TEMP "/var/run/tftpd" +#define RESOLVCONF_TEMP "/var/run/resolv.conf" +#define RESOLVCONF_SYM "/var/run/resolv.conf.symlink" +#define RESOLVCONF_DHCP "/var/run/resolv.conf.dhcp" +#define INETCONF_TEMP "/var/run/inetd.conf" +#define SSHDCONF_TEMP "/var/run/sshd.conf" +#define SMTPCONF_TEMP "/var/run/smtpd.conf" +#define LDAPCONF_TEMP "/var/run/ldapd.conf" +#define IFSTATECONF_TEMP "/var/run/ifstated.conf" +#define MOTD_TEMP "/var/run/motd" + +/* argument list replacement */ +#define OPT (void *)1 +#define REQ (void *)2 +#define IFNAME (void *)3 +#define REQTEMP (void *)4 +#define SIZE_CONF_TEMP 64 +int ctlhandler(int, char **, char *); +void rmtemp(char *); +/* control programs */ +#define PFCTL "/sbin/pfctl" +#define OSPFCTL "/usr/sbin/ospfctl" +#define OSPF6CTL "/usr/sbin/ospf6ctl" +#define EIGRPCTL "/usr/sbin/eigrpctl" +#define BGPCTL "/usr/sbin/bgpctl" +#define RIPCTL "/usr/sbin/ripctl" +#define LDPCTL "/usr/sbin/ldpctl" +#define IPSECCTL "/sbin/ipsecctl" +#define IKECTL "/usr/sbin/ikectl" +#define DVMRPCTL "/usr/sbin/dvmrpctl" +#define RELAYCTL "/usr/sbin/relayctl" +#define SNMPCTL "/usr/sbin/snmpctl" +#define SMTPCTL "/usr/sbin/smtpctl" +#define LDAPCTL "/usr/sbin/ldapctl" +struct ctl { + char *name; + char *help; + char *args[32]; + void (*handler)(); + int flag_x; + int type; +}; +#define T_HANDLER 1 +#define T_HANDLER_FILL1 2 +#define T_EXEC 3 +struct daemons { + char *name; + char *propername; + struct ctl *table; + char *tmpfile; + mode_t mode; + int doreload; + int rtablemax; +}; +extern struct daemons ctl_daemons[]; +extern struct ctl ctl_pf[]; +extern struct ctl ctl_ospf[]; +extern struct ctl ctl_ospf6[]; +extern struct ctl ctl_eigrp[]; +extern struct ctl ctl_relay[]; +extern struct ctl ctl_bgp[]; +extern struct ctl ctl_rip[]; +extern struct ctl ctl_ldp[]; +extern struct ctl ctl_ipsec[]; +extern struct ctl ctl_nppp[]; +extern struct ctl ctl_ifstate[]; +extern struct ctl ctl_ike[]; +extern struct ctl ctl_dvmrp[]; +extern struct ctl ctl_rtadv[]; +extern struct ctl ctl_sasync[]; +extern struct ctl ctl_dhcp[]; +extern struct ctl ctl_snmp[]; +extern struct ctl ctl_smtp[]; +extern struct ctl ctl_sshd[]; +extern struct ctl ctl_ntp[]; +extern struct ctl ctl_ftpproxy[]; +extern struct ctl ctl_tftpproxy[]; +extern struct ctl ctl_tftp[]; +extern struct ctl ctl_dns[]; +extern struct ctl ctl_inet[]; +extern struct ctl ctl_ldap[]; +extern struct ctl ctl_motd[]; +void flag_x(char *, char *, int, char *); + +/* commands.c */ +#define NOPTFILL 7 +#define DEFAULT_EDITOR "/usr/bin/vi" +#define NSHRC_TEMP "/var/run/nshrc" +#define NSHRC "/etc/nshrc" +#define PING "/sbin/ping" +#define PING6 "/sbin/ping6" +#define TRACERT "/usr/sbin/traceroute" +#define TRACERT6 "/usr/sbin/traceroute6" +#define TELNET "/usr/bin/telnet" +#define SSH "/usr/bin/ssh" +#define PKILL "/usr/bin/pkill" +#define SAVESCRIPT "/usr/local/bin/save.sh" +#ifndef DHCPLEASES +#define DHCPLEASES "/var/db/dhcpd.leases" +#endif +void command(void); +char **step_optreq(char **, char **, int, char **, int); +int argvtostring(int, char **, char *, int); +int cmdrc(char rcname[FILENAME_MAX]); +int cmdargs(char *, char **); +char *iprompt(void); +char *cprompt(void); +char *pprompt(void); +int group (int, char **); +void gen_help(char **, char *, char *, int); +void makeargv(void); +extern size_t cursor_argc; +extern size_t cursor_argo; + +typedef struct cmd { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler) (); /* routine which executes command */ + int needpriv; /* Do we need privilege to execute? */ + int nocmd; /* Can we specify 'no ...command...'? */ + int modh; /* Is it a mode handler for cmdrc()? */ +} Command; + +typedef struct menu { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int minarg; /* Minimum number of arguments */ + int maxarg; /* Maximum number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ +} Menu; + +struct intlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + char *complete; /* context sensitive completion list */ + char **table; /* next table for context completion */ + int stlen; /* struct length (for rows in next table) */ + int (*handler)(); /* Routine to perform (for special ops) */ + int bridge; /* 0 == Interface, 1 == Bridge, 2 == Both */ +}; + +/* generic help /complt struct */ +struct ghs { + char *name; + char *help; + char *complete; + char **table; + int stlen; +}; + +extern Command cmdtab[]; +extern struct intlist Intlist[]; +extern struct intlist Bridgelist[]; +extern struct intlist *whichlist; + +/* ieee80211.c */ +#define NWID 0 +#define NWKEY 1 +#define POWERSAVE 2 +#define TXPOWER 3 +#define BSSID 4 +#define DEFAULT_POWERSAVE 100 /* 100 ms */ +const char *get_string(const char *, const char *, __int8_t *, int *); +void make_string(char *str, int, const __int8_t *buf, int); +int get_nwinfo(char *, char *, int, int); +int get_nwpowersave(int, char *); +int intnwkey(char *, int, int, char **); +int inttxpower(char *, int, int, char **); +int intbssid(char *, int, int, char **); + +/* stats.c */ +void rt_stats(void); +void tcp_stats(void); +void udp_stats(void); +void ip_stats(void); +void icmp_stats(void); +void igmp_stats(void); +void ah_stats(void); +void esp_stats(void); +void ipip_stats(void); +void carp_stats(void); +void pfsync_stats(void); +void ipcomp_stats(void); + +/* mbuf.c */ +void mbpr(void); + +/* kread.c */ +char *plural(int); +char *plurales(int); + +/* genget.c */ +int isprefix(char *, char*); +char **genget(char *, char **, int); +int Ambiguous(void *); + +/* sysctl.c */ +int sysctl_int(int[], int, int); +int ipsysctl(int, char *, char *, int); +void conf_sysctls(FILE *); + +/* route.c */ +#define NO_NETMASK 0 +#define ASSUME_NETMASK 1 +int route(int, char**); +void show_route(char *, int); +int is_ip_addr(char *); +#ifdef _IP_T_ +void parse_ip_pfx(char *, int, ip_t *); +int ip_route(ip_t *, ip_t *, u_short, int, int, struct rt_metrics, int inits); +#endif +#ifdef _NETINET6_IN6_H_ +int parse_ipv6(char *, struct in6_addr *); +#endif + +/* if.c */ +#define DHCLIENT "/sbin/dhclient" +#define DHCRELAY "/usr/sbin/dhcrelay" +#define RTADVD "/usr/sbin/rtadvd" +#define IFDATA_MTU 1 /* request for if_data.ifi_mtu */ +#define IFDATA_BAUDRATE 2 /* request for if_data.ifi_baudrate */ +#define MBPS(bps) (bps / 1000 / 1000) +#define ROUNDMBPS(bps) ((float)bps == ((bps / 1000 / 1000) * 1000 * 1000)) +#define ROUNDKBPS(bps) ((float)bps == ((bps / 1000) * 1000)) +#define ROUNDKBYTES(bytes) ((float)bytes == ((bytes / 1024) * 1024)) +void imr_init(char *); +int is_valid_ifname(char *); +int show_int(int, char **); +int get_rdomain(int, char *); +int get_ifdata(char *, int); +int get_ifflags(char *, int); +int set_ifflags(char *, int, int); +int get_ifxflags(char *, int); +int set_ifxflags(char *, int, int); +int intip(char *, int, int, char **); +int intmtu(char *, int, int, char **); +int intkeepalive(char *, int, int, char **); +int intmpelabel(char *, int, int, char **); +int intrdomain(char *, int, int, char **); +int intdhcrelay(char *, int, int, char **); +int intmetric(char *, int, int, char **); +int intrtd(char *, int, int, char **); +int intvlan(char *, int, int, char **); +int intflags(char *, int, int, char **); +int intxflags(char *, int, int, char **); +int intaf(char *, int, int, char **); +int intlink(char *, int, int, char **); +int intnwid(char *, int, int, char **); +int intpowersave(char *, int, int, char **); +int intdesc(char *, int, int, char **); +int intpflow(char *, int, int, char **); +int intlladdr(char *, int, int, char **); +int intgroup(char *, int, int, char **); +int intrtlabel(char *, int, int, char **); +int intparent(char *, int, int, char **); +int intpatch(char *, int, int, char **); +int intmpw(char *, int, int, char **); +int addaf(char *, int, int); +int removeaf(char *, int, int); +char *get_hwdaddr(char *); + +/* main.c */ +void intr(void); + +/* version.c */ +int version(int, char **); + +/* compile.c */ +extern char compiled[], compiledby[], compiledon[], compilehost[]; + +/* bridge.c */ +long bridge_cfg(int, char *, int); +int bridge_confaddrs(int, char *, char *, FILE *); +int bridge_rules(int, char *, char *, char *, FILE *); +int bridge_list(int, char *, char *, char *, int, int); +int bridge_addrs(int, char *, char *, char *); +int set_ifflag(int, char *, short); +int clr_ifflag(int, char *, short); +int is_bridge(int, char *); +int brport(char *, int, int, char **); +int brval(char *, int, int, char **); +int brrule(char *, int, int, char **); +int brstatic(char *, int, int, char **); +int brpri(char *, int, int, char **); +int flush_bridgedyn(char *); +int flush_bridgeall(char *); +int flush_bridgerule(char *, char*); + +/* tunnel.c */ +int inttunnel(char *, int, int, char **); +int intvnetid(char *, int, int, char **); +int get_physrtable(int, char *); +int get_physttl(int, char *); +int get_vnetid(int, char *); + +/* media.c */ +#define DEFAULT_MEDIA_TYPE "autoselect" +void media_status(int, char *, char *); +void media_supported(int, char *, char *, char *); +int phys_status(int, char *, char *, char *, int, int); +int intmedia(char *, int, int, char **); +int intmediaopt(char *, int, int, char **); +int conf_media_status(FILE *, int, char *); + +/* passwd.c */ +#define NSHPASSWD_TEMP "/var/run/nshpasswd" +int read_pass(char *, size_t); +int gen_salt(char *, size_t); +int enable(int, char **); + +/* pfsync.c */ +#define PFSYNC_MAXUPDATES 128 +int intsyncdev(char *, int, int, char **); +int intsyncpeer(char *, int, int, char **); +int intmaxupd(char *, int, int, char **); +int conf_pfsync(FILE *, int, char *); + +/* carp.c */ +#define CARP_ADVSKEW 0 +#define CARP_ADVBASE 1 +#define CARP_VHID 2 +#define CARP_PEER 3 +#define CARP_BALANCING 4 +int intcarp(char *, int, int, char **); +int intcpass(char *, int, int, char **); +int intcnode(char *, int, int, char **); +int conf_carp(FILE *, int, char *); +int carp_state(int, char *); +int intcdev(char *, int, int, char **); + +/* trunk.c */ +int inttrunkport(char *, int, int, char **); +int inttrunkproto(char *, int, int, char **); +int conf_trunk(FILE *output, int ifs, char *ifname); +void show_trunk(int ifs, char *ifname); + +/* who.c */ +int who(int, char **); + +/* arp.c */ +int arpget(const char *); +int arpset(int, char **); +void arpdump(void); +void conf_arp(FILE *, char *); +//char *sec2str(time_t); + +/* more.c */ +int more(char *); +int nsh_cbreak(void); +void nsh_nocbreak(void); +void setwinsize(int); +#ifdef _SYS_TTYCOM_H_ +extern struct winsize winsize; +#endif + +/* complete.c */ +#define CMPL(x) __STRING(x), +#define CMPL0 "", +void inithist(void); +void endhist(void); +void initedit(void); +void endedit(void); + +/* utils.c */ +int string_index(char *, char **); +//char *format_time(time_t); +char *format_k(__uint64_t amt); + +/* sqlite3.c */ +/* sqlite3.c */ +#define SQ3DBFILE "/var/run/nsh.db" +#define DB_X_ENABLE 1 /* enable command */ +#define DB_X_DISABLE 2 /* disable command */ +#define DB_X_LOCAL 3 /* local control command */ +#define DB_X_OTHER 4 /* other command */ +#define DB_X_REMOVE 5 /* remove command */ +#define DB_X_ENABLE_DEFAULT 6 /* enable command, always prints enable until disabled */ +#define DB_X_DISABLE_ALWAYS 7 /* disable command, always prints if disabled */ +int db_create_table_rtables(void); +int db_create_table_flag_x(char *); +int db_create_table_nameservers(void); +int db_insert_flag_x(char *, char *, int, int, char *); +int db_insert_rtables(int, char *); +int db_insert_nameserver(char *); +int db_delete_rtables_rtable(int); +int db_delete_flag_x_ctl(char *, char *); +int db_delete_flag_x_ctl_data(char *, char *, char *); +int db_delete_nameservers(void); +#ifdef _STRINGLIST_H +int db_select_flag_x_ctl_data(StringList *, char *, char *, char *); +int db_select_flag_x_ctl(StringList *, char *, char *); +int db_select_rtable_rtables(StringList *); +int db_select_rtables_rtable(StringList *, int); +int db_select_rtables_ctl(StringList *, char *); +int db_select_name_rtable(StringList *, int); +int db_select_flag_x_ctl_rtable(StringList *, char *, int); +int db_select_flag_x_data_ctl_rtable(StringList *, char *, char *, int); +int db_select_nameservers(StringList *); +#endif +int db_select_flag_x_dbflag_rtable(char *, char *, int); + +/* pflow.c */ +#define PFLOW_SENDER 0 +#define PFLOW_RECEIVER 1 +#define PFLOW_VERSION 2 +#ifdef _SYS_SOCKET_H_ +int pflow_addr(const char *, struct sockaddr_storage *); +#endif +int pflow_status(int, int, char *, char *); diff --git a/netbsd/genget.c b/netbsd/genget.c new file mode 100644 index 0000000..549e785 --- /dev/null +++ b/netbsd/genget.c @@ -0,0 +1,99 @@ +/* From: $OpenBSD: genget.c,v 1.5 2001/05/25 10:23:06 hin Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include "externs.h" + +int isprefix(char *, char*); + +/* + * The prefix function returns 0 if *s1 is not a prefix + * of *s2. If *s1 exactly matches *s2, the negative of + * the length is returned. If *s1 is a prefix of *s2, + * the length of *s1 is returned. + */ +int +isprefix(char *s1, char *s2) +{ + char *os1; + char c1, c2; + + if (*s1 == '\0') + return(-1); + os1 = s1; + c1 = *s1; + c2 = *s2; + while (tolower((unsigned char)c1) == tolower((unsigned char)c2)) { + if (c1 == '\0') + break; + c1 = *++s1; + c2 = *++s2; + } + return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); +} + +static char *ambiguous; /* special return value for command routines */ + +char ** +genget(char *name, char **table, int stlen) + /* name to match */ + /* name entry in table */ + +{ + char **c, **found; + int n; + + if (name == 0) + return 0; + + found = 0; + for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { + if ((n = isprefix(name, *c)) == 0) + continue; + if (n < 0) /* exact match */ + return(c); + if (found) + return(&ambiguous); + found = c; + } + return(found); +} + +/* + * Function call version of Ambiguous() + */ +int +Ambiguous(void *s) +{ + return((char **)s == &ambiguous); +} diff --git a/netbsd/main.c b/netbsd/main.c new file mode 100644 index 0000000..7fd6984 --- /dev/null +++ b/netbsd/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2002-2013 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "editing.h" +#include "stringlist.h" +#include "externs.h" + +void usage(void); + +jmp_buf toplevel; + +char *vers = "1.0"; +int bridge = 0; /* bridge mode for interface() */ +int verbose = 0; /* verbose mode */ +int priv = 0, cli_rtable = 0; +int editing = 1; +pid_t pid; + +History *histi = NULL; +History *histc = NULL; +HistEvent ev; +EditLine *elc = NULL; +EditLine *eli = NULL; +char *cursor_pos = NULL; + +void intr(void); + +int +main(int argc, char *argv[]) +{ + int top, ch, iflag = 0, cflag = 0; + char rc[PATH_MAX]; + + if(getuid() != 0) + printf("%% Functionality limited without root privilege.\n"); + + pid = getpid(); + + while ((ch = getopt(argc, argv, "c:i:v")) != -1) + switch (ch) { + case 'c': + cflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'i': + iflag = 1; + strlcpy(rc, optarg, PATH_MAX); + break; + case 'v': + verbose = 1; + break; + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (cflag && iflag) + usage(); + if (argc > 0) + usage(); + if (iflag) + rmtemp(SQ3DBFILE); + + printf("%% NSH v%s\n", vers); + + if (iflag) { + /* + * Interpret config file and exit + */ + priv = 1; + + /* + * Set carp group carpdemote to 128 during initialization + */ + + cmdrc(rc); + + /* + * Initialization over + */ + + exit(0); + } + if (cflag) { + /* + * Interpret command file and exit + */ + priv = 1; + + cmdrc(rc); + + exit(0); + } + + top = setjmp(toplevel) == 0; + if (top) { + (void)signal(SIGWINCH, setwinsize); + (void)signal(SIGINT, (sig_t)intr); + (void)setwinsize(0); + } else + putchar('\n'); + + for (;;) { + command(); + top = 1; + } + + /* NOTREACHED */ + return 0; +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-v] [-i rcfile | -c rcfile]\n", __progname); + fprintf(stderr, " -v indicates verbose operation\n"); + fprintf(stderr, " -i rcfile loads initial system" \ + " configuration from rcfile\n"); + fprintf(stderr, " -c rcfile loads commands from rcfile\n"); + exit(1); +} + +void +intr(void) +{ + longjmp(toplevel, 1); +} diff --git a/netbsd/more.c b/netbsd/more.c new file mode 100644 index 0000000..4e037df --- /dev/null +++ b/netbsd/more.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +#define PAGERPROMPT " --More-- " +#define BACKOVERPROMPT "\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b" + +int nsh_cbreak(void); +void nsh_nocbreak(void); + +static struct termios oldtty; + +struct winsize winsize; + +/* + * Display file + */ +int +more(char *fname) +{ + FILE *f; + char *input, c; + size_t s; + int i, nopager = 0; + + if ((f = fopen(fname, "r")) == NULL) { + if (errno == ENOENT) + printf ("%% File %s not found\n", fname); + else + printf ("%% more: fopen(%s): %s\n", fname, + strerror(errno)); + return(0); + } + + if (nsh_cbreak() < 0) + nopager = 1; + + for (i = 0; (input = fgetln(f, &s)) != NULL; i++) { + + if (!nopager && i == (winsize.ws_row - 1)) { + printf(PAGERPROMPT); + fflush(0); + c = getchar(); + printf(BACKOVERPROMPT); + if (c == 'q') + break; /* stop */ + if (c == '\r' || c == '\n') + i--; /* skip one line */ + else + i = 0; /* skip one page */ + } + + /* + * We replace newline (or whatever was at the end of + * the line) with NUL termination + */ + input[s-1] = '\0'; + printf("%s\n", input); + } + + if (!nopager) + nsh_nocbreak(); + + fclose(f); + return(1); +} + +int +nsh_cbreak(void) +{ + struct termios newtty; + + if (tcgetattr(fileno(stdout), &oldtty) < 0) + return(-1); + + (void)memcpy(&newtty, &oldtty, sizeof(newtty)); + + newtty.c_lflag &= ~(ECHO | ICANON); /* no echo, canonical */ + newtty.c_cc[VMIN] = 1; /* one char at a time */ + newtty.c_cc[VTIME] = 0; /* no timeout */ + + if (tcsetattr(fileno(stdout), TCSAFLUSH, &newtty) < 0) + return(-1); + return(0); +} + +void +nsh_nocbreak(void) +{ + tcsetattr(0, TCSAFLUSH, &oldtty); +} + +void +setwinsize(int signo) +{ + int save_errno = errno; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) { + winsize.ws_col = winsize.ws_col ? winsize.ws_col : 80; + winsize.ws_row = winsize.ws_row ? winsize.ws_row : 24; + } else { + winsize.ws_col = 80; + winsize.ws_row = 24; + } + + errno = save_errno; +} diff --git a/netbsd/passwd.c b/netbsd/passwd.c new file mode 100644 index 0000000..9700a20 --- /dev/null +++ b/netbsd/passwd.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2004 + * Christian Gut. 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 ``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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int read_pass(char *, size_t); +int write_pass(char *); +int gen_salt(char *, size_t); + +/* read_pass reads the (blowfish crypted) password from a file */ +int +read_pass(char *pass, size_t size) +{ + FILE *pwdhandle; + + pwdhandle = fopen(NSHPASSWD_TEMP, "r"); + if (pwdhandle == NULL) + return (0); + fgets(pass, size, pwdhandle); + fclose(pwdhandle); + + return (1); +} + +/* write the crypted password to the passwd-temp file */ +int +write_pass(char *cpass) +{ + FILE *pwdhandle; + + umask(S_IWGRP | S_IRWXO); + /* maybe we should flock here? */ + pwdhandle = fopen(NSHPASSWD_TEMP, "w"); + if (pwdhandle == NULL) { + printf("%% Unable to write run-time crypt repository: %s\n", + strerror(errno)); + return (0); + } + fprintf(pwdhandle, "%s", cpass); + fclose(pwdhandle); + + return (1); +} + +int +gen_salt(char *salt, size_t saltlen) +{ + /* 6 is a rounds value like from localcipher option of login.conf */ + strlcpy(salt, "1234567", saltlen); + return 1; +} + +/* + * enable privileged mode + */ +int +enable(int argc, char **argv) +{ + char *p, *cpass; + char salt[_PASSWORD_LEN]; + char pass[_PASSWORD_LEN + 1]; + + switch (argc) { + + case 1: + if (priv == 1) + return 0; + + /* try to read pass */ + if (!(read_pass(pass, sizeof(pass)))) { + if (errno == ENOENT) { + /* no password file, so enable */ + priv = 1; + return 1; + } else { + /* cant read password file */ + printf("%% Unable to read password: %s\n", + strerror(errno)); + return 0; + } + } + p = getpass("Password:"); + if (p == NULL || *p == '\0') + return 0; + + if (strcmp(pass, pass) == 0) { + priv = 1; + return 1; + } else { + printf("%% Password incorrect\n"); + return 0; + } + + case 2: + if (argv[1][0] == '?') { + /* print help */ + printf("%% enable\t\t\t\tenable privileged mode\n"); + printf("%% enable ?\t\t\t\tShow Options\n"); + printf("%% enable secret \t\tSet password" + "(plaintext)\n"); + printf("%% enable secret \t\tSet" + " password(ciphertext)\n"); + return 1; + } else { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + case 3: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[1]); + return 0; + } + + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* crypt plaintext and save as pass */ + strlcpy(pass, argv[2], sizeof(pass)); + return(write_pass(pass)); + + case 4: + if (!isprefix(argv[1], "secret")) { + printf("%% Invalid argument: %s\n", argv[2]); + return 0; + } + + if (!isprefix(argv[2], "blowfish")) { + printf("%% Invalid cipher: %s\n", argv[3]); + return 0; + } + + /* privileged? */ + if (priv != 1) { + printf("%% Privilege required\n"); + return 0; + } + + /* set crypted pass */ + strlcpy(pass, argv[3], sizeof(pass)); + return (write_pass(pass)); + + default: + printf("%% Too many arguments\n"); + return 0; + } + +} diff --git a/netbsd/sqlite3.c b/netbsd/sqlite3.c new file mode 100644 index 0000000..bf02668 --- /dev/null +++ b/netbsd/sqlite3.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "stringlist.h" +#include "externs.h" + +int sq3simple(char *, StringList *); + +#define QSZ 1024 /* maximum query text size */ + +int +db_create_table_rtables(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS rtables (rtable INTEGER PRIMARY KEY, name TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_nameservers(void) +{ + char query[]="CREATE TABLE IF NOT EXISTS nameservers (nameserver TEXT)"; + return(sq3simple(query, NULL)); +} + +int +db_create_table_flag_x(char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "CREATE TABLE IF NOT EXISTS %s (ctl TEXT, rtable INTEGER, flag INTEGER," + "data TEXT)", name); + return(sq3simple(query, NULL)); +} + +int +db_insert_flag_x(char *name, char *ctl, int rtableid, int flag, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO '%s' VALUES('%s', %d, %d, '%s')", + name, ctl, rtableid, flag, data); + return(sq3simple(query, NULL)); +} + +int +db_insert_rtables(int rtableid, char *name) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT INTO 'rtables' VALUES(%d, '%s')", rtableid, name); + return(sq3simple(query, NULL)); +} + +int +db_delete_rtables_rtable(int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'rtables' WHERE rtable=%d", rtableid); + return(sq3simple(query, NULL)); +} + +int +db_insert_nameserver(char *nameserver) +{ + char query[QSZ]; + + snprintf(query, QSZ, "INSERT OR REPLACE INTO 'nameservers' VALUES('%s')", + nameserver); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl(char *name, char *ctl) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND rtable=%d", name, ctl, cli_rtable); + return(sq3simple(query, NULL)); +} + +int +db_delete_flag_x_ctl_data(char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, NULL)); +} + +int +db_delete_nameservers(void) +{ + char query[QSZ]; + + snprintf(query, QSZ, "DELETE FROM 'nameservers'"); + return(sq3simple(query, NULL)); +} + +int +db_select_flag_x_ctl_data(StringList *words, char *name, char *ctl, char *data) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s' AND data='%s'", name, ctl, data); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_ctl(StringList *words, char *name, char *ctl) +{ + char query [QSZ]; + + snprintf(query, QSZ, "SELECT data FROM '%s' WHERE ctl='%s'", name, ctl); + return(sq3simple(query, words)); +} + +int +db_select_rtable_rtables(StringList *words) +{ + char query[]="SELECT rtable FROM rtables"; + return(sq3simple(query, words)); +} + +int +db_select_rtables_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable=%d", rtableid); + return(sq3simple(query,words)); +} + +int +db_select_flag_x_ctl_rtable(StringList *words, char *name, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT ctl FROM %s WHERE rtable=%d", name, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_data_ctl_rtable(StringList *words, char *name, char *ctl, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT data FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + return(sq3simple(query, words)); +} + +int +db_select_flag_x_dbflag_rtable(char *name, char *ctl, int rtableid) +{ + StringList *words; + char query[QSZ]; + int rv; + const char *errmsg = NULL; + + snprintf(query, QSZ, "SELECT flag FROM %s WHERE ctl='%s' AND rtable=%d", + name, ctl, rtableid); + words = sl_init(); + if((rv = sq3simple(query, words)) > 0) { + rv = strtonum(words->sl_str[0], INT_MIN, INT_MAX, &errmsg); + if (errmsg) { + printf("%% db_select_flag_x_dbflag_rtable %s: %s\n", + words->sl_str[0], errmsg); + rv = -1; + } + } + + sl_free(words, 1); + + return rv; +} + +int +db_select_nameservers(StringList *words) +{ + char query[]="SELECT nameserver FROM nameservers"; + return(sq3simple(query, words)); +} + +int +db_select_name_rtable(StringList *words, int rtableid) +{ + char query[QSZ]; + + snprintf(query, QSZ, "SELECT name FROM rtables WHERE rtable='%d'", rtableid); + return(sq3simple(query, words)); +} + +/* simple query execution, dump results straight into words */ +int +sq3simple(char *sql, StringList *words) +{ + sqlite3 *db; + sqlite3_stmt *stmt; + char *result, *new = NULL; + int rv, len, tlen = 0; + + if (sqlite3_open(SQ3DBFILE, &db)) { + printf("%% database file open failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) + != SQLITE_OK) { + printf("%% sqlite3_prepare_v2 failed: %s (%s)\n", + sqlite3_errmsg(db), sql); + return -1; + } + + while ((rv = sqlite3_step(stmt)) == SQLITE_ROW) { + result = (char *)sqlite3_column_text(stmt, 0); + len = strlen(result) + 1; + if ((new = malloc(len)) == NULL) { + printf("%% sq3simple: malloc failed\n"); + break; + } + tlen += len; + strlcpy(new, result, len); + sl_add(words, new); + } + sqlite3_finalize(stmt); + sqlite3_close(db); + + if (rv != SQLITE_DONE) { + printf("%% sq3simple: error: %s\n", sqlite3_errmsg(db)); + return -1; + } + return tlen; +} diff --git a/netbsd/stringlist.h b/netbsd/stringlist.h new file mode 100644 index 0000000..442657b --- /dev/null +++ b/netbsd/stringlist.h @@ -0,0 +1,51 @@ +/* From: $OpenBSD: /usr/src/usr.bin/ftp/stringlist.h,v 1.2 2002/02/16 21:27:46 millert Exp $ */ + +/* + * Copyright (c) 1994 Christos Zoulas + * 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 ``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 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. + */ + +#ifndef _STRINGLIST_H +#define _STRINGLIST_H + +#include +#include + +/* + * Simple string list + */ +typedef struct _stringlist { + char **sl_str; + size_t sl_max; + size_t sl_cur; +} StringList; + +__BEGIN_DECLS +StringList *sl_init(void); +void sl_add(StringList *, char *); +void sl_free(StringList *, int); +char *sl_find(StringList *, char *); +__END_DECLS + +#endif /* _STRINGLIST_H */ diff --git a/netbsd/sysctl.h b/netbsd/sysctl.h new file mode 100644 index 0000000..430c54a --- /dev/null +++ b/netbsd/sysctl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct ipsysctl { + char *name; + int mib[6]; + int32_t def_larg; /* default value, or 0 for on/off + * sysctls */ + int enable; /* if on/off sysctl, 0 default is enabled, 1 + * default is disabled, 2 always show ena ble + * or disable */ +}; + +struct sysctltab { + char *name; + int pf; + Menu *table; + struct ipsysctl *sysctl; +}; + +extern struct sysctltab sysctls[]; +extern struct ipsysctl ipsysctls[]; +extern struct ipsysctl ip6sysctls[]; +extern struct ipsysctl mplssysctls[]; +extern struct ipsysctl ddbsysctls[]; +extern struct ipsysctl pipexsysctls[]; +extern Menu iptab[]; +extern Menu ip6tab[]; +extern Menu mplstab[]; +extern Menu ddbtab[]; +extern Menu pipextab[]; + +#define DEFAULT_MAXDYNROUTES 4096 /* net.inet6.ip6.maxdynroutes */ +#define DEFAULT_NEIGHBORGCTHRESH 2048 /* net.inet6.ip6.neighborgcthresh */ diff --git a/netbsd/version.c b/netbsd/version.c new file mode 100644 index 0000000..c723dde --- /dev/null +++ b/netbsd/version.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "externs.h" + +int +version(int argc, char **argv) +{ + char cpubuf[1024]; + char kernver[1024]; + struct timeval tv, boottime; + struct utsname un; + size_t len; + time_t c; + uint64_t physmem; + int mib[5], pntd, weeks, days, hours, mins; + + mib[0] = CTL_HW; + mib[1] = HW_PHYSMEM64; + len = sizeof(physmem); + if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) { + printf("%% HW_PHYSMEM: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + len = sizeof(cpubuf); + if (sysctl(mib, 2, &cpubuf, &len, NULL, 0) == -1) { + printf("%% HW_MODEL: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + len = sizeof(boottime); + if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1) { + printf("%% KERN_BOOTTIME: %s\n", strerror(errno)); + return(1); + } + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + len = sizeof(kernver); + if (sysctl(mib, 2, &kernver, &len, NULL, 0) == -1) { + printf("%% KERN_VERSION: %s\n", strerror(errno)); + return(1); + } + if (uname(&un)) { + printf("%% uname: %s\n", strerror(errno)); + return(1); + } + gettimeofday(&tv, (struct timezone *)0); + c = difftime(tv.tv_sec, boottime.tv_sec); + + printf("%% NSH v%s\n", vers); + printf("Compiled %s by %s@%s\n", compiled, compiledby, compilehost); + printf("uptime: "); + pntd = 0; + weeks = c / (7 * 24 * 60 * 60); + c %= (7 * 24 * 60 * 60); + days = c / (24 * 60 * 60); + c %= (24 * 60 * 60); + hours = c / (60 * 60); + c %= (60 * 60); + mins = c / 60; + c %= 60; + if (weeks) { + printf("%d week%s", weeks, weeks == 1 ? "" : "s"); + pntd = 1; + } + if (days) { + printf("%s%d day%s", pntd ? ", " : "", days, + days == 1 ? "" : "s"); + pntd = 1; + } + if (hours) { + printf("%s%d hour%s", pntd ? ", " : "", hours, + hours == 1 ? "" : "s"); + pntd = 1; + } + if (mins) { + printf("%s%d minute%s", pntd ? ", " : "", mins, + mins == 1 ? "" : "s"); + pntd = 1; + } + if (!pntd) + printf("%d second%s", (int)c, c == 1 ? "" : "s"); + printf("\n"); + printf("system: %s/%s version %s\n", un.sysname, un.machine, + un.release); + printf("cpu: %s\n", cpubuf); + printf("memory: %ldB\n", (physmem / 1024)); + printf("kernel: %s", kernver); + return(0); +} + diff --git a/who.c b/netbsd/who.c similarity index 100% rename from who.c rename to netbsd/who.c diff --git a/nsh.cat8 b/nsh.cat8 new file mode 100644 index 0000000..8c1b1e5 --- /dev/null +++ b/nsh.cat8 @@ -0,0 +1,3370 @@ +NSH(8) BSD System Manager's Manual NSH(8) + +NNAAMMEE + nnsshh — network configuration shell + +SSYYNNOOPPSSIISS + nnsshh [--eevv] [--ii _r_c_f_i_l_e] [--cc _c_o_n_f_i_g_-_s_c_r_i_p_t_-_f_i_l_e] + +DDEESSCCRRIIPPTTIIOONN + nnsshh is a command interpreter intended for both interactive and shell + script use. nnsshh is an alternative to: ifconfig(8), sysctl(8), route(8), + and encapsulates configuration for other daemons into one place. nnsshh + provides an alternative to: netstart(8) and parts of rc(8). nnsshh has its + own command language similar to the configuration language used by many + network appliance vendors. + + nnsshh encapsulates the many available networking services and daemons that + are included in OpenBSD base, see the _S_E_E _A_L_S_O section for a complete + list. + + nnsshh is a shell to configure OpenBSD kernel's networking functions such as + routing of packets, firewalling, network address translation, rate limit‐ + ing, bandwidth queueing, LAN bridging, IP tunnelling, and encryption. + nnsshh provides simple wrappers around these functions to aid setting up a + network. The goals of this software are: + + -- Make the command syntax uniform + + -- Bring all configuration together in a single configuration file + + -- Provide a wrapper for any OpenBSD ctl utility such as ospfctl(8), + ipsecctl(8), and bgpctl(8). + + nnsshh encapsulates those configuration files, so that their native configu‐ + ration files are encapsulated within the nnsshh configuration framework. + nnsshh does not in any way obfuscate the configuration syntax that is + utilised or provided by these ctl.c based programs. nnsshh allows the ad‐ + ministrator to view and edit all configuration in one place. + + CCOOMMMMAANNDD LLIINNEE AARRGGUUMMEENNTTSS + When nnsshh is run without arguments it loads an interactive shell. + + The options are as follows: + + --vv Produce verbose output + + --cc _c_o_n_f_i_g_-_s_c_r_i_p_t_-_f_i_l_e + Execute the command(s) in the _c_o_n_f_i_g_-_s_c_r_i_p_t_-_f_i_l_e. This is typi‐ + cally used to implement scripted changes to configuration. + + --ii _r_c_f_i_l_e + Load the initial system configuration from the command(s) in the + _r_c_f_i_l_e. This is typically used to clear the configuration and + load a full nnsshh configuration script from rcfile . + + --ee Start nnsshh in a privileged mode session. This option is not in‐ + tended to be used directly. It is used internally by nnsshh while + restarting itself with root privileges when a non-root user runs + the eennaabbllee command. + + IINNTTEERRAACCTTIIVVEE FFEEAATTUURREESS + When run without any command line arguments, nnsshh presents an interactive + shell to the user. If nnsshh is run as root user then nnsshh shall start as a + privileged full functionality shell. If nnsshh is run as a non-root user + then nnsshh shall start as an unprivileged and limited functionality shell. + Privileged nnsshh shell functionality can be enabled using the eennaabbllee com‐ + mand. + + All nnsshh interactive command line modes allow basic command line editing + features from editline(7) library. The command history of the current + session is available through the up / down arrow keys. + + It is possible to repeat the commands from the command history. + + Any command can be abbreviated as long as the abbreviation is not ambigu‐ + ous. E.g. 'show running-config' can be abbreviated to 'sho run'. + + If the user enters a command that is ambiguous nnsshh warns the user with + 'Ambiguous argument' message, E.g. ambiguous command entry. + + nsh/show i + % Ambiguous argument i + + CCoommmmaanndd lliinnee ccoommpplleettiioonn + nnsshh has double command line completion for user convenience if the + command is not ambiguous double completes the command. + + E.g show all available valid commands with double tab key sequence + + + nsh(config-p)/ + ! exit ipsec ping smtp + ? flush ldap ping6 snmp + arp ftp-proxy ldp pipex ssh + bgp group motd quit sshd + bridge halt mpls rad telnet + configure help nameserver reboot tftp + ddb hostname ndp relay tftp-proxy + dhcp ifstate no resolv traceroute + disable ike nppp rip traceroute6 + dvmrp inet ntp route verbose + editing interface ospf rtable who + eigrp ip ospf6 sasync write-config + enable ip6 pf show + nsh(config-p)/ + If what is typed is ambiguous double tab presents the administrator with + the available command line options that match what has been typed thus + far. + + E.g. command line completion display for all commands begining with i + + nsh(config-p)/i + ifstate inet ip ipsec + ike interface ip6 + + CCoommmmaanndd HHiissttoorryy + Use the up arrow on most keyboards to review the previous commands en‐ + tered in the current session. The command being currently viewed can be + repeated by hitting enter. + + RReevveerrssiinngg CCoommmmaannddss + nnsshh commands can be reversed in the following ways: + + -- Any affirmative commands that do not contain eennaabbllee keyword can be + reversed with the nnoo keyword in front of the affirmative version of + the command. e.g. reverse allowing IP packet forwarding. + + nsh(config-p)/ip forwarding + nsh(config-p)/no ip forwarding + + -- Any affirmative commands that contain eennaabbllee keyword can be reversed + with ddiissaabbllee keyword. E.g reverse enabling packet filter firewall + command. + + nsh(config-p)/pf enable + %pf enabled + nsh(config-p)/pf disable + %pf disabled + + SSttaannddaarrdd PPrroommpptt vvss PPrriivviilleeggeedd PPrroommpptt vvss CCoonnffiigguurraattiioonn mmooddee PPrroommpptt + SSttaannddaarrdd PPrroommpptt The shell starts out with an unprivileged prompt which + displays as the text of the FQDN (fully qualified domain name) of the ma‐ + chine followed by a forward slash. This unprivileged prompt will allow + only basic diagnostic commands and does not allow viewing sensitive con‐ + figuration information. + + -- e.g. standard prompt of the device firewall.machine.com + + firewall.machinename.com/ + + PPrriivviilleeggeedd PPrroommpptt The privileged shell is accessed using the eennaabbllee com‐ + mand. It allows the administrator to run privileged diagnostic commands. + If external commands are enabled, external commands can be invoked by the + user in privileged mode. The privileged mode alone will not allow + changes to the system via nnsshh commands. The privileged shell is indi‐ + cated by the FQDN of the machine followed by (p) and followed by a / + + -- E.g. privileged shell prompt of the device firewall.machine.com + + firewall.machinename.com(p)/ + + CCoonnffiigguurraattiioonn MMooddee PPrroommpptt The ccoonnffiigguurree command allows the administrator + to make changes to the system configuration. This additional command is + a safeguard against accidental configuration of a system. I.e. a user + can run privileged diagnostic commands, however without configuration + mode being enabled, nnsshh will not permit any modifications to the system + configuration. + + E.g. user elevating privileges from privilege disabled, to enabled privi‐ + lege mode and finally configuration mode on a system called host‐ + name.nsh.org + + % NSH v1.1 + hostname.nsh.org/ + hostname.nsh.org/enable + hostname.nsh.org(p)/ + hostname.nsh.org(p)/configure + hostname.nsh.org(config-p)/ + + For the purposes of this manual, any examples the machine is called nnsshh + + -- E.g. standard prompt appearing in examples in this manual + + nsh/ + + -- E.g. privileged prompt appearing in examples in this manual + + nsh(p)/ + +IINNTTEERRAACCTTIIVVEE CCOOMMMMAANNDDSS + ? | hheellpp [nsh-command] + + Display available commands and options that can used in the current nnsshh + mode. The help or ? can be followed by a nnsshh command, nnsshh displays the + purpose of the specified command. + + -- E.g. display help on the rtable command + + nsh(config-p)/? rtable + % rtable: Routing table switch + + -- E.g. display help for all available commands. + + nsh(p)/help + % Commands may be abbreviated. + % Commands are: + + hostname Set system hostname + interface Modify interface parameters + rtable Routing table switch + group Modify group attributes + arp Static ARP set + ndp Static NDP set + nameserver set or remove static DNS nameservers + bridge Modify bridge parameters + show Show system information + ip Set IP networking parameters + ip6 Set IPv6 networking parameters + mpls Set MPLS network parameters + ddb Set DDB parameters + pipex Set PIPEX parameters + flush Flush system tables + enable Enable privileged mode + disable Disable privileged mode + route Add a host or network route + pf Packet filter control + ospf OSPF control + ospf6 OSPF6 control + eigrp EIGRP control + bgp BGP control + rip RIP control + ldp LDP control + relay Relay control + ipsec IPsec IKEv1 control + ike IPsec IKEv2 control + dvmrp DVMRP control + rad Router advertisement control + sasync SA synchronization control + dhcp DHCP server control + snmp SNMP server control + ldap LDAP server control + smtp SMTP server control + sshd SSH server control + ntp NTP synchronization control + nppp PPP server control + ifstate ifstate server control + ftp-proxy ftp-proxy server control + tftp-proxy tftp-proxy server control + tftp TFTP server control + resolv Resolver configuration control + motd Message of-the-day + inet Inet super-server control + ping Send IPv4 ICMP echo request + ping6 Send IPv6 ICMP echo request + traceroute Print the route to IPv4 host + traceroute6 Print the route to IPv6 host + ssh SSH connection to remote host + telnet Telnet connection to remote host + reboot Reboot the system + halt Halt the system + powerdown Power the system down + write-config Save the current configuration + verbose Set verbose diagnostics + editing Set command line editing + who Display system users + ! Invoke a subshell + ? Print help information + quit Close current connection + nsh(p)/ + + mmaannuuaall [_s_e_a_r_c_h _t_a_g] + + Display the nnsshh manual page. If a _s_e_a_r_c_h _t_a_g is specified then jump to + the first section matching this tag if one or more matching tags exist. + + hhoossttnnaammee [_h_o_s_t_n_a_m_e] + + hostname without arguments displays the current configured hostname of + the system. hostname with an argument will set hostname to the argu‐ + ment's value. + + -- e.g. set hostname to the myfirewallname.com . + + nsh(config-p)/hostname myfirewallname.com + myfirewallname.com(p)/ + + eennaabbllee + + Start a privileged shell to allow the user to run privileged commands. + If an enable secret is set, the user shall be prompted to enter the se‐ + cret to access the privileged shell. If neccessary, nnsshh then attempts to + obtain root privileges. Depending on configuration, this step may re‐ + quire the user's password or the root password to be entered. Root priv‐ + ileges will be obtained via access rules in doas.conf(5), with a fallback + to the root password. For relevant configuration examples see _S_e_c_t_i_o_n _7 + _A_l_l_o_w_i_n_g _u_s_e_r_s _t_o _r_u_n _N_S_H below. + + [no] eennaabbllee _s_e_c_r_e_t + + Set or the password that an administrator would enter to access the priv‐ + ileged shell. + + -- e.g. Set a password manually to yourpassword + + nsh(config-p)/enable secret yourpassword + + -- e.g. Set a password using a previously set encrypted password + + nsh(config-p)/enable secret blowfish $2b$10$kKSJFDd....NqIUaTCZ0= + + ddiissaabbllee + + Exit privileged mode. Useful if you have completed configuration but + still want the ability to run diagnostics in an unprivileged nnsshh shell. + + [no] rrttaabbllee [_t_a_b_l_e_-_i_d] [_n_a_m_e] + + rtable when used with a specified table-id can execute services, diagnos‐ + tic commands (ping, traceroute) and set routes under alternate routing + tables. The default OpenBSD kernel can accommodate 256 rtables. They + have a 1:1 relationship with routing domains, except that routing domain + 0 can contain multiple routing tables. In addition, routing tables ini‐ + tialized prior to their corresponding routing domain rdomain(4) , shall + be initialised with a routing domain of 0. + + -- e.g. Create a new routing table rdomain 3 create a loopback for rdo‐ + main 3. + + nsh(config-p)/interface lo3 + nsh(interface-lo3)/rdomain 3 + nsh(interface-lo3)/inet 127.0.0.1/8 + + -- configure a physical interface + + nsh(config-p)/interface em0 + nsh(interface-em0)/rdomain 3 + nsh(interface-em0)/inet 10.255.0.10/24 + + -- Once the rdomain has been initialized (by creating a loopback inside + the + rdomain) the administrator can add routes to the rtable. + + nsh(config-p)/rtable 3 customer label network3 + nsh(p-rtable 3)/route 0.0.0.0/0 10.255.0.1 + + -- One can configure any service or daemon inside that routing domain + e.g. to setup ssh in rdomain 3 + + nsh(p-rtable 3)/sshd edit + nsh(p-rtable 3)/sshd enable + + -- The rtable command also supports unprivileged mode usage to execute + diagnostic commands in the respective route domain / VRF. + + nsh(p)/disable + nsh/rtable 3 + nsh(rtable 3)/ping 10.255.0.10 + %PING 10.255.0.10 (10.255.0.10): 56 data bytes + %64 bytes from 10.255.0.10: icmp_seq=0 ttl=255 time=0.090 ms + + -- To leave the rtable menu the user can type rtable 0 to return to the + main routing table. + + nsh(p-rtable 3)/rtable 0 + nsh(p)/ + + [no] ggrroouupp [_g_r_o_u_p_-_n_a_m_e] [ccaarrppddeemmoottee] [demotion-counter] + + Modify group attributes for the group-name named group. TBC + + [no] aarrpp [_I_P_v_4_-_A_d_d_r_e_s_s] [_M_A_C_-_A_d_d_r_e_s_s] + + Set or remove a static IP address and MAC address binding for Address + Resolution Protocol. TBC + + [no] nnddpp [_I_P_v_6_-_A_d_d_r_e_s_s] [_M_A_C_-_A_d_d_r_e_s_s] [tteemmpp] [pprrooxxyy] + + Set or remove a static IPv6 address and MAC address binding for the IPv6 + Neighbour Discovery Protocol (NDP). The entry will be permanent unless + the word tteemmpp is given in the command. If the word pprrooxxyy is given, this + system will act as an ND Proxy server, responding to requests for + _I_P_v_6_-_A_d_d_r_e_s_s even though the MAC address is not its own. + + [no] bbrriiddggee [_b_r_i_d_g_e_-_n_a_m_e] + + Modify bridge configuration on the named bridge or layer 2 forwarding in‐ + terfaces such as, bridge(4), veb(4), tpmr(4). See also OpenBSD manual + pages for bridge(4), veb(4), tpmr(4) and ifconfig(8) (accessible via the + following nnsshh commands): + + !man bridge + !man ifconfig + + -- e.g. configure bridge settings on bridge1, and display bridge config‐ + uration help. + E.g show available bridge configuration commands. + + nsh(config-p)/bridge bridge100 + nsh(bridge-bridge100)/? + % Commands may be abbreviated. + % Type 'exit' at a prompt to leave bridge configuration mode. + % Bridge configuration commands are: + + description Bridge description + member Bridge member(s) + span Bridge spanning port(s) + blocknonip Block non-IP traffic forwarding on member(s) + discover Mark member(s) as discovery port(s) + learning Mark member(s) as learning port(s) + stp Enable 802.1D spanning tree protocol on member(s) + maxaddr Maximum address cache size + timeout Address cache timeout + maxage Time for 802.1D configuration to remain valid + fwddelay Time before bridge begins forwarding packets + hellotime 802.1D configuration packet broadcast interval + priority Spanning priority for all members on an 802.1D bridge + ping Send IPv4 ICMP echo request + ping6 Send IPv6 ICMP echo request + traceroute Print the route to IPv4 host + traceroute6 Print the route to IPv6 host + ssh SSH connection to remote host + telnet Telnet connection to remote host + rule Bridge layer 2 filtering rules + static Static bridge address entry + ifpriority Spanning priority of a member on an 802.1D bridge + ifcost Spanning tree path cost of a member on 802.1D bridge + link Link level options + txprio Priority in tunnel protocol headers + rxprio Source used for packet priority + vnetid Virtual interface network identifier + parent Parent interface + tunneldomain Tunnel parameters + protect Configure protected bridge domains + shutdown Shutdown bridge + show Show system information + who Display system users + verbose Set verbose diagnostics + editing Set command line editing + ! Invoke a subshell + ? Options + manual Display the NSH manual + exit Leave bridge config mode and return to global config mode + nsh(bridge-bridge100)/ + [no] mmeemmbbeerr [_i_n_t_e_r_f_a_c_e_-_n_a_m_e] + + Add a named interface as a member port to the layer 2 bridge device. Us‐ + ing the no suffix removes the named interface from the layer 2 bridge de‐ + vice. + + E.g. configure a standard bridge(4) device called bridge101 and add vlan + 101 and vether101 as member ports. + + nsh(config-p)/bridge bridge101 + nsh(bridge-bridge101)/member vether101 + nsh(bridge-bridge101)/member vlan101 + nsh(bridge-bridge101)/exit + E.g. configure a virtual ethernet bridge veb(4) device called veb101 and + add vlan 101 and vether101 as member ports. + + nsh(config-p)/bridge veb101 + nsh(bridge-veb101)/member vether101 + nsh(bridge-veb101)/member vlan101 + nsh(bridge-veb101)/exit + E.g. configure a virtual ethernet bridge veb(4) device called veb101 and + add vlan 101 and vether101 as member ports. + + nsh(config-p)/bridge tpmr101 + nsh(bridge-tpmr101)/member vether101 + nsh(bridge-tpmr101)/member vlan101 + nsh(bridge-tpmr101)/exit + Note tpmr(4) is a layer 2 mac relay and it does not have layer2 to physi‐ + cal interface mac learning capabilities it is simply a relay, its purpose + is to minimise processing when forwarding packets transparently between + two and only two interfaces on a machine. Consequentially not all bridge + configuration commands will be accepted by the system. If an unsupported + command is issued to a tpmr interface the system will display the follow‐ + ing when rejecting the configuration command + + % Inappropriate ioctl for device + [no] pprrootteecctteedd [_i_n_t_e_r_f_a_c_e_-_n_a_m_e] + + This command requires that the named interface is already a member of the + layer 2 bridge device. Add the named interface to a protected domain. + Any member ports in the same bridge in the same protected domain are iso‐ + lated from each other. No layer 2 communication is possible between + memers ports in the same port protection group. Protected domains allow + for selective port isolation and or private vlan functionality. + + E.g. enable port isolation between vether101 and vlan101 which are member + ports of the bridge veb101. + + nsh(config-p)/bridge veb101 + nsh(bridge-veb101)/protect vether101 20 + nsh(bridge-veb101)/protect vlan101 20 + nsh(bridge-veb101)/exit + [no] iipp66 [?? | ffoorrwwaarrddiinngg | mmffoorrwwaarrddiinngg | mmuullttiippaatthh | mmaaxxiiffpprreeffiixxeess | + mmaaxxiiffddeeffrroouutteerrss | mmaaxxddyynnrroouutteess] + + Configure IPv6 networking parameters, such as forwarding, multicast for‐ + warding, multipath routing, etc. + + -- e.g. list available IPv6 configuration options + + nsh(config-p)/ip6 + % Commands may be abbreviated. + % 'ip6' commands are: + forwarding Enable IPv6 Forwarding + mforwarding Enable IPv6 Multicast Forwarding + multipath Multipath routing + maxdynroutes Max IPv6 Dyn Routes + ? Help + + [no] iipp66 ffoorrwwaarrddiinngg + + Enable or disable forwarding (routing /NAT) of IPv6 packets through the + kernel. + + nsh(config-p)/ip6 forwarding + + [no] iipp66 ffoorrwwaarrddiinngg + + Enable or disable forwarding of IPv6 multicast packets through the ker‐ + nel. + + nsh(config-p)/ip6 mforwarding + + [no] iipp66 mmuullttiippaatthh + + Enable or disable multipath routing for IPv6 addresses. If multipath is + disabled, only the first selected route is used for a given destination + regardless of how many routes exist in the routing table. + + nsh(config-p)/ip6 multipath + + [no] iipp66 mmaaxxddyynnrroouutteess [_m_a_x_-_r_o_u_t_e_-_v_a_l_u_e] + + Set or disable the limit on maximum number of IPv6 routes created as a + result of incomming ICMPv6 redirects. The max-route-value can be set to + any value 0-20480 or -1. A value of 0 prevents any routes being created + as a result of incoming ICMPv6 redirects. Set to -1 to disable the + limit. The default value for maxdynroutes is 4096. + + nsh(config-p)/ip6 maxdynroutes 8192 + [no] mmppllss [?? | ttttll | mmaappttttll--iipp | mmaappttttll--iipp66] Configure MPLS (Multi Proto‐ + col Label Switching) network parameters in the kernel. + + nsh(config-p)/mpls ? + % Commands may be abbreviated. + % 'mpls' commands are: + + ttl MPLS ttl + mapttl-ip MPLS mapttl IPv4 + mapttl-ip6 MPLS mapttl IPv6 + ? Help + + [no] mmppllss ttttll [_0_-_2_5_5] + + Configure the default MPLS (Multi Protocol Label Switching) TTL (time to + live) in the kernel for MPLS shim headers of generated (not forwarded) + MPLS packets. The default value is 255. + + nsh(config-p)/mpls ttl 64 + + [no] mmppllss mmaappttttll--iipp [_0_-_1] + + Set or unset whether the kernel decrements the TTL of the IP packet + header that is encapsulated in mpls packet, when the packet is mpls label + switched (forwarded via MPLS). This is useful when diagnosing failures + in the forwarding path of an MPLS tunnel. If set to 0, the encapsulated + payload IP header TTL is not modified while passing through MPLS and the + MPLS label stack. The default value is 1. + + nsh(config-p)/mpls mapttl-ip 1 + + [no] mmppllss mmaappttttll--iipp66 [_0_-_1] + + Set or unset whether or not the kernel decrements the TTL of the IPv6 + packet header that is encapsulated in mpls packet, when the packet is + mpls label switched (forwarded via MPLS). This feature is useful when + diagnosing failures in the forwarding path of an MPLS tunnel. If set to + 0, the encapsulated payload IPv6 header TTL field is not modified while + passing through MPLS and the MPLS label stack. The default value is 0. + + nsh(config-p)/mpls mapttl-ip6 1 + + [no] ddddbb [?? | ppaanniicc | ccoonnssoollee | lloogg] + + Configure or remove kernel debug (DDB) options. + + nsh(config-p)/ddb ? + % Commands may be abbreviated. + % 'ddb' commands are: + + panic DDB panic + console DDB console + log DDB log + ? Help + + + [no] ddddbb ppaanniicc + + Enable or disable dropping the system to the kernel debugger in the event + of a system panic. By default, dropping to the ddb debugger in a system + panic is enabled. + + nsh(config-p)/ddb panic + + [no] ddddbb ccoonnssoollee + + Enable access to the kernel debugger from the console using an architec‐ + ture-dependent magic key sequence on the console or a debugger button. + When running OpenBSD with a securelevel(7) greater than 0, this feature + cannot be enabled. By default accessing the ddb debugger from the con‐ + sole is disabled. + + nsh(config-p)/ddb console + + [no] ddddbb lloogg + + Enable or disable logging the output of the kernel debugger in the kernel + message buffer. By default ddb debugger output logging to the kernel + message buffer is enabled. + + nsh(config-p)/ddb log + + [no] ppiippeexx [?? | eennaabbllee] + + Enable or disable pipex(4) processing on pppac(4) and pppx(4) interfaces. + pipex(4) handles PPP frames and forwards IP packets in-kernel. It accel‐ + erates the performance of packet forwarding, because it reduces copying + of packets between kernel and userland. By default pipex is disabled. + + nsh(config-p)/pipex enable + + ppff [?? | eennaabbllee | ddiissaabbllee | eeddiitt | cchheecckk--ccoonnffiigg | rreellooaadd] + + Control the configuration and operation of the pf (Packet Filter) fire‐ + wall. + + nsh(config-p)/pf ? + % Arguments may be abbreviated + + enable enable pf firewall + disable disable pf firewall + edit edit, test and stage firewall rules + check-config test and display staged firewall rules + reload test and apply staged firewall rules + nsh(config-p)/ + + ppff eeddiitt + + Open the default editor for the user and allow the user modify and stage + the firewall configuration. The edited ruleset is automatically vali‐ + dated by nnsshh with pfctl(8) on exiting the editor. If the user entered pf + configuration is incorrect on exiting the editor, nnsshh will display a syn‐ + tax error warning with each line number that fails the syntax check. + + E.g. warning displayed by ppff eeddiitt when the incorrect syntax is used. + + nsh(config-p)/pf edit + /var/run/pf.conf.0:15: syntax error + /var/run/pf.conf.0:17: syntax error + Note! firewall configuration changes DO NOT take effect until the ppff + rreellooaadd command is excecuted. The editor used by nnsshh can be customised to + your preferred editor using the EDITOR or VISUAL environment variables. + For packet filter configuration syntax, refer to pf.conf(5). + + nsh(p)/!man pf.conf + nsh(config-p)/pf edit + + ppff cchheecckk--ccoonnffiigg + + The ppff cchheecckk--ccoonnffiigg command uses OpenBSD pfctl(8) to validate the syntax + of the staged pf configuration. If the staged pf configuration passes + the syntax checker, the rules will be displayed in order with their rule + number. If the staged pf configuration fails the syntax checker, the + line numbers with the syntax errors will be listed. + + ppff rreellooaadd + + The ppff rreellooaadd command uses OpenBSD pfctl(8) to validate the syntax of the + staged pf configuration. If the ppff eeddiitt config passes, nnsshh commits the + new configuration atomically. In other words ppff rreellooaadd checks firewall + configuration using OpenBSD pfctl(8) and if the pf configuration passes + nnsshh commits the configuration so that it is active in the kernel. If the + user entered pf configuration is not correct. nnsshh will issue warning + listing the line numbers where the syntax is incorrect. E.g. Example + syntax warning issued by pf reload warning that there is an error in + lines 15 and 17 of the user entered pf configuration. + + nsh(config-p)/pf reload + /var/run/pf.conf.0:15: syntax error + /var/run/pf.conf.0:17: syntax error + pfctl: Syntax error in config file: pf rules not loaded + + oossppff [?? | eennaabbllee | ddiissaabbllee | eeddiitt | rreellooaadd | ffiibb | lloogg] Enable, disable + or configure ospfd(8), the OSPF (Open Shortest Path First) daemon. + + nsh(config-p)/ospf enable + + oossppff eeddiitt Edit the configuration of the OSPF daemon. The edited ruleset + is automatically validated on saving and exiting the editor. Note ospfd + configuration changes DO NOT take effect until the "ospf reload" command + is entered. The editor used by nnsshh can be customised to your preferred + editor using the EDITOR or VISUAL environment variables. For OSPF con‐ + figuration syntax, refer to ospfd.conf(5). + + nsh(p)/!man ospfd.conf + nsh(config-p)/ospf edit + + oossppff rreellooaadd Reread and apply the OSPF configuration. + + nsh(config-p)/ospf reload + + oossppff ffiibb [?? | ccoouuppllee | ddeeccoouuppllee | rreellooaadd] + + Configure whether or not ospfd(8) updates the forwarding information base + (the active kernel routing tables). this is an active control not a per‐ + sistent configuration setting. See "fib-update" in ospfd.conf(5) for + more information. The decouple feature is useful for monitoring OSPF + networks without affecting the routing table of the system. OSPF decou‐ + ple should only be done where there is only one link between the system + and the rest of the OSPF network. The ospf fib reload command re fetches + and relearns the routes in the FIB and passes them to the ospfd daemon + for processing. + + nsh(config-p)/ospf fib decouple + + oossppff lloogg [?? | vveerrbboossee | bbrriieeff] + + Configure the detail level of ospfd(8) logging messages. Set ospf log + verbose to enable detailed debug log output from ospfd. set ospf log + brief to disable detailed debug log output from ospfd. + + nsh(config-p)/ospf log verbose + + eeiiggrrpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [ooppttiioonnss] + + Enable or disable or configure the eigrpd(8) Enhanced Interior Gateway + Routing Protocol daemon. The configuration of eeiiggrrpp daemon can be edited + with eeddiitt command, the configuration syntax of eeiiggrrpp daemon is documented + in eigrpd.conf(5) manual page. Thre are a number of ooppttiioonnss that can be + used to control the operation of eigrpd(8) daemon, these options are doc‐ + umented in the eigrpctl(8) manual page. + + bbggpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [ooppttiioonnss] + + Enable or disable or configure bgpd(8), the Border Gateway Protocol dae‐ + mon. Configuration of the bbggpp daemon can be edited with eeddiitt command, + the syntax is documented in bgpd.conf(5). Thre are a number of ooppttiioonnss + that can be used to control the operation of bgpd(8), documented in + bgpctl(8). + + rriipp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [ooppttiioonnss] + + Enable or disable or configure the ripd(8) Routing Information Protocol + daemon. The configuration of rriipp daemon can be edited with eeddiitt command, + the configuration syntax is documented in ripd.conf(5). Thre are a num‐ + ber of ooppttiioonnss that can be used to control the operation of ripd(8) dae‐ + mon, these options are documented in ripctl(8). + + llddpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [ooppttiioonnss] + + Enable or disable or configure the ldpd(8) Label Distribution Protocol + daemon. The configuration of llddpp daemon can be edited with eeddiitt command, + the configuration syntax of llddpp daemon is documented in ldpd.conf(5). + Thre are a number of ooppttiioonnss that can be used to control the operation of + ldpd(8) daemon, these options are documented in ldpctl(8). + + rreellaayy [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [ooppttiioonnss] + + Enable or disable or configure the relayd(8), a load balancer and TLS + termination daemon. The configuration of rreellaayy daemon can be edited with + eeddiitt command, the syntax is documented in relayd.conf(5). There are a + number of ooppttiioonnss that can be used to control the operation of relayd(8) + daemon, these options are documented in relayctl(8). + + iippsseecc [?? | eennaabbllee | ddiissaabbllee | eeddiitt | rreellooaadd] + + Enable or disable or configure the isakmpd(8) Internet Key Exchange ver‐ + sion 1 IKEv1 ISAKMP / Oakley daemon. The configuration of iippsseecc daemon + can be edited with eeddiitt command, the configuration syntax of iippsseecc daemon + is documented in isakmpd.conf(5) and ipsec.conf(5). + + iikkee [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [_o_p_t_i_o_n_s] + + Enable or disable or configure the iked(8) Internet Key Exchange version + 2 IKEv2 daemon. The configuration of iikkee daemon can be edited with eeddiitt + command, the configuration syntax of iikkee daemon is documented in + iked.conf(5). _o_p_t_i_o_n_s to control the iked(8) daemon in a similar manner + to ikectl(8) i.e to force ike daemon to run in active mode or passive + mode, or reload the the daemon configuration. These features are docu‐ + mented in ikectl(8). + + ddvvmmrrpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the dvmrpd(8) Distance Vector Multicast + Routing Protocol daemon. The configuration of ddvvmmrrpp daemon can be edited + with eeddiitt command, the configuration syntax of ddvvmmrrpp daemon is documented + in dvmrpd.conf(5) manual page. + + rraadd [?? | eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the rad(8) Router Advertisement daemon for + IPv6. The configuration of rraadd daemon can be edited with eeddiitt command, + the syntax is documented in rad.conf(5). + + ssaassyynncc [?? | eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the sasyncd(8) IPSec Security Association + synchronisation daemon for failover gateways. The configuration of + ssaassyynncc daemon can be edited with eeddiitt command, the configuration syntax + of ssaassyynncc daemon is documented in sasyncd.conf(5). + + nsh(config-p)/sasync + % Arguments may be abbreviated + + enable enable sasyncd service + disable disable sasyncd service + edit edit,test and stage sasyncd config + + ddhhccpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt | rreessttaarrtt] + + Enable, disable, configure, or restart the dhcpd(8) Dynamic Host Configu‐ + ration Protocol daemon. This daemon acts as a DHCP server. The configu‐ + ration of ddhhccpp daemon can be edited with eeddiitt command, the configuration + syntax of ddhhccpp daemon is documented in dhcpd.conf(5). Configuration file + changes will not take effect until dhcpd(8) is restarted. + + ssnnmmpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt | ttrraapp] [_o_p_t_i_o_n_s] + + Enable or disable or configure the snmpd(8) Lightweight Directory Access + Protocol daemon. The configuration of ssnnmmpp daemon can be edited with + eeddiitt command, the configuration syntax of ssnnmmpp daemon is documented in + snmpd.conf(5). + + llddaapp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [_o_p_t_i_o_n_s] + + Enable or disable or configure the ldapd(8) Lightweight Directory Access + Protocol daemon. The configuration of llddaapp daemon can be edited with + eeddiitt command, the configuration syntax of llddaapp daemon is documented in + ldapd.conf(5). _o_p_t_i_o_n_s to control the ldapd(8) daemon in a similar man‐ + ner to ldapctl(8) e.g. to set log verbose vs brief or to compact / re-in‐ + dex the LDAP database are documented in ldapctl(8). + + ssmmttpp [?? | eennaabbllee | ddiissaabbllee | eeddiitt] [options] + + Enable or disable or configure the smtpd(8) OpenSMTPD Simple Mail Trans‐ + fer Protocol daemon. The configuration of ssmmttpp daemon can be edited with + eeddiitt command, the configuration syntax of ssmmttpp daemon is documented in + smtpd.conf(5) manual page. + + _o_p_t_i_o_n_s to control smtpd(8) in a similar manner to smtpctl(8) i.e pausing + / resuming mta (mail transfer agents) / mda (mail delivery agents) are + documented in smtpctl(8). + + sssshhdd [?? | eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the sshd(8) OpenSSH secure shell daemon. + The configuration of sssshhdd daemon can be edited with eeddiitt command, the + syntax is documented in sshd_config(5). + + nnttpp [eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the ntpd(8) Open network time protocol + daemon. The configuration of nnttpp daemon can be edited with eeddiitt command, + the syntax is documented in ntpd.conf(5). + + nnpppppp [?? | eennaabbllee | ddiissaabbllee | sseessssiioonn | mmoonniittoorr | eeddiitt] [cclleeaarr _? | _a_l_l | + _p_p_p_-_i_d | _a_d_d_r_e_s_s | _i_n_t_e_r_f_a_c_e | _p_r_o_t_o_c_o_l | _r_e_a_l_m | _u_s_e_r_n_a_m_e] [sseessssiioonn _? + _|_a_l_l | _b_r_i_e_f | _p_a_c_k_e_t_s] [mmoonniittoorr _? | _a_l_l | _p_p_p_-_i_d | _a_d_d_r_e_s_s | _i_n_t_e_r_f_a_c_e | + _p_r_o_t_o_c_o_l | _r_e_a_l_m | _u_s_e_r_n_a_m_e] + + Enable or disable or configure the npppd(8) new Point-to-Point Protocol + daemon. The nnpppppp daemon supports termination of PPPoE, PPTP and L2TP PPP + tunnels. npppd(8) works with pipex(4) for improved throughput through + the ppp tunnels. + + The configuration of nnpppppp daemon can be edited with eeddiitt command, the + syntax is documented in npppd.conf(5). + + iiffssttaattee [eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the ifstated(8) interface state daemon. + The configuration of iiffssttaattee daemon can be edited with eeddiitt command, the + syntax is documented in ifstated.conf(5). + + ffttpp--pprrooxxyy [eennaabbllee | ddiissaabbllee] Activate or deactivate the local ftp proxy + on the system. ftp-proxy in order to function properly requires pf to be + enabled on the system. nnsshh starts ftp-proxy on 127.0.0.1 (rdomain 0) by + default. Redirect rules in pf must be used to direct outside traffic + from any rdomain to the local tftp daemon. + + -- e.g. enable ftp-proxy + + nsh(config-p)/ftp-proxy enable + + ttffttpp--pprrooxxyy [eennaabbllee | ddiissaabbllee] + + Activate or deactivate the local tftp proxy on the system. tftp-proxy in + order to function properly requires pf to be enabled on the system. nnsshh + starts tftp-proxy on 127.0.0.1 (domain 0), port 6969 by default. Redi‐ + rect rules in pf must be used to direct outside traffic from any rdomain + to the local tftp proxy. + + -- e.g. enable tftp-proxy and redirects needed to use it. + + nsh(config-p)/tftp-proxy enable + + -- Add firewall rule in pf to divert tftp requests to tftp proxy + + nsh(config-p)/pf edit + + pass in quick on $int_if inet proto udp from $lan to port tftp + divert-to 127.0.0.1 port 6969 + pass out quick on $ext_if inet proto udp from $lan to port tftp + group proxy divert-reply + + ttffttpp [eennaabbllee | ddiissaabbllee] + + Enable or disable the tftp daemon. nnsshh starts tftpd on 127.0.0.1, port + 69 by default. + + rreessoollvv [eennaabbllee | ddiissaabbllee] + + Enable or disable resolvd(8). resolvd(8) is enabled by default and is + required to learn DNS information over DHCP and IPv6 RA. If resolvd(8) + is disabled then the resolv.conf(5) file must be maintained manually. + + [no] nnaammeesseerrvveerr _I_P_-_a_d_d_r_e_s_s_1 [_I_P_-_a_d_d_r_e_s_s_2 _._._. _I_P_-_a_d_d_r_e_s_s_5] + + Configure static DNS name resolution servers used by the system. Up to 5 + IPv4 and/or IPv6. _I_P_-_a_d_d_r_e_s_s arguments can be specified, which will then + be added to resolv.conf(5) via resolvd(8). + + The nnoo nnaammeesseerrvveerr command removes any previously configured static DNS + servers. + + The nnaammeesseerrvveerr command requires resolvd(8) to be enabled. DNS servers + learned via DHCP or IPv6 RA are not affected by the nnaammeesseerrvveerr command. + + iinneett [eennaabbllee | ddiissaabbllee | eeddiitt] + + Enable or disable or configure the inetd(8) inet superserver daemon. The + configuration of inet daemon can be edited with eeddiitt command, the syntax + is documented in inetd.conf(8). + + ppiinngg [options] _h_o_s_t + + Send ICMP ECHO_REQUEST packets to an IPv4 network _h_o_s_t, specified by name + or IPv4 address. The _o_p_t_i_o_n_s are documented in the ping(8). + + ppiinngg66 [options] _h_o_s_t + + Send ICMP ECHO_REQUEST packets to an IPv6 network _h_o_s_t, specified by name + or IPv6 address. The _o_p_t_i_o_n_s are documented in the ping6(8) manual page. + + ttrraacceerroouuttee [options] _h_o_s_t + + Trace and print the route packets take to an IPv4 network _h_o_s_t, specified + by name or IP address. The _o_p_t_i_o_n_s are documented in traceroute(8). + + ttrraacceerroouuttee66 [options] _h_o_s_t + + Trace and print the route packets take to an IPv6 network _h_o_s_t, specified + by name or IP address. The _o_p_t_i_o_n_s are documented in traceroute6(8). + + sssshh [_o_p_t_i_o_n_s] [--pp _p_o_r_t] _h_o_s_t + + Open a OpenSSH ssh(1) session to the remote system _h_o_s_t, specified by + name or IP address. The _p_o_r_t is the TCP port on the remote host which + you wish to connect. The _o_p_t_i_o_n_s are documented in ssh(1). + + tteellnneett [_o_p_t_i_o_n_s] [_h_o_s_t] [port] + + Open a telnet(1) session to the given TCP _p_o_r_t on the remote server _h_o_s_t, + specified by name or IP address. If the port is not specified the IANA + assigned port 23 for telnet will be used. The _o_p_t_i_o_n_s are documented in + telnet(1). + + ccrroonnttaabb [eeddiitt | iinnssttaallll] + + Edit the configuration of scheduled background jobs which are managed by + cron(8). Only the crontab file of the root user can be edited. See the + crontab(5) man page for information about configuration file syntax. + + nnsshh stores a private copy of the root user's crontab in + _/_v_a_r_/_r_u_n_/_c_r_o_n_t_a_b_._0. The ccrroonnttaabb eeddiitt command edits this file and then + installs it to the system by running the crontab(1) command. + + The ccrroonnttaabb iinnssttaallll command skips editing but otherwise has the same ef‐ + fect. This command can be used to overwrite the system crontab in case + it has become out of sync with the copy managed by nnsshh. + + sscchheedduulleerr [eeddiitt | iinnssttaallll] + + The sscchheedduulleerr command is an alias for the ccrroonnttaabb command described + above. + + rreebboooott + + Restart the system. Requires nnsshh to be in privileged mode and requires + root user privileges. + + -- E.g. restart the system + + nsh(config-p)/reboot + % Reboot initiated + + hhaalltt Shut down the system. The system will halt and then wait for a key + to be pressed on the console before rebooting. Requires nnsshh to be in + privileged mode and requires root user privileges. + + -- e.g. shutdown the system + + nsh(p)/halt + % Shutdown initiated + + ppoowweerrddoowwnn Shut down the system and then turn off power. Restarting the + system will require access to the power-on button. Requires nnsshh to be in + privileged mode and requires root user privileges. + + -- e.g. power the system down + + nsh(p)/powerdown + % Shutdown initiated + + wwrriittee--ccoonnffiigg + + Save the running configuration to the permanent configuration space. On + the next startup of the system, this saved configuration is used. + + -- e.g. save the configuration on the system + + nsh(p)/write-config + % Configuration saved + + [no] vveerrbboossee + + Verbose mode sets nnsshh to display extra information on entered commands. + It is useful during a diagnostic and troubleshooting session. + + -- E.g. enable verbose output + + nsh/verbose + % Diagnostic mode enabled + + -- If you do not wish to have the extra information displayed, you may + disable verbose mode. + + nsh/no verbose + % Diagnostic mode disabled + sshhooww [hostname | interface | autoconf | ip | inet | inet6 | route | + route6 | sadb | arp | ndp | vlan | kernel | bgp | ospf | ospf6 | pf | + eigrp | rip | ldp | ike | ipsec | dvmrp | relay | dhcp | smtp | ldap | + monitor | version | users | crontab | running-config | startup-config |? + | help] + + The main diagnostic and informational command is 'show'. show without + arguments displays the available diagnostic show sub commands. + + -- E.g using show and its built in help + + nsh(p)/show + % Commands may be abbreviated. + % 'show' commands are: + + hostname Router hostname + interface Interface config + autoconf IPv4/IPv6 autoconf state + ip IP address information + inet IPv4 address information + inet6 IPv6 address information + route IPv4 route table or route lookup + route6 IPv6 route table or route lookup + sadb Security Association Database + arp ARP table + ndp NDP table + vlan 802.1Q/802.1ad VLANs + bridge Ethernet bridges + kernel Kernel statistics + bgp BGP information + ospf OSPF information + ospf6 OSPF6 information + pf Packet Filter firewall information + eigrp EIGRP information + rip RIP information + ldp LDP information + ike IKE information + ipsec IPsec information + dvmrp DVMRP information + relay Relay server + dhcp DHCP server + smtp SMTP server + ldap LDAP server + monitor Monitor routing/arp table changes + version Software information + users System users + crontab Scheduled background jobs + running-config Operating configuration + startup-config Startup configuration + ? Options + nsh(p)/ + + sshhooww hhoossttnnaammee + + Display the system's currently assigned hostname. + + -- e.g. display the name of the device + + nsh(p)/show hostname + % devicename.com + + sshhooww iinntteerrffaaccee [_i_n_t_e_r_f_a_c_e_-_n_a_m_e] [ssttaattuuss] + + Display essential information about the system network interfaces includ‐ + ing any network bridges / switches. show interface without any arguments + displays information about all interfaces available on the system. The + ssttaattuuss keyword shows a useful summary (including the Name, Admin Status, + Link state, and Media type) of each hardware and other configured network + interfaces on the system. + + show interface _i_n_t_e_r_f_a_c_e_-_n_a_m_e Display information about a specific inter‐ + face. + + -- e.g. display information about the loopback interface. + + nsh/show interface lo0 + % lo0 + Interface is up (last change 22:07:02), protocol is up + Interface type Loopback + Internet address ::1/128, fe80::1%lo0/64, 127.0.0.1/8 + rdomain 0, MTU 32768 bytes + 4 packets input, 160 bytes, 0 errors, 0 drops + 4 packets output, 160 bytes, 0 errors, 0 unsupported + + -- "Interface is up" means that the interface is turned on in software. + "Protocol is up" means that the interface is configured and ready to + run. The "Interface type" explains what the interface is used for on + the system. Some interfaces are not intended to pass traffic for + network users, and instead handle internal functions on the system. + See ifconfig(8) for more information on interface types supported by + OpenBSD. + + -- "Internet address" shows the IPv4 and IPv6 addresses configured for + the interface, if any. IPv6 addresses with a % sign are "link-local" + and not valid outside of the context of the interface name specified. + MTU describes the Maximum Transmission Unit, the largest size of a + packet which the kernel can transmit on this interface. + + -- The statistics show the number of packets, bytes, errors, and dropped + packets in both incoming and outgoing directions. The average in‐ + put/output sizes describe the median size of packets going in and out + the interface. Note that the total bytes in and/or out may not be + accurate. OpenBSD uses an unsigned long type to hold the byte count. + When the byte count exceeds the storage limit of an unsigned long + (4,294,967,295 on a 32 bit architecture or 18,446,744,073,709,551,615 + on a 64-bit architecture), the counter will overflow, causing it to + roll over to 0. The average packet size is inaccurate when the total + byte count rolls over, because the total number of packets reflects + bytes that are no longer counted. + + -- With verbose mode enabled, 'show interface' displays the raw kernel + flags for an interface. See ifmedia(4) for an explanation of these + flags. + + + nsh(p)/show interface lo0 + % lo0 + Interface is up (last change 22:13:28), protocol is up + Interface type Loopback + Internet address ::1/128, fe80::1%lo0/64, 127.0.0.1/8 + rdomain 0, MTU 32768 bytes + 4 packets input, 160 bytes, 0 errors, 0 drops + 4 packets output, 160 bytes, 0 errors, 0 unsupported + Flags: + + Hardware features: + + + -- With a bridge, verbose mode displays spanning tree member states and + bridge members. + + nsh/show int bridge0 + % bridge0 + Bridge is up (last change 00:00:21), protocol is up + Interface type Ethernet Bridge + 0 packets input, 0 bytes, 0 errors, 0 drops + 0 packets output, 0 bytes, 0 errors, 0 unsupported + Flags: + + STP member state: + sis0: listening + + + -- With an IEEE 802.11 wireless interface, verbose mode displays the + network ID, network key, and power-saving mode (if enabled). + + nsh/show int athn0 + % athn0 + BLah blah + IEEE 802.11 + network id blah + network key blah + powersaving (111 ms) + + + -- With an interface that supports media commands, including Ethernet + and IEEE 802.11 wireless interfaces, verbose mode displays which me‐ + dia types are available. + + nsh/show int sis0 + % sis0 + Supported media types: + media none + media 10baseT + media 10baseT, mediaopt full-duplex + media 100baseTX + media 100baseTX, mediaopt full-duplex + media autoselect + + e.g. briefly list the status of all interfaces on the system. + + nsh(p)/show interface status + % Name Status Link Media + lo0 up - + em0 up active Ethernet 1000baseT full-duplex + enc0 down active + pflog0 up - + tpmr1 up active + vether1 up active Ethernet + vether2 up active Ethernet + vether10 up active Ethernet + vether11 up active Ethernet + bridge101 up - + vether20 up active Ethernet + vether21 up active Ethernet + veb201 up - + nsh(p)/ + + sshhooww aauuttooccoonnff + + Display the interfaces on the system that are dynamically configured and + the current state and configured settings such as IP addresses, routes + nameservers and the server that the system recieved the autoconf settings + from. + + e.g. list current autoconfiguration state of the system. + + nsh(p)/show autoconf + em0 [Bound] + inet 10.0.2.15 netmask 255.255.255.0 + default gateway 10.0.2.2 + nameservers 10.0.0.1 192.168.0.1 + lease 17 hours + dhcp server 10.0.2.2 + + sshhooww [ip | inet | inet6] + + Display the IP addresses on all interfaces, their respective rdomains and + where the ip address was configured from on the system including: + + -- static + + -- dhcp + + -- ppp + + -- link-local + + E.g show all ipv4 and IPv6 adddresses on the system + + nsh(p)/show ip + Address Interface RDomain Type + 10.0.2.15 em0 0 dhcp + 10.10.10.10 em1 200 static + 127.0.0.1 lo0 0 static + 127.0.0.1 lo0 200 static + ::1 lo0 0 static + ::1 lo200 200 static + fe80:4::1 lo0 0 link-local + nsh(p)/ + E.g. show only IPv4 addresses on the system. + + nsh(config-p)/show inet + Address Interface RDomain Type + 10.0.2.15 em0 0 dhcp + 10.10.10.10 em1 200 static + 127.0.0.1 lo0 0 static + 127.0.0.1 lo200 200 static + E.g. show only IPv6 addresses on the system. + + sh(config-p)/show inet6 + Address Interface RDomain Type + ::1 lo0 0 static + ::1 lo200 200 static + fe80:4::1 lo0 0 link-local + + sshhooww rroouuttee + + Display a dump of the kernel's IPv4 routing table, including ARP entries. + + e.g. display contents of the IPv4 routing table. + + nsh/show route + Flags: U - up, G - gateway, H - host, L - link layer, R - reject (unreachable), + D - dynamic, S - static + + % IPv4 routing table: + + Destination Gateway Flags Refs Packets Mtu Interface + 0.0.0.0/0 172.20.1.1 UGS 3 57502 - sis0 + 127.0.0.0/8 127.0.0.1 UGRS 0 0 33224 lo0 + 127.0.0.1 127.0.0.1 UH 2 12 33224 lo0 + 172.20.1.0/24 link#1 U 0 0 - sis0 + 172.20.1.1 8:0:20:71:22:e7 UHL 1 0 - sis0 + 172.20.1.2 127.0.0.1 UGHS 0 0 33224 lo0 + 172.20.1.23 link#1 UHL 1 1764 - sis0 + 172.20.1.255 link#1 UHL 2 1555 - sis0 + 224.0.0.0/4 127.0.0.1 URS 0 0 33224 lo0 + + -- The destination column is simply the destination network which the + route describes. The gateway is the next hop for this route to pass + through. Gateways which are described as 'link#' are local area net‐ + works or members of local area networks. + + -- The flags are useful to determine if the kernel is using a particular + route or not. + + -- U - up + This route is active G - gateway + The destination of this route is behind a gateway (next hop). H - + host + This route describes a host on the local network. L - link layer + The destination has been or needs to be discovered through a layer + 2 protocol R - reject + This route is unreachable, and therefore marked unusable in the + kernel D - dynamic + This is a dynamic route which has is managed through routing soft‐ + ware on + the local system (such as ripd, ospfd or bgpd) S - static + This is a static route set by a user + + sshhooww rroouuttee66 + + Display a dump of the kernel's IPv6 routing table, including neighbour + entries. + + e.g. display contents of the IPv6 routing table. + + nsh(p)/show route6 + Flags: U - up, G - gateway, H - host, L - link layer, R - reject (unreachable), + D - dynamic, S - static, T - MPLS, c - CLONED, l - LOCAL + + % IPv6: + Destination Gateway Flags Refs Use Mtu Interface + ::/96 ::1 UGRS 0 0 32768 lo0 + ::1 ::1 UH 10 20 32768 lo0 + ::ffff:0.0.0.0/96 ::1 UGRS 0 0 32768 lo0 + 2002::/24 ::1 UGRS 0 0 32768 lo0 + 2002:7f00::/24 ::1 UGRS 0 0 32768 lo0 + 2002:e000::/20 ::1 UGRS 0 0 32768 lo0 + 2002:ff00::/24 ::1 UGRS 0 0 32768 lo0 + fe80::/10 ::1 UGRS 0 0 32768 lo0 + fec0::/10 ::1 UGRS 0 0 32768 lo0 + fe80::1%lo0 fe80::1%lo0 UH 0 0 32768 lo0 + ff01::/16 ::1 UGRS 0 0 32768 lo0 + ff01::%lo0/32 fe80::1%lo0 U 0 1 32768 lo0 + ff02::/16 ::1 UGRS 0 0 32768 lo0 + ff02::%lo0/32 fe80::1%lo0 U 0 1 32768 lo0 + nsh(p)/ + + sshhooww ssaaddbb + + Display the IPSEC security association database of the system. + + sshhooww aarrpp + + Display Address Resolution Protocol table of the system, listing IPv4 to + layer2 mac-address entries, the interfaces they were learned on and the + expiry of each interfaces. Locally configured IPv4 addresses appear as + permanent arp entries. + + e.g. display contents of the arp table. + + nsh(p)/show arp + Host Ethernet Address Netif Expire Flags + 10.0.2.2 52:54:00:12:35:02 em0 2m14s + 10.0.2.15 08:00:27:bd:cb:77 em0 permanent l + nsh(p)/ + + sshhooww nnddpp + + Display Neighbour Discovery Protocol NDP table. Neighbour Discovery Pro‐ + tocol database of the system, listing IPv6 to layer2 mac-address entries, + the interfaces they were learned on and the expiry of each interfaces. + Locally configured IPv6 addresses appear as permanent ndp entries. + + e.g. display contents of the ndp table. + + nsh(p)/show ndp + Neighbor Linklayer Address Netif Expire S Flags + fe80::a00:27ff:febd:cb77%em0 08:00:27:bd:cb:77 em0 permanent R l + fe80::cafe:babe:beef:face%em0 52:54:00:12:35:02 em0 17m03s + nsh(p)/ + + sshhooww vvllaann [vlan-id] [ ] + + Display all virtual local area network interfaces configured on the sys‐ + tem. It Lists the following: + + -- the vlan interface name + + -- the vlan's parent interfaces + + -- the status of the interface + + -- the rdomain of the interface + + -- any layer2 forwarding device the vlan interface is a member of + + -- the vlan interface description. + List of vlans displayed can be restricted to an individual vlan if its + vlan-id is supplied as an optional argument. The vlans displayed can be + restricted to a range of vlans if the start and end vlan-id are supplied + as 2 optional consequitive arguments in ascending order. + + E.g. display all vlan interfaces on the system + + nsh(p)/show vlan + % Interface Tag Status Type RDomain Parent Bridge Description + vlan4093 4093 up 802.1Q 200 em1 - Chris-VLAN + vlan100 100 up 802.1Q 0 em1 - Stefan-VLAN + vlan200 200 up 802.1Q 200 em1 tpmr100 Tom-VLAN + nsh(p)/ + e.g. display information on all vlans with vnetid/tag of 200. + + nsh(p)/show vlan 200 + % Interface Tag Status Type RDomain Parent Bridge Description + vlan200 200 up 802.1Q 200 em1 tpmr100 Tom-VLAN + nsh(p)/ + + E.g. show vlan interfaces with vlan-ids the range 100 to 4093 + + nsh(p)/show vlan 100 4093 + % Interface Tag Status Type RDomain Parent Bridge Description + vlan4093 4093 up 802.1Q 200 em1 - Chris-VLAN + vlan200 200 up 802.1Q 200 em1 tpmr100 Tom-VLAN + + sshhooww bbrriiddggee [bridge-interface | veb-interace | tpmr-interface] + + Without specifying an argument, it displays all layer2 forwarding devices + configured on the system, and all members of each layer2 forwarding de‐ + vice, and any description of the layer2 forwarding device. Layer 2 for‐ + warding devices supported by this command include bridge(4) standard + bridge, veb(4) virtual ethernet bridge and the tpmr(4) two port mac relay + device. + + e.g. Display all layer2 forwarding devices and their member ports + + nsh(p)/show bridge + % Bridge Status Member Interfaces + bridge1 down + Description: - + bridge100 up vlan100 + Description: Tom-Smyths-Bridge + veb200 up vlan200 + Description: Chris-Cappuccios-Bridge + tpmr102 up vether1102 vether2102 + Description: dlg-bridge + nsh(p)/ + e.g. Display the information the tpmr102 layer2 forwarding device + + nsh(p)/show bridge tpmr102 + % Bridge Status Member Interfaces + tpmr102 up vether1102 vether2102 + Description: 2PortMacRelay-bridge-102 + + sshhooww kkeerrnneell [_i_p | _a_h | _e_s_p | _t_c_p | _i_c_m_p | _i_g_m_p | _i_p_c_o_m_p | _r_o_u_t_e | _c_a_r_p | + _m_b_u_f | _p_f] + + Display kernel statistics available for query. Display kernel statistics + as selected by the argument. Executing show kernel without an argument + lists all available statistics + + e.g. show available kernel statistics. + + nsh(p)/show kernel + % Arguments may be abbreviated + + show kernel ip Internet Protocol statistics + show kernel ah Authentication Header statistics + show kernel esp Encapsulated Security Payload statistics + show kernel tcp Transmission Control Protocol statistics + show kernel udp Unreliable Datagram Protocol statistics + show kernel icmp Internet Control Message Protocol statistics + show kernel igmp Internet Group Management Protocol statistics + show kernel ipcomp IP Compression statistics + show kernel route Routing statistics + show kernel carp Common Address Redundancy Protocol statistics + show kernel mbuf Packet memory buffer statistics + show kernel pf Packet Filter statistics + nsh(p)/ + + e.g. show packet filter kernel statistics + + nsh(p)/show kernel pf + % pf statistics: + Status: Enabled for 0 days 23:58:32 Debug: err + + State Table Total Rate + current entries 7 + half-open tcp 0 + searches 284973 3.3/s + inserts 836 0.0/s + removals 829 0.0/s + Counters + match 841 0.0/s + bad-offset 0 0.0/s + fragment 0 0.0/s + short 0 0.0/s + normalize 0 0.0/s + memory 0 0.0/s + bad-timestamp 0 0.0/s + congestion 0 0.0/s + ip-option 1 0.0/s + proto-cksum 0 0.0/s + state-mismatch 0 0.0/s + state-insert 0 0.0/s + state-limit 0 0.0/s + src-limit 0 0.0/s + synproxy 0 0.0/s + translate 0 0.0/s + no-route 0 0.0/s + nsh(p)/ + + sshhooww bbggpp [_a_n_n_o_u_n_c_e_d | _i_n_t_e_r_f_a_c_e_s | _n_e_x_t_h_o_p | _s_u_m_m_a_r_y | _r_i_b | _n_e_i_g_h_b_o_r | + _i_p] + + Display status for bgpd(8) Border Gateway Protocol BGPv4 dynamic routing + on this system. e.g. show bgp + + nsh(p)/show bgp + % Arguments may be abbreviated + + show bgp announced All announced networks information + show bgp interfaces Interface states information + show bgp nexthop BGP nexthop routes information + show bgp summary Neighbor session states and counters information + show bgp rib Routing Information Base information + show bgp neighbor Detailed peer information + show bgp ip IP BGP information + nsh(p)/ + + sshhooww oossppff [_f_i_b | _d_a_t_a_b_a_s_e | _i_n_t_e_r_f_a_c_e_s | _n_e_i_g_h_b_o_r | _r_i_b | _s_u_m_m_a_r_y] + + Display the state of ospfd(8) Open Shortest Path First OSPF dynamic links + state routing protocol for IPv4 on this system. + + nsh(p)/show ospf + % Arguments may be abbreviated + + show ospf fib Forward Information Base information + show ospf database Link State Database information + show ospf interfaces Interface information + show ospf neighbor Neighbor information + show ospf rib Routing Information Base information + show ospf summary Summary information + nsh(p)/ + + sshhooww oossppff66 [_f_i_b | _d_a_t_a_b_a_s_e | _i_n_t_e_r_f_a_c_e_s | _n_e_i_g_h_b_o_r | _r_i_b | _s_u_m_m_a_r_y] + + Display the state of ospf6d(8) Open Shortest Path First OSPFv3 daemon for + dynamic links state routing protocol for IPv6 on this system. + + nsh(p)/show ospf6 + % Arguments may be abbreviated + + show ospf6 fib Forward Information Base information + show ospf6 database Link State Database information + show ospf6 interfaces Interface information + show ospf6 neighbor Neighbor information + show ospf6 rib Routing Information Base information + show ospf6 summary Summary information + nsh(p)/ + + sshhooww ppff [_a_l_l | _a_n_c_h_o_r_s | _i_n_f_o | _l_a_b_e_l_s | _m_e_m_o_r_y | _q_u_e_u_e_s | _r_u_l_e_s | + _s_o_u_r_c_e_s |] + states | tables | timeouts | osfingerprint | interfaces + + Display the status of pf(4) OpenBSD Packet Filter firewall. uusseess + pfctl(8) with the -s (show) command with modifier arguments to display + various aspects the current pf status on the system. + + nsh(p)/show pf + % Arguments may be abbreviated + + show pf all all pf info except fingerprints and interfaces information + show pf anchors currently loaded anchors in main pf ruleset information + show pf info pf filter statistics, counters and tracking information + show pf labels per rule stats (bytes, packets and states) information + show pf memory current pf pool memory hard limit information + show pf queues currently loaded pf queue definition information + show pf rules active pf firewall rule information + show pf sources contents of the pf source tracking table information + show pf states contents of the pf state table information + show pf tables pf table information + show pf timeouts current pf global timeout information + show pf osfingerprint pf Operating System fingerprint information + show pf interfaces pf usable interfaces/ interface group information + nsh(p)/ + sshhooww eeiiggrrpp [_i_n_t_e_r_f_a_c_e_s | _n_e_i_g_h_b_o_r | _t_o_p_o_l_o_g_y | _t_r_a_f_f_i_c] + + Display the status of eigrpd(8) Enhanced Interior Gateway Routing Proto‐ + col (EIGRP) daemon. + + nsh(p)/show eigrp + % Arguments may be abbreviated + + show eigrp interfaces Interface information + show eigrp neighbor Neighbor information + show eigrp topology Topology information + show eigrp traffic Traffic information + nsh(p)/ + + sshhooww rriipp [_f_i_b | _i_n_t_e_r_f_a_c_e_s | _n_e_i_g_h_b_o_r | _r_i_b] + + Display the status of ripd(8) Routing Information Protocol RIP daemon for + dynamic distance vector routing protocol on this system. + + nsh(p)/show rip + % Arguments may be abbreviated + + show rip fib Forward Information Base information + show rip interfaces Interfaces information + show rip neighbor Neighbor information + show rip rib Routing Information Base information + nsh(p)/ + + sshhooww llddpp [_f_i_b | _i_n_t_e_r_f_a_c_e_s | _n_e_i_g_h_b_o_r | _l_i_b | _d_i_s_c_o_v_e_r_y | _l_2_v_p_n] + + Display information on the status of ldpd(8) Label Distribution protocol + LDP routing daemon for MPLS Multi Protocol label Switching on this sys‐ + tem. + + nsh(p)/show ldp + % Arguments may be abbreviated + + show ldp fib Forward Information Base information + show ldp interfaces Interfaces information + show ldp neighbor Neighbors information + show ldp lib Label Information Base information + show ldp discovery Adjacencies information + show ldp l2vpn Pseudowire information + nsh(p)/ + + sshhooww iikkee [_m_o_n_i_t_o_r] + + Display Information on the Internet Key Exchange IKEv2 daemon on this + system. + + sshhooww iippsseecc [_f_l_o_w_s | _s_a_d_b] + + Display IPSECurity information related to either IPSEC flows or the Secu‐ + rity Association Database on the system. + + sshhooww ddvvmmrrpp [_i_g_m_p | _i_n_t_e_r_f_a_c_e_s | _m_f_c | _n_e_i_g_h_b_o_r | _r_i_b | _s_u_m_m_a_r_y] + + Display status information from dvmrpd(8) the Distance Vector Multicast + Routing Protocol (DVMRP) daemon. + + nsh(p)/show dvmrp + % Arguments may be abbreviated + + show dvmrp igmp Internet Group Message Protocol information + show dvmrp interfaces Interfaces information + show dvmrp mfc Multicast Forwarding Cache information + show dvmrp neighbor Neighbor information + show dvmrp rib Routing Information Base information + show dvmrp summary Summary information + nsh(p)/ + rreellaayy [_h_o_s_t_s | _r_e_d_i_r_e_c_t_s | _s_t_a_t_u_s | _s_e_s_s_i_o_n_s | _s_u_m_m_a_r_y] + + Display status information from relayd(8) daemon for loadbalancing, TLS + termination and content switching. + + nsh(p)/show relay + % Arguments may be abbreviated + + show relay hosts hosts information + show relay redirects redirects information + show relay status status information + show relay sessions sessions information + show relay summary summary information + nsh(p)/ + + sshhooww ddhhccpp [_l_e_a_s_e_s] Display leases recored in the lease database as handed + out by dhcpd(8) Dynamic Host Configuration Protocol (DHCP) daemon. + + sshhooww llddaapp [_s_t_a_t_s] Display statistics from ldapd(8) Lightweight Directory + Access Protocol (LDAP) daemon. + + sshhooww mmoonniittoorr + + Start an interactive console monitor mode for the system's routing + socket. The monitor displays raw descriptions of the data passing into + the kernel's routing socket and dumps of the kernel's routing messages to + the machine. Press enter or control-C to exit this mode. + + sshhooww vveerrssiioonn + + Display basic version information about the host and about NSH, includ‐ + ing, + the system's uptime and kernel version. It also shows both the kernel + that nnsshh was compiled under, and the current kernel that nnsshh is running + under. nnsshh should always be running on a kernel that is of a similar + version to the version of the kernel/header files that nnsshh was compiled + under. This ensures that nnsshh can interact with the kernel properly (and + vice versa). + + nsh/show version + % NSH v1.1 + Compiled 03-Apr-22 06:03 by _pbuild@amd64-1.ports.openbsd.org + uptime: 1 day, 2 hours, 17 minutes + system: OpenBSD/amd64 version 7.1 + cpu: Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz + memory: 8175MB + kernel: OpenBSD 7.1 (GENERIC.MP) #459: Mon Apr 4 18:16:13 MDT 2022 + deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP + + sshhooww ccrroonnttaabb + + Display the scheduled background jobs of the root user which are managed + by cron(8). See the crontab(5) manual page for information about sched‐ + uling rules syntax. + + sshhooww sscchheedduulleerr + + Alias for the sshhooww ccrroonnttaabb command described above. + + sshhooww rruunnnniinngg--ccoonnffiigg + + Display the current running configuration on the system, including inter‐ + face and bridge configurations, routes, the system hostname, firewall + rules, and other information compiled by nnsshh. + + sshhooww ssttaarrttuupp--ccoonnffiigg + + Display the startup configuration on the system, read from nshrc, includ‐ + ing interface and bridge configuration, routes, the system hostname, + firewall rules, and other information compiled by nnsshh. + + sshhooww ddiiffff--ccoonnffiigg + + Display differences between the startup configuration and the running + configuration. This command requires root user privileges. + + sshhooww eennvviirroonnmmeenntt [_N_A_M_E] + + Display environment variables. If the _N_A_M_E of a variable is specified + then display the value of this variable. Otherwise, display all existing + environment variable names and values. + + sseetteennvv _N_A_M_E_=_V_A_L_U_E + + Set the environment variable _N_A_M_E to the specified _V_A_L_U_E If a _N_A_M_E or + _V_A_L_U_E contains whitespace then it must be quoted in double-quotes. For + example: + + nsh/setenv EDITOR=/usr/local/bin/emacs + nsh/setenv MY_VARIABLE="this value contains whitespace" + nsh/setenv "MY OTHER VARIABLE"=my-name-contains-whitespace + + Variables set with sseetteennvv are valid for the current session and will be + inherited to other programs started by nnsshh The ssaavveeeennvv command can be + used to persist variables set by sseetteennvv in the file _~_/_._n_s_h_e_n_v. + + uunnsseetteennvv _N_A_M_E + + Delete the variable _N_A_M_E from the environment. The ssaavveeeennvv command can + be used afterwards to delete the variable from _~_/_._n_s_h_e_n_v as well. + + ssaavveeeennvv + + Save variables set by the sseetteennvv command to the file _~_/_._n_s_h_e_n_v. If this + file exists and is owned by the invoking user then nnsshh will automatically + load environment variables from this file at startup. + + ssaavveeeennvv is only effective for variables set in the current nnsshh process. + While switching from non-privileged mode to privileged mode with the + eennaabbllee command a new nnsshh process will be started. Any variables set by + sseetteennvv in non-privileged mode, before eennaabbllee, may still appear in the en‐ + vironment of the privileged process. But a ssaavveeeennvv command run in the + privileged process will not save them. It is necessary to return to un‐ + privileged mode with the ddiissaabbllee command in order to save any variables + which were set in unprivileged mode. + + fflluusshh [routes | arp | ndp | line | bridge-dyn | bridge-all | bridge-rule + | pf | history |? | help] + + Clear various system tables. + + fflluusshh rroouutteess + + Clear the system routing table. + + fflluusshh aarrpp + + Clear the system arp cache and static arp table. + + fflluusshh nnddpp + + Clear the system NDP cache and static NDP table. + + fflluusshh bbrriiddggee--ddyynn _b_r_i_d_g_e_-_n_a_m_e + + Clear dynamically learned members from the named bridge. + + nsh/flush bridge-dyn bridge0 + + Delete all dynamically learned members from bridge0. Note! any members + set manually (static members) are not removed by this command. + + fflluusshh bbrriiddggee--aallll _b_r_i_d_g_e_-_n_a_m_e + + Clear dynamically and statically learned members from the named bridge. + + nsh/flush bridge-all bridge0 + + fflluusshh bbrriiddggee--rruullee _b_r_i_d_g_e_-_n_a_m_e _i_n_t_e_r_f_a_c_e_-_n_a_m_e + + Clear all rules on the named bridge on the named interface. + + nsh/flush bridge-rule bridge0 vether0 + + fflluusshh hhiissttoorryy + + Clear the command history + + [no] rroouuttee [destination] [_/_p_r_e_f_i_x_l_e_n | _n_e_t_m_a_s_k] _g_a_t_e_w_a_y [flags] + + Add or remove static routes. IPv4 addresses can be configured with pre‐ + fix length in CIDR or dotted decimal IP netmasks (e.g. 255.255.255.0) to + describe the route. The IPv6 address may only be configured with a pre‐ + fix length. This command only runs in privileged mode. + + -- e.g. setup routes on the system + + nsh(config-p)/route 192.168.0.0/16 1.2.3.4 + + -- is equivalent to: + + nsh(config-p)/route 192.168.0.0/255.255.0.0 1.2.3.4 + + -- Use the nnoo keyword to remove the specific route (if present) in the + routing table. + + nsh(config-p)/no route 192.168.0.0/16 1.2.3.4 + + -- If you do not specify a mask, nnsshh assumes you are routing a host ad‐ + dress (/32 in ipv4). + + nsh(config-p)/route 10.6.6.4 1.2.3.4 + + -- Routing flags may be defined after a route. + + nsh(config-p)/route 127.0.0.0/8 127.0.0.1 reject + + -- or + + nsh(config-p)/route ::/96 ::1 reject + + RRoouuttee FFllaaggss + Flags: bbllaacckkhhoollee | cclloonniinngg | iiffaaccee | lllliinnffoo | nnmmppaatthh | nnoossttaattiicc | pprroottoo11 + | pprroottoo22 | rreejjeecctt [mtu _m_t_u_-_b_y_t_e_s] [expire _s_e_c_o_n_d_s] + + blackhole RTF_BLACKHOLE discard packets for this route + cloning RTF_CLONING generate a new route on use + iface !RTF_GATEWAY destination is directly reachable + llinfo RTF_LLINFO translates proto addr(l3) to link addr(l2) + nompath !RTF_MPATH do not allow multiple gateways for this route + nostatic !RTF_STATIC do not save this in the static routing table + proto1 RTF_PROTO1 protocol specific flag #1 + proto2 RTF_PROTO2 protocol specific flag #2 + reject RTF_REJECT reject packets with ICMP unreachable + qquuiitt + + exit nnsshh + + [no] vveerrbboossee + + Sets verbose mode on / off. (By default verbose mode is off). Use the + nnoo keyword turn verbose mode off. + + nsh(p)/verbose + % Diagnostic mode enabled + + nsh(p)/no verbose + % Diagnostic mode disabled + + + [no] eeddiittiinngg + + Set command line editing on / off. (If defaults to on). Use the nnoo key‐ + word to turn command editing mode off. + + nsh(p)/editing + % Command line editing enabled + + nsh(p)/no editing + % Command line editing disabled + + nnsshh((pp))//!! [sshheellll--ccoommmmaanndd] _a_r_g_u_m_e_n_t_-_1 [_a_r_g_u_m_e_n_t_-_n] + + Invoke a shell or run an entered shell-command with arguments if re‐ + quired. (requires privileged mode). The active users login shell is the + shell that is invoked by this feature. This feature disabled to enhance + security. + + E.g. list files in /root + + nsh(p)/!ls /root + + helloworld.c + helloworld2.c + + nsh(p)/! + + OpenBSDshell# + + [no] iipp [aarrppttiimmeeoouutt | aarrppddoowwnn | ccaarrpp | ccaarrpp--lloogg | ccaarrpp--pprreeeemmpptt | + ffoorrwwaarrddiinngg | mmffoorrwwaarrddiinngg | mmttuu--ppaatthh--ddiisscc | mmttuu--ddiisscc--ttiimmeeoouutt | iippiipp | ggrree + | wwccccpp | eetthheerriipp | iippccoommpp | eesspp | eesspp--uuddppeennccaapp | eesspp--uuddppeennccaapp--ppoorrtt | aahh | + ssoouurrcceerroouuttee | eennccddeebbuugg | sseenndd--rreeddiirreeccttss | iiffqq--mmaaxxlleenn | ddiirreecctteedd--bbrrooaaddccaasstt + | mmuullttiippaatthh | ddeeffaauulltt--ttttll ||??] + + Modify system kernel ip processing parameters or features. (requires + privileged mode). + + All commands in this category allow the 'no' modifier to disable the op‐ + tion. + + nsh(config-p)/ip ? + % Commands may be abbreviated. + % 'ip' commands are: + + arptimeout Seconds for ARP entries to remain in cache + arpdown Seconds before resending unanswered ARP requests + carp Allow CARP + carp-log CARP Logging Priority + carp-preempt CARP Virtual Host Preemption + forwarding Enable IPv4 Forwarding + mforwarding Enable IPv4 Multicast Forwarding + mtu-path-disc Enable IPv4 MTU Path Discovery + mtu-disc-timeout Seconds that MTU entries remain in Path MTU discovery cache + ipip Allow IP-in-IP Encapsulation + gre Allow Generic Route Encapsulation + wccp Allow Web Cache Control Protocol + etherip Allow Ether-IP Encapsulation + ipcomp Allow IP Compression + esp Allow Encapsulated Security Payload + esp-udpencap Allow ESP encapsulation within UDP + esp-udpencap-port UDP port number for encapsulation + ah Allow Authentication Header + sourceroute Process Loose/Strict Source Route Options + encdebug Enable if_enc debugging + send-redirects Send ICMP redirects + ifq-maxlen IPv4 ifqueue max length + directed-broadcast Allow directed broadcasts + multipath Multipath routing + default-ttl Default IP packet TTL + ? Options + + iipp aarrppttiimmeeoouutt _s_e_c_o_n_d_s + + Sets the timeout (seconds) for ARP entries to remain in cache on this + system. + + When the system stops receiving ARP packets from the host and, the + aarrppttiimmoouutt seconds pass, the arp entries are removed from the ARP cache. + If a service or user requests to communicate with the IP address of the + removed cache entry the system requests via broadcast an ARP request. + Lower aarrppttiimmeeoouutt values increase the broadcast traffic on the underlying + network. While higher aarrppttiimmeeoouutt values increase the time it takes to + resolve a host. This setting should be the same or lower on a router + than the bridge MAC table timeout on an intermediate bridge. + + nsh(config-p)/ip arptimeout 300 + + [no] iipp aarrppddoowwnn _s_e_c_o_n_d_s + + Set or remove configured timeout (seconds) the system waits before re‐ + sending an unanswered ARP request. + + If the ARP system fails to resolve a MAC address, the system waits for iipp + aarrppddoowwnn number of seconds before retrying. + + Lower settings increases the broadcast traffic on the underlying network + while higher settings increases the time it takes to resolve a host (af‐ + ter the host boots up) and on a network that is experiencing packet loss. + + nsh(config-p)/ip arpdown 20 + + [no] iipp ccaarrpp + + Enable or disable carp(4) functionality in the system kernel. Carp is a + BSD licensed technology for router redundancy utilising a virtual ip that + floats between 2 or more routers on a LAN segment, it is similar to VRRP + or HSRP. + + nsh(config-p)/ip carp + + [no] iipp ccaarrpp--lloogg _0_-_7 + + Enable or disable logging of carp state change, bad packets and other er‐ + rors in the system kernel. carp-log may be set to a value between 0 and + 7 corresponding with standard syslog(3) priorities. The default value is + 2, which limits logging to changes in CARP state. + + nsh(config-p)/ip carp-log 7 + + [no] iipp ccaarrpp--pprreeeemmpptt + + Enable or disable the device taking master role from an existing master + carp router + + nsh(config-p)/ip carp-preempt + + [no] iipp ffoorrwwaarrddiinngg + + Enable or disable IP packet forwarding in the system kernel. This must + be set in order to use routing, NAT, IPsec or packet filter features. + + nsh(config-p)/ip forwarding + + [no] iipp iippiipp + + Enable or disable IP-in-IP encapsulation in the system kernel. + + nsh(config-p)/ip ipip + + [no] iipp ggrree + + Enable or disable Generic Route Encapsulation in the system kernel. Must + be used to enable gre(4) interfaces. + + nsh(config-p)/ip gre + + [no] iipp wwccccpp + + Enable or disable GRE-based Web Cache Control Protocol packets to manage + caching device. Must be used to enable WCCP on gre(4) interfaces. + + nsh(config-p)/ip wccp + + [no] iipp eetthheerriipp + + Enable or disable GRE-based Ether-IP encapsulation in the system kernel. + + nsh(config-p)/ip etherip + + [no] iipp iippccoommpp + + Enable or disable IPComp internet protocol compression in the system ker‐ + nel. + + nsh(config-p)/ip ipcomp + + [no] iipp eesspp + + Enable or disable IPsec Encapsulated Security Payload procesing in the + system kernel. (Enabled by default.) + + nsh(config-p)/ip esp + + [no] iipp eesspp--uuddppeennccaapp Enable or Disable processing of UDP encapsulated ESP + packets in the system kernel. (Enabled by default.) + + nsh(config-p)/ip esp-udpencap + + [no] iipp eesspp--uuddppeennccaapp--ppoorrtt _0_-_6_5_5_3_5 Sets the value of the UDP port that + triggers decapsulation for incoming UDP encapsulated ESP packets. (The + default port is 4500) udp encapsulated esp packets are useful for + traversing NAT routers. + + nsh(config-p)/ip esp-udpencap-port 4600 + + [no] iipp aahh + + Enable or disable IPsec Authentication Header processing in the system + kernel. (Enabled by default.) + + nsh(config-p)/ip ah + + [no] iipp ssoouurrcceerroouuttee + + Enable or disable processing loose or strict source routing options on IP + packet headers. Do not enable this option on systems connected to the + public internet. + + nsh(config-p)/ip sourceroute + + [no] iipp eennccddeebbuugg + + Enable or disable printing debug messages for the enc(4) interface to the + kernel output. Note! Requires a kernel compiled with ENCDEBUG option. + + nsh(config-p)/ip encdebug + + [no] iipp sseenndd--rreeddiirreeccttss + + Controls whether or not the system sends ICMP redirects to local hosts. + (Enabled by default). + + When there is a direct path on the local network from one host to an‐ + other, but one of those hosts chooses to talk through the router instead, + the system sends an ICMP redirect to the originating host. This redirect + tells the host the direct path on the network to send further packets. + + nsh(config-p)/ip send-redirects + + [no] iipp ddiirreecctteedd--bbrrooaaddccaasstt + + Enable or disable kernel forwarding of IP traffic to the broadcast ad‐ + dress of any interface on the system. This setting is useful for limit‐ + ing certain types of DoS attacks. + + [no] iipp mmuullttiippaatthh + + Enable or disable ip multicast forwarding in the system kernel. (Dis‐ + abled by default.) + + nsh(config-p)/ip mforwarding + + [no] iipp ddeeffaauulltt--ttttll _t_t_l + + Sets the default ttl used on IP packets originating from this system. + Valid ttl value is in the range 1-255. + + The TTL, or time-to-live, is decremented by one each time the packet + passes through another router on the internet. The default TTL that the + system uses is 64, therefore it allows for the packet to pass through up + to 64 routers (also called hops) before reaching its destination. The + main purpose of the TTL is to avoid routing loops in the network. + + nsh(config-p)/ip default-ttl 128 + + iipp ?? + + Displays the help menu and available ip command options. + + nsh(config-p)/ip ? + + [no] iinntteerrffaaccee [inet | ip | autoconf4 | description | group | rdomain | | + rtlabel | priority| llpriority | mtu | metric | link | arp | lladdr | + nwid | nwkey | powersave | txpower | bssid | media | mediaopt | auth | + peer | pppoe | tunnel | tunneldomain | txprio | rxprio | vnetid | + vnetflowid | parent | patch | keepalive | mplslabel | pwe | syncdev | + syncpeer | maxupd | vhid | advbase | advskew | carppass | carpdev | + carpnode | carppeer | balancing | pflow | debug | dhcrelay | wol | mpls | + inet6 | autoconf6 | autoconfprivacy | temporary | monitor | wgpeer | + wgport | wgkey | wgrtable | trunkport | trunkproto | shutdown | show | |? + | manual | exit] interface mode commands, are commands that can be ap‐ + plied to a specific named interface. + + nsh(interface-em0)/? + % Commands may be abbreviated. + % Type 'exit' at a prompt to leave interface configuration mode. + % Interface configuration commands are: + + inet IPv4/IPv6 addresses + ip Alias for the "inet" command + autoconf4 IPv4 Autoconfigurable address (DHCP) + description Interface description + group Interface group + rdomain Interface routing domain + rtlabel Interface route labels + priority Data packet priority + llpriority Link Level packet priority + mtu Maximum Transmission Unit + metric Routing metric + link Link level options + arp Address Resolution Protocol + staticarp Always use static ARP to find other hosts + lladdr Link Level (MAC) Address + nwid 802.11 network ID + nwkey 802.11 network key + powersave 802.11 powersaving mode + txpower 802.11 transmit power + bssid 802.11 bss id + media Media type + mediaopt Media options + auth PPP authentication + peer PPP peer authentication + pppoe PPPoE settings + tunnel Tunnel parameters + tunneldomain Tunnel routing domain for transit + txprio Priority in tunnel protocol headers + rxprio Source used for packet priority + vnetid Virtual interface network identifier + vnetflowid Use part of vnetid as flowid + parent Parent interface + patch Pair interface + ping Send IPv4 ICMP echo request + ping6 Send IPv6 ICMP echo request + traceroute Print the route to IPv4 host + traceroute6 Print the route to IPv6 host + ssh SSH connection to remote host + telnet Telnet connection to remote host + keepalive GRE tunnel keepalive + mplslabel MPLS local label + pwe MPLS PWE3 + syncdev PFsync control message interface + syncpeer PFsync peer address + maxupd PFsync max updates, defer first packet + vhid CARP virtual host ID + advbase CARP advertisement interval + advskew CARP advertisement skew + carppass CARP passphrase + carpdev CARP device + carpnode CARP additional vhid/advskew + carppeer CARP peer + balancing CARP balancing mode + pflow pflow data export + debug Driver dependent debugging + dhcrelay DHCP Relay Agent + wol Wake On LAN + mpls MPLS + inet6 IPv6 addresses + autoconf6 IPv6 Autoconfigurable address + autoconfprivacy Privacy addresses for IPv6 autoconf + temporary Temporary addresses for IPv6 autoconf + monitor Monitor mode for incoming traffic + wgpeer Wireguard peer config + wgport Wireguard UDP port + wgkey Wireguard private key + wgrtable Wireguard routing table + trunkport Add child interface(s) to trunk + trunkproto Define trunkproto + shutdown Shutdown interface + show Show system information + who Display system users + verbose Set verbose diagnostics + editing Set command line editing + ! Invoke a subshell + ? Options + manual Display the NSH manual + exit Leave interface config mode and return to global config mode + ? Options + + [no] iinneett [_a_d_d_r_e_s_s_/_p_r_e_f_i_x_-_l_e_n_g_t_h | _a_d_d_r_e_s_s_/_n_e_t_m_a_s_k] + + Adds or removes the specified IPv4 or IPv6 address on the interface. An + IPv4 address can be configured with CIDR bitlength, or classic netmask. + + nsh(interface-fxp0)/inet 192.168.100.1/24 + or + + nsh(interface-fxp0)/inet 192.168.100.1/255.255.255.0 + + An IPv6 address may be configured with a network prefix length. + + nsh(interface-lo0)/inet ::1/128 + + The command nnoo iinneett without futher arguments removes all IPv4 addresses + from the interface. The nnoo iinneett66 command (see below) may be used to re‐ + move all IPv6 addresses. + + [no] iinneett aauuttooccoonnff + + Equivalent to the aauuttooccoonnff44 command. + + [no] iinneett ddhhccpp + + Equivalent to the aauuttooccoonnff44 command. + + [no] iipp + + Equivalent to the iinneett command, for convenience. All parameters accepted + by iinneett are also accepted by iipp, including aauuttooccoonnff and ddhhccpp. + + [no] aalliiaass + + Deprecated and also equivalent to the iinneett command. + + [no] aauuttooccoonnff44 + + Enables or disables DHCP on a given (broadcast and layer2 capable) inter‐ + face. + + DHCP client notes: DHCP client mode takes control of default gateway + route. There is currently no way to control default gateway if DHCP + client is used on multiple interfaces. The first DHCP client interface + to succeed in obtaining a lease sets the default gateway. + + [no] ddeessccrriippttiioonn _t_e_x_t + + Adds or removes a descriptive label to the interface. + + nsh(interface-em0)/description Chris-WAN01-Link + + [no] ggrroouupp _g_r_o_u_p_-_n_a_m_e [another-group-name...groupname-N] + + Adds or removes a group label to the interface. The group can then be + referred to in other configuration such as the firewall pf configuration. + This is useful for grouping similar interfaces together and, can reduce + the size of your firewall rule set. An interface can be a member of mul‐ + tiple groups. + + nsh(interface-em0)/group WAN + + [no] rrddoommaaiinn _r_o_u_t_i_n_g_-_d_o_m_a_i_n_-_n_u_m_b_e_r + + Set the rdomain(4) or routing domain of an interface. Note that this + command clears all existing ip configuration on the interface. There‐ + fore, you should run this command before any configuring any other set‐ + ting on the interface. + + [no] rrttllaabbeell [_r_t_a_b_l_e_-_i_d] + + Set or remove the rtable(4) id on an interface. Each rdomain(4) can con‐ + tain multiple rtable(4) this feature allows for policy routing within + each rdomain. + + [no] pprriioorriittyy _0_-_1_5 + + Set the interface routing priority to a value in the range of 0 to 15 + with smaller numbers being better. The default priority of an interface + is 0, except for IEEE 802.11 wireless interfaces (priority 4), umb(4) in‐ + terfaces (priority 6), and carp(4) interfaces (priority 15). The default + priority of newly connected routes (routes created by configuring an IP + address on an interface) is calculated by adding 4 (RTP_CONNECTED) to the + interface priority. The default priority of new static routes added to + the kernel is calculated by adding 8 (RTP_STATIC) to the interface prior‐ + ity. + + [no] llllpprriioorriittyy _0_-_7 Sets or remove the priority for link layer communica‐ + tions on the interface to a value between 0-7 arp(8) ndp(8) bpf(4) + pppoe(4) + + nsh(interface-em0)/llpriority 7 + + [no] mmttuu _m_t_u_-_b_y_t_e_s + + Add or remove a configured Maximum Transmission Unit (MTU) on the inter‐ + face. This is the maximum packet size that the operating system is per‐ + mitted to transmit. Use the nnoo keyword to set mmttuu to reset the interface + MTU to the default value for that interface type. + + The output of 'show interface' displays a 'hardmtu' value which is the + maximum mtu value supported by the hardware and driver currently in‐ + stalled. The mtu command fails gracefully if the specified mtu exceeds + the hardmtu value of the interface. + + A larger MTU is particularly useful for underlay interfaces which encap‐ + sulated tunneled traffic traverses or for features which stack tags, such + as pppoe(4), vxlan(4), etherip(4), eoip(4), gre(4), vlan(4), QinQ, svlan + or tagging or QinQ (svlan) tagging and MPLS devices such as mpe(4), + mpip(4), and mpw(4). + + nsh(interface-vr0)/mtu 1600 + + [no] mmeettrriicc _0_-_2_1_4_7_4_8_3_6_4_7 + + Set routing metric for the interface. Using nnoo keyword before metric + sets the interface metric to the default value of zero. + + nsh(interface-fxp0)/metric 2 + + [no] lliinnkk <<00||11||22>> + + Set any of the link flags on the interface. Using nnoo keyword before lliinnkk + XXYYZZ removes the specified link flags 'XYZ'. Using nnoo keyword before lliinnkk + removes all link flags from the interface. + + nsh(interface-gre0)/no link 0 + Each different interface type uses link flags for different purposes. + + [no] aarrpp + + Enable or disable arp(8) Address Resolution Protocol ARP on the inter‐ + face. (Enabled by default.) + + nsh(interface-fxp0)/arp + nsh(interface-fxp0)/no arp + + [no] ssttaattiiccaarrpp + + Always use static ARP entries to find other hosts reachable via the in‐ + terface. (Disabled by default.) + + nsh(interface-fxp0)/staticarp + nsh(interface-fxp0)/no staticarp + + Only hosts with entries in the static ARP table will be reachable via the + interface. Static ARP entries can be configured using the aarrpp command in + the global context (not the aarrpp command in the interface context). + + When ssttaattiiccaarrpp is enabled no ARP requests will be sent out on the inter‐ + face, while responses to incoming ARP requests for the interface's own + addresses will still be sent. If ARP was previously disabled on the in‐ + terface with the nnoo aarrpp command then ARP will be automatically re-enabled + to allow outgoing ARP responses. + + [no] llllaaddddrr _m_a_c_-_a_d_d_r_e_s_s | _r_a_n_d_o_m + + Set or remove the mac address on the interface. The administrator can + specific a macadress in colon notation e.g. 00:11:22:33:44:55 or random + to request a random mac address assignment for the interface. + + nsh(interface-vether3)/lladdr random + nsh(interface-vether3)/lladdr 00:11:22:33:44:55 + + [no] nnwwiidd _n_e_t_w_o_r_k_-_i_d + + Set or remove the configured network ID for an 802.11 capable interface. + Use the nnoo keyword before the nnwwiidd to reset to the default value of a + blank network ID. + + [no] nnwwkkeeyy _k_e_y + + Set the WEP network key for an 802.11 capable interface. Use the nnoo key‐ + word before nwkey to turn off WEP. + + [no] ppoowweerrssaavvee _t_i_m_e + + Set the 802.11 powersaving mode to X ms of time. Use the nnoo keyword be‐ + fore powersave to set the powersave mode to the default powersave time. + + [no] ttxxppoowweerr _d_B_m + + Set the transmit power on an 802.11 radio network interface manually. + Power units are in dBm. Use the nnoo keyword before ttxxppoowweerr to set the ra‐ + dio transmit power to automatic. + + E.g to set the tx power of iwn0 to 10dBm simply enter the command below: + + nsh(interface-iwn0)/txpower 10 + + [no] bbssssiidd _m_a_c_-_a_d_d_r_e_s_s + + Set or remove the configured BSSID of a radio interface to a specific MAC + address, the mac-address should be entered in semi colon format e.g. + 12:34:56:78:9a:bc. + + E.g. set the bssid of radio interface iwn0 + + nsh(interface-iwn0)/bssid 12:34:56:78:90:12 + + [no] mmeeddiiaa [type] [instance] + + Set the media type of the interface. Entering media without an argument + diplays help for the media settings available for the interface. + + E.g. show media settings supported by an intel pro 1000 em(4) interface + + nsh(interface-em0)media + + %autoselect | 10baseT | 100baseTx | 1000baseT. + + E.g to set the speed of the network interface speed to 1000mb/s + + nsh(interface-em0)/media 1000baseT + Note! Enabling verbose mode and running show interface + displays all media settings supported by the network interface. + + nsh(p)/verbose + % Diagnostic mode enabled + + nsh(p)/sho int vr0 + % vr0 + Interface is up (last change 37d 12:16:02), protocol is up + Interface type Ethernet (Broadcast), hardware address 00:0d:b9:29:6b:50 + Media type autoselect (100baseTX full-duplex), status active + Internet address 100.64.0.1/24, fe80::20d:b9ff:fe29:6b50%vr0/64 + Routing Domain 0, MTU 1500 bytes (hardmtu 1740), Line Rate 100 Mbps + 187081496 packets input, 232860544316 bytes, 19 errors, 0 drops + 102231197 packets output, 21564487790 bytes, 0 errors, 3267264 unsupported + 1244 input, 210 output (average bytes/packet) + 0 collisions + Flags: + + Hardware features: + + Supported media types on vr0: + media none + media 10baseT + media 10baseT, mediaopt full-duplex + media 100baseTX + media 100baseTX, mediaopt full-duplex + media autoselect + + To force the interface to use a particular media type, + + nsh(interface-vr0)/media 10baseT + + [no] mmeeddiiaaoopptt _o_p_t_i_o_n + + Set or remove media options such as full-duplex / half-duplex. + + e.g to set vr0 interface to full-duplex mode: + + nsh(interface-vr0)/mediaopt full-duplex + + nsh(interface-vr0)/no mediaopt full-duplex + + [no] aauutthh pprroottoo _p_a_p | _c_h_a_p nnaammee _n_a_m_e_-_t_e_x_t kkeeyy _k_e_y_-_t_e_x_t + + Set or remove the PPP authentication parameters for the interface. + + [no] ppeeeerr pprroottoo _p_a_p | _c_h_a_p nnaammee _n_a_m_e_-_t_e_x_t kkeeyy _k_e_y_-_t_e_x_t [ffllaagg _c_a_l_l_i_n | + _n_o_r_e_c_h_a_l_a_n_g_e] + + Set or remove configured peer PPP authentication parameters for the in‐ + terface. + + [no] ttuunnnneell _s_o_u_r_c_e_-_i_p _d_e_s_t_i_n_a_t_i_o_n_-_i_p [ttttll _0_-_2_5_5] [df] [ecn] + + Set or remove tunnel assignments with this command. Note that tunnel as‐ + signments are only valid on gif and gre interfaces at this time. TODO + + nsh(interface-gre0)/tunnel 12.3.3.3 12.6.6.6 + + [no] ttuunnnneellddoommaaiinn [rdomain-id] + + Set or remove tunnel routing domain over which tunnel encapsulated pack‐ + ets are to be exchanged between tunnel ip endpoints. + + [no] ttxxpprriioo [_0_-_7 | _p_a_c_k_e_t | _p_a_y_l_o_a_d] + + Set or remove configured transmit priority of the headers of a tunnel in‐ + terface. Valid options are standard traffic priority values (0-7) or set + the headers according to encapsulated packet or payload priority. + + E.g. to set the priority of headers of the tunnel gre1 to match that of + the payload. + + nsh(interface-gre1)/txprio payload + + [no] rrxxpprriioo [_0_-_7 | _p_a_c_k_e_t | _p_a_y_l_o_a_d] + + Set or remove configured receive priority of the headers of a tunnel in‐ + terfaces are standard traffic priority values (0-7) or set the headers + according to encapsulated packet / payload priority). + + E.g. to set the priority of headers of tunnel gre1 manually to 7 regard‐ + less of payload: + + nsh(interface-gre1)/rxprio 7 + + [no] vvnneettiidd [0-16777215 | 1-4094] + + On a vxlan(4) interface, set or remove the 24 bit virtual network identi‐ + fier VNI tag. Virtual network identifier tags are typically used in + large multi tenant VXLAN multiple routing domain environments and have an + acceptable range of 0-16777215. + + On a vlan(4) interface, set or remove the VLAN ID in IEEE 802.1Q vlan tag + If vnetid invoked inside a vlan interface the acceptable range is the + standard 12-bit vlan id 1-4094. + + E.g. set vxlan100 vnetid to 8192. + + nsh(interface-vxlan100)/vnetid 8192 + + [no] vvnneettfflloowwiidd + + Allow or disallow the interface to use a portion of the virtual network + identifier space as a flow identifier. This allows loadbalancing of the + encapsulated traffic over multiple links. + + E.g. enable vnetflowid load balancing for gre1. + + nsh(interface-gre1)/vnetflowid + + [no] ppaarreenntt _p_a_r_e_n_t_-_i_n_t_e_r_f_a_c_e + + Set or remove the parent interface for a vlan(4) interface. + + E.g. set the parent interface of vlan1024 to em0. + + nsh(interface-vlan1024)/parent em0 + + [no] ppaattcchh _p_a_i_r_-_i_n_t_e_r_f_a_c_e_-_n_a_m_e + + Set or remove patch (layer1+ connection) between current interface and + another pair(4) interface. A patch is a CPU efficient way of forwarding + packets between two pair(4) interfaces, the forwarding mechanisim is + layer1 like a cable what is sent by one pair(4) interface is recived by + the other pair(4) interface and vice versa. Patch can only connect two + pair(4) interfaces, no other interface types are supported. + + E.g. To connect pair1 and pair2 interfaces with a virtual patch cable. + nsh(config-p)/interface pair1 + + nsh(interface-pair1)/patch pair2 + + [no] kkeeeeppaalliivvee [_p_e_r_i_o_d _c_o_u_n_t] + + Enable or disable gre / gre based interfaces sending keepalive packets + sent every period seconds. A second timer is run with a timeout of count + * period. If no keepalive response is received during that time, the + link is considered down. The minimal usable count is 2 since the round- + trip time of keepalive packets + needs to be taken into account. + + E.g. enable keepalives on interface gre1 at 1 second interval and down + count of 3. + + nsh(interface-gre1)/keepalive 1 3 + + [no] mmppllssllaabbeell [_1_6_-_1_0_2_4_5_7_5] + + Set or remove the local MPLS label to the specified mplslabel this label + on the local system shall de-encapsulated for input. (MPLS labels 0-15 + inclusive are reserved labels and cannot be used). MPLS labels are sup‐ + ported for mpe(4), mpip(4) and mpw(4) interfaces. + + E.g. set the mpls label to 10240 on interface mpe1. + + nsh(interface-mpe1)/mplslabel 10240 + + [no] ppwwee nneeiigghhbboorr [_n_e_i_g_h_b_o_r_-_l_a_b_e_l _n_e_i_g_h_b_o_r_-_i_p] + + Set or remove the configuration of the PWE3 neighbor, configured with an + MPLS neighbor label and a neighbor ip. neighbor-label can be any value + 16-1024575. neighbour-ip should be set to the ip address of the PWE3 + neighbor. + + [no] ppwwee [_c_w] + + Enable or disable the use of PWE3 Control Word. The control word is used + to facilitate fragmentation across mpls packets. This option supported + on the mpip(4) and mpw(4) interfaces. + + E.g. enable control word on an mpls pseudo wire interface mpw1. + + nsh(interface-mpw1)/pw cw + + [no] ppwwee [_f_a_t] + + Enables or disables the use of PWE flow-aware transport FAT flow label. + This option supported on the mpip(4) and mpw(4) interfaces. + + E.g. Enable flow-aware transport flow label on mpls ip interface mpip1 + + interface-mpip1)/pw fat + + [no] ssyynnccddeevv _s_y_n_c_d_e_v_-_n_a_m_e + + Configures or removes the data interface through which pfsync update mes‐ + sages are sent. Note that the pfsync protocol currently includes no au‐ + thentication method. It is advisable to layer authentication, signing + and (possibly encrypted tunnels for the underlay interfaces. For sim‐ + plicity on co-located pfsynced firewalls a secure way to use pfsync, is + through a a direct (layer1 (i.e. no switches)) cable connecting directly + between two pfsync capable devices (i.e. a conenction made with an ether‐ + net patch cable). This command is valid only for pfsync(4) interfaces. + + E.g. Set the physical interface em1 as the pfsync0 syncdev + + nsh(interface-pfsync0)/syncdev em1 + + [no] ssyynnccppeeeerr [_i_p_v_4_-_p_e_e_r_-_p_f_s_y_n_c_-_a_d_d_r_e_s_s] + + Set or remove a manually entered ip address of the pfsync interface of a + peer pf sync firewall. By default, state change messages are sent out on + the synchronisation interface using IP multicast packets to the + 224.0.0.240 group address. When syncpeer ip address is set the sync mes‐ + sages are sent via unicast to the specified ipv4-peer-pfsync-address. + This command is valid only for pfsync(4) interfaces. + + E.g. set sync messages to use unicast peer ip address 192.0.0.10 which is + reachable via syncdev interface. + + nsh(interface-pfsync0)/syncpeer 192.0.0.10 + + [no] mmaaxxuuppdd _0_-_2_5_5 [defer] + + Configures or removes the maximum number of updates which are collapsible + into one for a single state. The default value is 128. The transmission + a pfsync update packet shall be delayed by a maximum of 1 second. The + defer flag defers the first packet of each connection from being deliv‐ + ered until the state is active on pfsync peer. This command is valid + only for pfsync(4) interfaces. + + E.g. set the pfsync to aggregate the maximum number of state changes be‐ + fore sending a pfsync update message (reduce pfsync traffic updates) + + nsh(interface-pfsync0)/maxupd 255 + + E.g. set pfsync to aggregate a max of 32 state changes in one packet and + delay fowarding of new connection packets until peers pfstate is synchro‐ + nised use: + + nsh(interface-pfsync0)/maxupd 32 defer + + [no] vvhhiidd [_1_-_2_5_5] + + Configure or remove the virtual host ID for the Common Address Redundancy + CARP protocol. vhid is valid for carp(4) interfaces only. + + E.g. set virtual router host id on carp0 interface to 12. + + nsh(interface-carp0)/vhid 12 + + [no] aaddvvbbaassee [_0_-_2_5_4] + + Configure or remove the advertisement interval in seconds for the master + host to advertise itself. advbase is valid for carp(4) interfaces only. + + E.g. set the advertisement interval to 10 seconds on carp0 interface. + + nshpromot(interface-carp0)/advbase 10 + + [no] aaddvvsskkeeww _s_k_e_w + + Configure or remove the carp advertisement skew on the active carp inter‐ + face. The formula is advbase + (advskew / 255). If the master does not + advertise within three times this interval, this host assumes master role + and starts advertising as master. The device with the highest advskew + value is least likely to become master, a device with a high advskew only + becomes master if all other devices are offline. advskew is valid for + carp(4) interfaces only. + + E.g. set the advskew to 20 on carp0 interface. + + nsh(interface-carp0)/advskew 20 + + [no] ccaarrppppaassss _p_a_s_s_p_h_r_a_s_e + + Configure or remove the CARP passphrase of the active interface. The + passphrase can be up to 19 characters long and can contain special char‐ + acters. There is no passphrase by default. carpass is valid for carp(4) + interfaces only. + + E.g. Set carp0 carp passphrase to 19CharPassphrase!!! including exclama‐ + tion marks. + + nsh(interface-carp0)/carppass 19CharPassphrase!!! + + [no] ccaarrppddeevv [_i_n_t_e_r_f_a_c_e_-_n_a_m_e] + + Set or remove the interface on which the selected carp interface's carp + advertisements are sent and received. The carpdev is the "real inter‐ + face" over which the carp virtual IP is accessible. carpdev is valid for + carp(4) interfaces only. + + E.g set carp0 to use vlan10 as its carpdev. + + nsh(interface-carp0)/carpdev vlan10 + + [no] ccaarrppnnooddee [_v_h_i_d] [advskew] [state] + + Set or remove carpnode parameter on a carp interface. carpnode facili‐ + tates loadbalancing across carp nodes. Each carpdevice that you wish to + loadbalance should have a carpnode and advskew entry on each carp device. + carpnode is valid for carp(4) interfaces only. + + E.g. For a 3 node carp cluster, one can setup carpnode loadbalanced en‐ + tries as follows. + + on carp router 1 + + nsh(interface-carp0)/carpnode 1 10 + on caro router 2 + + nsh(interface-carp0)/carpnode 1 20 + on carp router 3 + + nsh(interface-carp0)/carpnode 1 30 + + [no] ccaarrppppeeeerr [_p_e_e_r_-_i_p_-_a_d_d_r_e_s_s] + + Set or remove the carppeer ip address of a carp peer on the active carp + interface. carppeer is valid for carp(4) interfaces only. + + E.g. set carppeer to 10.2.3.4 on carp0 interface. + + nsh(interface-carp0)/carppeer 10.2.3.4 + + [no] bbaallaanncciinngg [_n_o_n_e | _i_p | _i_p_-_s_t_e_a_l_t_h | _i_p_-_u_n_i_c_a_s_t] + + Set or remove the balancing mode on the active carp interface. Valid + balancing modes are as follows: + •• none no load-balancing. + •• ip IP load balancing on top of Layer 2 multicast + MAC (requires multicast mac support on the + network switch) + •• ip-stealth carp wont send packets with its own virtual + MAC address as the source. + Stealth mode prevents a switch from learning + the virtual MAC address, therefore the switch + would unicast flood traffic to all switch + ports + (unless there is some swithc acls to prevent + flooding unnecessarily. + •• ip-unicast Used in conjunction with a HUB or a switch + that can replicate packets (monitoring or + mirror) or other non-standard switch forward‐ + ing mechanism. + Note: IP balancing is being used on a firewall, it is recommended to con‐ + figure the carpnodes in a symmetrical manner. This is achieved by simply + using the same carpnodes list on all sides of the firewall. This ensures + that packets of one connection pass in and out on the same host and are + not routed asymmetrically. + + balancing is valid when used in carp(4) interfaces. + + E.g. enable standard IP balancing over layer2 multicast mac on carp0 in‐ + terface + + nsh(interface-carp0)/balancing ip + + [no] ppffllooww [sseennddeerr _s_e_n_d_e_r_-_i_p rreecceeiivveerr _r_e_c_e_i_v_e_r_-_i_p_:_p_o_r_t] [vveerrssiioonn _5 | _9 | + _1_0] + + Set or remove pflow export to a pflow(4) interface. plfow without argu‐ + ments displays command help. To set a up a pflow export the sender-ip + and receiver-ip:port must be specified. The specified pflow sender-ip + address must exist on an interface on the system already. The receiver- + ip:port is the address of the flow collector in your network. version + specifies the export flow prtocol i.e. netflow version (5 or 9) or the + standardised IPFIX (10). + + The pflow interface attempts aggregate multiple pflow records in one ex‐ + port UDP packet. The aggregation algoritim record for longer than 30 + seconds. The packet size and thus the maximum number of flows is con‐ + trolled by the mtu of the inteface the flows are exported via. + + There is a one-to-one correspondence between packets seen by bpf(4) on + the pflow interface and packets sent out to the flow receiver. I.e. if a + packet with 30 flows on pflow, then the same 30 flows were sent out to + the receiver. + + pflow command is valid only on a pflow(4) interface. + + E.g. to setup a pflow export from 10.1.1.1 to an IPFIX flow collector + listening on another server on 10.1.1.2 port 4739. + + nsh(config-p)/interface pflow0 + + nsh(interface-pflow0)/pflow sender 10.1.1.1 receiver 10.1.1.2:4379 version 10 + + [no] ddeebbuugg + + Set or remove the driver-dependant debugging flag for an interface. Use‐ + ful for troubleshooting. + + E.g to set debugging on a carp0 interface. + + nsh(interface-carp0)/debug + + [no] ddhhccrreellaayy [_d_h_c_p_-_s_e_r_v_e_r_-_i_p] + + Set or remove dhcp relay agent on the selected interface. The + dhcrelay(8) service listens on the selected interface for broadcast dhcp + requests and then wrap the recieved broadcast request in a unicast ip + packet and send it to a DHCP server specified by dhcp-server-ip. + + E.g. set up dhcprelay on em0 and send requests to DHCP server 10.1.1.2 + + nsh(interface-em0)/dhcrelay 10.1.1.2 + + [no] wwooll + + Enable or disable WOL (wake on lan) functionality on the selected inter‐ + face. The interface and device bios or firmware must support WOL func‐ + tionality. + + E.g. to enable wake on lan on interface em0. + + nsh(config-p)/interface em0 + + nsh(interface-em0)/wol + + [no] mmppllss + + Set or remove the MPLS flag on the selected interface,if mpls is set on + the interface, the interface can send and receive mpls traffic. + + E.g enable mpls on em0 + + nsh(config-p)/interface em0 + + nsh(interface-em0)/mpls + + [no] iinneett66 [_a_d_d_r_e_s_s_/_p_r_e_f_i_x_-_l_e_n_g_t_h] + + Adds or removes the specified IPv6 address on the interface. The IPv6 + address may be configured with a network prefix length. + + nsh(interface-lo0)/inet6 ::1/128 + + The command nnoo iinneett66 without futher arguments removes all IPv6 addresses + from the interface, including link-local addresses. + + The command iinneett66 without further arguments enables link-local addresses + on the interface. + + E.g. to enable ipv6 link local address on em0 + + nsh(config-p)/interface em0 + + nsh(interface-em0)/inet6 + + [no] iinneett66 aauuttooccoonnff + + Equivalent to the aauuttooccoonnff66 command. + + [no] aauuttooccoonnff66 + + Enable or disable IPv6 auto configuration of Ipv6 address on the inte‐ + face. If autoconf6 is used alone (without temporary or autoconfprivacy + being set on the interface then the autoconfigured address assigned is + repeatable based on the MAC address of the interface (EUI64). + + E.g. enable ipv6 autoconf address on the interface em0. + + nsh(config-p)/interface em0 + + nsh(interface-em0)/autoconf6 + + [no] tteemmppoorraarryy + + Configure or remove temporary address extension for stateless ipv6 auto‐ + configuaration. Temporary address assignments prevents a repeatable IPv6 + address being assigned to the device to reduce the possibility of + longterm external tracking of device (users) activity. + + E.g. enable ipv6 autoconf with a temporary address on the interface em0. + + nsh(config-p)/interface em0 + + nsh(interface-em0)/autoconf6 + + nsh(interface-em0)/temporary + + [no] aauuttooccoonnffpprriivvaaccyy + + deprecated. alias for Cm temporary above. Randomised addresses used to + be called autoconfprivacy extensions for IPv6. Temporary addressing is a + better description as privacy is not necessarily guaranteed by random IP + addressing of a device. + + E.g. enable ipv6 autoconf with "privacy" random temp address on the in‐ + terface em0. + + nsh(config-p)/interface em0 + + nsh(interface-em0)/autoconf6 + + nsh(interface-em0)/autoconfprivacy + + [no] mmoonniittoorr + + Configure or remove the monitor flag on the selected interface. Prevents + the packets being processed in the network stack. Useful for intrusion + detection sniffing and other diagnostics. + + E.g. to enable ipv6 autoconf with "privacy" random temp address on the + interface em0 + + nsh(config-p)/interface em0 + + nsh(interface-em0)/monitor + + [no] wwggppeeeerr [_p_u_b_l_i_c_-_k_e_y] [eennddppooiinntt _e_n_d_p_o_i_n_t_-_i_p_:_p_o_r_t | aaiipp + _a_l_l_o_w_e_d_-_i_p_/_p_r_e_f_i_x | ppsskk _p_r_e_-_s_h_a_r_e_d_-_k_e_y | ppkkaa _i_n_t_e_r_v_a_l_-_s_e_c] + + Configure or remove a wireguard peer with the peers publickey. The pub‐ + lic-key is 32 bytes and base64-encoded. + + ppkkaa _i_n_t_e_r_v_a_l_-_s_e_c The persistent keep alive (pka) option sets the interval + of keepalive packets in seconds. By default pka is is disabled i.e. the + interval is 0. pka can help maintain connectivity to a peer that would + otherwise be denied unsolicited traffic by an intermediate firewall or + NAT device. Empirically, an interval of 25 seconds should suffice for + most firewall configurations. + + ppsskk _p_r_e_-_s_h_a_r_e_d_-_k_e_y The psk and preshared-key is optional but recommended + as it supplements the public key cryptography with symmetric key cryptog‐ + raphy. + + aaiipp _a_l_l_o_w_e_d_-_i_p_/_p_r_e_f_i_x Set the peer's allowed IPv4 or IPv6 addresses or + prefixes for tunnelled traffic. The option be repeated to set multiple + allowed ip/ranges. No addresses are allowed by default. + + -- E.g set the a peer with the following requirements: + + •• public key EJqeFntM71Dfvn/LDu88gLOWw8aeOHoxrshOEHFd6lQ= + + •• from an ip of 10.1.2.3/32 + + •• with a keep alive packet interval of 25 seconds + + nsh(config-p)/interface wg0 + + nsh(interface-wg0)/wgpeer EJqeFntM71Dfvn/LDu88gLOWw8aeOHoxrshOEHFd6lQ= + aip 10.1.2.3/32 endpoint 10.1.2.3:5252 + psk oJo0kNhoF3TElGUXDg4b0H6IJvOiVCAc/tuaJa1nmVU= + wwggkkeeyy [_p_r_i_v_a_t_e_k_e_y] Set the private key of the current wg(4) wireguard in‐ + terface. When wwggkkeeyy is run without an argument a new wireguard key is + generated for the interface. The privatekey is 32 bytes and base64-en‐ + coded. + + E.g. set the private key of wg(4) wireguard interface wg0 to a specific + key. + + nsh(config-p)/interface wg0 + + nsh(interface-wg0)/wgkey QComa+ca+mWih+Vl/5G/p+UwhYy17hw5vdwysZpIAn0= + + [no] wwggppoorrtt _0_-_6_5_5_3_5 + + Set or remove the configuration for the local UDP port to be used by the + current wireguard interface when exchanging traffic with its wireguard + peers. The interface binds to INADDR_ANY and IN6ADDR_ANY_INIT. If + wwggppoorrtt is entered without an argument wireguard selects its own port au‐ + tomatically. + + E.g. set wireguard interface wg0 to listen on 18443 UDP. + + nsh(config-p)/interface wg0 + + nsh(interface-wg0)/wgport 18443 + + [no] wwggrrttaabbllee [_r_t_a_b_l_e_-_i_d] + + Set or remove the configuration of which routing table the Exchange traf‐ + fic with peers under. The routing table choice is made using rtable-id + which would be a value between 0 and 255 on a default OpenBSD kernel. + The routing domain of the wgrtable does not need be in the same routing + domain to which the interface is attached. wgrtable configures which + rdomain(4) the interface's tunnelled traffic appears. + + E.g. set wireguard interface wg0 routing table to routing domain 5. + + nsh(config-p)/interface wg0 + + nsh(interface-wg0)/wgrtable 5 + + [no] sshhuuttddoowwnn + + Administratively turn off or on the current interface. + + Using this command to shutdown and then turn up an interface resets the + interface. + + nsh(interface-de0)/shutdown + nsh(interface-de0)/no shutdown + +SSeeccttiioonn 55 >> BBrriiddggee mmooddee ccoommmmaannddss + see the following man pages for information + + !man bridge + + !man ifconfig + +SSeeccttiioonn 66 >> PPFF mmooddee ccoommmmaannddss + see the following man pages for information + + !man pfctl !man pf.conf + +SSeeccttiioonn 77 AAlllloowwiinngg uusseerrss ttoo rruunn NNSSHH + The design of OpenBSD requires root privileges to administer the network + stack. + + *NB Security Warning!!! + + The doas configurations outlined below grant a non-root nnsshh user the + ability to obtain root privileges without knowledge of the root password. + A user can abuse nnsshh running as root to run arbitrary commands with the ! + shell escape syntax. + + e.g. + + nsh(p)/!adduser new-unauthorised-user + + Access to root privileges must be restricted to trusted users only. + + *NB End Security Warning + + Users with regular shell access can start nnsshh from another shell. + + Users will be logged into an nnsshh session directly if the user account's + login shell is set to nnsshh as follows: + + usermod -s /usr/local/bin/nsh nshuser + + (replace 'nshuser' with the actual user name) + + If a user has knowlege of the root password they can use the nsh eennaabbllee + command to enter nnsshh privileged mode with root privileges. + + If the user should not know the root password then doas.conf(5) can be + used with nsh arguments restricted to the --ee option. nnsshh will attempt to + obtain root privileges when privileged mode is entered. To prevent abuse + the user will be required to authenticate again with their own password. + With a line such as the following in _/_e_t_c_/_d_o_a_s_._c_o_n_f this will succeed: + + permit keepenv stacy as root cmd /usr/local/bin/nsh args -e + + To allow a user to run nnsshh as root and with arbitrary arguments such as + --cc or --ii, configure _/_e_t_c_/_d_o_a_s_._c_o_n_f with a line starting with 'permit' to + allow the full path to the nnsshh binary without any other restrictions. + For example, the following allows user 'stacy' to run nnsshh as root via + doas(1) with arbitrary arguments: + + permit keepenv stacy as root cmd /usr/local/bin/nsh + + The user stacy can now start nnsshh via doas with an arbitrary amount of ar‐ + guments: + + doas /usr/local/bin/nsh ... + + To allow a restricted user to run a specifc nnsshh script only, configure + /etc/doas.conf to require specific arguments to nsh that involve the --cc + option. The following example allows a backupuser to display the run‐ + ning-config: + + permit nopass backupuser as root cmd /usr/local/bin/nsh args -c /etc/showrunconfig.nshrc + + Where the file _/_e_t_c_/_s_h_o_w_r_u_n_c_o_n_f_i_g_._n_s_h_r_c would not be writable by the + backupuser account and would look like this: + + enable + show running-config + quit + + A more standards RBAC based approach would be to create a group + “nshusers” on the system for users with the role of managing the system + via nsh. Then allow users that are members of a group to run nnsshh using + /etc/doas.conf by referring to the groupname rather than just a single + username (the colon before the group name is required by doas.conf(5) + syntax and signifies a group name argument): + + permit keepenv :nshusers as root cmd /usr/local/bin/nsh args -e + +CCoommmmoonn iinntteerrffaaccee ttyyppeess + Packet Filter Logging: This interface is used to pass traffic logged by + the firewall to software which can record it. These interface names + start with 'pflog'. + + IPsec Loopback: This interface is used internally in the system to pass + decapsulated IPsec traffic. All traffic from this interface has already + been authenticated and unencrypted from the IPsec subsystem. This is + useful when writing firewall rules. These interface names start with + 'enc'. + + Generic Tunnel: This interface is used to configure a network tunnel to + another host or router. It follows the RFC1933 tunnelling standard. + These interface names start with 'gif'. + + Ethernet Bridge: This interface is used to configure layer 2 bridging be‐ + tween physical and virtual network ports on a system. These interface + names start with 'bridge'. + + Ethernet: This is a physical Ethernet interface, running at 10, 100, or + 1000 megabits per second. These interface names are based on the name of + the driver, and vary with different Ethernet chip types. + + IEEE 802.1Q Virtual: This is a virtual Ethernet, Token Ring, or FDDI in‐ + terface. It uses the IEEE 802.1Q protocol to segment real Ethernet in‐ + terfaces into multiple layer 2 networks. These interface names start + with 'vlan'. + + Virtual: This is a virtual interface of any type. Often several differ‐ + ent interfaces use this type. Several versions of OpenBSD use this type + to denote virtual IEEE 802.1Q interfaces, described above. + + PPP: This interface implements the Point to Point Protocol (PPP). PPP, + described in RFC 1661, creates a network over serial communication lines. + It is used over modem connections, direct serial links, leased lines, and + over virtual IP based connections such as in SSH sessions. These inter‐ + face names start with 'ppp' when referring to a version which supports + serial and modem connections. Other interface types may also implement + the Point to Point Protocol. + + IEEE 802.11 Wireless: This interface implements the IEEE 802.11 wireless + LAN protocol. Many implementations of this network have little or no se‐ + curity unless used with proper encryption such as IPsec. These interface + names are based on the name of the driver, and vary with different wire‐ + less chip types. + +IInntteerrffaaccee ffllaaggss + •• UUPP + + Interface is up + + •• BBRROOAADDCCAASSTT + + broadcast address valid + + •• DDEEBBUUGG + + debugging enabed (only some network drivers use this) + + •• LLOOOOPPBBAACCKK + + Interface is a loopback network (internal to the machine) + + •• PPOOIINNTTOOPPOOIINNTT + + Interface is point-to-point link + + •• NNOOAARRPP + + Address Resolution Protocol is disabled on this interface + + •• PPRROOMMIISSCC + + Interface is in promiscuous mode, the system's software to + receive all packets visible to the network card, + even if they are not destined for this host + + •• AALLLLMMUULLTTII + + This causes the interface to receive all multicast traffic, + even for multicast networks that it was not signed up for + + •• OOAACCTTIIVVEE + + Transmission in progress. An interface that dis‐ + plays this flag continuously may be stuck. You + may be able to reset an interface that is in this state by + using and then reversing the 'shutdown' command from the + interface menu. + + E.g. reset an interface. + + nsh(p)interface vr0 + nsh(interface-vr0)/shutdown + nsh(interface-vr0)/no shutdown + •• SSIIMMPPLLEEXX + + Can't hear own transmissions + + •• LLIINNKK00 + + This flag has different meanings with different in‐ + terface types + + •• LLIINNKK11 + + This flag has different meanings with different in‐ + terface types + + •• LLIINNKK22 + + This flag has different meanings with different in‐ + terface types + + •• MMUULLTTIICCAASSTT This interface supports multicast + +AALLTTQQ nnootteess + TODO + +IInntteerrffaaccee--ssppeecciiffiicc nnootteess + There are several special interfaces. + + ggrree + The gre interface allows for tunnel construction using the Cisco GRE en‐ + capsulation protocol. + You can use the tunnel command under interface mode to create a tunnel. + + nsh(interface-gre0)/tunnel 1.2.3.4 5.5.5.5 + enc (IPsec Loopback) + + enc (specifically, enc0) is the encapsulating interface. It is a soft‐ + ware loopback mechanism used to control non-encapsulated IPsec traffic + using the pf firewall ruleset. It allows an administrator to see outgo‐ + ing packets before they have been processed by IPsec, or incoming packets + after they have been processed. + + All traffic out of enc0 is already decrypted and authenticated via IPsec. + Thus, it is helpful when writing firewall rulesets. + + pppppp ((PPooiinntt ttoo PPooiinntt PPrroottooccooll)) + The serial line Point-to-Point protocol uses this interface. + + ssll ((SSeerriiaall LLiinnee IInntteerrffaaccee PPrroottooccooll)) + The Serial Line Internet Protocol uses this interface. + + tun (Tunnel Interface) + + This is another software loopback mechanism. It allows user processes to + create their own virtual network interfaces. It is used by the PPPoE im‐ + plementation. + + ggiiff + This interface is used for RFC 1933 IPv[46] to IPv[46] tunnels. + + nsh(interface-gif0)/tunnel 1.2.3.4 5.5.5.5 + tunnels can be used between rdomains. + + nsh(interface-gif0)/tunnel 1.2.3.4 5.5.5.5 rdomain 5 + + ppfflloogg + Packets logged from the packet filter are visible on this interface + + vvllaann + This interface type allows virtual LANs to be setup over an Ethernet port + using the 802.1Q protocol. E.g. setup a virtual interface with the + 192.168.44.1 IP address, with 802.1Q trunking on the fxp3 physical inter‐ + face, and a vlan ID of 4. + + nsh(interface-vlan0)/vnetid 4 + + nsh(interface-vlan0)/parent fxp3 + + nsh(interface-vlan0)/address 192.168.44.1/24 + + SSvvllaann + This interface type allows virtual LANs to be setup over an Ethernet port + using 802.1AD provider bridge. + + This product includes software developed by the University of California, + Berkeley and its contributors. + + This product includes software developed by Jason L. Wright + + This product includes software developed by the NetBSD Foundation Incor‐ + porated and its contributors. + + EDITOR was used to specify the name of an (old-style) line editor, such + as ed(1), and VISUAL was used to specify a (new-style) screen editor, + such as vi(1). Hence if VISUAL is set, it overrides EDITOR. TODO + +EENNVVIIRROONNMMEENNTT + NSH_MANUAL_PAGE + The manual page displayed by the built-in mmaannuuaall command. This must be + an absolute path to the mdoc(7) file that should be displayed. Defaults + to _/_u_s_r_/_l_o_c_a_l_/_m_a_n_/_m_a_n_8_/_n_s_h_._8 + +FFIILLEESS + /etc/nshrc global configuration file + ~/.profile user's login profile + /etc/shells shell database + /etc/suid_profile privileged shell profile + ~/.nshenv If this file exists and is owned by the invoking user + then nnsshh will automatically load environment variables + from this file at startup. The sseetteennvv and ssaavveeeennvv + commands can be used to generate this file. The file + will not be loaded if the --ii or --cc options are used. + +SSEEEE AALLSSOO + ed(1), mg(1), stty(1), vi(1), pf(4), bgpd.conf(5), dhcpd.conf(5), + ospf6d.conf(5), ospfd.conf(5), pf.conf(5), relayd.conf(5), + resolv.conf(5), shells(5), environ(7), script(7), bgpd(8), + dhcpd(8), dhcpleased(8), dvmrpd(8), eigrpd(8), ftpd(8), + ftp-proxy(8), ifstated(8), iked(8), inetd(8), ipsecctl(8), ldapd(8) + ldpd(8), npppd(8), ntpd(8), ospf6d(8), ospfd(8), pfctl(8), + relayd(8), resolvd(8), ripd(8), rad(8), sasyncd(8), slaacd(8), + smtpd(8), snmpd(8), sshd(8), tftp-proxy(8), tftpd(8), + + Chris Cappuccio, _h_t_t_p_:_/_/_w_w_w_._n_m_e_d_i_a_._n_e_t_/_n_s_h_/, 2014. + + Chris Cappuccio, _h_t_t_p_s_:_/_/_g_i_t_h_u_b_._c_o_m_/_y_e_l_l_o_w_m_a_n_/_n_s_h, 2022. + + Stephen G. Kochan and Patrick H. Wood, _U_N_I_X _S_h_e_l_l _P_r_o_g_r_a_m_m_i_n_g_, _3_r_d + _E_d_i_t_i_o_n, _S_a_m_s, 2003, ISBN 0672324903. + +AAUUTTHHOORRSS + This shell was originally designed and written by Chris Cappuccio + <_c_h_r_i_s_@_n_m_e_d_i_a_._n_e_t>, and is now co-maintained by Stefan Sperling + <_s_t_s_p_@_o_p_e_n_b_s_d_._o_r_g> and Tom Smyth <_t_o_m_._s_m_y_t_h_@_w_i_r_e_l_e_s_s_c_o_n_n_e_c_t_._e_u>. + +BBUUGGSS +BSD April 09, 2023 BSD diff --git a/arp.c b/openbsd/arp.c similarity index 100% rename from arp.c rename to openbsd/arp.c diff --git a/bgpcommands.c b/openbsd/bgpcommands.c similarity index 100% rename from bgpcommands.c rename to openbsd/bgpcommands.c diff --git a/bgpnsh/.gitignore b/openbsd/bgpnsh/.gitignore similarity index 100% rename from bgpnsh/.gitignore rename to openbsd/bgpnsh/.gitignore diff --git a/bgpnsh/Makefile b/openbsd/bgpnsh/Makefile similarity index 100% rename from bgpnsh/Makefile rename to openbsd/bgpnsh/Makefile diff --git a/bgpnsh/bgpnsh.8 b/openbsd/bgpnsh/bgpnsh.8 similarity index 100% rename from bgpnsh/bgpnsh.8 rename to openbsd/bgpnsh/bgpnsh.8 diff --git a/bgpnsh/bgpnsh.c b/openbsd/bgpnsh/bgpnsh.c similarity index 100% rename from bgpnsh/bgpnsh.c rename to openbsd/bgpnsh/bgpnsh.c diff --git a/bgpnsh/stubs.c b/openbsd/bgpnsh/stubs.c similarity index 100% rename from bgpnsh/stubs.c rename to openbsd/bgpnsh/stubs.c diff --git a/bridge.c b/openbsd/bridge.c similarity index 100% rename from bridge.c rename to openbsd/bridge.c diff --git a/bridge.h b/openbsd/bridge.h similarity index 100% rename from bridge.h rename to openbsd/bridge.h diff --git a/carp.c b/openbsd/carp.c similarity index 100% rename from carp.c rename to openbsd/carp.c diff --git a/cmdargs.c b/openbsd/cmdargs.c similarity index 100% rename from cmdargs.c rename to openbsd/cmdargs.c diff --git a/commands.c b/openbsd/commands.c similarity index 100% rename from commands.c rename to openbsd/commands.c diff --git a/commands.h b/openbsd/commands.h similarity index 100% rename from commands.h rename to openbsd/commands.h diff --git a/openbsd/compile.sh b/openbsd/compile.sh new file mode 100644 index 0000000..3af29ec --- /dev/null +++ b/openbsd/compile.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +cat >compile.c <<__END +char compiled[] = "`/bin/date +"%d-%b-%y %H:%M"`"; +char compiledby[] = "`/usr/bin/whoami`"; +char compilehost[] = "`uname -n`"; +__END diff --git a/complete.c b/openbsd/complete.c similarity index 100% rename from complete.c rename to openbsd/complete.c diff --git a/conf.c b/openbsd/conf.c similarity index 100% rename from conf.c rename to openbsd/conf.c diff --git a/ctl.c b/openbsd/ctl.c similarity index 100% rename from ctl.c rename to openbsd/ctl.c diff --git a/ctl.h b/openbsd/ctl.h similarity index 100% rename from ctl.h rename to openbsd/ctl.h diff --git a/ctlargs.c b/openbsd/ctlargs.c similarity index 100% rename from ctlargs.c rename to openbsd/ctlargs.c diff --git a/editing.h b/openbsd/editing.h similarity index 100% rename from editing.h rename to openbsd/editing.h diff --git a/externs.h b/openbsd/externs.h similarity index 100% rename from externs.h rename to openbsd/externs.h diff --git a/genget.c b/openbsd/genget.c similarity index 100% rename from genget.c rename to openbsd/genget.c diff --git a/hashtable.c b/openbsd/hashtable.c similarity index 100% rename from hashtable.c rename to openbsd/hashtable.c diff --git a/helpcommands.c b/openbsd/helpcommands.c similarity index 100% rename from helpcommands.c rename to openbsd/helpcommands.c diff --git a/ieee80211.c b/openbsd/ieee80211.c similarity index 100% rename from ieee80211.c rename to openbsd/ieee80211.c diff --git a/if.c b/openbsd/if.c similarity index 100% rename from if.c rename to openbsd/if.c diff --git a/ip.h b/openbsd/ip.h similarity index 100% rename from ip.h rename to openbsd/ip.h diff --git a/kroute.c b/openbsd/kroute.c similarity index 100% rename from kroute.c rename to openbsd/kroute.c diff --git a/main.c b/openbsd/main.c similarity index 100% rename from main.c rename to openbsd/main.c diff --git a/makeargv.c b/openbsd/makeargv.c similarity index 100% rename from makeargv.c rename to openbsd/makeargv.c diff --git a/mantab.sh b/openbsd/mantab.sh similarity index 100% rename from mantab.sh rename to openbsd/mantab.sh diff --git a/media.c b/openbsd/media.c similarity index 100% rename from media.c rename to openbsd/media.c diff --git a/more.c b/openbsd/more.c similarity index 100% rename from more.c rename to openbsd/more.c diff --git a/nameserver.c b/openbsd/nameserver.c similarity index 100% rename from nameserver.c rename to openbsd/nameserver.c diff --git a/ndp.c b/openbsd/ndp.c similarity index 100% rename from ndp.c rename to openbsd/ndp.c diff --git a/nopt.c b/openbsd/nopt.c similarity index 100% rename from nopt.c rename to openbsd/nopt.c diff --git a/nshdoas/.gitignore b/openbsd/nshdoas/.gitignore similarity index 100% rename from nshdoas/.gitignore rename to openbsd/nshdoas/.gitignore diff --git a/nshdoas/Makefile b/openbsd/nshdoas/Makefile similarity index 100% rename from nshdoas/Makefile rename to openbsd/nshdoas/Makefile diff --git a/nshdoas/doas.h b/openbsd/nshdoas/doas.h similarity index 100% rename from nshdoas/doas.h rename to openbsd/nshdoas/doas.h diff --git a/nshdoas/env.c b/openbsd/nshdoas/env.c similarity index 100% rename from nshdoas/env.c rename to openbsd/nshdoas/env.c diff --git a/nshdoas/nshdoas.c b/openbsd/nshdoas/nshdoas.c similarity index 100% rename from nshdoas/nshdoas.c rename to openbsd/nshdoas/nshdoas.c diff --git a/nshdoas/parse.y b/openbsd/nshdoas/parse.y similarity index 100% rename from nshdoas/parse.y rename to openbsd/nshdoas/parse.y diff --git a/passwd.c b/openbsd/passwd.c similarity index 100% rename from passwd.c rename to openbsd/passwd.c diff --git a/pflow.c b/openbsd/pflow.c similarity index 100% rename from pflow.c rename to openbsd/pflow.c diff --git a/pfsync.c b/openbsd/pfsync.c similarity index 100% rename from pfsync.c rename to openbsd/pfsync.c diff --git a/ppp.c b/openbsd/ppp.c similarity index 100% rename from ppp.c rename to openbsd/ppp.c diff --git a/prompt.c b/openbsd/prompt.c similarity index 100% rename from prompt.c rename to openbsd/prompt.c diff --git a/route.c b/openbsd/route.c similarity index 100% rename from route.c rename to openbsd/route.c diff --git a/show.c b/openbsd/show.c similarity index 100% rename from show.c rename to openbsd/show.c diff --git a/sqlite3.c b/openbsd/sqlite3.c similarity index 100% rename from sqlite3.c rename to openbsd/sqlite3.c diff --git a/stats.c b/openbsd/stats.c similarity index 100% rename from stats.c rename to openbsd/stats.c diff --git a/stringlist.c b/openbsd/stringlist.c similarity index 100% rename from stringlist.c rename to openbsd/stringlist.c diff --git a/stringlist.h b/openbsd/stringlist.h similarity index 100% rename from stringlist.h rename to openbsd/stringlist.h diff --git a/sysctl.c b/openbsd/sysctl.c similarity index 100% rename from sysctl.c rename to openbsd/sysctl.c diff --git a/openbsd/sysctl.h b/openbsd/sysctl.h new file mode 100644 index 0000000..430c54a --- /dev/null +++ b/openbsd/sysctl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Chris Cappuccio + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct ipsysctl { + char *name; + int mib[6]; + int32_t def_larg; /* default value, or 0 for on/off + * sysctls */ + int enable; /* if on/off sysctl, 0 default is enabled, 1 + * default is disabled, 2 always show ena ble + * or disable */ +}; + +struct sysctltab { + char *name; + int pf; + Menu *table; + struct ipsysctl *sysctl; +}; + +extern struct sysctltab sysctls[]; +extern struct ipsysctl ipsysctls[]; +extern struct ipsysctl ip6sysctls[]; +extern struct ipsysctl mplssysctls[]; +extern struct ipsysctl ddbsysctls[]; +extern struct ipsysctl pipexsysctls[]; +extern Menu iptab[]; +extern Menu ip6tab[]; +extern Menu mplstab[]; +extern Menu ddbtab[]; +extern Menu pipextab[]; + +#define DEFAULT_MAXDYNROUTES 4096 /* net.inet6.ip6.maxdynroutes */ +#define DEFAULT_NEIGHBORGCTHRESH 2048 /* net.inet6.ip6.neighborgcthresh */ diff --git a/trunk.c b/openbsd/trunk.c similarity index 100% rename from trunk.c rename to openbsd/trunk.c diff --git a/tunnel.c b/openbsd/tunnel.c similarity index 100% rename from tunnel.c rename to openbsd/tunnel.c diff --git a/umb.c b/openbsd/umb.c similarity index 100% rename from umb.c rename to openbsd/umb.c diff --git a/utf8.c b/openbsd/utf8.c similarity index 100% rename from utf8.c rename to openbsd/utf8.c diff --git a/utils.c b/openbsd/utils.c similarity index 100% rename from utils.c rename to openbsd/utils.c diff --git a/version.c b/openbsd/version.c similarity index 100% rename from version.c rename to openbsd/version.c diff --git a/wg.c b/openbsd/wg.c similarity index 100% rename from wg.c rename to openbsd/wg.c diff --git a/openbsd/who.c b/openbsd/who.c new file mode 100644 index 0000000..25605f4 --- /dev/null +++ b/openbsd/who.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Fischbein. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "externs.h" + +void output(struct utmp *); +void output_labels(void); + +int +who(int argc, char **argv) +{ + FILE *utmp; + struct utmp who; + int count = 0; + + if (argc == 2 && !isprefix(argv[1], "users")) { + printf("%% Too many arguments\n"); + return(0); + } + + if ((utmp = fopen(_PATH_UTMP, "r")) == NULL) { + printf("%% who: fopen %s: %s\n",_PATH_UTMP,strerror(errno)); + return(0); + } + +#define HOST_WIDTH 40 +#define NAME_WIDTH 8 + + output_labels(); + + while (fread((char *)&who, sizeof(who), 1, utmp) == 1) { + if (*who.ut_name && *who.ut_line) { + output(&who); + count++; + } + } + (void) printf ("%% users=%d\n", count); + + return(0); +} + +void +output_labels(void) +{ + (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, "User"); + + (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, "Line"); + (void)printf("When "); + + (void)printf("Idle %.*s", HOST_WIDTH, "From"); + + (void)putchar('\n'); +} + +void +output(struct utmp *up) +{ + char line[sizeof(_PATH_DEV) + sizeof (up->ut_line)]; + static time_t now = 0; + time_t idle = 0; + + if (now == 0) + time(&now); + + memset(line, 0, sizeof line); + strlcpy(line, _PATH_DEV, sizeof line); + strlcat(line, up->ut_line, sizeof line); + + (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, up->ut_name); + + (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line); + (void)printf("%.12s ", ctime(&up->ut_time) + 4); + + if (idle < 60) + (void)printf("00:00 "); + else if (idle < (24 * 60 * 60)) + (void)printf("%02d:%02d ", + ((int)idle / (60 * 60)), + ((int)idle % (60 * 60)) / 60); + else + (void)printf(" old "); + + if (*up->ut_host) + printf(" %.*s", HOST_WIDTH, up->ut_host); + (void)putchar('\n'); +}