summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ngctl
diff options
context:
space:
mode:
authorarchie <archie@FreeBSD.org>1999-11-30 02:45:32 +0000
committerarchie <archie@FreeBSD.org>1999-11-30 02:45:32 +0000
commit81fceb37a95304786f88f6611289a27c7262d394 (patch)
tree321a35b746bb34b931d0691c03f9888db83ed68b /usr.sbin/ngctl
parent9716636318d4160418baceabe7ba05ce065692fc (diff)
downloadFreeBSD-src-81fceb37a95304786f88f6611289a27c7262d394.zip
FreeBSD-src-81fceb37a95304786f88f6611289a27c7262d394.tar.gz
Add two new generic control messages, NGM_ASCII2BINARY and
NGM_BINARY2ASCII, which convert control messages to ASCII and back. This allows control messages to be sent and received in ASCII form using ngctl(8), which makes ngctl a lot more useful. This also allows all the type-specific debugging code in libnetgraph to go away -- instead, we just ask the node itself to do the ASCII translation for us. Currently, all generic control messages are supported, as well as messages associated with the following node types: async, cisco, ksocket, and ppp. See /usr/share/examples/netgraph/ngctl for an example of using this. Also give ngctl(8) the ability to print out incoming data and control messages at any time. Eventually nghook(8) may be subsumed. Several other misc. bug fixes. Reviewed by: julian
Diffstat (limited to 'usr.sbin/ngctl')
-rw-r--r--usr.sbin/ngctl/Makefile2
-rw-r--r--usr.sbin/ngctl/connect.c3
-rw-r--r--usr.sbin/ngctl/list.c3
-rw-r--r--usr.sbin/ngctl/main.c219
-rw-r--r--usr.sbin/ngctl/msg.c88
-rw-r--r--usr.sbin/ngctl/ngctl.822
-rw-r--r--usr.sbin/ngctl/ngctl.h12
-rw-r--r--usr.sbin/ngctl/rmhook.c3
-rw-r--r--usr.sbin/ngctl/show.c3
-rw-r--r--usr.sbin/ngctl/shutdown.c3
10 files changed, 315 insertions, 43 deletions
diff --git a/usr.sbin/ngctl/Makefile b/usr.sbin/ngctl/Makefile
index 9f51407..468a17c 100644
--- a/usr.sbin/ngctl/Makefile
+++ b/usr.sbin/ngctl/Makefile
@@ -3,7 +3,7 @@
PROG= ngctl
SRCS= main.c mkpeer.c connect.c name.c show.c list.c \
- debug.c shutdown.c rmhook.c status.c types.c
+ msg.c debug.c shutdown.c rmhook.c status.c types.c
MAN8= ngctl.8
DPADD+= ${LIBNETGRAPH}
LDADD+= -lnetgraph
diff --git a/usr.sbin/ngctl/connect.c b/usr.sbin/ngctl/connect.c
index 8b15ca0..470468a 100644
--- a/usr.sbin/ngctl/connect.c
+++ b/usr.sbin/ngctl/connect.c
@@ -49,7 +49,8 @@ const struct ngcmd connect_cmd = {
" \"path\" and \"relpath\" using hooks \"hook\" and \"peerhook\","
" respectively. The \"relpath\", if not absolute, is specified"
" relative to the node at \"path\"."
- " If \"path\" is omitted then \".\" is assumed."
+ " If \"path\" is omitted then \".\" is assumed.",
+ { "join" }
};
static int
diff --git a/usr.sbin/ngctl/list.c b/usr.sbin/ngctl/list.c
index d763061..aeb74fb 100644
--- a/usr.sbin/ngctl/list.c
+++ b/usr.sbin/ngctl/list.c
@@ -47,7 +47,8 @@ const struct ngcmd list_cmd = {
"Show information about all nodes",
"The list command shows information every node that currently"
" exists in the netgraph system. The optional -n argument limits"
- " this list to only those nodes with a global name assignment."
+ " this list to only those nodes with a global name assignment.",
+ { "ls" }
};
static int
diff --git a/usr.sbin/ngctl/main.c b/usr.sbin/ngctl/main.c
index f6d68b9..74017e7 100644
--- a/usr.sbin/ngctl/main.c
+++ b/usr.sbin/ngctl/main.c
@@ -35,14 +35,16 @@
* OF SUCH DAMAGE.
*
* $FreeBSD$
+ * $Whistle: main.c,v 1.12 1999/11/29 19:17:46 archie Exp $
*/
#include "ngctl.h"
-#define PROMPT "+ "
-#define MAX_ARGS 512
-#define WHITESPACE " \t\r\n\v\f"
-#define NG_SOCKET_KLD "ng_socket.ko"
+#define PROMPT "+ "
+#define MAX_ARGS 512
+#define WHITESPACE " \t\r\n\v\f"
+#define NG_SOCKET_KLD "ng_socket.ko"
+#define DUMP_BYTES_PER_LINE 16
/* Internal functions */
static int ReadFile(FILE *fp);
@@ -50,6 +52,8 @@ static int DoParseCommand(char *line);
static int DoCommand(int ac, char **av);
static int DoInteractive(void);
static const struct ngcmd *FindCommand(const char *string);
+static int MatchCommand(const struct ngcmd *cmd, const char *s);
+static void DumpAscii(const u_char *buf, int len);
static void Usage(const char *msg);
static int ReadCmd(int ac, char **av);
static int HelpCmd(int ac, char **av);
@@ -62,6 +66,7 @@ static const struct ngcmd *const cmds[] = {
&help_cmd,
&list_cmd,
&mkpeer_cmd,
+ &msg_cmd,
&name_cmd,
&read_cmd,
&rmhook_cmd,
@@ -78,19 +83,22 @@ const struct ngcmd read_cmd = {
ReadCmd,
"read <filename>",
"Read and execute commands from a file",
- NULL
+ NULL,
+ { "source", "." }
};
const struct ngcmd help_cmd = {
HelpCmd,
"help [command]",
"Show command summary or get more help on a specific command",
- NULL
+ NULL,
+ { "?" }
};
const struct ngcmd quit_cmd = {
QuitCmd,
"quit",
"Exit program",
- NULL
+ NULL,
+ { "exit" }
};
/* Our control and data sockets */
@@ -200,16 +208,107 @@ ReadFile(FILE *fp)
static int
DoInteractive(void)
{
- char buf[LINE_MAX];
+ const int maxfd = MAX(csock, dsock) + 1;
- /* Read commands from stdin */
(*help_cmd.func)(0, NULL);
- do {
- printf("%s", PROMPT);
- if (fgets(buf, sizeof(buf), stdin) == NULL)
+ while (1) {
+ struct timeval tv;
+ fd_set rfds;
+
+ /* See if any data or control messages are arriving */
+ FD_ZERO(&rfds);
+ FD_SET(csock, &rfds);
+ FD_SET(dsock, &rfds);
+ memset(&tv, 0, sizeof(tv));
+ if (select(maxfd, &rfds, NULL, NULL, &tv) <= 0) {
+
+ /* Issue prompt and wait for anything to happen */
+ printf("%s", PROMPT);
+ fflush(stdout);
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ FD_SET(csock, &rfds);
+ FD_SET(dsock, &rfds);
+ if (select(maxfd, &rfds, NULL, NULL, NULL) < 0)
+ err(EX_OSERR, "select");
+
+ /* If not user input, print a newline first */
+ if (!FD_ISSET(0, &rfds))
+ printf("\n");
+ }
+
+ /* Display any incoming control message */
+ while (FD_ISSET(csock, &rfds)) {
+ u_char buf[2 * sizeof(struct ng_mesg) + 8192];
+ struct ng_mesg *const m = (struct ng_mesg *)buf;
+ struct ng_mesg *const ascii = (struct ng_mesg *)m->data;
+ char path[NG_PATHLEN+1];
+
+ /* Get incoming message (in binary form) */
+ if (NgRecvMsg(csock, m, sizeof(buf), path) < 0) {
+ warn("recv incoming message");
+ break;
+ }
+
+ /* Ask originating node to convert to ASCII */
+ if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
+ NGM_BINARY2ASCII, m,
+ sizeof(*m) + m->header.arglen) < 0
+ || NgRecvMsg(csock, m, sizeof(buf), NULL) < 0) {
+ printf("Rec'd %s %d from \"%s\":\n",
+ (m->header.flags & NGF_RESP) != 0 ?
+ "response" : "command",
+ m->header.cmd, path);
+ if (m->header.arglen == 0)
+ printf("No arguments\n");
+ else
+ DumpAscii(m->data, m->header.arglen);
+ break;
+ }
+
+ /* Display message in ASCII form */
+ printf("Rec'd %s \"%s\" (%d) from \"%s\":\n",
+ (ascii->header.flags & NGF_RESP) != 0 ?
+ "response" : "command",
+ ascii->header.cmdstr, ascii->header.cmd, path);
+ if (*ascii->data != '\0')
+ printf("Args:\t%s\n", ascii->data);
+ else
+ printf("No arguments\n");
+ break;
+ }
+
+ /* Display any incoming data packet */
+ while (FD_ISSET(dsock, &rfds)) {
+ u_char buf[8192];
+ char hook[NG_HOOKLEN + 1];
+ int rl;
+
+ /* Read packet from socket */
+ if ((rl = NgRecvData(dsock,
+ buf, sizeof(buf), hook)) < 0)
+ err(EX_OSERR, "read(hook)");
+ if (rl == 0)
+ errx(EX_OSERR, "EOF from hook \"%s\"?", hook);
+
+ /* Write packet to stdout */
+ printf("Rec'd data packet on hook \"%s\":\n", hook);
+ DumpAscii(buf, rl);
break;
- fflush(stdout);
- } while (DoParseCommand(buf) != CMDRTN_QUIT);
+ }
+
+ /* Get any user input */
+ if (FD_ISSET(0, &rfds)) {
+ char buf[LINE_MAX];
+
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ printf("\n");
+ break;
+ }
+ if (DoParseCommand(buf) == CMDRTN_QUIT)
+ break;
+ }
+ }
return(CMDRTN_QUIT);
}
@@ -255,17 +354,10 @@ DoCommand(int ac, char **av)
static const struct ngcmd *
FindCommand(const char *string)
{
- const struct ngcmd *cmd;
- int k, len, found;
-
- if (strcmp(string, "?") == 0)
- string = "help";
- for (k = 0, found = -1; cmds[k]; k++) {
- cmd = cmds[k];
- len = strcspn(cmd->cmd, WHITESPACE);
- if (len > strlen(string))
- len = strlen(string);
- if (!strncasecmp(string, cmd->cmd, len)) {
+ int k, found = -1;
+
+ for (k = 0; cmds[k] != NULL; k++) {
+ if (MatchCommand(cmds[k], string)) {
if (found != -1) {
warnx("\"%s\": ambiguous command", string);
return(NULL);
@@ -281,6 +373,32 @@ FindCommand(const char *string)
}
/*
+ * See if string matches a prefix of "cmd" (or an alias) case insensitively
+ */
+static int
+MatchCommand(const struct ngcmd *cmd, const char *s)
+{
+ int a;
+
+ /* Try to match command, ignoring the usage stuff */
+ if (strlen(s) <= strcspn(cmd->cmd, WHITESPACE)) {
+ if (strncasecmp(s, cmd->cmd, strlen(s)) == 0)
+ return (1);
+ }
+
+ /* Try to match aliases */
+ for (a = 0; a < MAX_CMD_ALIAS && cmd->aliases[a] != NULL; a++) {
+ if (strlen(cmd->aliases[a]) >= strlen(s)) {
+ if (strncasecmp(s, cmd->aliases[a], strlen(s)) == 0)
+ return (1);
+ }
+ }
+
+ /* No match */
+ return (0);
+}
+
+/*
* ReadCmd()
*/
static int
@@ -333,6 +451,20 @@ HelpCmd(int ac, char **av)
/* Show help on a specific command */
if ((cmd = FindCommand(av[1])) != NULL) {
printf("Usage: %s\n", cmd->cmd);
+ if (cmd->aliases[0] != NULL) {
+ int a = 0;
+
+ printf("Aliases: ");
+ while (1) {
+ printf("%s", cmd->aliases[a++]);
+ if (a == MAX_CMD_ALIAS
+ || cmd->aliases[a] == NULL) {
+ printf("\n");
+ break;
+ }
+ printf(", ");
+ }
+ }
printf("Summary: %s\n", cmd->desc);
if (cmd->help != NULL) {
const char *s;
@@ -370,6 +502,43 @@ QuitCmd(int ac, char **av)
}
/*
+ * Dump data in hex and ASCII form
+ */
+static void
+DumpAscii(const u_char *buf, int len)
+{
+ char ch, sbuf[100];
+ int k, count;
+
+ for (count = 0; count < len; count += DUMP_BYTES_PER_LINE) {
+ snprintf(sbuf, sizeof(sbuf), "%04x: ", count);
+ for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
+ if (count + k < len) {
+ snprintf(sbuf + strlen(sbuf),
+ sizeof(sbuf) - strlen(sbuf),
+ "%02x ", buf[count + k]);
+ } else {
+ snprintf(sbuf + strlen(sbuf),
+ sizeof(sbuf) - strlen(sbuf), " ");
+ }
+ }
+ snprintf(sbuf + strlen(sbuf), sizeof(sbuf) - strlen(sbuf), " ");
+ for (k = 0; k < DUMP_BYTES_PER_LINE; k++) {
+ if (count + k < len) {
+ ch = isprint(buf[count + k]) ?
+ buf[count + k] : '.';
+ snprintf(sbuf + strlen(sbuf),
+ sizeof(sbuf) - strlen(sbuf), "%c", ch);
+ } else {
+ snprintf(sbuf + strlen(sbuf),
+ sizeof(sbuf) - strlen(sbuf), " ");
+ }
+ }
+ printf("%s\n", sbuf);
+ }
+}
+
+/*
* Usage()
*/
static void
diff --git a/usr.sbin/ngctl/msg.c b/usr.sbin/ngctl/msg.c
new file mode 100644
index 0000000..7a04076
--- /dev/null
+++ b/usr.sbin/ngctl/msg.c
@@ -0,0 +1,88 @@
+
+/*
+ * msg.c
+ *
+ * Copyright (c) 1999 Whistle Communications, Inc.
+ * All rights reserved.
+ *
+ * Subject to the following obligations and disclaimer of warranty, use and
+ * redistribution of this software, in source or object code forms, with or
+ * without modifications are expressly permitted by Whistle Communications;
+ * provided, however, that:
+ * 1. Any and all reproductions of the source or object code must include the
+ * copyright notice above and the following disclaimer of warranties; and
+ * 2. No rights are granted, in any manner or form, to use Whistle
+ * Communications, Inc. trademarks, including the mark "WHISTLE
+ * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
+ * such appears in the above copyright notice or in the software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
+ * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
+ * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+ * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
+ * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
+ * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
+ * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
+ * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
+ * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Whistle: msg.c,v 1.2 1999/11/29 23:38:35 archie Exp $
+ * $FreeBSD$
+ */
+
+#include "ngctl.h"
+
+#define BUF_SIZE 1024
+
+static int MsgCmd(int ac, char **av);
+
+const struct ngcmd msg_cmd = {
+ MsgCmd,
+ "msg path command [args ... ]",
+ "Send a netgraph control message to the node at \"path\"",
+ "The msg command constructs a netgraph control message from the"
+ " command name and ASCII arguments (if any) and sends that message"
+ " to the node. It does this by first asking the node to convert"
+ " the ASCII message into binary format, and resending the result."
+ " The typecookie used for the message is assumed to be the typecookie"
+ " corresponding to the target node's type.",
+ { "cmd" }
+};
+
+static int
+MsgCmd(int ac, char **av)
+{
+ char buf[BUF_SIZE];
+ char *path, *cmdstr;
+ int i;
+
+ /* Get arguments */
+ if (ac < 3)
+ return(CMDRTN_USAGE);
+ path = av[1];
+ cmdstr = av[2];
+
+ /* Put command and arguments back together as one string */
+ for (*buf = '\0', i = 3; i < ac; i++) {
+ snprintf(buf + strlen(buf),
+ sizeof(buf) - strlen(buf), " %s", av[i]);
+ }
+
+ /* Send it */
+ if (NgSendAsciiMsg(csock, path, "%s%s", cmdstr, buf) < 0) {
+ warn("send msg");
+ return(CMDRTN_ERROR);
+ }
+
+ /* Done */
+ return(CMDRTN_OK);
+}
+
diff --git a/usr.sbin/ngctl/ngctl.8 b/usr.sbin/ngctl/ngctl.8
index 8537d76..44b5402 100644
--- a/usr.sbin/ngctl/ngctl.8
+++ b/usr.sbin/ngctl/ngctl.8
@@ -60,11 +60,15 @@ will enter interactive mode. Otherwise
.Nm ngctl
will execute the supplied command(s) and exit immediately.
.Pp
-If the
-.Dv ng_socket.ko
-module is not installed in the kernel,
-.Nm ngctl
-will attempt to install it.
+Nodes can be created, removed, joined together, etc.
+ASCII formatted control messages can be sent to any node if that node
+supports binary/ASCII control message conversion.
+.Pp
+In interactive mode,
+.Nm
+will display any control messages and data packets received by the socket node.
+In the case of control messages, the message arguments are displayed in ASCII
+form if the originating node supports conversion.
.Pp
The options are as follows:
.Bl -tag -width indent
@@ -92,6 +96,7 @@ debug Get/set debugging verbosity level
help Show command summary or get help on a command
list Show information about all nodes
mkpeer Create and connect a new node to an existing node
+msg Send an ASCII formatted message to a node
name Assign a name to a node
read Read and execute commands from a file
rmhook Disconnect a node's hook
@@ -102,8 +107,9 @@ types Show all installed node types
quit Exit program
.Ed
.Pp
+Some commands have aliases, e.g., ``ls'' is the same as ``list''.
The ``help'' command displays the available
-commands, their usage, and a brief description.
+commands, their usage and aliases, and a brief description.
.Sh EXIT VALUE
The
.Nm
@@ -117,5 +123,5 @@ Archie Cobbs <archie@whistle.com>
.Sh HISTORY
The
.Em netgraph
-system was designed and first implemented at Whistle Communications, Inc.
-in a version FreeBSD 2.2 customized for the Whistle InterJet.
+system was designed and first implemented at Whistle Communications, Inc. in
+a version FreeBSD 2.2 customized for the Whistle InterJet.
diff --git a/usr.sbin/ngctl/ngctl.h b/usr.sbin/ngctl/ngctl.h
index 817c6e8..8c7155b 100644
--- a/usr.sbin/ngctl/ngctl.h
+++ b/usr.sbin/ngctl/ngctl.h
@@ -58,12 +58,15 @@
#include <netgraph/ng_socket.h>
#include <netgraph/ng_message.h>
+#define MAX_CMD_ALIAS 8
+
/* Command descriptors */
struct ngcmd {
- int (*func)(int ac, char **av);
- const char *cmd;
- const char *desc;
- const char *help;
+ int (*func)(int ac, char **av); /* command function */
+ const char *cmd; /* command usage */
+ const char *desc; /* description */
+ const char *help; /* help text */
+ const char *aliases[MAX_CMD_ALIAS]; /* command aliases */
};
/* Command return values */
@@ -78,6 +81,7 @@ extern const struct ngcmd debug_cmd;
extern const struct ngcmd help_cmd;
extern const struct ngcmd list_cmd;
extern const struct ngcmd mkpeer_cmd;
+extern const struct ngcmd msg_cmd;
extern const struct ngcmd name_cmd;
extern const struct ngcmd read_cmd;
extern const struct ngcmd rmhook_cmd;
diff --git a/usr.sbin/ngctl/rmhook.c b/usr.sbin/ngctl/rmhook.c
index 551c06f..4af398e 100644
--- a/usr.sbin/ngctl/rmhook.c
+++ b/usr.sbin/ngctl/rmhook.c
@@ -47,7 +47,8 @@ const struct ngcmd rmhook_cmd = {
"Disconnect hook \"hook\" of the node at \"path\"",
"The rmhook command forces the node at \"path\" to break the link"
" formed by its hook \"hook\", if connected."
- " If \"path\" is omitted then \".\" is assumed."
+ " If \"path\" is omitted then \".\" is assumed.",
+ { "disconnect" }
};
static int
diff --git a/usr.sbin/ngctl/show.c b/usr.sbin/ngctl/show.c
index 7cfdd48..da51361 100644
--- a/usr.sbin/ngctl/show.c
+++ b/usr.sbin/ngctl/show.c
@@ -49,7 +49,8 @@ const struct ngcmd show_cmd = {
ShowCmd,
"show [-n] <path>",
"Show information about the node at <path>",
- "If the -n flag is given, hooks are not listed."
+ "If the -n flag is given, hooks are not listed.",
+ { "inquire", "info" }
};
static int
diff --git a/usr.sbin/ngctl/shutdown.c b/usr.sbin/ngctl/shutdown.c
index 769f122..d391ba8 100644
--- a/usr.sbin/ngctl/shutdown.c
+++ b/usr.sbin/ngctl/shutdown.c
@@ -45,7 +45,8 @@ const struct ngcmd shutdown_cmd = {
ShutdownCmd,
"shutdown <path>",
"Shutdown the node at <path>",
- NULL
+ NULL,
+ { "kill", "rmnode" }
};
static int
OpenPOWER on IntegriCloud