summaryrefslogtreecommitdiffstats
path: root/lib/libnetgraph
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 /lib/libnetgraph
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 'lib/libnetgraph')
-rw-r--r--lib/libnetgraph/Makefile3
-rw-r--r--lib/libnetgraph/debug.c377
-rw-r--r--lib/libnetgraph/internal.h4
-rw-r--r--lib/libnetgraph/msg.c109
-rw-r--r--lib/libnetgraph/netgraph.368
-rw-r--r--lib/libnetgraph/netgraph.h2
6 files changed, 309 insertions, 254 deletions
diff --git a/lib/libnetgraph/Makefile b/lib/libnetgraph/Makefile
index 569a1f7..342b2e5 100644
--- a/lib/libnetgraph/Makefile
+++ b/lib/libnetgraph/Makefile
@@ -9,8 +9,7 @@ SHLIB_MAJOR= 1
SRCS= sock.c msg.c debug.c
-CFLAGS+= -g -Wall -O2 -Werror
-CFLAGS+= -I/usr/src.freefall/sys
+CFLAGS+= -g -Wall
beforeinstall:
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/netgraph.h \
diff --git a/lib/libnetgraph/debug.c b/lib/libnetgraph/debug.c
index bf57da6..cd7f7cb 100644
--- a/lib/libnetgraph/debug.c
+++ b/lib/libnetgraph/debug.c
@@ -41,24 +41,45 @@
*/
#include <sys/types.h>
+
#include <stdarg.h>
+
+#include <netinet/in.h>
+#include <net/ethernet.h>
+
#include <netgraph/ng_message.h>
#include <netgraph/ng_socket.h>
#include "netgraph.h"
#include "internal.h"
-#include <netgraph/ng_socket.h>
-#include <netgraph/ng_message.h>
-#include <netgraph/ng_iface.h>
-#include <netgraph/ng_rfc1490.h>
-#include <netgraph/ng_cisco.h>
+#include <netgraph/ng_UI.h>
#include <netgraph/ng_async.h>
-#include <netgraph/ng_ppp.h>
+#include <netgraph/ng_cisco.h>
+#include <netgraph/ng_echo.h>
+#include <netgraph/ng_ether.h>
#include <netgraph/ng_frame_relay.h>
+#include <netgraph/ng_hole.h>
+#include <netgraph/ng_iface.h>
+#include <netgraph/ng_ksocket.h>
#include <netgraph/ng_lmi.h>
+#include <netgraph/ng_ppp.h>
+#include <netgraph/ng_pppoe.h>
+#include <netgraph/ng_rfc1490.h>
+#include <netgraph/ng_socket.h>
+#include <netgraph/ng_tee.h>
#include <netgraph/ng_tty.h>
-#include <netgraph/ng_tty.h>
+#include <netgraph/ng_vjc.h>
+#ifdef WHISTLE
+#include <machine/../isa/df_def.h>
+#include <machine/../isa/if_wfra.h>
+#include <machine/../isa/ipac.h>
+#include <netgraph/ng_df.h>
+#include <netgraph/ng_ipac.h>
+#include <netgraph/ng_mppc.h>
+#include <netgraph/ng_pptpgre.h>
+#include <netgraph/ng_tn.h>
+#endif
/* Global debug level */
int _gNgDebugLevel = 0;
@@ -69,8 +90,45 @@ void (*_NgLogx) (const char *fmt,...) = warnx;
/* Internal functions */
static const char *NgCookie(int cookie);
-static const char *NgCmd(int cookie, int cmd);
-static void NgArgs(int cookie, int cmd, int resp, void *args, int arglen);
+
+/* Known typecookie list */
+struct ng_cookie {
+ int cookie;
+ const char *type;
+};
+
+#define COOKIE(c) { NGM_ ## c ## _COOKIE, #c }
+
+/* List of known cookies */
+static const struct ng_cookie cookies[] = {
+ COOKIE(UI),
+ COOKIE(ASYNC),
+ COOKIE(CISCO),
+ COOKIE(ECHO),
+ COOKIE(ETHER),
+ COOKIE(FRAMERELAY),
+ COOKIE(GENERIC),
+ COOKIE(HOLE),
+ COOKIE(IFACE),
+ COOKIE(KSOCKET),
+ COOKIE(LMI),
+ COOKIE(PPP),
+ COOKIE(PPPOE),
+ COOKIE(RFC1490),
+ COOKIE(SOCKET),
+ COOKIE(TEE),
+ COOKIE(TTY),
+ COOKIE(VJC),
+#ifdef WHISTLE
+ COOKIE(DF),
+ COOKIE(IPAC),
+ COOKIE(MPPC),
+ COOKIE(PPTPGRE),
+ COOKIE(TN),
+ COOKIE(WFRA),
+#endif
+ { 0, NULL }
+};
/*
* Set debug level, ie, verbosity, if "level" is non-negative.
@@ -102,27 +160,82 @@ NgSetErrLog(void (*log) (const char *fmt,...),
* Display a netgraph sockaddr
*/
void
-_NgDebugSockaddr(struct sockaddr_ng *sg)
+_NgDebugSockaddr(const struct sockaddr_ng *sg)
{
NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }",
sg->sg_family, sg->sg_len, sg->sg_data);
}
+#define ARGS_BUFSIZE 1024
+
/*
* Display a negraph message
*/
void
-_NgDebugMsg(struct ng_mesg * msg)
+_NgDebugMsg(const struct ng_mesg *msg, const char *path)
{
+ u_char buf[2 * sizeof(struct ng_mesg) + ARGS_BUFSIZE];
+ struct ng_mesg *const req = (struct ng_mesg *)buf;
+ struct ng_mesg *const bin = (struct ng_mesg *)req->data;
+ int arglen, debugSave, csock = -1;
+
+ /* Lower debugging to avoid infinite recursion */
+ debugSave = _gNgDebugLevel;
+ _gNgDebugLevel -= 4;
+
+ /* Display header stuff */
NGLOGX("NG_MESG :");
NGLOGX(" vers %d", msg->header.version);
NGLOGX(" arglen %d", msg->header.arglen);
NGLOGX(" flags %ld", msg->header.flags);
- NGLOGX(" token %lu", (u_long) msg->header.token);
- NGLOGX(" cookie %s", NgCookie(msg->header.typecookie));
- NGLOGX(" cmd %s", NgCmd(msg->header.typecookie, msg->header.cmd));
- NgArgs(msg->header.typecookie, msg->header.cmd,
- (msg->header.flags & NGF_RESP), msg->data, msg->header.arglen);
+ NGLOGX(" token %lu", (u_long)msg->header.token);
+ NGLOGX(" cookie %s (%d)",
+ NgCookie(msg->header.typecookie), msg->header.typecookie);
+
+ /* At lower debugging levels, skip ASCII translation */
+ if (_gNgDebugLevel <= 2)
+ goto fail2;
+
+ /* If path is not absolute, don't bother trying to use relative
+ address on a different socket for the ASCII translation */
+ if (strchr(path, ':') == NULL)
+ goto fail2;
+
+ /* Get a temporary socket */
+ if (NgMkSockNode(NULL, &csock, NULL) < 0)
+ goto fail;
+
+ /* Copy binary message into request message payload */
+ arglen = msg->header.arglen;
+ if (arglen > ARGS_BUFSIZE)
+ arglen = ARGS_BUFSIZE;
+ memcpy(bin, msg, sizeof(*msg) + arglen);
+ bin->header.arglen = arglen;
+
+ /* Ask the node to translate the binary message to ASCII for us */
+ if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
+ NGM_BINARY2ASCII, bin, sizeof(*bin) + bin->header.arglen) < 0)
+ goto fail;
+ if (NgRecvMsg(csock, req, sizeof(buf), NULL) < 0)
+ goto fail;
+
+ /* Display command string and arguments */
+ NGLOGX(" cmd %s (%d)", bin->header.cmdstr, bin->header.cmd);
+ NGLOGX(" args %s", bin->data);
+ goto done;
+
+fail:
+ /* Just display binary version */
+ NGLOGX(" [error decoding message: %s]", strerror(errno));
+fail2:
+ NGLOGX(" cmd %d", msg->header.cmd);
+ NGLOGX(" args (%d bytes)", msg->header.arglen);
+ _NgDebugBytes(msg->data, msg->header.arglen);
+
+done:
+ if (csock != -1)
+ (void)close(csock);
+ _gNgDebugLevel = debugSave;
}
/*
@@ -131,240 +244,20 @@ _NgDebugMsg(struct ng_mesg * msg)
static const char *
NgCookie(int cookie)
{
- static char buf[20];
-
- switch (cookie) {
- case NGM_GENERIC_COOKIE:
- return "generic";
- case NGM_TTY_COOKIE:
- return "tty";
- case NGM_ASYNC_COOKIE:
- return "async";
- case NGM_IFACE_COOKIE:
- return "iface";
- case NGM_FRAMERELAY_COOKIE:
- return "frame_relay";
- case NGM_LMI_COOKIE:
- return "lmi";
- case NGM_CISCO_COOKIE:
- return "cisco";
- case NGM_PPP_COOKIE:
- return "ppp";
- case NGM_RFC1490_NODE_COOKIE:
- return "rfc1490";
- case NGM_SOCKET_COOKIE:
- return "socket";
- }
- snprintf(buf, sizeof(buf), "?? (%d)", cookie);
- return buf;
-}
-
-/*
- * Return the name of the command
- */
-static const char *
-NgCmd(int cookie, int cmd)
-{
- static char buf[20];
-
- switch (cookie) {
- case NGM_GENERIC_COOKIE:
- switch (cmd) {
- case NGM_SHUTDOWN:
- return "shutdown";
- case NGM_MKPEER:
- return "mkpeer";
- case NGM_CONNECT:
- return "connect";
- case NGM_NAME:
- return "name";
- case NGM_RMHOOK:
- return "rmhook";
- case NGM_NODEINFO:
- return "nodeinfo";
- case NGM_LISTHOOKS:
- return "listhooks";
- case NGM_LISTNAMES:
- return "listnames";
- case NGM_LISTNODES:
- return "listnodes";
- case NGM_TEXT_STATUS:
- return "text_status";
- }
- break;
- case NGM_TTY_COOKIE:
- switch (cmd) {
- case NGM_TTY_GET_HOTCHAR:
- return "getHotChar";
- case NGM_TTY_SET_HOTCHAR:
- return "setHotChar";
- }
- break;
- case NGM_ASYNC_COOKIE:
- switch (cmd) {
- case NGM_ASYNC_CMD_GET_STATS:
- return "getStats";
- case NGM_ASYNC_CMD_CLR_STATS:
- return "setStats";
- case NGM_ASYNC_CMD_SET_CONFIG:
- return "setConfig";
- case NGM_ASYNC_CMD_GET_CONFIG:
- return "getConfig";
- }
- break;
- case NGM_IFACE_COOKIE:
- switch (cmd) {
- case NGM_IFACE_GET_IFNAME:
- return "getIfName";
- case NGM_IFACE_GET_IFADDRS:
- return "getIfAddrs";
- }
- break;
- case NGM_LMI_COOKIE:
- switch (cmd) {
- case NGM_LMI_GET_STATUS:
- return "get-status";
- }
- break;
- }
- snprintf(buf, sizeof(buf), "?? (%d)", cmd);
- return buf;
-}
-
-/*
- * Decode message arguments
- */
-static void
-NgArgs(int cookie, int cmd, int resp, void *args, int arglen)
-{
-
-switch (cookie) {
-case NGM_GENERIC_COOKIE:
- switch (cmd) {
- case NGM_SHUTDOWN:
- return;
- case NGM_MKPEER:
- {
- struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) args;
-
- if (resp)
- return;
- NGLOGX(" type \"%s\"", mkp->type);
- NGLOGX(" ourhook \"%s\"", mkp->ourhook);
- NGLOGX(" peerhook \"%s\"", mkp->peerhook);
- return;
- }
- case NGM_CONNECT:
- {
- struct ngm_connect *const ngc = (struct ngm_connect *) args;
-
- if (resp)
- return;
- NGLOGX(" path \"%s\"", ngc->path);
- NGLOGX(" ourhook \"%s\"", ngc->ourhook);
- NGLOGX(" peerhook \"%s\"", ngc->peerhook);
- return;
- }
- case NGM_NAME:
- {
- struct ngm_name *const ngn = (struct ngm_name *) args;
-
- if (resp)
- return;
- NGLOGX(" name \"%s\"", ngn->name);
- return;
- }
- case NGM_RMHOOK:
- {
- struct ngm_rmhook *const ngr = (struct ngm_rmhook *) args;
-
- if (resp)
- return;
- NGLOGX(" hook \"%s\"", ngr->ourhook);
- return;
- }
- case NGM_NODEINFO:
- return;
- case NGM_LISTHOOKS:
- return;
- case NGM_LISTNAMES:
- case NGM_LISTNODES:
- return;
- case NGM_TEXT_STATUS:
- if (!resp)
- return;
- NGLOGX(" status \"%s\"", (char *) args);
- return;
- }
- break;
-
-case NGM_TTY_COOKIE:
- switch (cmd) {
- case NGM_TTY_GET_HOTCHAR:
- if (!resp)
- return;
- NGLOGX(" char 0x%02x", *((int *) args));
- return;
- case NGM_TTY_SET_HOTCHAR:
- NGLOGX(" char 0x%02x", *((int *) args));
- return;
- }
- break;
-
-case NGM_ASYNC_COOKIE:
- switch (cmd) {
- case NGM_ASYNC_CMD_GET_STATS:
- {
- struct ng_async_stat *const as = (struct ng_async_stat *) args;
-
- if (!resp)
- return;
- NGLOGX(" syncOctets = %lu", as->syncOctets);
- NGLOGX(" syncFrames = %lu", as->syncFrames);
- NGLOGX(" syncOverflows = %lu", as->syncOverflows);
- NGLOGX(" asyncOctets = %lu", as->asyncOctets);
- NGLOGX(" asyncFrames = %lu", as->asyncFrames);
- NGLOGX(" asyncRunts = %lu", as->asyncRunts);
- NGLOGX(" asyncOverflows = %lu", as->asyncOverflows);
- NGLOGX(" asyncBadCheckSums = %lu", as->asyncBadCheckSums);
- return;
- }
- case NGM_ASYNC_CMD_GET_CONFIG:
- case NGM_ASYNC_CMD_SET_CONFIG:
- {
- struct ng_async_cfg *const ac = (struct ng_async_cfg *) args;
-
- if (!resp ^ (cmd != NGM_ASYNC_CMD_GET_CONFIG))
- return;
- NGLOGX(" enabled %s", ac->enabled ? "YES" : "NO");
- NGLOGX(" Async MRU %u", ac->amru);
- NGLOGX(" Sync MRU %u", ac->smru);
- NGLOGX(" ACCM 0x%08x", ac->accm);
- return;
- }
- case NGM_ASYNC_CMD_CLR_STATS:
- return;
- }
- break;
-
-case NGM_IFACE_COOKIE:
- switch (cmd) {
- case NGM_IFACE_GET_IFNAME:
- return;
- case NGM_IFACE_GET_IFADDRS:
- return;
- }
- break;
+ int k;
+ for (k = 0; cookies[k].cookie != 0; k++) {
+ if (cookies[k].cookie == cookie)
+ return cookies[k].type;
}
- _NgDebugBytes(args, arglen);
+ return "??";
}
/*
* Dump bytes in hex
*/
void
-_NgDebugBytes(const u_char * ptr, int len)
+_NgDebugBytes(const u_char *ptr, int len)
{
char buf[100];
int k, count;
diff --git a/lib/libnetgraph/internal.h b/lib/libnetgraph/internal.h
index 1022183..d521cfa 100644
--- a/lib/libnetgraph/internal.h
+++ b/lib/libnetgraph/internal.h
@@ -61,7 +61,7 @@ extern void (*_NgLogx)(const char *fmt, ...);
#define NGLOG (*_NgLog)
#define NGLOGX (*_NgLogx)
-extern void _NgDebugSockaddr(struct sockaddr_ng *sg);
-extern void _NgDebugMsg(struct ng_mesg *msg);
+extern void _NgDebugSockaddr(const struct sockaddr_ng *sg);
+extern void _NgDebugMsg(const struct ng_mesg *msg, const char *path);
extern void _NgDebugBytes(const u_char *ptr, int size);
diff --git a/lib/libnetgraph/msg.c b/lib/libnetgraph/msg.c
index 7eda707..ece1787 100644
--- a/lib/libnetgraph/msg.c
+++ b/lib/libnetgraph/msg.c
@@ -82,6 +82,66 @@ NgSendMsg(int cs, const char *path,
}
/*
+ * Send a message given in ASCII format. We first ask the node to translate
+ * the command into binary, and then we send the binary.
+ */
+int
+NgSendAsciiMsg(int cs, const char *path, const char *fmt, ...)
+{
+ const int bufSize = 1024;
+ char replybuf[2 * sizeof(struct ng_mesg) + bufSize];
+ struct ng_mesg *const reply = (struct ng_mesg *)replybuf;
+ struct ng_mesg *const binary = (struct ng_mesg *)reply->data;
+ struct ng_mesg *ascii;
+ char *buf, *cmd, *args;
+ va_list fmtargs;
+
+ /* Parse out command and arguments */
+ va_start(fmtargs, fmt);
+ vasprintf(&buf, fmt, fmtargs);
+ va_end(fmtargs);
+ if (buf == NULL)
+ return (-1);
+
+ /* Parse out command, arguments */
+ for (cmd = buf; isspace(*cmd); cmd++)
+ ;
+ for (args = cmd; *args != '\0' && !isspace(*args); args++)
+ ;
+ if (*args != '\0') {
+ while (isspace(*args))
+ *args++ = '\0';
+ }
+
+ /* Get a bigger buffer to hold inner message header plus arg string */
+ if ((ascii = malloc(sizeof(struct ng_mesg)
+ + strlen(buf) + 1)) == NULL) {
+ free(buf);
+ return (-1);
+ }
+ memset(ascii, 0, sizeof(*ascii));
+
+ /* Build inner header (only need cmdstr, arglen, and data fields) */
+ strncpy(ascii->header.cmdstr, cmd, sizeof(ascii->header.cmdstr) - 1);
+ strcpy(ascii->data, args);
+ ascii->header.arglen = strlen(ascii->data) + 1;
+ free(buf);
+
+ /* Send node a request to convert ASCII to binary */
+ if (NgSendMsg(cs, path, NGM_GENERIC_COOKIE, NGM_ASCII2BINARY,
+ (u_char *)ascii, sizeof(*ascii) + ascii->header.arglen) < 0)
+ return (-1);
+
+ /* Get reply */
+ if (NgRecvMsg(cs, reply, sizeof(replybuf), NULL) < 0)
+ return (-1);
+
+ /* Now send binary version */
+ return NgDeliverMsg(cs,
+ path, binary, binary->data, binary->header.arglen);
+}
+
+/*
* Send a message that is a reply to a previously received message.
* Returns -1 and sets errno on error, otherwise returns zero.
*/
@@ -143,7 +203,7 @@ NgDeliverMsg(int cs, const char *path,
NGLOGX("SENDING %s:",
(msg->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE");
_NgDebugSockaddr(sg);
- _NgDebugMsg(msg);
+ _NgDebugMsg(msg, sg->sg_data);
}
/* Send it */
@@ -193,7 +253,7 @@ NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path)
NGLOGX("RECEIVED %s:",
(rep->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE");
_NgDebugSockaddr(sg);
- _NgDebugMsg(rep);
+ _NgDebugMsg(rep, sg->sg_data);
}
/* Done */
@@ -204,3 +264,48 @@ errout:
return (-1);
}
+/*
+ * Receive a control message and convert the arguments to ASCII
+ */
+int
+NgRecvAsciiMsg(int cs, struct ng_mesg *reply, size_t replen, char *path)
+{
+ struct ng_mesg *msg, *ascii;
+ int bufSize, errnosv;
+ u_char *buf;
+
+ /* Allocate buffer */
+ bufSize = 2 * sizeof(*reply) + replen;
+ if ((buf = malloc(bufSize)) == NULL)
+ return (-1);
+ msg = (struct ng_mesg *)buf;
+ ascii = (struct ng_mesg *)msg->data;
+
+ /* Get binary message */
+ if (NgRecvMsg(cs, msg, bufSize, path) < 0)
+ goto fail;
+ memcpy(reply, msg, sizeof(*msg));
+
+ /* Ask originating node to convert the arguments to ASCII */
+ if (NgSendMsg(cs, path, NGM_GENERIC_COOKIE,
+ NGM_BINARY2ASCII, msg, sizeof(*msg) + msg->header.arglen) < 0)
+ goto fail;
+ if (NgRecvMsg(cs, msg, bufSize, NULL) < 0)
+ goto fail;
+
+ /* Copy result to client buffer */
+ if (sizeof(*ascii) + ascii->header.arglen > replen) {
+ errno = ERANGE;
+fail:
+ errnosv = errno;
+ free(buf);
+ errno = errnosv;
+ return (-1);
+ }
+ strncpy(reply->data, ascii->data, ascii->header.arglen);
+
+ /* Done */
+ free(buf);
+ return (0);
+}
+
diff --git a/lib/libnetgraph/netgraph.3 b/lib/libnetgraph/netgraph.3
index dc9df04..6926f96 100644
--- a/lib/libnetgraph/netgraph.3
+++ b/lib/libnetgraph/netgraph.3
@@ -57,10 +57,14 @@
.Ft int
.Fn NgSendMsg "int cs" "const char *path" "int cookie" "int cmd" "const void *arg" "size_t arglen"
.Ft int
+.Fn NgSendAsciiMsg "int cs" "const char *path" "const char *fmt" "..."
+.Ft int
.Fn NgSendMsgReply "int cs" "const char *path" "struct ng_mesg *msg" "const void *arg" "size_t arglen"
.Ft int
.Fn NgRecvMsg "int cs" "struct ng_mesg *rep" "size_t replen" "char *path"
.Ft int
+.Fn NgRecvAsciiMsg "int cs" "struct ng_mesg *rep" "size_t replen" "char *path"
+.Ft int
.Fn NgSendData "int ds" "const char *hook" "const u_char *buf" "size_t len"
.Ft int
.Fn NgRecvData "int ds" "u_char *buf" "size_t len" "char *hook"
@@ -97,7 +101,8 @@ assigns a global name to the node addressed by
.Fa path .
.Pp
.Fn NgSendMsg
-sends a control message from the socket node associated with control socket
+sends a binary control message from the socket node associated
+with control socket
.Fa cs
to the node addressed by
.Fa path .
@@ -122,6 +127,20 @@ to send reply to a previously received control message.
The original message header should be pointed to by
.Fa msg .
.Pp
+.Fn NgSendAsciiMsg
+performs the same function as
+.Fn NgSendMsg ,
+but adds support for ASCII encoding of control messages.
+.Fn NgSendAsciiMsg
+formats its input a la
+.Xr printf 3
+and then sends the resulting ASCII string to the node in a
+.Dv NGM_ASCII2BINARY
+control message. The node returns a binary version of the
+message, which is then sent back to the node just as with
+.Fn NgSendMsg .
+Note that ASCII conversion may not be supported by all node types.
+.Pp
.Fn NgRecvMsg
reads the next control message received by the node associated with
control socket
@@ -136,6 +155,18 @@ is non-NULL, it must point to a buffer of at least
bytes, which will be filled in (and NUL terminated) with the path to
the node from which the message was received.
.Pp
+.Fn NgRecvAsciiMsg
+works exactly like
+.Fn NgRecvMsg ,
+except that after the message is received, any binary arguments
+are converted to ASCII by sending a
+.Dv NGM_BINARY2ASCII
+request back to the originating node. The result is the same as
+.Fn NgRecvAsciiMsg ,
+with the exception that the reply arguments field will contain
+a NUL-terminated ASCII version of the arguments (and the reply
+header argument length field will be adjusted).
+.Pp
.Fn NgSendData
writes a data packet out on the specified hook of the node corresponding
to data socket
@@ -171,6 +202,11 @@ The default logging functions are
and
.Xr vwarnx 3 .
.Pp
+At debug level 3, the library attempts to display control message arguments
+in ASCII format; however, this results in additional messages being
+sent which may interfere with debugging. At even higher levels,
+even these additional messagages will be displayed, etc.
+.Pp
Note that
.Xr select 2
can be used on the data and the control sockets to detect the presence of
@@ -182,9 +218,9 @@ User mode programs must be linked with the
.Dv -lnetgraph
flag to link in this library.
.Sh INITIALIZATION
-Netgraph is not part of the standard FreeBSD kernel. To enable it,
-either your kernel must be compiled with ``options NETGRAPH''
-in the kernel configuration file, or else the
+To enable Netgraph in your kernel, either your kernel must be
+compiled with ``options NETGRAPH'' in the kernel configuration
+file, or else the
.Xr netgraph 4
and
.Xr ng_socket 8
@@ -196,6 +232,26 @@ All functions except
and
.Fn NgSetErrLog
return -1 if there was an error and set errno accordingly.
+.Pp
+For
+.Fn NgSendAsciiMsg
+and
+.Fn NgRecvAsciiMsg ,
+the following additional errors are possible:
+.Bl -tag -width Er
+.It Bq Er ENOSYS
+The node type does not know how to encode or decode the control message.
+.It Bq Er ERANGE
+The encoded or decoded arguments were too long for the supplied buffer.
+.It Bq Er ENOENT
+An unknown structure field was seen in an ASCII control message.
+.It Bq Er EALREADY
+The same structure field was specified twice in an ASCII control message.
+.It Bq Er EINVAL
+ASCII control message parse error or illegal value.
+.It Bq Er E2BIG
+ASCII control message array or fixed width string buffer overflow.
+.El
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr socket 2 ,
@@ -205,7 +261,7 @@ return -1 if there was an error and set errno accordingly.
.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.
.Sh AUTHOR
.An Archie Cobbs <archie@whistle.com>
diff --git a/lib/libnetgraph/netgraph.h b/lib/libnetgraph/netgraph.h
index f60f04b..c5a87cb 100644
--- a/lib/libnetgraph/netgraph.h
+++ b/lib/libnetgraph/netgraph.h
@@ -50,9 +50,11 @@ __BEGIN_DECLS
int NgMkSockNode(const char *, int *, int *);
int NgNameNode(int, const char *, const char *, ...);
int NgSendMsg(int, const char *, int, int, const void *, size_t);
+int NgSendAsciiMsg(int, const char *, const char *, ...);
int NgSendReplyMsg(int, const char *,
const struct ng_mesg *, const void *, size_t);
int NgRecvMsg(int, struct ng_mesg *, size_t, char *);
+int NgRecvAsciiMsg(int, struct ng_mesg *, size_t, char *);
int NgSendData(int, const char *, const u_char *, size_t);
int NgRecvData(int, u_char *, size_t, char *);
int NgSetDebug(int);
OpenPOWER on IntegriCloud